diff --git a/OS/Readme.md b/OS/Readme.md new file mode 100644 index 0000000..c9bb2f5 --- /dev/null +++ b/OS/Readme.md @@ -0,0 +1,746 @@ +# Xubuntu Setup — Asus T101HA (`ears-tablet`) + +Working notes for setting up an Asus T101HA (Atom x5-Z8350, 2 GB RAM / ~1.8 GB +usable, eMMC) as a Mono + GTK#3 development and runtime machine. + +User: `ears` · Hostname: `ears-tablet` + +--- + +## Contents + +- [0. Recommended baseline](#0-recommended-baseline) +- [1. Installing Xubuntu](#1-installing-xubuntu) + - [1.1 Check firmware bitness first](#11-check-firmware-bitness-first--this-determines-everything) + - [1.2 Build the USB](#12-build-the-usb) + - [1.3 BIOS](#13-bios) + - [1.4 Install](#14-install) + - [1.5 Post-install GRUB fix (IA32 only)](#15-post-install-grub-fix-ia32-machines-only) + - [1.6 Expect to fix afterwards](#16-expect-to-fix-afterwards) +- [2. First boot / recovery mode](#2-first-boot--recovery-mode) +- [3. Low-RAM tuning](#3-low-ram-tuning) + - [Option A — `zram-tools`](#option-a--zram-tools-simple) + - [Option B — `systemd-zram-generator`](#option-b--systemd-zram-generator-current-preferred-on-2404) + - [Swappiness](#swappiness) +- [4. apt: repair and sources](#4-apt-repair-and-sources) + - [4.1 The modern layout](#41-the-modern-layout) + - [4.2 Correct stock sources](#42-correct-stock-sources-2510-example--substitute-your-codename) + - [4.3 Which host? archive vs old-releases](#43-which-host-archive-vs-old-releases) + - [4.4 Check for genuinely broken packages](#44-check-for-genuinely-broken-packages) + - [4.5 Don't do these](#45-dont-do-these) + - [4.6 `full-upgrade` checklist](#46-full-upgrade-checklist) + - [4.7 Reboot needed?](#47-reboot-needed) +- [5. Mono + GTK#3](#5-mono--gtk3) + - [Install](#install) + - [Optional](#optional) + - [Verify](#verify) + - [Smoke test](#smoke-test) + - [Notes vs. the WSL guide](#notes-vs-the-wsl-guide) +- [6. Display rotation + touchscreen](#6-display-rotation--touchscreen) + - [Identify devices](#identify-devices) + - [Matrices](#matrices) + - [Persistence script](#persistence-script) + - [Login screen (LightDM)](#login-screen-lightdm--separate-from-your-session) + - [Better: rotate before the session starts](#better-rotate-before-the-session-starts) + - [Wallpaper breaks after rotating](#wallpaper-breaks-after-rotating) + - [Auto-rotation (optional)](#auto-rotation-optional) +- [7. Audio](#7-audio) + - [Install and test](#install-and-test) + - [Choosing the right card](#choosing-the-right-card) + - [Renumbering at the kernel level](#renumbering-at-the-kernel-level) + - [Caveats](#caveats) +- [8. Running a script at boot](#8-running-a-script-at-boot) +- [9. File transfer to/from Windows](#9-file-transfer-tofrom-windows) +- [10. Quick reference](#10-quick-reference) + +--- + +## 0. Recommended baseline + +**Target: Xubuntu 24.04 LTS (Minimal ISO).** + +Reasons, from the apt/Mono investigation: +- The machine was found running **Ubuntu 25.10 "questing"**, which hit end of + life on **9 July 2026**. No further updates will ever be published for it. +- `gtk-sharp3` is **not packaged on 25.10**, and upgrading to 26.04 would not + bring it back. +- `gtk-sharp3` **is** packaged on 24.04 (noble), supported to 2029. +- Xfce on 24.04 idles around 500–600 MB, which matters at 1.8 GB RAM. + +Mono + `mcs` + GTK# is the correct toolchain for this hardware — the .NET SDK +(~800 MB) and Avalonia are far heavier. + +Before reinstalling, back up: `*.cs`, `*.glade`, SSH keys, browser profile. + +```bash +lsblk # is /home a separate partition? +df -h / +free -h +mkdir -p ~/backup && cp ~/*.cs ~/*.glade ~/backup/ +``` + +If `/home` is its own partition, it can be preserved during install (assign +`/home` **without** format). Use the same username to keep permissions clean. + +--- + +## 1. Installing Xubuntu + +### 1.1 Check firmware bitness first — this determines everything + +In Windows: **Settings → System → About → System type** + +- *32-bit operating system, x64-based processor* → **IA32 UEFI**, needs the + bootia32 workaround below. +- *64-bit* → skip the GRUB steps. + +### 1.2 Build the USB + +Ventoy includes IA32 UEFI support, so try it first. If it won't boot, fall back +to Rufus and copy a 32-bit `bootia32.efi` (GRUB) into `/EFI/BOOT` on the stick. + +From Linux, writing directly: + +```bash +sudo dd if=xubuntu-24.04-minimal-amd64.iso of=/dev/sdX bs=4M status=progress conv=fsync +``` + +> Verify the target with `lsblk` first. `dd` to the wrong disk destroys it +> silently. + +Verify the ISO: `sha256sum` against the checksum on the download page. + +### 1.3 BIOS + +- F2 at power-on +- **Disable Secure Boot** (the ia32 GRUB is unsigned) +- Boot menu is usually F12 / Esc + +### 1.4 Install + +Choose **Install**, not *Try* — the live session eats RAM you don't have. +Don't open Firefox or anything else during install. Let it create swap. + +### 1.5 Post-install GRUB fix (IA32 machines only) + +The installer writes a 64-bit `grubx64.efi` the firmware can't read. Boot the +live session, chroot in, and: + +```bash +grub-install --target=i386-efi --efi-directory=/boot/efi +``` + +This is **not optional** on IA32 firmware. + +### 1.6 Expect to fix afterwards + +| Component | Notes | +|---|---| +| Wi-Fi | RTL8723BS SDIO — finicky | +| Audio | ESS ES8316 codec, needs UCM configs | +| Touchscreen | Works, but rotation needs manual matrix (§6) | +| Auto-rotation | Needs `iio-sensor-proxy` + custom handler | + +A recent 6.x kernel fixes most of these. + +--- + +## 2. First boot / recovery mode + +If the user account lacks admin rights: + +```bash +usermod -aG sudo ears +groups ears # confirm 'sudo' appears +hostnamectl set-hostname ears-tablet +localectl set-locale LANG=en_US.UTF-8 # optional, cosmetic +exit # then 'resume' +``` + +`usermod -aG sudo` is the one that isn't optional — without it you can log in +but can't run any admin command. + +--- + +## 3. Low-RAM tuning + +### Option A — `zram-tools` (simple) + +```bash +sudo apt install zram-tools +``` + +Edit `/etc/default/zramswap`: +``` +PERCENT=60 +ALGO=zstd +``` + +### Option B — `systemd-zram-generator` (current, preferred on 24.04+) + +```bash +sudo apt install systemd-zram-generator + +sudo tee /etc/systemd/zram-generator.conf > /dev/null <<'EOF' +[zram0] +zram-size = min(ram / 2, 4096) +compression-algorithm = zstd +swap-priority = 100 +EOF + +sudo systemctl daemon-reload +sudo systemctl start systemd-zram-setup@zram0.service +swapon --show # expect /dev/zram0 +zramctl +``` + +The package does nothing without a config file containing at least one section. + +### Swappiness + +Swapping to zram is cheap, so raise it so the kernel actually uses it: + +```bash +echo 'vm.swappiness=100' | sudo tee /etc/sysctl.d/99-zram.conf +``` + +Reboot. Verdict: worth it at 2–4 GB, marginal at 8 GB, skip above 16 GB. +zram compresses **RAM** — it does nothing for low disk space. + +--- + +## 4. apt: repair and sources + +### 4.1 The modern layout + +Since 24.04, archive config lives in **`/etc/apt/sources.list.d/ubuntu.sources`** +(deb822 format). `/etc/apt/sources.list` being empty is normal, not a symptom. +Most apt advice online predates this and edits a file that does nothing. + +### 4.2 Correct stock sources (25.10 example — substitute your codename) + +```bash +sudo tee /etc/apt/sources.list.d/ubuntu.sources > /dev/null <<'EOF' +Types: deb +URIs: http://archive.ubuntu.com/ubuntu/ +Suites: questing questing-updates questing-backports +Components: main restricted universe multiverse +Signed-By: /usr/share/keyrings/ubuntu-archive-keyring.gpg + +Types: deb +URIs: http://security.ubuntu.com/ubuntu/ +Suites: questing-security +Components: main restricted universe multiverse +Signed-By: /usr/share/keyrings/ubuntu-archive-keyring.gpg +EOF + +sudo apt update +``` + +Do not drop the `Signed-By:` line — without it apt falls back to the legacy +trusted-keyring and you get confusing "not signed" errors later. + +`ubuntu.sources.curtin.orig` is the installer's pristine backup. apt ignores +`.orig` files. Useful as a reference, don't copy blindly. + +### 4.3 Which host? archive vs old-releases + +An EOL release only moves to `old-releases.ubuntu.com` when the migration +actually runs — which can lag the EOL date by weeks. Pointing there too early +gives four clean 404s. Test before switching: + +```bash +for p in questing questing-updates questing-backports questing-security; do + echo -n "$p: " + curl -sI "http://old-releases.ubuntu.com/ubuntu/dists/$p/Release" | head -1 +done + +curl -sI http://archive.ubuntu.com/ubuntu/dists/questing/Release | head -1 +``` + +`200` = pocket exists. `404` = drop it or use the other host. + +### 4.4 Check for genuinely broken packages + +All read-only, cheapest first: + +```bash +sudo dpkg --audit # clean = no output at all +sudo apt-get check # verifies the dependency tree +dpkg -l | grep -v '^ii' | grep -v '^rc' +apt-mark showhold # held packages are silently skipped on upgrade +``` + +dpkg status codes (desired state, then actual): + +| Code | Meaning | +|---|---| +| `ii` | Healthy | +| `rc` | Removed, config left — harmless | +| `iU` | Unpacked, never configured | +| `iF` | Half-configured | +| `iH` | Half-installed | +| `iW` / `it` | Waiting on / pending triggers | +| `*R*` | Reinstall required → `apt install --reinstall ` | + +Then repair: + +```bash +sudo dpkg --configure -a +sudo apt --fix-broken install +sudo apt full-upgrade +``` + +### 4.5 Don't do these + +```bash +# WRONG — killall receives 'sudo', 'rm', paths etc. as process names +sudo killall apt apt-get dpkg 2>/dev/null sudo rm /var/lib/apt/lists/lock ... + +# DANGEROUS — rm -rf also targets files named sudo, apt, clean, update in $PWD +sudo rm -rf /var/lib/apt/lists/* sudo apt clean sudo apt update +``` + +These must be separate lines. Also: killing `dpkg` mid-transaction is what +*creates* the broken state. Check first with `ps aux | grep -E 'apt|dpkg'`. + +Don't remove `universe` — it's an Ubuntu component, not a PPA, and +`gtk-sharp3` lives there. And never run +`add-apt-repository --remove ppa:repository-name/ppa` literally; that's a +placeholder from a copied guide. + +### 4.6 `full-upgrade` checklist + +- Use `full-upgrade`, not `upgrade` — it permits removals where deps changed +- Read the summary line; mass removals of desktop/kernel packages = stop +- Plug the tablet in; power loss mid-`dpkg` recreates the broken state +- On config prompts, keeping the local version (the default) is safe unless + you know you edited it +- Then `sudo apt autoremove` — but answer `n` if anything with `efi` appears +- Reboot before `do-release-upgrade` so the newest kernel is running + +### 4.7 Reboot needed? + +```bash +[ -f /var/run/reboot-required ] && cat /var/run/reboot-required.pkgs +sudo needrestart # interactive; shows what's running old libs +``` + +Kernel / initramfs / systemd / glibc → reboot. Everything else → restart the +service. + +--- + +## 5. Mono + GTK#3 + +### Install + +```bash +sudo add-apt-repository universe +sudo apt update +sudo apt install mono-complete gtk-sharp3 +``` + +| Package | Contents | Size | +|---|---|---| +| `mono-runtime` | JIT + `mscorlib` only | ~15 MB | +| `mono-devel` | Compiler + the BCL you need | ~200–400 MB | +| `mono-complete` | Runtime + `mcs` + entire class library + F#/VB | ~300–500 MB | + +**Avoid `mono-runtime`.** The BCL is split across dozens of +`libmono-system-*-cil` packages; hello-world runs, but anything touching LINQ, +XML, HTTP, or `System.IO.Ports` (the COM-port combo box in `homepage.glade`) +throws `Could not load file or assembly`. On a tight disk, `mono-devel` saves +~100 MB over `mono-complete` and still covers everything this project needs. + +### Optional + +```bash +sudo apt install glade # visual designer — skip on this machine +sudo apt install libgdiplus # only if using System.Drawing +sudo apt install libcanberra-gtk3-module # silences a harmless console warning +``` + +### Verify + +```bash +mono --version +mcs --version +pkg-config --list-all | grep gtk-sharp # want gtk-sharp-3.0 +apt policy gtk-sharp3 +``` + +### Smoke test + +```bash +cat > gtkcheck.cs <<'EOF' +using System; +using Gtk; + +class GtkCheck { + static void Main() { + Application.Init(); + var win = new Window("Hello GTK#3"); + win.SetDefaultSize(300, 200); + win.DeleteEvent += (o, args) => Application.Quit(); + + var button = new Button("Click me"); + button.Clicked += (o, args) => Console.WriteLine("Clicked!"); + win.Add(button); + + win.ShowAll(); + Application.Run(); + } +} +EOF + +mcs -pkg:gtk-sharp-3.0 gtkcheck.cs +mono gtkcheck.exe +``` + +Do the throwaway test first — it isolates "is gtk-sharp3 working" from "does my +app compile." + +Then the real thing: + +```bash +mcs -pkg:gtk-sharp-3.0 program.cs MainWindow.cs ArduinoConnection.cs -out:test.exe +mono test.exe +``` + +(`ArduinoConnection.cs` is needed because `MainWindow` calls +`_arduino.Disconnect()`; omitting it gives `CS0246`.) + +### Notes vs. the WSL guide + +- No WSLg, no `$DISPLAY` fiddling — Xfce is itself GTK3, so the app picks up the + system theme and the window just appears. +- Only exception: over SSH you need `ssh -X`. +- Companion files (`-r:` DLLs, `homepage.glade`) must sit next to the `.exe`, or + you get `FileNotFoundException`. +- `homepage.glade` targets GTK 3.24, which 22.04 and 24.04 both ship. +- `gtk-sharp2` is gone from 24.04 onward — use `gtk-sharp3`. + +--- + +## 6. Display rotation + touchscreen + +X11 does **not** rotate touch input when you rotate the display. The touch +device needs its own coordinate transformation matrix. + +### Identify devices + +```bash +xrandr # output name — DSI-1, or None-1 on this unit +xinput list --name-only # look for Silead / GSL / SIS, NOT 'Touchpad' +``` + +> On this tablet the output reported as **`None-1`** (xrandr's fallback when the +> connector type isn't identified — it can change between kernels) and the +> touchscreen as **`SIS0457:00 0457:11ED`**. + +### Matrices + +| Rotation | Matrix | +|---|---| +| normal | `1 0 0 0 1 0 0 0 1` | +| right (90° CW) | `0 1 0 -1 0 1 0 0 1` | +| left (90° CCW) | `0 -1 1 1 0 0 0 0 1` | +| inverted (180°) | `-1 0 1 0 -1 1 0 0 1` | + +```bash +xrandr --output None-1 --rotate right +xinput set-prop "SIS0457:00 0457:11ED" "Coordinate Transformation Matrix" 0 1 0 -1 0 1 0 0 1 +``` + +### Persistence script + +```bash +nano ~/rotate.sh +``` + +```bash +#!/bin/bash +sleep 3 +OUT=$(xrandr | awk '/ connected/{print $1; exit}') +xrandr --output "$OUT" --rotate right +TS=$(xinput list --name-only | grep -iE 'silead|gsl|touchscreen|SIS' | grep -vi 'touchpad' | head -1) +[ -n "$TS" ] && xinput set-prop "$TS" "Coordinate Transformation Matrix" 0 1 0 -1 0 1 0 0 1 +xset s off +xset -dpms +``` + +```bash +chmod +x ~/rotate.sh +~/rotate.sh # test before automating +``` + +Then **Settings → Session and Startup → Application Autostart → Add**, command +`/home/ears/rotate.sh`. + +> **Gotcha:** grepping bare `touch` matches the **trackpad** and rotates the +> pointer instead. Use `touchscreen` and exclude `touchpad`. To undo: +> ```bash +> TP=$(xinput list --name-only | grep -i -m1 touchpad) +> xinput set-prop "$TP" "Coordinate Transformation Matrix" 1 0 0 0 1 0 0 0 1 +> ``` +> Or just log out — the matrix isn't saved anywhere. + +The `sleep 3` matters; the touchscreen isn't registered the instant the session +starts. Raise to 5 if touch still comes out wrong. + +**Try Settings → Display first.** Its rotation dropdown often persists on its +own, leaving the script to handle only the `xinput` part. + +### Login screen (LightDM — separate from your session) + +```bash +sudo nano /etc/lightdm/lightdm.conf +``` +```ini +[Seat:*] +display-setup-script=/usr/bin/xrandr --output None-1 --rotate right +``` + +### Better: rotate before the session starts + +```bash +sudo nano /etc/X11/xorg.conf.d/10-monitor.conf +``` +``` +Section "Monitor" + Identifier "DSI-1" + Option "Rotate" "right" +EndSection +``` + +Whole machine including the text console — add to `/etc/default/grub`: +`fbcon=rotate:1` plus `video=DSI-1:panel_orientation=right_side_up`, then +`sudo update-grub`. + +### Wallpaper breaks after rotating + +The desktop paints the wallpaper onto a surface sized for the old geometry and +doesn't repaint after `xrandr`. On Xfce: + +```bash +xfdesktop --reload +``` + +Also set the image style to **scaled** — `spanned` and `zoom` misbehave badly +when the aspect ratio flips. Rotating before the session starts avoids this +entirely. + +### Auto-rotation (optional) + +Xfce has no built-in handler. Confirm the sensor works before writing anything: + +```bash +sudo apt install -y iio-sensor-proxy +monitor-sensor # tilt the tablet; orientation should print +``` + +If nothing prints, this unit needs a kernel quirk — not worth chasing. + +```bash +monitor-sensor | while read -r line; do + case "$line" in + *normal*) R=normal; M="1 0 0 0 1 0 0 0 1" ;; + *right-up*) R=right; M="0 1 0 -1 0 1 0 0 1" ;; + *left-up*) R=left; M="0 -1 1 1 0 0 0 0 1" ;; + *bottom-up*) R=inverted; M="-1 0 1 0 -1 1 0 0 1" ;; + *) continue ;; + esac + xrandr --output DSI-1 --rotate "$R" + xinput set-prop "SIS0457:00 0457:11ED" "Coordinate Transformation Matrix" $M +done +``` + +> Most community auto-rotate scripts only call `xrandr` and leave touch behind. +> If a script doesn't contain `xinput set-prop`, it won't rotate touch. + +--- + +## 7. Audio + +### Install and test + +```bash +sudo apt install alsa-utils # this is what provides aplay + +aplay --version +aplay -l # list playback devices +aplay /usr/share/sounds/alsa/Front_Center.wav +speaker-test -c 2 -t wav -l 1 +``` + +PipeWire/PulseAudio layer: + +```bash +pactl info # "Server Name" tells you which +pactl list short sinks +paplay /usr/share/sounds/alsa/Front_Center.wav +``` + +### Choosing the right card + +Neither config file exists by default — create whichever you prefer: + +```bash +nano ~/.asoundrc # per-user; wins over the system file +# or +sudo nano /etc/asound.conf # system-wide, incl. root and systemd services +``` + +``` +defaults.pcm.card 1 +defaults.ctl.card 1 +``` + +`ctl` is what `alsamixer` reads, `pcm` is what `aplay` reads — set both. No +reload needed; it's read per-process. + +With `plughw` conversion behaviour as the default: + +``` +pcm.!default { + type plug + slave.pcm "hw:1,0" +} +ctl.!default { + type hw + card 1 +} +``` + +Verify — `-v` prints the resolved device: + +```bash +aplay -D default -v /usr/share/sounds/alsa/Front_Center.wav 2>&1 | head -20 +``` + +### Renumbering at the kernel level + +```bash +cat /proc/asound/modules +sudo nano /etc/modprobe.d/alsa-card-order.conf +``` +``` +options snd_soc_sst_bytcr_rt5640 index=0 +options snd_hda_intel index=1 +``` +```bash +sudo update-initramfs -u && sudo reboot +``` + +### Caveats + +- **PipeWire ignores all of the above.** `~/.asoundrc` only governs programs + talking to ALSA directly (`aplay`, `alsamixer`). For desktop apps use + `pactl set-default-sink` or `pavucontrol`. +- Save your mixer levels or they come back muted: `sudo alsactl store 1` +- Device busy → use `aplay -D default file.wav`, not `-D hw:0,0` +- Permission errors → `sudo usermod -aG audio $USER`, then re-login +- `aplay` handles WAV/AU/RAW only — use `mpg123` or `ffplay` for MP3/FLAC + +--- + +## 8. Running a script at boot + +```bash +sudo nano /usr/local/bin/myscript.sh +sudo chmod +x /usr/local/bin/myscript.sh +``` + +Start with `#!/bin/bash` and use **absolute paths** — there's almost no +environment at boot. + +```bash +sudo nano /etc/systemd/system/myscript.service +``` + +```ini +[Unit] +Description=My boot script +After=network-online.target +Wants=network-online.target + +[Service] +Type=oneshot +ExecStart=/usr/local/bin/myscript.sh +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target +``` + +```bash +sudo systemctl daemon-reload +sudo systemctl enable --now myscript.service +systemctl status myscript.service +journalctl -u myscript.service +``` + +Variations: + +- Long-running daemon → `Type=simple`, drop `RemainAfterExit` +- Before the login screen → `Before=display-manager.service` in `[Unit]`, + `WantedBy=display-manager.service` in `[Install]` +- Quick and dirty → `sudo crontab -e`, then + `@reboot /usr/local/bin/myscript.sh` (no logging, no ordering) +- Drop `After=`/`Wants=` if networking isn't needed — it'll run earlier + +> **A root systemd service cannot rotate the display** — no `DISPLAY`, no +> `XAUTHORITY`. Use the config-level methods in §6 instead. Same for audio: a +> root service has no audio session, so use `systemctl --user` or target the +> hardware device directly. + +--- + +## 9. File transfer to/from Windows + +**Tailscale is not required.** It creates a private network *across the +internet* — only needed to reach the tablet from outside your home. For a +tablet and PC on the same Wi-Fi it's just another background daemon on a +2 GB machine. + +Lightest option — SSH: + +```bash +sudo apt install -y openssh-server +``` + +Connect from Windows with WinSCP or `scp` in PowerShell. No configuration +beyond the above. + +Samba is only worth it if you want the tablet's folders to appear in Windows +Explorer as a normal network drive. + +--- + +## 10. Quick reference + +```bash +# state +free -h; df -h /; lsblk; swapon --show +cat /etc/os-release +. /etc/os-release; echo $VERSION_CODENAME + +# apt health +sudo dpkg --audit; sudo apt-get check; apt-mark showhold +ls /etc/apt/sources.list.d/ +cat /etc/apt/sources.list.d/ubuntu.sources + +# display +xrandr; xinput list --name-only +~/rotate.sh; xfdesktop --reload + +# audio +aplay -l; pactl list short sinks +aplay /usr/share/sounds/alsa/Front_Center.wav +sudo alsactl store 1 + +# build +mcs -pkg:gtk-sharp-3.0 program.cs MainWindow.cs ArduinoConnection.cs -out:test.exe +mono test.exe +``` \ No newline at end of file