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

这篇具有很好参考价值的文章主要介绍了鼠标驱动框架:模拟键盘按键。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。


/* 参考: 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);   /*模拟键盘L键 查看鼠标数据格式可知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信息:文章来源地址https://www.toymoban.com/news/detail-794178.html

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

到了这里,关于鼠标驱动框架:模拟键盘按键的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • linux下模拟鼠标键盘的工具xdotool

    xdotool 是一个 Linux 命令行工具,用于模拟鼠标和键盘的输入,可以用于自动化 GUI 界面测试、模拟用户交互等场景。 xdotool 的功能包括: 模拟鼠标点击、滚动、移动等操作; 模拟键盘按键、组合键等操作; 发送文本、设置剪贴板内容等操作; 查找窗口、激活窗口、移动、调

    2024年02月13日
    浏览(45)
  • C# 实现按键精灵 记录录制键盘鼠标

     是一个非常实用的键盘鼠标脚本录制工具,通过它你可以轻松地进行脚本录制,简单易用,不需要任何编程知识就能做出功能强大的脚本,只要你在电脑前用双手可以完成的动作,都可以替你完成。                下载软件 1.运行录制脚步时模拟过程 比按键精灵 更加流畅

    2024年02月11日
    浏览(33)
  • C#版本的按键精灵,全局键盘鼠标事件

    代码参考: 钩子类:

    2024年02月14日
    浏览(34)
  • 12.2 实现键盘模拟按键

    本节将向读者介绍如何使用键盘鼠标操控模拟技术,键盘鼠标操控模拟技术是一种非常实用的技术,可以自动化执行一些重复性的任务,提高工作效率,在Windows系统下,通过使用各种键盘鼠标控制函数实现动态捕捉和模拟特定功能的操作。 键盘鼠标的模拟是实现自动化的必

    2024年02月08日
    浏览(79)
  • Python 模拟发送键盘按键

    在rpa项目中,对于一些客户端软件,例如SAP,经常会用到一些快捷键来提高工作效率,或者实现人工点击的操作。开发软件时则是通过封装函数的方式,将传进来的按键或者鼠标的点击通过代码的方式模拟键入某些快捷按键以及鼠标的操作实现该功能。对用户而言,只需通过

    2024年02月16日
    浏览(34)
  • 电脑端(PC)按键精灵——2.键盘命令和鼠标命令

    注:说命令之前,先说下基本设置 电脑端(PC)按键精灵—小白入门 详细教程 一、设置 如下图,点击设置,脚本格式——可以设置字体等内容 字体变大了 修改文件名,脚本属性 二、简单常用按键 1.注释和取消注释 注释的话前面加“ // ”,取消注释择删掉“ // ” 软件自带

    2024年02月08日
    浏览(42)
  • C#使用SnsSharp实现鼠标键盘钩子,实现全局按键响应

    CSDN下载地址:https://download.csdn.net/download/sns1991sns/88041637 gitee下载地址:https://gitee.com/linsns/snssharp 一、键盘事件,使用 SnsKeyboardHook 按键事件共有3个:         KeyDown (按键按下)                 KeyUp (按键松开)                  KeyPress (按键按下并松开) 以

    2024年02月14日
    浏览(38)
  • 嵌入式培训机构四个月实训课程笔记(完整版)-Linux ARM驱动编程第二天-ARM按键1*3矩阵键盘编程 (物联技术666)

    链接:https://pan.baidu.com/s/1E4x2TX_9SYhxM9sWfnehMg?pwd=1688 提取码:1688 1、键盘1*3的中断程序 //************************************************ #include \\\"2440addr.h\\\"           #include \\\"2440lib.h\\\" #include \\\"uart.h\\\" void __irq Eint2Handler(void); void __irq Eint3Handler(void); void __irq Eint4_7Handler(void); void EXIT_IRQ_init(int num

    2024年02月21日
    浏览(48)
  • DD驱动鼠标键盘(驱动级别机器人使用鼠标键盘)

    官网下载 DD虚拟键盘虚拟鼠标 github下载 GitHub - ddxoft/master    点击下载后,将驱动包下,这里以win7为例    setup运行安装  安装成功后   可以打开电脑管理,可以看见DD虚拟鼠标和键盘   这里以JAVA接入为例 使用管理员权限启动eclipse ,新建工程,将相关dll拷贝到工程classpa

    2024年02月11日
    浏览(36)
  • C++ 模拟按下键盘的某个按键

    以下是一段使用C++的Windows API模拟按下向下箭头键的代码: 需要注意的是,这段代码只在Windows平台上有效,且需要包含Windows.h头文件。 keybd_event是Windows API中的一个函数,用于模拟键盘按键事件。它有四个参数: 第一个参数指定要模拟的键码,例如VK_DOWN表示向下箭头键。 第

    2024年02月08日
    浏览(39)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包