El archivo test.h queda asi:
#ifndef _TEST_SPI_H_
#define _TEST_SPI_H_
#define DEVICE_NAME "test-spi"
MODULE_AUTHOR("Jorge Eduardo Cardona <jorgeecardona@gmail.com>");
MODULE_DESCRIPTION("SPI test driver.");
MODULE_LICENSE("GPL");
// Character device functions.
static int this_open(struct inode *inode, struct file *file);
static int this_release(struct inode *inode, struct file *file);
static ssize_t this_read(struct file *file, char __user *buffer, size_t len, loff_t *offset);
static ssize_t this_write(struct file *file, const char __user *buffer, size_t len, loff_t *offset);
// File Operations structure.
struct file_operations this_fops = {
.open = this_open,
.release = this_release,
.read = this_read,
.write = this_write
};
// Linux module functions.
static int __init this_init(void);
static void __exit this_exit(void);
module_init(this_init);
module_exit(this_exit);
#endif
Para crear el dispositivo de caracteres debemos llamar a la funcion: register_chrdev (http://kerneltrap.org/man/linux/man9/register_chrdev.9)(http://www.silicontao.com/ProgrammingGuide/GNU_function_list/register_chrdev.html)
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/err.h>
#include "test.h"
// Global data
static int this_major;
// Function that is called every time we try to open a device.
static int this_open(struct inode *inode, struct file *file)
{
printk(DEVICE_NAME": Open device.\n");
return 0;
}
// Function that is called when we close a device.
static int this_release(struct inode *inode, struct file *file)
{
printk(DEVICE_NAME": Close device.\n");
return 0;
}
// Function that is called when we read from a device.
static ssize_t this_read(struct file *file, char __user *buffer, size_t len, loff_t *offset)
{
printk(DEVICE_NAME": Read device.\n");
return 0;
}
// Function that is called when we write to a device.
static ssize_t this_write(struct file *file, const char __user *buffer, size_t len, loff_t *offset)
{
printk(DEVICE_NAME": Write device.\n");
return 0;
}
// Function that is called when we load the module.
static int __init this_init(void)
{
int ret;
printk(DEVICE_NAME ": Init.\n");
// Register char device: 0 for dynamically allocation of the major number.
ret = register_chrdev(0, DEVICE_NAME, &this_fops);
if (~IS_ERR_VALUE(ret))
{
printk(DEVICE_NAME ": Character device registered, with major=%d.\n",ret);
this_major = ret;
return 0;
}
unregister_chrdev(this_major, DEVICE_NAME);
printk(DEVICE_NAME ": Character device unregistered.\n");
return ret;
}
// Function that is called when we remove the module.
static void __exit this_exit(void)
{
unregister_chrdev(this_major, DEVICE_NAME);
printk(DEVICE_NAME ": Character device unregistered.\n");
printk(DEVICE_NAME ": Exit.\n");
}
(http://tomoyo.sourceforge.jp/cgi-bin/lxr/ident?i=IS_ERR_VALUE)
Bueno, igual que antes, configuramos, compilamos y tenemos:
root@gumstix-custom-connex:~$ modprobe test
root@gumstix-custom-connex:~$ dmesg | grep "test-spi"
<4>test-spi: Init.
<4>test-spi: Character device registered, with major=254.
root@gumstix-custom-connex:~$ mknod /dev/test c 254 0
root@gumstix-custom-connex:~$ cat /dev/test
root@gumstix-custom-connex:~$ dd bs=1 count=0 if=/dev/zero of=/dev/test
0+0 records in
0+0 records out
root@gumstix-custom-connex:~$ echo "ja" > /dev/test
root@gumstix-custom-connex:~$ rmmod test
root@gumstix-custom-connex:~$ dmesg | grep "test-spi"
<4>test-spi: Init.
<4>test-spi: Character device registered, with major=254.
<4>test-spi: Open device.
<4>test-spi: Read device.
<4>test-spi: Close device.
<4>test-spi: Open device.
<4>test-spi: Close device.
<4>test-spi: Open device.
<4>test-spi: Write device.
<4>test-spi: Write device.
<4>test-spi: Write device.
<4>test-spi: Write device.
<4>test-spi: Write device.
<4>test-spi: Write device.
<4>test-spi: Write device.
<4>test-spi: Write device.
<4>test-spi: Write device.
<4>test-spi: Write device.
<4>test-spi: Close device.
<4>test-spi: Character device unregistered.
<4>test-spi: Exit.
root@gumstix-custom-connex:~$
Los varios mensajes de Write se deben a que retornamos 0 esto quiere decir que no escribimos ningun caracter y la funcion es llamada hasta que vacie el buffer, pero aqui toca matarla con un Ctrl-C.
Bueno, un paso mas.