domenica 18 maggio 2008

Modulo driver per kernel 2.6.x

Dopo un pò di googling in rete, ho trovato alcuni esempi di come programmare i moduli per il kernel 2.4.x
Il nuovo kernel 2.6.x attualmente in distribuzione presenta alcune differenze che hanno reso inutili gli esempi pubblicati sino ad oggi. Vediamo quindi qui alcune considerazioni utili a realizzare un modulo per la porta parallela, che mi servirà a pilotare il motore stepper unipolare già postato in precedenza e che è in fase di sviluppo. Premetto che maggiori info si possono trovare nei repository ufficiali della distribuzione che si utilizza (inutile mettere qui i link che ce ne sono a iosa)
Il kernel di linux fa un largo uso di driver caricabili dinamicamente quando serve, il che ci dà la possibilità di evitare la ricompilazione dello stesso in caso fosse necessario utilizzare delle periferiche nuove. Un altra comodità di linux è che "tutto è un file", ovvero i dispositivi possono essere utilizzati come se fossero dei files. Ci posso scrivere e ci posso leggere. Ciò ci permette di avere accesso ad aree di memoria protette o accedere a basso livello alle periferiche che normalmente equipaggiano i PC. Per fare ciò è necessario "vedere" il dispositivo nella gerarchia /dev. Negli esempi di codice che seguono, si utilizza il linguaggio C. Il codice è preso da vari esempi, cercando di tradurre alcune istruzioni scritte in klingon che si trovano "spezzettate" in vari post di altri programmatori.

Apertura del driver
static int miaporta_open(struct inode *inode, struct file *filep)
{
//ci limitiamo a scrivere un messaggio
printk("Dispositivo aperto\n");
return 0;
}

Chiusura del driver
static int miaporta_release(struct inode *inode, struct file *filep)
{
//anche qui scriviamo solamente un messaggio
printk("Dispositivo chiuso\n");
return 0;
}

La scrittura sul driver
static ssize_t miaporta_write(struct file *filep, const char *buf, size_t count, loff_t *f_pos)
{
outb(0x00,0x37A); // porta parallela 1 in uscita
outb(buf[0],0x37B); // Scrittura sul registro ADDRESS
return 0;
}

La lettura dal driver
static ssize_t miaporta_read(struct file *filep, char *buf, size_t count, loff_t *f_pos)
{
outb(0x20,0x37A); // Porta parallela1 in Input
buf[0]=inb(0x37B); // lettura dal registro ADDRESS
return 0;
}

Occorre ora associare le procedure alle funzioni dei files. Per farlo, quest’ultime devono essere esportate al sistema. Questo lavoro viene svolto riempendo una struttura particolare di tipo ”file operations”, definita nell’header file ”linux/fs.h”.

struct file_operations epp_fops =
{
owner: THIS_MODULE,
open: miaporta_open,
release: miaporta_release,
read: miaporta_read,
write: miaporta_write,
};

Per l'inizializzazione del modulo occorre anche associare, con la funzione "register chardev", un ben definito device al nostro driver. Basta passare come parametri, nell’ordine, il major-char-number (20), una stringa con il nome del driver e la struttura con registrate le funzioni specifiche di accesso.

static int __init init_mod(void)
{
int result;
if ((result = register_chrdev(20, "miaporta", &epp_fops)) < style="color: rgb(51, 204, 0);">Chiusura del driver (deregistrazione9

static void __exit end_mod(void)
{
unregister_chrdev(20, "miaporta");
printk("Driver MIAPORTA unloaded.\n");
}

Per ultimo occorre aggiungere la linea in testa MODULE_LICENSE("GPL"); (o altre opzioni disponibili in base al tipo di licenza prescelto) e in fondo

module_init(init_mod);
module_exit(end_mod);

Per compilare, occorre creare un Makefile come segue:

obj-m:= miaporta_drv.o
KDIR = /lib/modules/$(shell uname -r)/build
PWD = $(shell pwd)
default:
$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules
clean:
rm -f *.mod.* *.o *.ko

Una volta compilato occorre caricare il modulo con insmod ./miaporta_drv.ko e per poterlo utilizzare basta dare il comando mknod -m 0666 /dev/miaporta c 20 0
Funziona?. non lo so, devo ancora provare.

In attesa che sviluppi il codice e inizi a testarlo vediamo come si prevede di utilizzarlo all'interno del programma che lo utilizza...

#include "fcntl.h"
#include "stdio.h"
int main()
{
char buffer[1];
int fd;
fd=open("/dev/miaporta",O_RDWR);
buffer[0]=0x00;
write(fd,buffer,1,NULL); //scrivo il byte
read(fd,buffer,1,NULL); //leggo i byte
printf("Valore : 0x%02x\n",buffer[0]);
close(fd);
}

Dovrebbe funzionare. Se nei prossimi giorni trovo il tempo di svilupparlo e mi accorgo che qualcosa non va, provvederò alle modifiche. Per ora STOP. Una domenica passata al PC approfittando del maltempo mi pare sufficiente. Ora un pò di relax. un abbraccio

P.S. Mille bit fanno un megabit. Ripeto: Mille bit fanno un megabit.

sabato 17 maggio 2008

Magicrescue per linux

Speravo tanto di non doverlo mai fare. Oggi ho combinato un pasticcio degno del più principiante degli informatici. Accidentalmente, nell'usare incautamente un file manager appena installato, ho cancellato il 90% dei sorgenti di un progetto che sto sviluppando da quasi un mese. Me ne sono accorto solo alla ri-accensione del sistema. Persi i sorgenti, le impostazioni del progetto, le form... una piccola catastrofe. Com'è noto, gli informatici sono i primi a bacchettare i clienti che non salvano i dati con i backup giornalieri, salvo poi non farli mai per se stessi. Ho dovuto quindi procedere con un tentativo di recupero utilizzando magicrescue per linux. Dopo aver ri-montato la partizione da ext3 a ext2 (non journaled), ho proceduto con la programmazione dei "recipes" (le configurazioni). Fortunatamente, fresco di sviluppo, ricordo a memoria i nomi dei files e delle form create. Credo di aver recuperato tutto il minimo per tentare una ri-compilazione. Al massimo avrò perso solo le ultime righe di codice sviluppato. Al limite, proverò con sleuthkit sul dd effettuato sulla partizione interessata, oppure con Autopsy.
Ora è troppo tardi per un tentativo. è dalle 7 di stamattina che programmo e sono un pò stanchino. Vado a riposare e sabato, invece di dedicarmi ai miei hobbies preferiti, proverò a sistemare gli ultimi dettagli. Notte.

Aggiornamento 17.5.2008 - Tutto ok. Files recuperati al 98%. Tre ore di lavoro per lo sviluppo dei sorgenti mancanti e il software è tornato operativo. Utilizzato Magicrescue per linux.

P.S. il ragno non esce dal buco. Ripeto: il ragno non esce dal buco.

martedì 13 maggio 2008

Lazarus per linux - Reports


Lazarus è un IDE (ambiente di sviluppo) del linguaggio di programmazione Free Pascal. E' compatibile con il linguaggio Delphi di Borland. Lo sto utilizzando per sviluppare alcune procedure software in ambiente linux. Il progetto Lazarus è in fase embrionale (versione 0.9.x Beta) e la documentazione davvero scarsa. Per chi ha sviluppato in Delphi per anni come me, la cosa non rappresenta un grosso problema, ma in alcuni casi serve sempre ancora un pò di supporto, specie per quei componenti "nuovi" che in Delphi non ci sono o sono diversi. Allora, per contribuire, visto che non ho trovato indicazioni in rete, voglio pubblicare qui alcuni "tutorial" che possano essere utili a chi inizia o non ha troppo tempo da perdere nel cercare fra i forum in inglese e le varie wiki perennemente under development...
Iniziamo con i componenti per creare i report (le stampe) con un esempio minimale. Vogliamo creare dei report da un database MySQL su un server remoto (host) utilizzando i componenti ZeosDBO per l'accesso alle tabelle.
Passo 1 - Creare un nuovo progetto con la classica form1. Ci mettiamo un Bottone per lanciare l'esecuzione dei componenti
Passo 2 - depositare nella form i seguenti componenti:
  • ZConnection1
  • ZTable1
  • frDBDataset1
  • frReport1
  • Opendialog1
Passo 3 - Colleghiamo i vari componenti e settiamo le proprietà minime per farle funzionare (alcune proprietà le mettiamo "hardcoded" a design time, anche se è semplice farlo a run-time
Proprietà ZConnection1
  • Hostname = 192.168.2.x (dipende dalla tua rete locale) è l'indirizzo del server ove è installato il database. indica "localhost" se apache risponde sulla macchina su cui stai lavorando.
  • User = il nome dell'utente abilitato ad accedere
  • Password = la password di autenticazione abbinata all'utente (senon ce l'aqhi chiedi all'amministratore della rete o al provider se ti sati collegando ad un server su internet)
  • Protocol = mysql-5 in questo esempio. dipende dal tipo di archivio che stai usando.
  • Catalog = nome del database (compare in un menu drop-down dopo aver settato host, user e password)
  • Database = scrivilo a mano uguale al nome del Catalog se si tratta come in questo esempio di un database remoto
  • Active=True

Proprietà ZTable1
  • Connection = Zonnection1
  • Active=True
Al termine con un doppio click sul componente sulla form sei in grado di aggiungere i campi che desideri gestire.

Proprietà frDBDataset1
Va collegato a Table1

Proprietà frReport1
Va collegato a frDBDataset1

Passo 4 - Ora passiamo alla scrittura del codice per attivare il disegnatore dei report, con salvataggio e stampa.
Per lanciare il designer basta chiamare la procedura DesignReport come segue, in concomitanza all'evento OnClick del Bottone:

frReport1.DesignReport;

Una volta creato e salvato il report, per aprirlo ed eseguirlo basta la seguente procedura:
if Opendialog.execute then
begin
frReport.LoadFromfile(Opendialog1.filename);
frReport.Showreport;
end;

Nei prossimi giorni prometto, forse, di ampliare le indicazioni e completarle. Adesso, dopo 15 ore di lavoro, mi prendo una pausa per andare a dormire. Buona notte

P.S. Il pollo è cotto. Ripeto: il pollo è cotto.