paltform框架的驱动形式实现在应用层通过ioctl控制LED灯流水,当按键KEY1按下,让风扇转动

作业要求:

        paltform框架的驱动形式实现在应用层通过ioctl控制LED灯流水,当按键KEY1按下,让风扇转动

头文件:

#ifndef __MYLED_H__
#define __MYLED_H__
 
#define LED_1ON _IOW('a',1,int)
#define LED_2ON _IOW('a',2,int)
#define LED_3ON _IOW('a',3,int)
 
#endif

应用层源文件:

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include "test.h"
 
int main(int argc,const char * argv[])
{
    char buf[128] = {0};
    int whitch;
    int fd = -1;
    fd = open("/dev/myself0",O_RDWR);
    if(fd == -1)
    {
        perror("open is error\n");
        return -1;
    }
    printf("文件打开成功\n");
    while(1)
    {
        ioctl(fd,LED_1ON,&whitch);
        sleep(1);
        ioctl(fd,LED_2ON,&whitch);
        sleep(1);
        ioctl(fd,LED_3ON,&whitch);
        sleep(1);
 
    }
 
 
    close(fd);
    return 0;
}

驱动源文件:

#include 
#include 
#include 
#include 
#include
#include
#include
#include
#include
#include
#include 
#include 
#include 
#include "test.h"
#define CNAME "myself"
struct device_node *dnode;
struct device_node *dnode1;
int irqno;
//tasklet对象分配
struct tasklet_struct tasklet;
 
//解析gpio编号
int gpiono[4];
 
 
struct class * cls;
struct device * dev;
unsigned int minor = 0;
 
#if 0
unsigned int major = 0; //动态申请主设备号
#else
unsigned int major = 495;   //静态申请主设备号
#endif
 
int myled_open(struct inode *inode, struct file *file)
{
    printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);
    printk("myled_open\n");
    return 0;
}
ssize_t myled_read (struct file *file, char __user *ubuf, size_t size, loff_t *loff)
{
    printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);
    printk("myled_read\n");
    return 0;
}
ssize_t myled_write(struct file *file, const char __user *ubuf, size_t size, loff_t *loff)
{
    printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);
    printk("myled_write\n");
    return 0;
}
int myled_close (struct inode *inode, struct file *file)
{
    printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);
    printk("myled_close\n");
    return 0;
}
 
long myled_ioctl (struct file *file, unsigned int cmd, unsigned long args)
{
 
    //1.判断cmd switch(cmd)
    //2.判断操作哪盏灯进行点亮 copy_from_user
    switch(cmd)
    {
        case LED_1ON:
            gpio_set_value(gpiono[0],1);
            gpio_set_value(gpiono[1],0);
            gpio_set_value(gpiono[2],0);
            break;
        case LED_2ON:
            gpio_set_value(gpiono[0],0);
            gpio_set_value(gpiono[1],1);
            gpio_set_value(gpiono[2],0);
            break;
        case LED_3ON:
            gpio_set_value(gpiono[0],0);
            gpio_set_value(gpiono[1],0);
            gpio_set_value(gpiono[2],1);
            break;
    }
    return 0;
 
}
 
const struct file_operations fops = {
    .open = myled_open,
    .read = myled_read,
    .write = myled_write,
    .unlocked_ioctl = myled_ioctl,
    .release = myled_close,
};
 
//对象指针
struct cdev *cdev_p = NULL;
int ret = 0;
int i = 0;
dev_t  dev_val = 0; 
 
//工作队列对象分配
struct work_struct work;
 
//底半部函数
void work_func(struct work_struct *work)
{
    printk("工作队列\n");
    gpio_set_value(gpiono[3],!gpio_get_value(gpiono[3]));
}
//中断 处理函数
irqreturn_t irq1_handler(int irqno, void *arg)
{
      printk("key interrupt\n");
      //开启中断底半部
      schedule_work(&work);
 
    return  IRQ_HANDLED;
}
//分配对象并且初始化
//probe函数
int pdrv_probe(struct platform_device *pdev)
{
    int i;
    int j = 0;
    printk("进入函数\n");
    //1.分配对象
    cdev_p = cdev_alloc();
    if(NULL == cdev_p)
    {
        printk("分配对象空间失败\n");
        ret = -ENOMEM;
        goto ERR1;
    }
    printk("分配对象空间成功\n");
 
    //2.对象初始化
    cdev_init(cdev_p,&fops);
 
    //3.设备资源的申请(设备号)
    if(0 == major)
    {
        ret = alloc_chrdev_region(&dev_val,minor,3,"myself");
        if(ret)
        {
            printk("动态申请设备号失败\n");
            goto ERR2;
        }
        major = MAJOR(dev_val); //获取主设备号
        minor = MINOR(dev_val); //获取次设备号
    }
    else if(major>0)
    {
        ret = register_chrdev_region(MKDEV(major,minor),3,"myself");
        if(ret)
        {
            printk("静态申请设备号失败\n");
            goto ERR2;
        }
    }
 
    //4.注册
    ret = cdev_add(cdev_p,MKDEV(major,minor),3);
    if(ret)
    {
        printk("驱动对象注册进内核失败\n");
        goto ERR3;
    }
    printk("驱动对象注册进内核成功\n");
 
    //5.向上提交目录
    cls = class_create(THIS_MODULE,"myself");
    if(IS_ERR(cls))
    {
        printk("向上提交目录失败\n");
        goto ERR4;
    }
    printk("向上提交目录成功\n");
 
    //6.向上提交设备节点信息
    for(i=0;i<3;i++)
    {
        dev = device_create(cls,NULL,MKDEV(major,i),NULL,"myself%d",i);
        if(IS_ERR(dev))
        {
            printk("向上提交节点信息失败\n");
            goto ERR5;
        }
    }
    printk("向上提交节点信息成功\n");
 
    //解析设备树节点
    dnode=of_find_node_by_name(NULL,"myplatform");
    if(dnode==NULL)
    {
        printk("解析设备树节点失败\n");
        return -EIO;
    }
    printk("解析设备树节点成功\n");
 
    //根据设备树节点解析gpio编号
    gpiono[0]= of_get_named_gpio(dnode,"led1",0);
    if(gpiono[0]<0)
    {
        printk("1解析gpio编号失败\n");
        return -EIO;
    }
    printk("1解析gpio编号成功\n");
    gpiono[1]= of_get_named_gpio(dnode,"led2",0);
    if(gpiono[1]<0)
    {
        printk("2解析gpio编号失败\n");
        return -EIO;
    }
    printk("2解析gpio编号成功\n");
    gpiono[2]= of_get_named_gpio(dnode,"led3",0);
    if(gpiono[2]<0)
    {
        printk("3解析gpio编号失败\n");
        return -EIO;
    }
    printk("3解析gpio编号成功\n");
    gpiono[3]= of_get_named_gpio(dnode,"pwm1",0);
    if(gpiono[3]<0)
    {
        printk("4解析gpio编号失败\n");
        return -EIO;
    }
    printk("4解析gpio编号成功\n");
 
    //申请gpio编号
    //设置gpio为输出并且初始化数值为0
    for(j=0;j<4;j++)
    {   
        //申请gpio编号
        gpio_request(gpiono[j],NULL);
        
        //设置gpio为输出并且初始化数值为0
        gpio_direction_output(gpiono[j],0);
    }
 
        //解析设备树节点
    dnode1=of_find_node_by_name(NULL,"myirqs");
    if(dnode==NULL)
    {
        printk("解析设备树节点失败\n");
        return -EIO;
    }
    printk("解析设备树节点成功\n");
    //根据设备树节点解析出软中断号
    irqno=irq_of_parse_and_map(dnode1,0);
    if(!irqno)
    {
        printk("获取软中断号失败\n");
        return -ENXIO;
    }
    printk("解析设备树获取软中断号成功\n");
    //注册中断
    request_irq(irqno,irq1_handler,IRQF_TRIGGER_FALLING,"myirq",(void *)0);
    //初始化工作队列对象
    INIT_WORK(&work,work_func); 
 
    return 0;
ERR5:
    for(--i;i>=0;i--)
    {
        device_destroy(cls,MKDEV(major,i));
    }
    class_destroy(cls);
 
ERR4:
    cdev_del(cdev_p);
ERR3:
    unregister_chrdev_region(MKDEV(major,minor),3);
ERR2:
    kfree(cdev_p);
ERR1:
    return ret;
}
//remove函数
int pdrv_remove(struct platform_device *pdev)
{
    int i;
    printk("退出函数\n");
    for(i=0;i<3;i++)
        {
            device_destroy(cls,MKDEV(major,i));
        }
    class_destroy(cls);
 
    cdev_del(cdev_p);
    unregister_chrdev_region(MKDEV(major,minor),3);
    kfree(cdev_p);
 
    for(i=0;i<4;i++)
    {
        gpio_free(gpiono[i]);
    }
    return 0;
}

//构建设备树匹配标配
struct of_device_id oftable[] = 
{
    {.compatible = "hqyj,platform"},
    {.compatible = "hqyj,platform1"},
    {},
};

//分配对象并且初始化
struct platform_driver pdrv={
    .probe=pdrv_probe,
    .remove=pdrv_remove,
    .driver={
        .name="aaaaa",
        .of_match_table=oftable,//设置设备树匹配     
    },
};
//一键注册宏
module_platform_driver(pdrv);
MODULE_LICENSE("GPL");

实验现象:

 

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