linux混杂设备的驱动-LED

混杂设备概念:

Misc(或miscellaneous)驱动是一些拥有着共同特性的简单字符设备驱动。内核抽象出这些特性而形成一些API(在文件drivers/char/misc.c中实现),以简化这些设备驱动程序的初始化。所有的misc设备被分配同一个主设备号MISC_MAJOR(10),但是每一个可以选择一个单独的次设备号。如果一个字符设备驱动要驱动多个设备,那么它就不应该用misc设备来实现。
通常情况下,一个字符设备都不得不在初始化的过程中进行下面的步骤:
通过alloc_chrdev_region()分配主/次设备号。
使用cdev_init()cdev_add()来以一个字符设备注册自己。
而一个misc驱动,则可以只用一个调用misc_register()来完成这所有的步骤。
所有的miscdevice设备形成一个链表,对设备访问时,内核根据次设备号查找对应的miscdevice设备,然后调用其file_operations中注册的文件操作方法进行操作。

//=================================================

//version: linux2.6.24

//led_pin:GB5/GB6/GB8/GB10

//混杂设备驱动

//=================================================

#include <linux/miscdevice.h> //混杂设备头文件

#include <linux/kernel.h>

#include <linux/module.h>

#include <linux/init.h>

#include <linux/fs.h>

#include <linux/types.h>

#include <linux/slab.h>

#include <linux/errno.h>

#include <linux/ioctl.h>

#include <linux/cdev.h>

#include <linux/device.h>

#include <asm/irq.h>

#include <asm/arch/regs-gpio.h>

#include <asm/hardware.h>

 

#define DEVICE_NAME      "ledsmisc"    //定义设备名

//#define LED_MAJOR        231        //手动定义主设备号

//#define LED_MINOR        0

 

//定义要操作的设备,把每一个led作为结构体的一个成员

static unsigned long led_table [] = {         

        S3C2410_GPB5,

        S3C2410_GPB6,

        S3C2410_GPB8,

        S3C2410_GPB10,

};

//对设备进行设置,结构体的每一个成员是对对应led的设置

static unsigned int led_cfg_table [] = {

        S3C2410_GPB5_OUTP,  //0x01<<10 defined in  refg-gpio.h

        S3C2410_GPB6_OUTP,

        S3C2410_GPB8_OUTP,

        S3C2410_GPB10_OUTP,

};

//设备驱动程序中对设备的I/O通道进行管理的函数,用来实现对led的操作

static int s3c2410_leds_ioctl(struct inode *inode,

       struct file *file, unsigned int cmd, unsigned long arg)

{

    switch(cmd) {

        case 0:

        case 1:

            if (arg > 4)

                return -EINVAL;

            s3c2410_gpio_setpin(led_table[arg], !cmd);

            return 0;

        default:

            return -EINVAL;

    }

}

//================================================

//            文件操作结构体填充

//================================================

static struct file_operations s3c2410_leds_fops = {

    .owner    =    THIS_MODULE,

    .ioctl    =    s3c2410_leds_ioctl,

};

//===============================================

//            填充混杂设备驱动结构

//==============================================

static struct miscdevice misc = {

    .minor = MISC_DYNAMIC_MINOR, //动态分配此设备号

    .name = DEVICE_NAME,  //设备名

    .fops = &s3c2410_leds_fops, //设备操作

};

//struct cdev *my_cdev;

//struct class *my_class;

//=========================================

//            模块加载函数

//========================================

static int __init s3c2410_leds_init(void)

{

    int err, i;

    int ret;

#if 0 

   /* register the 'dummy_dev' char device */

    my_cdev = cdev_alloc();//分配一个虚拟设备号

    cdev_init(my_cdev, &s3c2410_leds_fops);//初始化cdev

    my_cdev->owner = THIS_MODULE;

    err = cdev_add(my_cdev, devno, 1);//添加cdev

    if (err != 0)

        printk("led device register failed!\n");

    /* creating your own class */

    my_class = class_create(THIS_MODULE, "led_class");

    if(IS_ERR(my_class)) {

        printk("Err: failed in creating class.\n");

        return -1;

     }

    /* register your own device in sysfs, and this will cause udevd to create corresponding device node */

    class_device_create(my_class, NULL, devno, NULL, DEVICE_NAME "%d", LED_MINOR );

#endif

    //======led端口配置,数组不要超长,否则会导致insmodsegment fault========

    for (i = 0; i < 4; i++) {

        s3c2410_gpio_cfgpin(led_table[i], led_cfg_table[i]);

        s3c2410_gpio_setpin(led_table[i], 1);

    }

    ret = misc_register(&misc);//注册混杂设备

    printk("Led_Driver insmod success!\r\n");

    return 0;

}

//========================================

//            模块卸载函数

//=======================================

static void __exit s3c2410_leds_exit(void)

{

#if 0

    cdev_del(my_cdev);

    class_device_destroy(my_class, MKDEV(LED_MAJOR, LED_MINOR));

    class_destroy(my_class);

#endif

    misc_deregister(&misc);//注销混杂设备

    printk("Led_Driver removed success!\r\n");

}

 

module_init(s3c2410_leds_init);

module_exit(s3c2410_leds_exit);

MODULE_LICENSE("GPL");

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

叶落西湘

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值