Chinaunix首页 | 论坛 | 博客
  • 博客访问: 15483026
  • 博文数量: 2005
  • 博客积分: 11986
  • 博客等级: 上将
  • 技术积分: 22535
  • 用 户 组: 普通用户
  • 注册时间: 2007-05-17 13:56
文章分类

全部博文(2005)

文章存档

2014年(2)

2013年(2)

2012年(16)

2011年(66)

2010年(368)

2009年(743)

2008年(491)

2007年(317)

分类: LINUX

2009-09-26 22:08:18

// 如果问题可以联系我 luther.ge@163.com
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/device.h>

#define log_printf(msg...) printk(KERN_ERR "===luther:=== "msg)
struct gliethttp_card_t {
    int irq;
    
    struct class *dchars_class;
    struct device *dchars_classdev;
    struct cdev cdev;
    dev_t devt;
};

static struct gliethttp_card_t *gcard;

static int gcard_open(struct inode *inode, struct file *file)
{
    log_printf("gcard_open\n");
    return 0;
}

static int gcard_release(struct inode *inode, struct file *file)
{
    log_printf("gcard_release\n");
    return 0;
}

static const struct file_operations gcard_fops = {
    .owner        = THIS_MODULE,
    .open        = gcard_open,
    .release    = gcard_release,
};

static int __init dchars_init(void)
{
    int retval;

    gcard = kzalloc(sizeof(*gcard), GFP_KERNEL);
    if (gcard == NULL) {
        retval = -ENOMEM;
        goto out;
    }

    gcard->dchars_class = class_create(THIS_MODULE, "dchars");
    if (IS_ERR(gcard->dchars_class)) {
        log_printf("Unable to register dchars class\n");
        retval = PTR_ERR(gcard->dchars_class);
        gcard->dchars_class = NULL;
        goto error_class;
    }
    /* devices of this class shadow the major:minor of their parent
     * device, so clear ->dev_kobj to prevent adding duplicate entries
     * to /sys/dev
     */

    gcard->dchars_class->dev_kobj = NULL;


    retval = alloc_chrdev_region(&gcard->devt, 0, 1, "dchars"); // 申请minor=0开始的1个空间,
                                                                // devt存放起始数值[luther.gliethttp]
    if (retval) {
        log_printf("Failed to alloc_chrdev_region\n");
        goto error_chrdev;
    }
    
    cdev_init(&gcard->cdev, &gcard_fops);
    retval = cdev_add(&gcard->cdev, gcard->devt, 1); // 从devt开始注册1个字符设备空间[luther.gliethttp]
    if (retval) {
        log_printf("Failed to cdev_add\n");
        goto error_cdev;
    }
    
    gcard->dchars_classdev = device_create(gcard->dchars_class, NULL,
                                           gcard->devt, NULL, "dchars"); // 参考自usb_classdev_add
    if (IS_ERR(gcard->dchars_classdev)) {
        log_printf("Failed to device_create\n");
        retval = PTR_ERR(gcard->dchars_classdev);
        gcard->dchars_classdev = NULL;
        goto error_device;
    }
out:
    return retval;
error_device:
    cdev_del(&gcard->cdev);
error_cdev:
    unregister_chrdev_region(gcard->devt, 1);
error_chrdev:
    class_destroy(gcard->dchars_class);
error_class:
    kfree(gcard);
    goto out;
}

static void __exit dchars_cleanup(void)
{
    //if (gcard->dchars_classdev)
    device_unregister(gcard->dchars_classdev);
    cdev_del(&gcard->cdev);
    unregister_chrdev_region(gcard->devt, 1);
    class_destroy(gcard->dchars_class);
    kfree(gcard);
}

module_init(dchars_init);
module_exit(dchars_cleanup);
MODULE_LICENSE("GPL");
/*
================================
可以使用modinfo查看ko依赖模块
luther@gliethttp:/vobs/tmp$ modinfo dchars.ko
filename: dchars.ko
license: GPL
srcversion: A29A046B3F84ECA76BB2967
depends:
vermagic: 2.6.27-7-generic SMP mod_unload modversions 586
================================
// 用来测试驱动test_dchars.c
#include
#include

int main(void)
{
    int retval;

    retval = open("/dev/dchars", O_WRONLY);
    printf("%d\n", retval);
    
    for (;;) {
        sleep(1);
        fprintf(stderr, ".");
    }
}
luther@gliethttp:/vobs/tmp$ sudo ./a.out
3
.....Terminated

当然可以配置udev脚本,让/dev/dchars字符设备节点的自动修改执行权限
luther@gliethttp:~$ sudo vim /etc/udev/rules.d/40-basic-permissions.rules
# 在文件结尾追加如下一条rules规则[luther.gliethttp]
KERNEL=="dchars",            MODE="0666"
================================
Makefile文件:

obj-m :=dchars.o
CURRENT_PATH := $(shell pwd)
LINUX_KERNEL_PATH := /lib/modules/`uname -r`/build

all:
    make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) modules
clean:
    rm -rf .*.cmd *.o *.mod.c *.ko .tmp_versions Module.symvers modules.order Module.markers .Makefile.swp
*/


阅读(1568) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~