⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 chardev.c

📁 基于linux2.6内核的字符驱动的编写,调试过程,在PC机和s3c2410嵌入式系统中正常可用.
💻 C
字号:
  /*
   *  chardev.c  kf701  2006/12/05
   *  /dev/kf701_chardev0  /proc/devices
   */
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <asm/uaccess.h>
#include <linux/cdev.h>
static int      chardev_open(struct inode *, struct file *);
static int      chardev_release(struct inode *, struct file *);
static ssize_t  chardev_read(struct file *, char __user *, size_t, loff_t *);
static ssize_t  chardev_write(struct file *, const char __user *, size_t, loff_t *);
#define SUCCESS 0
#define DEVICE  "kf701_chardev"
int major = 233;
int minor = 0;
struct file_operations fops = {
    .owner =        THIS_MODULE,
    .read =         chardev_read,
    .write =        chardev_write,
    .open =         chardev_open,
    .release =      chardev_release,
};
struct my_dev{
    uint8_t *buf;
    uint32_t size;
    uint32_t index;
    struct semaphore sem;
    struct cdev cdev;
} kf701_dev;
static int __init chardev_init(void){
    // 1. 分配主设备号
    dev_t devno = MKDEV( major, minor );
    int ret = register_chrdev_region( devno, 1, DEVICE );
    if( ret < 0 )
    {
        printk(KERN_DEBUG "register major number failed with %d\n", ret);
        return ret;
    }
    printk(KERN_DEBUG "%s:register major number OK\n",DEVICE);
    // 2. 注册设备
    cdev_init( &kf701_dev.cdev, &fops );
    kf701_dev.cdev.ops = &fops;
    kf701_dev.cdev.owner = THIS_MODULE;
    ret = cdev_add( &kf701_dev.cdev, devno, 1 );
    if( ret < 0 )
    {
    printk(KERN_DEBUG "register device failed with %d\n", ret);
    return ret;
    }
    printk(KERN_DEBUG "%s:register device OK\n",DEVICE);
    // 3. 分配本驱动要使用的内存
    kf701_dev.index = 0;
    kf701_dev.size = 1024;
    kf701_dev.buf = kmalloc( kf701_dev.size, GFP_KERNEL );
    if( NULL == kf701_dev.buf )
    {
    printk(KERN_DEBUG "kmalloc failed\n");
    return -ENOMEM;
    }
    printk(KERN_DEBUG "%s:kmalloc buffer OK\n",DEVICE);
    // 初始化信号量
    init_MUTEX( &(kf701_dev.sem) );
    printk(KERN_DEBUG "%s:init semaphore OK\n",DEVICE);
    return SUCCESS;
    }
static void __exit chardev_exit(void)
    {
    dev_t devno = MKDEV( major, minor );
    cdev_del( &kf701_dev.cdev );
    unregister_chrdev_region( devno, 1 );
    printk(KERN_DEBUG "%s:unregister device OK\n",DEVICE);
    }
int chardev_open(struct inode *inode, struct file *file)
    {
    struct my_dev *dev = container_of(inode->i_cdev, struct my_dev, cdev);
     file->private_data = dev;
     printk(KERN_DEBUG "%s:open OK\n",DEVICE);
     return SUCCESS;
     }
int chardev_release(struct inode *inode, struct file *file)
{
    printk(KERN_DEBUG "%s:release OK\n",DEVICE);
    return SUCCESS;
}
ssize_t chardev_read(struct file *file, char __user *buf, size_t count,loff_t *offset)
{
    struct my_dev *dev = file->private_data;
    ssize_t retval = 0;
    if( down_interruptible(&dev->sem) )
    return -ERESTARTSYS;
    printk(KERN_DEBUG "%s:read down sem OK\n",DEVICE);
    if( 0 == dev->index )
    goto out;
    if( *offset >= dev->index )
    goto out;
    if( (*offset+count) > dev->index )
    count = dev->index - *offset;
    if( copy_to_user(buf, dev->buf + *offset, count) )
    {
       retval = -EFAULT;
       goto out;
    }
    *offset += count;
    retval = count;
 out:
    up(&dev->sem);
    printk(KERN_DEBUG "%s:read up sem OK\n",DEVICE);
    return retval;
    }
    //  omit offset argument for write
    ssize_t chardev_write(struct file *file, const char __user *buf, size_t count, loff_t *offset)
    {
     struct my_dev *dev = file->private_data;
     ssize_t retval = -ENOMEM;
     if( down_interruptible(&dev->sem) )
        return -ERESTARTSYS;
     printk(KERN_DEBUG "%s:write down sem OK\n",DEVICE);
    if( count > dev->size )
    goto out;
    if( copy_from_user(dev->buf, buf, count) )
    {
    retval = -EFAULT;
   goto out;
    }
    dev->index = count;
    retval = count;
 out:
    up(&dev->sem);
    printk(KERN_DEBUG "%s:write up sem OK\n",DEVICE);
    return retval;
    }
    module_init(chardev_init);
    module_exit(chardev_exit);
    MODULE_AUTHOR("kf701.ye at gmail.com");
    MODULE_DESCRIPTION("Study for kf701");
    MODULE_SUPPORTED_DEVICE(DEVICE);
    MODULE_LICENSE("GPL");

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -