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"><p>After the disappointment of my
2 <a href="/2021/01/27/x1nano">X1 Nano</a>
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.</p>
7
8 <p><img src="/images/2021-07-19-hero-665x246.jpg" srcset="/images/2021-07-19-hero-665x246.jpg 1x, /images/2021-07-19-hero-1330x492@2x.jpg 2x" width="665" height="246" alt="desktop with screen and new desktop system" class="header" /></p>
9
10 <h2 class="no_toc" id="table-of-contents">Table of Contents</h2>
11
12 <ol id="markdown-toc">
13 <li><a href="#architecture" id="markdown-toc-architecture">Architecture</a></li>
14 <li><a href="#monitor" id="markdown-toc-monitor">Monitor</a></li>
15 <li><a href="#case" id="markdown-toc-case">Case</a></li>
16 <li><a href="#cpu-and-motherboard" id="markdown-toc-cpu-and-motherboard">CPU and Motherboard</a></li>
17 <li><a href="#ram-and-ssd" id="markdown-toc-ram-and-ssd">RAM and SSD</a></li>
18 <li><a href="#keyboard-and-mouse" id="markdown-toc-keyboard-and-mouse">Keyboard and Mouse</a></li>
19 <li><a href="#openbsd" id="markdown-toc-openbsd">OpenBSD</a></li>
20 <li><a href="#temperatures" id="markdown-toc-temperatures">Temperatures</a></li>
21 </ol>
22
23 <h2 id="architecture">Architecture</h2>
24
25 <p>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 <a href="https://twitter.com/bluerise/status/1352587849359568898">HoneyComb LX2</a>
29 was many weeks out.</p>
30
31 <p>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:</p>
34
35 <ul>
36 <li>Excellent OpenBSD support</li>
37 <li>Fanless with no coil whine</li>
38 <li>A high-resolution, small monitor (more on that later)</li>
39 </ul>
40
41 <p>Ever since reading
42 <a href="https://fabiensanglard.net/the_beautiful_machine/index.html">Fabien Sanglard’s writeup</a>
43 about building a system with a
44 <a href="https://streacom.com/products/db4-fanless-mini-itx-case/">Streacom DB4 case</a>,
45 I knew I wanted that case in particular since it looks beautiful and could
46 passively cool a 65W processor.</p>
47
48 <h2 id="monitor">Monitor</h2>
49
50 <p>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.</p>
54
55 <p>I’ve always chosen smaller (&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.</p>
61
62 <p>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 (<code class="language-plaintext highlighter-rouge">layout.css.devPixelsPerPx</code>).
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.</p>
68
69 <p>After some research, I chose the
70 <a href="https://www.lg.com/us/monitors/lg-22MD4KA-B-4k-uhd-led-monitor">LG UltraFine 21.5” IPS LED
71 monitor</a>
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.</p>
77
78 <p>Since the LG UltraFine had a VESA mount option, I purchased an
79 <a href="https://amzn.to/3ivzmgP">Ergotron LX monitor arm</a>
80 to be able to position the monitor however I wanted on my desk.</p>
81
82 <p><a href="/images/2021-07-19-monitor_arm-large.jpg"><img src="/images/2021-07-19-monitor_arm-665x385.jpg" srcset="/images/2021-07-19-monitor_arm-665x385.jpg 1x, /images/2021-07-19-monitor_arm-1330x770@2x.jpg 2x" width="665" height="385" alt="LG UltraFine monitor attached to Ergotron LX monitor arm" class="wide" /></a></p>
83
84 <p>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.</p>
89
90 <p>This all works by using the USB-C cable for data as usual but it sends the
91 screen data over
92 <a href="https://www.benq.com/en-us/knowledge-center/knowledge/usb-c-introduction-what-is-dp-alt-mode.html">DisplayPort</a>
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.</p>
101
102 <p>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 <a href="https://dancharblog.wordpress.com/2020/07/20/add-usb-c-with-dp-alt-mode-to-your-desktop-pc/">Sunix
105 upd2018</a>
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 <a href="https://amzn.to/3ipjCvD">short DisplayPort cable</a>
113 is used to connect between the PCI card and the motherboard/GPU DisplayPort
114 connector.</p>
115
116 <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>xhci0 at pci1 dev 0 function 0 "ASMedia ASM1042AE xHCI" rev 0x00: msi, xHCI 1.10
117 usb0 at xhci0: USB revision 3.0
118 uhub0 at usb0 configuration 1 interface 0 "ASMedia xHCI root hub" rev 3.00/1.00 addr 1
119 </code></pre></div></div>
120
121 <p>The monitor’s brightness controls and ambient light sensor are available through
122 USB HID devices, and its integrated speakers work through <code class="language-plaintext highlighter-rouge">uaudio</code> as expected:</p>
123
124 <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>uhub5 at uhub0 port 3 configuration 1 interface 0 "LG Electronics Inc. USB2.1 Hub" rev 2.10/52.26 addr 2
125 uhub6 at uhub5 port 4 configuration 1 interface 0 "LG USA product 0x9a48" rev 2.00/88.32 addr 3
126 uaudio0 at uhub6 port 1 configuration 1 interface 1 "LG Electronics Inc. USB Audio" 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 "LG Electronics Inc. USB Controls" 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 "LG Electronics Inc. USB Controls" 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 "LG Electronics Inc. USB Controls" rev 2.00/3.04 addr 5
137 uhidev2: iclass 3/0
138 uhid2 at uhidev2: input=6, output=0, feature=13
139 </code></pre></div></div>
140
141 <p>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.</p>
143
144 <h2 id="case">Case</h2>
145
146 <p>I already had my heart set on the
147 <a href="https://www.quietpcusa.com/Streacom-DB4-Fanless-Chassis">Streacom DB4 fanless
148 case</a>,
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.</p>
153
154 <p>I purchased a
155 <a href="https://www.quietpcusa.com/Streacom-ST-ZF240-ZeroFlex-240W-PSU">Streacom ST-ZF240 ZeroFlex 240W
156 PSU</a>
157 because it was also fanless.
158 I’ve used a
159 <a href="https://www.quietpcusa.com/Streacom-160W-nanoPSU-and-AC/DC-adapter-block">nanoPSU</a>
160 before but heard coil whine from it so I didn’t want to go that route again.</p>
161
162 <p>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”.</p>
165
166 <p>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.</p>
171
172 <p><a href="/images/2021-07-19-bottom-large.jpg"><img src="/images/2021-07-19-bottom-665x378.jpg" srcset="/images/2021-07-19-bottom-665x378.jpg 1x, /images/2021-07-19-bottom-1330x756@2x.jpg 2x" width="665" height="378" class="wide" /></a></p>
173
174 <h2 id="cpu-and-motherboard">CPU and Motherboard</h2>
175
176 <p>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.</p>
184
185 <p><a href="/images/2021-07-19-ryzen-large.jpg"><img src="/images/2021-07-19-ryzen-665x331.jpg" srcset="/images/2021-07-19-ryzen-665x331.jpg 1x, /images/2021-07-19-ryzen-1330x662@2x.jpg 2x" width="665" height="331" class="wide" /></a></p>
186
187 <p>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 <a href="https://amzn.to/36M6dbH">available on Amazon</a>
191 which was good enough for me.</p>
192
193 <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>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 </code></pre></div></div>
203
204 <p>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.</p>
212
213 <p>Eventually I settled on the
214 <a href="https://amzn.to/3kx6APl">ASUS ROG Strix X570-I</a>.
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.</p>
220
221 <p>While I don’t intend to use them, its onboard WiFi and sound work fine in
222 OpenBSD:</p>
223
224 <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>iwx0 at pci4 dev 0 function 0 "Intel Wi-Fi 6 AX200" rev 0x1a, msix
225 [...]
226 azalia1 at pci10 dev 0 function 6 "AMD 17h/1xh HD Audio" rev 0x00: apic 18 int 12
227 azalia1: codecs: Realtek ALC1220
228 audio0 at azalia1
229 </code></pre></div></div>
230
231 <p>As does its ethernet port:</p>
232
233 <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>em0 at pci5 dev 0 function 0 "Intel I211" rev 0x03: msi, address 7c:10:c9:[...]
234 </code></pre></div></div>
235
236 <h2 id="ram-and-ssd">RAM and SSD</h2>
237
238 <p>I purchased
239 <a href="https://amzn.to/3BeCqXf">Crucial 16Gb DDR4 3200Mhz RAM</a>
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?</p>
243
244 <p>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.</p>
247
248 <h2 id="keyboard-and-mouse">Keyboard and Mouse</h2>
249
250 <p>I’m not big into mechanical keyboards (aside from the one on my
251 <a href="https://jcs.org/2018/03/20/dolch64">Dolch PAC 64</a>)
252 but after seeing
253 <a href="https://www.youtube.com/watch?v=SPVboP_Fvgo">LGR’s video</a>
254 about the
255 <a href="https://www.pcgamingrace.com/products/glorious-gmmk-pro-75-barebone-black">Glorious GMMK
256 Pro</a>
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.</p>
263
264 <p>I opted for a black shell, aluminum switch plate, lubed (lol) Glorious Panda
265 switches, and a
266 <a href="https://pimpmykeyboard.com/dsa-dolch-keyset-two-shot/">“Dolch” DSA keycap set</a>
267 that I already had from years back.</p>
268
269 <p><a href="/images/2021-07-19-keyboard-large.jpg"><img src="/images/2021-07-19-keyboard-665x314.jpg" srcset="/images/2021-07-19-keyboard-665x314.jpg 1x, /images/2021-07-19-keyboard-1330x628@2x.jpg 2x" width="665" height="314" class="wide" /></a></p>
270
271 <p>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.</p>
274
275 <p>Configuration of the keys and lighting of the keyboard has to be done with a
276 <a href="https://www.pcgamingrace.com/pages/glorious-core?core=GMMK%20PRO">Windows-only piece of
277 software</a>,
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 <code class="language-plaintext highlighter-rouge">xmodmap</code>) and put Delete in the upper right
285 corner, although I rarely need it.</p>
286
287 <p>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 <a href="https://amzn.to/3xSq05i">ThinkPad Compact USB Keyboard</a>
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.</p>
297
298 <center>
299 <a href="/images/2021-07-19-thinkpad-large.jpg"><img src="/images/2021-07-19-thinkpad-327x154.jpg" srcset="/images/2021-07-19-thinkpad-327x154.jpg 1x, /images/2021-07-19-thinkpad-654x308@2x.jpg 2x" width="327" height="154" class="1/2" /></a>
300 <a href="/images/2021-07-19-mice-large.jpg"><img src="/images/2021-07-19-mice-327x144.jpg" srcset="/images/2021-07-19-mice-327x144.jpg 1x, /images/2021-07-19-mice-654x288@2x.jpg 2x" width="327" height="144" class="1/2" /></a>
301 </center>
302
303 <p>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 <a href="https://amzn.to/2Un65Nq">Lenovo N50 wireless mouse</a>
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 <a href="https://amzn.to/3isJmYf">Logitech M355</a>
311 because it’s nearly silent.
312 It uses a wireless USB dongle which I have plugged into the back of the monitor.</p>
313
314 <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>uhidev2 at uhub5 port 2 configuration 1 interface 0 "Logitech USB Receiver" 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 "Logitech USB Receiver" 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 "M355" serial e6-4f-59-05
322 </code></pre></div></div>
323
324 <p>Its battery status is available via the <code class="language-plaintext highlighter-rouge">uhidpp</code> driver:</p>
325
326 <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ sysctl hw.sensors.uhidpp0
327 hw.sensors.uhidpp0.raw0=4 (battery levels)
328 hw.sensors.uhidpp0.percent0=90.00% (battery level), OK
329 </code></pre></div></div>
330
331 <p>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.</p>
333
334 <h2 id="openbsd">OpenBSD</h2>
335
336 <p>Of course my system wouldn’t be usable to me if I couldn’t run OpenBSD on it.</p>
337
338 <p>When I first booted OpenBSD on the system, once the <code class="language-plaintext highlighter-rouge">amdgpu</code> KMS driver took
339 over from <code class="language-plaintext highlighter-rouge">efifb</code>, 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.</p>
346
347 <p>This would get the system to boot, but the LG UltraFine display would go blank
348 (though the backlight was still on) once <code class="language-plaintext highlighter-rouge">amdgpu</code> took over.
349 I SSH’d in and did an <code class="language-plaintext highlighter-rouge">xinit</code>, 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 <a href="https://github.com/jcs/openbsd-src/commit/e529589c95e80a9487927e40a02cc608baad3ab3">quirk</a>
355 to prefer the 4096x2304@48Hz rate in the monitor’s EDID.</p>
356
357 <p>Since the LG UltraFine exposes a USB HID device to control its brightness, I
358 <a href="https://github.com/jcs/openbsd-src/commit/c42e01c96df77fb113167b08509b76fd33d6521c">wrote a driver</a>
359 to attach to it and expose the brightness adjustment through <code class="language-plaintext highlighter-rouge">wsconsctl
360 display.brightness</code>.</p>
361
362 <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ dmesg | grep ulguf
363 ulguf0 at uhub6 port 4 configuration 1 interface 0 "LG Electronics Inc. USB Controls" 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 -&gt; 20.00%
369 </code></pre></div></div>
370
371 <p>I still need to add support for reading the ambient light sensor and exposing it
372 through <code class="language-plaintext highlighter-rouge">sysctl hw.sensors</code>, which I can then use with something like my
373 <a href="https://github.com/jcs/xdimmer">xdimmer</a>
374 to automatically dim the screen at night.</p>
375
376 <p>To route sound through the monitor’s speakers by default, I have made it use
377 <code class="language-plaintext highlighter-rouge">rsnd/1</code> by default, which maps to <code class="language-plaintext highlighter-rouge">audio1</code>, via <code class="language-plaintext highlighter-rouge">uaudio0</code>.</p>
378
379 <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ dmesg | grep uaudio
380 uaudio0 at uhub6 port 1 configuration 1 interface 1 "LG Electronics Inc. USB Audio" 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 </code></pre></div></div>
387
388 <p>Since some people have asked, the window manager shown in my photos above is my
389 <a href="https://github.com/jcs/sdorfehs">sdorfehs</a>
390 which is a fork of ratpoison.</p>
391
392 <p>Other than the quirks with my monitor, OpenBSD works well on this motherboard
393 and CPU.</p>
394
395 <h2 id="temperatures">Temperatures</h2>
396
397 <p>CPU temperature can be monitored in OpenBSD with the <code class="language-plaintext highlighter-rouge">ksmn</code> driver:</p>
398
399 <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ sysctl hw.sensors.ksmn0
400 hw.sensors.ksmn0.temp0=54.25 degC
401 </code></pre></div></div>
402
403 <p>Through a <code class="language-plaintext highlighter-rouge">make -j8 build</code> 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:</p>
407
408 <center>
409 <a href="/images/2021-07-19-flir-large.jpg"><img src="/images/2021-07-19-flir-493x369.jpg" srcset="/images/2021-07-19-flir-493x369.jpg 1x, /images/2021-07-19-flir-986x738@2x.jpg 2x" width="493" height="369" class="3/4" /></a>
410 </center></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"><p>I’ve created an adapter for the
411 <a href="https://jcs.org/2019/05/03/mailstation">Cidco MailStation</a>
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 <a href="https://github.com/jcs/msTERM">msTERM</a>
415 terminal emulator.</p>
416
417 <p><img src="/images/2021-04-23-hero-665x182.jpg" srcset="/images/2021-04-23-hero-665x182.jpg 1x, /images/2021-04-23-hero-1330x364@2x.jpg 2x" width="665" height="182" alt="WiFiStation" class="header" /></p>
418
419
420
421 <p class="alert"><strong>Note:</strong> For the latest information on this project, please see my dedicated
422 <a href="/wifistation">WiFiStation</a>
423 pages.</p>
424
425 <h2 id="background">Background</h2>
426
427 <p>In 2019, I
428 <a href="https://jcs.org/2019/05/03/mailstation#creating-msterm">created a terminal program</a>
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 <a href="//klud.ge/">my own BBS</a>,
433 the novelty soon wore off and I returned to using telnet and SSH.</p>
434
435 <p>Last year, someone asked me if the MailStation could be used as a simple word
436 processor similar to the
437 <a href="https://en.wikipedia.org/wiki/AlphaSmart">AlphaSmart Dana</a>.
438 I told them such software could be written but it would be difficult to use
439 since the only<sup id="fnref:0" role="doc-noteref"><a href="#fn:0" class="footnote">1</a></sup> way to exchange documents with the MailStation would be
440 through its modem or a
441 <a href="https://en.wikipedia.org/wiki/LapLink_cable">parallel LapLink cable</a>,
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.</p>
444
445 <p>While I had recently created a
446 <a href="/2020/03/31/mailstation_usb">USB adapter</a>
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 <a href="/2017/06/23/wifi232">WiFi modem serial adapters</a>,
452 while also providing a simple web interface where users could upload files and
453 have them transferred to the MailStation.</p>
454
455 <h2 id="data-transfer">Data Transfer</h2>
456
457 <p>Like those WiFi serial adapters, using an
458 <a href="https://en.wikipedia.org/wiki/ESP8266">ESP32/ESP8266</a> 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.</p>
464
465 <p>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.</p>
468
469 <p>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 <a href="https://github.com/jcs/mailstation-tools/blob/master/loader.asm">loader program</a>
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.</p>
477
478 <p>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 <a href="https://github.com/jcs/WiFiStation/blob/main/mailstation/wsloader.asm">loader</a>
485 for this protocol, which doesn’t rely on any firmware functionality, ended
486 up being 117 bytes vs. 97 for the
487 <a href="https://github.com/jcs/mailstation-tools/blob/master/loader.asm">original</a>.</p>
488
489 <h2 id="prototyping">Prototyping</h2>
490
491 <p>Earlier this year I assembled a prototype based on
492 <a href="https://www.adafruit.com/product/2471">Adafruit’s Huzzah ESP8266</a>
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 <a href="https://www.microchip.com/wwwproducts/en/mcp23017">MCP23017</a>
497 I<sup>2</sup>C chip, which ultimately proved to be too slow to transfer large
498 files (~16Kb) so I switched to the
499 <a href="https://www.microchip.com/wwwproducts/en/MCP23S18">MCP23S18</a>
500 which interfaces over SPI.</p>
501
502 <figure>
503 <a href="/images/2021-04-23-prototype-large.jpg"><img src="/images/2021-04-23-prototype-327x245.jpg" srcset="/images/2021-04-23-prototype-327x245.jpg 1x, /images/2021-04-23-prototype-654x490@2x.jpg 2x" width="327" height="245" alt="prototype of WiFiStation on a breadboard" class="1/2" /></a>
504 <a href="/images/2021-04-23-prototype_rear-large.jpg"><img src="/images/2021-04-23-prototype_rear-327x245.jpg" srcset="/images/2021-04-23-prototype_rear-327x245.jpg 1x, /images/2021-04-23-prototype_rear-654x490@2x.jpg 2x" width="327" height="245" alt="rear view of WiFiStation prototype" class="1/2" /></a>
505 </figure>
506
507 <p>The prototype worked with the
508 <a href="https://github.com/jcs/msTERM/commit/bfa680dbe1759ca34fe285d223d81684ea436892">msTERM
509 modifications</a>
510 I made, so I set about turning into something I could make available to others.</p>
511
512 <p>While the Adafruit Huzzah board had almost everything I needed, I decided to
513 upgrade to their slightly larger
514 <a href="https://www.adafruit.com/product/2821">Feather Huzzah</a>
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 <a href="https://www.adafruit.com/product/4237">rechargable battery</a>.
519 Since the MailStation can already run on AA batteries, this would allow the
520 entire system to be portable.</p>
521
522 <p>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.</p>
527
528 <h2 id="designing-a-pcb">Designing a PCB</h2>
529
530 <p>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 <a href="https://www.autodesk.com/products/eagle/overview">EAGLE</a>
534 and stumbled through how to design a
535 <a href="https://github.com/jcs/WiFiStation/tree/main/pcb">schematic</a>
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.</p>
539
540 <p>Once my initial design seemed sufficient, I uploaded it to
541 <a href="https://www.pcbway.com/">PCBWay</a>
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 <a href="https://www.digikey.com/">DigiKey</a>.</p>
546
547 <figure>
548 <a href="/images/2021-04-23-eagle-large.png"><img src="/images/2021-04-23-eagle-327x207.png" srcset="/images/2021-04-23-eagle-327x207.png 1x, /images/2021-04-23-eagle-654x414@2x.png 2x" width="327" height="207" alt="WiFiStation schematic" class="1/2" /></a>
549 <a href="/images/2021-04-23-eagle_board-large.png"><img src="/images/2021-04-23-eagle_board-327x208.png" srcset="/images/2021-04-23-eagle_board-327x208.png 1x, /images/2021-04-23-eagle_board-654x416@2x.png 2x" width="327" height="208" alt="WiFiStation board" class="1/2" /></a>
550 </figure>
551
552 <p>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.</p>
555
556 <p>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.</p>
563
564 <figure>
565 <a href="/images/2021-04-23-rev1-large.jpg"><img src="/images/2021-04-23-rev1-327x245.jpg" srcset="/images/2021-04-23-rev1-327x245.jpg 1x, /images/2021-04-23-rev1-654x490@2x.jpg 2x" width="327" height="245" alt="WiFiStation board - revision 1" class="1/2" /></a>
566 <a href="/images/2021-04-23-rev2_assembled-large.jpg"><img src="/images/2021-04-23-rev2_assembled-327x245.jpg" srcset="/images/2021-04-23-rev2_assembled-327x245.jpg 1x, /images/2021-04-23-rev2_assembled-654x490@2x.jpg 2x" width="327" height="245" alt="WiFiStation board - revision 2 assembled" class="1/2" /></a>
567 </figure>
568
569 <p>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.</p>
574
575 <p>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.</p>
582
583 <p>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.</p>
590
591 <p>I finished this third redesign of the board and sent it off for printing.</p>
592
593 <figure>
594 <a href="/images/2021-04-23-final-large.jpg"><img src="/images/2021-04-23-final-327x245.jpg" srcset="/images/2021-04-23-final-327x245.jpg 1x, /images/2021-04-23-final-654x490@2x.jpg 2x" width="327" height="245" alt="WiFiStation board - final revision" class="1/2" /></a>
595 <a href="/images/2021-04-23-final_assembled-large.jpg"><img src="/images/2021-04-23-final_assembled-327x245.jpg" srcset="/images/2021-04-23-final_assembled-327x245.jpg 1x, /images/2021-04-23-final_assembled-654x490@2x.jpg 2x" width="327" height="245" alt="WiFiStation board - final revision assembled" class="1/2" /></a>
596 </figure>
597
598 <h2 id="making-the-case">Making the Case</h2>
599
600 <p>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 <a href="https://twitter.com/jcs/status/1372024803817877506">3D modeling and printing</a>.
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 <a href="https://github.com/jcs/WiFiStation/blob/main/enclosure/enclosure.stl">decent case</a>
608 that connected together and allowed an optional lithium ion battery to be
609 housed in it as well.</p>
610
611 <figure>
612 <a href="/images/2021-04-23-printing-large.jpg"><img src="/images/2021-04-23-printing-327x245.jpg" srcset="/images/2021-04-23-printing-327x245.jpg 1x, /images/2021-04-23-printing-654x490@2x.jpg 2x" width="327" height="245" alt="Enclosure being printed" class="1/2" /></a>
613 <a href="/images/2021-04-23-case-large.jpg"><img src="/images/2021-04-23-case-327x245.jpg" srcset="/images/2021-04-23-case-327x245.jpg 1x, /images/2021-04-23-case-654x490@2x.jpg 2x" width="327" height="245" alt="Enclosure" class="1/2" /></a>
614 </figure>
615
616 <p>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 <a href="https://www.digikey.com/en/products/detail/molex/1727040159/5817827">these</a>.</p>
620
621 <h2 id="firmware">Firmware</h2>
622
623 <p>With the hardware design done, I developed more of the
624 <a href="https://github.com/jcs/WiFiStation/tree/main/esp8266">firmware</a>
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.</p>
628
629 <figure>
630 <a href="/images/2021-04-23-http-large.jpg"><img src="/images/2021-04-23-http-493x148.jpg" srcset="/images/2021-04-23-http-493x148.jpg 1x, /images/2021-04-23-http-986x296@2x.jpg 2x" width="493" height="148" alt="WiFiStation HTTP interface" class="3/4" /></a>
631 </figure>
632
633 <p>I also improved the telnet/<code class="language-plaintext highlighter-rouge">ATDT</code> handling so msTERM can now dial into BBSes
634 over telnet with proper telnet negotiation, and one do things like <code class="language-plaintext highlighter-rouge">+++ ATH</code> to
635 hang up.</p>
636
637 <figure>
638 <a href="/images/2021-04-23-telnet-large.jpg"><img src="/images/2021-04-23-telnet-493x284.jpg" srcset="/images/2021-04-23-telnet-493x284.jpg 1x, /images/2021-04-23-telnet-986x568@2x.jpg 2x" width="493" height="284" alt="WiFiStation telnetting" class="3/4" /></a>
639 </figure>
640
641 <p>And with the WiFiStation using a battery, this entire thing can be done
642 wirelessly.</p>
643
644 <h2 id="wifistation-kits">WiFiStation Kits</h2>
645
646 <p>With all of the hardware design nailed down and the software mostly done, I’ve
647 written up some
648 <a href="/wifistation">documentation</a>
649 for the whole system including assembly instructions.</p>
650
651 <p>These kits are
652 <a href="https://www.tindie.com/products/jcs/wifistation/">for sale on Tindie</a>
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.</p>
656
657 <p><br /></p>
658
659 <div class="footnotes" role="doc-endnotes">
660 <ol>
661 <li id="fn:0" role="doc-endnote">
662 <p>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. <a href="#fnref:0" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
663 </li>
664 </ol>
665 </div></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"><p>Lenovo has finally made a smaller version of its
666 <a href="/2019/08/14/x1c7">X1 Carbon</a>,
667 something I’ve been looking forward to for years.</p>
668
669 <p><img src="/images/2021-01-27-hero-665x207.jpg" srcset="/images/2021-01-27-hero-665x207.jpg 1x, /images/2021-01-27-hero-1330x414@2x.jpg 2x" width="665" height="207" alt="side profile of thinkpad x1 nano on desk" class="header" /></p>
670
671
672
673 <h2 id="hardware">Hardware</h2>
674
675 <p>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.</p>
682
683 <p>The X1 Nano (X1N1?) weighs 2.0 lbs compared to my previous
684 <a href="/2019/08/14/x1c7">X1C7’s</a>
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.</p>
688
689 <p>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).</p>
695
696 <p>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.</p>
700
701 <p>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.</p>
705
706 <p>The 13” 2K (2160x1350) matte, non-touch IPS screen looks great and is the same
707 horizontal resolution as my
708 <a href="/2017/07/14/matebook">13” MateBook X</a>
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.</p>
715
716 <p>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.</p>
718
719 <p>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.</p>
722
723 <p>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 <code class="language-plaintext highlighter-rouge">Fn+Space</code> or
729 through <code class="language-plaintext highlighter-rouge">wsconsctl keyboard.backlight</code> on OpenBSD, or through software
730 utilities like
731 <a href="https://github.com/jcs/xdimmer">xdimmer</a>.</p>
732
733 <p>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<sup>2</sup>C as on the X1C7.</p>
740
741 <p>I am using the far-superior
742 <a href="https://www.etsy.com/jp/shop/SaotoTech">“soft rim”-style TrackPoint cap</a>
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.</p>
746
747 <figure>
748 <a href="/images/2021-01-27-trackpoint-large.jpg"><img src="/images/2021-01-27-trackpoint-327x245.jpg" srcset="/images/2021-01-27-trackpoint-327x245.jpg 1x, /images/2021-01-27-trackpoint-654x490@2x.jpg 2x" width="327" height="245" alt="close-up of keyboard showing new trackpoint cap installed, with old cap next to it" class="1/2" /></a>
749 <a href="/images/2021-01-27-trackpoint_profile-large.jpg"><img src="/images/2021-01-27-trackpoint_profile-327x245.jpg" srcset="/images/2021-01-27-trackpoint_profile-327x245.jpg 1x, /images/2021-01-27-trackpoint_profile-654x490@2x.jpg 2x" width="327" height="245" alt="new trackpoint cap height compared to keyboard key height" class="1/2" /></a>
750 </figure>
751
752 <p>A square USB-attached fingerprint sensor sits next to the touchpad which I’ve
753 honestly forgotten about until I just looked.</p>
754
755 <p>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.</p>
759
760 <p>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.</p>
770
771 <figure>
772 <a href="/images/2021-01-27-inside-large.jpg"><img src="/images/2021-01-27-inside-493x369.jpg" srcset="/images/2021-01-27-inside-493x369.jpg 1x, /images/2021-01-27-inside-986x738@2x.jpg 2x" width="493" height="369" alt="inside of x1 nano" class="3/4" /></a>
773 </figure>
774
775 <h2 id="firmware">Firmware</h2>
776
777 <p>The X1 Nano defaults to a graphical firmware upon pressing <code class="language-plaintext highlighter-rouge">F1</code>, which can be
778 switched back into a simple text mode.
779 <code class="language-plaintext highlighter-rouge">F12</code> can be used to temporarily select a different boot device.
780 Pro-tip: press <code class="language-plaintext highlighter-rouge">Fn+F1</code> to mute the speakers before pressing either of these
781 options to prevent a loud, annoying beep.</p>
782
783 <p>I recommend enabling the “F1-F12 as Primary Function” option to not require
784 using the Fn key to register these keys.</p>
785
786 <p>Installing a different boot logo is still
787 <a href="https://jcs.org/2017/09/01/thinkpad_x1c#firmware">possible</a>
788 through Windows, which also gets rid of the new “TCO Certified” logo in the
789 bottom-right corner.</p>
790
791 <p>Secure Boot must be disabled in the BIOS menu to boot OpenBSD, and a “CSM
792 Support” option is no longer available (nor needed).</p>
793
794 <p>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 <code class="language-plaintext highlighter-rouge">S0ix</code> and achieve a similar level of suspended power
801 consumption are underway, as my
802 <a href="/2020/05/15/surface_go2">Surface Go 2</a>
803 was a similar device.</p>
804
805 <h2 id="openbsd-support-log">OpenBSD Support Log</h2>
806
807 <p><strong>2021-01-17:</strong> The usual round of PCI device ID additions have been made, and
808 <code class="language-plaintext highlighter-rouge">iwx</code> has been
809 <a href="https://github.com/openbsd/src/commit/8edfa316af4155e6583562fc817d827a3f2fbd09">updated</a>
810 to attach to the AX201 device found in the X1 Nano.</p>
811
812 <p>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.</p>
816
817 <p><strong>2021-01-25:</strong> I’ve been experimenting with
818 <a href="https://github.com/jcs/openbsd-src/commit/cf7c4a31389d24a07c91c40e3daa9da68339e037">adjustable fan control in <code class="language-plaintext highlighter-rouge">acpithinkpad</code></a>
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.</p>
823
824 <p><strong>2021-01-27:</strong> I’ve also been working on
825 <a href="https://github.com/jcs/openbsd-src/commit/29edcdbd593388193af3e1461f4432c6c94ff5b2">adding support for Intel HWP</a>
826 as a modern replacement for OpenBSD’s <code class="language-plaintext highlighter-rouge">hw.setperf</code>, 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.</p>
829
830 <p><strong>2021-04-07:</strong> 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.</p>
836
837 <h2 id="current-openbsd-support-summary">Current OpenBSD Support Summary</h2>
838
839 <p>Status is relative to OpenBSD-current as of 2021-01-27.</p>
840
841 <table>
842 <thead>
843 <tr>
844 <th>Component</th>
845 <th>Works?</th>
846 <th>Notes</th>
847 </tr>
848 </thead>
849 <tbody>
850 <tr>
851 <td>Audio</td>
852 <td>Yes</td>
853 <td>Intel audio with Realtek ALC287 codec and supported by <a href="http://man.openbsd.org/azalia.4"><code class="language-plaintext highlighter-rouge">azalia</code></a>. Microphone can be disabled in the BIOS.</td>
854 </tr>
855 <tr>
856 <td>Battery status</td>
857 <td>Yes</td>
858 <td>48Whr battery, status available through <a href="http://man.openbsd.org/acpibat.4"><code class="language-plaintext highlighter-rouge">acpibat</code></a>.</td>
859 </tr>
860 <tr>
861 <td>Bluetooth</td>
862 <td>No</td>
863 <td>Attaches as a <a href="http://man.openbsd.org/ugen.4"><code class="language-plaintext highlighter-rouge">ugen</code></a> device, but OpenBSD does not support Bluetooth. Can be disabled in the BIOS.</td>
864 </tr>
865 <tr>
866 <td>Fingerprint sensor</td>
867 <td>No</td>
868 <td>Synaptics <code class="language-plaintext highlighter-rouge">00bd</code> via USB, <a href="https://www.reddit.com/r/thinkpad/comments/e90cgp/p43s_working_fingerprint_reader_on_linux/">might be supported by libfprint</a> with some extra firmware. Can be disabled in the BIOS.</td>
869 </tr>
870 <tr>
871 <td>Keyboard backlight</td>
872 <td>Yes</td>
873 <td>Supported natively by the EC. Can be toggled with Fn+Space and with <code class="language-plaintext highlighter-rouge">wsconsctl keyboard.backlight</code> values of <code class="language-plaintext highlighter-rouge">0</code>, <code class="language-plaintext highlighter-rouge">50</code>, and <code class="language-plaintext highlighter-rouge">100</code>.</td>
874 </tr>
875 <tr>
876 <td>Hibernation</td>
877 <td>Yes</td>
878 <td>Can be triggered by <a href="http://man.openbsd.org/ZZZ.8"><code class="language-plaintext highlighter-rouge">ZZZ</code></a>.</td>
879 </tr>
880 <tr>
881 <td>SSD</td>
882 <td>Yes</td>
883 <td>The Western Digital PC SN530 NVMe drive is supported by <a href="http://man.openbsd.org/nvme.4"><code class="language-plaintext highlighter-rouge">nvme</code></a>.</td>
884 </tr>
885 <tr>
886 <td>Suspend / resume</td>
887 <td>No</td>
888 <td>The firmware does not support ACPI S3 suspend.</td>
889 </tr>
890 <tr>
891 <td>Thunderbolt 3</td>
892 <td>Kinda</td>
893 <td>Any devices attached at boot time will work in OpenBSD, but hotplugging is not supported since we do not have an NHI driver.</td>
894 </tr>
895 <tr>
896 <td>Touchpad</td>
897 <td>Yes</td>
898 <td>Elan I<sup>2</sup>C, supported by <a href="http://man.openbsd.org/imt.4"><code class="language-plaintext highlighter-rouge">imt</code></a>.</td>
899 </tr>
900 <tr>
901 <td>TrackPoint</td>
902 <td>Yes</td>
903 <td>Supported by <a href="http://man.openbsd.org/pms.4"><code class="language-plaintext highlighter-rouge">pms</code></a>.</td>
904 </tr>
905 <tr>
906 <td>USB</td>
907 <td>Yes</td>
908 <td>The 2 USB-C ports work fine. I am using the <a href="https://amzn.to/2NjUxEx">Lenovo USB-C UltraDock</a> which provides charging, USB ethernet (via <a href="http://man.openbsd.org/ure.4"><code class="language-plaintext highlighter-rouge">ure</code></a>) and a connection for the dongle for my wireless mouse, all over a single USB-C cable.</td>
909 </tr>
910 <tr>
911 <td>Video</td>
912 <td>Yes</td>
913 <td><a href="http://man.openbsd.org/inteldrm.4"><code class="language-plaintext highlighter-rouge">inteldrm</code></a> supports accelerated video, DPMS, gamma control, and integrated backlight control. HDMI output through a USB-C adapter works.</td>
914 </tr>
915 <tr>
916 <td>Webcam</td>
917 <td>Yes</td>
918 <td>Chicony USB, supported by the <a href="http://man.openbsd.org/uvideo.4"><code class="language-plaintext highlighter-rouge">uvideo</code></a> driver when the <code class="language-plaintext highlighter-rouge">kern.video.record</code> sysctl is enabled. Can be disabled in the BIOS.</td>
919 </tr>
920 <tr>
921 <td>Wireless</td>
922 <td>Yes</td>
923 <td>The non-removable Intel AX201 802.11ax wireless chip is supported by <a href="http://man.openbsd.org/iwx.4"><code class="language-plaintext highlighter-rouge">iwx</code></a>.</td>
924 </tr>
925 </tbody>
926 </table></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"><p>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 <a href="//blog.mozilla.org/security/2020/11/17/firefox-83-introduces-https-only-mode/">even looked at</a>)
930 and search engines de-prioritizing their content.</p>
931
932 <p>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 <em>need</em> 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.</p>
936
937
938
939 <p class="alert">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.</p>
946
947 <h2 id="http-upgrading">HTTP Upgrading</h2>
948
949 <p>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 <code class="language-plaintext highlighter-rouge">https</code>
951 scheme.
952 (Imagine a user hearing your website mentioned on a podcast and they have to
953 type it into their browser.)</p>
954
955 <p>For a URL entered with an <code class="language-plaintext highlighter-rouge">http</code> scheme or, more commonly, no scheme specified,
956 unless your domain is listed in the
957 <a href="//www.chromium.org/hsts"><abbr title="Strict Transport Security">STS</abbr> preload list</a>
958 of the user’s browser or they are using a plugin like
959 <a href="//www.eff.org/https-everywhere">HTTPS Everywhere</a>, 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.</p>
964
965 <p>If your server is properly configured to send a <code class="language-plaintext highlighter-rouge">Strict-Transport-Security</code>
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 <code class="language-plaintext highlighter-rouge">http://</code> URL.</p>
970
971 <h2 id="avoid-forced-upgrading-by-default">Avoid Forced Upgrading by Default</h2>
972
973 <p>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.</p>
980
981 <p>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 <a href="https://meyerweb.com/eric/thoughts/2018/08/07/securing-sites-made-them-less-accessible/">not the first</a>
992 to complain about this.</p>
993
994 <p>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 <code class="language-plaintext highlighter-rouge">server</code> blocks with the <code class="language-plaintext highlighter-rouge">listen
997 *:80</code> version redirecting to the <code class="language-plaintext highlighter-rouge">listen *:443 ssl</code> version, use a single
998 <code class="language-plaintext highlighter-rouge">server</code> block with multiple <code class="language-plaintext highlighter-rouge">listen</code> lines, like so:</p>
999
1000 <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>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 </code></pre></div></div>
1011
1012 <p>While it may seem counter to the point of this article, I recommend <strong>not</strong>
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 <a href="//en.wikipedia.org/wiki/Downgrade_attack">tricked into negotiating</a>
1020 an old, broken cipher if your server still offers it.</p>
1021
1022 <p>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.</p>
1025
1026 <h2 id="continue-upgrading-modern-browsers">Continue Upgrading Modern Browsers</h2>
1027
1028 <p>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 <a href="//developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Upgrade-Insecure-Requests"><code class="language-plaintext highlighter-rouge">Upgrade-Insecure-Requests</code></a>
1032 header.
1033 This header is only sent by modern browsers that support
1034 <a href="//developer.mozilla.org/en-US/docs/Web/HTTP/CSP">CSP</a>
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.</p>
1038
1039 <p>For Nginx, this can be done inside a <code class="language-plaintext highlighter-rouge">server</code> block by defining a variable
1040 per-request that includes whether it was made over plaintext HTTP and whether it
1041 included an <code class="language-plaintext highlighter-rouge">Upgrade-Insecure-Requests: 1</code> header:</p>
1042
1043 <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>server {
1044 ...
1045 set $need_http_upgrade "$https$http_upgrade_insecure_requests";
1046 location / {
1047 if ($need_http_upgrade = "1") {
1048 add_header Vary Upgrade-Insecure-Requests;
1049 return 301 https://$host$request_uri;
1050 }
1051
1052 ...
1053 }
1054 }
1055 </code></pre></div></div>
1056
1057 <p>This <code class="language-plaintext highlighter-rouge">location</code> block will respond for any request and, for those made over
1058 plaintext HTTP where <code class="language-plaintext highlighter-rouge">$https</code> will be blank and which included an
1059 <code class="language-plaintext highlighter-rouge">Upgrade-Insecure-Requests: 1</code> header, they will be offered a 301 redirection to
1060 the HTTPS version.
1061 The <code class="language-plaintext highlighter-rouge">Vary</code> header is sent so that any caching proxies in the middle won’t cache
1062 the redirect.</p>
1063
1064 <h2 id="content-concessions">Content Concessions</h2>
1065
1066 <p>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.</p>
1071
1072 <p>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.</p>
1075
1076 <p>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 <code class="language-plaintext highlighter-rouge">&lt;a&gt;</code> or <code class="language-plaintext highlighter-rouge">&lt;img&gt;</code> tags that are local to your site, use relative links to
1079 avoid specifying a particular scheme.</p>
1080
1081 <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>&lt;a href="/posts/blah"&gt;
1082 &lt;img src="/images/..."&gt;
1083 &lt;/a&gt;
1084 </code></pre></div></div>
1085
1086 <p>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 <code class="language-plaintext highlighter-rouge">http:</code> or <code class="language-plaintext highlighter-rouge">https:</code> that the document is being viewed
1089 over:</p>
1090
1091 <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>&lt;a href="//other.example.com/"&gt;My other site&lt;/a&gt;
1092 </code></pre></div></div>
1093
1094 <h2 id="a-rant-about-gemini">A Rant About Gemini</h2>
1095
1096 <p>Tangentially related,
1097 <a href="//gemini.circumlunar.space/">Gemini</a>
1098 is a modern document transfer protocol that aims to fit between the ancient
1099 <a href="//en.wikipedia.org/wiki/Gopher_(protocol)">Gopher</a>
1100 protocol and the too-modern HTTP web.
1101 Its document markup language is based on
1102 <a href="//en.wikipedia.org/wiki/Markdown">Markdown</a>
1103 so it’s very lightweight and simple to parse without complex HTML/CSS parsers.</p>
1104
1105 <p>It sounds like the perfect thing to bring modern content to vintage computers,
1106 except that its
1107 <a href="//gemini.circumlunar.space/docs/specification.html">protocol</a>
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.</p>
1111
1112 <p>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.</p>
1118
1119 <p>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 <a href="http://tenfourfox.blogspot.com/2018/02/the-tls-apocalypse-reaches-power-macs.html">platform doesn’t have a TLS 1.2 library</a>
1125 available, that makes it difficult to write a client without depending on an
1126 <a href="//github.com/jcs/sockhole">external system</a>
1127 [<a href="https://oldvcr.blogspot.com/2020/11/fun-with-crypto-ancienne-tls-for.html">2</a>].</p>
1128
1129 <p>In my opinion, the protocol should <em>recommend</em> that servers offer both plaintext
1130 and TLS encrypted versions and <em>recommend</em> that clients prefer TLS, but <em>may</em>
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.</p>
1134
1135 <p>Perhaps just sending actual Markdown text over plaintext HTTP to clients that
1136 ask for it can be the new, old web.</p>
1137
1138 <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Accept: text/markdown,text/plain;q=0.9,*/*;q=0.1
1139 </code></pre></div></div>
1140
1141 <hr />
1142
1143 <p><em>Please don’t contact me to “well ackchyually” me and explain
1144 <a href="/2011/08/17/a_man-in-the-middle_attack_in_the_wild">MITM attacks</a>
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.</em></p></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"><p>Fifteen years ago, NetBSD’s Bluetooth audio stack was
1149 <a href="https://github.com/openbsd/src/commit/9dd45fb4d11e8194bf48b594393800ae9c06d75d">imported</a>
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 <a href="https://github.com/openbsd/src/commit/b8042ed98e3e7a691133b4fd8e91f61ba15a83ba"><code class="language-plaintext highlighter-rouge">tedu'd</code></a>
1156 due to conflicts with how it integrated into our kernel.</p>
1157
1158 <p>While we still have no Bluetooth support today, it is possible to play audio on
1159 Bluetooth headphones using a small hardware dongle.</p>
1160
1161 <p><img src="/images/2020-11-18-bt-w3-665x215.jpg" srcset="/images/2020-11-18-bt-w3-665x215.jpg 1x, /images/2020-11-18-bt-w3-1330x430@2x.jpg 2x" width="665" height="215" alt="creative bt-w3 plugged into laptop on desk" class="header" /></p>
1162
1163
1164
1165 <h2 id="creative-bt-w2">Creative BT-W2</h2>
1166
1167 <p>Last year I
1168 <a href="https://web.archive.org/web/20200625180156/https://twitter.com/jcs/status/1111806329717432325">came across</a>
1169 the
1170 <a href="https://amzn.to/2HMScQt">Creative BT-W2</a>
1171 USB device, which presents a standard
1172 <a href="https://man.openbsd.org/uaudio"><code class="language-plaintext highlighter-rouge">uaudio(4)</code></a>
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 <a href="https://sndio.org/"><code class="language-plaintext highlighter-rouge">sndiod</code></a>,
1178 did have software volume control so it was possible to limit the volume through
1179 <code class="language-plaintext highlighter-rouge">aucatctl</code> (now
1180 <a href="https://man.openbsd.org/sndioctl"><code class="language-plaintext highlighter-rouge">sndioctl</code></a>).</p>
1181
1182 <p>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 <a href="https://www.cnet.com/how-to/how-to-fix-low-volume-issues-when-using-airpods-on-android/">Android phones</a>.
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.</p>
1190
1191 <p>Unfortunately, even at the loudest volume from <code class="language-plaintext highlighter-rouge">sndiod</code>, 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.</p>
1196
1197 <h2 id="creative-bt-w3">Creative BT-W3</h2>
1198
1199 <p>The other day I became aware of the updated
1200 <a href="https://amzn.to/2UBC0pE">Creative BT-W3</a>,
1201 which now has a USB-C interface instead of USB-A and finally exposes hardware
1202 mixer control (note the <code class="language-plaintext highlighter-rouge">2 ctls</code>):</p>
1203
1204 <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>uaudio0 at uhub0 port 3 configuration 1 interface 1 "Creative Technology Ltd Creative BT-W3" 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 </code></pre></div></div>
1208
1209 <p>Since Tweeting about the BT-W2 last year, OpenBSD’s audio system has changed
1210 quite a bit and now <code class="language-plaintext highlighter-rouge">sndiod</code> controls output volume itself with <code class="language-plaintext highlighter-rouge">sndioctl</code> being
1211 the preferred utility, rather than directly changing hardware mixer settings
1212 with <code class="language-plaintext highlighter-rouge">mixerctl</code> as in years past.
1213 The new hardware volume control (<code class="language-plaintext highlighter-rouge">outputs.dac</code>) can still be seen or modified
1214 directly with <code class="language-plaintext highlighter-rouge">mixerctl</code> and passing it the control device for <code class="language-plaintext highlighter-rouge">audio1</code> (as
1215 the default <code class="language-plaintext highlighter-rouge">/dev/audioctl0</code> is for the built-in audio device of my laptop):</p>
1216
1217 <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code># mixerctl -f /dev/audioctl1
1218 outputs.dac=161
1219 outputs.dac_mute=off
1220 record.enable=sysctl
1221 </code></pre></div></div>
1222
1223 <p>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.</p>
1227
1228 <h2 id="automatically-switching-to-bluetooth">Automatically Switching to Bluetooth</h2>
1229
1230 <p>My laptop’s
1231 <a href="https://jcs.org/2018/11/12/vfio">Dolby Atmos speaker setup</a>
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.</p>
1237
1238 <p>To accomplish this, set an alternate device name with <code class="language-plaintext highlighter-rouge">sndiod</code>:</p>
1239
1240 <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code># rcctl set sndiod flags -f rsnd/0 -F rsnd/1
1241 # rcctl restart sndiod
1242 </code></pre></div></div>
1243
1244 <p>In this mode, <code class="language-plaintext highlighter-rouge">sndiod</code> will play through <code class="language-plaintext highlighter-rouge">rsnd/1</code> if it exists, which maps to
1245 the second audio device (<code class="language-plaintext highlighter-rouge">audio1</code>).
1246 If the device is not present, such as when the BT-W3 is not plugged in, it will
1247 play through <code class="language-plaintext highlighter-rouge">rsnd/0</code> which maps to <code class="language-plaintext highlighter-rouge">audio0</code>, the laptop’s built-in speakers.</p>
1248
1249 <p>This works fine if the device is present when <code class="language-plaintext highlighter-rouge">sndiod</code> starts, but otherwise it
1250 will need a <code class="language-plaintext highlighter-rouge">SIGHUP</code> 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 <code class="language-plaintext highlighter-rouge">hotplugd</code>:</p>
1253
1254 <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code># cat &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 </code></pre></div></div>
1265
1266 <p>Now when a new <code class="language-plaintext highlighter-rouge">uaudio</code> device is plugged in and detected by the kernel,
1267 <code class="language-plaintext highlighter-rouge">hotplugd</code> will send a <code class="language-plaintext highlighter-rouge">SIGHUP</code> to <code class="language-plaintext highlighter-rouge">sndiod</code> which will see that <code class="language-plaintext highlighter-rouge">rsnd/1</code> is
1268 available and start sending audio to it.
1269 When the BT-W3 is unplugged, <code class="language-plaintext highlighter-rouge">sndiod</code> will automatically detect that the device
1270 is no longer usable and send audio to its fallback, <code class="language-plaintext highlighter-rouge">rsnd/0</code>.
1271 Hardware device switching will be seamless and any applications playing audio
1272 won’t have to stop or be restarted.</p>
1273
1274 <p>My
1275 <a href="https://github.com/jcs/sdorfehs">window manager</a>
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 <code class="language-plaintext highlighter-rouge">sndioctl</code>, so the
1278 commands will work the same regardless of which device <code class="language-plaintext highlighter-rouge">sndiod</code> is talking to.</p>
1279
1280 <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>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 </code></pre></div></div>
1284
1285 <h2 id="responding-to-headphone-buttons">Responding to Headphone Buttons</h2>
1286
1287 <p>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.</p>
1292
1293 <p>The possible actions that the BT-W3 supports can be seen with
1294 <a href="//man.openbsd.org/usbhidctl.1"><code class="language-plaintext highlighter-rouge">usbhidctl</code></a>
1295 on the first HID report of the device, which must be located in <code class="language-plaintext highlighter-rouge">dmesg</code>:</p>
1296
1297 <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>uaudio1 at uhub0 port 1 configuration 1 interface 1 "Creative Technology Ltd Creative BT-W3" 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 "Creative Technology Ltd Creative BT-W3" 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 </code></pre></div></div>
1305
1306 <p>In my case, the first HID report on the BT-W3 is <code class="language-plaintext highlighter-rouge">uhid11</code>, so running
1307 <code class="language-plaintext highlighter-rouge">usbhidctl</code> on <code class="language-plaintext highlighter-rouge">/dev/uhid11</code> can retrieve the full report descriptor:</p>
1308
1309 <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code># 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 </code></pre></div></div>
1328
1329 <p>By using the <code class="language-plaintext highlighter-rouge">-l</code> option, input reports can be seen when the button on the
1330 AirPod is pressed:</p>
1331
1332 <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code># 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 </code></pre></div></div>
1348
1349 <p>One event is generated to report <code class="language-plaintext highlighter-rouge">Consumer_Control.Play/Pause=1</code>, then another
1350 right after it to report <code class="language-plaintext highlighter-rouge">Consumer_Control.Play/Pause=0</code>.</p>
1351
1352 <p>To automate responding to these events,
1353 <a href="//man.openbsd.org/usbhidaction"><code class="language-plaintext highlighter-rouge">usbhidaction</code></a>
1354 can be used.
1355 By default, the <code class="language-plaintext highlighter-rouge">/dev/uhid*</code> devices are owned by <code class="language-plaintext highlighter-rouge">root:wheel</code> and are mode
1356 <code class="language-plaintext highlighter-rouge">0600</code>, so to make things easier, I’ll <code class="language-plaintext highlighter-rouge">chmod</code> them <code class="language-plaintext highlighter-rouge">0660</code> so I can access them
1357 without <code class="language-plaintext highlighter-rouge">doas</code>.
1358 This needed because the program has to run as my own user to access my X11
1359 session and environment variables.</p>
1360
1361 <p>With a simple configuration file, I can make <code class="language-plaintext highlighter-rouge">usbhidaction</code> run my
1362 <a href="https://github.com/jcs/dotfiles/blob/master/bin/music"><code class="language-plaintext highlighter-rouge">music</code></a>
1363 script to play/pause, skip to the next track, or play the previous track.</p>
1364
1365 <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ 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 </code></pre></div></div>
1380
1381 <p>Unfortunately <code class="language-plaintext highlighter-rouge">usbhidaction</code> 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 <code class="language-plaintext highlighter-rouge">uhid</code> device is
1383 the correct one to operate on each time.</p>
1384
1385 <p>I have
1386 <a href="https://github.com/jcs/openbsd-src/commit/b2ad5f79a9e1848e0bcf5cc31fcf1846ec723eb3">some</a>
1387 <a href="https://github.com/jcs/openbsd-src/commit/bdd58222f11ff91a0576bd7506306b740307d38d">hacks</a>
1388 to work around these issues but it would be nice to have something more generic
1389 that listens for input reports from all <code class="language-plaintext highlighter-rouge">uhid</code> 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.</p></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"><p>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.</p>
1395
1396
1397 <video controls="1" preload="none" poster="/images/2020-11-12-thumbnail-1330x748@2x.jpg">
1398 <source src="/videos/2020-11-12.mp4" type="video/mp4" />
1399 <track default="" kind="captions" label="English" srclang="en" src="/video_captions/2020-11-12.vtt" />
1400 <p>
1401 Your browser doesn't seem to support HTML video.
1402 You can download the video in
1403 <a href="//cdn.jcs.org/videos/2020-11-12.mp4" download="">H.264/AAC</a>
1404 format instead.
1405 </p>
1406 </video>
1407
1408
1409 <p>Video notes:</p>
1410 <ul>
1411 <li><a href="https://tools.ietf.org/html/rfc1928">SOCKS5 - RFC1928</a></li>
1412 <li><a href="https://github.com/jcs/sockhole">sockhole</a></li>
1413 <li><a href="https://amzn.to/2Io10OV">Teensy 4.0</a></li>
1414 <li><a href="https://gemini.circumlunar.space/">Gemini</a></li>
1415 <li><a href="https://en.wikipedia.org/wiki/Gopher_(protocol)">Gopher</a>
1416 and
1417 <a href="https://www.macintoshrepository.org/265-turbogopher">TurboGopher 0.8</a></li>
1418 </ul>
1419
1420 <p>Please
1421 <a href="/contact">contact me</a>
1422 with any feedback or questions for future videos, and
1423 <a href="https://jcs.org/rss">subscribe to my RSS feed</a>
1424 for new videos and other posts.</p>
1425
1426 <p>Join me and others on
1427 <a href="//libera.chat/">Libera Chat</a>
1428 in the
1429 <a href="irc://irc.libera.chat/cyberpals"><code class="language-plaintext highlighter-rouge">#cyberpals</code></a>
1430 channel if you are interested in following along with this series and have
1431 questions or would like to help others.</p></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"><p>In the
1432 <a href="/2020/10/28/openbsd_diff">previous episode</a>
1433 I quickly ported OpenBSD’s <code class="language-plaintext highlighter-rouge">diff(1)</code> 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.</p>
1439
1440
1441 <video controls="1" preload="none" poster="/images/2020-11-04-thumbnail-1330x748@2x.jpg">
1442 <source src="/videos/2020-11-04.mp4" type="video/mp4" />
1443 <track default="" kind="captions" label="English" srclang="en" src="/video_captions/2020-11-04.vtt" />
1444 <p>
1445 Your browser doesn't seem to support HTML video.
1446 You can download the video in
1447 <a href="//cdn.jcs.org/videos/2020-11-04.mp4" download="">H.264/AAC</a>
1448 format instead.
1449 </p>
1450 </video>
1451
1452
1453 <p>Video notes:</p>
1454 <ul>
1455 <li>Download on the Kludge BBS via <a href="telnet://klud.ge">telnet</a>,
1456 <a href="ssh://guest@klud.ge">SSH</a>, and <a href="https://klud.ge/">web</a> at <code class="language-plaintext highlighter-rouge">klud.ge</code>, or
1457 modem at <code class="language-plaintext highlighter-rouge">+1-312-654-0090</code></li>
1458 </ul>
1459
1460 <p>Please
1461 <a href="/contact">contact me</a>
1462 with any feedback or questions for future videos, and
1463 <a href="https://jcs.org/rss">subscribe to my RSS feed</a>
1464 for new videos and other posts.</p>
1465
1466 <p>Join me and others on
1467 <a href="//libera.chat/">Libera Chat</a>
1468 in the
1469 <a href="irc://irc.libera.chat/cyberpals"><code class="language-plaintext highlighter-rouge">#cyberpals</code></a>
1470 channel if you are interested in following along with this series and have
1471 questions or would like to help others.</p></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"><p>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 <a href="https://github.com/openbsd/src/tree/master/usr.bin/rcs">RCS</a>
1476 implementation would suffice.
1477 For now, just having a <code class="language-plaintext highlighter-rouge">diff</code> utility would be helpful so in this video I port
1478 the guts of
1479 <a href="https://github.com/openbsd/src/tree/master/usr.bin/diff">OpenBSD’s <code class="language-plaintext highlighter-rouge">diff(1)</code></a>
1480 and show it generating a unified diff between revisions of a C file.</p>
1481
1482
1483 <video controls="1" preload="none" poster="/images/2020-10-28-thumbnail-1330x748@2x.jpg">
1484 <source src="/videos/2020-10-28.mp4" type="video/mp4" />
1485 <track default="" kind="captions" label="English" srclang="en" src="/video_captions/2020-10-28.vtt" />
1486 <p>
1487 Your browser doesn't seem to support HTML video.
1488 You can download the video in
1489 <a href="//cdn.jcs.org/videos/2020-10-28.mp4" download="">H.264/AAC</a>
1490 format instead.
1491 </p>
1492 </video>
1493
1494
1495 <p>Video notes:</p>
1496 <ul>
1497 <li><a href="https://github.com/openbsd/src/tree/master/usr.bin/diff">OpenBSD <code class="language-plaintext highlighter-rouge">diff(1)</code> source code</a></li>
1498 <li><code class="language-plaintext highlighter-rouge">KAHL</code> 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)</li>
1500 <li><a href="https://www.youtube.com/watch?v=zAkmUi_PpJw&amp;t=47">Phil Collins - stdio</a></li>
1501 <li>My <code class="language-plaintext highlighter-rouge">strdup</code> code in <code class="language-plaintext highlighter-rouge">xstrdup</code> should <code class="language-plaintext highlighter-rouge">malloc(len + 1)</code></li>
1502 <li><a href="https://www.tinkerboy.xyz/product/tinkerboy-ps-2-keyboard-to-mac-converter-adapter-for-macintosh-with-4p4c-keyboard-port/">tinkerBOY PS/2 keyboard to Mac converter</a></li>
1503 </ul>
1504
1505 <p>Please
1506 <a href="/contact">contact me</a>
1507 with any feedback or questions for future videos, and
1508 <a href="https://jcs.org/rss">subscribe to my RSS feed</a>
1509 for new videos and other posts.</p>
1510
1511 <p>Join me and others on
1512 <a href="//libera.chat/">Libera Chat</a>
1513 in the
1514 <a href="irc://irc.libera.chat/cyberpals"><code class="language-plaintext highlighter-rouge">#cyberpals</code></a>
1515 channel if you are interested in following along with this series and have
1516 questions or would like to help others.</p></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"><p>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.</p>
1519
1520
1521 <video controls="1" preload="none" poster="/images/2020-10-27-thumbnail-1330x748@2x.jpg">
1522 <source src="/videos/2020-10-27.mp4" type="video/mp4" />
1523 <track default="" kind="captions" label="English" srclang="en" src="/video_captions/2020-10-27.vtt" />
1524 <p>
1525 Your browser doesn't seem to support HTML video.
1526 You can download the video in
1527 <a href="//cdn.jcs.org/videos/2020-10-27.mp4" download="">H.264/AAC</a>
1528 format instead.
1529 </p>
1530 </video>
1531
1532
1533 <p>Please
1534 <a href="/contact">contact me</a>
1535 with any feedback or questions for future videos, and
1536 <a href="https://jcs.org/rss">subscribe to my RSS feed</a>
1537 for new videos and other posts.</p>
1538
1539 <p>Join me and others on
1540 <a href="//libera.chat/">Libera Chat</a>
1541 in the
1542 <a href="irc://irc.libera.chat/cyberpals"><code class="language-plaintext highlighter-rouge">#cyberpals</code></a>
1543 channel if you are interested in following along with this series and have
1544 questions or would like to help others.</p></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"><p>Today, I implement plaintext message viewing and hook it up to the message list.
1545 I also review a cleanup of <code class="language-plaintext highlighter-rouge">int</code> variables to make them either <code class="language-plaintext highlighter-rouge">short</code> or <code class="language-plaintext highlighter-rouge">long</code>
1546 throughout the project.</p>
1547
1548
1549 <video controls="1" preload="none" poster="/images/2020-10-21-thumbnail-1330x748@2x.jpg">
1550 <source src="/videos/2020-10-21.mp4" type="video/mp4" />
1551 <track default="" kind="captions" label="English" srclang="en" src="/video_captions/2020-10-21.vtt" />
1552 <p>
1553 Your browser doesn't seem to support HTML video.
1554 You can download the video in
1555 <a href="//cdn.jcs.org/videos/2020-10-21.mp4" download="">H.264/AAC</a>
1556 format instead.
1557 </p>
1558 </video>
1559
1560
1561 <p>Video notes:</p>
1562
1563 <ul>
1564 <li><a href="https://vintageapple.org/macprogramming/pdf/Macintosh_C_Programming_By_Example_1991.pdf">Macintosh C Programming by Example (PDF)</a></li>
1565 <li><a href="https://tools.ietf.org/html/rfc3501#page-58">RFC3501 - <code class="language-plaintext highlighter-rouge">RFC822.TEXT</code></a></li>
1566 <li><a href="/system6c">My “C Programming on System 6” Series page</a></li>
1567 </ul>
1568
1569 <p>Please
1570 <a href="/contact">contact me</a>
1571 with any feedback or questions for future videos, and
1572 <a href="https://jcs.org/rss">subscribe to my RSS feed</a>
1573 for new videos and other posts.</p>
1574
1575 <p>Join me and others on
1576 <a href="//libera.chat/">Libera Chat</a>
1577 in the
1578 <a href="irc://irc.libera.chat/cyberpals"><code class="language-plaintext highlighter-rouge">#cyberpals</code></a>
1579 channel if you are interested in following along with this series and have
1580