Come assegnare il driver USB al dispositivo


30

Questa domanda è duplice:

Innanzitutto, come si fa a staccare manualmente un driver da un dispositivo USB e collegarne uno diverso? Ad esempio, ho un dispositivo che, quando collegato, utilizza automaticamente il driver di archiviazione USB.

uscita usbview

Vendor Id: xxxx
Product Id: xxxx
...
    Number of Interfaces: 2
    Interface Number: 0
        Name: usb-storage
        Number of Endpoints: 2
        ...
    Interface Number: 1
        Name: (none)
        Number of Endpoints: 2
        ...

Non voglio utilizzare il driver di archiviazione USB, quindi nella mia applicazione utilizzo la libusblibreria per staccare il driver di archiviazione USB e quindi rivendico l'interfaccia. Posso quindi inviare dati da e verso le applicazioni in esecuzione sul mio dispositivo USB e sul mio sistema Linux host.

Come si scollega manualmente un driver al di fuori di un'applicazione?


In secondo luogo, come posso assegnare automaticamente il driver da collegare al plug-in del dispositivo? Al momento ho una configurazione della regola udev per impostare automaticamente le autorizzazioni del dispositivo:

SUBSYSTEM=="usb", ATTR{idVendor}=="xxxx", MODE="0666"

Posso usare le regole udev per assegnare i driver a interfacce specifiche sul dispositivo USB? Ad esempio, se volevo che il modulo usbnet venisse utilizzato automaticamente sull'interfaccia 0 anziché su memoria USB, è possibile in udev?


1
Se parte del problema sta caricando il modulo giusto, vedi Webcam su Angström
Gilles 'SO- smetti di essere malvagio'

1
Hai bisogno di tutto il modulo di archiviazione USB? perché se no puoi metterlo in una lista nera e non si carica affatto.
Hanan N.

@Gilles, sono riuscito a caricare LKM. La mia domanda è: come collegarla manualmente e automaticamente al dispositivo?
Linsek,

@Hanan, al momento non ho alcuna utilità per il modulo di archiviazione USB. Potrei finire per doverlo inserire nella blacklist per collegare automaticamente il modulo corretto, ma prima devo sapere come collegare quello usbnet.
Linsek,

1
Il modulo @njozwiak usbnetnon si caricherà automaticamente, perché non ha informazioni sull'hardware, che può usarlo. Prova a trovare il driver corretto e usa, ad esempio modinfo kalmia,. Nelle aliasrighe vedrai l'ID fornitore xxxx e l'ID prodotto yyyy as usb:vxxxxpyyyy. Oppure puoi modificare il file /lib/modules/kernel_version/modules.usbmap e per il tuo HW puoi eliminare la linea, dove è per te l'archiviazione USB del modulo HW o cambiare usbstorage con il driver di rete appropriato. Ma dopo depmod -aquesto cambiamento andrà via ...
Jan Marek,

Risposte:


20

Per la prima parte della domanda, ho cercato e non sono riuscito a trovare un modo migliore per staccare un driver USB rispetto a quello che stai già facendo con libusb.

Per quanto riguarda la seconda parte della domanda, udev può reagire al caricamento del driver, ma non forzare l' assegnazione di un driver specifico a un dispositivo.

Ogni driver nel kernel Linux è responsabile di uno o più dispositivi. Il driver stesso sceglie quali dispositivi supporta. Lo fa a livello di codice, cioè controllando il fornitore del dispositivo e l'ID del prodotto o, se questi non sono disponibili (ad esempio un vecchio dispositivo), eseguendo alcune euristiche di rilevamento automatico e controlli di integrità. Una volta che il driver è sicuro di aver trovato un dispositivo che supporta, si attacca ad esso. In breve, spesso non è possibile forzare un determinato driver a utilizzare un determinato dispositivo. A volte, tuttavia, un driver di dispositivo è generoso con ciò che accetta e un dispositivo può funzionare di cui non è a conoscenza. Il tuo chilometraggio varierà! In passato, ho dovuto aggiungere manualmente strani ID dispositivo / fornitore PCI ai driver che dovrebbero supportarli, con successo misto e alcuni crash del kernel divertenti.

Ora, nel caso dei moduli, c'è un ulteriore passaggio. Il caricatore del modulo viene svegliato dal kernel quando viene rilevato un nuovo dispositivo. Ha passato una stringa "modalias", che identifica il dispositivo e assomiglia a qualcosa del genere per i dispositivi USB:

usb:v046DpC221d0170dc00dsc00dp00ic03isc00ip00

Questa stringa contiene la classe del dispositivo ( usb) e le informazioni specifiche della classe (fornitore / dispositivo / numero di serie, classe del dispositivo, ecc.). Ogni driver del kernel contiene una riga come:

MODULE_ALIAS("usb:...")

Che deve corrispondere alle usbalias (i caratteri jolly vengono utilizzati per abbinare più dispositivi). Se modaliascorrisponde a quello supportato dal driver, questo driver viene caricato (o avvisato del nuovo dispositivo, se è già presente).

Puoi vedere i dispositivi supportati (per modalias) e i loro moduli associati con

less /lib/modules/`uname -r`/modules.alias

Se cerchi il driver del dispositivo di archiviazione USB, vedrai che ha alcuni dispositivi specifici supportati dal fornitore e dall'ID dispositivo e tenterà anche di supportare qualsiasi dispositivo con la giusta classe (archiviazione), indipendentemente dal fornitore / dispositivo .

Puoi influenzarlo usando i meccanismi di userspace sul tuo sistema operativo ( /etc/modprobe.d/su Debian e amici). È possibile inserire nella blacklist i moduli oppure specificare i moduli che devono essere caricati dalle modalie, proprio come il modules.aliasfile (e utilizzando la stessa sintassi). depmod -arigenera quindi i modelli del caricatore del modulo.

Tuttavia, anche se puoi condurre questo cavallo particolare all'acqua, ma non puoi farlo bere. Se il driver non ha supporto per il tuo dispositivo, dovrebbe ignorarlo.

Questa è la teoria nel caso generale.

In pratica, e nel caso di USB, vedo che il tuo dispositivo sembra avere due interfacce , di cui una di archiviazione è una. Il kernel si collegherà all'interfaccia di archiviazione dell'intero dispositivo. Se l'altra interfaccia ha la classe giusta, il usbnetdriver potrebbe collegarsi ad essa. Sì, puoi avere più driver collegati allo stesso dispositivo fisico , perché un dispositivo USB esporta più interfacce (ad esempio la mia tastiera Logitech G15 ne esporta due perché ha un dispositivo tastiera e uno schermo LCD, ognuno dei quali è gestito da un driver separato) .

Il fatto che la seconda interfaccia del dispositivo USB non venga rilevata è indicativo della mancanza di supporto nel kernel. In ogni caso, puoi elencare le interfacce / gli endpoint del dispositivo in modo estremamente dettagliato usando lsusb -v | less, quindi scorrere fino al tuo dispositivo particolare (puoi limitare l'output per dispositivo: ID fornitore o percorso USB se sei così incline).

Nota: sto semplificando un po 'qui la struttura logica dei dispositivi USB. Colpa del consorzio USB. :)


4
C'è già static struct usb_device_id id_table [] = { { USB_DEVICE(VENDOR_ID, PRODUCT_ID) }, { }, }; MODULE_DEVICE_TABLE (usb, id_table);nel codice, è ridondante con le modalie?
Thomas,

Nel mio caso quelle linee sono autogenerate da un po 'di magia Makefile ovunque all'interno del driver. Ecco perché ho aggiunto tre volte le righe per MODULE_ALIAS ma non viene mai elencato. Comunque grazie per lsusb -v. con ciò ho potuto verificarlo e trovare il difetto nella mia idea. Quindi ho greppato la fonte per un identificatore noto e ho trovato l'array con le voci che dovevo manipolare.
JackGrinningCat
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.