绑定设备文件与设备

head.h

#ifndef __HEAD_H__

#define __HEAD_H__

typedef struct

{

    unsigned int MODER;

    unsigned int OTYPER;

    unsigned int OSPEEDR;

    unsigned int PUPDR;

    unsigned int IDR;

    unsigned int ODR;

} gpio_t;

#define PHY_LED1_ADDR 0X50006000

#define PHY_LED2_ADDR 0X50007000

#define PHY_LED3_ADDR 0X50006000

#define PHY_RCC_ADDR 0X50000A28

#define LED_ON _IOW('l',1,int)

#define LED_OFF _IOW('l',0,int)

#endif

test.c

#include

#include

#include

#include

#include

#include

#include

#include

#include"head.h"

int main(int argc,const char * argv[])

{

    char buf[128]={0};

    int a,b;

   

    printf("打开设备文件成功\n");

     while(1)

    {

        //从终端读取

        int fd;

        printf("请选择要控制的灯:1(LED1)2(LED2)3(LED3)\n");

        printf("请输入>");

        scanf("%d",&a);

        printf("请输入要实现的功能 ");

        printf("0(关灯) 1(开灯)\n");

        printf("请输入>");

        scanf("%d",&b);

        switch(a)

        {

            case 1:

            fd=open("/dev/mycdev0",O_RDWR);

            if(fd < 0)

             {

                printf("打开设备文件失败\n");

              return -1;

             }

             if(b==1)

                ioctl(fd,LED_ON,&b);

             if(b==0)

                ioctl(fd,LED_OFF,&b);

                break;

            case 2:

            fd=open("/dev/mycdev1",O_RDWR);

            if(fd < 0)

             {

                printf("打开设备文件失败\n");

              return -1;

             }

                if(b==1)

                ioctl(fd,LED_ON,&b);

             if(b==0)

                ioctl(fd,LED_OFF,&b);

                break;

            case 3:

            fd=open("/dev/mycdev2",O_RDWR);

            if(fd < 0)

             {

                printf("打开设备文件失败\n");

              return -1;

             }

             if(b==1)

                ioctl(fd,LED_ON,&b);

             if(b==0)

                ioctl(fd,LED_OFF,&b);

                break;

        }

        close(fd);

    }

   

    return 0;

}

mycdev.c

#include

#include

#include

#include

#include

#include

#include

#include

#include"head.h"

char kbuf[128]={0};

gpio_t *vir_led1;

gpio_t *vir_led2;

gpio_t *vir_led3;

unsigned int *vir_rcc;

struct cdev *cdev;

unsigned int major=0;

unsigned int minor=0;

dev_t devno;

struct class *cls;

struct device *dev;

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

{

    int min=MINOR(inode->i_rdev);//获取打开的的文件的次设备号

    file->private_data= (void *)min;

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

    return 0;

}

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

{

   int min=(int)file->private_data;//获取到文件的次设备号

   switch(min)

   {

        case 0://操作LED1

            switch(cmd)

            {

                case LED_ON://开灯

                vir_led1->ODR |= (0X1<<10);

                    break;

                case LED_OFF: //关灯

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

                    break;

            }

            break;

        case 1://操作LED2

            switch(cmd)

            {

                case LED_ON://开灯

                vir_led2->ODR |= (0X1<<10);

                    break;

                case LED_OFF: //关灯

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

                    break;

            }

            break;

        case 2://操作LED3

            switch(cmd)

            {

                case LED_ON://开灯

                vir_led3->ODR |= (0X1<<10);

                    break;

                case LED_OFF://关灯

                vir_led3->ODR &= (~(0X1<<10));

                    break;

            }

            break;

   }

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

    return 0;

}

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

{

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

    return 0;

}

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

struct file_operations fops = {

    .open = mycdev_open,

    .unlocked_ioctl = mycdev_ioctl,

    .release = 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) |= (3<<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_led1->MODER |= (1<<16);

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

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

    return 0;

}

static int __init mycdev_init(void)

{

    int ret;

    //申请一个对象空间 cdev_alloc

    cdev=cdev_alloc();

    if(cdev==NULL)

    {

        printk("申请对象空间失败\n");

        ret=-EFAULT;

        goto out1;

    }

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

    //初始化对象 cdev_init

    cdev_init(cdev, &fops);

    //申请设备号

    if (major==0)

    {

        ret=alloc_chrdev_region(&devno, minor, 3,"mychrdev");

        if(ret)

        {

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

            goto out2;

        }

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

        minor=MINOR(devno);//根据设备获取次设备号

        printk("字符主设备驱动注册成功:major=%d\n",major);

        printk("字符次设备驱动注册成功:minor=%d\n",minor);

    }

    else

    {

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

        if(ret)

        {

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

            goto out2;

        }

    }

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

    //注册驱动对象

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

    if(ret)

    {

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

        goto out3;

    }

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

    //向上提交目录

    cls=class_create(THIS_MODULE,"mychrdev");

    if(IS_ERR(cls))

    {

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

        goto out4;

    }

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

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

    int i;

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

    {

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

        if(IS_ERR(dev))

        {

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

            goto out5;

        }

    }

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

    all_led_init();

    return 0;

out5:

    //将提交成功的信息释放

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

    {

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

    }

    //将提交失败的信息销毁

    class_destroy(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;

    iounmap(vir_led1);

    iounmap(vir_led2);

    iounmap(vir_led3);

    iounmap(vir_rcc);

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

    {

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

    }

    //销毁目录

    class_destroy(cls);

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

    cdev_del(cdev);

    //释放设备号

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

    //释放申请到的字符设备驱动对象空间

    kfree(cdev);

}

module_init(mycdev_init);

module_exit(mycdev_exit);

MODULE_LICENSE("GPL");

你可能感兴趣的:(linux,运维,服务器)