当前位置: 首页 > news >正文

鼠标驱动框架:模拟键盘按键


/* 参考: drivers\hid\usbhid\usbmouse.c */
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/usb.h>
#include <linux/input.h>
#include <linux/hid.h>struct usb_mouse_as_key_desc {struct usb_device *dev;struct usb_interface *intf;const struct usb_device_id *id;int pipe, maxp;int bInterval;void *data_buffer;dma_addr_t data_dma;struct urb *urb;
};/* 1. 构造usb_driver * 1.1 id_table : 能支持哪些设备* 1.2 probe : 记录某些信息, 分配/设置/注册input_dev, 也许也可以在probe里面做"分配/填充/提交URB"*/static struct usb_device_id usb_mouse_as_key_id_table [] = {{ USB_INTERFACE_INFO(USB_INTERFACE_CLASS_HID, USB_INTERFACE_SUBCLASS_BOOT,USB_INTERFACE_PROTOCOL_MOUSE), .driver_info = (kernel_ulong_t)"it is a mouse", },/*.driver_info = (kernel_ulong_t)"it is a mouse" 可以增加一些probe需要的驱动信息,probe里面会自动得到这些信息*/{ }	/* Terminating entry */
};static void usb_mouse_as_key_irq(struct urb *urb)
{struct input_dev *dev = urb->context;struct usb_mouse_as_key_desc *desc = input_get_drvdata(dev);signed char *data = desc->data_buffer;int status;//printk("%s %s %d, urb->status = %d\n", __FILE__, __FUNCTION__, __LINE__, urb->status);switch (urb->status) {case 0:			/* success */break;case -ECONNRESET:	/* unlink */case -ENOENT:case -ESHUTDOWN:return;/* -EPIPE:  should clear the halt */default:		/* error */goto resubmit;  /*如果错误,重新提交*/}//    printk("data[0] = 0x%x\n", data[1]);input_report_key(dev, KEY_L, data[1] & 0x01);   /*查看鼠标数据格式可知data[1]代表 按键状态   见 07_使用libusb读取鼠标数据.md*/input_report_key(dev, KEY_S, data[1] & 0x02);input_report_key(dev, KEY_ENTER, data[1] & 0x04);input_sync(dev);
resubmit:status = usb_submit_urb (urb, GFP_ATOMIC);//printk("%s %s %d, status = %d\n", __FILE__, __FUNCTION__, __LINE__, status);
}static int usb_mouse_as_key_open(struct input_dev *dev)
{struct urb *urb;struct usb_mouse_as_key_desc *desc = input_get_drvdata(dev); /*获取我们之前存入的驱动信息*/int err;urb= desc->urb;printk("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);err = usb_submit_urb (urb, GFP_KERNEL);printk("%s %s %d, err = %d\n", __FILE__, __FUNCTION__, __LINE__, err);return err;
}static void usb_mouse_as_key_close(struct input_dev *dev)
{struct usb_mouse_as_key_desc *desc = input_get_drvdata(dev);    /*获取我们之前存入的驱动信息*//* 取消/释放 URB */usb_kill_urb(desc->urb);usb_free_urb(desc->urb);
}static int usb_mouse_as_key_probe(struct usb_interface *intf, const struct usb_device_id *id)
{struct usb_device *dev = interface_to_usbdev(intf);struct input_dev *input_dev;struct usb_mouse_as_key_desc *desc;int error;struct usb_host_interface *interface;struct usb_endpoint_descriptor *endpoint;int pipe, maxp;printk("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);/* 1. 记录设备信息:  intf *//*判断是不是真正的鼠标*/interface = intf->cur_altsetting;if (interface->desc.bNumEndpoints != 1)return -ENODEV;endpoint = &interface->endpoint[0].desc;if (!usb_endpoint_is_int_in(endpoint))  /*如果不是输入端口,说明不是真正的鼠标设备*/return -ENODEV;pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));  /*管道一次性能够传输的数据*/desc = kmalloc(sizeof(struct usb_mouse_as_key_desc), GFP_KERNEL);desc->dev  = dev;desc->intf = intf;desc->id   = id;desc->pipe = pipe;desc->maxp = maxp;desc->bInterval = endpoint->bInterval;desc->data_buffer = usb_alloc_coherent(dev, maxp, GFP_ATOMIC, &desc->data_dma); /*分配dma*///printk("%s %s %d, desc->data_buffer = 0x%x\n", __FILE__, __FUNCTION__, __LINE__, desc->data_buffer);/* 2. 分配/设置/注册input_dev * 2.1 能产生哪类事件* 2.2 能产生这类事件里哪些些事件: L/S/ENTER       ,可见   input   框架* 2.3 设置函数, 比如open* 2.4 在open函数里: 分配/填充/提交 URB* 2.5 URB的回调函数: 解析数据, 上报input_event*/input_dev = devm_input_allocate_device(&intf->dev);  /*里面自带free   ,一般带前缀的allocate,里面都自带free*/input_set_drvdata(input_dev, desc);   /*存入一些我们想要的驱动描述信息*//* set 1: which type event ? */	__set_bit(EV_KEY, input_dev->evbit);/* set 2: which event ? */	__set_bit(KEY_L, input_dev->keybit);__set_bit(KEY_S, input_dev->keybit);__set_bit(KEY_ENTER, input_dev->keybit);/* set 3: open */input_dev->open  = usb_mouse_as_key_open;input_dev->close = usb_mouse_as_key_close;/* 分配/填充 URB */desc->urb = usb_alloc_urb(0, GFP_KERNEL);usb_fill_int_urb(desc->urb,desc->dev,desc->pipe,desc->data_buffer,(desc->maxp > 8 ? 8 : desc->maxp),usb_mouse_as_key_irq,dev,           /*context参数会传入回调函数*/desc->bInterval);/**如果URB使用DMA Buffer,需要如下的设置**/desc->urb->transfer_dma = desc->data_dma;     desc->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;error = input_register_device(input_dev);usb_set_intfdata(intf, input_dev);return 0;
}static void usb_mouse_as_key_disconnect(struct usb_interface *intf)
{struct input_dev *input_dev = usb_get_intfdata (intf);struct usb_mouse_as_key_desc *desc = input_get_drvdata(input_dev);usb_free_coherent(desc->dev, desc->maxp, desc->data_buffer, desc->data_dma);kfree(desc);input_unregister_device(input_dev);usb_set_intfdata(intf, NULL);
}static struct usb_driver usb_mouse_as_key_driver = {.name		= "usbmouse_as_key",.probe		= usb_mouse_as_key_probe,.disconnect	= usb_mouse_as_key_disconnect,.id_table	= usb_mouse_as_key_id_table,
};/* 入口函数  / 出口函数 */
// module_usb_driver(usb_mouse_as_key_driver);可以使用这个宏一键完成入口函数  / 出口函数 等同于196:208行代码
static int __init usb_mouse_as_key__init(void)
{printk("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);return usb_register(&usb_mouse_as_key_driver);
}static void __exit usb_mouse_as_key__init_exit(void)
{ usb_deregister(&usb_mouse_as_key_driver);
}module_init(usb_mouse_as_key__init);
module_exit(usb_mouse_as_key__init_exit);/* 2. 注册usb_driver */MODULE_LICENSE("GPL");

装载该驱动时,首先要卸载原本内核自带的驱动程序

# 把USB鼠标查到开发板上
# 先看看原来有哪些设备节点
ls /dev/input/event*

# 安装驱动程序
insmod usbmouse_as_key.ko

# 再看看新得到了哪个设备节点
ls /dev/input/event*

# 执行命令, 假设event4是新节点
hexdump /dev/input/event4

# 点击鼠标按键即可观察输出信息

# 第2种测试方法: 执行以下命令,按鼠标左键、右键,再按中键就有输出"ls"
cat /dev/tty0

# 第3种测试方法: 执行以下命令(注意"<"号前后没有空格),就可以使用鼠标按键在控制台输入字符
exec 0</dev/tty0

打印内核input信息:

hexdump /dev/input/event*  /*具体对应 event几 要自己判断*/

相关文章:

鼠标驱动框架:模拟键盘按键

/* 参考: drivers\hid\usbhid\usbmouse.c */ #include <linux/kernel.h> #include <linux/slab.h> #include <linux/module.h> #include <linux/init.h> #include <linux/usb.h> #include <linux/input.h> #include <linux/hid.h>st…...

ES6之Promise的链式调用

✨ 专栏介绍 在现代Web开发中&#xff0c;JavaScript已经成为了不可或缺的一部分。它不仅可以为网页增加交互性和动态性&#xff0c;还可以在后端开发中使用Node.js构建高效的服务器端应用程序。作为一种灵活且易学的脚本语言&#xff0c;JavaScript具有广泛的应用场景&#x…...

HTML----JavaScript操作对象BOM对象

文章目录 目录 文章目录 本章要求 一.BOM模型概述 二.BOM核心&#xff1a;window对象 常用属性 常用方法&#xff1a; confirm() 案例 open ()close()案例 setTimeout( ) 案例 setInterval( ) 案例 document对象 练习 本章要求 了解BOM模型掌握BOM模型实际应用 一.BOM模型…...

隆道数智大会回顾|第13期《如何构建绿色产业供应链新生态》(完)

本期演讲嘉宾&#xff1a; 史文月 采购与供应链专家 邢庆峰 品类管理和质量管理专家 刘婷婷 中兴通讯供应链规划总监 张燕华 正大生物CIO 吴树贵 隆道公司总裁 本期演讲主题&#xff1a; 如何构建绿色产业供应链新生态 本期内容要点&#xff1a; 1.供应链管理的核心问…...

粒子群优化pso结合bp神经网络优化对csv文件预测matlab(3)

1.csv数据为密西西比数据集&#xff0c;获取数据集可以管我要&#xff0c;数据集内容形式如下图&#xff1a; 2.代码 这里参考的是b站的一位博主。 数据集导入教程在我的另一篇文章bp写过&#xff0c;需要的话可以去看一下 psobp.m close all clc%读取数据 inputX; outputY;…...

软性演员-评论家算法 SAC

软性演员-评论家算法 SAC 软性演员-评论家算法 SAC优势原理软性选择模型结构目标函数重参数化熵正则化代码实现 软性演员-评论家算法 SAC 优势原理 DDPG 的问题在于&#xff0c;训练不稳定、收敛差、依赖超参数、不适应复杂环境。 软性演员-评论家算法 SAC&#xff0c;更稳定…...

Nginx多域名部署多站点

目录 1.修改配置文件nginx.conf 2. 修改hosts文件 1.修改配置文件nginx.conf 在配置文件的 server_name 处修改成自己需要的域名&#xff0c;然后保存退出 j 查看语法是否错误&#xff0c;然后重启nginx nginx -t # 查看语法是否正确 systemctl restart nginx # 重启nginx …...

Java的常规面试题

Java的面试题主要涉及Java基础知识、并发编程、集合原理、JVM原理、I/O与网络编程、设计模式、互联网常用框架等多个领域[6]。一些常见的面试问题包括&#xff1a; 1. 面向对象的特征&#xff1a;继承、封装和多态性。 2. 访问修饰符public、private、protected以及默认时的区别…...

大数据技术发展史

文章目录 Google论文HadoopHive大数据生态 Google论文 今天我们常说的大数据技术&#xff0c;其实起源于Google在2004年前后发表的三篇论文&#xff0c;也就是我们经常听到的“三驾马车”&#xff0c;分别是分布式文件系统GFS、大数据分布式计算框架MapReduce和NoSQL数据库系统…...

linux常见基础指令

入门常见基础指令 ls、stat、 pwd 、cd、tree、 whoami、 touch、 mkdir、 rm 、 man、 cp、mv、cat、tac、echo、>、 >>、 < 、more、 less、 head、 tail、date、 cal、 find、 which、alias、whereis、grep、zip与unzip、 tar、bc、uname、xargs... 热键Tab、…...

“人家赚那么多”系列01:如何练习?练什么?

01 如何练习&#xff1f;练习什么&#xff1f; 今年计划重点围绕「在不骗自己的前提下&#xff0c;如何才能把事儿彻底做好&#xff0c;并做得有声有色&#xff1f;」为主题来写点儿东西&#xff0c;聊聊我是怎么做的&#xff0c;如何通过一些有效的方法来不断优化自己的。 想把…...

【Android】使用android studio查看内置数据库信息

要使用Android Studio查看内置数据库信息&#xff0c;可以按照以下步骤进行操作&#xff1a; 打开Android Studio并打开你的项目。 在左侧的Project窗口中&#xff0c;找到并展开你的app模块。 找到并展开"app" > "src" > "main"文件夹。…...

PHP开发日志 ━━ 基于PHP和JS的AES相互加密解密方法详解(CryptoJS) 适合CryptoJS4.0和PHP8.0

最近客户在做安全等保&#xff0c;需要后台登录密码采用加密方式&#xff0c;原来用个base64变形一下就算了&#xff0c;现在不行&#xff0c;一定要加密加key加盐~~ 前端使用Cypto-JS加密&#xff0c;传输给后端使用PHP解密&#xff0c;当然&#xff0c;前端虽然有key有盐&…...

2021-01-03 excel实现列递增,行保持不变

需求&#xff1a;excel文档数据操作的时候发现自动递增只能实现列不变行号递增 我这里里需要的是列递增行不变 解决方式&#xff1a;通过一些函数的组合使用 INDIRECT("驻场明细!"&CHAR(ROW()62)&ROW(驻场明细!A$28)) INDIRECT()函数的使用&#xff1a; INDI…...

[Python]两个杯子取水问题

利用两个杯子巧取三升水&#xff1a; 今天的这个趣味数学小游戏是利用两个没有刻度的水杯&#xff0c;巧妙地取出三升水来。 题目的条件是&#xff1a;一个总容量为6升的杯子和一个总容量为5升的杯子&#xff0c;同时面前有无限容量的水供你使用。不借助其它任何的容器&#xf…...

C++汇编语言学习计划

前几天买了某游戏的外挂&#xff0c;感觉外挂在我计算机上进行了不少操作&#xff0c;我想一探究竟&#xff0c;可是只有exe&#xff0c;没办法&#xff0c;翻译成汇编我也看不懂&#xff0c;索性来简单学习下。访问Chatgpt4&#xff0c;给了如下学习计划。 要从零开始学习C生成…...

微信服务号升级订阅号条件

服务号和订阅号有什么区别&#xff1f;服务号转为订阅号有哪些作用&#xff1f;首先我们要看一下服务号和订阅号的主要区别。1、服务号推送的消息没有折叠&#xff0c;消息出现在聊天列表中&#xff0c;会像收到消息一样有提醒。而订阅号推送的消息是折叠的&#xff0c;“订阅号…...

SpringBoot整合mybatis多数据源

废话不多说先上结果 对应数据库 首先导入所需的mybatis、mysql和lombok依赖 <dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>2.2.2</version></dependen…...

垃圾收集器与内存分配策略

内存分配和回收原则 对象优先在Eden区分配 大对象直接进入老年代 长期存活的对象进入老年代 什么是内存泄漏 不再使用的对象在系统中未被回收&#xff0c;内存泄漏的积累可能会导致内存溢出 自动垃圾回收与手动垃圾回收 自动垃圾回收&#xff1a;由虚拟机来自动回收对象…...

Python计算三角形的面积

Python 计算三角形的面积 以下实例为通过用户输入三角形三边长度&#xff0c;并计算三角形的面积&#xff1a; # 三角形第一边长 a 3 # 三角形第二边长 b 4 c float( input("输入三角形第三边长: ") ) # 计算半周长 s (a b c) / 2 # 计算…...

conda相比python好处

Conda 作为 Python 的环境和包管理工具&#xff0c;相比原生 Python 生态&#xff08;如 pip 虚拟环境&#xff09;有许多独特优势&#xff0c;尤其在多项目管理、依赖处理和跨平台兼容性等方面表现更优。以下是 Conda 的核心好处&#xff1a; 一、一站式环境管理&#xff1a…...

SkyWalking 10.2.0 SWCK 配置过程

SkyWalking 10.2.0 & SWCK 配置过程 skywalking oap-server & ui 使用Docker安装在K8S集群以外&#xff0c;K8S集群中的微服务使用initContainer按命名空间将skywalking-java-agent注入到业务容器中。 SWCK有整套的解决方案&#xff0c;全安装在K8S群集中。 具体可参…...

UE5 学习系列(三)创建和移动物体

这篇博客是该系列的第三篇&#xff0c;是在之前两篇博客的基础上展开&#xff0c;主要介绍如何在操作界面中创建和拖动物体&#xff0c;这篇博客跟随的视频链接如下&#xff1a; B 站视频&#xff1a;s03-创建和移动物体 如果你不打算开之前的博客并且对UE5 比较熟的话按照以…...

【磁盘】每天掌握一个Linux命令 - iostat

目录 【磁盘】每天掌握一个Linux命令 - iostat工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景 注意事项 【磁盘】每天掌握一个Linux命令 - iostat 工具概述 iostat&#xff08;I/O Statistics&#xff09;是Linux系统下用于监视系统输入输出设备和CPU使…...

Java-41 深入浅出 Spring - 声明式事务的支持 事务配置 XML模式 XML+注解模式

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; &#x1f680; AI篇持续更新中&#xff01;&#xff08;长期更新&#xff09; 目前2025年06月05日更新到&#xff1a; AI炼丹日志-28 - Aud…...

python如何将word的doc另存为docx

将 DOCX 文件另存为 DOCX 格式&#xff08;Python 实现&#xff09; 在 Python 中&#xff0c;你可以使用 python-docx 库来操作 Word 文档。不过需要注意的是&#xff0c;.doc 是旧的 Word 格式&#xff0c;而 .docx 是新的基于 XML 的格式。python-docx 只能处理 .docx 格式…...

自然语言处理——循环神经网络

自然语言处理——循环神经网络 循环神经网络应用到基于机器学习的自然语言处理任务序列到类别同步的序列到序列模式异步的序列到序列模式 参数学习和长程依赖问题基于门控的循环神经网络门控循环单元&#xff08;GRU&#xff09;长短期记忆神经网络&#xff08;LSTM&#xff09…...

MFC 抛体运动模拟:常见问题解决与界面美化

在 MFC 中开发抛体运动模拟程序时,我们常遇到 轨迹残留、无效刷新、视觉单调、物理逻辑瑕疵 等问题。本文将针对这些痛点,详细解析原因并提供解决方案,同时兼顾界面美化,让模拟效果更专业、更高效。 问题一:历史轨迹与小球残影残留 现象 小球运动后,历史位置的 “残影”…...

基于IDIG-GAN的小样本电机轴承故障诊断

目录 🔍 核心问题 一、IDIG-GAN模型原理 1. 整体架构 2. 核心创新点 (1) ​梯度归一化(Gradient Normalization)​​ (2) ​判别器梯度间隙正则化(Discriminator Gradient Gap Regularization)​​ (3) ​自注意力机制(Self-Attention)​​ 3. 完整损失函数 二…...

Git 3天2K星标:Datawhale 的 Happy-LLM 项目介绍(附教程)

引言 在人工智能飞速发展的今天&#xff0c;大语言模型&#xff08;Large Language Models, LLMs&#xff09;已成为技术领域的焦点。从智能写作到代码生成&#xff0c;LLM 的应用场景不断扩展&#xff0c;深刻改变了我们的工作和生活方式。然而&#xff0c;理解这些模型的内部…...