← paintstorm-distrobox-legacy

Add comprehensive guide for OTD vs Native HID device conflict

1eb459f82629bd36ea46d6e705a0ed56db378429 · Claude · Jan 24, 2026 09:00

Created detailed documentation and diagnostic tools to help users understand
and resolve the device conflict between OpenTabletDriver and native Linux HID support.

New files:
- TABLET-INPUT-GUIDE.md: Complete guide explaining the device conflict
  * Why pressure works without OTD but breaks with OTD
  * Technical explanation of device grabbing and virtual devices
  * Three solution options (native HID, OTD with config, hybrid)
  * Step-by-step instructions for each approach

- test-which-device-active.sh: Interactive test to determine which device
  is actually receiving tablet input events
  * Tests native Huion device
  * Tests OTD virtual device
  * Provides diagnosis and recommendations based on results

- check-which-device-used.sh: Simple xinput event monitor for manual testing

Issue explained:
When otd-daemon runs, it takes exclusive control of /dev/hidraw* devices,
causing native input devices (id=11) to stop receiving data. OTD creates
virtual devices (id=25) instead. Applications like Paintstorm continue
trying to read from the now-dead native device, breaking pressure sensitivity.

Solutions provided:
1. Use native HID (simpler, already works)
2. Use OTD + disable native devices via xinput
3. Hybrid approach with wrapper scripts

+450 · 3 files changed

  • TABLET-INPUT-GUIDE.md +272 −0
  • check-which-device-used.sh +26 −0
  • test-which-device-active.sh +152 −0
diff --git a/TABLET-INPUT-GUIDE.md b/TABLET-INPUT-GUIDE.md
new file mode 100644
index 0000000..fa095a2
--- /dev/null
+++ b/TABLET-INPUT-GUIDE.md
@@ -0,0 +1,272 @@
+# Tablet Input Device Guide - OTD vs Native HID
+
+## Understanding Your Tablet Setup
+
+Your diagnostic shows a **device conflict** between two input systems. This guide explains what's happening and how to fix it.
+
+## Current Situation
+
+You have discovered that:
+- ✅ **Without otd-daemon**: Pressure works perfectly
+- ❌ **With otd-daemon**: Pressure stops working
+
+### Why This Happens
+
+When you look at `xinput list`, you see TWO sets of tablet devices:
+
+```
+1. Native Huion Devices (from kernel HID driver):
+   - HUION Huion Tablet_G930L Pen stylus (id=11)
+   - HUION Huion Tablet_G930L Pen eraser (id=24)
+
+2. OpenTabletDriver Virtual Devices:
+   - OpenTabletDriver Virtual Artist Tablet stylus (id=25)
+   - OpenTabletDriver Virtual Artist Tablet eraser (id=27)
+```
+
+### The Conflict
+
+**Without OTD:**
+```
+Tablet → /dev/hidraw1-3 → Generic Linux HID driver → id=11 → Paintstorm ✓
+```
+
+**With OTD:**
+```
+Tablet → /dev/hidraw1-3 (OTD GRABS EXCLUSIVE ACCESS)
+                ↓
+         otd-daemon → id=25 (virtual device)
+                ↓
+         id=11 (DEAD - no data because OTD owns hidraw)
+                ↓
+         Paintstorm (still trying to read id=11) ✗
+```
+
+When OTD starts, it takes **exclusive control** of the hidraw devices. The native devices (id=11, id=24) remain visible in `xinput list` but **stop receiving data**. Paintstorm is still configured to read from id=11, which is why pressure breaks.
+
+## Solutions
+
+### Option 1: Use Native HID Support (Recommended if it works)
+
+**Pros:**
+- ✅ Already working perfectly
+- ✅ No configuration needed
+- ✅ Simpler setup
+- ✅ Pressure and tilt both work
+
+**Cons:**
+- ❌ No OTD-specific features (custom curves, remapping, etc.)
+- ❌ No GUI configuration (otd-gui)
+
+**How to use:**
+```bash
+# Stop OTD if running
+pkill otd-daemon
+
+# Prevent OTD from auto-starting (if it does)
+# Check your startup applications and disable OTD
+
+# Use Paintstorm normally - pressure will work
+~/paintstorm
+```
+
+### Option 2: Use OpenTabletDriver (if you need its features)
+
+**Pros:**
+- ✅ Custom pressure curves
+- ✅ Pen button remapping
+- ✅ Better tablet area configuration
+- ✅ GUI configuration (otd-gui)
+
+**Cons:**
+- ❌ Requires configuration
+- ❌ Application must use the virtual device
+- ❌ More complex setup
+
+**How to use:**
+
+#### Step 1: Configure Paintstorm to use OTD virtual device
+
+The issue is that Paintstorm is hardcoded or configured to use device id=11 (native Huion), but needs to use id=25 (OTD virtual device).
+
+Unfortunately, **Paintstorm Studio doesn't allow you to choose specific input devices** - it uses whatever X11 provides as the "core pointer" or first available tablet device.
+
+#### Step 2: Disable native Huion devices
+
+Make X11 ignore the native devices and only use OTD virtual devices:
+
+```bash
+# List current devices
+xinput list
+
+# Disable native Huion devices (when OTD is running)
+xinput disable "HUION Huion Tablet_G930L Pen stylus"
+xinput disable "HUION Huion Tablet_G930L Pen eraser"
+
+# Now only OTD virtual devices are active
+# Paintstorm should automatically use them
+```
+
+To make this permanent, create a script:
+
+```bash
+cat > ~/.config/autostart/disable-huion-native.desktop << 'EOF'
+[Desktop Entry]
+Type=Application
+Name=Disable Native Huion Devices
+Exec=sh -c "sleep 5 && xinput disable 'HUION Huion Tablet_G930L Pen stylus' && xinput disable 'HUION Huion Tablet_G930L Pen eraser'"
+Hidden=false
+NoDisplay=false
+X-GNOME-Autostart-enabled=true
+EOF
+```
+
+### Option 3: Hybrid Approach (Advanced)
+
+Only start OTD when you need its features:
+
+```bash
+# Create a wrapper script
+cat > ~/paintstorm-with-otd << 'EOF'
+#!/bin/bash
+# Start OTD
+otd-daemon &
+OTD_PID=$!
+sleep 2
+
+# Disable native devices
+xinput disable "HUION Huion Tablet_G930L Pen stylus" 2>/dev/null || true
+xinput disable "HUION Huion Tablet_G930L Pen eraser" 2>/dev/null || true
+
+# Run Paintstorm
+~/paintstorm
+
+# Cleanup: stop OTD when Paintstorm exits
+kill $OTD_PID 2>/dev/null || true
+EOF
+chmod +x ~/paintstorm-with-otd
+```
+
+Then use:
+- `~/paintstorm` - Native HID (simple, works)
+- `~/paintstorm-with-otd` - With OTD features
+
+## Which Device is Actually Sending Data?
+
+To verify which device is active, use this test:
+
+```bash
+# Monitor input events (move pen while this runs)
+xinput test "HUION Huion Tablet_G930L Pen stylus"
+
+# Or for OTD virtual device:
+xinput test "OpenTabletDriver Virtual Artist Tablet stylus"
+```
+
+If you see output like:
+```
+motion a[0]=123 a[1]=456 a[2]=4567 a[3]=5 a[4]=6
+```
+
+Where `a[2]` changes with pressure, that device is active.
+
+**Test both:**
+```bash
+# Test native device
+echo "Testing native Huion device (id=11)..."
+timeout 5 xinput test 11
+
+# Test OTD virtual device
+echo "Testing OTD virtual device (id=25)..."
+timeout 5 xinput test 25
+```
+
+Move your pen during each test. The one showing events is the active device.
+
+## Recommendation
+
+Based on your situation:
+
+### If you DON'T need OTD features:
+**Just use native HID support** (no otd-daemon):
+```bash
+pkill otd-daemon
+~/paintstorm  # Pressure works perfectly
+```
+
+This is simpler and already works.
+
+### If you DO need OTD features:
+**Disable native devices** when OTD is running:
+```bash
+otd-daemon &
+sleep 2
+xinput disable 11  # Native stylus
+xinput disable 24  # Native eraser
+~/paintstorm  # Now uses OTD virtual devices
+```
+
+## Technical Details
+
+### Why Both Devices Appear in xinput
+
+When you see both sets of devices in `xinput list` (with OTD running), it's misleading:
+
+- **Native devices (id=11, 24)**: Visible in xinput but **INACTIVE** (no data flow)
+- **Virtual devices (id=25, 27)**: Visible and **ACTIVE** (receiving OTD processed data)
+
+The native devices appear because:
+1. The kernel still detects the USB tablet
+2. The HID subsystem still creates input devices
+3. But OTD has grabbed `/dev/hidraw*` with exclusive access
+4. So the native devices get no data
+
+It's like having two phone lines but only one is connected.
+
+### Why wacom/hid_uclogic are Blacklisted
+
+Your `/etc/modprobe.d/99-opentabletdriver.conf` blacklists:
+- `wacom` - Wacom-specific kernel driver
+- `hid_uclogic` - Generic Chinese tablet driver (for Huion/XP-Pen/etc)
+
+This is correct for OTD because:
+1. Those drivers would conflict with OTD
+2. Generic HID support (not blacklisted) still works
+3. Generic HID provides basic pressure/tilt
+4. OTD provides advanced features
+
+You're using the **generic Linux HID driver** (not hid_uclogic), which is why pressure works without OTD.
+
+## Summary
+
+```
+┌─────────────────────────────────────────────────┐
+│ Without OTD (Current working state)             │
+├─────────────────────────────────────────────────┤
+│ Tablet → hidraw → Generic HID → id=11 →         │
+│ Paintstorm ✓ WORKS                              │
+└─────────────────────────────────────────────────┘
+
+┌─────────────────────────────────────────────────┐
+│ With OTD (Current broken state)                 │
+├─────────────────────────────────────────────────┤
+│ Tablet → hidraw → OTD → id=25                   │
+│                       ↘                          │
+│                         id=11 (dead)             │
+│                             ↓                    │
+│                         Paintstorm ✗ BROKEN     │
+└─────────────────────────────────────────────────┘
+
+┌─────────────────────────────────────────────────┐
+│ With OTD + disabled native (FIX)                │
+├─────────────────────────────────────────────────┤
+│ Tablet → hidraw → OTD → id=25 → Paintstorm      │
+│ (id=11 disabled via xinput)     ✓ WORKS         │
+└─────────────────────────────────────────────────┘
+```
+
+**Your choice:**
+- **Simple**: Don't use OTD, just use native HID (already works)
+- **Advanced**: Use OTD + disable native devices via xinput
+
+Choose based on whether you need OTD's features (custom curves, remapping, area config).
diff --git a/check-which-device-used.sh b/check-which-device-used.sh
new file mode 100755
index 0000000..7df2aaa
--- /dev/null
+++ b/check-which-device-used.sh
@@ -0,0 +1,26 @@
+#!/bin/bash
+# Check which input device is actually receiving events
+
+echo "=========================================="
+echo "Input Device Event Monitor"
+echo "=========================================="
+echo ""
+
+echo "Available tablet devices:"
+echo ""
+xinput list | grep -i -E "(huion|opentabletdriver|stylus|eraser)" | nl
+
+echo ""
+echo "Testing which device receives events..."
+echo ""
+echo "Move your pen on the tablet now (10 second test)..."
+echo ""
+
+# Monitor all tablet-related devices for 10 seconds
+timeout 10 xinput test-xi2 --root 2>&1 | grep -A 5 -i -E "(huion|opentabletdriver|pressure|valuator)" || true
+
+echo ""
+echo "Test complete."
+echo ""
+echo "If you saw 'Valuator' or 'pressure' events, the device is active."
+echo "Note which device ID was shown in the output above."
diff --git a/test-which-device-active.sh b/test-which-device-active.sh
new file mode 100755
index 0000000..3e378c0
--- /dev/null
+++ b/test-which-device-active.sh
@@ -0,0 +1,152 @@
+#!/bin/bash
+# Test which tablet device is actually receiving events
+
+RED='\033[0;31m'
+GREEN='\033[0;32m'
+YELLOW='\033[1;33m'
+BLUE='\033[0;34m'
+NC='\033[0m'
+
+echo "=========================================="
+echo "Tablet Device Activity Test"
+echo "=========================================="
+echo ""
+
+# Get device IDs
+NATIVE_STYLUS=$(xinput list | grep -i "HUION.*Pen stylus" | grep -v "Virtual" | grep -o 'id=[0-9]*' | cut -d= -f2)
+NATIVE_ERASER=$(xinput list | grep -i "HUION.*Pen eraser" | grep -v "Virtual" | grep -o 'id=[0-9]*' | cut -d= -f2)
+VIRTUAL_STYLUS=$(xinput list | grep -i "OpenTabletDriver.*stylus" | grep -o 'id=[0-9]*' | cut -d= -f2)
+VIRTUAL_ERASER=$(xinput list | grep -i "OpenTabletDriver.*eraser" | grep -o 'id=[0-9]*' | cut -d= -f2)
+
+echo "Detected devices:"
+if [ -n "$NATIVE_STYLUS" ]; then
+    echo -e "${BLUE}  Native Huion Stylus: id=$NATIVE_STYLUS${NC}"
+else
+    echo -e "${YELLOW}  Native Huion Stylus: NOT FOUND${NC}"
+fi
+
+if [ -n "$VIRTUAL_STYLUS" ]; then
+    echo -e "${BLUE}  OTD Virtual Stylus: id=$VIRTUAL_STYLUS${NC}"
+else
+    echo -e "${YELLOW}  OTD Virtual Stylus: NOT FOUND (otd-daemon not running?)${NC}"
+fi
+
+echo ""
+echo "=========================================="
+echo "Testing Native Huion Device"
+echo "=========================================="
+
+if [ -n "$NATIVE_STYLUS" ]; then
+    echo "Move your pen on the tablet for 5 seconds..."
+    echo ""
+
+    NATIVE_OUTPUT=$(timeout 5 xinput test "$NATIVE_STYLUS" 2>&1 | head -20)
+
+    if echo "$NATIVE_OUTPUT" | grep -q "motion"; then
+        echo -e "${GREEN}✓ Native device is ACTIVE${NC}"
+        echo "  Sample output:"
+        echo "$NATIVE_OUTPUT" | head -5 | sed 's/^/    /'
+        NATIVE_ACTIVE=true
+    else
+        echo -e "${RED}✗ Native device is INACTIVE (no events detected)${NC}"
+        NATIVE_ACTIVE=false
+    fi
+else
+    echo -e "${YELLOW}Skipping (device not found)${NC}"
+    NATIVE_ACTIVE=false
+fi
+
+echo ""
+echo "=========================================="
+echo "Testing OTD Virtual Device"
+echo "=========================================="
+
+if [ -n "$VIRTUAL_STYLUS" ]; then
+    echo "Move your pen on the tablet for 5 seconds..."
+    echo ""
+
+    VIRTUAL_OUTPUT=$(timeout 5 xinput test "$VIRTUAL_STYLUS" 2>&1 | head -20)
+
+    if echo "$VIRTUAL_OUTPUT" | grep -q "motion"; then
+        echo -e "${GREEN}✓ OTD virtual device is ACTIVE${NC}"
+        echo "  Sample output:"
+        echo "$VIRTUAL_OUTPUT" | head -5 | sed 's/^/    /'
+        VIRTUAL_ACTIVE=true
+    else
+        echo -e "${RED}✗ OTD virtual device is INACTIVE (no events detected)${NC}"
+        VIRTUAL_ACTIVE=false
+    fi
+else
+    echo -e "${YELLOW}Skipping (device not found - otd-daemon probably not running)${NC}"
+    VIRTUAL_ACTIVE=false
+fi
+
+echo ""
+echo "=========================================="
+echo "DIAGNOSIS"
+echo "=========================================="
+
+if [ "$NATIVE_ACTIVE" = true ] && [ "$VIRTUAL_ACTIVE" = false ]; then
+    echo -e "${GREEN}Result: Using NATIVE Huion HID driver${NC}"
+    echo ""
+    echo "This means:"
+    echo "  • otd-daemon is NOT running (or not working)"
+    echo "  • Generic Linux HID driver is handling your tablet"
+    echo "  • Paintstorm reads from: HUION Huion Tablet_G930L Pen stylus (id=$NATIVE_STYLUS)"
+    echo "  • This is why pressure works WITHOUT otd-daemon"
+    echo ""
+    echo "Recommendation:"
+    echo "  If pressure works, you don't need OTD unless you want its features"
+    echo "  (custom curves, remapping, etc.)"
+
+elif [ "$NATIVE_ACTIVE" = false ] && [ "$VIRTUAL_ACTIVE" = true ]; then
+    echo -e "${GREEN}Result: Using OpenTabletDriver virtual device${NC}"
+    echo ""
+    echo "This means:"
+    echo "  • otd-daemon IS running"
+    echo "  • OTD has exclusive control of hidraw devices"
+    echo "  • Native device (id=$NATIVE_STYLUS) is inactive"
+    echo "  • Paintstorm should read from: OpenTabletDriver Virtual Artist Tablet stylus (id=$VIRTUAL_STYLUS)"
+    echo ""
+    echo "If pressure doesn't work in Paintstorm:"
+    echo "  Paintstorm is probably still trying to use the native device (id=$NATIVE_STYLUS)"
+    echo "  which is now dead because OTD took over."
+    echo ""
+    echo "Solution:"
+    echo "  xinput disable $NATIVE_STYLUS"
+    echo "  This forces Paintstorm to use the OTD virtual device"
+
+elif [ "$NATIVE_ACTIVE" = true ] && [ "$VIRTUAL_ACTIVE" = true ]; then
+    echo -e "${YELLOW}Result: BOTH devices are active (unusual!)${NC}"
+    echo ""
+    echo "This is unexpected. Usually when OTD runs, it takes exclusive"
+    echo "access to hidraw and the native device stops working."
+    echo ""
+    echo "Possible causes:"
+    echo "  • OTD is running but not grabbing your specific tablet"
+    echo "  • Multiple tablets connected"
+    echo "  • OTD configuration issue"
+
+else
+    echo -e "${RED}Result: NO devices are active${NC}"
+    echo ""
+    echo "This means:"
+    echo "  • Your tablet might not be connected"
+    echo "  • Or you didn't move the pen during the tests"
+    echo ""
+    echo "Try running this script again and make sure to move the pen"
+    echo "when prompted."
+fi
+
+echo ""
+echo "=========================================="
+echo "Current OTD Status"
+echo "=========================================="
+
+if pgrep -x otd-daemon > /dev/null; then
+    echo -e "${GREEN}otd-daemon: RUNNING${NC}"
+else
+    echo -e "${YELLOW}otd-daemon: NOT RUNNING${NC}"
+fi
+
+echo ""