Compare commits

...

10 Commits

Author SHA1 Message Date
Bastian de Byl
da7c837fc0 post: kde plasma performance improvements on arch 2026-01-04 14:23:11 -05:00
Bastian de Byl
4a269c01d8 Merge branch 'main' of github.com:bdebyl/bdebyl-site 2025-12-21 19:17:27 -05:00
Bastian de Byl
d82196bc35 chore: updated btw_win_linux.md guide 2025-12-21 19:17:23 -05:00
Bastian de Byl
96e42a411d added yoga6 fingerprint support post
🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-23 22:54:26 -04:00
Bastian de Byl
2a34727289 added boot-partition-initramfs-bloat post 2025-09-22 23:42:20 -04:00
Bastian de Byl
20c51ebc83 noticket - Makefile updates 2025-01-31 12:34:30 -05:00
Bastian de Byl
dcea5bf679 noticket - updates 2025-01-08 12:35:09 -05:00
Bastian de Byl
67efdf6d41 noticket - s/Same/same/ on bt_win_linux post 2023-10-14 16:47:49 -04:00
Bastian de Byl
51d9ba3390 noticket - markdownlint fixes 2023-10-14 16:45:34 -04:00
Bastian de Byl
5f4c121113 noticket - updated win-linux post for invisible key workaround 2023-10-14 16:42:30 -04:00
29 changed files with 888 additions and 374 deletions

2
.gitignore vendored
View File

@@ -1,5 +1,5 @@
*.lock
flymd* flymd*
public/ public/
resources/ resources/
static/ static/
themes/

3
.gitmodules vendored Normal file
View File

@@ -0,0 +1,3 @@
[submodule "themes/papermod"]
path = themes/papermod
url = git@github.com:adityatelange/hugo-PaperMod.git

105
Makefile
View File

@@ -1,109 +1,32 @@
# This Makefile was originally taken from https://github.com/alimac/alimac.io/ WEBSITE=debyl.io
# Website hostname, used to set:
# - image and container names
# - path to web root (in /tmp directory)
WEB_BUCKET=bdebyl.net
STATIC_BUCKET=bdebyl.static
STATIC_DIR=static
HUGO_IMAGE_NAME=bdebyl/hugo AWS=aws --profile default
HUGO_IMAGE_TAG?=latest
HUGO_IMAGE=$(HUGO_IMAGE_NAME):$(HUGO_IMAGE_TAG)
THUMBR_IMAGE_NAME=bdebyl/thumbr
THUMBR_IMAGE_TAG?=latest
THUMBR_IMAGE?=$(THUMBR_IMAGE_NAME):$(THUMBR_IMAGE_TAG)
AWS_IMAGE_NAME=bdebyl/awscli
AWS_IMAGE_TAG?=latest
AWS_IMAGE=$(AWS_IMAGE_NAME):$(AWS_IMAGE_TAG)
MDLINT_IMAGE_NAME=peterdavehello/markdownlint
MDLINT_IMAGE_TAG?=latest
MDLINT_IMAGE?=$(MDLINT_IMAGE_NAME):$(MDLINT_IMAGE_TAG)
MDLINT_PATH?=content/
# Container Variables
RUN_USER=--user $(shell id -u $$USER):$(shell id -g $$USER)
RUN_VOL=-v $(shell pwd):/src
AWS_ENV=-e "AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID}" -e "AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY}" -e "AWS_DEFAULT_REGION=${AWS_DEFAULT_REGION}"
MOUNT_BUCKET?=1
DOCKER_PORT=-p 1313:1313/tcp
DOCKER_RUN=docker run --rm ${RUN_USER} ${RUN_VOL}
# Look up CloudFront distribution ID based on website alias # Look up CloudFront distribution ID based on website alias
DISTRIBUTION_ID=$(shell docker run --rm ${AWS_ENV} ${AWS_IMAGE} cloudfront list-distributions \ DISTRIBUTION_ID=$(shell ${AWS} cloudfront list-distributions \
--query 'DistributionList.Items[].{id:Id,a:Aliases.Items}[?contains(a,`${WEB_BUCKET}`)].id' \ --query 'DistributionList.Items[].{id:Id,a:Aliases.Items}[?contains(a,`${WEBSITE}`)].id' \
--output text) --output text)
S3_SYNC=s3 sync --sse "AES256" public/ s3://${WEBSITE}
CLOUDFRONT_INVALIDATE=cloudfront create-invalidation --distribution-id ${DISTRIBUTION_ID} --paths '/*'
ifdef DRYRUN # Default target for make (<=3.80)
S3_DRYRUN=--dryrun default:
endif -hugo server
ifdef DELETE .PHONY: default
S3_DELETE=--delete
endif
S3_CACHE_CONTROL?=86400
S3_CMD=s3 sync ${S3_DRYRUN} ${S3_DELETE} --metadata-directive REPLACE --cache-control max-age=${S3_CACHE_CONTROL},public --acl "public-read" --sse "AES256"
S3_CMD_WEB=${S3_CMD} public/ s3://${WEB_BUCKET}
S3_CMD_STATIC=${S3_CMD} static/ s3://${STATIC_BUCKET}
CLOUDFRONT_PATHS?='/*'
CLOUDFRONT_CMD=cloudfront create-invalidation --distribution-id ${DISTRIBUTION_ID} --paths ${CLOUDFRONT_PATHS}
all: build
build: build:
$(DOCKER_RUN) ${HUGO_IMAGE} -hugo build
.PHONY: build .PHONY: build
lint:
$(DOCKER_RUN) -v $$PWD:/md:ro ${MDLINT_IMAGE} markdownlint ${MDLINT_PATH}
.PHONY: lint
static-pull:
if [ ! -d "${STATIC_DIR}/static" ]; then aws s3 sync s3://${STATIC_BUCKET} ${STATIC_DIR}/; fi
.PHONY: static-pull
static-push:
aws ${S3_CMD_STATIC}
.PHONY: static-push
static-images:
@${DOCKER_RUN} ${THUMBR_IMAGE} ${STATIC_DIR}/static/img
.PHONY: static-images
css-push:
aws s3 cp --acl "public-read" --sse "AES256" public/dist/style.css s3://${WEB_BUCKET}/dist/style.css
.PHONY: css-push
run: static-pull
-$(DOCKER_RUN) -it ${DOCKER_PORT} ${HUGO_IMAGE} -D server --bind=0.0.0.0
.PHONY: run
version:
$(DOCKER_RUN) ${HUGO_IMAGE} version
.PHONY: version
new:
$(DOCKER_RUN) ${HUGO_IMAGE} new post/"$(shell read -p 'Post Name (i.e. my_post.md): ' pn; echo $$pn)"
.PHONY: new
clean: clean:
@# Clean up existing generated site rm -rfv public/
rm -rf public/ resources/
.PHONY: clean
static-clean:
if [ -d "${STATIC_DIR}/static" ]; then rm -rfv static/
.PHONY: static-clean
deploy: clean build deploy: clean build
@# Upload files to S3 @# Upload files to S3
@$(DOCKER_RUN) ${AWS_ENV} ${AWS_IMAGE} ${S3_CMD_WEB} ${AWS} ${S3_SYNC}
.PHONY: deploy .PHONY: deploy
cache: cache:
@# Invalidate caches @# Invalidate caches
@$(DOCKER_RUN) ${AWS_ENV} ${AWS_IMAGE} ${CLOUDFRONT_CMD} ${AWS} ${CLOUDFRONT_INVALIDATE}
.PHONY: cache .PHONY: cache

View File

@@ -0,0 +1,39 @@
.thumbnail-container {
width: 100%;
text-align: center;
padding: 10px 0;
}
.thumbnail-container a {
all: unset;
}
.thumbnail {
margin: auto;
padding: .75rem;
text-align: center;
max-width: 80%;
display: inline-block;
}
.thumbnail sub {
font-size: small;
font-style: italic;
}
.thumbnail-gallery {
margin: auto;
text-align: center;
padding-bottom: 2rem;
}
.thumbnail-gallery a {
all: unset;
}
.thumbnail-gallery .thumbnail {
display: inline-block;
margin: .125rem;
padding: .50rem;
width: 42%;
}

View File

@@ -1,12 +1,12 @@
# core # core
baseURL: "https://bdebyl.net/" baseURL: https://debyl.io/
title: "Collection of useful, and useless information" title: debyl.io
theme: "even" theme: papermod
enableEmoji: true
# settings # settings
paginate: 5 defaultContentLanguage: en
defaultContentLanguage: "en" languageCode: en
languageCode: "en"
buildDrafts: false buildDrafts: false
canonifyURLs: true canonifyURLs: true
enableRobotsTXT: true enableRobotsTXT: true
@@ -15,10 +15,17 @@ markup:
goldmark: goldmark:
renderer: renderer:
unsafe: true unsafe: true
highlight:
noClasses: false
# anchorLineNos: true
# codeFences: true
# guessSyntax: true
# lineNos: true
# style: monokai
# google analytics # google analytics
googleAnalytics: "UA-163975086-1" googleAnalytics: UA-163975086-1
googleVerification: "" googleVerification:
# See https://gohugo.io/about/hugo-and-gdpr/ # See https://gohugo.io/about/hugo-and-gdpr/
privacy: privacy:
@@ -30,63 +37,135 @@ privacy:
# https://gohugo.io/content-management/syntax-highlighting/ # https://gohugo.io/content-management/syntax-highlighting/
pygmentsCodefences: true pygmentsCodefences: true
pygmentsCodefencesGuessSyntax: true pygmentsCodefencesGuessSyntax: true
pygmentsOptions: "" pygmentsOptions:
pygmentsUseClasses: true pygmentsUseClasses: true
author:
name: "Bastian de Byl"
sitemap: sitemap:
changefreq: "weekly" changefreq: weekly
filename: "sitemap.xml" filename: sitemap.xml
priority: 0.5 priority: 0.5
menu: outputs:
main: home:
- name: "Home" - HTML
weight: 10 - RSS
identifier: "home" - JSON
url: "/"
- name: "About" languages:
weight: 20 en:
identifier: "about" languageName: English
url: "/about" weight: 1
- name: "Archives" taxonomies:
weight: 30 category: categories
identifier: "archives" tag: tags
url: "/post/" series: series
- name: "Tags" menu:
weight: 40 main:
identifier: "tags" - name: Archive
url: "/tags/" url: archives
weight: 5
- name: Search
url: search/
weight: 10
- name: Tags
url: tags/
weight: 10
params: params:
favicon: "/static/img/favicon.ico" env: production # to enable google analytics, opengraph, twitter-cards and schema.
since: "2017" description: Theme PaperMod - https://github.com/adityatelange/hugo-PaperMod
logoImage: "/static/img/logo.png" author: Bastian de Byl
images: # author: [Me, You] # multiple authors
- "/static/img/logo-prev.png"
logoTitle: "bdebyl"
keywords: ["bastian", "de byl", "bdebyl", "bastian de byl"]
description: "A random assortment of my personal projects."
# paginate of archives, tags and categories ShowAllPagesInArchive: true
archivePaginate: 20 ShowBreadCrumbs: true
# show 'xx Posts In Total' in archive page ShowCodeCopyButtons: true
showArchiveCount: true ShowPageNums: true
# The date format to use; for a list of valid formats, see https://gohugo.io/functions/format/ ShowPostNavLinks: true
dateFormatToUse: "2006-01-02" ShowReadingTime: true
# show word count and read time ShowRssButtonInSectionTermList: true
moreMeta: true ShowShareButtons: true
# show "read more" link on post summary ShowToc: false
readMoreEnabled: false comments: false
postMetaInFooter: true # contain author, lastMod, markdown link, license defaultTheme: dark
linkToMarkDown: true # Only effective when hugo will output .md files. disableSpecial1stPost: false
contentCopyright: '<a rel="license" href="http://creativecommons.org/licenses/by-nc/4.0/"><img alt="Creative Commons License" style="border-width:0" src="https://i.creativecommons.org/l/by-nc/4.0/80x15.png" /></a>' disableThemeToggle: true
displayFullLangName: true
images: [images/papermod-cover.png]
social: profileMode:
a-email: "mailto:bastian@bdebyl.net" enabled: false
g-github: "https://github.com/bdebyl"
m-instagram: "https://instagram.com/bastian.remi" homeInfoParams:
n-gitlab: "https://gitlab.com/bdebyl" Title: >
e-linkedin: "https://www.linkedin.com/in/bastian-de-byl-90171b187" :wave: Welcome
Content: >
I created this site as a way of showcasing my projects, or other general
ideas. Its a sort of engineering portfolio, if you will.
<br/>
<br/>
This is just my personal blog site, feel free to get in touch with me
using the icon links below.
socialIcons:
- name: github
title: Github
url: https://github.com/bdebyl
- name: X
title: Twitter
url: https://x.com/bastiandebyl
- name: email
title: Email
url: mailto:bastian@debyl.io
# label:
# iconSVG: '<svg xmlns=http://www.w3.org/2000/svg height=25 viewBox=0 -960 960 960 fill=currentColor><path d=M320-240h320v-80H320v80Zm0-160h320v-80H320v80ZM240-80q-33 0-56.5-23.5T160-160v-640q0-33 23.5-56.5T240-880h320l240 240v480q0 33-23.5 56.5T720-80H240Zm280-520v-200H240v640h480v-440H520ZM240-800v200-200 640-640Z/></svg>'
# text: Home
# icon: icon.png
# iconHeight: 35
assets:
disableHLJS: true
# favicon: <link / abs url>
# favicon16x16: <link / abs url>
# favicon32x32: <link / abs url>
# apple_touch_icon: <link / abs url>
# safari_pinned_tab: <link / abs url>
# cover:
# hidden: true # hide everywhere but not in structured data
# hiddenInList: true # hide on list pages and home
# hiddenInSingle: true # hide on single page
# fuseOpts:
# isCaseSensitive: false
# shouldSort: true
# location: 0
# distance: 1000
# threshold: 0.4
# minMatchCharLength: 0
# keys: [title, permalink, summary, content]
# privacy:
# vimeo:
# disabled: false
# simple: true
# twitter:
# disabled: false
# enableDNT: true
# simple: true
# instagram:
# disabled: false
# simple: true
# youtube:
# disabled: false
# privacyEnhanced: true
services:
instagram:
disableInlineCSS: true
twitter:
disableInlineCSS: true

View File

@@ -29,7 +29,7 @@ link to a text file containing my full public key is attached.
`70A4 AA02 555D BD55 9189 B4E0 F32B E05E ADAA 54FC`[^2] `70A4 AA02 555D BD55 9189 B4E0 F32B E05E ADAA 54FC`[^2]
{{< sub >}}[**Public Key**](/static/pubkey.txt){{< /sub >}} [**Public Key**](/static/pubkey.txt)
</center> </center>
## Donations ## Donations

6
content/archives.md Normal file
View File

@@ -0,0 +1,6 @@
---
title: "Archive"
layout: "archives"
# url: "/archives"
summary: "archives"
---

View File

@@ -4,8 +4,8 @@ date: 2019-01-16
lastmod: 2019-02-11 lastmod: 2019-02-11
categories: ["Blog"] categories: ["Blog"]
tags: ["photography"] tags: ["photography"]
images: cover:
- "/static/img/aperture-study/f17-f40-comp.jpg" image: /static/img/aperture-study/f17-f40-comp.jpg
--- ---
I found out recently that using the maximum aperture for a lens can have I found out recently that using the maximum aperture for a lens can have
deminishing returns. Simply put: it makes the image look "soft", or otherwise deminishing returns. Simply put: it makes the image look "soft", or otherwise

View File

@@ -27,16 +27,12 @@ better understanding of the tools and methods used.
## Partitioning with `fdisk` ## Partitioning with `fdisk`
{{% admonition warning Warning %}}
This operation will destroy any data on the device, please ensure to back up This operation will destroy any data on the device, please ensure to back up
any data desired prior to this operation! any data desired prior to this operation!
{{% /admonition %}}
{{% admonition info Info %}}
Replace instances of `/dev/sdN` with your actual device name (e.g. `/dev/sda`). Replace instances of `/dev/sdN` with your actual device name (e.g. `/dev/sda`).
References specific to partitions will be stated as such (e.g. `/dev/sdN1`, References specific to partitions will be stated as such (e.g. `/dev/sdN1`,
`/dev/sdN2`) `/dev/sdN2`)
{{% /admonition %}}
1. Remove any existing partitions on the drive: 1. Remove any existing partitions on the drive:

View File

@@ -0,0 +1,120 @@
---
title: "The Case of the Bloated Boot"
date: 2025-09-22
lastmod: 2025-09-22
categories: ["Blog"]
tags: ["linux"]
---
When `sudo mkinitcpio -P` fails because your boot partition is full, you've got
a fun problem. The culprit? That massive fallback initramfs taking up precious
space on a tiny boot partition.
<!--more-->
# The Problem
Picture this: you're dual-booting Linux and running a system update when
suddenly `mkinitcpio` fails to generate the larger fallback image. Your boot
partition is completely stuffed.
```bash
$ df -h /boot
Filesystem Size Used Avail Use% Mounted on
/dev/nvme0n1p1 256M 256M 0 100% /boot
```
**Yikes.** Time to investigate what's eating all that space.
# Damage Assessment
A quick `du -sh` reveals the usual suspects:
```bash
$ du -sh /boot/*
157M /boot/initramfs-linux-fallback.img
52M /boot/initramfs-linux.img
16M /boot/vmlinuz-linux
30M /boot/EFI
```
The fallback initramfs is **three times larger** than the normal one. But why?
# The Autodetect Mystery
The secret lies in one simple flag in `/etc/mkinitcpio.d/linux.preset`:
```bash
fallback_options="-S autodetect"
```
That `-S autodetect` flag skips the autodetect hook, which normally shrinks your
initramfs by only including modules your hardware actually needs. Without it,
mkinitcpio includes **everything**.
## By the Numbers
Here's what that means in practice for me:
| Component | Normal (with autodetect) | Fallback (no autodetect) | Ratio |
| :----------------- | -----------------------: | -----------------------: | ------: |
| **Kernel modules** | 190 modules | 6,319 modules | **33x** |
| **Firmware files** | 711 files | 2,996 files | **4x** |
| **Total size** | 52M | 157M | **3x** |
The fallback image is essentially a universal boot disk that works on _any_
hardware — your laptop, your friend's desktop, that ancient server in the
closet. It includes drivers for RAID controllers you don't have, network cards
from 2003, and GPU firmware for every generation of graphics hardware.
# The Nuclear Option
Since I never use the fallback image anyway (live USB for rescue), the
solution was just to get rid of this:
1. **Remove the fallback image** to free immediate space:
```bash
sudo rm /boot/initramfs-linux-fallback.img
```
2. **Disable future generation** by editing `/etc/mkinitcpio.d/linux.preset`:
```bash
# Change this line:
PRESETS=('default' 'fallback')
# To this:
PRESETS=('default')
```
3. **Test it works**:
```bash
sudo mkinitcpio -P
```
Result: boot partition goes from 100% to 39% usage, and future kernel updates
won't recreate the bloated fallback.
# Why It Matters
The autodetect hook is actually quite clever. On my system with 443MB of total
kernel modules available, it correctly identified that I only need 190 of them
— things like my specific WiFi driver, filesystem modules for ext4 and LVM, and
encryption support for LUKS.
The fallback includes _everything else too_: drivers for hardware I'll never own
(_especially since this is on a laptop_), filesystem support for formats I'll
never use, and network protocols from the dawn of time. It's the digital
equivalent of packing for a trip by bringing your entire garage of tools "just
in case"
# The Takeaway
Unless you're regularly swapping hardware or need guaranteed boot recovery from
the initramfs itself, the fallback image is dead weight. Modern autodetection
works well enough that most people never need it. I've personnally never, ever
used the fallback image and for the context of this laptop probably never will
as a bootable USB is my go-to for any and all boot issues.
For those tight boot partitions in dual-boot setups, disabling fallback
generation is it. Save the space for kernel updates that actually matter :^)
And if you _do_ need recovery? Well, that's what live USBs are for, but you're
welcome to make your own decisions.

View File

@@ -1,7 +1,7 @@
--- ---
title: "Sharing Same Bluetooth device on Windows/Linux dual-boot" title: "Sharing same Bluetooth device on Windows/Linux dual-boot"
date: 2023-10-14 date: 2023-10-14
lastmod: 2023-10-14 lastmod: 2025-12-21
categories: ["Tutorial"] categories: ["Tutorial"]
tags: ["linux","windows","bluetooth"] tags: ["linux","windows","bluetooth"]
contentCopyright: true contentCopyright: true
@@ -9,16 +9,107 @@ hideHeaderAndFooter: false
--- ---
This is a guide written on how to share the same Bluetooth device(s) across Windows and Linux without having to uniquely pair each. This is a guide written on how to share the same Bluetooth device(s) across Windows and Linux without having to uniquely pair each.
<!--more--> <!--more-->
## Steps
## Method 1: Extract Keys from Linux (Recommended)
This method uses `hivexsh` to read the Windows registry directly from Linux without needing to boot into Windows.
### Prerequisites
Install hivex:
```bash
# Arch Linux
sudo pacman -S hivex
# Debian/Ubuntu
sudo apt install libhivex-bin
# Fedora
sudo dnf install hivex
```
### Steps
1. Pair your Bluetooth device(s) with Linux **first**
2. Reboot into Windows, then re-pair the devices with Windows
3. Reboot back to Linux
4. Mount your Windows partition (if not already mounted):
```bash
sudo mount /dev/sdXN /mnt/windows
```
5. Find your Bluetooth adapter MAC address and paired devices:
```bash
ls /var/lib/bluetooth/
# Example output: 24:EB:16:23:5B:94
ls /var/lib/bluetooth/24:EB:16:23:5B:94/
# Example output: EC:66:D1:B1:9A:33 (your device)
```
6. Use `hivexsh` to extract the pairing key from the Windows registry:
```bash
hivexsh /mnt/windows/Windows/System32/config/SYSTEM
```
7. Navigate to the Bluetooth keys (MAC addresses are lowercase, no colons):
```text
cd ControlSet001\Services\BTHPORT\Parameters\Keys
ls
cd 24eb16235b94
lsval
```
Example output:
```text
"ec66d1b19a33"=hex(3):1d,68,ef,88,a8,fa,60,2e,a3,1c,69,2e,61,a4,36,4f
```
8. Convert the key to Linux format (remove commas, uppercase):
```text
1d,68,ef,88,a8,fa,60,2e,a3,1c,69,2e,61,a4,36,4f
→ 1D68EF88A8FA602EA31C692E61A4364F
```
9. Update the Linux Bluetooth info file:
```bash
sudo nano /var/lib/bluetooth/24:EB:16:23:5B:94/EC:66:D1:B1:9A:33/info
```
Replace the `Key=` value under `[LinkKey]` with the converted key.
10. Restart the Bluetooth service:
```bash
sudo systemctl restart bluetooth
```
---
## Method 2: Export Keys from Windows
This method requires exporting the registry keys while booted into Windows.
### Steps
1. Pair your Bluetooth device(s) with Linux **first** 1. Pair your Bluetooth device(s) with Linux **first**
2. Reboot into Windows, then re-pair the devices with Windows 2. Reboot into Windows, then re-pair the devices with Windows
3. Run `regedit` **as Administrator** 3. Run `regedit` **as Administrator**
4. Navigate to: 4. Navigate to:
```
```text
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\BTHPORT\Parameters\Keys HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\BTHPORT\Parameters\Keys
``` ```
If you **do not see any Keys under the tree** then you need to open `regedit` as a system-account user. One way to do this is using the PsExec by [downloading it from Microsoft Sysinternals](https://learn.microsoft.com/en-us/sysinternals/downloads/psexec). Once it is downloaded, you will need to run a command-prompt **as Administrator** and navigate to the location `PsExec` is unzipped and run `PsExec.exe -s -i regedit`. The Bluetooth keys should now be visible.
5. Right-click on `Keys` in the left-hand pane and select `Export`. During the dialog change `Save as type` to `Text files` and that the `Export range` is set to `Selected branch`. Store this somewhere **accessible by both Windows and Linux** -- if a shared drive is unavailable, use a USB drive or cloud-storage. 5. Right-click on `Keys` in the left-hand pane and select `Export`. During the dialog change `Save as type` to `Text files` and that the `Export range` is set to `Selected branch`. Store this somewhere **accessible by both Windows and Linux** -- if a shared drive is unavailable, use a USB drive or cloud-storage.
6. Reboot to Linux 6. Reboot to Linux
7. In a root (e.g. `sudo su`) terminal navigate to `/var/lib/bluetooth` then to the MAC address of your host-system (_there should only be a single sub-directory under `/var/lib/bluetooth`_) 7. In a root (e.g. `sudo su`) terminal navigate to `/var/lib/bluetooth` then to the MAC address of your host-system (_there should only be a single sub-directory under `/var/lib/bluetooth`_)
@@ -26,10 +117,17 @@ This is a guide written on how to share the same Bluetooth device(s) across Wind
9. Open the `info` file, with root privileges, in the text editor of your choice. 9. Open the `info` file, with root privileges, in the text editor of your choice.
10. In another tab/window, using either a text viewer or editor, open the **previously exported Windows registry text file for the device** 10. In another tab/window, using either a text viewer or editor, open the **previously exported Windows registry text file for the device**
11. From the **Windows** file, copy the Bluetooth Key. Example: 11. From the **Windows** file, copy the Bluetooth Key. Example:
```
```text
00000000 31 c0 08 fa 4f 7b d2 4c - 6f e1 7d ba 32 29 a9 a7 1À.ïO{ÒLoá}ºQ)©§ 00000000 31 c0 08 fa 4f 7b d2 4c - 6f e1 7d ba 32 29 a9 a7 1À.ïO{ÒLoá}ºQ)©§
``` ```
_From the above copy `31 c0 .... a9 a7`_ _From the above copy `31 c0 .... a9 a7`_
12. Paste the key from the previous step into the `Key=` portion of the **Linux** Bluetooth `info` file. Make sure to **remove all spaces and change all characters to upper-case (all-caps)**. 12. Paste the key from the previous step into the `Key=` portion of the **Linux** Bluetooth `info` file. Make sure to **remove all spaces, hyphens, and change all characters to upper-case (all-caps)**.
13. Save the `info` file with the changes to complete device sharing. Repeat for any other Bluetooth devices to share. 13. Save the `info` file with the changes to complete device sharing. Repeat for any other Bluetooth devices to share.
14. Restart the Bluetooth service:
```bash
sudo systemctl restart bluetooth
```

View File

@@ -6,8 +6,8 @@ tags: ["emacs", "linux"]
categories: ["Tutorial"] categories: ["Tutorial"]
contentCopyright: true contentCopyright: true
hideHeaderAndFooter: false hideHeaderAndFooter: false
images: cover:
- "/static/img/emacs-clang-libopencm3/header-completion.png" image: /static/img/emacs-clang-libopencm3/header-completion.png
--- ---
With some minor dependencies, it's fairly straightforward in setting up your With some minor dependencies, it's fairly straightforward in setting up your
Emacs workflow to include IntelliSense-like auto-completion! Emacs workflow to include IntelliSense-like auto-completion!
@@ -114,13 +114,11 @@ The above assumes that `libopencm3` is also places within the project
directory directory
{{< /sub >}} {{< /sub >}}
{{< admonition warning Note >}}
There is a strange issue that is encountered with non-working completion for new There is a strange issue that is encountered with non-working completion for new
header include statements. The workaround for this includes running `M-x irony-server-kill`after new header header include statements. The workaround for this includes running `M-x irony-server-kill`after new header
additions to your current working file. Irony's server is clever enough to additions to your current working file. Irony's server is clever enough to
restart itself after a completion request is triggered via `TAB` so this is a restart itself after a completion request is triggered via `TAB` so this is a
fairly uninvolved workaround. fairly uninvolved workaround.
{{< /admonition >}}
## Example ## Example

View File

@@ -92,43 +92,34 @@ this via:
- **ArchLinux:** `sudo update-ca-trust` - **ArchLinux:** `sudo update-ca-trust`
- **Debian/Ubuntu, RHEL:** `sudo update-ca-certificates` - **Debian/Ubuntu, RHEL:** `sudo update-ca-certificates`
{{< admonition tip "CA Path" >}}
On my system the full path to the CA certs is: On my system the full path to the CA certs is:
- `/etc/ca-certificates/extracted/cadir/sks-keyservers.net_CA.pem` - `/etc/ca-certificates/extracted/cadir/sks-keyservers.net_CA.pem`
{{< /admonition >}}
Two following parameters should be added to your `~/.gnupg` configuration files: Two following parameters should be added to your `~/.gnupg` configuration files:
### GnuPG Versions >2.1 ### GnuPG Versions >2.1
{{< admonition note "gpg.conf" >}}
```text ```text
keyserver hkps://hkps.pool.sks-keyservers.net keyserver hkps://hkps.pool.sks-keyservers.net
``` ```
{{< /admonition >}}
{{< admonition note "dirmngr.conf" >}}
```text ```text
hkp-cacert /etc/ca-certificates/path/to/CA.pem hkp-cacert /etc/ca-certificates/path/to/CA.pem
``` ```
{{< /admonition >}}
### GnuPG Versions <2.1 ### GnuPG Versions <2.1
{{< admonition note "gpg.conf" >}}
```text ```text
keyserver hkps://hkps.pool.sks-keyservers.net keyserver hkps://hkps.pool.sks-keyservers.net
keyserver-options ca-cert-file=/path/to/CA/sks-keyservers.netCA.pem keyserver-options ca-cert-file=/path/to/CA/sks-keyservers.netCA.pem
``` ```
{{< /admonition >}}
## *Optional* - Ensure keys refreshed through keyserver ## *Optional* - Ensure keys refreshed through keyserver

View File

@@ -4,8 +4,8 @@ date: 2018-01-11
lastmod: 2019-01-16 lastmod: 2019-01-16
categories: ["Blog"] categories: ["Blog"]
tags: ["electronics"] tags: ["electronics"]
images: cover:
- "/static/img/headphone-fix/IMG_7505.jpg" image: /static/img/headphone-fix/IMG_7505.jpg
--- ---
A colleague offered a pair of Bern Bluetooth drop-in headphones to me fore free, A colleague offered a pair of Bern Bluetooth drop-in headphones to me fore free,
with the catch being: _I had to fix them_ with the catch being: _I had to fix them_
@@ -19,7 +19,7 @@ with the catch being: _I had to fix them_
Past mistakes have taught me to be gentle and patient when it comes to taking Past mistakes have taught me to be gentle and patient when it comes to taking
things apart. This was no exception either. After looking over the unit on each things apart. This was no exception either. After looking over the unit on each
side, I figured the only way *in* was lifting the mesh cover off. So I went at side, I figured the only way _in_ was lifting the mesh cover off. So I went at
it, carefully, with a pair of tweezers. I worked my way around the edge and it, carefully, with a pair of tweezers. I worked my way around the edge and
wedged the mesh upwards. wedged the mesh upwards.
@@ -60,7 +60,7 @@ search of `AIWI TI` (_as shown in the photograph_) resulted
in [the following datasheet](http://www.ti.com/lit/ds/symlink/tpa6132a2.pdf) in [the following datasheet](http://www.ti.com/lit/ds/symlink/tpa6132a2.pdf)
which verified that to be the case. which verified that to be the case.
<center>![Hello](/static/img/headphone-fix/TPA6132A2.png)</center> ![Hello](/static/img/headphone-fix/TPA6132A2.png#center)
**Bingo!** Now knowing the pinout, I could use my trusty multimeter (_a Fluke **Bingo!** Now knowing the pinout, I could use my trusty multimeter (_a Fluke
115_) to test continuity of the circuit from the known-good and the now 115_) to test continuity of the circuit from the known-good and the now

View File

@@ -14,11 +14,9 @@ from WordPress)
<!--more--> <!--more-->
# Disclaimer # Disclaimer
{{< admonition warning "Out of Date" >}}
The information in this article is **out-of-date**. I am, and have been, using my The information in this article is **out-of-date**. I am, and have been, using my
own fork of the [hugo-even-theme](https://gitlab.com/bdebyl/hugo-theme-even) on own fork of the [hugo-even-theme](https://gitlab.com/bdebyl/hugo-theme-even) on
my [GitLab](https://gitlab.com/bdebyl) profile. my [GitLab](https://gitlab.com/bdebyl) profile.
{{< /admonition >}}
--- ---

View File

@@ -0,0 +1,293 @@
---
title: "Taming the KDE Plasma Beast: Desktop Responsiveness on Arch Linux"
date: 2026-01-04
lastmod: 2026-01-04
categories: ["Blog"]
tags: ["linux", "kde", "performance"]
---
When your beefy Ryzen 9 system locks up during a simple `pacman -Syu`, something
is very wrong. Here's how to stop Baloo, ClamAV, and poor IO scheduling from
hijacking your desktop.
<!--more-->
# The Problem
Picture this: you're running system updates on a Ryzen 9 7945HX3D with 62GB of
RAM and dual NVMe drives. DKMS starts compiling the nvidia module and suddenly
your entire desktop freezes. Mouse cursor? Frozen. Keyboard? Unresponsive. The
only option is reaching for the power button.
**This should not happen.** A modern system with this kind of hardware should
handle background compilation without breaking a sweat. Time to investigate.
# The Culprits
After some digging, three major offenders emerged:
## 1. Baloo File Indexer
KDE's file indexer was the worst offender:
```bash
$ balooctl6 status
Total files indexed: 845,512
Files waiting for content indexing: 103,138
Current size of index is 24.27 GiB
```
**Twenty-five gigabytes** of index data, with over 100,000 files still queued.
Worse, checking mounted filesystems revealed the real problem:
```bash
$ mount | grep cifs
//truenas.localdomain/share on /mnt/share type cifs ...
```
Baloo was trying to index a network share. Every file access over the network
was blocking IO and competing with the desktop for resources. Classic.
## 2. ClamAV Daemon
The antivirus daemon was consuming 1.2GB of RAM just sitting there:
```bash
$ systemctl status clamav-daemon
Memory: 1.2G (peak: 2.1G)
```
On Linux, ClamAV is honestly overkill for a desktop system. It's designed for
mail servers and file shares, not personal workstations where you control what
gets executed.
## 3. Wrong IO Scheduler
Both NVMe drives were using the BFQ scheduler:
```bash
$ cat /sys/block/nvme*/queue/scheduler
[bfq]
[bfq]
```
BFQ is great for HDDs and SATA SSDs where the kernel needs to optimize head
movement and queue depth. NVMe drives have their own hardware schedulers with
massive parallel queue support. Adding kernel-level scheduling just creates
overhead.
# The Fixes
## Step 1: Kill Baloo
If you don't use KDE's file search (and let's be honest, most terminal users
don't), just disable it:
```bash
# Disable the indexer
balooctl6 disable
# Delete the bloated database
rm -rf ~/.local/share/baloo
```
The config file at `~/.config/baloofilerc` will now show:
```ini
[Basic Settings]
Indexing-Enabled=false
```
This persists across reboots. Done.
## Step 2: Remove or Throttle ClamAV
> **Security Consideration:** Removing antivirus software is a trade-off
> between performance and security. While Linux desktops are less targeted than
> Windows, threats do exist — especially if you download software from untrusted
> sources, open email attachments, or share files with Windows users. **Proceed
> at your own risk.**
For a personal desktop where you're not scanning incoming mail or shared files,
you have a few options:
### Option A: Remove ClamAV entirely (at your own risk)
```bash
sudo systemctl disable --now clamav-daemon clamav-freshclam
sudo pacman -Rns clamav
```
### Option B: Keep ClamAV but throttle it
If you want to keep real-time protection but prevent it from impacting system
responsiveness, create a systemd override:
```bash
sudo mkdir -p /etc/systemd/system/clamav-daemon.service.d
sudo tee /etc/systemd/system/clamav-daemon.service.d/override.conf << 'EOF'
[Service]
Nice=19
IOSchedulingClass=idle
IOSchedulingPriority=7
CPUSchedulingPolicy=idle
CPUQuota=30%
MemoryMax=1G
EOF
sudo systemctl daemon-reload
sudo systemctl restart clamav-daemon
```
This forces ClamAV to only use idle CPU/IO time and caps its resource usage.
### Option C: Manual scans only
Disable the daemon but keep the package for on-demand scanning:
```bash
sudo systemctl disable --now clamav-daemon clamav-freshclam
# Scan manually when needed:
# clamscan -r /path/to/scan
```
### Alternatives to ClamAV
If you remove ClamAV, consider these complementary security measures:
- **[Firejail](https://wiki.archlinux.org/title/Firejail)** — Sandbox untrusted
applications with minimal effort
- **[AppArmor](https://wiki.archlinux.org/title/AppArmor)** — Mandatory access
control for limiting application capabilities
- **[USBGuard](https://wiki.archlinux.org/title/USBGuard)** — Protect against
rogue USB devices
- **Common sense** — Don't run random binaries from the internet, verify
checksums, use official repositories
For most Linux desktop users who stick to official repos and don't open
suspicious attachments, the risk is manageable. But if you're handling sensitive
data or files from untrusted sources, keep some form of scanning available.
## Step 3: Fix the IO Scheduler
Create a udev rule to set the correct scheduler per drive type:
```bash
sudo tee /etc/udev/rules.d/60-ioschedulers.rules << 'EOF'
# NVMe drives have hardware schedulers - use none
ACTION=="add|change", KERNEL=="nvme[0-9]*n[0-9]*", ATTR{queue/scheduler}="none"
# HDDs benefit from BFQ
ACTION=="add|change", KERNEL=="sd[a-z]", ATTR{queue/rotational}=="1", ATTR{queue/scheduler}="bfq"
# SATA SSDs - none is fine
ACTION=="add|change", KERNEL=="sd[a-z]", ATTR{queue/rotational}=="0", ATTR{queue/scheduler}="none"
EOF
# Apply immediately
echo none | sudo tee /sys/block/nvme*/queue/scheduler
```
## Step 4: Install ananicy-cpp
This is the real game-changer. [Ananicy-cpp](https://gitlab.com/ananicy-cpp/ananicy-cpp)
automatically adjusts process priorities based on what's running:
```bash
sudo pacman -S ananicy-cpp
yay -S cachyos-ananicy-rules-git # Community rules
sudo systemctl enable --now ananicy-cpp
```
Now add custom rules for package management and compilation:
```bash
sudo tee /etc/ananicy.d/package-managers.rules << 'EOF'
# Package managers and compilers - lowest priority
{"name": "pacman", "type": "BG_CPUIO"}
{"name": "yay", "type": "BG_CPUIO"}
{"name": "makepkg", "type": "BG_CPUIO"}
{"name": "dkms", "type": "BG_CPUIO"}
{"name": "mkinitcpio", "type": "BG_CPUIO"}
{"name": "gcc", "type": "BG_CPUIO"}
{"name": "cc1", "type": "BG_CPUIO"}
{"name": "cc1plus", "type": "BG_CPUIO"}
{"name": "rustc", "type": "BG_CPUIO"}
{"name": "cargo", "type": "BG_CPUIO"}
{"name": "ninja", "type": "BG_CPUIO"}
{"name": "make", "type": "BG_CPUIO"}
EOF
```
The `BG_CPUIO` type sets `nice=16`, `ioclass=idle`, and `sched=idle`. These
processes will only get CPU and disk time when nothing else needs it.
## Step 5: Tune VM Dirty Page Handling
The kernel's default dirty page settings are tuned for servers, not desktops.
With 62GB of RAM, the defaults would allow gigabytes of dirty pages to
accumulate before flushing — causing massive IO storms that freeze everything.
```bash
sudo tee /etc/sysctl.d/99-desktop-responsiveness.conf << 'EOF'
# Use absolute byte limits instead of percentages
vm.dirty_ratio = 0
vm.dirty_background_ratio = 0
# Start background writeback at 256MB
vm.dirty_background_bytes = 268435456
# Force sync at 1GB max
vm.dirty_bytes = 1073741824
# Flush dirty pages faster
vm.dirty_expire_centisecs = 1000
vm.dirty_writeback_centisecs = 100
# Keep 256MB always free
vm.min_free_kbytes = 262144
# Desktop-friendly swappiness
vm.swappiness = 10
vm.vfs_cache_pressure = 50
EOF
sudo sysctl --system
```
# The Results
| Before | After |
|:-------|:------|
| System freezes during updates | Desktop stays responsive |
| 25GB Baloo database | 0 bytes |
| 1.2GB ClamAV RAM usage | 0 bytes |
| BFQ overhead on NVMe | Direct hardware scheduling |
| Compilation starves desktop | Compilation yields to UI |
DKMS can now compile nvidia modules while I continue working. Package updates
run in the background without the mouse cursor freezing. The system finally
behaves like it should on modern hardware.
# Diagnostic Commands
When things go wrong, these help identify the culprit:
```bash
# What's causing IO wait?
iotop -oPa
# System IO-bound?
vmstat 1 5
# Processes stuck in disk wait (D state)?
ps auxf | grep " D "
# Current dirty page status
grep -E "^(Dirty|Writeback):" /proc/meminfo
```
# The Takeaway
A powerful system shouldn't freeze during routine operations. The defaults in
most Linux distributions are tuned for servers or general compatibility, not
desktop responsiveness. A few targeted tweaks — killing unnecessary indexers,
fixing IO schedulers, and prioritizing interactive processes — make all the
difference.
No more hard resets during system updates :^)

View File

@@ -1,154 +0,0 @@
---
title: "Installing LineageOS Unofficial on Pixel 3a"
date: 2020-07-13
lastmod: 2020-07-13
draft: false
tags: ["android", "security", "hacking"]
categories: ["Tutorial"]
contentCopyright: true
hideHeaderAndFooter: false
images:
- "/static/img/lineageos-pixel3a/lineage-settings.png"
---
{{< admonition warning "Out of Date" >}}
This guide is now out of date since LineageOS officially supports the Pixel 3a,
see more here: <https://wiki.lineageos.org/devices/sargo/install>
{{< /admonition >}}
In this post I aim to highlight my findings in deciding to go through the
process of installing LineageOS on my Pixel 3a. Currently, LineageOS does not
officially support the Pixel 3a. However, InvisibleK (Dan Pasanen) does host
updated versions of his unofficial LineageOS build for the Pixel 3a complete
with a custom recovery to utilize for this purpose!
<!--more-->
{{< thumbgallery >}}
{{< thumb src="/static/img/lineageos-pixel3a/lineage-settings.png"
alt="Screenshot showing the LineageOS version and other LineageOS settings on the Pixel 3a" >}}
{{< thumb src="/static/img/lineageos-pixel3a/lineage-trust.png"
alt="Screenshot showing the LineageOS Trust feature" >}}
{{< /thumbgallery >}}
# Thank You
Before going on any further, I'd like to take a moment to give my sincere thanks
to InvisibleK (Dan Pasanen). Having to set up the entire custom build for Pixel
3a of LineageOS myself would add far more overhead in the overall simple task in
trying to get LineageOS to work on a Pixel 3a!
[**tl;dr**](#flash-custom-recovery)
# Preface
There are plenty of guides out there on how to install and set up ADB and
Fastboot on your host machine. For me, on Arch Linux, this was as simple as
running `pacman -S android-tools`. However, should you be on MacOS or Windows
you may have to find resources on how to go about this. I do not intend to go
over this here -- _sorry_
Additionally, this _guide_ also assumes the reader has some familiarity with ADB
and/or Fastboot.
# Source Files
If you, the reader, know what you're doing and simply just require the files
for your Pixel 3a they can be found here:
- <https://updater.invisiblek.org/sargo>
# Installation
{{< admonition warning "Warning!" >}}
If it isn't abundantly clear by now, be aware that you **will be destroying all
the data currently on your Pixel 3a** in the process of installing LineageOS on
your device! Stop now and back up any files, 2FA codes, or other prior to
proceeding.
{{< /admonition >}}
## Note about TWRP
As of writing this, TWRP[^1] (_a custom recovery commonly used in custom OS
installation_) does not support Android 10. This would have been the preferred
for a custom recovery, though not strictly required. Since we will be installing
LineageOS 17.1 for Android 10 we cannot use TWRP.
## Flash to Stock
Google is kind enough to provide a variety of versions of the stock images for
the Pixel devices. In my process of installing LineageOS, as it will be on
Android 10, I made sure to flash to the latest stock version of Pixel 3a Android
10. Do note that the versions are listed in reverse order, with the latest being
found in the bottom-most row.
- <https://developers.google.com/android/images>
Additionally, Google provides a helper script `flash-all` that I highly
recommend running as-is to flash your Pixel 3a to stock. This can take a few
minutes to complete.
## Flash Custom Recovery
Using InvisibleK's build page, you'll find the required custom recovery image
for flashing found at the bottom of the list of zip files marked with a lone
"download" link.
Flash it via the following steps:
1. Reboot to recovery
```bash
adb reboot bootloader
```
1. Unlock the bootloader if the 'Status' is locked:
```bash
fastboot flashing unlock
```
1. Flash the custom recovery (_make sure to replace `N` with the version you
downloaded, mine was '4'_)
```bash
fastboot flash boot sargo-recovery-eng-N.img
```
1. Boot the custom recovery either by re-entering recovery mode or fastboot --
make sure to wait for it to enter Android Recovery after
```bash
fastboot boot sargo-recovery-eng-N.img
```
## Install LineageOS
Now that the custom recovery is set up and booted into, we're ready to install LineageOS!
1. **Important!** Once in recovery, ensure to `Wipe data/factory reset` prior to
proceeding.
1. Select `Apply update from ADB`
1. ADB Sideload the version, if not latest, of LineageOS you want for your Pixel
3a
```bash
adb sideload lineage-17.1-2020517-UNOFFICIAL-sargo.zip
```
1. Wait for installation to complete then select 'Reboot system now' from the
recovery menu
1. **Enjoy LineageOS!**
## Verification
Once in LineageOS, you can browse the settings to verify the installation and
set up Trust the preferred way. Personally, I chose to leave the defaults.
# Bugs / Issues
I plan to keep this list of bugs and issues I discover up to date, but this is
what I have encountered so far:
- WiFi calling does not seem to work
[^1]: [Team Win Recovery Project](https://twrp.me/)

View File

@@ -67,10 +67,8 @@ It may be worth mentioning, to folks less familiar with `awk`, that the
being piped into `sha1sum`. I discovered incorrect `sha1sum` outputs **without** being piped into `sha1sum`. I discovered incorrect `sha1sum` outputs **without**
`FNR==1` resulting in a useless password check! `FNR==1` resulting in a useless password check!
{{< admonition note Note >}}
`IFS=` would not have fixed the above newline issue, as the problem stems `IFS=` would not have fixed the above newline issue, as the problem stems
from the output of `pass "$p"` and **not** the filenames. from the output of `pass "$p"` and **not** the filenames.
{{< /admonition >}}
That takes care of gathering our passwords, but we'll revisit this again in the That takes care of gathering our passwords, but we'll revisit this again in the
next part. next part.
@@ -106,7 +104,7 @@ getpws()
} }
``` ```
This accomplishes our *first goal* of checking duplicate passwords -- This accomplishes our _first goal_ of checking duplicate passwords --
**hooray!** **hooray!**
# Passwortstärke # Passwortstärke
@@ -117,10 +115,9 @@ it's weak (_i.e. "Exists in attack dictionary", "Too short", etc._) was to use
well-documented or fully-fledged application to fully determine password well-documented or fully-fledged application to fully determine password
strength though for my purposes it will be good enough (_I don't care to write strength though for my purposes it will be good enough (_I don't care to write
my own version of this, yet.._). my own version of this, yet.._).
{{< admonition note Note >}}
I made this part of the script **optional**, as not every user would want to I made this part of the script **optional**, as not every user would want to
install `cracklib` on their system. install `cracklib` on their system.
{{< /admonition >}}
This addition was made in the following order: This addition was made in the following order:

View File

@@ -6,8 +6,8 @@ tags: ["libopencm3", "stm32", "tutorial"]
categories: ["Tutorial"] categories: ["Tutorial"]
contentCopyright: true contentCopyright: true
hideHeaderAndFooter: false hideHeaderAndFooter: false
images: cover:
- "/static/img/stm32-examples/part0/stm32-basic-gpio-leds.jpeg" image: /static/img/stm32-examples/part0/stm32-basic-gpio-leds.jpeg
--- ---
One of the simplest projects to get started with the STM32 microcontroller One of the simplest projects to get started with the STM32 microcontroller
series: turn on the lights! series: turn on the lights!
@@ -17,21 +17,12 @@ series: turn on the lights!
{{< thumb src="/static/img/stm32-examples/part0/stm32-basic-gpio-leds.jpeg" {{< thumb src="/static/img/stm32-examples/part0/stm32-basic-gpio-leds.jpeg"
alt="Photo of STM32 discovery board with illuminated green and blue LEDs" >}} alt="Photo of STM32 discovery board with illuminated green and blue LEDs" >}}
{{< admonition warning "Windows Users" >}}
This series of write-ups assumes the reader is on a Linux operating
system. Windows users _can_ utilize the [**Windows Subsystems for
Linux**](https://docs.microsoft.com/en-us/windows/wsl/install-win10) though your
mileage may vary!
{{< /admonition >}}
# Straight to the Chase # Straight to the Chase
For those that want to cut to the chase and save time, here is the full source For those that want to cut to the chase and save time, here is the full source
code with friendly names to get you started: code with friendly names to get you started:
{{< admonition note "Source Code" true >}}
```C ```C
#include <libopencm3/stm32/gpio.h> #include <libopencm3/stm32/gpio.h>
#include <libopencm3/stm32/rcc.h> #include <libopencm3/stm32/rcc.h>
@@ -50,8 +41,6 @@ int main(void) {
} }
``` ```
{{< /admonition >}}
# Getting Started with libopencm3 # Getting Started with libopencm3
[libopencm3](https://github.com/libopencm3/libopencm3) is a very powerful, [libopencm3](https://github.com/libopencm3/libopencm3) is a very powerful,
@@ -127,11 +116,9 @@ Makefile's variables of things you may want to change:
# Explanation # Explanation
{{< admonition info "Naming Convention" >}}
As a note to the reader: below I will not refer to the GPIO port or pins using As a note to the reader: below I will not refer to the GPIO port or pins using
the `#define` friendly names from above. This is purely for the sake the `#define` friendly names from above. This is purely for the sake
of clarity in hopes of avoiding confusion. of clarity in hopes of avoiding confusion.
{{< /admonition >}}
Although the source code is fairly simple, lets dive into it at least Although the source code is fairly simple, lets dive into it at least
_somewhat_. _somewhat_.

View File

@@ -6,8 +6,8 @@ tags: ["libopencm3", "stm32", "tutorial"]
categories: ["Tutorial"] categories: ["Tutorial"]
contentCopyright: true contentCopyright: true
hideHeaderAndFooter: false hideHeaderAndFooter: false
images: cover:
- "/static/img/stm32-examples/part1/blinky.gif" image: /static/img/stm32-examples/part1/blinky.gif
--- ---
After having reviewed [**Part 0**](/post/stm32-part0) of this series, we can now After having reviewed [**Part 0**](/post/stm32-part0) of this series, we can now
explore controlling GPIO with the hardware timers! Other tutorials have used the explore controlling GPIO with the hardware timers! Other tutorials have used the
@@ -26,8 +26,6 @@ timers and their associated GPIO ports with Alternate Function modes.
For those that want to cut to the chase and save time, here is the full source For those that want to cut to the chase and save time, here is the full source
code with friendly names to get you started: code with friendly names to get you started:
{{< admonition note "Source Code" true >}}
```C ```C
#include <libopencm3/stm32/gpio.h> #include <libopencm3/stm32/gpio.h>
#include <libopencm3/stm32/rcc.h> #include <libopencm3/stm32/rcc.h>
@@ -79,8 +77,6 @@ int main(void) {
} }
``` ```
{{< /admonition >}}
# Set up the GPIO # Set up the GPIO
Assuming the reader is either familiar with GPIO setup for the STM32F0, or has Assuming the reader is either familiar with GPIO setup for the STM32F0, or has
@@ -107,10 +103,8 @@ For accomplishing this, a few things need to happen:
1. The desired GPIO pins need to be set to `GPIO_MODE_AF` in `gpio_mode_setup()` 1. The desired GPIO pins need to be set to `GPIO_MODE_AF` in `gpio_mode_setup()`
1. The alternate function mode number `GPIO_AFx` has to be set for the pins using `gpio_set_af()` 1. The alternate function mode number `GPIO_AFx` has to be set for the pins using `gpio_set_af()`
{{< admonition warning "Note for Different STM32Fx Microcontrollers" >}}
Review the datasheet for the specific **STM32Fx** microcontroller being Review the datasheet for the specific **STM32Fx** microcontroller being
programmed, as the Alternate Function mappings may be *significantly* different! programmed, as the Alternate Function mappings may be _significantly_ different!
{{< /admonition >}}
## GPIO Alternate Function Setup ## GPIO Alternate Function Setup

View File

@@ -4,8 +4,8 @@ date: 2019-02-28
lastmod: 2019-02-28 lastmod: 2019-02-28
categories: ["Blog"] categories: ["Blog"]
tags: ["electronics"] tags: ["electronics"]
images: cover:
- "/static/img/thinkpad-usb-fix/DSC04781.jpg" image: /static/img/thinkpad-usb-fix/DSC04781.jpg
--- ---
From the moment that I first had my (_used_) ThinkPad X220, the bottom-right USB From the moment that I first had my (_used_) ThinkPad X220, the bottom-right USB
port nearest to the SD card reader had been broken. The pad (_or bolster_) was port nearest to the SD card reader had been broken. The pad (_or bolster_) was

View File

@@ -13,10 +13,8 @@ is done!
<!--more--> <!--more-->
{{< admonition info Info >}}
If the reader is unfamiliar with OpenPGP, it's suggested to check out the prior If the reader is unfamiliar with OpenPGP, it's suggested to check out the prior
write-up on this blog: [**OpenPGP Best Practices (and Git)**](/post/gpg_best_practices_and_git/) write-up on this blog: [**OpenPGP Best Practices (and Git)**](/post/gpg_best_practices_and_git/)
{{< /admonition >}}
# Importing Secret Keys # Importing Secret Keys
@@ -229,4 +227,4 @@ gpg --armor --export-secret-keys YOUREMAILADDRESS | gpg --armor --symmetric --ou
Import it in OpenKeychain (_may require deletion in OpenKeychain first -- make Import it in OpenKeychain (_may require deletion in OpenKeychain first -- make
sure **not to revoke and delete!**_) and we're done! sure **not to revoke and delete!**_) and we're done!
[^1]: https://guardianproject.info/archive/luks/ [^1]: [guardianproject.info/archive/luks/](https://guardianproject.info/archive/luks/)

View File

@@ -0,0 +1,112 @@
---
title: "Fingerprint Support on Lenovo Yoga 6 with Arch Linux"
date: 2025-09-23
lastmod: 2025-09-23
categories: ["Blog"]
tags: ["linux", "archlinux", "hardware"]
---
Got a Lenovo Yoga 6 2-in-1 and frustrated that your fingerprint reader isn't working on Arch Linux? You're not alone. The standard fprintd package doesn't include the necessary firmware for this laptop's Synaptics sensor.
<!--more-->
# The Problem
The Lenovo Yoga 6 2-in-1 laptop comes with a Synaptics fingerprint sensor that requires proprietary firmware not included in the standard fprintd package. Without this firmware, fprintd can't communicate with the sensor, leaving you with a non-functional fingerprint reader.
# The Solution
The AUR package `libfprint-2-tod1-synatudor-git` provides the necessary Touch-On-Display (TOD) driver and firmware for Synaptics sensors, including the one in the Yoga 6.
## Installation Steps
1. **Install the AUR package:**
```bash
yay -S libfprint-2-tod1-synatudor-git
```
Or if you're using paru:
```bash
paru -S libfprint-2-tod1-synatudor-git
```
2. **Install fprintd (if not already installed):**
```bash
sudo pacman -S fprintd
```
3. **Enable and start the fprintd service:**
```bash
sudo systemctl enable --now fprintd.service
```
4. **Verify the fingerprint reader is detected:**
```bash
fprintd-list-devices
```
You should see output listing your Synaptics sensor.
## Setting Up Fingerprints
Once the driver is installed and working:
1. **Enroll your fingerprints:**
```bash
fprintd-enroll
```
Follow the prompts to scan your finger multiple times.
2. **Test authentication:**
```bash
fprintd-verify
```
## PAM Integration
To use fingerprint authentication for system login and authentication, add fingerprint support to the appropriate PAM configuration files:
1. **For system login**, add to `/etc/pam.d/system-local-login`:
```
auth sufficient pam_fprintd.so
```
2. **For display managers**, the configuration may already exist:
- SDDM: `/etc/pam.d/sddm` should have `auth sufficient pam_fprintd.so`
- LightDM: `/etc/pam.d/lightdm` should have `auth sufficient pam_fprintd.so`
3. **For sudo authentication**, add to `/etc/pam.d/sudo`:
```
auth sufficient pam_fprintd.so
```
The `sufficient` directive means fingerprint authentication will be attempted first, falling back to password if fingerprint fails.
# Why This Works
The `libfprint-2-tod1-synatudor-git` package provides:
- The proprietary Synaptics firmware blob required by the sensor
- The TOD (Touch-On-Display) driver implementation for libfprint2
- Proper USB device ID mappings for various Synaptics sensors
Without this package, fprintd only has access to open-source drivers that don't support the proprietary communication protocol used by many modern fingerprint sensors.
# Troubleshooting
If the fingerprint reader still doesn't work:
1. **Check USB device detection:**
```bash
lsusb | grep -i synaptics
```
2. **Review fprintd logs:**
```bash
journalctl -u fprintd -b
```
3. **Ensure secure boot is disabled** - some proprietary firmware doesn't load with secure boot enabled.
4. **Reboot after installation** - the driver may need a fresh start to properly initialize.
# Final Notes
While it's unfortunate that proprietary firmware is required, this AUR package makes fingerprint authentication possible on the Yoga 6 and similar laptops with Synaptics sensors. The convenience of fingerprint login, especially on a 2-in-1 device, is worth the extra installation step.

5
content/search.md Normal file
View File

@@ -0,0 +1,5 @@
---
title: "Search"
placeholder: Enter text to search..
layout: "search"
---

View File

@@ -0,0 +1,11 @@
{{- $src := .Get "src" }}
{{- $sub := .Get "sub" -}}
{{- $alt := .Get "alt" -}}
<div class="thumbnail-container">
<a href="{{ $src }}"><div class="thumbnail">
<center><img src="{{ $src }}" alt="{{ $alt }}" title="{{ $alt }}"></center>
{{- if $sub -}}
<sub>{{ $sub }}</sub>
{{- end -}}
</div></a>
</div>

View File

@@ -0,0 +1 @@
<center><sub><i>{{ .Inner | markdownify }}</i></sub></center>

View File

@@ -0,0 +1,15 @@
{{- $src := .Get "src" }}
{{- $sub := .Get "sub" -}}
{{- $alt := .Get "alt" -}}
{{ if not .Parent }}
<div class="thumbnail-container">
{{ end }}
<a href="{{ $src }}"><div class="thumbnail">
<center><img src="{{ $src | replaceRE "^(.*static/img)/(.*)$" "$1/w_500/$2" }}" alt="{{ $alt }}" title="{{ $alt }}"></center>
{{- if $sub -}}
<center><sub>{{ $sub }}</sub></center>
{{- end -}}
</div></a>
{{ if not .Parent }}
</div>
{{ end }}

View File

@@ -0,0 +1,3 @@
<div class="thumbnail-gallery">
{{.Inner}}
</div>

1
themes/papermod Submodule

Submodule themes/papermod added at 9f1f414be8