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


/* 参考: 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几 要自己判断*/

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/592876.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

计算机毕业设计-------基于JSP+Servlet的毕业生离校管理系统

需求分析 使用JSPServletMysql技术设计一个毕业生离校管理系统, 整个系统采用BS架构, 为高校方便进行毕业生离校流程进行统一的离校流程, 极大的减少了大量学生同时离校的过程中杂乱的情况, 整个系统分为学生, 教务处, 辅导员, 图书馆, 宿管, 财务处, 系办公室, 管理员登等角色…

Vue.observable你有了解过吗?

一、Observable 是什么 Observable 翻译过来我们可以理解成可观察的 我们先来看一下其在Vue中的定义 Vue.observable&#xff0c;让一个对象变成响应式数据。Vue 内部会用它来处理 data 函数返回的对象 返回的对象可以直接用于渲染函数和计算属性内&#xff0c;并且会在发生变…

【华为机试】2023年真题B卷(python)-考古问题

一、题目 题目描述&#xff1a; 考古问题&#xff0c;假设以前的石碑被打碎成了很多块&#xff0c;每块上面都有一个或若干个字符&#xff0c;请你写个程序来把之前石碑上文字可能的组合全部写出来&#xff0c;按升序进行排列。 二、输入输出 三、示例 示例1: 输入输出示例仅供…

了解Apache 配置与应用

本章内容 理解 Apache 连接保持 掌握 Apache 的访问控制 掌握 Apache 日志管理的方法 Apache HTTP Server 之所以受到众多企业的青睐&#xff0c;得益于其代码开源、跨平台、功能 模块化、可灵活定制等诸多优点&#xff0c;不仅性能稳定&#xff0c;在安全性方面的表现也十分…

【设计模式-2】原型模式的原理、代码实现及类图展示

我们一定对类的实例化比较熟悉&#xff0c;前面我们说的单例、还有3种工厂模式都是通过new关键字来创建对象&#xff0c;下面我们来了解一种新的对象创建的方式。 1. 定义 原型模式也是一种创建型的设计模式&#xff0c;实现和原理总体比较简单&#xff0c;一句话总结呢&#…

Weblogic安全漫谈(二)

前言 继本系列上篇从CVE-2015-4852入手了解T3协议的构造后&#xff0c;本篇继续分析开启T3反序列化魔盒后的修复与绕过。 Weblogic对于10.3.6推出了p20780171和p22248372用于修复CVE-2015-4852&#xff0c;在补丁详情中又提示了p21984589是它的超集&#xff0c;所以可以直接装…

kubeadm

kubeadm快速搭建一个k8s小集群 二进制搭建适合搭建大集群&#xff08;50台以上主机&#xff09; kubeadm更适合中小企业的业务集群 master 120.168.233.70 dockerkubelet kubeadm kubectl flannel node01 120.168.233.80 dockerkubelet kubeadm kubectl flannel node02 …

通过软盘拷贝文件 - 华为OD统一考试

OD统一考试(B卷) 分值&#xff1a; 200分 题解&#xff1a; Java / Python / C 题目描述 有一名科学家想要从一台古董电脑中拷贝文件到自己的电脑中加以研究但此电脑除了有一个3.5寸软盘驱动器以外&#xff0c;没有任何手段可以将文件持贝出来&#xff0c;而且只有一张软盘可以…

MySQL将多条数据合并成一条的完整示例

数据库中存的是多条数据&#xff0c;展示的时候需要合并成一条 数据表存储形式如下图 以type分组&#xff0c;type相同的算一条&#xff0c;且保留image和link的所有数据&#xff0c;用groupBy只保留一条数据 解决方案&#xff1a;用GROUP_CONCAT 完整语法如下 group_concat…

Python是怎么调用接口的

在Python中调用接口可以使用多种方式&#xff0c;以下是其中几种常用的方法&#xff1a; 使用标准库中的urllib模块或第三方库requests发送HTTP请求。首先需要导入对应的库&#xff0c;然后使用相应的函数发送请求&#xff0c;并获得返回的结果。 例如&#xff0c;在使用requ…

从有向带权图判断最短路径里各目标顶点顺序

对如下有向带权图&#xff0c;若采用迪杰斯特拉(Dijkstra)算法求从源点a到其他各顶点的最短路径&#xff0c;则得到的第一路径的目标顶点是b&#xff0c;第二条最短路径的目标顶点是c&#xff0c;后续得到的其余各最短路径的目标顶点依次是() A.d,e,f B.e,d,f C.f,d,e D.f,…

linux-6.0 内核存储栈全景图

linux 存储栈原图地址&#xff1a;https://www.thomas-krenn.com/en/wiki/Linux_Storage_Stack_Diagram

自动驾驶TPM技术杂谈 ———— ODDODC

文章目录 介绍研究现状主流相关定义国标定义SAE定义WP29定义 ODD主流构建框架NHTSA ODD构建框架SAE AVSC ODD构建框架PEGASUS 6层模型BSI ODD构建框架 设计运行条件的原则ODC 的设计原则ODC 元素的制定原则ODC 的使用原则 设计运行条件元素ODD 元素驾乘人员状态4车辆状态 ODC 描…

3分钟Alibaba Cloud Linux镜像操作系统详解

Alibaba Cloud Linux是基于龙蜥社区OpenAnolis龙蜥操作系统Anolis OS的阿里云发行版&#xff0c;针对阿里云服务器ECS做了大量深度优化&#xff0c;Alibaba Cloud Linux由阿里云官方免费提供长期支持和维护LTS&#xff0c;Alibaba Cloud Linux完全兼容CentOS/RHEL生态和操作方式…

大学生如何当一个程序员——第二篇:就业实战2

第二篇&#xff1a;就业实战2 第二篇&#xff1a;就业实战21.职场的十大基本素质2.公司调研3.项目调研4.基础技术准备5.热门技术准备6.更高端技术准备7.本专业之外的技术准备8.共同话题准备 文章出自https://www.bjsxt.com/xiulian.html#1F 各位小伙伴想要博客相关资料的话关注…

深入了解隧道代理HTTP的协议与技术细节

隧道代理HTTP&#xff0c;作为一种网络通信的桥梁技术&#xff0c;其背后的协议与技术细节承载着网络世界的无尽奥秘。对于技术人员而言&#xff0c;深入了解这些细节&#xff0c;不仅有助于优化网络性能&#xff0c;还能为网络安全提供坚实的保障。 一、隧道代理HTTP的协议基…

2024阿里云服务器租赁优惠价格表_ECS和轻量应用服务器配置报价

阿里云服务器租用价格表大全&#xff0c;云服务器一年费用、一个月价格以及1小时收费明细&#xff0c;阿里云2核2G3M带宽轻量服务器一年61元、2核4G4M带宽轻量服务器一年165元12个月&#xff0c;ECS云服务器e系列2核2G配置99元一年、2核4G服务器30元3个月、2核4G配置365元一年、…

二维码、条形码识别

一. 场景介绍 二维码和条形码包含很多信息&#xff0c;对二维码和条形码识别对信息抽取具有重要意义。下面介绍两种二维码识别的方法&#xff0c;并用python实现。 二. 代码实现 import os import cv2 from cv2.wechat_qrcode import WeChatQRCode from pyzbar import pyzba…

v-if导致el-button的disabled属性动态修改失败,加key解决(虚拟列表+el-checkbox出现勾选/未勾选的闪现问题同理解决)

<template v-if"isPrev"><el-button type"primary"size"small" click"nextHandle">下一步&#xff1a;添加设备</el-button> </template> <template v-else><el-button type"primary" siz…

WPF中的KeyGesture类

用于表示键盘快捷键的组合。 KeyGesture类位于System.Windows.Input命名空间中&#xff0c;它提供了一种方便的方式来定义和处理用户通过键盘操作执行的命令或操作 。 KeyGesture类具有一下重要属性&#xff1a; key&#xff1a;表示快捷键的主键(Key)。Modifiers&#xff1…