zoukankan      html  css  js  c++  java
  • 设备驱动基础学习--platform driver简单实现

    platform是一条虚拟的总线。设备用platform_device表示,驱动用platform_driver进行注册,Linux platform driver机制和传统的device driver机制(通过driver_register进行注册)相比,一个明显的优势在于platform机制将设备本身的资源注册进内核,由内核统一管理,在驱动中使用这些资源时通过platform device提供的标准结构进行申请并使用。这样提高了驱动和资源的独立性,并且具有较好的可移植性和安全性(这些标准接口是安全的)。

    pltform机制本身使用并不复杂,由两部分组成:platform_device和platform_driver。通过platform机制开发底层驱动的大致流程为:定义platform_deive->注册platform_device->定义platform_driver->注册platform_driver。

    platform driver的probe函数是平台总线实现匹配以后首先被调用的函数,因此在其中实现字符设备、块设备、网络设备驱动的初始化是有意义的,这样的设备驱动就是基于平台总线的设备驱动,便于维护。如果添加实际的设备到该平台总线设备驱动模型中,则可以在该函数中实现具体的设备驱动函数的初始化操作,包括设备号的申请,设备的初始化,添加。自动设备文件创建函数的添加等操作。或者是混杂字符设备的相关初始化操作。在remove函数中实现具体的设备的释放,包括设备的删除,设备号的注销等操作。

    基于misc device实现一个简单的platform driver(仿照driver/char/sonypi.c).

    fellowplat.h

    #ifndef _FELLOW_MISC_H_
    #define _FELLOW_MISC_H_
    #include <linux/ioctl.h>
    //#define FELLOW_MISC_MAJOR 199
    //#define FELLOW_MISC_NR 2
    struct miscdata {
    int val;
    char *str;
    unsigned int size;
    };
    #define FELLOW_MISC_IOC_MAGIC 'f'
    #define FELLOW_MISC_IOC_PRINT _IO(FELLOW_MISC_IOC_MAGIC, 1)
    #define FELLOW_MISC_IOC_GET _IOR(FELLOW_MISC_IOC_MAGIC, 2, struct miscdata)
    #define FELLOW_MISC_IOC_SET _IOW(FELLOW_MISC_IOC_MAGIC, 3, struct miscdata)
    #define FELLOW_MISC_IOC_MAXNR 3
    #endif

    fellowplat.c

    #include <linux/module.h>
    #include <linux/init.h>
    //#include <linux/moduleparam.h>
    #include <linux/types.h>
    #include <linux/miscdevice.h>
    #include <linux/platform_device.h>
    #include <linux/fs.h>
    #include <linux/errno.h>
    #include <linux/mm.h>
    #include <linux/slab.h>
    #include <asm/io.h>
    #include <asm/uaccess.h>
    #include "fellowplat.h"
    struct fellowmisc_dev{
    struct miscdevice misc;
    struct miscdata data;
    };
    struct fellowmisc_dev *fellowmisc_devp;
    int fellowmisc_open(struct inode *inode, struct file *filep)
    {
      filep->private_data = fellowmisc_devp;
      return 0;
    }
    int fellowmisc_release(struct inode *inode, struct file *filep)
    {
      return 0;
    }

    long fellowmisc_ioctl(struct file *filep,unsigned int cmd,unsigned long arg)

    {

      int ret = 0;
      struct fellowmisc_dev *devp = (struct fellowmisc_dev *)(filep->private_data);
      if (_IOC_TYPE(cmd) != FELLOW_MISC_IOC_MAGIC)
        return -EINVAL;
      if (_IOC_NR(cmd) > FELLOW_MISC_IOC_MAXNR)
        return -EINVAL;
      switch(cmd)
      {
        case FELLOW_MISC_IOC_PRINT:
          printk("FELLOW_MISC_IOC_PRINT ");
          printk("val:%d, size: %d, str: %s ", devp->data.val, devp->data.size, devp->data.str);
        break;
        case FELLOW_MISC_IOC_SET:
          printk("FELLOW_MISC_IOC_SET ");
          ret = copy_from_user((unsigned char*)&(devp->data), (unsigned char *)arg, sizeof(struct miscdata));
          printk("set val:%d, size: %d, str: %s ", devp->data.val, devp->data.size, devp->data.str);
        break;
        case FELLOW_MISC_IOC_GET:
          printk("FELLOW_MISC_IOC_GET ");
          ret = copy_to_user((unsigned char*)arg,(unsigned char*)&(devp->data), sizeof(struct miscdata));
        break;
        default:
          return -EINVAL;

      }
      return ret;
    }
    static const struct file_operations fellowmisc_fops ={
    .owner = THIS_MODULE,
    .open = fellowmisc_open,
    .release = fellowmisc_release,
    .unlocked_ioctl = fellowmisc_ioctl,
    };
    static struct miscdevice fellow_misc = {
    .minor = MISC_DYNAMIC_MINOR,
    .name = "fellowplat",
    .fops = &fellowmisc_fops,
    };
    static struct platform_device *fellow_platform_device;
    static int fellow_plat_drv_probe(struct platform_device *dev)
    {
      int error;
      printk("fellow_plat_drv_probe ");
      fellowmisc_devp = kmalloc(sizeof(struct fellowmisc_dev), GFP_KERNEL);
      if (!fellowmisc_devp)
      {
        error = -ENOMEM;
        return error;
      }
      memset(&(fellowmisc_devp->data), 0, sizeof(fellowmisc_devp->data));
      fellowmisc_devp->misc = fellow_misc;
      error = misc_register(&fellow_misc);
      return error;
    }
    static int fellow_plat_drv_remove(struct platform_device *dev)
    {
      int error;
      if (fellowmisc_devp)
        kfree(fellowmisc_devp);
      error = misc_deregister(&fellow_misc);
      return error;
    }
    static struct platform_driver fellow_platform_driver = {
    .driver = {
    .name = "fellow",
    },
    .probe = fellow_plat_drv_probe,
    .remove = fellow_plat_drv_remove,
    };

    static int fellowplat_init(void)
    {
      int error;
      printk("fellowplat_init ");
      printk("fellow register driver ");
      error = platform_driver_register(&fellow_platform_driver);//注册platform driver
      if (error)
        return error;

      fellow_platform_device = platform_device_alloc("fellow", -1);//名字与platform driver相同。
      if (!fellow_platform_device) {
        error = -ENOMEM;
        goto err_driver_unregister;
      }

      printk("fellow register device ");
      error = platform_device_add(fellow_platform_device);//添加platform device
      if (error)
        goto err_free_device;


      return 0;

    err_free_device:
      platform_device_put(fellow_platform_device);
    err_driver_unregister:
      platform_driver_unregister(&fellow_platform_driver);
      return error;
    }

    static void fellowplat_exit(void)
    {
      platform_device_unregister(fellow_platform_device);
      platform_driver_unregister(&fellow_platform_driver);
    }

    MODULE_AUTHOR("fellow");
    MODULE_LICENSE("GPL");
    module_init(fellowplat_init);
    module_exit(fellowplat_exit);

    app.c

    #include <stdio.h>
    #include <fcntl.h>
    #include <errno.h>
    #include <string.h>
    #include "fellowplat.h"
    int main(void)
    {
      int fd = open("/dev/fellowplat", O_RDWR);
      if (fd < 0)
      {
        printf("open fail:%s ", strerror(errno));
        return -1;
      }
      int ret = 0;
      struct miscdata data;
      data.val = 18;
      data.str = "fellow platform device";
      data.size = sizeof("fellow platform device");
      if ((ret = ioctl(fd, FELLOW_MISC_IOC_SET, &data)) < 0)
      {
        printf("ioctl set fail:%s ", strerror(errno));
      }
      struct miscdata getdata;
      if ((ret = ioctl(fd, FELLOW_MISC_IOC_GET, &getdata)) < 0)
      {
        printf("ioctl get fail:%s ", strerror(errno));
      }
      printf("get val:%d, str:%s, size: %d ", getdata.val, getdata.str, getdata.size);
      if ((ret = ioctl(fd, FELLOW_MISC_IOC_PRINT, NULL)) < 0)
      {
        printf("ioctl print fail:%s ", strerror(errno));
      }
      close(fd);
      return ret;
    }

    运行结果如下

  • 相关阅读:
    [转]被玩坏的innerHTML、innerText、textContent和value属性
    在github上优雅的搭建个人博客
    使用jmeter进行压力测试入门讲解
    一、docker 入坑(win10和Ubuntu 安装)
    使用C#开发Android应用之WebApp
    Win10上的Docker应用:Kubernetes(容器集群)
    Win10上的Docker应用:Docker-compose(容器编排)
    Win10上的Docker应用:Hello World
    在web端使用html5访问远程桌面
    HtmlAgilityPack
  • 原文地址:https://www.cnblogs.com/fellow1988/p/6262646.html
Copyright © 2011-2022 走看看