Linux驱动学习之点灯(四,linux2.6)

上篇最后的第二种点灯方法年代比较久远,register_chrdev()这个函数一下申请了255个设备号,不建议使用  如下图

下图的函数在linux2.6里是上图函数的升级版,不过他是静态分配,后续还得添加到cdev里

从上图函数不难发现,静态申请多个设备号,主设备号不变,次设备号++

一般我们会使用下图函数动态申请设备号,并添加到cdev里

第一个参数:无符号32位设备号的地址,申请成功后该地址空间里存放的就是设备号

第二个参数:次设备号起始地址,

第三个参数:申请设备号的数量(主设备号不变,次设备号++)

第四个参数:名字(随便给)

申请完设备号后,把它加入cdev链表里 

struct cdev cdev; //定义cdev
struct file_operations led_fops = {
    .owner=THIS_MODULE,
    .open=led_open,
    .release=led_close,
    .write=led_write,
};
cdev_init(&cdev, &led_fops);  //用文件操作结构体初始化cdev
cdev_add(&cdev, dev, 1);     //添加设备号

也可以动态分配

struct cdev *cdev; //定义cdev
cdev=cdev_alloc();
struct file_operations led_fops = {
    .owner=THIS_MODULE,
    .open=led_open,
    .release=led_close,
    .write=led_write,
};
cdev.ops=&fops;  //用文件操作结构体初始化cdev
cdev_add(cdev, dev, 1);     //添加设备号

这里不需要cdev_init 因为cdev_alloc 跟cdev_init 内操作一样,只是少了一个操作结构体赋值,所以单独补上。 

接下里就是创建/dev/led

    struct class *led;
    led = class_create(THIS_MODULE, "myled_class");
    device_create(led,NULL,dev,NULL,"led");

完整代码 

#include "linux/device.h"
#include "linux/export.h"
#include "linux/gpio.h"
#include "linux/module.h"
#include "linux/kernel.h"
#include "linux/init.h"
#include "linux/fs.h"
#include "linux/cdev.h"
#include "linux/uaccess.h"

dev_t dev;
struct cdev cdev;
struct class *led;
static int led_open (struct inode *a, struct file *b){

    return 0;
}
static int led_close (struct inode *a, struct file *b){

    return 0;
}
static ssize_t led_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos)
{
    char val;
    unsigned long a=copy_from_user(&val,buf,1);
    if(a)
    {

    }
    else
    {
    
    }
    if(val=='1')
    {
        printk("开灯\r\n");
        gpio_set_value(21,1);
        gpio_set_value(22,1);
        printk("ok\r\n");
    }    
    else
    {
        printk("关灯\r\n");
        gpio_set_value(21,0);
        gpio_set_value(22, 0);
        printk("ok\r\n");
    }
    return 0;
}
struct file_operations led_fops = {
    .owner=THIS_MODULE,
    .open=led_open,
    .release=led_close,
    .write=led_write,
};
static int __init led_init(void)
{
    //申请设备号
    int ret=  alloc_chrdev_region(&dev,0,1,"led_dev");
    if(ret<0)
    {
        return -1;   //加载失败
    }
    printk(KERN_INFO "LED driver loaded successfully\n");
    //初始化LINUX2.6 cdev结构体
    cdev_init(&cdev, &led_fops);
    cdev_add(&cdev, dev, 1);
    gpio_request(21,"led");
    gpio_direction_output(21, 0);
    gpio_request(22,"led");
    gpio_direction_output(22, 0);
    led = class_create(THIS_MODULE, "myled_class");
    device_create(led,NULL,dev,NULL,"led");

    return 0;
}
static void __exit led_exit(void)
{
    device_destroy(led, dev);
    class_destroy(led);
    cdev_del(&cdev);
    printk(KERN_INFO "LED driver unloaded successfully\n");
}
module_init(led_init);
module_exit(led_exit);
MODULE_LICENSE("GPL");

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值