驱动学习6--新接口alloc_chrdev_region&cdev_alloc的使用

驱动

#include        // module_init  module_exit
#include          // __init   __exit
#include            //register_chrdev   file_operations
#include         //copy_from_user    copy_to_user
#include      //gpio virtual address
#include      //gpio virtual address
#include          

#define DEMO_MAJOR  200
#define DEMO_CNT    1
#define DEMO_NAME   "demo_char"

#define GPJ0CON *((volatile unsigned int *)S5PV210_GPJ0CON)
#define GPJ0DAT *((volatile unsigned int *)S5PV210_GPJ0DAT)

static dev_t mydev;
static struct cdev *pcdev;

static int demo_chrdev_open(struct inode *inode, struct file *file)
{
    GPJ0CON &= 0xff000fff;
    GPJ0CON |= (1<<12)|(1<<16)|(1<<20);
    GPJ0DAT |= ((1<<3)|(1<<4)|(1<<5));
    printk(KERN_INFO "demo_chrdev_open\n");/*open的调试代码*/
    return 0;
}

static int demo_chrdev_release(struct inode *inode, struct file *file)
{
    GPJ0DAT |= ((1<<3)|(1<<4)|(1<<5));
    printk(KERN_INFO "demo_chrdev_release\n");/*close的调试代码*/
    return 0;
}

static ssize_t demo_chrdev_write(struct file *file, const char __user *ubuf, size_t count, loff_t *ppos)
{
    int ret = -1;
    char kbuf[100] = {0};
    ret = copy_from_user(kbuf,ubuf,count);/*返回值为0成功*/
    if(ret)
    {
        printk(KERN_ERR "copy_from_user fail\n");
        return -EINVAL;
    }
    if(!strcmp(kbuf,"0"))   /*亮*/
        GPJ0DAT &= ~((1<<3)|(1<<4)|(1<<5));
    else if(!strcmp(kbuf,"1"))  /*灭*/
        GPJ0DAT |= ((1<<3)|(1<<4)|(1<<5));
    else 
        printk(KERN_INFO "input err\r\n");
    printk(KERN_INFO "copy_from_user %s\r\n",kbuf);
    return 0;
}

static const struct file_operations demo_fops = {
    .owner      = THIS_MODULE,/*惯例,直接写即可*/  
    .open       = demo_chrdev_open,/*把open的api与此函数联系起来*/
    .release    = demo_chrdev_release,/*把close的api于此函数联系起来*/
    .write      = demo_chrdev_write,/*把write的api于此函数联系起来*/
};

static int __init chrdev_init(void) /*模块安装*/
{   
    int ret = -1;

    ret = alloc_chrdev_region(&mydev,12,DEMO_CNT,DEMO_NAME);/* 自动分配主设备号*/
    if(ret<0)
    {
        printk(KERN_ERR "register_chrdev_region error\r\n");
        goto alloc_err;
    }
    pcdev =  cdev_alloc();  /*给pcdev分配内存,会在cdev_del中自动释放*/
    pcdev->owner = THIS_MODULE;
    pcdev->ops = &demo_fops;

    ret = cdev_add(pcdev, mydev, DEMO_CNT);/*注册设备驱动*/
    if(ret)
    {
        printk(KERN_ERR "cdev_add error\r\n");
        goto add_err;
    }
    printk(KERN_INFO "chrdev_init %d    %d\n",MAJOR(mydev),MINOR(mydev));
    return 0;

add_err:    cdev_del(pcdev);
alloc_err:  return -EINVAL;
}

static void __exit chrdev_exit(void)/*模块卸载*/
{
    cdev_del(pcdev);/*注销设备驱动*/
    unregister_chrdev_region(mydev,DEMO_CNT);/*注销申请的设备号*/
}


module_init(chrdev_init);
module_exit(chrdev_exit);

MODULE_LICENSE("GPL");/*描述模块的许可证*/
MODULE_AUTHOR("Xin-Ya Zhu");/*描述模块的作者*/
MODULE_DESCRIPTION("demo test");/*描述模块的介绍信息*/   
MODULE_ALIAS("alias xxx");/*描述模块的别名信息*/

应用

#include 
#include 
#include 

#include   //open close
#include 
#include 


#define FILE    "/dev/demo_text"
#define LED_ON  "0"
#define LED_OFF "1"

int main(void)
{
    int fd = -1;
    char buf[100] = {0};

    fd = open(FILE,O_RDWR);
    if(fd<0)
    {
        printf("open error.\n");
        return -1;
    }

    write(fd,LED_ON,strlen(LED_ON));
    sleep(1);
    write(fd,LED_OFF,strlen(LED_OFF));
    sleep(1);
    write(fd,LED_ON,strlen(LED_ON));
    sleep(1);
    write(fd,LED_OFF,strlen(LED_OFF));
    sleep(1);

    close(fd);

    return 0;
}

/***************************
[root@zhuxinya text]# insmod demo.ko 
[   16.507874] chrdev_init 250  12
[root@zhuxinya text]# mknod /dev/demo_text c 250 012
[root@zhuxinya text]# ./app 
[   30.405199] demo_chrdev_open
[   30.407220] copy_from_user 0
[   31.489561] copy_from_user 1
[   32.491128] copy_from_user 0
[   33.492682] copy_from_user 1
[   34.494248] demo_chrdev_release
[root@zhuxinya text]# rm /dev/demo_text 
[root@zhuxinya text]# rmmod demo.ko 
*****************************/

你可能感兴趣的:(驱动学习6--新接口alloc_chrdev_region&cdev_alloc的使用)