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\n");
      printk("val:%d, size: %d, str: %s\n", devp->data.val, devp->data.size, devp->data.str);
    break;
    case FELLOW_MISC_IOC_SET:
      printk("FELLOW_MISC_IOC_SET\n");
      ret = copy_from_user((unsigned char*)&(devp->data), (unsigned char *)arg, sizeof(struct miscdata));
      printk("set val:%d, size: %d, str: %s\n", devp->data.val, devp->data.size, devp->data.str);
    break;
    case FELLOW_MISC_IOC_GET:
      printk("FELLOW_MISC_IOC_GET\n");
      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\n");
  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\n");
  printk("fellow register driver\n");
  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\n");
  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\n", 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\n", strerror(errno));
  }
  struct miscdata getdata;
  if ((ret = ioctl(fd, FELLOW_MISC_IOC_GET, &getdata)) < 0)
  {
    printf("ioctl get fail:%s\n", strerror(errno));
  }
  printf("get val:%d, str:%s, size: %d\n", getdata.val, getdata.str, getdata.size);
  if ((ret = ioctl(fd, FELLOW_MISC_IOC_PRINT, NULL)) < 0)
  {
    printf("ioctl print fail:%s\n", strerror(errno));
  }
  close(fd);
  return ret;
}

运行结果如下

设备驱动基础学习--platform driver简单实现的更多相关文章

  1. 设备驱动基础学习--misc device简单实现

    在Linux驱动中把无法归类的五花八门的设备定义为混杂设备(用miscdevice结构体表述).miscdevice共享一个主设备号MISC_MAJOR(即10),但次设备号不同. 所有的miscde ...

  2. 设备驱动基础学习--poll

    使用非阻塞I/O的应用程序通常会使用select()和poll()系统调用查询是否可对设备进行无阻塞的访问,这两个系统调用最终又会引发设备驱动中的poll()函数被执行,所以我们的问题就集中到了如何编 ...

  3. 设备驱动基础学习--/proc下增加节点

    在需要创建一个由一系列数据顺序组合而成的/proc虚拟文件或一个较大的/proc虚拟文件时,推荐使用seq_file接口. 数据结构struct seq_fille定义在include/linux/s ...

  4. Hasen的linux设备驱动开发学习之旅--时钟

    /** * Author:hasen * 參考 :<linux设备驱动开发具体解释> * 简单介绍:android小菜鸟的linux * 设备驱动开发学习之旅 * 主题:时钟 * Date ...

  5. Linux设备驱动模型之platform(平台)总线详解

    /********************************************************/ 内核版本:2.6.35.7 运行平台:三星s5pv210 /*********** ...

  6. Introduction the naive“scull” 《linux设备驱动》 学习笔记

    Introduction the naive "scull" 首先.什么是scull? scull (Simple Character Utility for Loading Lo ...

  7. 【驱动】Flash设备驱动基础·NOR·NAND

    Flash存储器 ——>Flash存储器是近几年来发展最快的存储设备,通常也称作闪存.Flash属于EEPROM(电可擦除可编程只读存储器),是一类存取速度很高的存储器. ——>它既有RO ...

  8. 探究linux设备驱动模型之——platform虚拟总线(一)

    说在前面的话 :      设备驱动模型系列的文章主要依据的内核版本是2.6.32的,因为我装的Linux系统差不多就是这个版本的(实际上我用的fedora 14的内核版本是2.6.35.13的.) ...

  9. Java基础学习-- 继承 的简单总结

    代码参考:Java基础学习小记--多态 为什么要引入继承? 还是做一个媒体库,里面可以放CD,可以放DVD.如果把CD和DVD做成两个没有联系的类的话,那么在管理这个媒体库的时候,要单独做一个添加CD ...

随机推荐

  1. eclipse unable to start within 45 seconds

    在eclipse4.8.2中运行tomcat8.5项目时,提示出错: Server Tomcat v8.0 Server at localhost was unable to start within ...

  2. normalization flow

    from Eric Jang Normalizing flows transform simple densities (like Gaussians) into rich complex distr ...

  3. (转)java 虚拟机内存划分

    深入理解java虚拟机(一):java内存区域(内存结构划分)深入理解java虚拟机(二):java内存溢出实战  深入理解java虚拟机(三):String.intern()-字符串常量池深入理解j ...

  4. 题解【洛谷P1948】[USACO08JAN]电话线Telephone Lines

    题面 题解 很显然,答案满足单调性. 因此,可以使用二分答案求解. 考虑\(check\)的实现. 贪心地想,免费的\(k\)对电话线一定都要用上. 每次\(check\)时将小于\(mid\)的边权 ...

  5. my bug of VG algorithm

    def visibility_graph(series): g = nx.Graph() # convert list of magnitudes into list of tuples that h ...

  6. (转)Hadoop Combiner

    转自:http://blog.csdn.net/jokes000/article/details/7072963 众所周知,Hadoop框架使用Mapper将数据处理成一个<key,value& ...

  7. k线中转器

    自动同步服务器k线,将交易日k线存入共享内存,交易平台直接去共享内存取想要的数据. 默认提供期货1.3.5分钟.日线数据.如果想要自定义,可以通过copydata向它发送请求,可以提供任何周期,任何偏 ...

  8. django 搭建一个投票类网站(三)

    之前修改index的视图的代码,工作原理是先试用loader方法加载视图,然后HTTPResponse方法初始化一个HTTPResponse对象并返回给浏览器.对于很多django视图来说,他们的工作 ...

  9. leetcode 925. Long Pressed Name

    判定是否长按 var isLongPressedName = function (name, typed) { var i = 1, j = 0, n = name.length, m = typed ...

  10. php基础系列之 数据的存储和读取

    ·文件处理 ·写入一个文件 1,打开这个文件.如果这个文件不存在,需要先创建它 2,将数据写入这个文件 3,关闭这个文件 ·从一个文件读出数据 1,打开这个文件.如果这个文件不能打开(例如,文件不存在 ...