From acaf1747f380d3a20655933e3e71a2b463766774 Mon Sep 17 00:00:00 2001 From: Mathieu Moran Date: Sat, 8 Aug 2026 20:50:45 -0400 Subject: [PATCH] Fix dashcam detection for whole-disk (superfloppy) SD card formats First real-hardware test revealed the connected dashcam's SD card ships factory-formatted with no partition table - lsblk reports it as a bare "disk" with an fstype set directly, never as a child "part". The previous detection logic only matched type=="part", so it silently missed this real device entirely. list_usb_storage_partitions() now also matches whole-disk USB devices that have no children and an fstype set directly on them, in addition to the existing partition-table case. Verified against a fixture built from this dashcam's actual `lsblk -J` output. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- modules/app_dash.py | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/modules/app_dash.py b/modules/app_dash.py index 9c25d0a..3ae3570 100644 --- a/modules/app_dash.py +++ b/modules/app_dash.py @@ -7,12 +7,14 @@ etc. - all common dashcam brands are covered since we just walk the whole filesystem for video extensions instead of assuming a specific folder name), then unmounts it again. -Detection is done via `lsblk`, filtering for partitions whose parent disk is +Detection is done via `lsblk`, filtering for volumes whose parent disk is attached over USB (TRAN == "usb"). This is what actually distinguishes a plugged-in dashcam/USB stick from the Pi's own storage (the boot/root partitions are on the onboard SD card, transport "mmc", never "usb") - so it's safe to run against real hardware without risk of touching the Pi's own filesystem, regardless of which /dev/sdX letter the kernel happens to assign. +Both real partitions and whole-disk "superfloppy" (no partition table) +layouts are matched - some dashcam SD cards ship factory-formatted that way. """ import json import os @@ -32,12 +34,19 @@ DEFAULT_DESTINATION = os.path.join( def list_usb_storage_partitions(): - """Return a list of dicts describing USB-attached storage partitions. + """Return a list of dicts describing USB-attached storage volumes. - Each dict has: path, fstype, label, size, mountpoint. Only partitions - whose parent disk reports TRAN "usb" are included - this is what makes - the detection brand/device-agnostic (no hardcoded /dev/sda) while still + Each dict has: path, fstype, label, size, mountpoint. Only volumes whose + parent disk reports TRAN "usb" are included - this is what makes the + detection brand/device-agnostic (no hardcoded /dev/sda) while still being safe (never matches the Pi's own onboard mmc storage). + + Includes both real partitions (type "part", the common case) *and* + whole-disk USB devices with an `fstype` set directly on them (type + "disk" but no partition table - a "superfloppy" layout with no MBR/GPT). + Several real dashcam SD cards ship formatted this way straight from the + factory - lsblk reports them as a bare "disk" with an fstype, never as a + child "part", so excluding them would silently miss those cameras. """ try: result = subprocess.run( @@ -61,7 +70,12 @@ def list_usb_storage_partitions(): def walk(devices, inherited_tran=None): for device in devices: tran = device.get("tran") or inherited_tran - if device.get("type") == "part" and tran == "usb": + children = device.get("children") or [] + is_partition = device.get("type") == "part" + is_superfloppy_disk = ( + device.get("type") == "disk" and not children and device.get("fstype") + ) + if tran == "usb" and (is_partition or is_superfloppy_disk): partitions.append( { "path": device.get("path"), @@ -71,7 +85,6 @@ def list_usb_storage_partitions(): "mountpoint": device.get("mountpoint"), } ) - children = device.get("children") or [] if children: walk(children, tran)