当前位置: 首页 > 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 # 计算…...

C++_核心编程_多态案例二-制作饮品

#include <iostream> #include <string> using namespace std;/*制作饮品的大致流程为&#xff1a;煮水 - 冲泡 - 倒入杯中 - 加入辅料 利用多态技术实现本案例&#xff0c;提供抽象制作饮品基类&#xff0c;提供子类制作咖啡和茶叶*//*基类*/ class AbstractDr…...

深入剖析AI大模型:大模型时代的 Prompt 工程全解析

今天聊的内容&#xff0c;我认为是AI开发里面非常重要的内容。它在AI开发里无处不在&#xff0c;当你对 AI 助手说 "用李白的风格写一首关于人工智能的诗"&#xff0c;或者让翻译模型 "将这段合同翻译成商务日语" 时&#xff0c;输入的这句话就是 Prompt。…...

【kafka】Golang实现分布式Masscan任务调度系统

要求&#xff1a; 输出两个程序&#xff0c;一个命令行程序&#xff08;命令行参数用flag&#xff09;和一个服务端程序。 命令行程序支持通过命令行参数配置下发IP或IP段、端口、扫描带宽&#xff0c;然后将消息推送到kafka里面。 服务端程序&#xff1a; 从kafka消费者接收…...

pam_env.so模块配置解析

在PAM&#xff08;Pluggable Authentication Modules&#xff09;配置中&#xff0c; /etc/pam.d/su 文件相关配置含义如下&#xff1a; 配置解析 auth required pam_env.so1. 字段分解 字段值说明模块类型auth认证类模块&#xff0c;负责验证用户身份&am…...

蓝牙 BLE 扫描面试题大全(2):进阶面试题与实战演练

前文覆盖了 BLE 扫描的基础概念与经典问题蓝牙 BLE 扫描面试题大全(1)&#xff1a;从基础到实战的深度解析-CSDN博客&#xff0c;但实际面试中&#xff0c;企业更关注候选人对复杂场景的应对能力&#xff08;如多设备并发扫描、低功耗与高发现率的平衡&#xff09;和前沿技术的…...

Java - Mysql数据类型对应

Mysql数据类型java数据类型备注整型INT/INTEGERint / java.lang.Integer–BIGINTlong/java.lang.Long–––浮点型FLOATfloat/java.lang.FloatDOUBLEdouble/java.lang.Double–DECIMAL/NUMERICjava.math.BigDecimal字符串型CHARjava.lang.String固定长度字符串VARCHARjava.lang…...

现代密码学 | 椭圆曲线密码学—附py代码

Elliptic Curve Cryptography 椭圆曲线密码学&#xff08;ECC&#xff09;是一种基于有限域上椭圆曲线数学特性的公钥加密技术。其核心原理涉及椭圆曲线的代数性质、离散对数问题以及有限域上的运算。 椭圆曲线密码学是多种数字签名算法的基础&#xff0c;例如椭圆曲线数字签…...

工业自动化时代的精准装配革新:迁移科技3D视觉系统如何重塑机器人定位装配

AI3D视觉的工业赋能者 迁移科技成立于2017年&#xff0c;作为行业领先的3D工业相机及视觉系统供应商&#xff0c;累计完成数亿元融资。其核心技术覆盖硬件设计、算法优化及软件集成&#xff0c;通过稳定、易用、高回报的AI3D视觉系统&#xff0c;为汽车、新能源、金属制造等行…...

OPENCV形态学基础之二腐蚀

一.腐蚀的原理 (图1) 数学表达式&#xff1a;dst(x,y) erode(src(x,y)) min(x,y)src(xx,yy) 腐蚀也是图像形态学的基本功能之一&#xff0c;腐蚀跟膨胀属于反向操作&#xff0c;膨胀是把图像图像变大&#xff0c;而腐蚀就是把图像变小。腐蚀后的图像变小变暗淡。 腐蚀…...

AI+无人机如何守护濒危物种?YOLOv8实现95%精准识别

【导读】 野生动物监测在理解和保护生态系统中发挥着至关重要的作用。然而&#xff0c;传统的野生动物观察方法往往耗时耗力、成本高昂且范围有限。无人机的出现为野生动物监测提供了有前景的替代方案&#xff0c;能够实现大范围覆盖并远程采集数据。尽管具备这些优势&#xf…...