9.13作业

#include

#include

#include

#include

#include

#include

#include

struct cdev *cdev

char kbuf[128]=0;

unsigned int major=0;

unsigned int minor=0;

dev_t devno;

module-param(major,unit,0664); //方便在命令行传递major的值

struct class*cls;

struct device *dev;

struct mutex mutex; //定义互斥体



 

int mycdev_open(struct inode *inode,struct file*file)

{

    mutex_lock(&mutex);//上锁

    printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);

    return 0;

}

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

{

    int which;

    //获取arg对应的用户空间中的值

    int ret=copy_from_user(&which,(void *)arg,4);

    if(ret)

    {

        printk("从用户空间获取数据失败\n");

        return -EIO;

    }

    switch (cmd)

    {

        case LED_ON:

        switch(which)

        {

            case 1: //LED1

                vir_led1->ODR |= 1 << 10;

                break;

            case 2:

                vir_led2->ODR |= 1 << 10;

                break;

            case 3:

                vir_led3->ODR |= 1 << 8;

                break;

        }

        break;

        case LED_OFF:

        switch(which)

        {

            case 1: //LED1

                 vir_led1->ODR &= (~(1 << 10));

                 break;

            case 2:

                 vir_led2->ODR &= (~(1 << 10));

                 break;

            case 3:

                 vir_led3->ODR &= (~(1 << 8));

                 break;

        }

        break;

    }

    return 0;

}

nt mycdev_close(struct inode *inode,struct file *file)

{

     mutex_unlock(mutex);//解锁

     printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);

     return 0;

}

//定义操作方法结构体变量并赋值

struct file_operation fops={

    .open=mycdev_open,

    .read=mycdev_read,

    .write=mycdev_write,

    .realease=mycdev_close,

};

int all_led_init(void)

{

    vir_led1=ioremap(PHY_LED1_ADDR,sizeof(gpio_t));

    if(vir_led1==NULL)

    {

        printk("ioremap filed: %d\n",__LINE__);

        return -ENOMEM;

    }

      vir_led2=ioremap(PHY_LED2_ADDR,sizeof(gpio_t));

    if(vir_led2==NULL)

    {

        printk("ioremap filed: %d\n",__LINE__);

        return -ENOMEM;

    }

    vir_led3=vir_led1;

    vir_rcc=ioremap(PHY_RCC_ADDR,4);

    if(vir_rcc==NULL)

    {

        printk("ioremap filed: %d\n",__LINE__);

        return -ENOMEM;

    }

printk("物理地址映射成功\n");

//寄存器的初始化

//rcc

(*vir_rcc) |= (0x3<<4);

//LED1

vir_led1->MODER &= (~(3<<20));

vir_led1->MODER |= (1<<20);

vir_led1->ODR &= (~(1<<10));

//LED2

vir_led2->MODER &= (~(3<<20));

vir_led2->MODER |= (1<<20);

vir_led2->ODR &= (~(1<<10));

//LED3

vir_led3->MODER &= (~(3<<16));

vir_led3->MODER |= (1<<16;

vir_led3->ODR &= (~(1<<8));

printk("寄存器初始化成功\n");

return 0;

}

static int __init mycdev_init(void)

{

    int ret;

    //为字符设备驱动对象申请空间

    cdev=cdev_alloc();

    if(cdev==NULL)

    {

        printk(" 字符设备驱动对象申请空间失败\n");

        ret=-EFAULT;

        goto out1;

       

    }

    printk("申请对象空间成功");

    //初始化字符设备驱动对象

    cdev——init(cdev,&fops);

    //申请设备号

    if(major>0)//静态指定设备号

    {

        ret=register_chrdev_region(MKDEV(major,minor),3,"myled");

        if(ret)

        {

            printk("静态申请设备号失败\n");

            goto out2;

        }

    }

    else if(major==0)//动态申请设备号

    {

       ret=register_chrdev_region(MKDEV(major,minor),3,"myled");

        if(ret)

        {

            printk("动态申请设备号失败\n");

            goto out2;

        }

        major=MAJOR(devno);//获取主设备号

        major=MINOR(devno);//获取次设备号

    }

    printk("申请设备号成功\n");

   

    mutex_init(&mutex);//初始化互斥体  

    //字符设备驱动对象注册

    ret=cdev_add(cdev,MKDEV(major,minor),3);

    if(ret)

    {

        printk("字符设备驱动对象注册失败\n");

        goto out3;

    }

    printk("字符设备驱动对象注册成功\n");

    //寄存器映射以及初始化

    all_led_init();

    //向上提交目录

    cls=class_create(THIS_MODULE,"myled");

    if(IS_ERR(cls))

    {

        printk("向上提交目录失败\n");

        return -PTR_ERR(cls);

        goto out4;

    }

    printk("向上提交目录成功\n");

    //向上提交设备节点信息

    int i;

    for(i=0;i<3;i++)

    {

        dev=device_create(cls,NULL,MKDEV(major,i)NULL,"mychrdevv%d",i);

        if(IS_ERR(dev))

        {

            printk("向上提交设备节点信息失败\n");

            return -PTR_ERR(dev);

        }

    }

    printk("向上提交设备节点信息成功\n");

    return 0;

}

out5:

     //释放前一次提交成功的设备信息

     for(--i;i>=0;i--)

     {

        device_destory(cls,MKDEV(major,i));

     }

     class_destory(cls);//释放目录

out4:

    cdev_del(cdev);

out3:

     unregister_chrdev_region(MKDEV(major,minor),3);

out2:

    kfree(cdev);

out1:

    return ret;

static void __exit mycdev_exit(void)

{

    //销毁设备节点信息

    int i;

    for(i=0;i<3;i++)

    {

        device_destory(cls,MKDEV(major,i));

    }

    //销毁目录信息

    class_destory(cls);

    //取消地址映射

    iounmap(vir_led1);

    iounmap(vir_led2);

    iounmap(vir_rcc);

    //注销字符设备驱动对象

    cdev_del(cdev);

    //释放设备号

    unregister_chrdev_region(MKDEV(major,minor),3);

    //释放对象空间

    kfree(cdev);

   

}

module_init(mycdev_init);

module_exit(mycdev_exit);

MODULE_LICENSE("GPL");

你可能感兴趣的:(c语言)