Manjaro Linux vs. Dell Latitude E7250 Bluetooth

Although the Dell Latitude E7250 allegedly had Bluetooth capability and the Blueman applet tried connecting to my Bluetooth headsets, the connection aways failed and nothing worked. There’s a WLAN module stuck in an M.2 socket inside the laptop providing both WiFi and Bluetooth:

Dell E7250 - DW1560 card in place
Dell E7250 – DW1560 card in place

A bit of searching suggested the driver wasn’t loading properly, which became obvious after I knew where to look:

dmesg | grep -i blue
… snippage …
[    5.678610] Bluetooth: hci0: BCM20702A1 (001.002.014) build 1572
[    5.678851] bluetooth hci0: Direct firmware load for brcm/BCM20702A1-0a5c-216f.hcd failed with error -2
[    5.678853] Bluetooth: hci0: BCM: Patch brcm/BCM20702A1-0a5c-216f.hcd not found
[   10.854607] Bluetooth: RFCOMM TTY layer initialized
[   10.854613] Bluetooth: RFCOMM socket layer initialized
[   10.854619] Bluetooth: RFCOMM ver 1.11

Without having the proper firmware / patch loaded, the module won’t work, even though the TTY / socket layers know it’s present, which explains why Blueman did everything except actually connect to the headsets.

More searching suggested you must extract the firmware HEX file from the Windows driver. Feeding the Service Tag into the Dell support site, then feeding “Bluetooth” and “Windows 8.1, 64-bit” (preinstalled on the laptop) into the Drivers & Downloads tab gets you the relevant EXE file: Dell Wireless 1550/1560 Wi-Fi and Bluetooth Driver. It turns out to be a self-extracting ZIP file (in Windows, anyway), so unzip it all by yourself:

unzip Network_Driver_5DFVH_WN32_6.30.223.262_A03.EXE

This produces a blizzard of HEX files in the newly created Drivers/production/Windows8.1-x64 directory. Each firmware HEX file is keyed to the USB Product Code identifying the unique USB gadget, found with lsusb:

lsusb
… snippage …
Bus 002 Device 003: ID 0a5c:216f Broadcom Corp. BCM20702A0 Bluetooth
… snippage …

The DW1560 apparently has a USB RAM interface, with the specific HEX file identified in the CopyList stanza of the INF file corresponding to that USB Product Code:

grep -i -A 5  ramusb216f.copylist Drivers/production/Windows8.1-x64/bcbtums-win8x64-brcm.inf
[RAMUSB216F.CopyList]
bcbtums.sys
btwampfl.sys
BCM20702A1_001.002.014.1443.1572.hex
… snippage …

However, the Linux firmware loader needs a different file format with a different name, mashed together from the HEX file, USB Vendor, and USB Product codes:

hex2hcd -o BCM20702A1-0a5c-216f.hcd BCM20702A1_001.002.014.1443.1572.hex

The converted firmware file goes where the loader expected to find it:

sudo cp BCM20702A1-0a5c-216f.hcd /lib/firmware/brcm/

Whereupon next reboot sorted things out:

dmesg | grep -i blue
[    6.024838] Bluetooth: Core ver 2.22
[    6.024868] Bluetooth: HCI device and connection manager initialized
[    6.024872] Bluetooth: HCI socket layer initialized
[    6.024874] Bluetooth: L2CAP socket layer initialized
[    6.024881] Bluetooth: SCO socket layer initialized
[    6.100796] Bluetooth: BNEP (Ethernet Emulation) ver 1.3
[    6.100800] Bluetooth: BNEP filters: protocol multicast
[    6.100804] Bluetooth: BNEP socket layer initialized
[    6.157114] Bluetooth: hci0: BCM: chip id 63
[    6.158125] Bluetooth: hci0: BCM: features 0x07
[    6.176119] Bluetooth: hci0: BCM20702A
[    6.177114] Bluetooth: hci0: BCM20702A1 (001.002.014) build 0000
[    7.031228] Bluetooth: hci0: BCM20702A1 (001.002.014) build 1572
[    7.047177] Bluetooth: hci0: DW1560 Bluetooth 4.0 LE
[   13.141854] Bluetooth: RFCOMM TTY layer initialized
[   13.141865] Bluetooth: RFCOMM socket layer initialized
[   13.141872] Bluetooth: RFCOMM ver 1.11

The firmware may be in one of the myriad Bluetooth packages not installed by default, so perhaps identifying & installing the proper package would sidestep the hocus-pocus.

Maybe next time?

Now I can wear my Bose Hearphones in Zoom sessions with the E7250, because my Pixel 3a phone heats up almost to the gets-bendy level while thrashing its battery to death.

JPG Recovery From a Camera FAT Filesystem

You can do it by hand, as I used to, or use recoverjpeg:

dmesg | tail
cd /tmp
sudo dcfldd if=/dev/sde1 of=pix.bin bs=1M count=100
recoverjpeg pix.bin 
ristretto image00*

Nothing prizewinning, but better than no picture at all:

Garage Robin - recovered image
Garage Robin – recovered image

Note that you start by copying a reasonable chunk of the partition from the Memory Stick / (micro)SD Card first, to prevent a bad situation from getting worse.

Now I can remember the easy way the next time around this block …

Solid Modeling: Support Puzzle

I’ve been putting this type of support structure inside screw holes & suchlike for years:

Browning Hi-Power Magazine Block - solid model - Generic 1 - support detail
Browning Hi-Power Magazine Block – solid model – Generic 1 – support detail

It’s basically a group of small rectangles rotated around the hole’s axis and about one thread thickness shorter than the overhanging interior.

I’ve found that incorporating exactly the right support structure eliminates Slic3r’s weird growths, eases removal, and generally works better all around.

So doing this for the baseplate of the Glass Tile frame came naturally:

Glass Tile Frame - octagonal support
Glass Tile Frame – octagonal support

This OpenSCAD snippet plunks one of those asterisks in each of four screw holes:

  if (Support)
    color("Yellow")
      for (i=[-1,1], j=[-1,1])
        translate([i*InsertOC.x/2,j*InsertOC.y/2,0])
          for (a=[0:45:135])
              rotate(a)
                translate([0,0,(Screw[LENGTH] - ThreadThick)/2])
                  cube([Screw[OD] - 2*ThreadWidth,2*ThreadWidth,Screw[LENGTH] - ThreadThick],center=true);

The “cubes” overlap in the middle, with no completely coincident faces or common edges, so it’s 2-manifold. Slic3r, however, produces a weird time estimate whenever the model includes those structures:

Slic3r - NaN time estimate
Slic3r – NaN time estimate

NaN stands for Not A Number and means something horrible has happened in the G-Code generation. Fortunately, the G-Code worked perfectly and produced the desired result, but I’m always uneasy when Something Seems Wrong.

Messing around with the code produced a slightly different support structure:

Glass Tile Frame - quad support
Glass Tile Frame – quad support

The one thread thick square on the bottom helps glue the structure to the platform and four ribs work just as well as eight in the octagonal hole:

  Fin = [Screw[OD]/2 - 1.5*ThreadWidth,2*ThreadWidth,ScrewRecess - ThreadThick];
  if (Inserts && SupportInserts)
    color("Yellow")
      for (i=[-1,1], j=[-1,1])
        translate([i*InsertOC.x/2,j*InsertOC.y/2,0]) {
          rotate(180/8)
            cylinder(d=6*ThreadWidth,h=ThreadThick,$fn=8);
          for (a=[0:90:360])
              rotate(a)
                translate([Fin.x/2 + ThreadWidth/2,0,(ScrewRecess - ThreadThick)/2])
                  cube(Fin,center=true);
        }

Which changed the NaN time estimates into actual numbers.

One key difference may be the small hole in the middle. The four ribs (not two!) now overlap by one thread width around the hole, so they’re not quite coincident and Slic3r produces a tidy model:

Glass Tile Frame - quad support - Slic3r
Glass Tile Frame – quad support – Slic3r

The hole eliminates a smear of infill from the center, which may have something to do with the improvement.

In any event, I have an improved copypasta recipe for the next screw holes in need of support, even if I don’t understand why it’s better.

Glass Tiles: Matrix for SK6812 PCBs

Tweaking the glass tile frame for press-fit SK6812 PCBs in the bottom of the array cells:

Glass Tile Frame - cell array - openscad
Glass Tile Frame – cell array – openscad

Which looks like this with the LEDs and brass inserts installed:

Glass Tile - 2x2 array - interior
Glass Tile – 2×2 array – interior

The base holds an Arduino Nano with room for wiring under the cell array:

Glass Tile Frame - base - openscad
Glass Tile Frame – base – openscad

Which looks like this after it’s all wired up:

Glass Tile - 2x2 array - wiring
Glass Tile – 2×2 array – wiring

The weird colors showing through the inserts are from the LEDs. The red thing in the upper left is a silicone insulation snippet. Yes, that’s hot-melt glue holding the Arduino Nano in place and preventing the PCBs from getting frisky.

Soak a handful of glass tiles overnight in paint stripper:

Glass Tiles - paint stripper soak
Glass Tiles – paint stripper soak

Whereupon the adhesive slides right off with the gentle application of a razor scraper. Rinse carefully, dry thoroughly, and snap into place.

Tighten the four M3 SHCS and it’s all good:

Glass Tile - 2x2 array - operating
Glass Tile – 2×2 array – operating

So far, I’ve had two people tell me they don’t know what it is, but they want one:

Glass Tile - various versions
Glass Tile – various versions

The OpenSCAD Customizer lets you set the array size:

Glass Tile Frame - 3x3 - press-fit SK6812 LEDs
Glass Tile Frame – 3×3 – press-fit SK6812 LEDs

However, just because you can do something doesn’t mean you should:

Glass Tile Frame - 6x6 cell array - openscad
Glass Tile Frame – 6×6 cell array – openscad

Something like this might be interesting:

Glass Tile Frame - 2x6 cell array - openscad
Glass Tile Frame – 2×6 cell array – openscad

In round numbers, printing the frame takes about an hour per cell, so a 2×2 array takes three hours and 3×3 array runs around seven hours. A 6×6 frame is just not happening.

The OpenSCAD source code as a GitHub Gist:

Glass Tiles: Glow vs. Flash Firmware

Although it’s not obvious in a still picture, the firmware now supports both the continuously changing colors of the Nissan fog lamp (mashed with tweaks from the vacuum tube lights) and the randomly changing colors from the LED matrix, both using SK6812 LEDs rather than the failing WS2812 modules:

Glass Tile - glow vs flash
Glass Tile – glow vs flash

Flash is a misnomer, as the tiles simply change from one color to the next, but I’ve never been adept at picking catchy names. In any event, the glass tiles on the left show nice pastel shades, in contrast to the bright primary(-ish) colors appearing on the right.

The colors are random numbers from 1 to 7, because 0 produces a somewhat ugly dark cell. The SK6812 modules have a white LED in addition to the RGB LEDs in the WS2812 modules, so I replace the “additive white” R+G+B color with the more-or-less true white (warm, for these modules) LED.

The new color goes into a cell picked at random (0 through 3, for 2×2 frames), except if the cell already holds the same color, whereupon a simple XOR flips the colors, except if the cell is already full-on white, whereupon it becomes half-on white to avoid going completely dark.

The glass tiles must change colors at a much slower pace than the 8×8 LED matrix, because there are so few cells; a random delay between 500 ms and 6 s seems about right.

They look really great in a dim room!

The Arduino source code as a GitHub Gist:

PiHole with DNS-over-HTTP: Revised

More than a year later, the PiHole continues to work fine, but the process for installing the Cloudflare DoH machinery has evolved.

(And, yes, it’s supposed to be DNS-over-HTTPS. So it goes.)

To forestall link rot, the key points:

cd /tmp ;  wget https://bin.equinox.io/c/VdrWdbjqyF/cloudflared-stable-linux-arm.tgz
tar -xvzf cloudflared-stable-linux-arm.tgz 
sudo cp cloudflared /usr/local/bin
sudo chmod +x /usr/local/bin/cloudflared
sudo cloudflared -v
sudo useradd -s /usr/sbin/nologin -r -M cloudflared
sudo nano /etc/default/cloudflared
----
CLOUDFLARED_OPTS=--port 5053 --upstream https://1.1.1.1/dns-query --upstream https://1.0.0.1/dns-query 
----
sudo chown cloudflared:cloudflared /etc/default/cloudflared
sudo chown cloudflared:cloudflared /usr/local/bin/cloudflared
sudo nano /etc/systemd/system/cloudflared.service
----
[Unit]
Description=cloudflared DNS over HTTPS proxy
After=syslog.target network-online.target

[Service]
Type=simple
User=cloudflared
EnvironmentFile=/etc/default/cloudflared
ExecStart=/usr/local/bin/cloudflared proxy-dns $CLOUDFLARED_OPTS
Restart=on-failure
RestartSec=10
KillMode=process

[Install]
WantedBy=multi-user.target
----
sudo systemctl enable cloudflared
sudo systemctl start cloudflared
sudo systemctl status cloudflared

Then aim PiHole’s DNS at 127.0.0.1#5053. It used to be on port #54, for whatever that’s worth.

Verify it at https://1.1.1.1/help, which should tell you DoH is in full effect.

To update the daemon, which I probably won’t remember:

wget https://bin.equinox.io/c/VdrWdbjqyF/cloudflared-stable-linux-arm.tgz
tar -xvzf cloudflared-stable-linux-arm.tgz
sudo systemctl stop cloudflared
sudo cp ./cloudflared /usr/local/bin
sudo chmod +x /usr/local/bin/cloudflared
sudo systemctl start cloudflared
cloudflared -v
sudo systemctl status cloudflared

And then It Just Works … again!

Garden Hose Valve Wrench: Reinforced

After five gardening seasons, my simple 3D printed wrench broke:

Hose Valve Knob - fractured
Hose Valve Knob – fractured

Although Jason’s comment suggesting carbon-fiber reinforcing rods didn’t prompt me to lay in a stock, ordinary music wire should serve the same purpose:

Hose Valve Knob - cut pins
Hose Valve Knob – cut pins

The pins are 1.6 mm diameter and 20 mm long, chopped off with hardened diagonal cutters. Next time, I must (remember to) grind the ends flat.

The solid model needs holes in appropriate spots:

Hose Valve Knob - Reinforced - Slic3r
Hose Valve Knob – Reinforced – Slic3r

Yes, I’m going to put round pins in square holes, without drilling the holes to the proper diameter: no epoxy, no adhesive, just 20 mm of pure friction.

The drill press aligns the pins:

Hose Valve Knob - pin ready
Hose Valve Knob – pin ready

And rams them about halfway down:

Hose Valve Knob - pin midway
Hose Valve Knob – pin midway

Close the chuck jaws and shove them flush with the surface:

Hose Valve Knob - pins installed
Hose Valve Knob – pins installed

You can see the pins and their solid plastic shells through the wrench stem:

Hose Valve Knob - assembled
Hose Valve Knob – assembled

Early testing shows the reinforced wrench works just as well as the previous version, even on some new valves sporting different handles, with an equally sloppy fit for all. No surprise: I just poked holes in the existing model and left all the other dimensions alone.

The OpenSCAD source code as a GitHub Gist: