jcs.org.atom.xml - sfeed_tests - sfeed tests and RSS and Atom files
 (HTM) git clone git://git.codemadness.org/sfeed_tests
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
       jcs.org.atom.xml (113525B)
       ---
            1 <?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><link href="https://jcs.org/rss" rel="self" type="application/atom+xml" /><link href="https://jcs.org/" rel="alternate" type="text/html" /><updated>2021-07-20T14:11:39-05:00</updated><id>https://jcs.org/rss</id><title type="html">joshua stein</title><entry><title type="html">My Fanless OpenBSD Desktop</title><link href="https://jcs.org/2021/07/19/desktop" rel="alternate" type="text/html" title="My Fanless OpenBSD Desktop" /><published>2021-07-19T00:00:00-05:00</published><updated>2021-07-19T00:00:00-05:00</updated><id>https://jcs.org/2021/07/19/desktop</id><content type="html" xml:base="https://jcs.org/2021/07/19/desktop">&lt;p&gt;After the disappointment of my
            2 &lt;a href=&quot;/2021/01/27/x1nano&quot;&gt;X1 Nano&lt;/a&gt;
            3 and learning that all future Intel “Evo”-branded laptops would lack S3 suspend,
            4 I started thinking about returning to my M1 MacBook full-time or building an
            5 OpenBSD desktop.
            6 I chose the latter, building my first desktop machine in many years.&lt;/p&gt;
            7 
            8 &lt;p&gt;&lt;img src=&quot;/images/2021-07-19-hero-665x246.jpg&quot; srcset=&quot;/images/2021-07-19-hero-665x246.jpg 1x, /images/2021-07-19-hero-1330x492@2x.jpg 2x&quot; width=&quot;665&quot; height=&quot;246&quot; alt=&quot;desktop with screen and new desktop system&quot; class=&quot;header&quot; /&gt;&lt;/p&gt;
            9 
           10 &lt;h2 class=&quot;no_toc&quot; id=&quot;table-of-contents&quot;&gt;Table of Contents&lt;/h2&gt;
           11 
           12 &lt;ol id=&quot;markdown-toc&quot;&gt;
           13   &lt;li&gt;&lt;a href=&quot;#architecture&quot; id=&quot;markdown-toc-architecture&quot;&gt;Architecture&lt;/a&gt;&lt;/li&gt;
           14   &lt;li&gt;&lt;a href=&quot;#monitor&quot; id=&quot;markdown-toc-monitor&quot;&gt;Monitor&lt;/a&gt;&lt;/li&gt;
           15   &lt;li&gt;&lt;a href=&quot;#case&quot; id=&quot;markdown-toc-case&quot;&gt;Case&lt;/a&gt;&lt;/li&gt;
           16   &lt;li&gt;&lt;a href=&quot;#cpu-and-motherboard&quot; id=&quot;markdown-toc-cpu-and-motherboard&quot;&gt;CPU and Motherboard&lt;/a&gt;&lt;/li&gt;
           17   &lt;li&gt;&lt;a href=&quot;#ram-and-ssd&quot; id=&quot;markdown-toc-ram-and-ssd&quot;&gt;RAM and SSD&lt;/a&gt;&lt;/li&gt;
           18   &lt;li&gt;&lt;a href=&quot;#keyboard-and-mouse&quot; id=&quot;markdown-toc-keyboard-and-mouse&quot;&gt;Keyboard and Mouse&lt;/a&gt;&lt;/li&gt;
           19   &lt;li&gt;&lt;a href=&quot;#openbsd&quot; id=&quot;markdown-toc-openbsd&quot;&gt;OpenBSD&lt;/a&gt;&lt;/li&gt;
           20   &lt;li&gt;&lt;a href=&quot;#temperatures&quot; id=&quot;markdown-toc-temperatures&quot;&gt;Temperatures&lt;/a&gt;&lt;/li&gt;
           21 &lt;/ol&gt;
           22 
           23 &lt;h2 id=&quot;architecture&quot;&gt;Architecture&lt;/h2&gt;
           24 
           25 &lt;p&gt;I briefly considered an arm64 CPU and motherboard, but the hardware support of
           26 OpenBSD/arm64 is not yet reliable enough for my daily use and the lead-time for
           27 ordering a
           28 &lt;a href=&quot;https://twitter.com/bluerise/status/1352587849359568898&quot;&gt;HoneyComb LX2&lt;/a&gt;
           29 was many weeks out.&lt;/p&gt;
           30 
           31 &lt;p&gt;I decided to go with an amd64 system since the OpenBSD/amd64 platform is very
           32 mature and I know it quite well.
           33 Beyond that, my only requirements for my new desktop were:&lt;/p&gt;
           34 
           35 &lt;ul&gt;
           36   &lt;li&gt;Excellent OpenBSD support&lt;/li&gt;
           37   &lt;li&gt;Fanless with no coil whine&lt;/li&gt;
           38   &lt;li&gt;A high-resolution, small monitor (more on that later)&lt;/li&gt;
           39 &lt;/ul&gt;
           40 
           41 &lt;p&gt;Ever since reading
           42 &lt;a href=&quot;https://fabiensanglard.net/the_beautiful_machine/index.html&quot;&gt;Fabien Sanglard’s writeup&lt;/a&gt;
           43 about building a system with a
           44 &lt;a href=&quot;https://streacom.com/products/db4-fanless-mini-itx-case/&quot;&gt;Streacom DB4 case&lt;/a&gt;,
           45 I knew I wanted that case in particular since it looks beautiful and could
           46 passively cool a 65W processor.&lt;/p&gt;
           47 
           48 &lt;h2 id=&quot;monitor&quot;&gt;Monitor&lt;/h2&gt;
           49 
           50 &lt;p&gt;After the case, the next component I chose was the monitor.
           51 In retrospect, this would make everything else more complicated, but I am pretty
           52 picky about the screens in the laptops that I buy, so I wanted to make sure my
           53 desktop display was of high quality.&lt;/p&gt;
           54 
           55 &lt;p&gt;I’ve always chosen smaller (&amp;lt;= 14”) laptop screens since I find too much
           56 horizontal space disorienting.
           57 I prefer to separate tasks with virtual desktops rather than have everything on
           58 one giant screen.
           59 I wanted a smaller monitor that I could have closer to me, lower on my desk and
           60 angled slightly upward like a laptop screen.&lt;/p&gt;
           61 
           62 &lt;p&gt;In addition to good image reproduction, I needed a monitor with a high
           63 resolution that could display Firefox in 1.5x or 2x mode
           64 (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;layout.css.devPixelsPerPx&lt;/code&gt;).
           65 While not an absolute requirement, integrated speakers would be a nice option on
           66 the monitor so I wouldn’t have to buy separate ones and find a place for them on
           67 my desk.&lt;/p&gt;
           68 
           69 &lt;p&gt;After some research, I chose the
           70 &lt;a href=&quot;https://www.lg.com/us/monitors/lg-22MD4KA-B-4k-uhd-led-monitor&quot;&gt;LG UltraFine 21.5” IPS LED
           71 monitor&lt;/a&gt;
           72 with a resolution of 4096x2304.
           73 This particular version of the LG UltraFine is no longer being produced, but the
           74 newer 24” version was larger but had a smaller resolution (3840x2160), and the
           75 newer 5K model (5120x2880) requires Thunderbolt.
           76 I found a 21.5” version on eBay that was in great condition in the original box.&lt;/p&gt;
           77 
           78 &lt;p&gt;Since the LG UltraFine had a VESA mount option, I purchased an
           79 &lt;a href=&quot;https://amzn.to/3ivzmgP&quot;&gt;Ergotron LX monitor arm&lt;/a&gt;
           80 to be able to position the monitor however I wanted on my desk.&lt;/p&gt;
           81 
           82 &lt;p&gt;&lt;a href=&quot;/images/2021-07-19-monitor_arm-large.jpg&quot;&gt;&lt;img src=&quot;/images/2021-07-19-monitor_arm-665x385.jpg&quot; srcset=&quot;/images/2021-07-19-monitor_arm-665x385.jpg 1x, /images/2021-07-19-monitor_arm-1330x770@2x.jpg 2x&quot; width=&quot;665&quot; height=&quot;385&quot; alt=&quot;LG UltraFine monitor attached to Ergotron LX monitor arm&quot; class=&quot;wide&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
           83 
           84 &lt;p&gt;After some testing with the monitor once I got it, I realized that using it with
           85 a desktop system might be difficult because it uses a single USB-C
           86 (non-Thunderbolt) cable for its display and audio, but it also has a 3-port
           87 USB-C hub on the back of it and its brightness controls and ambient light sensor
           88 also connect over that single USB-C cable.&lt;/p&gt;
           89 
           90 &lt;p&gt;This all works by using the USB-C cable for data as usual but it sends the
           91 screen data over
           92 &lt;a href=&quot;https://www.benq.com/en-us/knowledge-center/knowledge/usb-c-introduction-what-is-dp-alt-mode.html&quot;&gt;DisplayPort&lt;/a&gt;
           93 using dedicated pins of the USB-C cable (“Alt Mode”).
           94 This requires that the computer it’s connecting to have a USB-C port that can
           95 break out those pins and route them to the DisplayPort signal of the GPU while
           96 also handling the data devices of the USB-C connection.
           97 Using an external GPU (“video card” back in my day) would be difficult because
           98 even if it had a USB-C connector (most just have HDMI and/or DisplayPort), it
           99 would need to somehow route the data from that cable back to the computer as USB
          100 data since the GPU is only talking DisplayPort.&lt;/p&gt;
          101 
          102 &lt;p&gt;I didn’t quite figure out how to do all of this until after I had already
          103 purchased the motherboard and CPU, but eventually I got it working using a
          104 &lt;a href=&quot;https://dancharblog.wordpress.com/2020/07/20/add-usb-c-with-dp-alt-mode-to-your-desktop-pc/&quot;&gt;Sunix
          105 upd2018&lt;/a&gt;
          106 card (actually a Dell-branded version of it) which is a PCI USB-C card with a
          107 DisplayPort-out port.
          108 The monitor’s USB-C cable is plugged into the PCI card, which then breaks out
          109 the DisplayPort out to an external connector and the USB-C data routes through
          110 the PCI connection as a normal USB-C card.
          111 Then a 
          112 &lt;a href=&quot;https://amzn.to/3ipjCvD&quot;&gt;short DisplayPort cable&lt;/a&gt;
          113 is used to connect between the PCI card and the motherboard/GPU DisplayPort
          114 connector.&lt;/p&gt;
          115 
          116 &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;xhci0 at pci1 dev 0 function 0 &quot;ASMedia ASM1042AE xHCI&quot; rev 0x00: msi, xHCI 1.10
          117 usb0 at xhci0: USB revision 3.0
          118 uhub0 at usb0 configuration 1 interface 0 &quot;ASMedia xHCI root hub&quot; rev 3.00/1.00 addr 1
          119 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
          120 
          121 &lt;p&gt;The monitor’s brightness controls and ambient light sensor are available through
          122 USB HID devices, and its integrated speakers work through &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uaudio&lt;/code&gt; as expected:&lt;/p&gt;
          123 
          124 &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;uhub5 at uhub0 port 3 configuration 1 interface 0 &quot;LG Electronics Inc. USB2.1 Hub&quot; rev 2.10/52.26 addr 2
          125 uhub6 at uhub5 port 4 configuration 1 interface 0 &quot;LG USA product 0x9a48&quot; rev 2.00/88.32 addr 3
          126 uaudio0 at uhub6 port 1 configuration 1 interface 1 &quot;LG Electronics Inc. USB Audio&quot; rev 2.00/0.2f addr 4
          127 uaudio0: class v1, high-speed, sync, channels: 2 play, 0 rec, 3 ctls
          128 audio1 at uaudio0
          129 uhub6: device problem, disabling port 2
          130 uhidev0 at uhub6 port 4 configuration 1 interface 0 &quot;LG Electronics Inc. USB Controls&quot; rev 2.00/3.04 addr 5
          131 uhidev0: iclass 3/0
          132 uhid0 at uhidev0: input=64, output=64, feature=8
          133 uhidev1 at uhub6 port 4 configuration 1 interface 1 &quot;LG Electronics Inc. USB Controls&quot; rev 2.00/3.04 addr 5
          134 uhidev1: iclass 3/0
          135 uhid1 at uhidev1: input=4, output=0, feature=6
          136 uhidev2 at uhub6 port 4 configuration 1 interface 2 &quot;LG Electronics Inc. USB Controls&quot; rev 2.00/3.04 addr 5
          137 uhidev2: iclass 3/0
          138 uhid2 at uhidev2: input=6, output=0, feature=13
          139 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
          140 
          141 &lt;p&gt;I’m still not sure why that port 2 gets disabled on the monitor’s internal hub
          142 (not the 3-port hub on the back of it) but it doesn’t seem to affect anything.&lt;/p&gt;
          143 
          144 &lt;h2 id=&quot;case&quot;&gt;Case&lt;/h2&gt;
          145 
          146 &lt;p&gt;I already had my heart set on the
          147 &lt;a href=&quot;https://www.quietpcusa.com/Streacom-DB4-Fanless-Chassis&quot;&gt;Streacom DB4 fanless
          148 case&lt;/a&gt;,
          149 though I waffled a bit between the black and titanium colors before choosing
          150 black.
          151 The case as-is can dissipate enough heat for a 65W processor, though Streacom
          152 offers a separate heat-pipe add-on that can support up to 110W.&lt;/p&gt;
          153 
          154 &lt;p&gt;I purchased a
          155 &lt;a href=&quot;https://www.quietpcusa.com/Streacom-ST-ZF240-ZeroFlex-240W-PSU&quot;&gt;Streacom ST-ZF240 ZeroFlex 240W
          156 PSU&lt;/a&gt;
          157 because it was also fanless.
          158 I’ve used a
          159 &lt;a href=&quot;https://www.quietpcusa.com/Streacom-160W-nanoPSU-and-AC/DC-adapter-block&quot;&gt;nanoPSU&lt;/a&gt;
          160 before but heard coil whine from it so I didn’t want to go that route again.&lt;/p&gt;
          161 
          162 &lt;p&gt;I didn’t quite appreciate how large and heavy the DB4 case is until it arrived.
          163 Fully assembled with everything in it, it weighs over 20 pounds and has a
          164 footprint of 10”x10”x11”.&lt;/p&gt;
          165 
          166 &lt;p&gt;The main bulk of the case is held up 2” off the surface by two large feet, which
          167 only leaves 2” between the motherboard and my table.
          168 This makes it a bit difficult to plug in certain cables like a DisplayPort cable
          169 with a large connector, but my desk has a grommet in the corner where the case
          170 sits so the majority of the cables can pass straight down through the desk.&lt;/p&gt;
          171 
          172 &lt;p&gt;&lt;a href=&quot;/images/2021-07-19-bottom-large.jpg&quot;&gt;&lt;img src=&quot;/images/2021-07-19-bottom-665x378.jpg&quot; srcset=&quot;/images/2021-07-19-bottom-665x378.jpg 1x, /images/2021-07-19-bottom-1330x756@2x.jpg 2x&quot; width=&quot;665&quot; height=&quot;378&quot; class=&quot;wide&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
          173 
          174 &lt;h2 id=&quot;cpu-and-motherboard&quot;&gt;CPU and Motherboard&lt;/h2&gt;
          175 
          176 &lt;p&gt;Since I’ve been pretty unhappy with Intel products lately, I decided to go with
          177 an AMD processor.
          178 I’ve never had one before so I wasn’t very familiar with the lineup, but I
          179 wanted one with integrated graphics to avoid buying an external GPU since I
          180 wouldn’t have room with the DisplayPort/USB-C card and because most external
          181 GPUs put out a ton of heat and/or have fans.
          182 I also needed a processor with a TDP of 65W or less to stay under the Streacom
          183 case’s limits.&lt;/p&gt;
          184 
          185 &lt;p&gt;&lt;a href=&quot;/images/2021-07-19-ryzen-large.jpg&quot;&gt;&lt;img src=&quot;/images/2021-07-19-ryzen-665x331.jpg&quot; srcset=&quot;/images/2021-07-19-ryzen-665x331.jpg 1x, /images/2021-07-19-ryzen-1330x662@2x.jpg 2x&quot; width=&quot;665&quot; height=&quot;331&quot; class=&quot;wide&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
          186 
          187 &lt;p&gt;I decided on the AMD Ryzen 7 Pro 4750G 4Ghz 8-core processor with integrated
          188 Radeon Graphics.
          189 Technically this CPU is not supposed to be sold to end-users, but it’s
          190 &lt;a href=&quot;https://amzn.to/36M6dbH&quot;&gt;available on Amazon&lt;/a&gt;
          191 which was good enough for me.&lt;/p&gt;
          192 
          193 &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;cpu0: AMD Ryzen 7 PRO 4750G with Radeon Graphics, 4000.51 MHz, 17-60-01
          194 cpu0: FPU,VME,DE,PSE,TSC,MSR,PAE,MCE,CX8,APIC,SEP,MTRR,PGE,MCA,CMOV,PAT,PSE36,CFLUSH,MMX,FXSR,SSE,SSE2,HTT,SSE3,PCLMUL,MWAIT,SSSE3,FMA3,CX16,SSE4.1,SSE4.2,MOVBE,POPCNT,AES,XSAVE,AVX,F16C,RDRAND,NXE,MMXX,FFXSR,PAGE1GB,RDTSCP,LONG,LAHF,CMPLEG,SVM,EAPICSP,AMCR8,ABM,SSE4A,MASSE,3DNOWP,OSVW,IBS,SKINIT,TCE,TOPEXT,CPCTR,DBKP,PCTRL3,MWAITX,ITSC,FSGSBASE,BMI1,AVX2,SMEP,BMI2,PQM,RDSEED,ADX,SMAP,CLFLUSHOPT,CLWB,SHA,UMIP,IBPB,IBRS,STIBP,SSBD,XSAVEOPT,XSAVEC,XGETBV1,XSAVES
          195 cpu0: 32KB 64b/line 8-way I-cache, 32KB 64b/line 8-way D-cache, 512KB 64b/line 8-way L2 cache
          196 cpu0: ITLB 64 4KB entries fully associative, 64 4MB entries fully associative
          197 cpu0: DTLB 64 4KB entries fully associative, 64 4MB entries fully associative
          198 [...]
          199 cpu15 at mainbus0: apid 15 (application processor)
          200 cpu15: AMD Ryzen 7 PRO 4750G with Radeon Graphics, 4000.01 MHz, 17-60-01
          201 [...]
          202 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
          203 
          204 &lt;p&gt;Once I had the CPU picked out, I looked for a motherboard.
          205 I’ve been out of the custom PC game for many years, but I was disappointed at
          206 how every non-server motherboard seems to be targeted towards gamers with all
          207 kinds of stupid flashing LEDs and aggressive branding.
          208 Beyond supporting the AM4-socketed Ryzen 4750G, my requirements for the
          209 motherboard were just that it have Intel gigabit ethernet (for optimum OpenBSD
          210 support), at least one M.2 socket for an NVMe drive, and have both HDMI (just in
          211 case) and DisplayPort ports.&lt;/p&gt;
          212 
          213 &lt;p&gt;Eventually I settled on the
          214 &lt;a href=&quot;https://amzn.to/3kx6APl&quot;&gt;ASUS ROG Strix X570-I&lt;/a&gt;.
          215 The stupid RGB LEDs can be disabled in the BIOS/firmware menu by setting “AURA”
          216 to “Stealth Mode”, and I unplugged the two 1” fans on the I/O board to keep
          217 everything silent.
          218 I also had to set the “CPU Fan Speed” in the “Monitor” section to “Ignore”, or
          219 else it would indicate a fan error at every boot since I had none plugged in.&lt;/p&gt;
          220 
          221 &lt;p&gt;While I don’t intend to use them, its onboard WiFi and sound work fine in
          222 OpenBSD:&lt;/p&gt;
          223 
          224 &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;iwx0 at pci4 dev 0 function 0 &quot;Intel Wi-Fi 6 AX200&quot; rev 0x1a, msix
          225 [...]
          226 azalia1 at pci10 dev 0 function 6 &quot;AMD 17h/1xh HD Audio&quot; rev 0x00: apic 18 int 12
          227 azalia1: codecs: Realtek ALC1220
          228 audio0 at azalia1
          229 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
          230 
          231 &lt;p&gt;As does its ethernet port:&lt;/p&gt;
          232 
          233 &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;em0 at pci5 dev 0 function 0 &quot;Intel I211&quot; rev 0x03: msi, address 7c:10:c9:[...]
          234 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
          235 
          236 &lt;h2 id=&quot;ram-and-ssd&quot;&gt;RAM and SSD&lt;/h2&gt;
          237 
          238 &lt;p&gt;I purchased
          239 &lt;a href=&quot;https://amzn.to/3BeCqXf&quot;&gt;Crucial 16Gb DDR4 3200Mhz RAM&lt;/a&gt;
          240 in a single DIMM in case I want to upgrade to 32Gb later.
          241 Again, what’s with all the RGB lighting and over-the-top heatsinks on the
          242 “gamer” RAM chips?&lt;/p&gt;
          243 
          244 &lt;p&gt;I installed a Samsung 980 Pro 1Tb NVMe SSD which I already had.
          245 The ASUS motherboard has two m.2 slots; one on the top which is underneath a
          246 large heatsink, and one on the bottom of the motherboard.&lt;/p&gt;
          247 
          248 &lt;h2 id=&quot;keyboard-and-mouse&quot;&gt;Keyboard and Mouse&lt;/h2&gt;
          249 
          250 &lt;p&gt;I’m not big into mechanical keyboards (aside from the one on my
          251 &lt;a href=&quot;https://jcs.org/2018/03/20/dolch64&quot;&gt;Dolch PAC 64&lt;/a&gt;)
          252 but after seeing
          253 &lt;a href=&quot;https://www.youtube.com/watch?v=SPVboP_Fvgo&quot;&gt;LGR’s video&lt;/a&gt;
          254 about the
          255 &lt;a href=&quot;https://www.pcgamingrace.com/products/glorious-gmmk-pro-75-barebone-black&quot;&gt;Glorious GMMK
          256 Pro&lt;/a&gt;
          257 75% keyboard, I decided to go with that one for my desktop.
          258 I like that it’s very solid and small, but still includes arrow keys and a nice
          259 rotary knob.
          260 I also share LGR’s opinion that the Glorious branding is stupid and
          261 over-the-top, but luckily it’s just on the bottom of the keyboard so I only ever
          262 had to see it once taking it out of the box.&lt;/p&gt;
          263 
          264 &lt;p&gt;I opted for a black shell, aluminum switch plate, lubed (lol) Glorious Panda
          265 switches, and a
          266 &lt;a href=&quot;https://pimpmykeyboard.com/dsa-dolch-keyset-two-shot/&quot;&gt;“Dolch” DSA keycap set&lt;/a&gt;
          267 that I already had from years back.&lt;/p&gt;
          268 
          269 &lt;p&gt;&lt;a href=&quot;/images/2021-07-19-keyboard-large.jpg&quot;&gt;&lt;img src=&quot;/images/2021-07-19-keyboard-665x314.jpg&quot; srcset=&quot;/images/2021-07-19-keyboard-665x314.jpg 1x, /images/2021-07-19-keyboard-1330x628@2x.jpg 2x&quot; width=&quot;665&quot; height=&quot;314&quot; class=&quot;wide&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
          270 
          271 &lt;p&gt;The switches have a nice tactile feel without being too loud.
          272 Also as Clint noted in his video, the space bar occasionally sticks.
          273 I’m not sure if this will fix itself over time.&lt;/p&gt;
          274 
          275 &lt;p&gt;Configuration of the keys and lighting of the keyboard has to be done with a
          276 &lt;a href=&quot;https://www.pcgamingrace.com/pages/glorious-core?core=GMMK%20PRO&quot;&gt;Windows-only piece of
          277 software&lt;/a&gt;,
          278 so I booted to my Windows-on-a-USB-stick and installed it.
          279 As with the motherboard, I disabled all RGB lighting on the
          280 keyboard.
          281 It would have been nice to have a subtle white backlighting on the keys like my
          282 laptops, but the GMMK Pro’s white RGB lights look blue when at a low brightness.
          283 I reconfigured the keymap to put a permanent Control key where Caps Lock usually
          284 is (as I would do otherwise with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;xmodmap&lt;/code&gt;) and put Delete in the upper right
          285 corner, although I rarely need it.&lt;/p&gt;
          286 
          287 &lt;p&gt;I will probably need to get a wrist rest because my wrists hurt after just a
          288 couple days of typing on it due to the height of the keys.
          289 I’m used to typing on laptop keyboards which are only a few millimeters above
          290 the surface of my desk, so my wrists are usually at a much flatter angle.
          291 For this reason I’ve also been using a
          292 &lt;a href=&quot;https://amzn.to/3xSq05i&quot;&gt;ThinkPad Compact USB Keyboard&lt;/a&gt;
          293 which feels just like a ThinkPad.
          294 My only complaint about this keyboard is that the plastic case can be creaky at
          295 times.
          296 If someone could reproduce the case in aluminum, I’d pay you many dollars.&lt;/p&gt;
          297 
          298 &lt;center&gt;
          299 &lt;a href=&quot;/images/2021-07-19-thinkpad-large.jpg&quot;&gt;&lt;img src=&quot;/images/2021-07-19-thinkpad-327x154.jpg&quot; srcset=&quot;/images/2021-07-19-thinkpad-327x154.jpg 1x, /images/2021-07-19-thinkpad-654x308@2x.jpg 2x&quot; width=&quot;327&quot; height=&quot;154&quot; class=&quot;1/2&quot; /&gt;&lt;/a&gt;
          300 &lt;a href=&quot;/images/2021-07-19-mice-large.jpg&quot;&gt;&lt;img src=&quot;/images/2021-07-19-mice-327x144.jpg&quot; srcset=&quot;/images/2021-07-19-mice-327x144.jpg 1x, /images/2021-07-19-mice-654x288@2x.jpg 2x&quot; width=&quot;327&quot; height=&quot;144&quot; class=&quot;1/2&quot; /&gt;&lt;/a&gt;
          301 &lt;/center&gt;
          302 
          303 &lt;p&gt;As for my mouse, I’m not a gamer so I don’t need something with 35 buttons on
          304 it.
          305 I had been using a
          306 &lt;a href=&quot;https://amzn.to/2Un65Nq&quot;&gt;Lenovo N50 wireless mouse&lt;/a&gt;
          307 for many years with my laptop and I like its design a lot, but its mouse click
          308 and especially its scroll wheel click are very loud.
          309 I recently switched to a
          310 &lt;a href=&quot;https://amzn.to/3isJmYf&quot;&gt;Logitech M355&lt;/a&gt;
          311 because it’s nearly silent.
          312 It uses a wireless USB dongle which I have plugged into the back of the monitor.&lt;/p&gt;
          313 
          314 &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;uhidev2 at uhub5 port 2 configuration 1 interface 0 &quot;Logitech USB Receiver&quot; rev 2.00/30.00 addr 4
          315 uhidev2: iclass 3/1
          316 ums1 at uhidev2: 16 buttons, Z and W dir
          317 wsmouse1 at ums1 mux 0
          318 uhidev3 at uhub5 port 2 configuration 1 interface 1 &quot;Logitech USB Receiver&quot; rev 2.00/30.00 addr 4
          319 uhidev3: iclass 3/0, 17 report ids
          320 uhid5 at uhidev3 reportid 3: input=4, output=0, feature=0
          321 uhidpp0 at uhidev3 reportid 16 device 1 mouse &quot;M355&quot; serial e6-4f-59-05
          322 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
          323 
          324 &lt;p&gt;Its battery status is available via the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uhidpp&lt;/code&gt; driver:&lt;/p&gt;
          325 
          326 &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ sysctl hw.sensors.uhidpp0
          327 hw.sensors.uhidpp0.raw0=4 (battery levels)
          328 hw.sensors.uhidpp0.percent0=90.00% (battery level), OK
          329 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
          330 
          331 &lt;p&gt;My mousepad is some very thin piece of cloth/rubber that I don’t remember where
          332 I got, but I like it because it’s quiet and has no logos on it.&lt;/p&gt;
          333 
          334 &lt;h2 id=&quot;openbsd&quot;&gt;OpenBSD&lt;/h2&gt;
          335 
          336 &lt;p&gt;Of course my system wouldn’t be usable to me if I couldn’t run OpenBSD on it.&lt;/p&gt;
          337 
          338 &lt;p&gt;When I first booted OpenBSD on the system, once the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;amdgpu&lt;/code&gt; KMS driver took
          339 over from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;efifb&lt;/code&gt;, the system would hang (even with a lower-resolution HDMI
          340 monitor connected).
          341 After playing with random BIOS options, I discovered that the BIOS’s CSM needs
          342 to be enabled for some reason.
          343 Even though the system still boots via EFI instead of legacy booting through the
          344 CSM, having the CSM enabled does something not-yet-understood that enables the
          345 video to work properly.&lt;/p&gt;
          346 
          347 &lt;p&gt;This would get the system to boot, but the LG UltraFine display would go blank
          348 (though the backlight was still on) once &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;amdgpu&lt;/code&gt; took over.
          349 I SSH’d in and did an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;xinit&lt;/code&gt;, and then was able to change the resolution from
          350 4096x2304@60Hz to 4096x2304@48Hz.
          351 I’m not sure if this is a bandwidth issue somewhere between the GPU, the
          352 DisplayPort, the cable, or some software issue.
          353 To work around this, I added a
          354 &lt;a href=&quot;https://github.com/jcs/openbsd-src/commit/e529589c95e80a9487927e40a02cc608baad3ab3&quot;&gt;quirk&lt;/a&gt;
          355 to prefer the 4096x2304@48Hz rate in the monitor’s EDID.&lt;/p&gt;
          356 
          357 &lt;p&gt;Since the LG UltraFine exposes a USB HID device to control its brightness, I
          358 &lt;a href=&quot;https://github.com/jcs/openbsd-src/commit/c42e01c96df77fb113167b08509b76fd33d6521c&quot;&gt;wrote a driver&lt;/a&gt;
          359 to attach to it and expose the brightness adjustment through &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;wsconsctl
          360 display.brightness&lt;/code&gt;.&lt;/p&gt;
          361 
          362 &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ dmesg | grep ulguf
          363 ulguf0 at uhub6 port 4 configuration 1 interface 0 &quot;LG Electronics Inc. USB Controls&quot; rev 2.00/3.04 addr 7
          364 
          365 $ wsconsctl display.brightness
          366 display.brightness=50.00%
          367 $ wsconsctl display.brightness=20
          368 display.brightness -&amp;gt; 20.00%
          369 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
          370 
          371 &lt;p&gt;I still need to add support for reading the ambient light sensor and exposing it
          372 through &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sysctl hw.sensors&lt;/code&gt;, which I can then use with something like my
          373 &lt;a href=&quot;https://github.com/jcs/xdimmer&quot;&gt;xdimmer&lt;/a&gt;
          374 to automatically dim the screen at night.&lt;/p&gt;
          375 
          376 &lt;p&gt;To route sound through the monitor’s speakers by default, I have made it use
          377 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rsnd/1&lt;/code&gt; by default, which maps to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;audio1&lt;/code&gt;, via &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uaudio0&lt;/code&gt;.&lt;/p&gt;
          378 
          379 &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ dmesg | grep uaudio
          380 uaudio0 at uhub6 port 1 configuration 1 interface 1 &quot;LG Electronics Inc. USB Audio&quot; rev 2.00/0.2f addr 6
          381 uaudio0: class v1, high-speed, sync, channels: 2 play, 0 rec, 3 ctls
          382 audio1 at uaudio0
          383 
          384 $ grep sndiod_flags /etc/rc.conf.local
          385 sndiod_flags=-f rsnd/1
          386 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
          387 
          388 &lt;p&gt;Since some people have asked, the window manager shown in my photos above is my
          389 &lt;a href=&quot;https://github.com/jcs/sdorfehs&quot;&gt;sdorfehs&lt;/a&gt;
          390 which is a fork of ratpoison.&lt;/p&gt;
          391 
          392 &lt;p&gt;Other than the quirks with my monitor, OpenBSD works well on this motherboard
          393 and CPU.&lt;/p&gt;
          394 
          395 &lt;h2 id=&quot;temperatures&quot;&gt;Temperatures&lt;/h2&gt;
          396 
          397 &lt;p&gt;CPU temperature can be monitored in OpenBSD with the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ksmn&lt;/code&gt; driver:&lt;/p&gt;
          398 
          399 &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ sysctl hw.sensors.ksmn0
          400 hw.sensors.ksmn0.temp0=54.25 degC
          401 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
          402 
          403 &lt;p&gt;Through a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;make -j8 build&lt;/code&gt; of the system maxing out all cores, the CPU
          404 temperature tops out at about 90 °C with the case reaching about 45 °C
          405 (113 °F).
          406 The hottest point is, of course, where the heat pipes attach to the case wall:&lt;/p&gt;
          407 
          408 &lt;center&gt;
          409 &lt;a href=&quot;/images/2021-07-19-flir-large.jpg&quot;&gt;&lt;img src=&quot;/images/2021-07-19-flir-493x369.jpg&quot; srcset=&quot;/images/2021-07-19-flir-493x369.jpg 1x, /images/2021-07-19-flir-986x738@2x.jpg 2x&quot; width=&quot;493&quot; height=&quot;369&quot; class=&quot;3/4&quot; /&gt;&lt;/a&gt;
          410 &lt;/center&gt;</content><author><name></name></author><category term="hardware" /><category term="openbsd" /><summary type="html">After the disappointment of my X1 Nano and learning that all future Intel “Evo”-branded laptops would lack S3 suspend, I started thinking about returning to my M1 MacBook full-time or building an OpenBSD desktop. I chose the latter, building my first desktop machine in many years.</summary></entry><entry><title type="html">WiFiStation: A WiFi interface for the Cidco MailStation</title><link href="https://jcs.org/2021/04/23/wifistation" rel="alternate" type="text/html" title="WiFiStation: A WiFi interface for the Cidco MailStation" /><published>2021-04-23T00:00:00-05:00</published><updated>2021-04-23T00:00:00-05:00</updated><id>https://jcs.org/2021/04/23/wifistation</id><content type="html" xml:base="https://jcs.org/2021/04/23/wifistation">&lt;p&gt;I’ve created an adapter for the
          411 &lt;a href=&quot;https://jcs.org/2019/05/03/mailstation&quot;&gt;Cidco MailStation&lt;/a&gt;
          412 Z80 computer which adds the ability to use WiFi for data transfer, code
          413 uploading, and to act as a WiFi modem for my
          414 &lt;a href=&quot;https://github.com/jcs/msTERM&quot;&gt;msTERM&lt;/a&gt;
          415 terminal emulator.&lt;/p&gt;
          416 
          417 &lt;p&gt;&lt;img src=&quot;/images/2021-04-23-hero-665x182.jpg&quot; srcset=&quot;/images/2021-04-23-hero-665x182.jpg 1x, /images/2021-04-23-hero-1330x364@2x.jpg 2x&quot; width=&quot;665&quot; height=&quot;182&quot; alt=&quot;WiFiStation&quot; class=&quot;header&quot; /&gt;&lt;/p&gt;
          418 
          419 
          420 
          421 &lt;p class=&quot;alert&quot;&gt;&lt;strong&gt;Note:&lt;/strong&gt; For the latest information on this project, please see my dedicated
          422 &lt;a href=&quot;/wifistation&quot;&gt;WiFiStation&lt;/a&gt;
          423 pages.&lt;/p&gt;
          424 
          425 &lt;h2 id=&quot;background&quot;&gt;Background&lt;/h2&gt;
          426 
          427 &lt;p&gt;In 2019, I
          428 &lt;a href=&quot;https://jcs.org/2019/05/03/mailstation#creating-msterm&quot;&gt;created a terminal program&lt;/a&gt;
          429 for the MailStation called msTERM which made it possible to dial into BBSes
          430 with the MailStation’s built-in modem.
          431 While this was a fun project and allowed me to dial into to
          432 &lt;a href=&quot;//klud.ge/&quot;&gt;my own BBS&lt;/a&gt;,
          433 the novelty soon wore off and I returned to using telnet and SSH.&lt;/p&gt;
          434 
          435 &lt;p&gt;Last year, someone asked me if the MailStation could be used as a simple word
          436 processor similar to the
          437 &lt;a href=&quot;https://en.wikipedia.org/wiki/AlphaSmart&quot;&gt;AlphaSmart Dana&lt;/a&gt;.
          438 I told them such software could be written but it would be difficult to use
          439 since the only&lt;sup id=&quot;fnref:0&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:0&quot; class=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; way to exchange documents with the MailStation would be
          440 through its modem or a
          441 &lt;a href=&quot;https://en.wikipedia.org/wiki/LapLink_cable&quot;&gt;parallel LapLink cable&lt;/a&gt;,
          442 both of which are difficult to use since most people don’t have landlines
          443 anymore and similarly, most computers don’t have parallel ports anymore.&lt;/p&gt;
          444 
          445 &lt;p&gt;While I had recently created a
          446 &lt;a href=&quot;/2020/03/31/mailstation_usb&quot;&gt;USB adapter&lt;/a&gt;
          447 to eliminate the need for a parallel cable, I thought it might be useful to have
          448 a WiFi interface instead.
          449 This would allow msTERM to “dial” out over telnet instead of its modem, just
          450 like the myriad of
          451 &lt;a href=&quot;/2017/06/23/wifi232&quot;&gt;WiFi modem serial adapters&lt;/a&gt;,
          452 while also providing a simple web interface where users could upload files and
          453 have them transferred to the MailStation.&lt;/p&gt;
          454 
          455 &lt;h2 id=&quot;data-transfer&quot;&gt;Data Transfer&lt;/h2&gt;
          456 
          457 &lt;p&gt;Like those WiFi serial adapters, using an
          458 &lt;a href=&quot;https://en.wikipedia.org/wiki/ESP8266&quot;&gt;ESP32/ESP8266&lt;/a&gt; seemed like the easiest
          459 solution.
          460 However, designing something that directly interfaced a ESP8266 to the
          461 processor seemed like a daunting task, mostly because I have no idea how to do
          462 such a thing but also because anyone that wanted similar functionality would
          463 have to tear apart their MailStation.&lt;/p&gt;
          464 
          465 &lt;p&gt;I settled on making an ESP8266 a standalone device and having it talk through
          466 the MailStation’s parallel port, allowing it to work without any hardware
          467 modifications needed.&lt;/p&gt;
          468 
          469 &lt;p&gt;The MailStation firmware includes a built-in function for sending and receiving
          470 bytes over its parallel port, but it does so over five of the eight data pins,
          471 in three transfers, for every single byte.
          472 The USB loader that I had made earlier adhered to this protocol to remain
          473 compatible with the firmware function, making the
          474 &lt;a href=&quot;https://github.com/jcs/mailstation-tools/blob/master/loader.asm&quot;&gt;loader program&lt;/a&gt;
          475 that runs on the MailStation as small as possible since its binary has to be
          476 hand-typed into the MailStation’s hex editor.&lt;/p&gt;
          477 
          478 &lt;p&gt;This three-step process is not terribly slow, but it makes bi-directional
          479 communication more complicated and seemed unnecessary when all eight of the data
          480 pins were wired up.
          481 For WiFistation, I decided to use a much more straightforward protocol using all
          482 eight data pins plus two status and two control pins.
          483 The new
          484 &lt;a href=&quot;https://github.com/jcs/WiFiStation/blob/main/mailstation/wsloader.asm&quot;&gt;loader&lt;/a&gt;
          485 for this protocol, which doesn’t rely on any firmware functionality, ended
          486 up being 117 bytes vs. 97 for the
          487 &lt;a href=&quot;https://github.com/jcs/mailstation-tools/blob/master/loader.asm&quot;&gt;original&lt;/a&gt;.&lt;/p&gt;
          488 
          489 &lt;h2 id=&quot;prototyping&quot;&gt;Prototyping&lt;/h2&gt;
          490 
          491 &lt;p&gt;Earlier this year I assembled a prototype based on
          492 &lt;a href=&quot;https://www.adafruit.com/product/2471&quot;&gt;Adafruit’s Huzzah ESP8266&lt;/a&gt;
          493 board.
          494 To be able to manipulate 12 5v GPIO pins from the ESP8266 (which only has a few
          495 available GPIO pins, and they only operate at 3.3v), I used an
          496 &lt;a href=&quot;https://www.microchip.com/wwwproducts/en/mcp23017&quot;&gt;MCP23017&lt;/a&gt;
          497 I&lt;sup&gt;2&lt;/sup&gt;C chip, which ultimately proved to be too slow to transfer large
          498 files (~16Kb) so I switched to the
          499 &lt;a href=&quot;https://www.microchip.com/wwwproducts/en/MCP23S18&quot;&gt;MCP23S18&lt;/a&gt;
          500 which interfaces over SPI.&lt;/p&gt;
          501 
          502 &lt;figure&gt;
          503 &lt;a href=&quot;/images/2021-04-23-prototype-large.jpg&quot;&gt;&lt;img src=&quot;/images/2021-04-23-prototype-327x245.jpg&quot; srcset=&quot;/images/2021-04-23-prototype-327x245.jpg 1x, /images/2021-04-23-prototype-654x490@2x.jpg 2x&quot; width=&quot;327&quot; height=&quot;245&quot; alt=&quot;prototype of WiFiStation on a breadboard&quot; class=&quot;1/2&quot; /&gt;&lt;/a&gt;
          504 &lt;a href=&quot;/images/2021-04-23-prototype_rear-large.jpg&quot;&gt;&lt;img src=&quot;/images/2021-04-23-prototype_rear-327x245.jpg&quot; srcset=&quot;/images/2021-04-23-prototype_rear-327x245.jpg 1x, /images/2021-04-23-prototype_rear-654x490@2x.jpg 2x&quot; width=&quot;327&quot; height=&quot;245&quot; alt=&quot;rear view of WiFiStation prototype&quot; class=&quot;1/2&quot; /&gt;&lt;/a&gt;
          505 &lt;/figure&gt;
          506 
          507 &lt;p&gt;The prototype worked with the
          508 &lt;a href=&quot;https://github.com/jcs/msTERM/commit/bfa680dbe1759ca34fe285d223d81684ea436892&quot;&gt;msTERM
          509 modifications&lt;/a&gt;
          510 I made, so I set about turning into something I could make available to others.&lt;/p&gt;
          511 
          512 &lt;p&gt;While the Adafruit Huzzah board had almost everything I needed, I decided to
          513 upgrade to their slightly larger
          514 &lt;a href=&quot;https://www.adafruit.com/product/2821&quot;&gt;Feather Huzzah&lt;/a&gt;
          515 board, which upgrades the 5-pin FTDI serial header to a proper CP2104 USB serial
          516 port and has built-in battery charging bits so the WiFiStation could optionally
          517 run from a
          518 &lt;a href=&quot;https://www.adafruit.com/product/4237&quot;&gt;rechargable battery&lt;/a&gt;.
          519 Since the MailStation can already run on AA batteries, this would allow the
          520 entire system to be portable.&lt;/p&gt;
          521 
          522 &lt;p&gt;Of course, only after doing all of my development and reflashing the original
          523 Huzzah board many dozens of times did I learn that the Feather version has
          524 auto-reset support so one can reflash it entirely from a command-line.
          525 The non-Feather version requires holding down two tiny buttons on the board to
          526 reset into its bootloader every time.&lt;/p&gt;
          527 
          528 &lt;h2 id=&quot;designing-a-pcb&quot;&gt;Designing a PCB&lt;/h2&gt;
          529 
          530 &lt;p&gt;Since I am not a hardware hacker and have no background in electronics, turning
          531 my prototype into a PCB was a bit daunting.
          532 I downloaded the free version of
          533 &lt;a href=&quot;https://www.autodesk.com/products/eagle/overview&quot;&gt;EAGLE&lt;/a&gt;
          534 and stumbled through how to design a
          535 &lt;a href=&quot;https://github.com/jcs/WiFiStation/tree/main/pcb&quot;&gt;schematic&lt;/a&gt;
          536 and then turned it into a halfway-decent looking board.
          537 Since I’m also not comfortable doing surface-mount soldering, I opted for
          538 entirely through-hole components.&lt;/p&gt;
          539 
          540 &lt;p&gt;Once my initial design seemed sufficient, I uploaded it to
          541 &lt;a href=&quot;https://www.pcbway.com/&quot;&gt;PCBWay&lt;/a&gt;
          542 for printing of the PCB.
          543 I also ordered a handful of Huzzah Feather modules, DB25 connectors, resistors,
          544 MCP23S18 chips, and sockets from
          545 &lt;a href=&quot;https://www.digikey.com/&quot;&gt;DigiKey&lt;/a&gt;.&lt;/p&gt;
          546 
          547 &lt;figure&gt;
          548 &lt;a href=&quot;/images/2021-04-23-eagle-large.png&quot;&gt;&lt;img src=&quot;/images/2021-04-23-eagle-327x207.png&quot; srcset=&quot;/images/2021-04-23-eagle-327x207.png 1x, /images/2021-04-23-eagle-654x414@2x.png 2x&quot; width=&quot;327&quot; height=&quot;207&quot; alt=&quot;WiFiStation schematic&quot; class=&quot;1/2&quot; /&gt;&lt;/a&gt;
          549 &lt;a href=&quot;/images/2021-04-23-eagle_board-large.png&quot;&gt;&lt;img src=&quot;/images/2021-04-23-eagle_board-327x208.png&quot; srcset=&quot;/images/2021-04-23-eagle_board-327x208.png 1x, /images/2021-04-23-eagle_board-654x416@2x.png 2x&quot; width=&quot;327&quot; height=&quot;208&quot; alt=&quot;WiFiStation board&quot; class=&quot;1/2&quot; /&gt;&lt;/a&gt;
          550 &lt;/figure&gt;
          551 
          552 &lt;p&gt;A week and a half and $25 later, I received my batch of five boards.
          553 I soldered the components to one of them and then spent a frustrating day trying
          554 to figure out why I was getting strange results with it.&lt;/p&gt;
          555 
          556 &lt;p&gt;As it turned out, the standard “SUB-D” DB25 part that I had picked in EAGLE had
          557 its pinout backwards from what I was expecting and how my prototype’s breakout
          558 board was numbered, and I did not verify it carefully enough.
          559 I flipped the component around and rerouted all of the wires in the board
          560 design, which also allowed me to eliminate the vias, and then sent the new
          561 revision to PCBWay.
          562 Another week and a half later, I had my “revision B” boards.&lt;/p&gt;
          563 
          564 &lt;figure&gt;
          565 &lt;a href=&quot;/images/2021-04-23-rev1-large.jpg&quot;&gt;&lt;img src=&quot;/images/2021-04-23-rev1-327x245.jpg&quot; srcset=&quot;/images/2021-04-23-rev1-327x245.jpg 1x, /images/2021-04-23-rev1-654x490@2x.jpg 2x&quot; width=&quot;327&quot; height=&quot;245&quot; alt=&quot;WiFiStation board - revision 1&quot; class=&quot;1/2&quot; /&gt;&lt;/a&gt;
          566 &lt;a href=&quot;/images/2021-04-23-rev2_assembled-large.jpg&quot;&gt;&lt;img src=&quot;/images/2021-04-23-rev2_assembled-327x245.jpg&quot; srcset=&quot;/images/2021-04-23-rev2_assembled-327x245.jpg 1x, /images/2021-04-23-rev2_assembled-654x490@2x.jpg 2x&quot; width=&quot;327&quot; height=&quot;245&quot; alt=&quot;WiFiStation board - revision 2 assembled&quot; class=&quot;1/2&quot; /&gt;&lt;/a&gt;
          567 &lt;/figure&gt;
          568 
          569 &lt;p&gt;This version produced the correct data on each pin, but was doing so
          570 inconsistently.
          571 I thought it might have been the bussed resistor that I chose instead of
          572 individual resistors like my prototype, but I later determined it to be the DB25
          573 connector itself not being properly grounded.&lt;/p&gt;
          574 
          575 &lt;p&gt;I fixed this in the board design but as I started mocking up an enclosure for
          576 it, I realized that the DB25 connector was not placed proud enough on the board
          577 for a case to fit along the front edge without the pins being too far back.
          578 I also realized there was no way to securely fasten the two DB25 connectors
          579 together, as the MailStation has fixed screw nuts on it, but with the rear of
          580 the WiFiStation’s connector being covered up, there would be no way to put a
          581 screw through it and tighten it down.&lt;/p&gt;
          582 
          583 &lt;p&gt;I came up with the idea to shrink the width of the board by moving the MCP23S18
          584 to a horizontal position with the Huzzah straddling it, since the Huzzah was
          585 already sticking up high enough due to its pin headers.
          586 I also positioned the Huzzah Feather so that the DB25 screw holes were visible
          587 from the back of the board, allowing long screws to reach from outside the rear
          588 of the case, under the Huzzah board, and through the DB25 connector holes, into
          589 the MailStation’s DB25 connector.&lt;/p&gt;
          590 
          591 &lt;p&gt;I finished this third redesign of the board and sent it off for printing.&lt;/p&gt;
          592 
          593 &lt;figure&gt;
          594 &lt;a href=&quot;/images/2021-04-23-final-large.jpg&quot;&gt;&lt;img src=&quot;/images/2021-04-23-final-327x245.jpg&quot; srcset=&quot;/images/2021-04-23-final-327x245.jpg 1x, /images/2021-04-23-final-654x490@2x.jpg 2x&quot; width=&quot;327&quot; height=&quot;245&quot; alt=&quot;WiFiStation board - final revision&quot; class=&quot;1/2&quot; /&gt;&lt;/a&gt;
          595 &lt;a href=&quot;/images/2021-04-23-final_assembled-large.jpg&quot;&gt;&lt;img src=&quot;/images/2021-04-23-final_assembled-327x245.jpg&quot; srcset=&quot;/images/2021-04-23-final_assembled-327x245.jpg 1x, /images/2021-04-23-final_assembled-654x490@2x.jpg 2x&quot; width=&quot;327&quot; height=&quot;245&quot; alt=&quot;WiFiStation board - final revision assembled&quot; class=&quot;1/2&quot; /&gt;&lt;/a&gt;
          596 &lt;/figure&gt;
          597 
          598 &lt;h2 id=&quot;making-the-case&quot;&gt;Making the Case&lt;/h2&gt;
          599 
          600 &lt;p&gt;While waiting for the new boards to arrive, I needed an enclosure for them.
          601 As if fumbling through PCB design wasn’t enough, I was also going to have to
          602 do some
          603 &lt;a href=&quot;https://twitter.com/jcs/status/1372024803817877506&quot;&gt;3D modeling and printing&lt;/a&gt;.
          604 I designed a case for the WiFiStation in TinkerCAD and thankfully this didn’t
          605 require a week and a half between iterations.
          606 I soon had a
          607 &lt;a href=&quot;https://github.com/jcs/WiFiStation/blob/main/enclosure/enclosure.stl&quot;&gt;decent case&lt;/a&gt;
          608 that connected together and allowed an optional lithium ion battery to be
          609 housed in it as well.&lt;/p&gt;
          610 
          611 &lt;figure&gt;
          612 &lt;a href=&quot;/images/2021-04-23-printing-large.jpg&quot;&gt;&lt;img src=&quot;/images/2021-04-23-printing-327x245.jpg&quot; srcset=&quot;/images/2021-04-23-printing-327x245.jpg 1x, /images/2021-04-23-printing-654x490@2x.jpg 2x&quot; width=&quot;327&quot; height=&quot;245&quot; alt=&quot;Enclosure being printed&quot; class=&quot;1/2&quot; /&gt;&lt;/a&gt;
          613 &lt;a href=&quot;/images/2021-04-23-case-large.jpg&quot;&gt;&lt;img src=&quot;/images/2021-04-23-case-327x245.jpg&quot; srcset=&quot;/images/2021-04-23-case-327x245.jpg 1x, /images/2021-04-23-case-654x490@2x.jpg 2x&quot; width=&quot;327&quot; height=&quot;245&quot; alt=&quot;Enclosure&quot; class=&quot;1/2&quot; /&gt;&lt;/a&gt;
          614 &lt;/figure&gt;
          615 
          616 &lt;p&gt;I still have some more iterating to go on the case design to make something that
          617 has a more secure closure.
          618 I’m also still sourcing some thumbscrews that will properly fit the case, like
          619 &lt;a href=&quot;https://www.digikey.com/en/products/detail/molex/1727040159/5817827&quot;&gt;these&lt;/a&gt;.&lt;/p&gt;
          620 
          621 &lt;h2 id=&quot;firmware&quot;&gt;Firmware&lt;/h2&gt;
          622 
          623 &lt;p&gt;With the hardware design done, I developed more of the
          624 &lt;a href=&quot;https://github.com/jcs/WiFiStation/tree/main/esp8266&quot;&gt;firmware&lt;/a&gt;
          625 to run on the Huzzah ESP8266 board.
          626 I integrated a web server which currently just allows uploading a file to be
          627 transferred to the new loader program.&lt;/p&gt;
          628 
          629 &lt;figure&gt;
          630 &lt;a href=&quot;/images/2021-04-23-http-large.jpg&quot;&gt;&lt;img src=&quot;/images/2021-04-23-http-493x148.jpg&quot; srcset=&quot;/images/2021-04-23-http-493x148.jpg 1x, /images/2021-04-23-http-986x296@2x.jpg 2x&quot; width=&quot;493&quot; height=&quot;148&quot; alt=&quot;WiFiStation HTTP interface&quot; class=&quot;3/4&quot; /&gt;&lt;/a&gt;
          631 &lt;/figure&gt;
          632 
          633 &lt;p&gt;I also improved the telnet/&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ATDT&lt;/code&gt; handling so msTERM can now dial into BBSes
          634 over telnet with proper telnet negotiation, and one do things like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;+++ ATH&lt;/code&gt; to
          635 hang up.&lt;/p&gt;
          636 
          637 &lt;figure&gt;
          638 &lt;a href=&quot;/images/2021-04-23-telnet-large.jpg&quot;&gt;&lt;img src=&quot;/images/2021-04-23-telnet-493x284.jpg&quot; srcset=&quot;/images/2021-04-23-telnet-493x284.jpg 1x, /images/2021-04-23-telnet-986x568@2x.jpg 2x&quot; width=&quot;493&quot; height=&quot;284&quot; alt=&quot;WiFiStation telnetting&quot; class=&quot;3/4&quot; /&gt;&lt;/a&gt;
          639 &lt;/figure&gt;
          640 
          641 &lt;p&gt;And with the WiFiStation using a battery, this entire thing can be done
          642 wirelessly.&lt;/p&gt;
          643 
          644 &lt;h2 id=&quot;wifistation-kits&quot;&gt;WiFiStation Kits&lt;/h2&gt;
          645 
          646 &lt;p&gt;With all of the hardware design nailed down and the software mostly done, I’ve
          647 written up some
          648 &lt;a href=&quot;/wifistation&quot;&gt;documentation&lt;/a&gt;
          649 for the whole system including assembly instructions.&lt;/p&gt;
          650 
          651 &lt;p&gt;These kits are
          652 &lt;a href=&quot;https://www.tindie.com/products/jcs/wifistation/&quot;&gt;for sale on Tindie&lt;/a&gt;
          653 for those interested.
          654 I realize the target audience for this is very small but I hope this project
          655 brings more attention to the MailStation as a fun Z80 development platform.&lt;/p&gt;
          656 
          657 &lt;p&gt;&lt;br /&gt;&lt;/p&gt;
          658 
          659 &lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
          660   &lt;ol&gt;
          661     &lt;li id=&quot;fn:0&quot; role=&quot;doc-endnote&quot;&gt;
          662       &lt;p&gt;I know the Dana can connect to a PC with a USB cable and act as a fake keyboard to “type-out” the document, but I think this is pretty cumbersome. &lt;a href=&quot;#fnref:0&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
          663     &lt;/li&gt;
          664   &lt;/ol&gt;
          665 &lt;/div&gt;</content><author><name></name></author><category term="hardware" /><category term="retrocomputing" /><category term="z80" /><summary type="html">I’ve created an adapter for the Cidco MailStation Z80 computer which adds the ability to use WiFi for data transfer, code uploading, and to act as a WiFi modem for my msTERM terminal emulator.</summary></entry><entry><title type="html">OpenBSD on the Lenovo ThinkPad X1 Nano (1st Gen)</title><link href="https://jcs.org/2021/01/27/x1nano" rel="alternate" type="text/html" title="OpenBSD on the Lenovo ThinkPad X1 Nano (1st Gen)" /><published>2021-01-27T00:00:00-06:00</published><updated>2021-04-07T14:40:20-05:00</updated><id>https://jcs.org/2021/01/27/x1nano</id><content type="html" xml:base="https://jcs.org/2021/01/27/x1nano">&lt;p&gt;Lenovo has finally made a smaller version of its
          666 &lt;a href=&quot;/2019/08/14/x1c7&quot;&gt;X1 Carbon&lt;/a&gt;,
          667 something I’ve been looking forward to for years.&lt;/p&gt;
          668 
          669 &lt;p&gt;&lt;img src=&quot;/images/2021-01-27-hero-665x207.jpg&quot; srcset=&quot;/images/2021-01-27-hero-665x207.jpg 1x, /images/2021-01-27-hero-1330x414@2x.jpg 2x&quot; width=&quot;665&quot; height=&quot;207&quot; alt=&quot;side profile of thinkpad x1 nano on desk&quot; class=&quot;header&quot; /&gt;&lt;/p&gt;
          670 
          671 
          672 
          673 &lt;h2 id=&quot;hardware&quot;&gt;Hardware&lt;/h2&gt;
          674 
          675 &lt;p&gt;The X1 Nano is basically a 13” version of the 14” X1 Carbon, reducing its
          676 footprint, thickness, and weight.
          677 Availability in the US has been fairly limited (and expensive) at the moment,
          678 offering no WWAN or any customizable options, and Core i7 models are not
          679 shipping out for months.
          680 I purchased the Intel Core i5-1135G7 model with 16Gb of RAM and a 1Tb NVMe SSD.
          681 The only screen option currently available is a matte non-touch 2K display.&lt;/p&gt;
          682 
          683 &lt;p&gt;The X1 Nano (X1N1?) weighs 2.0 lbs compared to my previous
          684 &lt;a href=&quot;/2019/08/14/x1c7&quot;&gt;X1C7’s&lt;/a&gt;
          685 2.4 lbs.
          686 The width is reduced from the 14” X1 Carbon’s 12.71” to 11.53”, depth from
          687 8.54” to 8.18”, and thickness from 14.95mm to 13.87mm.&lt;/p&gt;
          688 
          689 &lt;p&gt;On the left side of the laptop are two Thunderbolt 3-enabled (USB 4) USB-C
          690 ports and a headphone jack.
          691 The PCI ethernet device and its required dongle are no longer available, which
          692 is not really needed these days with non-Thunderbolt USB-C ethernet adapters
          693 being able to max out a gigabit ethernet connection (at least on non-OpenBSD
          694 platforms).&lt;/p&gt;
          695 
          696 &lt;p&gt;On the right side are just the fan vent and power button, which is now moved
          697 from about the middle of the side to the far-right edge.
          698 I find the power button very hard to press now, especially to hold it in for
          699 how ever many seconds it takes to force a hard power-off.&lt;/p&gt;
          700 
          701 &lt;p&gt;The Dolby Atmos sound system remains with its unfortunate branding still
          702 present on the left side of the keyboard deck.
          703 There are two up-firing speakers at the top of the keyboard deck, which sound
          704 excellent and loud.&lt;/p&gt;
          705 
          706 &lt;p&gt;The 13” 2K (2160x1350) matte, non-touch IPS screen looks great and is the same
          707 horizontal resolution as my
          708 &lt;a href=&quot;/2017/07/14/matebook&quot;&gt;13” MateBook X&lt;/a&gt;
          709 which I’ve still been using for years.
          710 The resolution is high enough to use 1.5x scaling but low enough to not draw a
          711 lot of power.
          712 It can get very bright at 450 nits, and most of the time indoors I’m using it
          713 at about 40% brightness.
          714 I did a color calibration and it wasn’t too far off the factory default.&lt;/p&gt;
          715 
          716 &lt;p&gt;The Nano has a ThinkShutter device to physically cover up the webcam lens as my
          717 X1 Carbon did, and retains the black “ThinkPad” branding on the keyboard deck.&lt;/p&gt;
          718 
          719 &lt;p&gt;The screen hinge is tight and cannot really be opened one-handed due to the
          720 reduced weight of the laptop.
          721 However, the lid does not wobble at all when typing.&lt;/p&gt;
          722 
          723 &lt;p&gt;The keyboard still seems full-sized, though the function-row keys are shorter.
          724 The X1 Nano further reduces the X1C7’s key travel from 1.5mm to 1.35mm, though
          725 I still find it very enjoyable to type on and it retains a chunky tactile feel.
          726 The keys do have a bit of a creaky sound when typing or just moving fingers on
          727 keys without pressing them.
          728 The keyboard is backlit and offers two levels of adjustment with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Fn+Space&lt;/code&gt; or
          729 through &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;wsconsctl keyboard.backlight&lt;/code&gt; on OpenBSD, or through software
          730 utilities like
          731 &lt;a href=&quot;https://github.com/jcs/xdimmer&quot;&gt;xdimmer&lt;/a&gt;.&lt;/p&gt;
          732 
          733 &lt;p&gt;The Elan touchpad surface remains soft and easy to glide fingers across,
          734 and its integrated “diving-board-style” button has a quiet thud for a click
          735 with no play in its mechanism.
          736 The three physical TrackPoint buttons between the keyboard and touchpad have a
          737 shallow click.
          738 The TrackPoint still operates over a legacy PS/2 attachment and the touchpad
          739 is a Windows Precision Touchpad connected over I&lt;sup&gt;2&lt;/sup&gt;C as on the X1C7.&lt;/p&gt;
          740 
          741 &lt;p&gt;I am using the far-superior
          742 &lt;a href=&quot;https://www.etsy.com/jp/shop/SaotoTech&quot;&gt;“soft rim”-style TrackPoint cap&lt;/a&gt;
          743 that was made for my X1C7 and is probably a hair too tall for the lower-profile
          744 X1N1 keyboard, but it doesn’t stick up past the keys nor contact the screen
          745 when closed.&lt;/p&gt;
          746 
          747 &lt;figure&gt;
          748 &lt;a href=&quot;/images/2021-01-27-trackpoint-large.jpg&quot;&gt;&lt;img src=&quot;/images/2021-01-27-trackpoint-327x245.jpg&quot; srcset=&quot;/images/2021-01-27-trackpoint-327x245.jpg 1x, /images/2021-01-27-trackpoint-654x490@2x.jpg 2x&quot; width=&quot;327&quot; height=&quot;245&quot; alt=&quot;close-up of keyboard showing new trackpoint cap installed, with old cap next to it&quot; class=&quot;1/2&quot; /&gt;&lt;/a&gt;
          749 &lt;a href=&quot;/images/2021-01-27-trackpoint_profile-large.jpg&quot;&gt;&lt;img src=&quot;/images/2021-01-27-trackpoint_profile-327x245.jpg&quot; srcset=&quot;/images/2021-01-27-trackpoint_profile-327x245.jpg 1x, /images/2021-01-27-trackpoint_profile-654x490@2x.jpg 2x&quot; width=&quot;327&quot; height=&quot;245&quot; alt=&quot;new trackpoint cap height compared to keyboard key height&quot; class=&quot;1/2&quot; /&gt;&lt;/a&gt;
          750 &lt;/figure&gt;
          751 
          752 &lt;p&gt;A square USB-attached fingerprint sensor sits next to the touchpad which I’ve
          753 honestly forgotten about until I just looked.&lt;/p&gt;
          754 
          755 &lt;p&gt;Wireless connectivity is provided by a non-socketed Intel AX201 802.11ax WiFi
          756 and Bluetooth 5.1 chip.
          757 The NVMe SSD is a Western Digital PC SN530 removable m.2 2242 form-factor drive
          758 mounted under a heatsink.&lt;/p&gt;
          759 
          760 &lt;p&gt;There is no audible coil whine.
          761 The fan has a tendency to come on rather eagerly when the CPU is allowed to use
          762 its full frequency with turbo, and to remain on for what seems like a long
          763 time even after the CPU-intensive operation has stopped and the surface of the
          764 laptop is cool to the touch.
          765 Fortunately the fan is rather quiet (~33 dBA about an inch from the exhaust
          766 outlet at the fan’s highest setting) and has a neutral white-noise sound
          767 without any high-pitched whining.
          768 Perhaps a future update to the firmware/EC will adjust the temperature
          769 thresholds for the fan to come on less eagerly, and not stay on so long.&lt;/p&gt;
          770 
          771 &lt;figure&gt;
          772 &lt;a href=&quot;/images/2021-01-27-inside-large.jpg&quot;&gt;&lt;img src=&quot;/images/2021-01-27-inside-493x369.jpg&quot; srcset=&quot;/images/2021-01-27-inside-493x369.jpg 1x, /images/2021-01-27-inside-986x738@2x.jpg 2x&quot; width=&quot;493&quot; height=&quot;369&quot; alt=&quot;inside of x1 nano&quot; class=&quot;3/4&quot; /&gt;&lt;/a&gt;
          773 &lt;/figure&gt;
          774 
          775 &lt;h2 id=&quot;firmware&quot;&gt;Firmware&lt;/h2&gt;
          776 
          777 &lt;p&gt;The X1 Nano defaults to a graphical firmware upon pressing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;F1&lt;/code&gt;, which can be
          778 switched back into a simple text mode.
          779 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;F12&lt;/code&gt; can be used to temporarily select a different boot device.
          780 Pro-tip: press &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Fn+F1&lt;/code&gt; to mute the speakers before pressing either of these
          781 options to prevent a loud, annoying beep.&lt;/p&gt;
          782 
          783 &lt;p&gt;I recommend enabling the “F1-F12 as Primary Function” option to not require
          784 using the Fn key to register these keys.&lt;/p&gt;
          785 
          786 &lt;p&gt;Installing a different boot logo is still
          787 &lt;a href=&quot;https://jcs.org/2017/09/01/thinkpad_x1c#firmware&quot;&gt;possible&lt;/a&gt;
          788 through Windows, which also gets rid of the new “TCO Certified” logo in the
          789 bottom-right corner.&lt;/p&gt;
          790 
          791 &lt;p&gt;Secure Boot must be disabled in the BIOS menu to boot OpenBSD, and a “CSM
          792 Support” option is no longer available (nor needed).&lt;/p&gt;
          793 
          794 &lt;p&gt;Unfortunately the X1 Nano is an “Intel Evo” platform device, which means it no
          795 longer has a normal ACPI S3 suspend mode.
          796 The X1C7 had a firmware option to disable this “Modern Standby” and enable
          797 “Legacy S3 standby mode”, but the X1 Nano no longer has this option.
          798 This means that OpenBSD is unable to suspend the laptop since the firmware no
          799 longer supports it.
          800 Efforts to support &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;S0ix&lt;/code&gt; and achieve a similar level of suspended power
          801 consumption are underway, as my
          802 &lt;a href=&quot;/2020/05/15/surface_go2&quot;&gt;Surface Go 2&lt;/a&gt;
          803 was a similar device.&lt;/p&gt;
          804 
          805 &lt;h2 id=&quot;openbsd-support-log&quot;&gt;OpenBSD Support Log&lt;/h2&gt;
          806 
          807 &lt;p&gt;&lt;strong&gt;2021-01-17:&lt;/strong&gt; The usual round of PCI device ID additions have been made, and
          808 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;iwx&lt;/code&gt; has been
          809 &lt;a href=&quot;https://github.com/openbsd/src/commit/8edfa316af4155e6583562fc817d827a3f2fbd09&quot;&gt;updated&lt;/a&gt;
          810 to attach to the AX201 device found in the X1 Nano.&lt;/p&gt;
          811 
          812 &lt;p&gt;There are some minor issues with DPMS that cause the screen to take a few
          813 seconds longer to wake up after being shut off.
          814 Sometimes when returning to my laptop after it’s been locked (and the screen
          815 turned off via DPMS) it blinks a few times before showing the screen contents.&lt;/p&gt;
          816 
          817 &lt;p&gt;&lt;strong&gt;2021-01-25:&lt;/strong&gt; I’ve been experimenting with
          818 &lt;a href=&quot;https://github.com/jcs/openbsd-src/commit/cf7c4a31389d24a07c91c40e3daa9da68339e037&quot;&gt;adjustable fan control in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;acpithinkpad&lt;/code&gt;&lt;/a&gt;
          819 to silence the fan at all times.
          820 It doesn’t seem to raise the temperature too high, and the laptop seems capable
          821 of passively cooling itself down fairly well once CPU-intensive tasks have
          822 stopped.&lt;/p&gt;
          823 
          824 &lt;p&gt;&lt;strong&gt;2021-01-27:&lt;/strong&gt; I’ve also been working on
          825 &lt;a href=&quot;https://github.com/jcs/openbsd-src/commit/29edcdbd593388193af3e1461f4432c6c94ff5b2&quot;&gt;adding support for Intel HWP&lt;/a&gt;
          826 as a modern replacement for OpenBSD’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hw.setperf&lt;/code&gt;, where the
          827 processors/firmware dynamically adjust their frequency on their own in response
          828 to work load, rather than the OpenBSD kernel doing it.&lt;/p&gt;
          829 
          830 &lt;p&gt;&lt;strong&gt;2021-04-07:&lt;/strong&gt; Due to the lack of S3 suspend and a keyboard repair (under
          831 warranty by Lenovo) that made the keyboard feel worse, I’ve sold my X1 Nano.
          832 At this time, I can’t recommend buying any “Intel Evo” branded laptop for
          833 OpenBSD use due to the lack of hardware S3 suspend support forced on these
          834 laptops, combined with a lack of any “instant wake” mechanism in OpenBSD’s
          835 kernel.&lt;/p&gt;
          836 
          837 &lt;h2 id=&quot;current-openbsd-support-summary&quot;&gt;Current OpenBSD Support Summary&lt;/h2&gt;
          838 
          839 &lt;p&gt;Status is relative to OpenBSD-current as of 2021-01-27.&lt;/p&gt;
          840 
          841 &lt;table&gt;
          842   &lt;thead&gt;
          843     &lt;tr&gt;
          844       &lt;th&gt;Component&lt;/th&gt;
          845       &lt;th&gt;Works?&lt;/th&gt;
          846       &lt;th&gt;Notes&lt;/th&gt;
          847     &lt;/tr&gt;
          848   &lt;/thead&gt;
          849   &lt;tbody&gt;
          850     &lt;tr&gt;
          851       &lt;td&gt;Audio&lt;/td&gt;
          852       &lt;td&gt;Yes&lt;/td&gt;
          853       &lt;td&gt;Intel audio with Realtek ALC287 codec and supported by &lt;a href=&quot;http://man.openbsd.org/azalia.4&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;azalia&lt;/code&gt;&lt;/a&gt;. Microphone can be disabled in the BIOS.&lt;/td&gt;
          854     &lt;/tr&gt;
          855     &lt;tr&gt;
          856       &lt;td&gt;Battery status&lt;/td&gt;
          857       &lt;td&gt;Yes&lt;/td&gt;
          858       &lt;td&gt;48Whr battery, status available through &lt;a href=&quot;http://man.openbsd.org/acpibat.4&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;acpibat&lt;/code&gt;&lt;/a&gt;.&lt;/td&gt;
          859     &lt;/tr&gt;
          860     &lt;tr&gt;
          861       &lt;td&gt;Bluetooth&lt;/td&gt;
          862       &lt;td&gt;No&lt;/td&gt;
          863       &lt;td&gt;Attaches as a &lt;a href=&quot;http://man.openbsd.org/ugen.4&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ugen&lt;/code&gt;&lt;/a&gt; device, but OpenBSD does not support Bluetooth. Can be disabled in the BIOS.&lt;/td&gt;
          864     &lt;/tr&gt;
          865     &lt;tr&gt;
          866       &lt;td&gt;Fingerprint sensor&lt;/td&gt;
          867       &lt;td&gt;No&lt;/td&gt;
          868       &lt;td&gt;Synaptics &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;00bd&lt;/code&gt; via USB, &lt;a href=&quot;https://www.reddit.com/r/thinkpad/comments/e90cgp/p43s_working_fingerprint_reader_on_linux/&quot;&gt;might be supported by libfprint&lt;/a&gt; with some extra firmware. Can be disabled in the BIOS.&lt;/td&gt;
          869     &lt;/tr&gt;
          870     &lt;tr&gt;
          871       &lt;td&gt;Keyboard backlight&lt;/td&gt;
          872       &lt;td&gt;Yes&lt;/td&gt;
          873       &lt;td&gt;Supported natively by the EC.  Can be toggled with Fn+Space and with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;wsconsctl keyboard.backlight&lt;/code&gt; values of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;50&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;100&lt;/code&gt;.&lt;/td&gt;
          874     &lt;/tr&gt;
          875     &lt;tr&gt;
          876       &lt;td&gt;Hibernation&lt;/td&gt;
          877       &lt;td&gt;Yes&lt;/td&gt;
          878       &lt;td&gt;Can be triggered by &lt;a href=&quot;http://man.openbsd.org/ZZZ.8&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ZZZ&lt;/code&gt;&lt;/a&gt;.&lt;/td&gt;
          879     &lt;/tr&gt;
          880     &lt;tr&gt;
          881       &lt;td&gt;SSD&lt;/td&gt;
          882       &lt;td&gt;Yes&lt;/td&gt;
          883       &lt;td&gt;The Western Digital PC SN530 NVMe drive is supported by &lt;a href=&quot;http://man.openbsd.org/nvme.4&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nvme&lt;/code&gt;&lt;/a&gt;.&lt;/td&gt;
          884     &lt;/tr&gt;
          885     &lt;tr&gt;
          886       &lt;td&gt;Suspend / resume&lt;/td&gt;
          887       &lt;td&gt;No&lt;/td&gt;
          888       &lt;td&gt;The firmware does not support ACPI S3 suspend.&lt;/td&gt;
          889     &lt;/tr&gt;
          890     &lt;tr&gt;
          891       &lt;td&gt;Thunderbolt 3&lt;/td&gt;
          892       &lt;td&gt;Kinda&lt;/td&gt;
          893       &lt;td&gt;Any devices attached at boot time will work in OpenBSD, but hotplugging is not supported since we do not have an NHI driver.&lt;/td&gt;
          894     &lt;/tr&gt;
          895     &lt;tr&gt;
          896       &lt;td&gt;Touchpad&lt;/td&gt;
          897       &lt;td&gt;Yes&lt;/td&gt;
          898       &lt;td&gt;Elan I&lt;sup&gt;2&lt;/sup&gt;C, supported by &lt;a href=&quot;http://man.openbsd.org/imt.4&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;imt&lt;/code&gt;&lt;/a&gt;.&lt;/td&gt;
          899     &lt;/tr&gt;
          900     &lt;tr&gt;
          901       &lt;td&gt;TrackPoint&lt;/td&gt;
          902       &lt;td&gt;Yes&lt;/td&gt;
          903       &lt;td&gt;Supported by &lt;a href=&quot;http://man.openbsd.org/pms.4&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pms&lt;/code&gt;&lt;/a&gt;.&lt;/td&gt;
          904     &lt;/tr&gt;
          905     &lt;tr&gt;
          906       &lt;td&gt;USB&lt;/td&gt;
          907       &lt;td&gt;Yes&lt;/td&gt;
          908       &lt;td&gt;The 2 USB-C ports work fine. I am using the &lt;a href=&quot;https://amzn.to/2NjUxEx&quot;&gt;Lenovo USB-C UltraDock&lt;/a&gt; which provides charging, USB ethernet (via &lt;a href=&quot;http://man.openbsd.org/ure.4&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ure&lt;/code&gt;&lt;/a&gt;) and a connection for the dongle for my wireless mouse, all over a single USB-C cable.&lt;/td&gt;
          909     &lt;/tr&gt;
          910     &lt;tr&gt;
          911       &lt;td&gt;Video&lt;/td&gt;
          912       &lt;td&gt;Yes&lt;/td&gt;
          913       &lt;td&gt;&lt;a href=&quot;http://man.openbsd.org/inteldrm.4&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;inteldrm&lt;/code&gt;&lt;/a&gt; supports accelerated video, DPMS, gamma control, and integrated backlight control. HDMI output through a USB-C adapter works.&lt;/td&gt;
          914     &lt;/tr&gt;
          915     &lt;tr&gt;
          916       &lt;td&gt;Webcam&lt;/td&gt;
          917       &lt;td&gt;Yes&lt;/td&gt;
          918       &lt;td&gt;Chicony USB, supported by the &lt;a href=&quot;http://man.openbsd.org/uvideo.4&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uvideo&lt;/code&gt;&lt;/a&gt; driver when the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kern.video.record&lt;/code&gt; sysctl is enabled.  Can be disabled in the BIOS.&lt;/td&gt;
          919     &lt;/tr&gt;
          920     &lt;tr&gt;
          921       &lt;td&gt;Wireless&lt;/td&gt;
          922       &lt;td&gt;Yes&lt;/td&gt;
          923       &lt;td&gt;The non-removable Intel AX201 802.11ax wireless chip is supported by &lt;a href=&quot;http://man.openbsd.org/iwx.4&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;iwx&lt;/code&gt;&lt;/a&gt;.&lt;/td&gt;
          924     &lt;/tr&gt;
          925   &lt;/tbody&gt;
          926 &lt;/table&gt;</content><author><name></name></author><category term="hardware" /><category term="laptops" /><category term="openbsd" /><category term="thinkpad" /><summary type="html">Lenovo has finally made a smaller version of its X1 Carbon, something I’ve been looking forward to for years.</summary></entry><entry><title type="html">Plaintext HTTP in a Modern World</title><link href="https://jcs.org/2021/01/06/plaintext" rel="alternate" type="text/html" title="Plaintext HTTP in a Modern World" /><published>2021-01-06T00:00:00-06:00</published><updated>2021-01-06T00:00:00-06:00</updated><id>https://jcs.org/2021/01/06/plaintext</id><content type="html" xml:base="https://jcs.org/2021/01/06/plaintext">&lt;p&gt;On the modern web, everything must be encrypted.
          927 Unencrypted websites are treated as relics of the past with browsers declaring
          928 them toxic waste not to be touched (or
          929 &lt;a href=&quot;//blog.mozilla.org/security/2020/11/17/firefox-83-introduces-https-only-mode/&quot;&gt;even looked at&lt;/a&gt;)
          930 and search engines de-prioritizing their content.&lt;/p&gt;
          931 
          932 &lt;p&gt;While this push for security is good for protecting modern communication, there
          933 is a whole web full of information and services that don’t &lt;em&gt;need&lt;/em&gt; to be secured
          934 and those trying to access them from older vintage computers or even through
          935 modern embedded devices are increasingly being left behind.&lt;/p&gt;
          936 
          937 
          938 
          939 &lt;p class=&quot;alert&quot;&gt;Note: This article is mostly directed at those serving personal websites, like
          940 this one, with no expectation of privacy or security by most readers of the
          941 content.
          942 If you are running a commercial website, collecting personal information from
          943 users, or transmitting sensitive data that users would expect to be done
          944 privately, disregard everything here and don’t bother offering your website over
          945 plaintext.&lt;/p&gt;
          946 
          947 &lt;h2 id=&quot;http-upgrading&quot;&gt;HTTP Upgrading&lt;/h2&gt;
          948 
          949 &lt;p&gt;Though it’s less common these days, users may still type in your website URL
          950 manually as opposed to clicking on a link that already includes the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;https&lt;/code&gt;
          951 scheme.
          952 (Imagine a user hearing your website mentioned on a podcast and they have to
          953 type it into their browser.)&lt;/p&gt;
          954 
          955 &lt;p&gt;For a URL entered with an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;http&lt;/code&gt; scheme or, more commonly, no scheme specified,
          956 unless your domain is listed in the
          957 &lt;a href=&quot;//www.chromium.org/hsts&quot;&gt;&lt;abbr title=&quot;Strict Transport Security&quot;&gt;STS&lt;/abbr&gt; preload list&lt;/a&gt;
          958 of the user’s browser or they are using a plugin like
          959 &lt;a href=&quot;//www.eff.org/https-everywhere&quot;&gt;HTTPS Everywhere&lt;/a&gt;, the browser will
          960 default to loading your website over plaintext HTTP.
          961 For this reason, even if your website is only served over HTTPS, it’s still
          962 necessary to configure your server to respond to plaintext HTTP requests with a
          963 301 or 302 redirect to the HTTPS version of the URL.&lt;/p&gt;
          964 
          965 &lt;p&gt;If your server is properly configured to send a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Strict-Transport-Security&lt;/code&gt;
          966 header, once the user’s browser loads your website’s HTTPS version, the browser
          967 will cache that information for days or months and future attempts to load your
          968 site will default to the HTTPS scheme instead of HTTP even if the user manually
          969 types in an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;http://&lt;/code&gt; URL.&lt;/p&gt;
          970 
          971 &lt;h2 id=&quot;avoid-forced-upgrading-by-default&quot;&gt;Avoid Forced Upgrading by Default&lt;/h2&gt;
          972 
          973 &lt;p&gt;This forced redirection is a major cause of websites becoming inaccessible on
          974 vintage computers.
          975 Your server responds to the HTTP request with a 301 or 302 status and no
          976 content, and either a) the browser follows the redirection and tries to
          977 negotiate an SSL connection, but your server doesn’t offer legacy SSL versions
          978 or old ciphers so the negotiation fails, or b) the browser just doesn’t support
          979 SSL/TLS at all and fails to follow the redirection.&lt;/p&gt;
          980 
          981 &lt;p&gt;A real-life example of this is that I recently purchased a Powerbook G4 and
          982 updated it to MacOS X 10.5.8 from 2009.
          983 It has a 1.5Ghz processor and 1.25Gb of RAM, and can connect to my modern WiFi
          984 network and use most of my USB peripherals.
          985 It includes a Mail client that can talk to my IMAP and SMTP servers, and a
          986 Safari web browser which can render fairly modern CSS layouts.
          987 However, it’s unable to view any content at all on Wikipedia simply because it
          988 can’t negotiate TLS 1.2 with the ciphers Wikipedia requires.
          989 Why is a decade-old computer too old to view encyclopedia articles?
          990 I am
          991 &lt;a href=&quot;https://meyerweb.com/eric/thoughts/2018/08/07/securing-sites-made-them-less-accessible/&quot;&gt;not the first&lt;/a&gt;
          992 to complain about this.&lt;/p&gt;
          993 
          994 &lt;p&gt;A solution to this problem is for websites to continue offering their full
          995 content over plaintext HTTP in addition to HTTPS.
          996 If you’re using Nginx, instead of creating two &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;server&lt;/code&gt; blocks with the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;listen
          997 *:80&lt;/code&gt; version redirecting to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;listen *:443 ssl&lt;/code&gt; version, use a single
          998 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;server&lt;/code&gt; block with multiple &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;listen&lt;/code&gt; lines, like so:&lt;/p&gt;
          999 
         1000 &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;server {
         1001     server_name jcs.org;
         1002     listen *:80;
         1003     listen *:443 ssl http2;
         1004 
         1005     ssl_certificate ...;
         1006     ssl_certificate_key ...;
         1007     ...
         1008     ssl_protocols TLSv1.2;
         1009 }
         1010 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
         1011 
         1012 &lt;p&gt;While it may seem counter to the point of this article, I recommend &lt;strong&gt;not&lt;/strong&gt;
         1013 serving legacy SSL/TLS ciphers like SSLv3 to try to help older browsers.
         1014 These old protocols and ciphers are insecure and broken, and I feel it’s better
         1015 to make it clear to the user they’re connecting to a website in cleartext than
         1016 to offer a false sense of security by having the browser indicate a “secure
         1017 connection” when it’s being done over an old, broken protocol.
         1018 Also, while it may not be practical anymore, modern browsers might be
         1019 &lt;a href=&quot;//en.wikipedia.org/wiki/Downgrade_attack&quot;&gt;tricked into negotiating&lt;/a&gt;
         1020 an old, broken cipher if your server still offers it.&lt;/p&gt;
         1021 
         1022 &lt;p&gt;Even if you do offer legacy protocols and ciphers to older browsers, your TLS
         1023 certificate might be signed by a certificate authority whose root certificate is
         1024 not trusted by older browsers.&lt;/p&gt;
         1025 
         1026 &lt;h2 id=&quot;continue-upgrading-modern-browsers&quot;&gt;Continue Upgrading Modern Browsers&lt;/h2&gt;
         1027 
         1028 &lt;p&gt;Now that your entire website is being offered to legacy browsers over HTTP,
         1029 modern browsers can still be directed to connect over HTTPS for added privacy by
         1030 responding to the
         1031 &lt;a href=&quot;//developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Upgrade-Insecure-Requests&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Upgrade-Insecure-Requests&lt;/code&gt;&lt;/a&gt;
         1032 header.
         1033 This header is only sent by modern browsers that support
         1034 &lt;a href=&quot;//developer.mozilla.org/en-US/docs/Web/HTTP/CSP&quot;&gt;CSP&lt;/a&gt;
         1035 when making an HTTP request, so it’s a reasonable indicator that the client is
         1036 sufficiently modern and robust that it will be able to negotiate a TLS 1.2
         1037 connection if redirected to your site’s HTTPS version.&lt;/p&gt;
         1038 
         1039 &lt;p&gt;For Nginx, this can be done inside a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;server&lt;/code&gt; block by defining a variable
         1040 per-request that includes whether it was made over plaintext HTTP and whether it
         1041 included an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Upgrade-Insecure-Requests: 1&lt;/code&gt; header:&lt;/p&gt;
         1042 
         1043 &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;server {
         1044     ...
         1045     set $need_http_upgrade &quot;$https$http_upgrade_insecure_requests&quot;;
         1046     location / {
         1047         if ($need_http_upgrade = &quot;1&quot;) {
         1048             add_header Vary Upgrade-Insecure-Requests;
         1049             return 301 https://$host$request_uri;
         1050         }
         1051 
         1052         ...
         1053     }
         1054 }
         1055 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
         1056 
         1057 &lt;p&gt;This &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;location&lt;/code&gt; block will respond for any request and, for those made over
         1058 plaintext HTTP where &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$https&lt;/code&gt; will be blank and which included an
         1059 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Upgrade-Insecure-Requests: 1&lt;/code&gt; header, they will be offered a 301 redirection to
         1060 the HTTPS version.
         1061 The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Vary&lt;/code&gt; header is sent so that any caching proxies in the middle won’t cache
         1062 the redirect.&lt;/p&gt;
         1063 
         1064 &lt;h2 id=&quot;content-concessions&quot;&gt;Content Concessions&lt;/h2&gt;
         1065 
         1066 &lt;p&gt;With legacy browsers now able to access your site, you may want to make some
         1067 changes to your HTML and CSS to allow your site to render with some degree of
         1068 readability.
         1069 I don’t recommend giving it the full IE6 treatment catering to the lowest common
         1070 denominator, but at least make the main text of your site readable.&lt;/p&gt;
         1071 
         1072 &lt;p&gt;Obviously avoid JavaScript unless it is used progressively, though many older
         1073 browsers raise error dialogs at the mere presence of modern JavaScript that
         1074 can’t be parsed even if it’s never executed.&lt;/p&gt;
         1075 
         1076 &lt;p&gt;Modern CSS and complex layouts can also be a problem even for browsers just a
         1077 few years old, so it’s probably best to use them sparingly.
         1078 For any &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;a&amp;gt;&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;img&amp;gt;&lt;/code&gt; tags that are local to your site, use relative links to
         1079 avoid specifying a particular scheme.&lt;/p&gt;
         1080 
         1081 &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&amp;lt;a href=&quot;/posts/blah&quot;&amp;gt;
         1082 &amp;lt;img src=&quot;/images/...&quot;&amp;gt;
         1083 &amp;lt;/a&amp;gt;
         1084 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
         1085 
         1086 &lt;p&gt;If you have to specify an absolute URL to another site that is also available
         1087 over both HTTP and HTTPS, you can specify it without a scheme or colon and the
         1088 browser will use the same &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;http:&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;https:&lt;/code&gt; that the document is being viewed
         1089 over:&lt;/p&gt;
         1090 
         1091 &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&amp;lt;a href=&quot;//other.example.com/&quot;&amp;gt;My other site&amp;lt;/a&amp;gt;
         1092 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
         1093 
         1094 &lt;h2 id=&quot;a-rant-about-gemini&quot;&gt;A Rant About Gemini&lt;/h2&gt;
         1095 
         1096 &lt;p&gt;Tangentially related,
         1097 &lt;a href=&quot;//gemini.circumlunar.space/&quot;&gt;Gemini&lt;/a&gt;
         1098 is a modern document transfer protocol that aims to fit between the ancient
         1099 &lt;a href=&quot;//en.wikipedia.org/wiki/Gopher_(protocol)&quot;&gt;Gopher&lt;/a&gt;
         1100 protocol and the too-modern HTTP web.
         1101 Its document markup language is based on
         1102 &lt;a href=&quot;//en.wikipedia.org/wiki/Markdown&quot;&gt;Markdown&lt;/a&gt;
         1103 so it’s very lightweight and simple to parse without complex HTML/CSS parsers.&lt;/p&gt;
         1104 
         1105 &lt;p&gt;It sounds like the perfect thing to bring modern content to vintage computers,
         1106 except that its
         1107 &lt;a href=&quot;//gemini.circumlunar.space/docs/specification.html&quot;&gt;protocol&lt;/a&gt;
         1108 requires all content to be transferred over TLS 1.2 or higher which makes it
         1109 nearly impossible to access from a vintage computer or even a modern embedded
         1110 system with limited CPU power.&lt;/p&gt;
         1111 
         1112 &lt;p&gt;This requirement seems poorly thought out, especially considering the Gemini
         1113 protocol doesn’t even support forms (other than a single text box on a search
         1114 form) so there’s no chance of users submitting private data, and, short of using
         1115 clunky TLS client certificates, there’s no mechanism for client-server sessions
         1116 like cookies so clients can’t be authenticated, meaning everything served pretty
         1117 much has to be public anyway.&lt;/p&gt;
         1118 
         1119 &lt;p&gt;Its protocol author argues that TLS is just a simple dependency no different
         1120 than a TCP server module, so it should be trivial to implement in any client or
         1121 server.
         1122 But if your computer’s CPU is so slow that a modern TLS negotiation would take
         1123 so long as to be unusable, or its
         1124 &lt;a href=&quot;http://tenfourfox.blogspot.com/2018/02/the-tls-apocalypse-reaches-power-macs.html&quot;&gt;platform doesn’t have a TLS 1.2 library&lt;/a&gt;
         1125 available, that makes it difficult to write a client without depending on an
         1126 &lt;a href=&quot;//github.com/jcs/sockhole&quot;&gt;external system&lt;/a&gt;
         1127 [&lt;a href=&quot;https://oldvcr.blogspot.com/2020/11/fun-with-crypto-ancienne-tls-for.html&quot;&gt;2&lt;/a&gt;].&lt;/p&gt;
         1128 
         1129 &lt;p&gt;In my opinion, the protocol should &lt;em&gt;recommend&lt;/em&gt; that servers offer both plaintext
         1130 and TLS encrypted versions and &lt;em&gt;recommend&lt;/em&gt; that clients prefer TLS, but &lt;em&gt;may&lt;/em&gt;
         1131 use plaintext if needed.
         1132 Clients for modern operating systems can continue enforcing a TLS requirement so
         1133 their users aren’t feeling any less secure.&lt;/p&gt;
         1134 
         1135 &lt;p&gt;Perhaps just sending actual Markdown text over plaintext HTTP to clients that
         1136 ask for it can be the new, old web.&lt;/p&gt;
         1137 
         1138 &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Accept: text/markdown,text/plain;q=0.9,*/*;q=0.1
         1139 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
         1140 
         1141 &lt;hr /&gt;
         1142 
         1143 &lt;p&gt;&lt;em&gt;Please don’t contact me to “well ackchyually” me and explain
         1144 &lt;a href=&quot;/2011/08/17/a_man-in-the-middle_attack_in_the_wild&quot;&gt;MITM attacks&lt;/a&gt;
         1145 and how your terrible ISP inserts ads into your unencrypted web pages and how
         1146 you were able to make a Gemini client out of a whistle and some shoelaces.
         1147 If you don’t want to make your website content available to stupid old
         1148 computers, then don’t.&lt;/em&gt;&lt;/p&gt;</content><author><name></name></author><category term="networking" /><category term="retrocomputing" /><summary type="html">On the modern web, everything must be encrypted. Unencrypted websites are treated as relics of the past with browsers declaring them toxic waste not to be touched (or even looked at) and search engines de-prioritizing their content.</summary></entry><entry><title type="html">Bluetooth Audio on OpenBSD with the Creative BT-W3</title><link href="https://jcs.org/2020/11/18/openbsd_btaudio" rel="alternate" type="text/html" title="Bluetooth Audio on OpenBSD with the Creative BT-W3" /><published>2020-11-18T00:00:00-06:00</published><updated>2021-03-22T22:59:36-05:00</updated><id>https://jcs.org/2020/11/18/openbsd_btaudio</id><content type="html" xml:base="https://jcs.org/2020/11/18/openbsd_btaudio">&lt;p&gt;Fifteen years ago, NetBSD’s Bluetooth audio stack was
         1149 &lt;a href=&quot;https://github.com/openbsd/src/commit/9dd45fb4d11e8194bf48b594393800ae9c06d75d&quot;&gt;imported&lt;/a&gt;
         1150 into OpenBSD.
         1151 From what I remember using it back then, it worked sufficiently well but its
         1152 configuration was cumbersome.
         1153 It supported Bluetooth HID keyboards and mice, audio, and serial devices.
         1154 Six years ago, however, it was
         1155 &lt;a href=&quot;https://github.com/openbsd/src/commit/b8042ed98e3e7a691133b4fd8e91f61ba15a83ba&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tedu'd&lt;/code&gt;&lt;/a&gt;
         1156 due to conflicts with how it integrated into our kernel.&lt;/p&gt;
         1157 
         1158 &lt;p&gt;While we still have no Bluetooth support today, it is possible to play audio on
         1159 Bluetooth headphones using a small hardware dongle.&lt;/p&gt;
         1160 
         1161 &lt;p&gt;&lt;img src=&quot;/images/2020-11-18-bt-w3-665x215.jpg&quot; srcset=&quot;/images/2020-11-18-bt-w3-665x215.jpg 1x, /images/2020-11-18-bt-w3-1330x430@2x.jpg 2x&quot; width=&quot;665&quot; height=&quot;215&quot; alt=&quot;creative bt-w3 plugged into laptop on desk&quot; class=&quot;header&quot; /&gt;&lt;/p&gt;
         1162 
         1163 
         1164 
         1165 &lt;h2 id=&quot;creative-bt-w2&quot;&gt;Creative BT-W2&lt;/h2&gt;
         1166 
         1167 &lt;p&gt;Last year I
         1168 &lt;a href=&quot;https://web.archive.org/web/20200625180156/https://twitter.com/jcs/status/1111806329717432325&quot;&gt;came across&lt;/a&gt;
         1169 the
         1170 &lt;a href=&quot;https://amzn.to/2HMScQt&quot;&gt;Creative BT-W2&lt;/a&gt;
         1171 USB device, which presents a standard
         1172 &lt;a href=&quot;https://man.openbsd.org/uaudio&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uaudio(4)&lt;/code&gt;&lt;/a&gt;
         1173 device on OpenBSD and handles all of the Bluetooth pairing and audio
         1174 communication itself with just one shortcoming: it did not expose any volume
         1175 control mechanism.
         1176 OpenBSD’s sound server,
         1177 &lt;a href=&quot;https://sndio.org/&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sndiod&lt;/code&gt;&lt;/a&gt;,
         1178 did have software volume control so it was possible to limit the volume through
         1179 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;aucatctl&lt;/code&gt; (now
         1180 &lt;a href=&quot;https://man.openbsd.org/sndioctl&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sndioctl&lt;/code&gt;&lt;/a&gt;).&lt;/p&gt;
         1181 
         1182 &lt;p&gt;I’ve been using the BT-W2 frequently since then to send audio from my OpenBSD
         1183 laptop to my Apple AirPods Pro, but unfortunately Apple released a firmware at
         1184 some point that limited the volume output when paired with such devices,
         1185 including
         1186 &lt;a href=&quot;https://www.cnet.com/how-to/how-to-fix-low-volume-issues-when-using-airpods-on-android/&quot;&gt;Android phones&lt;/a&gt;.
         1187 Presumably this was a safety measure because unless the sending side was doing
         1188 software volume control (which the AirPods wouldn’t know about), the AirPods
         1189 would play at maximum volume.&lt;/p&gt;
         1190 
         1191 &lt;p&gt;Unfortunately, even at the loudest volume from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sndiod&lt;/code&gt;, the volume to the
         1192 AirPods was still quite low, sometimes even too low to understand YouTube videos
         1193 with poor audio like conference talks.
         1194 Otherwise though, the BT-W2 worked well and I didn’t notice any latency or
         1195 video sync issues on OpenBSD.&lt;/p&gt;
         1196 
         1197 &lt;h2 id=&quot;creative-bt-w3&quot;&gt;Creative BT-W3&lt;/h2&gt;
         1198 
         1199 &lt;p&gt;The other day I became aware of the updated
         1200 &lt;a href=&quot;https://amzn.to/2UBC0pE&quot;&gt;Creative BT-W3&lt;/a&gt;,
         1201 which now has a USB-C interface instead of USB-A and finally exposes hardware
         1202 mixer control (note the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;2 ctls&lt;/code&gt;):&lt;/p&gt;
         1203 
         1204 &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;uaudio0 at uhub0 port 3 configuration 1 interface 1 &quot;Creative Technology Ltd Creative BT-W3&quot; rev 2.00/1.00 addr 2
         1205 uaudio0: class v1, full-speed, sync, channels: 2 play, 1 rec, 2 ctls
         1206 audio1 at uaudio0
         1207 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
         1208 
         1209 &lt;p&gt;Since Tweeting about the BT-W2 last year, OpenBSD’s audio system has changed
         1210 quite a bit and now &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sndiod&lt;/code&gt; controls output volume itself with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sndioctl&lt;/code&gt; being
         1211 the preferred utility, rather than directly changing hardware mixer settings
         1212 with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mixerctl&lt;/code&gt; as in years past.
         1213 The new hardware volume control (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;outputs.dac&lt;/code&gt;) can still be seen or modified
         1214 directly with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mixerctl&lt;/code&gt; and passing it the control device for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;audio1&lt;/code&gt; (as
         1215 the default &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/dev/audioctl0&lt;/code&gt; is for the built-in audio device of my laptop):&lt;/p&gt;
         1216 
         1217 &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# mixerctl -f /dev/audioctl1
         1218 outputs.dac=161
         1219 outputs.dac_mute=off
         1220 record.enable=sysctl
         1221 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
         1222 
         1223 &lt;p&gt;Whatever mechanism the BT-W3 uses to handle this hardware volume control
         1224 (whether just doing software volume limiting itself, or passing it through to
         1225 the AirPods through some fancy audio protocol), the benefit is that now the
         1226 AirPods can be used at full volume from OpenBSD.&lt;/p&gt;
         1227 
         1228 &lt;h2 id=&quot;automatically-switching-to-bluetooth&quot;&gt;Automatically Switching to Bluetooth&lt;/h2&gt;
         1229 
         1230 &lt;p&gt;My laptop’s
         1231 &lt;a href=&quot;https://jcs.org/2018/11/12/vfio&quot;&gt;Dolby Atmos speaker setup&lt;/a&gt;
         1232 is pretty good, so normally I just listen to music or play YouTube videos
         1233 through the speakers.
         1234 When my son is napping and I need to use my AirPods, I want to just plug in the
         1235 BT-W3 dongle and have it automatically start sending audio to my AirPods, and
         1236 have the volume controls on my keyboard control the AirPods.&lt;/p&gt;
         1237 
         1238 &lt;p&gt;To accomplish this, set an alternate device name with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sndiod&lt;/code&gt;:&lt;/p&gt;
         1239 
         1240 &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# rcctl set sndiod flags -f rsnd/0 -F rsnd/1
         1241 # rcctl restart sndiod
         1242 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
         1243 
         1244 &lt;p&gt;In this mode, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sndiod&lt;/code&gt; will play through &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rsnd/1&lt;/code&gt; if it exists, which maps to
         1245 the second audio device (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;audio1&lt;/code&gt;).
         1246 If the device is not present, such as when the BT-W3 is not plugged in, it will
         1247 play through &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rsnd/0&lt;/code&gt; which maps to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;audio0&lt;/code&gt;, the laptop’s built-in speakers.&lt;/p&gt;
         1248 
         1249 &lt;p&gt;This works fine if the device is present when &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sndiod&lt;/code&gt; starts, but otherwise it
         1250 will need a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SIGHUP&lt;/code&gt; to re-scan the audio devices once the BT-W3 is plugged in,
         1251 and start sending audio through it.
         1252 This can be done automatically with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hotplugd&lt;/code&gt;:&lt;/p&gt;
         1253 
         1254 &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# cat &amp;gt; /etc/hotplug/attach
         1255 case $2 in
         1256 uaudio*)
         1257         pkill -HUP sndiod
         1258         ;;
         1259 esac
         1260 ^D
         1261 # chmod +x /etc/hotplug/attach
         1262 # rcctl enable hotplugd
         1263 # rcctl start hotplugd
         1264 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
         1265 
         1266 &lt;p&gt;Now when a new &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uaudio&lt;/code&gt; device is plugged in and detected by the kernel,
         1267 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hotplugd&lt;/code&gt; will send a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SIGHUP&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sndiod&lt;/code&gt; which will see that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rsnd/1&lt;/code&gt; is
         1268 available and start sending audio to it.
         1269 When the BT-W3 is unplugged, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sndiod&lt;/code&gt; will automatically detect that the device
         1270 is no longer usable and send audio to its fallback, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rsnd/0&lt;/code&gt;.
         1271 Hardware device switching will be seamless and any applications playing audio
         1272 won’t have to stop or be restarted.&lt;/p&gt;
         1273 
         1274 &lt;p&gt;My
         1275 &lt;a href=&quot;https://github.com/jcs/sdorfehs&quot;&gt;window manager&lt;/a&gt;
         1276 is configured to respond to the hardware volume keys on my laptop (F4 for mute,
         1277 F5 for volume down, and F6 for volume up) by executing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sndioctl&lt;/code&gt;, so the
         1278 commands will work the same regardless of which device &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sndiod&lt;/code&gt; is talking to.&lt;/p&gt;
         1279 
         1280 &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;definekey top F4 exec sndioctl -q output.mute=!; pkill -USR1 i3status; true
         1281 definekey top F5 exec sndioctl -q output.mute=0; sndioctl -q output.level=-0.05; pkill -USR1 i3status; true
         1282 definekey top F6 exec sndioctl -q output.mute=0; sndioctl -q output.level=+0.05; pkill -USR1 i3status; true
         1283 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
         1284 
         1285 &lt;h2 id=&quot;responding-to-headphone-buttons&quot;&gt;Responding to Headphone Buttons&lt;/h2&gt;
         1286 
         1287 &lt;p&gt;If your Bluetooth headphones have buttons on them, these can pass through the
         1288 BT-W3 as USB HID reports.
         1289 My AirPods Pro have one hardware button (a squeeze on the stem) which can be
         1290 single, double, or triple pressed to perform a play/pause, next track, and
         1291 previous track.&lt;/p&gt;
         1292 
         1293 &lt;p&gt;The possible actions that the BT-W3 supports can be seen with
         1294 &lt;a href=&quot;//man.openbsd.org/usbhidctl.1&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;usbhidctl&lt;/code&gt;&lt;/a&gt;
         1295 on the first HID report of the device, which must be located in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dmesg&lt;/code&gt;:&lt;/p&gt;
         1296 
         1297 &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;uaudio1 at uhub0 port 1 configuration 1 interface 1 &quot;Creative Technology Ltd Creative BT-W3&quot; rev 2.00/1.00 addr 10
         1298 uaudio1: class v1, full-speed, sync, channels: 2 play, 1 rec, 2 ctls
         1299 audio2 at uaudio1
         1300 uhidev4 at uhub0 port 1 configuration 1 interface 3 &quot;Creative Technology Ltd Creative BT-W3&quot; rev 2.00/1.00 addr 10
         1301 uhidev4: iclass 3/0, 3 report ids
         1302 uhid11 at uhidev4 reportid 1: input=2, output=0, feature=0
         1303 [...]
         1304 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
         1305 
         1306 &lt;p&gt;In my case, the first HID report on the BT-W3 is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uhid11&lt;/code&gt;, so running
         1307 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;usbhidctl&lt;/code&gt; on &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/dev/uhid11&lt;/code&gt; can retrieve the full report descriptor:&lt;/p&gt;
         1308 
         1309 &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# usbhidctl -f /dev/uhid11 -r
         1310 Report descriptor:
         1311 Collection page=Consumer usage=Consumer_Control
         1312 Input   size=1 count=1 page=Consumer usage=Play/Pause, logical range 0..1
         1313 Input   size=1 count=1 page=Consumer usage=Scan_Next_Track, logical range 0..1
         1314 Input   size=1 count=1 page=Consumer usage=Scan_Previous_Track, logical range 0..1
         1315 Input   size=1 count=1 page=Consumer usage=Stop, logical range 0..1
         1316 Input   size=1 count=1 page=Consumer usage=Play, logical range 0..1
         1317 Input   size=1 count=1 page=Consumer usage=Pause, logical range 0..1
         1318 Input   size=1 count=1 page=Consumer usage=Fast_Forward, logical range 0..1
         1319 Input   size=1 count=1 page=Consumer usage=Rewind, logical range 0..1
         1320 Input   size=1 count=1 page=Consumer usage=Volume_Increment, logical range 0..1
         1321 Input   size=1 count=1 page=Consumer usage=Volume_Decrement, logical range 0..1
         1322 Input   size=1 count=1 page=Consumer usage=Mute, logical range 0..1
         1323 End collection
         1324 Total   input size 2 bytes
         1325 Total  output size 0 bytes
         1326 Total feature size 0 bytes
         1327 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
         1328 
         1329 &lt;p&gt;By using the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-l&lt;/code&gt; option, input reports can be seen when the button on the
         1330 AirPod is pressed:&lt;/p&gt;
         1331 
         1332 &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# usbhidctl -f /dev/uhid11 -l
         1333 Consumer_Control.Play/Pause=1
         1334 Consumer_Control.Scan_Next_Track=0
         1335 Consumer_Control.Scan_Previous_Track=0
         1336 Consumer_Control.Stop=0
         1337 Consumer_Control.Play=0
         1338 Consumer_Control.Pause=0
         1339 Consumer_Control.Fast_Forward=0
         1340 Consumer_Control.Rewind=0
         1341 Consumer_Control.Volume_Increment=0
         1342 Consumer_Control.Volume_Decrement=0
         1343 Consumer_Control.Mute=0
         1344 
         1345 Consumer_Control.Play/Pause=0
         1346 [...]
         1347 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
         1348 
         1349 &lt;p&gt;One event is generated to report &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Consumer_Control.Play/Pause=1&lt;/code&gt;, then another
         1350 right after it to report &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Consumer_Control.Play/Pause=0&lt;/code&gt;.&lt;/p&gt;
         1351 
         1352 &lt;p&gt;To automate responding to these events,
         1353 &lt;a href=&quot;//man.openbsd.org/usbhidaction&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;usbhidaction&lt;/code&gt;&lt;/a&gt;
         1354 can be used.
         1355 By default, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/dev/uhid*&lt;/code&gt; devices are owned by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;root:wheel&lt;/code&gt; and are mode
         1356 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0600&lt;/code&gt;, so to make things easier, I’ll &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;chmod&lt;/code&gt; them &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0660&lt;/code&gt; so I can access them
         1357 without &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;doas&lt;/code&gt;.
         1358 This needed because the program has to run as my own user to access my X11
         1359 session and environment variables.&lt;/p&gt;
         1360 
         1361 &lt;p&gt;With a simple configuration file, I can make &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;usbhidaction&lt;/code&gt; run my
         1362 &lt;a href=&quot;https://github.com/jcs/dotfiles/blob/master/bin/music&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;music&lt;/code&gt;&lt;/a&gt;
         1363 script to play/pause, skip to the next track, or play the previous track.&lt;/p&gt;
         1364 
         1365 &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ cat .usbhidaction.conf
         1366 Consumer:Play/Pause             1
         1367         ~/bin/music playpause
         1368 Consumer:Scan_Next_Track        1
         1369         ~/bin/music next
         1370 Consumer:Scan_Previous_Track    1
         1371         ~/bin/music prev
         1372 
         1373 $ usbhidaction -dv -c .usbhidaction.conf -f /dev/uhid11
         1374 PARSE:1 Consumer:Play/Pause, 1, '~/bin/music playpause'
         1375 PARSE:2 Consumer:Scan_Next_Track, 1, '~/bin/music next'
         1376 PARSE:3 Consumer:Scan_Previous_Track, 1, '~/bin/music prev'
         1377 report size 2
         1378 executing '~/bin/music playpause'
         1379 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
         1380 
         1381 &lt;p&gt;Unfortunately &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;usbhidaction&lt;/code&gt; is not a very user-friendly program so it must be
         1382 started after the BT-W3 is plugged in and you must lookup which &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uhid&lt;/code&gt; device is
         1383 the correct one to operate on each time.&lt;/p&gt;
         1384 
         1385 &lt;p&gt;I have
         1386 &lt;a href=&quot;https://github.com/jcs/openbsd-src/commit/b2ad5f79a9e1848e0bcf5cc31fcf1846ec723eb3&quot;&gt;some&lt;/a&gt;
         1387 &lt;a href=&quot;https://github.com/jcs/openbsd-src/commit/bdd58222f11ff91a0576bd7506306b740307d38d&quot;&gt;hacks&lt;/a&gt;
         1388 to work around these issues but it would be nice to have something more generic
         1389 that listens for input reports from all &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uhid&lt;/code&gt; devices automatically and outputs
         1390 them on some device stream that any program can listen to.
         1391 But that is a project for another time.&lt;/p&gt;</content><author><name></name></author><category term="openbsd" /><summary type="html">Fifteen years ago, NetBSD’s Bluetooth audio stack was imported into OpenBSD. From what I remember using it back then, it worked sufficiently well but its configuration was cumbersome. It supported Bluetooth HID keyboards and mice, audio, and serial devices. Six years ago, however, it was tedu'd due to conflicts with how it integrated into our kernel.</summary></entry><entry><title type="html">Video: C Programming on System 6 - SOCKS5 Support</title><link href="https://jcs.org/2020/11/12/socks5" rel="alternate" type="text/html" title="Video: C Programming on System 6 - SOCKS5 Support" /><published>2020-11-12T00:00:00-06:00</published><updated>2020-11-12T00:00:00-06:00</updated><id>https://jcs.org/2020/11/12/socks5</id><content type="html" xml:base="https://jcs.org/2020/11/12/socks5">&lt;p&gt;Returning to the development of my IMAP client, I add SOCKS5 support to be able
         1392 to connect through a network proxy, particularly the one I made that is able to
         1393 convert TLS-encrypted data from my real mailserver into plaintext that the
         1394 Mac’s slow CPU can support.&lt;/p&gt;
         1395 
         1396 
         1397 &lt;video controls=&quot;1&quot; preload=&quot;none&quot; poster=&quot;/images/2020-11-12-thumbnail-1330x748@2x.jpg&quot;&gt;
         1398   &lt;source src=&quot;/videos/2020-11-12.mp4&quot; type=&quot;video/mp4&quot; /&gt;
         1399   &lt;track default=&quot;&quot; kind=&quot;captions&quot; label=&quot;English&quot; srclang=&quot;en&quot; src=&quot;/video_captions/2020-11-12.vtt&quot; /&gt;
         1400   &lt;p&gt;
         1401   Your browser doesn't seem to support HTML video.
         1402   You can download the video in
         1403   &lt;a href=&quot;//cdn.jcs.org/videos/2020-11-12.mp4&quot; download=&quot;&quot;&gt;H.264/AAC&lt;/a&gt;
         1404   format instead.
         1405   &lt;/p&gt;
         1406 &lt;/video&gt;
         1407 
         1408 
         1409 &lt;p&gt;Video notes:&lt;/p&gt;
         1410 &lt;ul&gt;
         1411   &lt;li&gt;&lt;a href=&quot;https://tools.ietf.org/html/rfc1928&quot;&gt;SOCKS5 - RFC1928&lt;/a&gt;&lt;/li&gt;
         1412   &lt;li&gt;&lt;a href=&quot;https://github.com/jcs/sockhole&quot;&gt;sockhole&lt;/a&gt;&lt;/li&gt;
         1413   &lt;li&gt;&lt;a href=&quot;https://amzn.to/2Io10OV&quot;&gt;Teensy 4.0&lt;/a&gt;&lt;/li&gt;
         1414   &lt;li&gt;&lt;a href=&quot;https://gemini.circumlunar.space/&quot;&gt;Gemini&lt;/a&gt;&lt;/li&gt;
         1415   &lt;li&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Gopher_(protocol)&quot;&gt;Gopher&lt;/a&gt;
         1416  and
         1417  &lt;a href=&quot;https://www.macintoshrepository.org/265-turbogopher&quot;&gt;TurboGopher 0.8&lt;/a&gt;&lt;/li&gt;
         1418 &lt;/ul&gt;
         1419 
         1420 &lt;p&gt;Please
         1421 &lt;a href=&quot;/contact&quot;&gt;contact me&lt;/a&gt;
         1422 with any feedback or questions for future videos, and
         1423 &lt;a href=&quot;https://jcs.org/rss&quot;&gt;subscribe to my RSS feed&lt;/a&gt;
         1424 for new videos and other posts.&lt;/p&gt;
         1425 
         1426 &lt;p&gt;Join me and others on
         1427 &lt;a href=&quot;//libera.chat/&quot;&gt;Libera Chat&lt;/a&gt;
         1428 in the
         1429 &lt;a href=&quot;irc://irc.libera.chat/cyberpals&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#cyberpals&lt;/code&gt;&lt;/a&gt;
         1430 channel if you are interested in following along with this series and have
         1431 questions or would like to help others.&lt;/p&gt;</content><author><name></name></author><category term="video" /><category term="mac" /><category term="retrocomputing" /><category term="system6c" /><summary type="html">Returning to the development of my IMAP client, I add SOCKS5 support to be able to connect through a network proxy, particularly the one I made that is able to convert TLS-encrypted data from my real mailserver into plaintext that the Mac’s slow CPU can support.</summary></entry><entry><title type="html">Video: C Programming on System 6 - Adding a GUI to diff(1)</title><link href="https://jcs.org/2020/11/04/diff_gui" rel="alternate" type="text/html" title="Video: C Programming on System 6 - Adding a GUI to diff(1)" /><published>2020-11-04T00:00:00-06:00</published><updated>2020-11-04T00:00:00-06:00</updated><id>https://jcs.org/2020/11/04/diff_gui</id><content type="html" xml:base="https://jcs.org/2020/11/04/diff_gui">&lt;p&gt;In the
         1432 &lt;a href=&quot;/2020/10/28/openbsd_diff&quot;&gt;previous episode&lt;/a&gt;
         1433 I quickly ported OpenBSD’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;diff(1)&lt;/code&gt; but there wasn’t any interface to select
         1434 files or scroll through the output.
         1435 I’ve since added a proper GUI with the ability to select files or folders, and
         1436 in this episode I walk through the GUI and filesystem code and then add a
         1437 proper Edit menu.
         1438 I also make a formal release of the code and binary available for download.&lt;/p&gt;
         1439 
         1440 
         1441 &lt;video controls=&quot;1&quot; preload=&quot;none&quot; poster=&quot;/images/2020-11-04-thumbnail-1330x748@2x.jpg&quot;&gt;
         1442   &lt;source src=&quot;/videos/2020-11-04.mp4&quot; type=&quot;video/mp4&quot; /&gt;
         1443   &lt;track default=&quot;&quot; kind=&quot;captions&quot; label=&quot;English&quot; srclang=&quot;en&quot; src=&quot;/video_captions/2020-11-04.vtt&quot; /&gt;
         1444   &lt;p&gt;
         1445   Your browser doesn't seem to support HTML video.
         1446   You can download the video in
         1447   &lt;a href=&quot;//cdn.jcs.org/videos/2020-11-04.mp4&quot; download=&quot;&quot;&gt;H.264/AAC&lt;/a&gt;
         1448   format instead.
         1449   &lt;/p&gt;
         1450 &lt;/video&gt;
         1451 
         1452 
         1453 &lt;p&gt;Video notes:&lt;/p&gt;
         1454 &lt;ul&gt;
         1455   &lt;li&gt;Download on the Kludge BBS via &lt;a href=&quot;telnet://klud.ge&quot;&gt;telnet&lt;/a&gt;,
         1456 &lt;a href=&quot;ssh://guest@klud.ge&quot;&gt;SSH&lt;/a&gt;, and &lt;a href=&quot;https://klud.ge/&quot;&gt;web&lt;/a&gt; at &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;klud.ge&lt;/code&gt;, or
         1457 modem at &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;+1-312-654-0090&lt;/code&gt;&lt;/li&gt;
         1458 &lt;/ul&gt;
         1459 
         1460 &lt;p&gt;Please
         1461 &lt;a href=&quot;/contact&quot;&gt;contact me&lt;/a&gt;
         1462 with any feedback or questions for future videos, and
         1463 &lt;a href=&quot;https://jcs.org/rss&quot;&gt;subscribe to my RSS feed&lt;/a&gt;
         1464 for new videos and other posts.&lt;/p&gt;
         1465 
         1466 &lt;p&gt;Join me and others on
         1467 &lt;a href=&quot;//libera.chat/&quot;&gt;Libera Chat&lt;/a&gt;
         1468 in the
         1469 &lt;a href=&quot;irc://irc.libera.chat/cyberpals&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#cyberpals&lt;/code&gt;&lt;/a&gt;
         1470 channel if you are interested in following along with this series and have
         1471 questions or would like to help others.&lt;/p&gt;</content><author><name></name></author><category term="video" /><category term="mac" /><category term="retrocomputing" /><category term="system6c" /><category term="openbsd" /><summary type="html">In the previous episode I quickly ported OpenBSD’s diff(1) but there wasn’t any interface to select files or scroll through the output. I’ve since added a proper GUI with the ability to select files or folders, and in this episode I walk through the GUI and filesystem code and then add a proper Edit menu. I also make a formal release of the code and binary available for download.</summary></entry><entry><title type="html">Video: C Programming on System 6 - Porting OpenBSD’s diff(1)</title><link href="https://jcs.org/2020/10/28/openbsd_diff" rel="alternate" type="text/html" title="Video: C Programming on System 6 - Porting OpenBSD’s diff(1)" /><published>2020-10-28T00:00:00-05:00</published><updated>2020-10-28T00:00:00-05:00</updated><id>https://jcs.org/2020/10/28/openbsd_diff</id><content type="html" xml:base="https://jcs.org/2020/10/28/openbsd_diff">&lt;p&gt;I’ve wanted a simple revision control system on my Mac since starting
         1472 development of my IMAP client.
         1473 Porting a large system like Git or even CVS would be overkill (and very slow),
         1474 but maybe something small like OpenBSD’s
         1475 &lt;a href=&quot;https://github.com/openbsd/src/tree/master/usr.bin/rcs&quot;&gt;RCS&lt;/a&gt;
         1476 implementation would suffice.
         1477 For now, just having a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;diff&lt;/code&gt; utility would be helpful so in this video I port
         1478 the guts of
         1479 &lt;a href=&quot;https://github.com/openbsd/src/tree/master/usr.bin/diff&quot;&gt;OpenBSD’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;diff(1)&lt;/code&gt;&lt;/a&gt;
         1480 and show it generating a unified diff between revisions of a C file.&lt;/p&gt;
         1481 
         1482 
         1483 &lt;video controls=&quot;1&quot; preload=&quot;none&quot; poster=&quot;/images/2020-10-28-thumbnail-1330x748@2x.jpg&quot;&gt;
         1484   &lt;source src=&quot;/videos/2020-10-28.mp4&quot; type=&quot;video/mp4&quot; /&gt;
         1485   &lt;track default=&quot;&quot; kind=&quot;captions&quot; label=&quot;English&quot; srclang=&quot;en&quot; src=&quot;/video_captions/2020-10-28.vtt&quot; /&gt;
         1486   &lt;p&gt;
         1487   Your browser doesn't seem to support HTML video.
         1488   You can download the video in
         1489   &lt;a href=&quot;//cdn.jcs.org/videos/2020-10-28.mp4&quot; download=&quot;&quot;&gt;H.264/AAC&lt;/a&gt;
         1490   format instead.
         1491   &lt;/p&gt;
         1492 &lt;/video&gt;
         1493 
         1494 
         1495 &lt;p&gt;Video notes:&lt;/p&gt;
         1496 &lt;ul&gt;
         1497   &lt;li&gt;&lt;a href=&quot;https://github.com/openbsd/src/tree/master/usr.bin/diff&quot;&gt;OpenBSD &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;diff(1)&lt;/code&gt; source code&lt;/a&gt;&lt;/li&gt;
         1498   &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;KAHL&lt;/code&gt; as the THINK C file creator type refers to Michael Kahl, the original
         1499 THINK C author (thanks to Theo Buehler for letting me know)&lt;/li&gt;
         1500   &lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=zAkmUi_PpJw&amp;amp;t=47&quot;&gt;Phil Collins - stdio&lt;/a&gt;&lt;/li&gt;
         1501   &lt;li&gt;My &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;strdup&lt;/code&gt; code in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;xstrdup&lt;/code&gt; should &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;malloc(len + 1)&lt;/code&gt;&lt;/li&gt;
         1502   &lt;li&gt;&lt;a href=&quot;https://www.tinkerboy.xyz/product/tinkerboy-ps-2-keyboard-to-mac-converter-adapter-for-macintosh-with-4p4c-keyboard-port/&quot;&gt;tinkerBOY PS/2 keyboard to Mac converter&lt;/a&gt;&lt;/li&gt;
         1503 &lt;/ul&gt;
         1504 
         1505 &lt;p&gt;Please
         1506 &lt;a href=&quot;/contact&quot;&gt;contact me&lt;/a&gt;
         1507 with any feedback or questions for future videos, and
         1508 &lt;a href=&quot;https://jcs.org/rss&quot;&gt;subscribe to my RSS feed&lt;/a&gt;
         1509 for new videos and other posts.&lt;/p&gt;
         1510 
         1511 &lt;p&gt;Join me and others on
         1512 &lt;a href=&quot;//libera.chat/&quot;&gt;Libera Chat&lt;/a&gt;
         1513 in the
         1514 &lt;a href=&quot;irc://irc.libera.chat/cyberpals&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#cyberpals&lt;/code&gt;&lt;/a&gt;
         1515 channel if you are interested in following along with this series and have
         1516 questions or would like to help others.&lt;/p&gt;</content><author><name></name></author><category term="video" /><category term="mac" /><category term="retrocomputing" /><category term="system6c" /><category term="openbsd" /><summary type="html">I’ve wanted a simple revision control system on my Mac since starting development of my IMAP client. Porting a large system like Git or even CVS would be overkill (and very slow), but maybe something small like OpenBSD’s RCS implementation would suffice. For now, just having a diff utility would be helpful so in this video I port the guts of OpenBSD’s diff(1) and show it generating a unified diff between revisions of a C file.</summary></entry><entry><title type="html">Video: C Programming on System 6 - Message Flags</title><link href="https://jcs.org/2020/10/27/message_flags" rel="alternate" type="text/html" title="Video: C Programming on System 6 - Message Flags" /><published>2020-10-27T00:00:00-05:00</published><updated>2020-10-27T00:00:00-05:00</updated><id>https://jcs.org/2020/10/27/message_flags</id><content type="html" xml:base="https://jcs.org/2020/10/27/message_flags">&lt;p&gt;In this episode, I fetch the flags of each message and for unseen messages,
         1517 make them appear in the list in bold.
         1518 That introduces an off-by-one which I run out of time to fix while recording.&lt;/p&gt;
         1519 
         1520 
         1521 &lt;video controls=&quot;1&quot; preload=&quot;none&quot; poster=&quot;/images/2020-10-27-thumbnail-1330x748@2x.jpg&quot;&gt;
         1522   &lt;source src=&quot;/videos/2020-10-27.mp4&quot; type=&quot;video/mp4&quot; /&gt;
         1523   &lt;track default=&quot;&quot; kind=&quot;captions&quot; label=&quot;English&quot; srclang=&quot;en&quot; src=&quot;/video_captions/2020-10-27.vtt&quot; /&gt;
         1524   &lt;p&gt;
         1525   Your browser doesn't seem to support HTML video.
         1526   You can download the video in
         1527   &lt;a href=&quot;//cdn.jcs.org/videos/2020-10-27.mp4&quot; download=&quot;&quot;&gt;H.264/AAC&lt;/a&gt;
         1528   format instead.
         1529   &lt;/p&gt;
         1530 &lt;/video&gt;
         1531 
         1532 
         1533 &lt;p&gt;Please
         1534 &lt;a href=&quot;/contact&quot;&gt;contact me&lt;/a&gt;
         1535 with any feedback or questions for future videos, and
         1536 &lt;a href=&quot;https://jcs.org/rss&quot;&gt;subscribe to my RSS feed&lt;/a&gt;
         1537 for new videos and other posts.&lt;/p&gt;
         1538 
         1539 &lt;p&gt;Join me and others on
         1540 &lt;a href=&quot;//libera.chat/&quot;&gt;Libera Chat&lt;/a&gt;
         1541 in the
         1542 &lt;a href=&quot;irc://irc.libera.chat/cyberpals&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#cyberpals&lt;/code&gt;&lt;/a&gt;
         1543 channel if you are interested in following along with this series and have
         1544 questions or would like to help others.&lt;/p&gt;</content><author><name></name></author><category term="video" /><category term="mac" /><category term="retrocomputing" /><category term="system6c" /><summary type="html">In this episode, I fetch the flags of each message and for unseen messages, make them appear in the list in bold. That introduces an off-by-one which I run out of time to fix while recording.</summary></entry><entry><title type="html">Video: C Programming on System 6 - Viewing Messages</title><link href="https://jcs.org/2020/10/21/viewing_messages" rel="alternate" type="text/html" title="Video: C Programming on System 6 - Viewing Messages" /><published>2020-10-21T00:00:00-05:00</published><updated>2020-10-21T00:00:00-05:00</updated><id>https://jcs.org/2020/10/21/viewing_messages</id><content type="html" xml:base="https://jcs.org/2020/10/21/viewing_messages">&lt;p&gt;Today, I implement plaintext message viewing and hook it up to the message list.
         1545 I also review a cleanup of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;int&lt;/code&gt; variables to make them either &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;short&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;long&lt;/code&gt;
         1546 throughout the project.&lt;/p&gt;
         1547 
         1548 
         1549 &lt;video controls=&quot;1&quot; preload=&quot;none&quot; poster=&quot;/images/2020-10-21-thumbnail-1330x748@2x.jpg&quot;&gt;
         1550   &lt;source src=&quot;/videos/2020-10-21.mp4&quot; type=&quot;video/mp4&quot; /&gt;
         1551   &lt;track default=&quot;&quot; kind=&quot;captions&quot; label=&quot;English&quot; srclang=&quot;en&quot; src=&quot;/video_captions/2020-10-21.vtt&quot; /&gt;
         1552   &lt;p&gt;
         1553   Your browser doesn't seem to support HTML video.
         1554   You can download the video in
         1555   &lt;a href=&quot;//cdn.jcs.org/videos/2020-10-21.mp4&quot; download=&quot;&quot;&gt;H.264/AAC&lt;/a&gt;
         1556   format instead.
         1557   &lt;/p&gt;
         1558 &lt;/video&gt;
         1559 
         1560 
         1561 &lt;p&gt;Video notes:&lt;/p&gt;
         1562 
         1563 &lt;ul&gt;
         1564   &lt;li&gt;&lt;a href=&quot;https://vintageapple.org/macprogramming/pdf/Macintosh_C_Programming_By_Example_1991.pdf&quot;&gt;Macintosh C Programming by Example (PDF)&lt;/a&gt;&lt;/li&gt;
         1565   &lt;li&gt;&lt;a href=&quot;https://tools.ietf.org/html/rfc3501#page-58&quot;&gt;RFC3501 - &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RFC822.TEXT&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
         1566   &lt;li&gt;&lt;a href=&quot;/system6c&quot;&gt;My “C Programming on System 6” Series page&lt;/a&gt;&lt;/li&gt;
         1567 &lt;/ul&gt;
         1568 
         1569 &lt;p&gt;Please
         1570 &lt;a href=&quot;/contact&quot;&gt;contact me&lt;/a&gt;
         1571 with any feedback or questions for future videos, and
         1572 &lt;a href=&quot;https://jcs.org/rss&quot;&gt;subscribe to my RSS feed&lt;/a&gt;
         1573 for new videos and other posts.&lt;/p&gt;
         1574 
         1575 &lt;p&gt;Join me and others on
         1576 &lt;a href=&quot;//libera.chat/&quot;&gt;Libera Chat&lt;/a&gt;
         1577 in the
         1578 &lt;a href=&quot;irc://irc.libera.chat/cyberpals&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#cyberpals&lt;/code&gt;&lt;/a&gt;
         1579 channel if you are interested in following along with this series and have
         1580