Appunti sullo sviluppo di un driver per Linux per il controllo di una automobilina radiocomandata

di Marco Faella e Marco Trucillo

 

1.0    Introduzione

Questi appunti illustrano i passi principali della realizzazione di un driver in C in grado di impartire comandi ad una automobilina radiocomandata, il cui telecomando sia stato opportunamente modificato per collegarsi alla porta parallela del PC. 
Una volta realizzato il driver, sarà possibile non solo scrivere programmi applicativi che impartiscano comandi al veicolo, ma anche controllare il modellino con il solo ausilio dei normali comandi di shell. 
Giungeremo infatti alla creazione di un file speciale di periferica, verso il quale si potranno indirizzare dei caratteri che il driver interpreterà e quindi invierà al telecomando. 
Per la comprensione del seguito è richiesta una certa dimestichezza sia con il linguaggio C che con il sistema operativo Linux. 

Il materiale qui esposto è frutto di un progetto sviluppato per l'esame di Laboratorio di Sistemi Operativi presso l'Università di Salerno, progetto che è valso agli autori il massimo dei voti. 
Gli autori si scusano per le imprecisioni che per distrattezza o ignoranza hanno inserito nel testo, invitando i lettori a segnalarle tramite e-mail. 
 
Marco Faella mfaella@cmare.peoples.it    homepage www.oocities.org/SiliconValley/Pines/1406 
Marco Trucillo  martru@zoo.diaedu.unisa.it
 
 

 

1.1    Generalità sui device driver di Linux

In ambiente Linux, come pure Unix, tutte le comunicazioni tra programmi applicativi e device driver avvengono tramite file speciali, solitamente collocati nella directory /dev
Una prima distinzione deve essere fatta tra driver a blocchi e a caratteri. Appartengono al primo tipo le periferiche, come i dischi fissi, in cui le letture e le scritture sono pesantemente bufferizzate, mentre al secondo i dispositivi in cui l'input/output avviene, come il nome stesso suggerisce, carattere per carettere. 
I driver esportano, cioè rendono note al kernel, le loro funzionalità riempiendo una struttura di tipo file_operations con gli indirizzi delle loro funzioni e poi registrandosi con una chiamata a: 
int register_chrdev(unsigned int major, const char *name, struct file_operations *fops),
una funzione di cui torneremo ad occuparci. 
I driver si distinguono anche in base a come si integrano con il kernel: essi possono cioè essere compilati insieme al kernel stesso oppure caricati al run-time; in quest ultimo caso si parla di loadable modules. Il driver della macchinina sarà di tipo a carattere e si dovrà compilare insieme al kernel; sono però semplici le modifiche da apportare per renderlo caricabile all'occorrenza. 
Vediamo ora più da vicino la struttura file_operations
struct file_operations { 
    int (*lseek) (struct inode *, struct file *, off_t, int); 
    int (*read) (struct inode *, struct file *, char *, int); 
    int (*write) (struct inode *, struct file *, char *, int); 
    int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long); 
    int (*open) (struct inode *, struct file *); 
    void (*release) (struct inode *, struct file *); 
    /* seguono altri puntatori che non prendiamo in considerazione */ 
}; 
Come si vede, si tratta di una sequenza di puntatori a funzione dai nomi abbastanza autoesplicativi. Quando un applicativo invoca una system call che riguarda un file speciale (poniamo che sia una open), il sistema operativo (e più precisamente una parte di esso che prende il nome di VFS=Virtual FileSystem) accede alla struttura file_operations relativa al driver che "possiede" quel file e quindi esamina il campo open della struttura: se è posto a NULL allora invoca una funzione standard di apertura file, altrimenti passa il controllo alla funzione puntata. Questo meccanismo consente ai driver di ridefinire soltanto quelle funzioni che hanno attinenza con la periferica gestita, lasciando che il VFS gestisca in maniera standard le altre. 
 
 

1.2    Il telecomando

Come è già stato accennato, il telecomando dell'automobile deve essere modificato per collegarsi alla porta parallela del PC. Non ci addentreremo nei dettagli di queste modifiche sia perché andremo decisamente fuori tema, sia perché essi dipendono dal particolare modello di telecomando usato. 
Vi basti sapere che dalla porta parallela abbiamo prelevato solo 4 bit di dati, più la terra ed abbiamo fatto in modo che le 4 linee dati attivassero altrettanti rele' che a loro volta impartissero al telecomando i 4 comandi fondamentali, ovvero motore AVANTI o INDIETRO, sterzo a DESTRA o a SINISTRA. 
E' affidato al driver il compito di impedire l'invio di comandi contraddittori come AVANTI e INDIETRO allo stesso tempo.