鼠标驱动框架:模拟键盘按键
/* 参考: 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开发中,JavaScript已经成为了不可或缺的一部分。它不仅可以为网页增加交互性和动态性,还可以在后端开发中使用Node.js构建高效的服务器端应用程序。作为一种灵活且易学的脚本语言,JavaScript具有广泛的应用场景&#x…...
HTML----JavaScript操作对象BOM对象
文章目录 目录 文章目录 本章要求 一.BOM模型概述 二.BOM核心:window对象 常用属性 常用方法: confirm() 案例 open ()close()案例 setTimeout( ) 案例 setInterval( ) 案例 document对象 练习 本章要求 了解BOM模型掌握BOM模型实际应用 一.BOM模型…...
隆道数智大会回顾|第13期《如何构建绿色产业供应链新生态》(完)
本期演讲嘉宾: 史文月 采购与供应链专家 邢庆峰 品类管理和质量管理专家 刘婷婷 中兴通讯供应链规划总监 张燕华 正大生物CIO 吴树贵 隆道公司总裁 本期演讲主题: 如何构建绿色产业供应链新生态 本期内容要点: 1.供应链管理的核心问…...
粒子群优化pso结合bp神经网络优化对csv文件预测matlab(3)
1.csv数据为密西西比数据集,获取数据集可以管我要,数据集内容形式如下图: 2.代码 这里参考的是b站的一位博主。 数据集导入教程在我的另一篇文章bp写过,需要的话可以去看一下 psobp.m close all clc%读取数据 inputX; outputY;…...
软性演员-评论家算法 SAC
软性演员-评论家算法 SAC 软性演员-评论家算法 SAC优势原理软性选择模型结构目标函数重参数化熵正则化代码实现 软性演员-评论家算法 SAC 优势原理 DDPG 的问题在于,训练不稳定、收敛差、依赖超参数、不适应复杂环境。 软性演员-评论家算法 SAC,更稳定…...
Nginx多域名部署多站点
目录 1.修改配置文件nginx.conf 2. 修改hosts文件 1.修改配置文件nginx.conf 在配置文件的 server_name 处修改成自己需要的域名,然后保存退出 j 查看语法是否错误,然后重启nginx nginx -t # 查看语法是否正确 systemctl restart nginx # 重启nginx …...
Java的常规面试题
Java的面试题主要涉及Java基础知识、并发编程、集合原理、JVM原理、I/O与网络编程、设计模式、互联网常用框架等多个领域[6]。一些常见的面试问题包括: 1. 面向对象的特征:继承、封装和多态性。 2. 访问修饰符public、private、protected以及默认时的区别…...
大数据技术发展史
文章目录 Google论文HadoopHive大数据生态 Google论文 今天我们常说的大数据技术,其实起源于Google在2004年前后发表的三篇论文,也就是我们经常听到的“三驾马车”,分别是分布式文件系统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 如何练习?练习什么? 今年计划重点围绕「在不骗自己的前提下,如何才能把事儿彻底做好,并做得有声有色?」为主题来写点儿东西,聊聊我是怎么做的,如何通过一些有效的方法来不断优化自己的。 想把…...
【Android】使用android studio查看内置数据库信息
要使用Android Studio查看内置数据库信息,可以按照以下步骤进行操作: 打开Android Studio并打开你的项目。 在左侧的Project窗口中,找到并展开你的app模块。 找到并展开"app" > "src" > "main"文件夹。…...
PHP开发日志 ━━ 基于PHP和JS的AES相互加密解密方法详解(CryptoJS) 适合CryptoJS4.0和PHP8.0
最近客户在做安全等保,需要后台登录密码采用加密方式,原来用个base64变形一下就算了,现在不行,一定要加密加key加盐~~ 前端使用Cypto-JS加密,传输给后端使用PHP解密,当然,前端虽然有key有盐&…...
2021-01-03 excel实现列递增,行保持不变
需求:excel文档数据操作的时候发现自动递增只能实现列不变行号递增 我这里里需要的是列递增行不变 解决方式:通过一些函数的组合使用 INDIRECT("驻场明细!"&CHAR(ROW()62)&ROW(驻场明细!A$28)) INDIRECT()函数的使用: INDI…...
[Python]两个杯子取水问题
利用两个杯子巧取三升水: 今天的这个趣味数学小游戏是利用两个没有刻度的水杯,巧妙地取出三升水来。 题目的条件是:一个总容量为6升的杯子和一个总容量为5升的杯子,同时面前有无限容量的水供你使用。不借助其它任何的容器…...
C++汇编语言学习计划
前几天买了某游戏的外挂,感觉外挂在我计算机上进行了不少操作,我想一探究竟,可是只有exe,没办法,翻译成汇编我也看不懂,索性来简单学习下。访问Chatgpt4,给了如下学习计划。 要从零开始学习C生成…...
微信服务号升级订阅号条件
服务号和订阅号有什么区别?服务号转为订阅号有哪些作用?首先我们要看一下服务号和订阅号的主要区别。1、服务号推送的消息没有折叠,消息出现在聊天列表中,会像收到消息一样有提醒。而订阅号推送的消息是折叠的,“订阅号…...
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区分配 大对象直接进入老年代 长期存活的对象进入老年代 什么是内存泄漏 不再使用的对象在系统中未被回收,内存泄漏的积累可能会导致内存溢出 自动垃圾回收与手动垃圾回收 自动垃圾回收:由虚拟机来自动回收对象…...
Python计算三角形的面积
Python 计算三角形的面积 以下实例为通过用户输入三角形三边长度,并计算三角形的面积: # 三角形第一边长 a 3 # 三角形第二边长 b 4 c float( input("输入三角形第三边长: ") ) # 计算半周长 s (a b c) / 2 # 计算…...
接口测试中缓存处理策略
在接口测试中,缓存处理策略是一个关键环节,直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性,避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明: 一、缓存处理的核…...
变量 varablie 声明- Rust 变量 let mut 声明与 C/C++ 变量声明对比分析
一、变量声明设计:let 与 mut 的哲学解析 Rust 采用 let 声明变量并通过 mut 显式标记可变性,这种设计体现了语言的核心哲学。以下是深度解析: 1.1 设计理念剖析 安全优先原则:默认不可变强制开发者明确声明意图 let x 5; …...
基于ASP.NET+ SQL Server实现(Web)医院信息管理系统
医院信息管理系统 1. 课程设计内容 在 visual studio 2017 平台上,开发一个“医院信息管理系统”Web 程序。 2. 课程设计目的 综合运用 c#.net 知识,在 vs 2017 平台上,进行 ASP.NET 应用程序和简易网站的开发;初步熟悉开发一…...
无法与IP建立连接,未能下载VSCode服务器
如题,在远程连接服务器的时候突然遇到了这个提示。 查阅了一圈,发现是VSCode版本自动更新惹的祸!!! 在VSCode的帮助->关于这里发现前几天VSCode自动更新了,我的版本号变成了1.100.3 才导致了远程连接出…...
(二)TensorRT-LLM | 模型导出(v0.20.0rc3)
0. 概述 上一节 对安装和使用有个基本介绍。根据这个 issue 的描述,后续 TensorRT-LLM 团队可能更专注于更新和维护 pytorch backend。但 tensorrt backend 作为先前一直开发的工作,其中包含了大量可以学习的地方。本文主要看看它导出模型的部分&#x…...
高防服务器能够抵御哪些网络攻击呢?
高防服务器作为一种有着高度防御能力的服务器,可以帮助网站应对分布式拒绝服务攻击,有效识别和清理一些恶意的网络流量,为用户提供安全且稳定的网络环境,那么,高防服务器一般都可以抵御哪些网络攻击呢?下面…...
2023赣州旅游投资集团
单选题 1.“不登高山,不知天之高也;不临深溪,不知地之厚也。”这句话说明_____。 A、人的意识具有创造性 B、人的认识是独立于实践之外的 C、实践在认识过程中具有决定作用 D、人的一切知识都是从直接经验中获得的 参考答案: C 本题解…...
docker 部署发现spring.profiles.active 问题
报错: org.springframework.boot.context.config.InvalidConfigDataPropertyException: Property spring.profiles.active imported from location class path resource [application-test.yml] is invalid in a profile specific resource [origin: class path re…...
初学 pytest 记录
安装 pip install pytest用例可以是函数也可以是类中的方法 def test_func():print()class TestAdd: # def __init__(self): 在 pytest 中不可以使用__init__方法 # self.cc 12345 pytest.mark.api def test_str(self):res add(1, 2)assert res 12def test_int(self):r…...
vulnyx Blogger writeup
信息收集 arp-scan nmap 获取userFlag 上web看看 一个默认的页面,gobuster扫一下目录 可以看到扫出的目录中得到了一个有价值的目录/wordpress,说明目标所使用的cms是wordpress,访问http://192.168.43.213/wordpress/然后查看源码能看到 这…...
