linux设备驱动入门,最简单的LED驱动,基于tq2440

写linux字符设备驱动的过程:

1、module_init()和module_exit(),这两个函数是驱动程序的入口函数和退出函数,然后就是补充init函数和exit函数了

2、在initi函数中,需要进行设备的注册,说白了,就是需要申请设备号和注册设备

3、然后写文件操作函数,比如write、read、ioctl等函数

/*************************************

	NAME:  led.c 
	COPYRIGHT: XMG

*************************************/

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#define DEVICE_NAME  "leds"
/* module name */

struct cdev cdev;
static struct class *led_class;
static led_major = 0;

static unsigned long led_table[]=
{
	S3C2410_GPB5,
	S3C2410_GPB6,
	S3C2410_GPB7,
	S3C2410_GPB8,
};

static int leds_ioctl(struct inode *inode,struct file *file,unsigned int cmd,unsigned long arg)//ioctl函数
{
	if(arg > 4)
	{
		return -EINVAL;
	}

	switch(cmd)
	{
		case 1:
			s3c2410_gpio_setpin(led_table[arg],0);
			return 0;
		case 0:
			s3c2410_gpio_setpin(led_table[arg],1);
			return 0;	
		default:
			return -EINVAL;
	}
}

static struct file_operations leds_fops = //文件操作结构体
{
	.owner = THIS_MODULE,
	.ioctl =  leds_ioctl,
};

static int __init leds_init(void)//入口函数
{
	int result;
	dev_t dev = MKDEV(led_major,0);

	if(led_major)
	{
		result = register_chrdev_region(dev,1,DEVICE_NAME);//由固定设备号,直接申请
		if(result < 0)
		{
			printk(DEVICE_NAME"can't register major number\n");
			return result;
		}
		printk("aaaa %d\n",led_major);
	}
	else
	{
		result = alloc_chrdev_region(&dev,0,1,DEVICE_NAME);//没有固定的设备号,动态申请
		led_major = MAJOR(dev);//得到主设备号
		printk("MAJOR IS %d",led_major);
	}

	cdev_init(&cdev,&leds_fops);//设备结构体的初始化
	cdev.owner = THIS_MODULE;
	cdev.ops = &leds_fops;
	cdev_add(&cdev,MKDEV(led_major,0),1);	

	led_class = class_create(THIS_MODULE,DEVICE_NAME);
	if(IS_ERR(led_class))
	{
		printk("Err:failed in leds class.\n");
		return -1;
	}

	device_create(led_class,NULL,MKDEV(led_major,0),NULL,DEVICE_NAME);//创建设备

	printk(DEVICE_NAME "initialized\n");
	return 0;
}

static void __exit leds_exit(void)
{
	unregister_chrdev_region(MKDEV(led_major,0),1);
	device_destroy(led_class,MKDEV(led_major,0));
	class_destroy(led_class);
	cdev_del(&cdev);
}

module_init(leds_init);//入口
module_exit(leds_exit);//出口

MODULE_AUTHOR("XMG");
MODULE_DESCRIPTION("TQ2440");
MODULE_LICENSE("GPL");

以下是测试程序:

/*******************************************
 *    NAME:test.c
 *    COPYRIHT: XMG
 ******************************************/

#include 
#include 
#include 
#include 

int main(int argc,char **argv)
{
	int on;
	int led_no;
	int fd;
	
	if(argc != 3 || sscanf(argv[1],"%d",&led_no)!= 1 || sscanf(argv[2],"%d",&on)!=1||on < 0 || on > 1 || led_no< 1 || led_no > 4){
		fprintf(stderr,"Usage:leds led_no 0|1 \n");
		exit(1);
	}
	fd = open("/dev/leds",0);
	if(fd < 0){
		perror("open device leds");
		exit(1);
	}
	ioctl(fd,on,(led_no-1));
	close(fd);
	return 0;
}




你可能感兴趣的:(linux,字符,设备驱动,LED)