Linux驱动开发之字符设备模板

/*****************************
*
* 驱动程序模板
* 版本:V1
* 使用方法(末行模式下):
* :%s/xxx/"你的驱动名称"/g
*
*******************************/

#include <linux/mm.h>
#include <linux/miscdevice.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <linux/mman.h>
#include <linux/random.h>
#include <linux/init.h>
#include <linux/raw.h>
#include <linux/tty.h>
#include <linux/capability.h>
#include <linux/ptrace.h>
#include <linux/device.h>
#include <linux/highmem.h>
#include <linux/crash_dump.h>
#include <linux/backing-dev.h>
#include <linux/bootmem.h>
#include <linux/splice.h>
#include <linux/pfn.h>
#include <linux/export.h>
#include <linux/io.h>
#include <linux/aio.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <asm/uaccess.h>
#include <linux/ioctl.h>

/**************** 基本定义 **********************/
//内核空间缓冲区定义
#if 0
#define KB_MAX_SIZE 20
#define kbuf[KB_MAX_SIZE];
#endif

//加密函数参数内容: _IOW(IOW_CHAR , IOW_NUMn , IOW_TYPE)
//加密函数用于xxx_ioctl函数中
//使用举例:ioctl(fd , _IOW(‘L‘,0x80,long) , 0x1);
//#define NUMn xxx , if you need!
#define IOW_CHAR ‘L‘
#define IOW_TYPE long
#define IOW_NUM1 0x80

//初始化函数必要资源定义
//用于初始化函数当中
//device number;
dev_t dev_num;
//struct dev
struct cdev xxx_cdev;
//auto "mknode /dev/xxx c dev_num minor_num"
struct class *xxx_class = NULL;
struct device *xxx_device = NULL;

/**************** 结构体 file_operations 成员函数 *****************/
//open
static int xxx_open(struct inode *inode, struct file *file)
{
printk("xxx drive open...\n");

return 0;
}

//close
static int xxx_close(struct inode *inode , struct file *file)
{
printk("xxx drive close...\n");

return 0;
}

//read
static ssize_t xxx_read(struct file *file, char __user *buffer,
size_t len, loff_t *pos)
{
int ret_v = 0;
printk("xxx drive read...\n");

return ret_v;
}

//write
static ssize_t xxx_write( struct file *file , const char __user *buffer,
size_t len , loff_t *offset )
{
int ret_v = 0;
printk("xxx drive write...\n");

return ret_v;
}

//unlocked_ioctl
static int xxx_ioctl (struct file *filp , unsigned int cmd , unsigned long arg)
{
int ret_v = 0;
printk("xxx drive ioctl...\n");

switch(cmd)
{
//常规:
//cmd值自行进行修改
case 0x1:
{
if(arg == 0x1) //第二条件;
{

}
}
break;

//带密码保护:
//请在"基本定义"进行必要的定义
case _IOW(IOW_CHAR,IOW_NUM1,IOW_TYPE):
{
if(arg == 0x1) //第二条件
{

}

}
break;

default:
break;
}

return ret_v;
}

/***************** 结构体: file_operations ************************/
//struct
static const struct file_operations xxx_fops = {
.owner = THIS_MODULE,
.open = xxx_open,
.release = xxx_close,
.read = xxx_read,
.write = xxx_write,
.unlocked_ioctl = xxx_ioctl,
};

/************* functions: init , exit*******************/
//条件值变量,用于指示资源是否正常使用
unsigned char init_flag = 0;
unsigned char add_code_flag = 0;

//init
static __init int xxx_init(void)
{
int ret_v = 0;
printk("xxx drive init...\n");

//函数alloc_chrdev_region主要参数说明:
//参数2: 次设备号
//参数3: 创建多少个设备
if( ( ret_v = alloc_chrdev_region(&dev_num,0,1,"xxx") ) < 0 )
{
goto dev_reg_error;
}
init_flag = 1; //标示设备创建成功;

printk("The drive info of xxx:\nmajor: %d\nminor: %d\n",
MAJOR(dev_num),MINOR(dev_num));

cdev_init(&xxx_cdev,&xxx_fops);
if( (ret_v = cdev_add(&xxx_cdev,dev_num,1)) != 0 )
{
goto cdev_add_error;
}

xxx_class = class_create(THIS_MODULE,"xxx");
if( IS_ERR(xxx_class) )
{
goto class_c_error;
}

xxx_device = device_create(xxx_class,NULL,dev_num,NULL,"xxx");
if( IS_ERR(xxx_device) )
{
goto device_c_error;
}
printk("auto mknod success!\n");

//------------ 请在此添加您的初始化程序 --------------//

//如果需要做错误处理,请:goto xxx_error;

add_code_flag = 1;
//---------------------- END ---------------------------//

goto init_success;

dev_reg_error:
printk("alloc_chrdev_region failed\n");
return ret_v;

cdev_add_error:
printk("cdev_add failed\n");
unregister_chrdev_region(dev_num, 1);
init_flag = 0;
return ret_v;

class_c_error:
printk("class_create failed\n");
cdev_del(&xxx_cdev);
unregister_chrdev_region(dev_num, 1);
init_flag = 0;
return PTR_ERR(xxx_class);

device_c_error:
printk("device_create failed\n");
cdev_del(&xxx_cdev);
unregister_chrdev_region(dev_num, 1);
class_destroy(xxx_class);
init_flag = 0;
return PTR_ERR(xxx_device);

//------------------ 请在此添加您的错误处理内容 ----------------//
xxx_error:

add_code_flag = 0;
return -1;
//-------------------- END -------------------//

init_success:
printk("xxx init success!\n");
return 0;
}

//exit
static __exit void xxx_exit(void)
{
printk("xxx drive exit...\n");

if(add_code_flag == 1)
{
//---------- 请在这里释放您的程序占有的资源 ---------//
printk("free your resources...\n");

printk("free finish\n");
//---------------------- END -------------------//
}

if(init_flag == 1)
{
//释放初始化使用到的资源;
cdev_del(&xxx_cdev);
unregister_chrdev_region(dev_num, 1);
device_unregister(xxx_device);
class_destroy(xxx_class);
}
}

/**************** module operations**********************/
//module loading
module_init(xxx_init);
module_exit(xxx_exit);

//some infomation
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("from Jafy");
MODULE_DESCRIPTION("xxx drive");

/********************* The End ***************************/

时间: 2024-10-16 12:54:09

Linux驱动开发之字符设备模板的相关文章

linux驱动学习(1)——字符设备驱动开发

(一)驱动程序介绍 (a)Linux驱动程序学习 知识结构: 1. Linux驱动程序设计模式(40%) 2. 内核相关知识(30%) 3. 硬件相关知识(30%) (b)驱动分类: ①字符设备: 字符设备是一种按字节来访问的设备,字符驱动则负责驱动字符设备,这样的驱动通常实现 open, close,read和 write 系统调用. ②块设备: 在大部分的 Unix 系统, 块设备不能按字节处理数据,只能一次传送一个或多个长度是512字节( 或一个更大的 2 次幂的数 )的整块数据,而Lin

驱动开发--【字符设备、块设备简介】【sky原创】

驱动开发   字符设备,块设备,网络设备 字符设备 以字节流的方式访问, 不能随机访问 有例外,显卡.EEPROM可以随机访问 EEPROM可以擦写1亿次,是一种字符设备,可以随机访问 读写是直接访问硬件的 flash 擦写次数有限,一百万次,容易有坏块 块设备 能随机访问 以”块“为单位进行访问 块大小一般为512字节 块的大小由硬件决定 是内核进行数据传输的基本单位 硬盘结构: 格式化分区是以柱面为单位的,即硬盘的柱面 如果有10个盘面,就有十个柱面 对于嵌入式设备 如果是flash的话,结

linux驱动开发之块设备学习笔记

学习参考:http://www.cnblogs.com/yuanfang/archive/2010/12/24/1916231.html 1.块设备 块设备将数据按照固定块大小的块中,每个块的大小通常在512字节到32768字节之间,磁盘.SD卡都是常见的块设备. 2.字符设备和块设备的区别: 字符设备 块设备 ---------------------------------------------- 按字节访问 按块进行访问 只能按照数据流访问 随机访问 直接访问设备 挂在文件系统的方式访问

初入android驱动开发之字符设备(五-定时器)

这个字符设备系列,主要借助较容易上手的字符设备实例,去讲解linux的一些机制,以及驱动中比较常用到的中断.定时器.信号量等一些知识,由于本人自身的知识有限,对于arm的架构体系不太了解,这里,一般这里只讲,如何去用,对于一些原理性的东西不会深究,以后的文章会慢慢的加深. 想想我们当初玩51单片机的时候,那时候按键防抖是一个硬件.软件都需要处理的地方.软件一般就是加延时检测判断.当然,这里我们也可以用到定时器的这个机制,做按键驱动,这里主要还是以按键为例,但不是讲的按键防抖. 1. 定时器的一些

初入android驱动开发之字符设备(四-中断)

上一篇讲到android驱动开发中,应用是怎样去操作底层硬件的整个流程,实现了按键控制led的亮灭.当然,这是一个非常easy的实例,只是略微演变一下,就能够得到广泛的应用. 如开发扫描头,应用透过监听上报的按键的键值,监听到,则调用扫描头的模块.成功,则点亮LED灯,并把扫描头解码后的条码信息.通过广播的形式发出.又扯到其他地方,这里主要说说中断. 1. 中断的一些概念 中断,是什么? 中断.能够看成是cpu对特殊事件的一种处理的机制,这类特殊事件一般指紧急事件或者说异常事件.非常easy的一

【linux驱动笔记】字符设备驱动相关数据结构与算法

欢迎转载,转载时需保留作者信息,谢谢. 邮箱:[email protected] 博客园地址:http://www.cnblogs.com/embedded-tzp Csdn博客地址:http://blog.csdn.net/xiayulewa   1.1.1.   设备号 alloc_chrdev_region(&dev, 0, 1, "buttons") /  register_chrdev_region: 动态申请设备号, 设备号组成了链表节点. 最后的结果为:所有的ch

从Linux内核LED驱动来理解字符设备驱动开发流程

目录 博客说明 开发环境 1. Linux字符设备驱动的组成 1.1 字符设备驱动模块加载与卸载函数 1.2 字符设备驱动的file_operations 结构体中的成员函数 2. 字符设备驱动--设备号注册卸载 2.1 设备号注册 2.2 设备号注销 3. 字符设备驱动--文件操作 参考资料 示例代码 @(从Linux内核LED驱动来理解字符设备驱动开发流程) 博客说明 撰写日期 2018.12.08 完稿日期 2019.10.06 最近维护 暂无 本文作者 multimicro 联系方式 [

linux驱动开发重点关注内容--摘自《嵌入式Linux驱动模板精讲与项目实践》

本文摘自本人拙著 <嵌入式Linux驱动模板精讲与项目实践> 初步看起来Linux设备驱动开发涉及内容非常多,而须要实现驱动的设备千差万别.事实上做一段时间驱动之后回首看来主要就是下面几点: (1)对驱动进行分类.先归纳为哪个类型的驱动.归类正确再利用内核提供的子系统进行开发,往往会发现事实上非常多通用的事情内核已经帮我们做了,一个优秀的驱动project师应该最大程度上利用内核的资源.内核已经实现的毕竟稳定性强.可移植性高. (2)找到内核的提供的子系统.接下来就是要制作该子系统对该类设备提

驱动编程思想之初体验 --------------- 嵌入式linux驱动开发之点亮LED

这节我们就开始开始进行实战啦!这里顺便说一下啊,出来做开发的基础很重要啊,基础不好,迟早是要恶补的.个人深刻觉得像这种嵌入式的开发对C语言和微机接口与原理是非常依赖的,必须要有深厚的基础才能hold的住,不然真像一些人说的,学了一年嵌入式感觉还没找到门. 不能再扯了,涉及到linux的驱动开发知识面灰常广,再扯文章就会变得灰常长.首先还是回到led驱动的本身上,自从linux被移植到arm上后,做驱动开发的硬件知识要求有所降低,很多都回归到了软件上,这是系统编程的一大特点,当然 ,也不排除有很多