Commit 19450cd4 authored by Vojtech Pavlik's avatar Vojtech Pavlik

Merge suse.cz:/home/vojtech/bk/linus into suse.cz:/home/vojtech/bk/input

parents 5ba15264 009ce6ad
......@@ -52,11 +52,13 @@ extern void ctrl_alt_del(void);
/*
* Some laptops take the 789uiojklm,. keys as number pad when NumLock is on.
* This seems a good reason to start with NumLock off. On PC9800 however there
* is no NumLock key and everyone expects the keypad to be used for numbers.
* This seems a good reason to start with NumLock off. On PC9800 and HIL keyboards
* of PARISC machines however there is no NumLock key and everyone expects the keypad
* to be used for numbers.
*/
#ifdef CONFIG_X86_PC9800
#if defined(CONFIG_X86_PC9800) || \
defined(CONFIG_PARISC) && (defined(CONFIG_KEYBOARD_HIL) || defined(CONFIG_KEYBOARD_HIL_OLD))
#define KBD_DEFLEDS (1 << VC_NUMLOCK)
#else
#define KBD_DEFLEDS 0
......
......@@ -395,7 +395,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
if (!perm)
return -EPERM;
if (arg)
arg = 1193180 / arg;
arg = 1193182 / arg;
kd_mksound(arg, 0);
return 0;
......@@ -412,7 +412,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
ticks = HZ * ((arg >> 16) & 0xffff) / 1000;
count = ticks ? (arg & 0xffff) : 0;
if (count)
count = 1193180 / count;
count = 1193182 / count;
kd_mksound(count, ticks);
return 0;
}
......
......@@ -29,6 +29,7 @@ struct evdev {
char name[16];
struct input_handle handle;
wait_queue_head_t wait;
struct evdev_list *grab;
struct list_head list;
};
......@@ -48,6 +49,17 @@ static void evdev_event(struct input_handle *handle, unsigned int type, unsigned
struct evdev *evdev = handle->private;
struct evdev_list *list;
if (evdev->grab) {
list = evdev->grab;
do_gettimeofday(&list->buffer[list->head].time);
list->buffer[list->head].type = type;
list->buffer[list->head].code = code;
list->buffer[list->head].value = value;
list->head = (list->head + 1) & (EVDEV_BUFFER_SIZE - 1);
kill_fasync(&list->fasync, SIGIO, POLL_IN);
} else
list_for_each_entry(list, &evdev->list, node) {
do_gettimeofday(&list->buffer[list->head].time);
......@@ -88,6 +100,11 @@ static int evdev_release(struct inode * inode, struct file * file)
{
struct evdev_list *list = file->private_data;
if (list->evdev->grab == list) {
input_release_device(&list->evdev->handle);
list->evdev->grab = NULL;
}
evdev_fasync(-1, file, 0);
list_del(&list->node);
......@@ -257,6 +274,22 @@ static int evdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
return -EFAULT;
return 0;
case EVIOCGRAB:
if (arg) {
if (evdev->grab)
return -EBUSY;
if (input_grab_device(&evdev->handle))
return -EBUSY;
evdev->grab = list;
return 0;
} else {
if (evdev->grab != list)
return -EINVAL;
input_release_device(&evdev->handle);
evdev->grab = NULL;
return 0;
}
default:
if (_IOC_TYPE(cmd) != 'E' || _IOC_DIR(cmd) != _IOC_READ)
......
......@@ -37,7 +37,7 @@ static LIST_HEAD(gameport_dev_list);
#ifdef __i386__
#define DELTA(x,y) ((y)-(x)+((y)<(x)?1193180/HZ:0))
#define DELTA(x,y) ((y)-(x)+((y)<(x)?1193182/HZ:0))
#define GET_TIME(x) do { x = get_time_pit(); } while (0)
static unsigned int get_time_pit(void)
......
......@@ -33,6 +33,8 @@ EXPORT_SYMBOL(input_register_device);
EXPORT_SYMBOL(input_unregister_device);
EXPORT_SYMBOL(input_register_handler);
EXPORT_SYMBOL(input_unregister_handler);
EXPORT_SYMBOL(input_grab_device);
EXPORT_SYMBOL(input_release_device);
EXPORT_SYMBOL(input_open_device);
EXPORT_SYMBOL(input_close_device);
EXPORT_SYMBOL(input_accept_process);
......@@ -175,6 +177,9 @@ void input_event(struct input_dev *dev, unsigned int type, unsigned int code, in
if (type != EV_SYN)
dev->sync = 0;
if (dev->grab)
dev->grab->handler->event(dev->grab, type, code, value);
else
list_for_each_entry(handle, &dev->h_list, d_node)
if (handle->open)
handle->handler->event(handle, type, code, value);
......@@ -201,6 +206,21 @@ int input_accept_process(struct input_handle *handle, struct file *file)
return 0;
}
int input_grab_device(struct input_handle *handle)
{
if (handle->dev->grab)
return -EBUSY;
handle->dev->grab = handle;
return 0;
}
void input_release_device(struct input_handle *handle)
{
if (handle->dev->grab == handle)
handle->dev->grab = NULL;
}
int input_open_device(struct input_handle *handle)
{
if (handle->dev->pm_dev)
......@@ -221,6 +241,7 @@ int input_flush_device(struct input_handle* handle, struct file* file)
void input_close_device(struct input_handle *handle)
{
input_release_device(handle);
if (handle->dev->pm_dev)
pm_dev_idle(handle->dev->pm_dev);
if (handle->dev->close)
......
......@@ -138,7 +138,7 @@ struct analog_port {
#ifdef __i386__
#define GET_TIME(x) do { if (cpu_has_tsc) rdtscl(x); else x = get_time_pit(); } while (0)
#define DELTA(x,y) (cpu_has_tsc?((y)-(x)):((x)-(y)+((x)<(y)?1193180L/HZ:0)))
#define DELTA(x,y) (cpu_has_tsc?((y)-(x)):((x)-(y)+((x)<(y)?1193182L/HZ:0)))
#define TIME_NAME (cpu_has_tsc?"TSC":"PIT")
static unsigned int get_time_pit(void)
{
......
......@@ -39,7 +39,7 @@ static int atkbd_reset = 1;
static unsigned char atkbd_set2_keycode[512] = {
0, 67, 65, 63, 61, 59, 60, 88, 0, 68, 66, 64, 62, 15, 41, 85,
0, 56, 42, 0, 29, 16, 2, 89, 0, 0, 44, 31, 30, 17, 3, 90,
0, 56, 42,182, 29, 16, 2, 89, 0, 0, 44, 31, 30, 17, 3, 90,
0, 46, 45, 32, 18, 5, 4, 91, 0, 57, 47, 33, 20, 19, 6, 0,
0, 49, 48, 35, 34, 21, 7, 0, 0, 0, 50, 36, 22, 8, 9, 0,
0, 51, 37, 23, 24, 11, 10, 0, 0, 52, 53, 38, 39, 25, 12, 0,
......
......@@ -271,7 +271,7 @@ static void sunkbd_connect(struct serio *serio, struct serio_dev *dev)
sprintf(sunkbd->name, "Sun Type %d keyboard", sunkbd->type);
memcpy(sunkbd->keycode, sunkbd_keycode, sizeof(sunkbd->keycode));
for (i = 0; i < 127; i++)
for (i = 0; i < 128; i++)
set_bit(sunkbd->keycode[i], sunkbd->dev.keybit);
clear_bit(0, sunkbd->dev.keybit);
......
......@@ -43,7 +43,7 @@ static int pcspkr_event(struct input_dev *dev, unsigned int type, unsigned int c
}
if (value > 20 && value < 32767)
count = 1193182 / value;
count = CLOCK_TICK_RATE / value;
spin_lock_irqsave(&i8253_beep_lock, flags);
......
......@@ -119,3 +119,14 @@ config SERIO_98KBD
The module will be called rpckbd.o. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>.
config SERIO_PCIPS2
tristate "PCI PS/2 keyboard and PS/2 mouse controller"
depends on PCI && SERIO
help
Say Y here if you have a Mobility Docking station with PS/2
keyboard and mice ports.
This driver is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called rpckbd. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>.
......@@ -14,3 +14,4 @@ obj-$(CONFIG_SERIO_SA1111) += sa1111ps2.o
obj-$(CONFIG_SERIO_AMBAKMI) += ambakmi.o
obj-$(CONFIG_SERIO_Q40KBD) += q40kbd.o
obj-$(CONFIG_SERIO_98KBD) += 98kbd-io.o
obj-$(CONFIG_SERIO_PCIPS2) += pcips2.o
......@@ -20,11 +20,14 @@
*/
#ifdef __alpha__
#define I8042_KBD_IRQ 1
#define I8042_AUX_IRQ (RTC_PORT(0) == 0x170 ? 9 : 12) /* Jensen is special */
# define I8042_KBD_IRQ 1
# define I8042_AUX_IRQ (RTC_PORT(0) == 0x170 ? 9 : 12) /* Jensen is special */
#elif defined(__ia64__)
# define I8042_KBD_IRQ isa_irq_to_vector(1)
# define I8042_AUX_IRQ isa_irq_to_vector(12)
#else
#define I8042_KBD_IRQ 1
#define I8042_AUX_IRQ 12
# define I8042_KBD_IRQ 1
# define I8042_AUX_IRQ 12
#endif
/*
......
/*
* linux/drivers/input/serio/pcips2.c
*
* Copyright (C) 2003 Russell King, All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License.
*
* I'm not sure if this is a generic PS/2 PCI interface or specific to
* the Mobility Electronics docking station.
*/
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/input.h>
#include <linux/pci.h>
#include <linux/init.h>
#include <linux/serio.h>
#include <linux/delay.h>
#include <asm/io.h>
#define PS2_CTRL (0)
#define PS2_STATUS (1)
#define PS2_DATA (2)
#define PS2_CTRL_CLK (1<<0)
#define PS2_CTRL_DAT (1<<1)
#define PS2_CTRL_TXIRQ (1<<2)
#define PS2_CTRL_ENABLE (1<<3)
#define PS2_CTRL_RXIRQ (1<<4)
#define PS2_STAT_CLK (1<<0)
#define PS2_STAT_DAT (1<<1)
#define PS2_STAT_PARITY (1<<2)
#define PS2_STAT_RXFULL (1<<5)
#define PS2_STAT_TXBUSY (1<<6)
#define PS2_STAT_TXEMPTY (1<<7)
struct pcips2_data {
struct serio io;
unsigned int base;
struct pci_dev *dev;
};
static int pcips2_write(struct serio *io, unsigned char val)
{
struct pcips2_data *ps2if = io->driver;
unsigned int stat;
do {
stat = inb(ps2if->base + PS2_STATUS);
cpu_relax();
} while (!(stat & PS2_STAT_TXEMPTY));
outb(val, ps2if->base + PS2_DATA);
return 0;
}
static void pcips2_interrupt(int irq, void *devid, struct pt_regs *regs)
{
struct pcips2_data *ps2if = devid;
unsigned char status, scancode;
do {
unsigned int flag;
status = inb(ps2if->base + PS2_STATUS);
if (!(status & PS2_STAT_RXFULL))
break;
scancode = inb(ps2if->base + PS2_DATA);
if (status == 0xff && scancode == 0xff)
break;
flag = (status & PS2_STAT_PARITY) ? 0 : SERIO_PARITY;
if (hweight8(scancode) & 1)
flag ^= SERIO_PARITY;
serio_interrupt(&ps2if->io, scancode, flag, regs);
} while (1);
}
static void pcips2_flush_input(struct pcips2_data *ps2if)
{
unsigned char status, scancode;
do {
status = inb(ps2if->base + PS2_STATUS);
if (!(status & PS2_STAT_RXFULL))
break;
scancode = inb(ps2if->base + PS2_DATA);
if (status == 0xff && scancode == 0xff)
break;
} while (1);
}
static int pcips2_open(struct serio *io)
{
struct pcips2_data *ps2if = io->driver;
int ret, val = 0;
outb(PS2_CTRL_ENABLE, ps2if->base);
pcips2_flush_input(ps2if);
ret = request_irq(ps2if->dev->irq, pcips2_interrupt, SA_SHIRQ,
"pcips2", ps2if);
if (ret == 0)
val = PS2_CTRL_ENABLE | PS2_CTRL_RXIRQ;
outb(val, ps2if->base);
return ret;
}
static void pcips2_close(struct serio *io)
{
struct pcips2_data *ps2if = io->driver;
outb(0, ps2if->base);
free_irq(ps2if->dev->irq, ps2if);
}
static int __devinit pcips2_probe(struct pci_dev *dev, const struct pci_device_id *id)
{
struct pcips2_data *ps2if;
int ret;
ret = pci_enable_device(dev);
if (ret)
return ret;
if (!request_region(pci_resource_start(dev, 0),
pci_resource_len(dev, 0), "pcips2")) {
ret = -EBUSY;
goto disable;
}
ps2if = kmalloc(sizeof(struct pcips2_data), GFP_KERNEL);
if (!ps2if) {
ret = -ENOMEM;
goto release;
}
memset(ps2if, 0, sizeof(struct pcips2_data));
ps2if->io.type = SERIO_8042;
ps2if->io.write = pcips2_write;
ps2if->io.open = pcips2_open;
ps2if->io.close = pcips2_close;
ps2if->io.name = dev->dev.name;
ps2if->io.phys = dev->dev.bus_id;
ps2if->io.driver = ps2if;
ps2if->dev = dev;
ps2if->base = pci_resource_start(dev, 0);
pci_set_drvdata(dev, ps2if);
serio_register_port(&ps2if->io);
return 0;
release:
release_region(pci_resource_start(dev, 0),
pci_resource_len(dev, 0));
disable:
pci_disable_device(dev);
return ret;
}
static void __devexit pcips2_remove(struct pci_dev *dev)
{
struct pcips2_data *ps2if = pci_get_drvdata(dev);
serio_unregister_port(&ps2if->io);
release_region(pci_resource_start(dev, 0),
pci_resource_len(dev, 0));
pci_set_drvdata(dev, NULL);
kfree(ps2if);
pci_disable_device(dev);
}
static struct pci_device_id pcips2_ids[] = {
{
.vendor = 0x14f2, /* MOBILITY */
.device = 0x0123, /* Keyboard */
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
.class = PCI_CLASS_INPUT_KEYBOARD << 8,
.class_mask = 0xffff00,
},
{
.vendor = 0x14f2, /* MOBILITY */
.device = 0x0124, /* Mouse */
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
.class = PCI_CLASS_INPUT_MOUSE << 8,
.class_mask = 0xffff00,
},
{ 0, }
};
static struct pci_driver pcips2_driver = {
.name = "pcips2",
.id_table = pcips2_ids,
.probe = pcips2_probe,
.remove = __devexit_p(pcips2_remove),
.driver = {
.devclass = &input_devclass,
},
};
static int __init pcips2_init(void)
{
return pci_module_init(&pcips2_driver);
}
static void __exit pcips2_exit(void)
{
pci_unregister_driver(&pcips2_driver);
}
module_init(pcips2_init);
module_exit(pcips2_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>");
MODULE_DESCRIPTION("PCI PS/2 keyboard/mouse driver");
MODULE_DEVICE_TABLE(pci, pcips2_ids);
......@@ -957,6 +957,10 @@ static void hid_output_field(struct hid_field *field, __u8 *data)
void hid_output_report(struct hid_report *report, __u8 *data)
{
unsigned n;
if (report->id > 0)
*data++ = report->id;
for (n = 0; n < report->maxfield; n++)
hid_output_field(report->field[n], data);
}
......@@ -1051,7 +1055,7 @@ static int hid_submit_out(struct hid_device *hid)
report = hid->out[hid->outtail];
hid_output_report(report, hid->outbuf);
hid->urbout->transfer_buffer_length = ((report->size - 1) >> 3) + 1;
hid->urbout->transfer_buffer_length = ((report->size - 1) >> 3) + 1 + (report->id > 0);
hid->urbout->dev = hid->dev;
dbg("submitting out urb");
......@@ -1075,7 +1079,7 @@ static int hid_submit_ctrl(struct hid_device *hid)
if (dir == USB_DIR_OUT)
hid_output_report(report, hid->ctrlbuf);
hid->urbctrl->transfer_buffer_length = ((report->size - 1) >> 3) + 1 + ((report->id > 0) && (dir != USB_DIR_OUT));
hid->urbctrl->transfer_buffer_length = ((report->size - 1) >> 3) + 1 + (report->id > 0);
hid->urbctrl->pipe = (dir == USB_DIR_OUT) ? usb_sndctrlpipe(hid->dev, 0) : usb_rcvctrlpipe(hid->dev, 0);
hid->urbctrl->dev = hid->dev;
......@@ -1351,6 +1355,9 @@ void hid_init_reports(struct hid_device *hid)
#define USB_VENDOR_ID_ESSENTIAL_REALITY 0x0d7f
#define USB_DEVICE_ID_ESSENTIAL_REALITY_P5 0x0100
#define USB_VENDOR_ID_A4TECH 0x09DA
#define USB_DEVICE_ID_A4TECH_WCP32PU 0x0006
struct hid_blacklist {
__u16 idVendor;
__u16 idProduct;
......@@ -1398,6 +1405,7 @@ struct hid_blacklist {
{ USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 500, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_TANGTOP, USB_DEVICE_ID_TANGTOP_USBPS2, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_ESSENTIAL_REALITY, USB_DEVICE_ID_ESSENTIAL_REALITY_P5, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_WCP32PU, HID_QUIRK_2WHEEL_MOUSE_HACK },
{ 0, 0 }
};
......
......@@ -376,6 +376,11 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
}
set_bit(usage->type, input->evbit);
if ((usage->type == EV_REL)
&& (device->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK)
&& (usage->code == REL_WHEEL)) {
set_bit(REL_HWHEEL, bit);
}
while (usage->code <= max && test_and_set_bit(usage->code, bit)) {
usage->code = find_next_zero_bit(bit, max + 1, usage->code);
......@@ -426,6 +431,20 @@ void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct
input_regs(input, regs);
if ((hid->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK)
&& (usage->code == BTN_BACK)) {
if (value)
hid->quirks |= HID_QUIRK_2WHEEL_MOUSE_HACK_ON;
else
hid->quirks &= ~HID_QUIRK_2WHEEL_MOUSE_HACK_ON;
return;
}
if ((hid->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_ON)
&& (usage->code == REL_WHEEL)) {
input_event(input, usage->type, REL_HWHEEL, value);
return;
}
if (usage->hat_min != usage->hat_max) {
value = (value - usage->hat_min) * 8 / (usage->hat_max - usage->hat_min + 1) + 1;
if (value < 0 || value > 8) value = 0;
......
......@@ -201,13 +201,15 @@ struct hid_item {
* HID device quirks.
*/
#define HID_QUIRK_INVERT 0x01
#define HID_QUIRK_NOTOUCH 0x02
#define HID_QUIRK_IGNORE 0x04
#define HID_QUIRK_NOGET 0x08
#define HID_QUIRK_HIDDEV 0x10
#define HID_QUIRK_BADPAD 0x20
#define HID_QUIRK_MULTI_INPUT 0x40
#define HID_QUIRK_INVERT 0x001
#define HID_QUIRK_NOTOUCH 0x002
#define HID_QUIRK_IGNORE 0x004
#define HID_QUIRK_NOGET 0x008
#define HID_QUIRK_HIDDEV 0x010
#define HID_QUIRK_BADPAD 0x020
#define HID_QUIRK_MULTI_INPUT 0x040
#define HID_QUIRK_2WHEEL_MOUSE_HACK 0x080
#define HID_QUIRK_2WHEEL_MOUSE_HACK_ON 0x100
/*
* This is the global environment of the parser. This information is
......
......@@ -442,10 +442,14 @@ static int hiddev_ioctl(struct inode *inode, struct file *file, unsigned int cmd
if (copy_to_user((void *) arg, &dinfo, sizeof(dinfo)))
return -EFAULT;
return 0;
case HIDIOCGFLAG:
if (put_user(list->flags, (int *) arg))
return -EFAULT;
return 0;
case HIDIOCSFLAG:
{
int newflags;
......@@ -533,6 +537,8 @@ static int hiddev_ioctl(struct inode *inode, struct file *file, unsigned int cmd
if (copy_to_user((void *) arg, &rinfo, sizeof(rinfo)))
return -EFAULT;
return 0;
case HIDIOCGFIELDINFO:
if (copy_from_user(&finfo, (void *) arg, sizeof(finfo)))
return -EFAULT;
......@@ -564,6 +570,8 @@ static int hiddev_ioctl(struct inode *inode, struct file *file, unsigned int cmd
if (copy_to_user((void *) arg, &finfo, sizeof(finfo)))
return -EFAULT;
return 0;
case HIDIOCGUCODE:
if (copy_from_user(&uref, (void *) arg, sizeof(uref)))
return -EFAULT;
......@@ -585,6 +593,8 @@ static int hiddev_ioctl(struct inode *inode, struct file *file, unsigned int cmd
if (copy_to_user((void *) arg, &uref, sizeof(uref)))
return -EFAULT;
return 0;
case HIDIOCGUSAGE:
case HIDIOCSUSAGE:
case HIDIOCGCOLLECTIONINDEX:
......
......@@ -15,7 +15,7 @@
#ifdef CONFIG_MELAN
# define CLOCK_TICK_RATE 1189200 /* AMD Elan has different frequency! */
#else
# define CLOCK_TICK_RATE 1193180 /* Underlying HZ */
# define CLOCK_TICK_RATE 1193182 /* Underlying HZ */
#endif
#endif
......
......@@ -10,7 +10,7 @@
#include <asm/msr.h>
#include <asm/vsyscall.h>
#define CLOCK_TICK_RATE 1193180 /* Underlying HZ */
#define CLOCK_TICK_RATE 1193182 /* Underlying HZ */
#define CLOCK_TICK_FACTOR 20 /* Factor of both 1000000 and CLOCK_TICK_RATE */
#define FINETUNE ((((((int)LATCH * HZ - CLOCK_TICK_RATE) << SHIFT_HZ) * \
(1000000/CLOCK_TICK_FACTOR) / (CLOCK_TICK_RATE/CLOCK_TICK_FACTOR)) \
......
......@@ -77,6 +77,8 @@ struct input_absinfo {
#define EVIOCRMFF _IOW('E', 0x81, int) /* Erase a force effect */
#define EVIOCGEFFECTS _IOR('E', 0x84, int) /* Report number of effects playable at the same time */
#define EVIOCGRAB _IOW('E', 0x90, int) /* Grab/Release device */
/*
* Event types
*/
......@@ -471,6 +473,11 @@ struct input_absinfo {
#define KEY_TEEN 0x19e
#define KEY_TWEN 0x19f
#define KEY_DEL_EOL 0x1c0
#define KEY_DEL_EOS 0x1c1
#define KEY_INS_LINE 0x1c2
#define KEY_DEL_LINE 0x1c3
#define KEY_MAX 0x1ff
/*
......@@ -798,6 +805,8 @@ struct input_dev {
int (*upload_effect)(struct input_dev *dev, struct ff_effect *effect);
int (*erase_effect)(struct input_dev *dev, int effect_id);
struct input_handle *grab;
struct list_head h_list;
struct list_head node;
};
......@@ -888,6 +897,9 @@ void input_unregister_device(struct input_dev *);
void input_register_handler(struct input_handler *);
void input_unregister_handler(struct input_handler *);
int input_grab_device(struct input_handle *);
void input_release_device(struct input_handle *);
int input_open_device(struct input_handle *);
void input_close_device(struct input_handle *);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment