#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/fcntl.h>
#include <linux/cdev.h>
#include <linux/version.h>
#include <linux/vmalloc.h>
#include <linux/ctype.h>
#include <linux/pagemap.h>
#include <linux/slab.h>
#include "Demo.h"
MODULE_AUTHOR("Yangjin");
MODULE_LICENSE("Dual BSD/GPL");
struct demo_dev *demo_devices;
static unsigned char demo_inc = 0;//全局变量,每次只能打开一个设备
static u8 demo_buffer[256];
int demo_open(struct inode *inode, struct file *filp)
{
struct demo_dev *dev;
if (demo_inc > 0) return -ERESTARTSYS;
demo_inc++;
dev = container_of(inode->i_cdev, struct demo_dev, cdev);
filp->private_data = dev;
return 0;
}
int demo_release(struct inode *inode, struct file *filp)
{
demo_inc--;
return 0;
}
ssize_t demo_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos)
{
int result;
loff_t pos = *f_pos; //pos: offset
if (pos >= 256) {
result = 0;
goto out;
}
if (count > (256 - pos))
count = 256 - pos;
pos += count;
if (copy_to_user(buf, demo_buffer+*f_pos, count)) {
count = -EFAULT;
goto out;
}
*f_pos = pos;
out:
return count;
}
ssize_t demo_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos)
{
ssize_t retval = -ENOMEM;
loff_t pos = *f_pos;
if (pos > 256)
goto out;
if (count > (256 - pos))
count = 256 - pos;
pos += count;
if (copy_from_user(demo_buffer+*f_pos, buf, count)) {
retval = -EFAULT;
goto out;
}
*f_pos = pos;
retval = count;
out:
return retval;
}
int demo_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
{
if (cmd == COMMAND1) {
printk("ioctl command 1 successfully\n");
return 0;
}
if (cmd == COMMAND2) {
printk("ioctl command 2 successfully\n");
return 0;
}
printk("ioctl error\n");
return -EFAULT;
}
long demo_unlock_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
if (cmd == COMMAND1) {
printk("ioctl command 1 successfully\n");
return 0;
}
if (cmd == COMMAND2) {
printk("ioctl command 2 successfully\n");
return 0;
}
printk("ioctl error\n");
return -EFAULT;
}
long demo_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
if (cmd == COMMAND1) {
printk("ioctl command 1 successfully\n");
return 0;
}
if (cmd == COMMAND2) {
printk("ioctl command 2 successfully\n");
return 0;
}
printk("ioctl error\n");
return -EFAULT;
}
loff_t demo_llseek(struct file *filp, loff_t off, int whence)
{
loff_t pos;
pos = filp->f_pos;
switch (whence) {
case 0:
pos = off;
break;
case 1:
pos += off;
break;
case 2:
default:
return -EINVAL;
}
if ((pos > 256) || (pos < 0))
return -EINVAL;
return filp->f_pos = pos;
}
struct file_operations demo_fops = {
.owner = THIS_MODULE,
.llseek = demo_llseek,
.read = demo_read,
.write = demo_write,
//.ioctl = demo_ioctl,
.unlocked_ioctl = demo_unlock_ioctl,
.compat_ioctl = demo_compat_ioctl,
.open = demo_open,
.release = demo_release,
};
void demo_cleanup_module(void)
{
dev_t devno = MKDEV(DEMO_MAJOR, DEMO_MINOR);
if (demo_devices) {
cdev_del(&demo_devices->cdev);
kfree(demo_devices);
}
unregister_chrdev_region(devno, 1);
}
//Init module流程:
//1)注册设备号MKDEV;
//2)注册设备驱动程序,即初始化cdev结构(嵌入到demo_devices结构中)
int demo_init_module(void)
{
int result;
dev_t dev = 0;
dev = MKDEV(DEMO_MAJOR, DEMO_MINOR);
result = register_chrdev_region(dev, 1, "DEMO");
if (result < 0) {
printk(KERN_WARNING "DEMO: can't get major %d\n", DEMO_MAJOR);
return result;
}
demo_devices = kmalloc(sizeof(struct demo_dev), GFP_KERNEL);
if (!demo_devices) {
result = -ENOMEM;
goto fail;
}
memset(demo_devices, 0, sizeof(struct demo_dev));
cdev_init(&demo_devices->cdev, &demo_fops);
demo_devices->cdev.owner = THIS_MODULE;
demo_devices->cdev.ops = &demo_fops; //将创建的字符设备与file_operations中各函数操作连接起来
result = cdev_add(&demo_devices->cdev, dev, 1);
if (result) {
printk(KERN_NOTICE "error %d adding demo\n", result);
goto fail;
}
return 0;
fail:
demo_cleanup_module();
return result;
}
module_init(demo_init_module);
module_exit(demo_cleanup_module);
最简单的linux驱动和测试例子
3星 · 超过75%的资源 需积分: 49 112 浏览量
2016-12-16
01:30:25
上传
评论 1
收藏 3KB ZIP 举报
zmy12007
- 粉丝: 32
- 资源: 10
最新资源
- rust-study0 介绍 Rust学习项目0 2021-12-14 第一个例子,猜数字: 使用rand获取一个100以内
- Springboot开发-springboot的国际化配置.zip
- 《基于tensorflow框架+ResNet残差神经网络实现白细胞图片分类》+源代码
- 串口调试助手-keil5调试工具
- Springboot开发-将springboot与elasticsearch进行整合开发.zip
- 电子通信设计资料不规则变换循环LED闪烁电路
- Springboot开发-将springboot与redis数据库结合使用.zip
- 电子通信设计资料DC-AC变换器标准多谐振荡器
- 基于ssm+jsp的母婴用品网站+数据库(毕业设计,包括源码,教程).zip
- 电子通信设计资料DC-AC变换器变形多谐振荡器
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈