`
rubynroll
  • 浏览: 204573 次
  • 性别: Icon_minigender_1
  • 来自: Wgt
社区版块
存档分类
最新评论

A Simple pseudo keyboard driver for Linux

阅读更多
如果你想把从串口或者其他地方接收到的数据当作是从键盘输入,该如何实现?

我最近写了个简单的Pseudo Keyboard (称之为:伪键盘)内核模块来实现这个功能,很简单但很有趣

把以下代码存成pkbd.c,编译成模块pkbd.ko,然后用insmod pkbd.ko插入内核。

模块插入成功后,会在/proc下建立pkbd文件,以及在/dev下自动建立输入设备(如果你用udev的话)。

用法:

    比如我想让从/dev/ttyS1来的数据模拟成键盘输入,最简单的方法是运行:
        cp /dev/ttyS1 /proc/pkbd &

当然,更正式点的用法是按需要的设置打开串口,读取数据,让后写入/proc/pkbd。

以下是source,适合Linux 2.6.15或之后的版本。

Enjoy it !

/*
 *	Pseudo Keyboard driver	
 *
 *	Change Logs:
 *		5 Jun, 2006 Created by ricky <ricky_gz_zheng@yahoo.co.nz>
 */

#include <linux/module.h>
#include <linux/config.h>
#include <linux/types.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <asm/uaccess.h>
#include <linux/proc_fs.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/cdev.h>
#include <linux/list.h>
#include <asm/io.h>
#include <linux/input.h>



static int dbg = 0;
MODULE_PARM(dbg, "i");
MODULE_PARM_DESC(dbg, "set dbg=1 enable debug message output to stdout, dbg=0 disable it");

#define DEBUG_PKBD

#ifdef DEBUG_PKBD

#define DBG(x...) \
	do { \
		if(dbg) \
			printk(KERN_INFO PFX x ); \
	} while(0)
#else
#define DBG(x...)
#endif

#define PFX "PKBD: "

static unsigned char m_mapedMin = 1;
static unsigned char m_mapedMax = 0;
static int ascii_to_key[] ={	
  /* 00: ^@ */ 0,
  /* 01: ^A */ (KEY_LEFTCTRL << 16) | KEY_A,
  /* 02: ^B */ (KEY_LEFTCTRL << 16) | KEY_B,
  /* 03: ^C */ (KEY_LEFTCTRL << 16) | KEY_C,
  /* 04: ^D */ (KEY_LEFTCTRL << 16) | KEY_D,
  /* 05: ^E */ (KEY_LEFTCTRL << 16) | KEY_E,
  /* 06: ^F */ (KEY_LEFTCTRL << 16) | KEY_F,
  /* 07: ^G */ (KEY_LEFTCTRL << 16) | KEY_G,
  /* 08: ^H */ (KEY_LEFTCTRL << 16) | KEY_H,
  /* 09: ^I */ (KEY_LEFTCTRL << 16) | KEY_I,
  /* 0a: ^J */ (KEY_LEFTCTRL << 16) | KEY_J,
  /* 0b: ^K */ (KEY_LEFTCTRL << 16) | KEY_K,
  /* 0c: ^L */ (KEY_LEFTCTRL << 16) | KEY_L,
  /* 0d: ^M */ (KEY_LEFTCTRL << 16) | KEY_M,
  /* 0e: ^N */ (KEY_LEFTCTRL << 16) | KEY_N,
  /* 0f: ^O */ (KEY_LEFTCTRL << 16) | KEY_O,
  /* 10: ^P */ (KEY_LEFTCTRL << 16) | KEY_P,
  /* 11: ^Q */ (KEY_LEFTCTRL << 16) | KEY_Q,
  /* 12: ^R */ (KEY_LEFTCTRL << 16) | KEY_R,
  /* 13: ^S */ (KEY_LEFTCTRL << 16) | KEY_S,
  /* 14: ^T */ (KEY_LEFTCTRL << 16) | KEY_T,
  /* 15: ^U */ (KEY_LEFTCTRL << 16) | KEY_U,
  /* 16: ^V */ (KEY_LEFTCTRL << 16) | KEY_V,
  /* 17: ^W */ (KEY_LEFTCTRL << 16) | KEY_W,
  /* 18: ^X */ (KEY_LEFTCTRL << 16) | KEY_X,
  /* 19: ^Y */ (KEY_LEFTCTRL << 16) | KEY_Y,
  /* 1a: ^Z */ (KEY_LEFTCTRL << 16) | KEY_Z,
  /* 1b: ^[ */ (KEY_LEFTCTRL << 16) | KEY_LEFTBRACE,
  /* 1c: ^\ */ (KEY_LEFTCTRL << 16) | KEY_BACKSLASH,
  /* 1d: ^] */ (KEY_LEFTCTRL << 16) | KEY_RIGHTBRACE,
  /* 1e: ^^ */ (KEY_LEFTCTRL << 16) | KEY_6,
  /* 1f: ^_ */ (KEY_LEFTCTRL << 16) | KEY_MINUS,
  /* 20: SP */ KEY_SPACE,
  /* 21: ! */ (KEY_LEFTSHIFT << 16) | KEY_1,
  /* 22: " */ (KEY_LEFTSHIFT << 16) | KEY_APOSTROPHE,
  /* 23: # */ (KEY_LEFTSHIFT << 16) | KEY_3,
  /* 24: $ */ (KEY_LEFTSHIFT << 16) | KEY_4,
  /* 25: % */ (KEY_LEFTSHIFT << 16) | KEY_5,
  /* 26: & */ (KEY_LEFTSHIFT << 16) | KEY_7,
  /* 27: ' */ KEY_APOSTROPHE,
  /* 28: ( */ (KEY_LEFTSHIFT << 16) | KEY_9,
  /* 29: ) */ (KEY_LEFTSHIFT << 16) | KEY_0,
  /* 2a: * */ (KEY_LEFTSHIFT << 16) | KEY_8,
  /* 2b: + */ (KEY_LEFTSHIFT << 16) | KEY_EQUAL,
  /* 2c: , */ KEY_COMMA,
  /* 2d: - */ KEY_MINUS,
  /* 2e: . */ KEY_DOT,
  /* 2f: / */ KEY_SLASH,
  /* 30: 0 */ KEY_0,
  /* 31: 1 */ KEY_1,
  /* 32: 2 */ KEY_2,
  /* 33: 3 */ KEY_3,
  /* 34: 4 */ KEY_4,
  /* 35: 5 */ KEY_5,
  /* 36: 6 */ KEY_6,
  /* 37: 7 */ KEY_7,
  /* 38: 8 */ KEY_8,
  /* 39: 9 */ KEY_9,
  /* 3a: : */ (KEY_LEFTSHIFT << 16) | KEY_SEMICOLON,
  /* 3b: ; */ KEY_SEMICOLON,
  /* 3c: < */ (KEY_LEFTSHIFT << 16) | KEY_COMMA,
  /* 3d: = */ KEY_EQUAL,
  /* 3e: > */ (KEY_LEFTSHIFT << 16) | KEY_DOT,
  /* 3f: ? */ (KEY_LEFTSHIFT << 16) | KEY_SLASH,
  /* 40: @ */ (KEY_LEFTSHIFT << 16) | KEY_2,
  /* 41: A */ (KEY_LEFTSHIFT << 16) | KEY_A,
  /* 42: B */ (KEY_LEFTSHIFT << 16) | KEY_B,
  /* 43: C */ (KEY_LEFTSHIFT << 16) | KEY_C,
  /* 44: D */ (KEY_LEFTSHIFT << 16) | KEY_D,
  /* 45: E */ (KEY_LEFTSHIFT << 16) | KEY_E,
  /* 46: F */ (KEY_LEFTSHIFT << 16) | KEY_F,
  /* 47: G */ (KEY_LEFTSHIFT << 16) | KEY_G,
  /* 48: H */ (KEY_LEFTSHIFT << 16) | KEY_H,
  /* 49: I */ (KEY_LEFTSHIFT << 16) | KEY_I,
  /* 4a: J */ (KEY_LEFTSHIFT << 16) | KEY_J,
  /* 4b: K */ (KEY_LEFTSHIFT << 16) | KEY_K,
  /* 4c: L */ (KEY_LEFTSHIFT << 16) | KEY_L,
  /* 4d: M */ (KEY_LEFTSHIFT << 16) | KEY_M,
  /* 4e: N */ (KEY_LEFTSHIFT << 16) | KEY_N,
  /* 4f: O */ (KEY_LEFTSHIFT << 16) | KEY_O,
  /* 50: P */ (KEY_LEFTSHIFT << 16) | KEY_P,
  /* 51: Q */ (KEY_LEFTSHIFT << 16) | KEY_Q,
  /* 52: R */ (KEY_LEFTSHIFT << 16) | KEY_R,
  /* 53: S */ (KEY_LEFTSHIFT << 16) | KEY_S,
  /* 54: T */ (KEY_LEFTSHIFT << 16) | KEY_T,
  /* 55: U */ (KEY_LEFTSHIFT << 16) | KEY_U,
  /* 56: V */ (KEY_LEFTSHIFT << 16) | KEY_V,
  /* 57: W */ (KEY_LEFTSHIFT << 16) | KEY_W,
  /* 58: X */ (KEY_LEFTSHIFT << 16) | KEY_X,
  /* 59: Y */ (KEY_LEFTSHIFT << 16) | KEY_Y,
  /* 5a: Z */ (KEY_LEFTSHIFT << 16) | KEY_Z,
  /* 5b: [ */ KEY_LEFTBRACE,
  /* 5c: \ */ KEY_BACKSLASH,
  /* 5d: ] */ KEY_RIGHTBRACE,
  /* 5e: ^ */ (KEY_LEFTSHIFT << 16) | KEY_6,
  /* 5f: _ */ (KEY_LEFTSHIFT << 16) | KEY_MINUS,
  /* 60: '  */ KEY_APOSTROPHE,
  /* 61: a */ KEY_A,
  /* 62: b */ KEY_B,
  /* 63: c */ KEY_C,
  /* 64: d */ KEY_D,
  /* 65: e */ KEY_E,
  /* 66: f */ KEY_F,
  /* 67: g */ KEY_G,
  /* 68: h */ KEY_H,
  /* 69: i */ KEY_I,
  /* 6a: j */ KEY_J,
  /* 6b: k */ KEY_K,
  /* 6c: l */ KEY_L,
  /* 6d: m */ KEY_M,
  /* 6e: n */ KEY_N,
  /* 6f: o */ KEY_O,
  /* 70: p */ KEY_P,
  /* 71: q */ KEY_Q,
  /* 72: r */ KEY_R,
  /* 73: s */ KEY_S,
  /* 74: t */ KEY_T,
  /* 75: u */ KEY_U,
  /* 76: v */ KEY_V,
  /* 77: w */ KEY_W,
  /* 78: x */ KEY_X,
  /* 79: y */ KEY_Y,
  /* 7a: z */ KEY_Z,
  /* 7b: { */ (KEY_LEFTSHIFT << 16) | KEY_LEFTBRACE,
  /* 7c: | */ (KEY_LEFTSHIFT << 16) | KEY_BACKSLASH,
  /* 7d: } */ (KEY_LEFTSHIFT << 16) | KEY_RIGHTBRACE,
  /* 7e: ~ */ 0,

  /* TODO: add more keymap here ... */
  /* 7f: ?? */ 0,
  /* 80: ?? */ 0,
  0,	/* end with 0 */
};
static struct input_dev *pkbd_dev = NULL;
static int pkbd_write_proc(struct file *file, const char __user *buffer, unsigned long count, void *data)
{
  #define MAX_INPUT_LEN	64
  unsigned char buf[MAX_INPUT_LEN];
  int i;
  if (pkbd_dev) {
    memset(buf, 0, MAX_INPUT_LEN);
    if(count > 0 && count < MAX_INPUT_LEN) {
      copy_from_user(buf, buffer, count);
      for (i = 0; i < count; i++) {
        if (buf[i] >= m_mapedMin &&	buf[i] <= m_mapedMax) {
          input_report_key(pkbd_dev, ascii_to_key[buf[i]], 1);
          input_report_key(pkbd_dev, ascii_to_key[buf[i]], 0);
        }
     	}
    }
  }
  return count;
}
static int __init pkbddev_init(void)
{	
  struct proc_dir_entry * pkbd_proc = NULL;	
  int i;	
  dbg = dbg;	
  pkbd_proc = create_proc_entry("pkbd", 0, NULL);	
  if(pkbd_proc) {		
    pkbd_proc->write_proc = pkbd_write_proc;	
  }
  else {
    printk (KERN_ERR PFX "Can't create proc entry for pkbd driver.\n");		
    return -EBUSY;	
  }	
  pkbd_dev = input_allocate_device();	
  if (pkbd_dev == NULL) {		
    return -ENODEV;	
  }    
  init_input_dev(pkbd_dev);	
  pkbd_dev->name = "pkbd";	
  set_bit(EV_KEY, pkbd_dev->evbit);	
  for(i = 1; ; i++) {		
    if(ascii_to_key[i] == 0) break;		
    set_bit(ascii_to_key[i], pkbd_dev->keybit);	
  }	
  m_mapedMax = i - 1;	
  input_register_device(pkbd_dev);	
  return 0;
}
static void __exit pkbddev_exit(void)
{	
  if (pkbd_dev) input_unregister_device(pkbd_dev);	
  remove_proc_entry("pkbd", NULL);
}
module_init(pkbddev_init);
module_exit(pkbddev_exit);
MODULE_AUTHOR("Ricky Zheng, <ricky_gz_zheng@yahoo.co.nz>");
MODULE_DESCRIPTION("Pseudo Keyboard Driver");
MODULE_LICENSE("GPL");

分享到:
评论

相关推荐

    Robust Pseudo Random Fields for Light-Field Stereo Matching

    Based on pseudo-likelihood, it applies soft expectation-maximization (EM) for good model fitting and hard EM for robust depth estimation. We introduce novel pixel difference models to enable such ...

    MUTUAL MEAN-TEACHING PSEUDO LABEL REFINERY FOR UNSUPERVISED DO

    计算机视觉Github开源论文 MUTUAL MEAN-TEACHING PSEUDO LABEL REFINERY FOR UNSUPERVISED DO- MAIN ADAPTATION ON PERSON RE-IDENTIFICATION

    Simple Pseudo Assembler-开源

    **标题详解:** "Simple Pseudo Assembler-开源" 指的是一款简易的伪汇编语言解释器,它的特点是开源。伪汇编语言是一种编程工具,它使用类似于汇编语言但更接近高级语言的语法,使得程序员可以更容易地编写低级代码...

    # End-to-end Pseudo-LiDAR for Image-Based 3D Object Detection Th

    本篇文章将深入探讨"End-to-end Pseudo-LiDAR for Image-Based 3D Object Detection"这一主题,以及如何通过伪LiDAR技术实现视觉与LiDAR的高效融合。 首先,我们要理解什么是伪LiDAR。传统的LiDAR系统能够提供高...

    Linux pSeudo Midi Input-开源

    "Linux pSeudo Midi Input"项目就是针对这一问题的解决方案,它提供了一组用户空间驱动程序,使得一些自制、改造或商业设备能够模拟MIDI输入,从而在Linux系统上作为MIDI控制器使用。 开源软件是该项目的核心特点,...

    Embedded Linux Primer.pdf

    Building a Simple File System Section 9.11. Chapter Summary Chapter 10. MTD Subsystem Section 10.1. Enabling MTD Services Section 10.2. MTD Basics Section 10.3. MTD Partitions Section 10.4. MTD ...

    jquery.pseudo.js

    jquery.pseudo.js 文件,当初上传好像是兼容IE8

    论文研究-QUERY DIFFICULTY ESTIMATION VIA PSEUDO RELEVANCE FEEDBACK FOR IMAGE SEARCH.pdf

    关键词中的图像检索(Image Retrieval)、查询难易度估计(Query Difficulty Estimation)、平均准确率(Average Precision)、伪相关反馈(Pseudo Relevance Feedback)和投票机制(Voting Scheme)都是与本研究...

    matlab开发-Pseudoinverse

    在MATLAB中,"Pseudoinverse",也称为广义逆或摩尔-彭若斯逆,是一种解决矩阵方程的重要工具。本教程将深入探讨如何在MATLAB环境中使用矩阵因式分解来计算伪逆。 一、矩阵的伪逆 1.1 伪逆的定义:对于矩阵A,如果...

    Pseudo

    在IT领域,"Pseudo"这个词经常用于描述各种与编程、设计和前端开发相关的概念。在本场景下,标签为“字体”,我们可以推测这个压缩包可能包含与自定义字体或者CSS伪类、伪元素相关的内容。以下是关于这些主题的详细...

    PSEUDO-LIDAR ACCURATE DEPTH FOR 3D OBJECT DETECTION IN AUTONOMOUS DRIVING

    计算机视觉Github开源论文

    Python库 | pseudo-python-0.2.12.tar.gz

    该文件格式通常是Linux和Unix系统中常见的tarball,它结合了tar(用于打包多个文件)和gzip(用于压缩)的功能。 "pseudo-python"这个名字暗示了它可能是一个用于处理伪代码或模拟Python行为的库。在软件开发过程中...

    Weighted pseudo almost periodic solutions of a fractional neutral functional differential equation

    分数阶中立泛函微分方程权伪概周期解的存在性,王奇,王志杰,本文讨论了具无穷时滞的分数阶中立泛函微分方程权伪概周期解的存在性问题,利用压缩映射原理得到了上述方程权伪概周期解的存在唯�

    Android代码-Pseudo-snake

    Simple game à la snake using sensors This is project created some years ago for university course. Code is a bit legacy and isn't well organized. App is written in Kotlin and uses canvas.

    Essential Linux Device Drivers

    Device Example: Simple Storage Controller Advanced Topics Debugging Looking at the Sources Chapter 15. Network Interface Cards Driver Data Structures Talking with Protocol Layers Buffer ...

    3D-pseudo3D.zip

    3D-pseudo3D.zip,cocos creator的简单伪三维透视组件,3D建模使用专门的软件来创建物理对象的数字模型。它是3D计算机图形的一个方面,用于视频游戏,3D打印和VR,以及其他应用程序。

    linux_system_Call.chm

    The scope of the ... The description of each syscall contains a rough sketch (almost pseudo-code) of the code that needs written in order to implement the syscall correctly for Linux compatiblity.

    A Practical Guide to TPM 2.0 Using the Trusted Platform Module

    A Practical Guide to TPM 2.0: Using the Trusted Platform Module in the New Age of Security is a straight-forward primer for developers. It shows security and TPM concepts, demonstrating their use in ...

Global site tag (gtag.js) - Google Analytics