Chinaunix首页 | 论坛 | 博客
  • 博客访问: 384631
  • 博文数量: 57
  • 博客积分: 2299
  • 博客等级: 大尉
  • 技术积分: 1109
  • 用 户 组: 普通用户
  • 注册时间: 2008-05-27 23:12
文章分类
文章存档

2011年(4)

2010年(53)

分类: 嵌入式

2010-08-09 20:00:48

/* char.c
*字符设备驱动模板,用于快速建立驱动框架
*/

#include <linux/module.h>            /*__init, __exit, module_init*/
#include <linux/types.h>            /* size_t */
#include <linux/fs.h>                /*file_operations*/
#include <linux/cdev.h>                /*stuct cdev*/

#include "char.h"
static int xxx_major = 0;
static int xxx_minor = 0;

struct xxx_devt
{
    struct cdev cdev;
    //....

}xxx_dev;
static ssize_t xxx_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos)
{
    struct xxx_devt *dev=filp->private_data;/*读取私有数据*/
    //...
    copy_to_user();/*设备到用户空间*/
    //...

}
static ssize_t xxx_write(struct file *filp, char __user *buf, size_t count, loff_t *f_pos)
{
    struct xxx_devt *dev=filp->private_data;/*读取私有数据*/
    //...
    copy_from_user();/*用户空间到设备*/
    //...

}
static int xxx_open(struct inode *inode, struct file *filp)
{
    filp->private_data = &xxx_dev;/*私有数据指针传递数据*/
    //...
}
static int xxx_ioctl(struct inode *inodep,struct file *filp,unsigned int cmd, unsigned long arg)
{
    int err = 0;
    int retval;
    int tmp;
    /* don't even decode wrong cmds: better returning ENOTTY than EFAULT */
    if (_IOC_TYPE(cmd) != XXX_IOC_MAGIC)
        return -ENOTTY;
    if (_IOC_NR(cmd) > XXX_IOC_MAXNR)
        return -ENOTTY;
    
    switch(cmd) {
        case XXX_IOCRESET:
            reset();
        break;
        case XXX_IOCGQUANTUM:
            retval = __put_user(tmp, (int __user *)arg);/*把数据从驱动传到用户空间*/
        break;
        case XXX_IOCSQSET:
            if (! capable (CAP_SYS_ADMIN))
                return -EPERM;
            retval = __get_user(tmp, (int __user *)arg);/*把数据从用户空间传到驱动*/
        break;
        case XXX_IOCXQSET:
            if (! capable (CAP_SYS_ADMIN))
                return -EPERM;
            retval = __get_user(tmp, (int __user *)arg);
            if(retval == 0)
                retval = __put_user(tmp, (int __user *)arg);
        break;
        default:
            return -ENOTTY;
            
    }
}
static struct file_operations xxx_fops =
{
    .owner    =THIS_MODULE,
    .read    =xxx_read,
    .write    =xxx_write,
    .open    =xxx_open,
    .ioctl    =xxx_ioctl,
//    .close    =xxx_close,

};
static int __init xxx_init(void)
{
    int rt;
    int count=1;
    dev_t dev;
    if(xxx_major)        /*获取设备号*/
    {
        dev = MKDEV(xxx_major,xxx_minor);
        rt = register_chrdev_region(dev, count, "xxx");
    } else {
        rt = alloc_chrdev_region(&dev, xxx_minor, count, "xxx");
        xxx_major = MAJOR(dev);
    }
    if(rt < 0)
        printk(KERN_WARNING"Major Error!\n");

    dev = MKDEV(xxx_major, 0);
    cdev_init(&xxx_dev.cdev, &xxx_fops);
    xxx_dev.cdev.owner = THIS_MODULE;
    xxx_dev.cdev.ops = &xxx_fops;
    rt = cdev_add(&xxx_dev.cdev, dev, count);
    if( rt )
    {
        printk(KERN_WARNING"Cdev Add Error!\n");
        cdev_del(&xxx_dev.cdev);
        return -1;
    }
    return 0;
}

static void __exit xxx_exit(void)
{
    cdev_del(&xxx_dev.cdev);
    unregister_chrdev_region(MKDEV (xxx_major, xxx_minor), 1);
}

module_init(xxx_init);
module_exit(xxx_exit);

MODULE_AUTHOR("gfy @ CQUPT");
MODULE_DESCRIPTION("Character Driver Model");
MODULE_LICENSE("GPL");


/* char.h
*IOCTL控制声明
*/

#ifndef __XXX_H__
#define __XXX_H__
#define XXX_IOC_MAGIC    'K'

#define XXX_IOCRESET    _IO(XXX_IOC_MAGIC, 0)

/*无参数命令,不需要传送参数*/
#define XXX_IOCGQUANTUM    _IOR(XXX_IOC_MAGIC, 1, int)    

/*从驱动中读取数据*/
#define XXX_IOCSQSET    _IOW(XXX_IOC_MAGIC, 2, int)   

 /*写入数据命令*/
#define XXX_IOCXQSET    _IOWR(XXX_IOC_MAGIC,3, int)/*双向传输*/

#define XXX_IOC_MAXNR    10
#endif

Makefile

# If KERNELRELEASE is defined, we've been invoked from the
# kernel build system and can use its language.
FILENAME = char
ifneq ($(KERNELRELEASE),)
 obj-m := $(FILENAME).o
# Otherwise we were called directly from the command
# line; invoke the kernel build system.
else
KERNELDIR ?= /root/pxa270/linux/linux-2.6.18
 PWD := $(shell pwd)
default:
 $(MAKE) -C $(KERNELDIR) M=$(PWD) modules
 @rm -vf *.o *.order *.symvers *.mod.* *~ *.markers
 @cp -vf $(FILENAME).ko /nfs
endif
clean:
 @rm -vf *.ko /nfs/$(FILENAME).ko

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