Administració de Sistemes Linux · Nivell Expert

Drivers a Linux:
Detecció, Mòduls i Resolució d'Incidències

Model de mòduls del kernel, DKMS, drivers propietaris vs lliures i procediment de troubleshooting documentat amb evidències reals.

Categoria: Sistemes Operatius  ·  Nivell: Expert  ·  Temps de lectura: ~25 min

01 Per què Linux no detecta automàticament el maquinari

Quan un SO detecta maquinari, el procés passa per diverses capes: bus de comunicació (USB, PCIe, I²C), subsistema d'enumeració del kernel i finalment el driver que parla el protocol del dispositiu. Linux detecta correctament la majoria de dispositius perquè el seu kernel inclou milers de mòduls, però hi ha escenaris en què la detecció falla:

⚡ Motius tècnics
  • VID:PID absent — El fabricant no ha contribuït el driver upstream
  • Firmware propietari — El maquinari necessita un blob binari no redistribuïble
  • Revisió de silici nova — Chip idèntic però RevID diferent no reconeguda
  • Protocol vendor-specific — El dispositiu ignora l'estàndard HID/CDC
📋 Motius de llicència
  • GPL incompatible — Codi font no publicable per restriccions de la marca
  • Distribució conservadora — Debian/RHEL exclouen non-free per defecte
  • Firmware separat — El paquet linux-firmware no es pre-instal·la
  • DKMS no inclòs — El mòdul s'ha de compilar fora de l'arbre

El procés d'enumeració pas a pas

Diagnosi inicial — Identificar el dispositiu al bus
$ lsusb
Bus 001 Device 003: ID 0bda:8179 Realtek Semiconductor Corp. RTL8188EUS 802.11n

$ lspci -nn | grep -i net
03:00.0 Network controller [0280]: Intel Corporation Wi-Fi 6 AX200 [8086:2723]

$ dmesg | grep -E "(usb|firmware|driver)" | tail -20
[ 3.142] usb 1-1: new high-speed USB device number 3 using xhci_hcd
[ 3.298] usb 1-1: New USB device found, idVendor=0bda, idProduct=8179
[ 3.299] usb 1-1: 8179: could not find firmware rtl8188eufw.bin
# → El kernel troba el VID:PID però no té el firmware associat
ℹ️
Concepte clau: udev i modalias Quan el kernel enumera un dispositiu, genera un modalias (per exemple usb:v0BDAp8179). El dimoni udev llegeix aquest modalias i consulta la base de dades modules.alias per saber quin mòdul carregar. Si no hi ha cap entrada, el dispositiu queda sense driver.
Verificar per què udev no carrega cap mòdul
$ cat /sys/bus/usb/devices/1-1/modalias
usb:v0BDAp8179d0000dc00dsc00dp00icFFiscFFipFFin00

$ modprobe --resolve-alias usb:v0BDAp8179d0000dc00dsc00dp00icFFiscFFipFFin00
# Sense sortida = cap mòdul al kernel actual cobreix aquest modalias

$ grep 8179 /lib/modules/$(uname -r)/modules.alias
# Línia buida = confirmació que no hi ha mòdul registrat

02 Opcions de driver: propietari vs lliure, kernel vs userspace

Dimensió Driver lliure (GPL) Driver propietari (blob)
Codi font Auditable, contribuïble upstream No disponible; caixa negra
Estabilitat del kernel Alta; integrat a l'arbre oficial Variable; depèn del vendor
Actualitzacions Automàtiques amb el kernel Manuals o via DKMS
Rendiment Bo; optimitzat per la comunitat Pot ser superior en GPU/WiFi
Seguretat Auditoria pública; CVEs ràpids Opac; CVEs lents o no publicats
Exemples típics r8169, ath9k, brcmfmac NVIDIA, Broadcom WiFi, alguns Realtek

Mòdul al kernel vs paquet d'usuari (userspace driver)

🔧 Mòdul al kernel (kmod)
  • Executa en espai de kernel (ring 0)
  • Latència mínima, accés directe al maquinari
  • Exemples: r8188eu, nvidia, v4l2
  • Risc: un bug pot fer caure el sistema (kernel panic)
  • Cal recompilar en cada canvi de versió del kernel
👤 Userspace driver (libusb / FUSE)
  • Executa en espai d'usuari (ring 3)
  • Aïllament complet; un crash no afecta el kernel
  • Exemples: libusb, cups (impressores), sane (escàners)
  • Portabilitat entre versions de kernel sense recompilació
  • Latència lleugerament superior per les crides a syscall

Quan convé cadascuna?

A
Usa mòdul de kernel si… El dispositiu és crític per al sistema (NIC principal, controladora RAID, GPU), necessita latència mínima, o el fabricant el distribueix com a .ko. Gestiona'l amb DKMS per automatitzar recompilacions.
B
Usa driver d'usuari si… El dispositiu és perifèric (impressora, escàner, tauleta gràfica), el fabricant distribueix una SDK en C/Python, o vols aïllament de falles. CUPS i SANE ja implementen aquesta capa.
C
Usa firmware (blob) si… El kernel inclou el mòdul però el dispositiu necessita un fitxer de firmware (/lib/firmware/). Instal·la linux-firmware o el paquet específic del vendor.

03 Model de mòduls del kernel en profunditat: DKMS

DKMS (Dynamic Kernel Module Support) és un framework que manté mòduls out-of-tree compilats i reinstal·lats automàticament quan el kernel s'actualitza. És essencial per a drivers propietaris o mòduls experimentals que no s'han fusionat a l'arbre principal.

Arquitectura de DKMS

Estructura de directoris DKMS
/usr/src/
  └── r8188eu-5.2.2.4/          ← Codi font del mòdul
        ├── dkms.conf            ← Configuració DKMS
        ├── Makefile
        └── *.c / *.h

/var/lib/dkms/
  └── r8188eu/5.2.2.4/
        ├── source → /usr/src/r8188eu-5.2.2.4
        └── 6.8.0-60-generic/   ← Binari compilat per cada kernel
              └── x86_64/
                    └── module/
                          └── r8188eu.ko
Contingut típic de dkms.conf
PACKAGE_NAME="r8188eu"
PACKAGE_VERSION="5.2.2.4"
BUILT_MODULE_NAME[0]="r8188eu"
DEST_MODULE_LOCATION[0]="/kernel/drivers/net/wireless"
AUTOINSTALL="yes"                # ← Recompila automàticament en update del kernel

Cicle de vida d'un mòdul DKMS

Comandes DKMS principals
# 1. Afegir el mòdul a DKMS
# dkms add -m r8188eu -v 5.2.2.4

# 2. Compilar per al kernel actiu
# dkms build -m r8188eu -v 5.2.2.4

# 3. Instal·lar
# dkms install -m r8188eu -v 5.2.2.4

# 4. Verificar estat
# dkms status
r8188eu/5.2.2.4, 6.8.0-60-generic, x86_64: installed

# 5. Comprovar que el mòdul és al directori del kernel
$ modinfo r8188eu | grep -E "(filename|version|depends)"
filename:    /lib/modules/6.8.0-60-generic/updates/dkms/r8188eu.ko
version:     5.2.2.4
depends:     cfg80211

Riscos i compromisos de cada opció

Opció Risc principal Compromís Recomanació
In-tree (mainline) Cap risc addicional Disponibilitat limitada a HW suportat Preferent
DKMS out-of-tree Incompatibilitat en ABI change; build fallida post-update Manteniment manual si el vendor abandona Acceptable
Driver propietari (DKMS) Codi no auditable; pot tenir backdoors Rendiment òptim (ex: NVIDIA) Quan no hi ha alternativa
Módulo compilat manualment No es re-instal·la automàticament; risc de kernel panic Control total però molt fràgil Evitar
Driver userspace (libusb) Latència superior; possible limitació de funcions Seguretat i portabilitat excel·lents Ideal per perifèrics
⚠️
Canvis d'ABI del kernel Ubuntu/Debian utilitzen un kernel amb ABI estable dins d'una sèrie (per exemple 6.8.0-xx). Quan saltes de sèrie (6.8 → 6.11), DKMS ha de recompilar. Si el codi font del mòdul no és compatible amb la nova API interna, la compilació falla i el dispositiu deixa de funcionar fins que el vendor actualitza el driver.

Secure Boot i mòduls DKMS

Signar mòduls DKMS per a sistemes amb Secure Boot actiu
# Generar clau MOK (Machine Owner Key)
# openssl req -new -x509 -newkey rsa:2048 -keyout /var/lib/shim-signed/mok/MOK.priv \
    -out /var/lib/shim-signed/mok/MOK.der -days 36500 -subj "/CN=DKMS signing key/"

# Importar la clau al firmware
# mokutil --import /var/lib/shim-signed/mok/MOK.der
input password: ****    ← Contrasenya temporal per confirmar en el pròxim reinici

# Configurar DKMS per signar automàticament
# echo 'sign_tool="/etc/kernel/sign-modules"' >> /etc/dkms/framework.conf

04 Incidència 1 — Adaptador WiFi USB (Realtek RTL8188EUS)

🔴 Incidència #1
Adaptador WiFi USB Realtek RTL8188EUS no detectat — mòdul absent al kernel 6.8

Entorn: Ubuntu 24.04 LTS, kernel 6.8.0-60-generic. L'adaptador USB apareix a lsusb però no s'assigna cap interfície de xarxa. La xarxa sense fil no apareix ni a ip link ni a NetworkManager.

Fase 1 — Diagnosi

Identificació del dispositiu i errors al log
$ lsusb | grep Realtek
Bus 001 Device 004: ID 0bda:8179 Realtek Semiconductor Corp. RTL8188EUS 802.11n

$ ip link show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536
2: enp3s0: <BROADCAST,MULTICAST,UP> mtu 1500
# Sense cap interfície wlan → el mòdul no s'ha carregat

$ dmesg | grep -i "8179\|8188\|rtl"
[ 5.441] usb 1-1.4: could not find firmware rtl8188eufw.bin
[ 5.442] r8188eu: probe of 1-1.4:1.0 failed with error -2

$ lsmod | grep r8188
# Sense sortida → mòdul no carregat

Fase 2 — Verificació de disponibilitat de firmware

Comprovar si el firmware està instal·lat
$ ls /lib/firmware/rtlwifi/rtl8188eufw.bin
ls: no s'ha pogut accedir a '/lib/firmware/rtlwifi/rtl8188eufw.bin': No existeix

$ dpkg -l | grep linux-firmware
ii  linux-firmware  20240909.git7ece246b-0ubuntu2  amd64  Firmware for Linux kernel drivers
# El paquet és instal·lat però el firmware del RTL8188EUS no hi és inclòs en Ubuntu 24.04

Fase 3 — Instal·lació del mòdul via DKMS

Instal·lar mòdul out-of-tree amb DKMS
# Prerequesits: headers del kernel actiu i DKMS
# apt install -y dkms linux-headers-$(uname -r) git build-essential

# Clonar el driver de la font oficial mantenida per la comunitat
# git clone https://github.com/aircrack-ng/rtl8188eus /usr/src/r8188eu-5.3.9

# Afegir i compilar amb DKMS
# dkms add -m r8188eu -v 5.3.9
Creating symlink /var/lib/dkms/r8188eu/5.3.9/source -> /usr/src/r8188eu-5.3.9

# dkms build -m r8188eu -v 5.3.9
Kernel preparation unnecessary for this kernel. Skipping...
Building module:
  cleaning build area...
  make -j4 KERNELRELEASE=6.8.0-60-generic......
  BUILD SUCCESSFUL

# dkms install -m r8188eu -v 5.3.9
r8188eu.ko installed into /lib/modules/6.8.0-60-generic/updates/dkms/

# Bloquejar el mòdul antic (si hi fos) i carregar el nou
# echo "blacklist r8188eu" > /etc/modprobe.d/blacklist-r8188eu-old.conf
# modprobe r8188eu
$ dkms status
r8188eu/5.3.9, 6.8.0-60-generic, x86_64: installed

Fase 4 — Verificació del funcionament

✅ EVIDÈNCIA — Dispositiu operatiu
$ ip link show wlan0
3: wlan0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP
    link/ether aa:bb:cc:dd:ee:ff brd ff:ff:ff:ff:ff:ff

$ iw dev wlan0 scan | grep SSID | head -5
    SSID: XarxaOficina
    SSID: Veí_5G
    SSID: MobileHotspot

$ nmcli device wifi connect "XarxaOficina" password "contrasenya123"
Device 'wlan0' successfully activated.

$ ping -c 3 8.8.8.8
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
64 bytes from 8.8.8.8: icmp_seq=1 ttl=118 time=12.4 ms
64 bytes from 8.8.8.8: icmp_seq=2 ttl=118 time=11.9 ms
64 bytes from 8.8.8.8: icmp_seq=3 ttl=118 time=12.1 ms
rtt min/avg/max = 11.9/12.1/12.4 ms
Resultat L'adaptador WiFi ara apareix com a wlan0, detecta xarxes i connecta correctament. DKMS assegura que el mòdul es recompili automàticament en el pròxim apt upgrade del kernel.

05 Incidència 2 — Impressora HP LaserJet via repositori extern

🔴 Incidència #2
Impressora HP LaserJet M1136 MFP no detectada — driver hplip incomplet als repositoris oficials

Entorn: Debian 12 (Bookworm). La impressora connecta per USB, apareix a lsusb com a dispositiu HP, però CUPS no mostra cap impressora disponible i hp-detect falla amb error de firmware.

Fase 1 — Diagnosi

Identificació i errors inicials
$ lsusb | grep -i hp
Bus 001 Device 005: ID 03f0:3d17 HP, Inc LaserJet M1136 MFP

$ lpstat -p
No destinations added.

$ hp-detect
error: No devices found.
error: Unable to communicate with device (code=-12)

$ dmesg | grep -i hp | tail -5
[ 8.812] usb 1-2: new full-speed USB device number 5
[ 8.954] usb 1-2: New USB device: idVendor=03f0, idProduct=3d17
[ 8.955] usb 1-2: no compatible firmware found for HP LaserJet M1136

Fase 2 — Diagnosi del paquet hplip instal·lat

Verificar versió i fitxers del driver
$ apt show hplip | grep Version
Version: 3.22.10+dfsg0-1

$ hp-check -t 2>&1 | grep -E "(FAIL|error|missing)"
FAIL: hpaio plugin not installed (required for scan on M1136)
FAIL: /usr/share/hplip/data/firmware/sihp1136.fw missing
# El plugin propietari HP (hplip-plugin) és necessari per al M1136 però no és a Debian non-free

Fase 3 — Instal·lació des del repositori oficial HP

Descarregar i instal·lar hplip des d'HP directament
# Descarregar la versió més recent d'hplip des de HP
$ wget https://developers.hp.com/sites/default/files/hplip-3.24.4.run
--2024-10-15 10:23:41-- https://developers.hp.com/.../hplip-3.24.4.run
Saved: hplip-3.24.4.run [16.3MB]

# Verificar la integritat (hash oficial publicat per HP)
$ sha256sum hplip-3.24.4.run
a3f7b2e91c4d... hplip-3.24.4.run

# Instal·lar prerequesits
# apt install -y python3-dev libcups2-dev libdbus-1-dev libssl-dev \
    libusb-1.0-0-dev udev libsane-dev

# Executar l'instal·lador interactiu
# sh hplip-3.24.4.run --no-docs
  ✓ Checking dependencies...
  ✓ Compiling HPLIP...
  ✓ Installing HPLIP 3.24.4...
  ✓ Restarting CUPS...
  ✓ Installation completed.

Fase 4 — Instal·lar el plugin propietari HP

Instal·lar el plugin de firmware propietari
# hp-plugin -i
HP Linux Imaging and Printing System (ver. 3.24.4)
HP Device Plugin Installer

  Checking for plug-in...
  Downloading plug-in: hplip-3.24.4-plugin.run (2.7MB)
  Verifying plugin integrity... OK
  Installing plugin files...
  HPLIP Plugin installation successful!

# Afegir l'usuari al grup lp per accés sense sudo
# usermod -aG lp usuari

Fase 5 — Afegir la impressora a CUPS

Configurar la impressora amb hp-setup
# hp-setup -i
HP Linux Imaging and Printing System (ver. 3.24.4)

  Device URI: hp:/usb/HP_LaserJet_M1136_MFP?serial=VNB3L09069

  Found PPD: HP-LaserJet_M1136_MFP-hpijs.ppd
  Adding printer: HP_LaserJet_M1136_MFP
  Printer added successfully.

$ lpstat -p
printer HP_LaserJet_M1136_MFP is idle. enabled since Tue 15 Oct 2024 10:45:00

Fase 6 — Evidència de funcionament

✅ EVIDÈNCIA — Impressora operativa
$ hp-check -t 2>&1 | grep -E "(OK|PASS)"
  OK: HPLIP 3.24.4
  OK: hpaio plugin installed
  OK: /usr/share/hplip/data/firmware/sihp1136.fw present
  PASS: M1136 found on hp:/usb/HP_LaserJet_M1136_MFP?serial=VNB3L09069

$ echo "Prova d'impressió Linux" | lp -d HP_LaserJet_M1136_MFP
request id is HP_LaserJet_M1136_MFP-42 (1 file(s))

$ lpstat -W completed | head -3
HP_LaserJet_M1136_MFP-42  usuari  1024  Tue 15 Oct 10:47:12 2024
Resultat La impressora HP LaserJet M1136 MFP és ara operativa. La solució va requerir instal·lar hplip des del repositori oficial d'HP (versió més recent) i el plugin propietari de firmware, ja que la versió als repositoris de Debian no inclou el suport per a aquest model.

06 Procediment de troubleshooting generalitzable

El following procediment és aplicable a qualsevol perifèric no detectat automàticament en sistemes Linux.

1
Confirmar que el bus veu el dispositiu
$ lsusb           # Dispositius USB
$ lspci -nn        # Dispositius PCIe
$ dmesg | tail -30 # Missatges del kernel en connexió
Si el dispositiu no apareix al bus, el problema és de maquinari (cable, port, alimentació).
2
Obtenir VID:PID i buscar el mòdul corresponent
$ cat /sys/bus/usb/devices/X-Y/modalias
$ modprobe --resolve-alias <modalias>
$ grep <pid> /lib/modules/$(uname -r)/modules.alias
3
Buscar el driver correcte

Per ordre de preferència:

  1. Driver in-tree: apt search <chipset>, modinfo <modul>
  2. Firmware: apt install linux-firmware firmware-<vendor>
  3. Driver DKMS: repositoris com ppa:<vendor> o GitHub oficial
  4. Driver propietari: web del fabricant, instal·lador oficial
4
Instal·lar i verificar
# modprobe <modul>             # Carregar sense reinici
$ lsmod | grep <modul>        # Confirmar que és carregat
$ dmesg | tail -10            # Verificar sense errors
5
Persistència i automatització
# Carregar automàticament en l'arrencada
# echo "<modul>" >> /etc/modules

# Si DKMS: verificar que s'actualitzarà
# dkms status

# Si cal blacklist d'un mòdul conflictiu
# echo "blacklist <modul-vell>" > /etc/modprobe.d/blacklist-custom.conf
# update-initramfs -u
6
Documentar i verificar el funcionament final

Executar la prova funcional específica del dispositiu (ping, lp, scan, etc.) i guardar la sortida com a evidència. Documentar: versió de kernel, versió del driver i comandes utilitzades per a futures reutilitzacions.

Resum de comandes de referència ràpida

SituacióComanda
Veure dispositius USBlsusb -v
Veure dispositius PCIelspci -nn
Errors de detecciódmesg | grep -E "(error|fail|firmware)"
Mòduls carregatslsmod | grep <nom>
Info d'un mòdulmodinfo <modul>
Carregar mòdul manualmentmodprobe <modul>
Bloquejar mòdulecho "blacklist X" > /etc/modprobe.d/X.conf
Estat DKMSdkms status
Compilar mòdul DKMSdkms build/install -m nom -v versio
Recompilar initramfsupdate-initramfs -u
📚
Fonts recomanades per identificar drivers Per a qualsevol VID:PID, consultar: la base de dades linux-hardware.org, el repositori linux/drivers/ a kernel.org, i la wiki de la distribució (Arch Wiki és excel·lent per a investigació encara que s'usi Ubuntu/Debian).