|
Appunti sullo sviluppo di un driver per Linux per il controllo di una automobilina radiocomandatadi Marco Faella e Marco Trucillo |
||||||||||||
2.1 Major e minor |
|||||||||||||
Ogni file speciale è collegato al "suo" driver tramite due numeri,
detti major e minor, di cui il primo identifica il driver
vero e proprio, mentre il secondo serve a discriminare tra diverse periferiche
nel caso che uno stesso driver ne gestisca più d'una.
E' possibile visualizzare i numeri associati ai file speciali presenti con il semplice comando ls -l. Il major e il minor saranno, nell'ordine, i due numeri che precedono la data di creazione del file. Ecco alcuni esempi:
Dalla tabella si evince che i dispositivi (virtuali) mem e null
sono gestiti dallo stesso driver (perché hanno major uguale).
|
|||||||||||||
2.2 I comandi |
|||||||||||||
A questo punto non ci resta che decidere come far corrispondere
ad ogni carattere inviato al driver un comando per il telecomando. Una
possibilità consiste nel prendere i 4 bit meno significativi di
ciascun carattere ed interpretarli direttamente come i 4 comandi disponibili,
dopo aver filtrato quelli contraddittori.
In altre parole, se il carattere inviato ha rappresentazione binaria <c7 c6 c5 c4 | c3 c2 c1 c0>, i suoi bit saranno così interpretati: Ad esempio, il carattere "Y", in decimale 89 ed in binario <0101 | 1001>, indicherà di andare avanti a destra per 5 secondi, mentre il carattere "B", in decimale 66 ed in binario <0100 | 0010>, richiede di tenere le ruote sterzate a sinistra per 4 secondi (un comando alquanto inutile, in effetti). |
|||||||||||||
2.3 Car.h |
|||||||||||||
Presentiamo l'header che conterrà le costanti e le macro usate
nel corpo del driver.
Mentre lo scopo di alcune di esse è evidente, l'utilità di altre sarà chiarita solo più avanti. struct car_struct {
/* Costanti varie */ #define CAR_MAJOR 50 #define STOP 0
#define CAR_EXIST 0x0001
/* Macro varie */
|
|||||||||||||
2.4 Open e Close |
|||||||||||||
Entriamo finalmente nel merito del driver, cominciandocon le funzioni
che saranno chiamate quando un applicativo invocherà una open
o una close sul file speciale car.
L'unico compito che queste due funzioni dovranno assolvere è far si che un solo programma per volta possa aprire con successo il file. Ad ogni macchina (contempleremo anche la possibilità che ce ne siano due) assoceremo un carattere che ne rappresenti lo stato; ne useremo però soltanto due bit: uno per specificare se la macchina è presente e l'altro per indicare se la macchina è attualmente in uso (cioè se il suo file speciale è stato aperto). Ecco il codice delle funzioni di apertura e chiusura: int car_open(struct inode * inode, struct file * file)
void car_release(struct inode * inode, struct file * file)
|
|||||||||||||
2.5 Ioctl |
|||||||||||||
Forniremo anche una funzione di i/o control, che però eseguirà
un solo comando (CAR_RESET), incaricato di far fermare la macchinina. Ecco
le due funzioni interessate.
int car_reset(int minor)
int car_ioctl(struct inode *inode, struct file *file, unsigned int
cmd, unsigned long arg)
if (minor >= CAR_NO) /* minor troppo alto */
switch ( cmd ) {
|