Linux Driver Example

html
File
mydriver.tar.gz
Required
Header Linux Source
Compile
run ./make.sh
Install
run ./install.sh
Open Driver
modprobe mydriver
Disable Driver
rmmod mydriver


Server Header

		c


/*====================================-- HEADER --=====================================*/

#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>  /* printk() */
#include <linux/slab.h>    /* kmalloc() */
#include <linux/fs.h>      /* everything... */
#include <linux/errno.h>   /* error codes */
#include <linux/types.h>   /* size_t */
#include <linux/proc_fs.h>
#include <linux/fcntl.h>   /* O_ACCMODE */
#include <linux/device.h>
#include <asm/uaccess.h>


// Informacoes mostradas pelo comando: modinfo 
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Felipe Bombardelli <felipebombardelli@gmail.com>");
MODULE_DESCRIPTION("Este eh um driver maroto");

// Variaveis Globais
#define MYDRIVER_FILENAME "mydriver"           // nome do arquivo em /dev
int MYDRIVER_MAJOR = 0;                        // Define um id automatico para o novo device
static struct class *MYDRIVER_CLASS = NULL;    // Objeto da nova Class MyDriver
static struct device *MYDRIVER_DEVICE = NULL;  // Objeto 

#define SUCCESS 0



// INIT/EXIT: Configuracao das rotinas de abertura e fechamento do driver
static int __init mydriver_init(void);
static void __exit mydriver_exit(void);

module_init(mydriver_init)
module_exit(mydriver_exit)


// MYDRIVER_FOPS: Personalizacao da abertura, fechamento, leitura e escrita de /dev/mydriver
static int mydriver_fops_open(struct inode *inode, struct file *filp);
static int mydriver_fops_release(struct inode *inode, struct file *filp);
static ssize_t mydriver_fops_read(struct file *filp, char *buf, size_t count, loff_t *f_pos);
static ssize_t mydriver_fops_write(struct file *filp, char *buf, size_t count, loff_t *f_pos);

struct file_operations mydriver_fops = {
	.owner   = THIS_MODULE,
	.open    = mydriver_fops_open,
	.release = mydriver_fops_release,
	.read    = mydriver_fops_read,
	.write   = mydriver_fops_write
};


/*-------------------------------------------------------------------------------------*/



/*==================================-- INIT/EXIT --====================================*/


static int __init mydriver_init(void){
	printk("mydriver: init
");
	
	MYDRIVER_MAJOR = register_chrdev(0, MYDRIVER_FILENAME, &mydriver_fops);
	
	// Pega um major(id) disponivel
	if ( MYDRIVER_MAJOR == 0 )
		printk("mydriver: error : nao foi possivel criar o /dev/mydriver
");
	else
		printk("mydriver: ok : criado o /dev/mydriver
");
	
	// Cria a nova classe mydriver
	MYDRIVER_CLASS = class_create(THIS_MODULE, MYDRIVER_FILENAME);
	if (IS_ERR(MYDRIVER_CLASS)){
		unregister_chrdev(MYDRIVER_MAJOR, MYDRIVER_FILENAME);
		return 1;
	}
	
	// Cria um novo dispositivo mydriver atrelado a class mydriver
	MYDRIVER_DEVICE = device_create(MYDRIVER_CLASS, NULL, MKDEV(MYDRIVER_MAJOR, 0), NULL, MYDRIVER_FILENAME);
	if (IS_ERR(MYDRIVER_DEVICE)){
		class_destroy(MYDRIVER_CLASS);
		unregister_chrdev(MYDRIVER_MAJOR, MYDRIVER_FILENAME);
		return 1;
	}
	
	return SUCCESS;
}

static void __exit mydriver_exit(void){
	printk("mydriver: exit");

	device_destroy(MYDRIVER_CLASS, MKDEV(MYDRIVER_MAJOR, 0));
	unregister_chrdev(MYDRIVER_MAJOR, MYDRIVER_FILENAME);
	class_destroy(MYDRIVER_CLASS);
}

/*-------------------------------------------------------------------------------------*/



/*=================================-- MYDRIVER_FOPS --==================================*/

static int mydriver_fops_open(struct inode *inode, struct file *filp){
	printk("mydriver: /dev/mydriver foi aberto
");
	return SUCCESS;
}

static int mydriver_fops_release(struct inode *inode, struct file *filp){
	printk("mydriver: /dev/mydriver foi fechado
");
	return SUCCESS;
}

static ssize_t mydriver_fops_read(struct file *filp, char *buf, size_t count, loff_t *f_pos){
	printk("mydriver: /dev/mydriver foi lido
");
	return 0;
}

static ssize_t mydriver_fops_write(struct file *filp, char *buf, size_t count, loff_t *f_pos){
	buf[count-1] = '0';
	printk("mydriver: write[%d] : %s
", count, buf);
	return count;  // Obrigatorio retornar count, caso contrario o kernel fica em loop infinito
	               // ate que a soma de todos os retornos seja == count;
}

/*-------------------------------------------------------------------------------------*/