Sunday, December 31, 2023

Pi Zero 2 W micro USB Journey

I've been using a RPi4 for running Pi-hole. The RPi4 is way overpowered for Pi-hole so I decided to switch to using the Pi Zero 2 W. The Pi Zero 2 supports WiFi but does not come with an ethernet port. WiFi works perfectly well for Pi-hole, but for personal reasons, I wanted to use ethernet instead. I've read many posts that setting up an ethernet USB dongle is as easy as plugging it in. I decided to purchase the TP-Link UE300, because a poster had given the thumbs up that the UE300 works on the Pi Zero 2 W. The UE300 has an USB A plug.

Through many attempts, I was more and more convincing myself that the USB (data) micro port on the Pi Zero 2 W was faulty. Some folks have floated this idea in the Raspberry Pi Forums. I eventually did find a solution, and I'm detailing my experience below.

Before I start, I am running thte lastest Raspberry Pi OS (64-bit) Lite for the Pi Zero 2 W installed using the Raspberry Pi Imager. I also want to mention that there are two USB micro ports on the Pi Zero 2 W. One is dedicated to providing only power while the second provides both power and data. Please ensure you are using the right port. 

I didn't have a USB A to micro USB adapter but had the parts on hand so I decided put together a DIY adapter. The wiring is pretty simple because the sequence of signals on the pins of the USB A aligned with the sequence of signals on the pins of the micro USB. The USB A has 4 pins while the micro USB has 5 pins. The extra pin on the micro USB is the ID pin which I first ignored (left floating) but will touch on later.

Attempt 1:

My first attempt invovled not using the ID pin. I wired up only the V, D-, D+, and G pins between the USB A and micro USB plugs. When I plugged in the UE300 adapter, I did not see the ethernet interface. I should mention that I also tried plugging in an USB keyboard and mouse but none showed any signs of functionality. I decided to dig into this issue and found a number of posts saying that I should use an OTG cable. OTG stands for "On the Go", and it's a special adapter that treats the Pi Zero as a host to the USB device that it is connected to (I do not know the full specifications of when an OTG cable is is needed).

Attempt 2:

My second attempt involved making an OTG cable. This is easily accomplished by shorting the ID pin and the G pin on the micro USB. Again, when I plugged in the UE300 adapter, I did not see the ethernet interface. It was now that I was starting to think whether the USB micro port was faulty given what I read from the Raspberry Pi Forums.

Validation:

I tried the UE300 adapter on a Windows machine and the machine recognized the adapter. I thought that perhaps the Raspberry Pi OS didn't support this adapter so I tried it on a RPi4 and it also recognized the adapter. At this point, I concluded that the UE300 was not misbehaving.

I needed a way to check if the micro USB data port was faulty. I learned that it was possible to connect the Pi Zero 2 W to a Windows machine by treating the Pi Zero W 2 as a OTG device. Don't confuse this concept with the OTG adapter mentioned above. The OTG concept here means that we can turn the Pi Zero 2 W into a OTG device which allows a connection to the Pi Zero 2 W using ethernet over USB. Anyway, I followed the instructions on the page below. Because the Pi Zero 2 W showed up as only a COM device on my Windows system, and I needed to install the RNDIS driver.

https://www.factoryforward.com/pi-zero-w-headless-setup-windows10-rndis-driver-issue-resolved/

After installing the driver, I was able to see the ethernet device and putty into the Pi Zero 2 W. This validated that the micro USB data port was functional.

Attempt 3:

Having validated the functionality of the UE300 and the Pi Zero 2 W's USB micro data port, I decided to look at the dmesg output on the Pi Zero 2 W when I plugged in the UE300.

[ 204.742680] Indeed it is in host mode hprt0 = 00021501
[ 204.952584] usb 1-1: new high-speed USB device number 2 using dwc_otg
[ 204.952825] Indeed it is in host mode hprt0 = 00001101
[ 205.162556] usb 1-1: device descriptor read/64, error -71
[ 205.282811] Indeed it is in host mode hprt0 = 00001101
[ 205.492506] usb 1-1: device descriptor read/64, error -71
[ 205.612548] Indeed it is in host mode hprt0 = 00001101
[ 205.822445] usb 1-1: new high-speed USB device number 3 using dwc_otg
[ 205.822743] Indeed it is in host mode hprt0 = 00001101
[ 206.032416] usb 1-1: device descriptor read/64, error -71
[ 206.152692] Indeed it is in host mode hprt0 = 00001101
[ 206.362359] usb 1-1: device descriptor read/64, error -71
[ 206.482400] usb usb1-port1: attempt power cycle

At least I was getting an indication when I plugged in the adapter. However, the highlighted text caught my attention. I googled this and came across several posts that offered different solutions. I tried them one by one. I'm not lisitng all of them but instead mentioning the one setting that worked for me. I'm convinced what setting you need is dependent on the USB peripheral that you are using.

For me, the solution was to add
"dwc_otg.speed=1" to /boot/cmdline.txt

There are more options described on this page.
https://raspberrypi.stackexchange.com/questions/1886/what-kernel-parameters-are-available-for-fixing-usb-problems

Upon booting, I now see this in dmesg.

[ 850.956370] Indeed it is in host mode hprt0 = 00021501
[ 851.166317] usb 1-1: new full-speed USB device number 3 using dwc_otg
[ 851.166517] Indeed it is in host mode hprt0 = 00021501
[ 851.406722] usb 1-1: not running at top speed; connect to a high speed hub
[ 851.407623] usb 1-1: New USB device found, idVendor=2357, idProduct=0601, bcdDevice=30.00
[ 851.407636] usb 1-1: New USB device strings: Mfr=1, Product=2, SerialNumber=6
[ 851.407645] usb 1-1: Product: USB 10/100/1000 LAN
[ 851.407652] usb 1-1: Manufacturer: TP-Link
[ 851.407659] usb 1-1: SerialNumber: 000001
[ 851.413636] Indeed it is in host mode hprt0 = 00021501
[ 851.616299] usb 1-1: reset full-speed USB device number 3 using dwc_otg
[ 851.616444] Indeed it is in host mode hprt0 = 00021501

I should mention that I tried using the OTG micro USB adapter and non-OTG micro USB adapter, and both work flawlessly for the UE300. In my case, I did not need an OTG micro USB adapter for the UE300.

Summary:

I'm using a non-OTG micro USB adapter to connect the UE300 to the Pi Zero 2 W. I'm running the latest Raspberry Pi OS. I had to add "dwc_otg.speed=1" to /boot/cmdline.txt to get the OS to recognize the UE300. I am convinced that the OS for the Pi Zero 2 W requires tweaking for your peripherals to work. Don't assume your micro USB port is faulty.

Good luck.

Saturday, December 02, 2023

Cycle Through Emacs Themes

I wrote a library that lets you cycle through the available themes in Emacs. F10 and shift-F10 keys will cycle forward and backward through the themes. The theme name is printed for reference.

https://github.com/tsengf/theme-cycle

Installation
Download theme-cycle.el into ~/.emacs.d.

Add the following to your Emacs configuration

(add-to-list 'load-path (expand-file-name "~/.emacs.d)
(require 'theme-cycle)
;; Load as many themes as you are interested in exploring.
(use-package doom-themes)
(use-package ef-themes)
(use-package modus-themes)
(use-package solarized-themes)

To Use

Use F10 to cycle forward through the themes. Use shift-F10 to cycle backward through the themes.


Monday, November 27, 2023

Preventing Emacs Window Resizing on Startup

If you set the geometry of your Emacs window in elisp, you may find that the window redraws itself upon resizing. Note that I try to avoid using Xresources to set the geometry which is another solution to this problem. I'd like to control all of my settings in Emacs elisp.

To do this, we will replace default-frame-alist by setting it in the set-initial-frame function which will be associated with the before-init-hook. This hook is run before the frame is drawn preventing the window to resize.

In this example, I set the font to RobotoMono. The width is 170 characters wide and the height is y resolution of the screen less 200 pixels. I also disable other parts of the window like the menu bar, tool bar, and scroll bars.

It would be great if I can control the default background color before my theme kicks in.

(defun set-initial-frame ()
  "Defines and center the frame window"
  (let* ((width-chars 170)
         (height-buffer 200)
         (setq my-font "RobotoMono Nerd Font")
         (monitor-width (x-display-pixel-width))
         (monitor-height (- (x-display-pixel-height) height-buffer)))
    (setq default-frame-alist
          `((width . ,width-chars)
            (height . (text-pixels . ,monitor-height))
            (font . ,my-font)
            ;; Prevent the glimpse of un-styled Emacs by disabling these UI elements early.
            (menu-bar-lines . 0)
            (tool-bar-lines . 0)
            (horizontal-scroll-bars . nil)
            (vertical-scroll-bars . nil)))))

(add-hook 'before-init-hook #'set-initial-frame)

Sunday, November 19, 2023

Using use-package to bootstrap quelpa and quelpa-use-package

I use use-package and wanted to use it to bootstrap quelpa and loading quelpa-use-package. The project pages had instructions without use-package. Here is what I had to do.

(require 'package)
(setq package-archives
      '(("melpa" . "https://melpa.org/packages/"))
      use-package-always-ensure t)

(package-initialize)

(require 'use-package-ensure)

(use-package quelpa
  :ensure)

(use-package quelpa-use-package
  :demand
  :config
  (quelpa-use-package-activate-advice))

;; Now, you can take advantage of the :quelpa keyword.
(use-package copilot
  :quelpa (copilot :fetcher github
                   :repo "zerolfx/copilot.el"
                   :branch "main"
                   :files ("dist" "*.el"))
  :hook (prog-mode . copilot-mode)
  :bind (:map copilot-completion-map
              ("<tab>" . copilot-accept-completion)))

Friday, September 16, 2022

My Minimalist ZSH Prompt

I have experimented with using many ZSH prompts. On some slow systems, the latency of rendering the prompt matters. I ended up going with the following solution which is by far the fastest prompt I have come across.

function git_prompt_info() {
    ref=$(git-branch-name -q -h 12 -b 64) || return
    echo " ${ref}"
}

function git_prompt() {
    #BRANCH=$(git branch 2> /dev/null | sed -e '/^[^*]/d' -e 's/*\(.*\)/\1/')
    BRANCH="$(git_prompt_info)"
    if [ ! -z $BRANCH ]; then
        echo -n "%F{yellow}$BRANCH"
        if [ ! -z "$(git status --short)" ]; then
            echo " %F{red}?"
        fi
    fi
}

setopt PROMPT_SUBST
PROMPT=$'%F{blue}%~$(git_prompt)\n%F{244}%# %F{reset}'

I use git-branch-name (https://github.com/itchyny/git-branch-name) to improve the speed of retrieving the branch name. If you won't wish to use git-branch-name, toggle the comment of the two BRANCH lines.


Monday, March 21, 2022

FreshTomato Resources for Netgear Nighthawk AC1900 R7000 WiFi Router

FreshTomato is an alternative firmware for routers. It runs very well on the Netgear R7000. Here is a list of useful FreshTomato resources for the Netgear R7000.

Here is a list of firmware available for the Netgear R7000.

AdvancedTomato (download)
dd-wrt (info | download)
FreshTomato (download)
Netgear (download)
OpenWrt (info)
Tomato RAF Firmware (download)
XWrt-Vortex (download)

Thursday, September 23, 2021

Power Raspberry Pi 4 over HDMI

I was setting up a new system. When I disconnected the USB-C power connector, the RPi4 retained its power from the HDMI cable.