设备驱动基础学习–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\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; }
运行结果如下
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/154964.html原文链接:https://javaforall.cn
相关文章
- 视频融合平台EasyCVR如何添加大华设备的云台功能?
- 设备通过海康EHOME协议接入EasyCVR视频无法播放的排查与分析
- 突然的:图形设备驱动程序错误代码 43 -(已解决)
- platform_driver_register,什么时候调用PROBE函数 注册后如何找到驱动匹配的设备
- 硬件设备驱动入坑记
- 第二弹!思科设备命令最全大合集(2022新版)
- 中国移动2021年至2022年SD-WAN设备集中采购
- 论文分享|基于被动DNS流量分析的大规模IoT设备识别系统
- 【错误记录】Flutter 报错 ( Android Studio 中 main.dart 左侧不显示设备栏 )
- 易点易动设备管理平台能帮助企业做哪些工作
- 网络编程懒人入门(十五):外行也能读懂的网络硬件设备功能原理速成
- 驱动开发Linux SPI设备驱动开发:步骤与挑战(linuxspi设备)
- 解析深入理解Linux设备驱动:实例分析(linux设备驱动实例)
- Neosem定于明年向三星美光英特尔提供PCIe 5.0 SSD测试设备
- 戴尔惠普华硕和宏碁公布可升级Win11的设备列表
- Linux设备驱动开发:深入剖析(Linux设备驱动开发详解)
- Linux设备驱动编程:指导原理与实践(linux设备驱动开发)
- 和设备驱动Linux 下平台总线及设备驱动实现(linux平台总线)
- Linux 虚拟设备驱动:缔造科技奇迹(linux虚拟设备驱动)
- 安卓设备上安装Linux系统:踏上新的体验之旅(安卓系统安装linux)
- 的知识点掌握Linux设备驱动:From Basics to Advanced Knowledge(linux设备驱动中)
- .NET 5.0 正式版发布:应用可在 ARM64 设备上原生运行
- Linux驱动移植:让硬件设备在不同平台上无缝运行(linux驱动移植)
- Linux设备总线驱动:连接硬件与操作系统之桥(linux设备总线驱动)
- 深入了解:Linux 设备标识的重要性与应用(linux设备标识)
- IBM推出新版Linux驱动,优化设备性能提升(ibmlinux驱动)
- 深入了解 Linux 设备管理,轻松掌握设备驱动及其应用(linux设备管理)
- Fitbit 亚洲区销量暴跌 45%,可穿戴设备已进入洗牌阶段