欢迎光临本站

肿瘤

您现在的位置是:首页>健康新闻

健康新闻

先办事后付款的黑客免费接单黑客QQ接单网

tangfengyu2023-01-30 20:14:34健康新闻74来源:抖时代

先办事后付款的黑客免费接单黑客QQ接单网

 

Note that input core keeps track of number of users for the device and
makes sure that dev->open() is called only when the first user connects
to the device and that dev->close() is called when the very last user
disconnects. Calls to both callbacks are serialized.
 
The open() callback should return a 0 in case of success or any nonzero value
in case of failure. The close() callback (which is void) must always succeed.
 
1.3 Basic event types
~~~~~~~~~~~~~~~~~~~~~
 
The most simple event type is EV_KEY, which is used for keys and buttons.
It's reported to the input system via:
 
  input_report_key(struct input_dev *dev, int code, int value)
 
See linux/input.h for the allowable values of code (from 0 to KEY_MAX).
Value is interpreted as a truth value, ie any nonzero value means key
pressed, zero value means key released. The input code generates events only
in case the value is different from before.
 
In addition to EV_KEY, there are two more basic event types: EV_REL and
EV_ABS. They are used for relative and absolute values supplied by the
device. A relative value may be for example a mouse movement in the X axis.
The mouse reports it as a relative difference from the last position,
because it doesn't have any absolute coordinate system to work in. Absolute
events are namely for joysticks and digitizers - devices that do work in an
absolute coordinate systems.
 
Having the device report EV_REL buttons is as simple as with EV_KEY, simply
set the corresponding bits and call the
 
  input_report_rel(struct input_dev *dev, int code, int value)
 
function. Events are generated only for nonzero value.
 
However EV_ABS requires a little special care. Before calling
input_register_device, you have to fill additional fields in the input_dev
struct for each absolute axis your device has. If our button device had also
the ABS_X axis:
 
  button_dev.absmin[ABS_X] = 0;
  button_dev.absmax[ABS_X] = 255;
  button_dev.absfuzz[ABS_X] = 4;
  button_dev.absflat[ABS_X] = 8;
 
Or, you can just say:
 
  input_set_abs_params(button_dev, ABS_X, 0, 255, 4, 8);
 
This setting would be appropriate for a joystick X axis, with the minimum of
0, maximum of 255 (which the joystick *must* be able to reach, no problem if
it sometimes reports more, but it must be able to always reach the min and
max values), with noise in the data up to +- 4, and with a center flat
position of size 8.
 
If you don't need absfuzz and absflat, you can set them to zero, which mean
that the thing is precise and always returns to exactly the center position
(if it has any).
 
1.4 BITS_TO_LONGS(), BIT_WORD(), BIT_MASK()
~~~~~~~~~~~~~~~~~~~~~~~~~~
 
These three macros from bitops.h help some bitfield computations:
 
  BITS_TO_LONGS(x) - returns the length of a bitfield array in longs for
        x bits
  BIT_WORD(x)   - returns the index in the array in longs for bit x
  BIT_MASK(x)   - returns the index in a long for bit x
 
1.5 The id* and name fields
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
The dev->name should be set before registering the input device by the input
device driver. It's a string like 'Generic button device' containing a
user friendly name of the device.
 
The id* fields contain the bus ID (PCI, USB, ...), vendor ID and device ID
of the device. The bus IDs are defined in input.h. The vendor and device ids
are defined in pci_ids.h, usb_ids.h and similar include files. These fields
should be set by the input device driver before registering it.
 
The idtype field can be used for specific information for the input device
driver.
 
The id and name fields can be passed to userland via the evdev interface.
 
1.6 The keycode, keycodemax, keycodesize fields
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
These three fields should be used by input devices that have dense keymaps.
The keycode is an array used to map from scancodes to input system keycodes.
The keycode max should contain the size of the array and keycodesize the
size of each entry in it (in bytes).
 
Userspace can query and alter current scancode to keycode mappings using
EVIOCGKEYCODE and EVIOCSKEYCODE ioctls on corresponding evdev interface.
When a device has all 3 aforementioned fields filled in, the driver may
rely on kernel's default implementation of setting and querying keycode
mappings.
 
1.7 dev->getkeycode() and dev->setkeycode()
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
getkeycode() and setkeycode() callbacks allow drivers to override default
keycode/keycodesize/keycodemax mapping mechanism provided by input core
and implement sparse keycode maps.
 
1.8 Key autorepeat
~~~~~~~~~~~~~~~~~~
 
... is simple. It is handled by the input.c module. Hardware autorepeat is
not used, because it's not present in many devices and even where it is
present, it is broken sometimes (at keyboards: Toshiba notebooks). To enable
autorepeat for your device, just set EV_REP in dev->evbit. All will be
handled by the input system.
 
1.9 Other event types, handling output events
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
The other event types up to now are:
 
EV_LED - used for the keyboard LEDs.
EV_SND - used for keyboard beeps.
 
They are very similar to for example key events, but they go in the other
direction - from the system to the input device driver. If your input device
driver can handle these events, it has to set the respective bits in evbit,
*and* also the callback routine:
 
  button_dev->event = button_event;
 
int button_event(struct input_dev *dev, unsigned int type, unsigned int code, int value);
{
  if (type == EV_SND && code == SND_BELL) {
    outb(value, BUTTON_BELL);
    return 0;
  }
  return -1;
}
 
This callback routine can be called from an interrupt or a BH (although that
isn't a rule), and thus must not sleep, and must not take too long to finish.
 
input-programming.txt

该例子提供的案例代码描述了一个button设备,产生的事件通过BUTTON_PORT引脚获取,当有按下/释放发生时,BUTTON_IRQ被触发,以下是驱动的源代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
#include <linux/input.h>
#include <linux/module.h>
#include <linux/init.h>
 
#include <asm/irq.h>
#include <asm/io.h>
 
static struct input_dev *button_dev; /*输入设备结构体*/
/*中断处理函数*/
static irqreturn_t button_interrupt(int irq, void *dummy)
{
  /*向输入子系统报告产生按键事件*/
  input_report_key(button_dev, BTN_0, inb(BUTTON_PORT) & 1);
  /*通知接收者,一个报告发送完毕*/
  input_sync(button_dev);
  return IRQ_HANDLED;
}
/*加载函数*/
static int __init button_init(void)
{
  int error;
  /*申请中断处理函数*/ //返回0表示成功,返回-INVAL表示无效
  if (request_irq(BUTTON_IRQ, button_interrupt, 0, "button", NULL)) {
        /*申请失败,则打印出错信息*/
        printk(KERN_ERR "button.c: Can't allocate irq %d\n", button_irq);
        return -EBUSY;
    }
  /*分配一个设备结构体*/
  //将在 sys/class/input/input-n 下面创建设备属性文件
  button_dev = input_allocate_device();
  if (!button_dev) {   /*判断分配是否成功*/
    printk(KERN_ERR "button.c: Not enough memory\n");
    error = -ENOMEM;
    goto err_free_irq;
  }
 
  button_dev->evbit[0] = BIT_MASK(EV_KEY); /*设置按键信息*/
  button_dev->keybit[BIT_WORD(BTN_0)] = BIT_MASK(BTN_0);
 
  error = input_register_device(button_dev); /*注册一个输入设备*/
  if (error) {
    printk(KERN_ERR "button.c: Failed to register device\n");
    goto err_free_dev;
  }
 
  return 0;
 /*以下是错误处理*/
 err_free_dev:
  input_free_device(button_dev);
 err_free_irq:
  free_irq(BUTTON_IRQ, button_interrupt);
  return error;
}
 /*卸载函数*/
static void __exit button_exit(void)
{
  input_unregister_device(button_dev); /*注销按键设备*/
  free_irq(BUTTON_IRQ, button_interrupt);/*释放按键占用的中断线*/
}
 
module_init(button_init);
module_exit(button_exit);