Commit 532c236e authored by Vojtech Pavlik's avatar Vojtech Pavlik

This (re)implements getkeycode/setkeycode, kbd_rate and kd_mksound

as functions interfacing to the input core. PC-Speaker handling is
moved to a separate file. Uinput is moved to a input/misc directory.
parent 46a704f6
...@@ -80,7 +80,7 @@ static fn_handler_fn FN_HANDLERS; ...@@ -80,7 +80,7 @@ static fn_handler_fn FN_HANDLERS;
static fn_handler_fn *fn_handler[] = { FN_HANDLERS }; static fn_handler_fn *fn_handler[] = { FN_HANDLERS };
/* /*
* Variables/functions exported for vt_ioctl.c * Variables exported for vt_ioctl.c
*/ */
/* maximum values each key_handler can handle */ /* maximum values each key_handler can handle */
...@@ -98,21 +98,7 @@ static struct kbd_struct *kbd = kbd_table; ...@@ -98,21 +98,7 @@ static struct kbd_struct *kbd = kbd_table;
int spawnpid, spawnsig; int spawnpid, spawnsig;
/* /*
* Translation of scancodes to keycodes. * Variables exported for vt.c
*/
int getkeycode(unsigned int scancode)
{
return 0; /* FIXME */
}
int setkeycode(unsigned int scancode, unsigned int keycode)
{
return 0; /* FIXME */
}
/*
* Variables/function exported for vt.c
*/ */
int shift_state = 0; int shift_state = 0;
...@@ -138,6 +124,114 @@ static struct ledptr { ...@@ -138,6 +124,114 @@ static struct ledptr {
unsigned char valid:1; unsigned char valid:1;
} ledptrs[3]; } ledptrs[3];
/*
* Translation of scancodes to keycodes. We set them on only the first attached
* keyboard - for per-keyboard setting, /dev/input/event is more useful.
*/
int getkeycode(unsigned int scancode)
{
struct input_handle *handle;
unsigned int keycode;
for (handle = kbd_handler.handle; handle; handle = handle->hnext)
if (handle->dev->keycodesize) break;
if (!handle->dev->keycodesize)
return -ENODEV;
switch (handle->dev->keycodesize) {
case 1: keycode = *(u8*)(handle->dev->keycode + scancode); break;
case 2: keycode = *(u16*)(handle->dev->keycode + scancode * 2); break;
case 4: keycode = *(u32*)(handle->dev->keycode + scancode * 4); break;
default: return -EINVAL;
}
return keycode;
}
int setkeycode(unsigned int scancode, unsigned int keycode)
{
struct input_handle *handle;
for (handle = kbd_handler.handle; handle; handle = handle->hnext)
if (handle->dev->keycodesize) break;
if (!handle->dev->keycodesize)
return -ENODEV;
switch (handle->dev->keycodesize) {
case 1: *(u8*)(handle->dev->keycode + scancode) = keycode; break;
case 2: *(u16*)(handle->dev->keycode + scancode * 2) = keycode; break;
case 4: *(u32*)(handle->dev->keycode + scancode * 4) = keycode; break;
}
return 0;
}
/*
* Making beeps and bells.
*/
static void kd_nosound(unsigned long ignored)
{
struct input_handle *handle;
for (handle = kbd_handler.handle; handle; handle = handle->hnext)
if (test_bit(EV_SND, handle->dev->evbit)) {
if (test_bit(SND_TONE, handle->dev->sndbit))
input_event(handle->dev, EV_SND, SND_TONE, 0);
if (test_bit(SND_BELL, handle->dev->sndbit))
input_event(handle->dev, EV_SND, SND_BELL, 0);
}
}
static struct timer_list kd_mksound_timer = { function: kd_nosound };
void kd_mksound(unsigned int hz, unsigned int ticks)
{
struct input_handle *handle;
del_timer(&kd_mksound_timer);
if (hz) {
for (handle = kbd_handler.handle; handle; handle = handle->hnext)
if (test_bit(EV_SND, handle->dev->evbit)) {
if (test_bit(SND_TONE, handle->dev->sndbit)) {
input_event(handle->dev, EV_SND, SND_TONE, hz);
break;
}
if (test_bit(SND_BELL, handle->dev->sndbit)) {
input_event(handle->dev, EV_SND, SND_BELL, 1);
break;
}
}
if (ticks)
mod_timer(&kd_mksound_timer, jiffies + ticks);
} else
kd_nosound(0);
}
/*
* Setting the keyboard rate.
*/
int kbd_rate(struct kbd_repeat *rep)
{
struct input_handle *handle;
if (rep->rate < 0 || rep->delay < 0)
return -EINVAL;
for (handle = kbd_handler.handle; handle; handle = handle->hnext)
if (test_bit(EV_REP, handle->dev->evbit)) {
if (rep->rate > HZ) rep->rate = HZ;
handle->dev->rep[REP_PERIOD] = rep->rate ? (HZ / rep->rate) : 0;
handle->dev->rep[REP_DELAY] = rep->delay * HZ / 1000;
if (handle->dev->rep[REP_DELAY] < handle->dev->rep[REP_PERIOD])
handle->dev->rep[REP_DELAY] = handle->dev->rep[REP_PERIOD];
}
return 0;
}
/* /*
* Helper Functions. * Helper Functions.
*/ */
......
...@@ -75,78 +75,6 @@ unsigned int video_scan_lines; ...@@ -75,78 +75,6 @@ unsigned int video_scan_lines;
#define GPLAST 0x3df #define GPLAST 0x3df
#define GPNUM (GPLAST - GPFIRST + 1) #define GPNUM (GPLAST - GPFIRST + 1)
/*
* Generates sound of some frequency for some number of clock ticks
*
* If freq is 0, will turn off sound, else will turn it on for that time.
* If msec is 0, will return immediately, else will sleep for msec time, then
* turn sound off.
*
* We also return immediately, which is what was implied within the X
* comments - KDMKTONE doesn't put the process to sleep.
*/
#if defined(__i386__) || defined(__alpha__) || defined(__powerpc__) \
|| (defined(__mips__) && defined(CONFIG_ISA)) \
|| (defined(__arm__) && defined(CONFIG_HOST_FOOTBRIDGE)) \
|| defined(__x86_64__)
static void
kd_nosound(unsigned long ignored)
{
/* disable counter 2 */
outb(inb_p(0x61)&0xFC, 0x61);
return;
}
void
_kd_mksound(unsigned int hz, unsigned int ticks)
{
static struct timer_list sound_timer = { function: kd_nosound };
unsigned int count = 0;
unsigned long flags;
if (hz > 20 && hz < 32767)
count = 1193180 / hz;
local_irq_save(flags); // FIXME: is this safe?
del_timer(&sound_timer);
if (count) {
/* enable counter 2 */
outb_p(inb_p(0x61)|3, 0x61);
/* set command for counter 2, 2 byte write */
outb_p(0xB6, 0x43);
/* select desired HZ */
outb_p(count & 0xff, 0x42);
outb((count >> 8) & 0xff, 0x42);
if (ticks) {
sound_timer.expires = jiffies+ticks;
add_timer(&sound_timer);
}
} else
kd_nosound(0);
local_irq_restore(flags);
return;
}
#else
void
_kd_mksound(unsigned int hz, unsigned int ticks)
{
}
#endif
int _kbd_rate(struct kbd_repeat *rep)
{
return -EINVAL;
}
void (*kd_mksound)(unsigned int hz, unsigned int ticks) = _kd_mksound;
int (*kbd_rate)(struct kbd_repeat *rep) = _kbd_rate;
#define i (tmp.kb_index) #define i (tmp.kb_index)
#define s (tmp.kb_table) #define s (tmp.kb_table)
#define v (tmp.kb_value) #define v (tmp.kb_value)
......
...@@ -88,12 +88,3 @@ CONFIG_INPUT_EVBUG ...@@ -88,12 +88,3 @@ CONFIG_INPUT_EVBUG
inserted in and removed from the running kernel whenever you want). inserted in and removed from the running kernel whenever you want).
The module will be called joydev.o. If you want to compile it as a The module will be called joydev.o. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>. module, say M here and read <file:Documentation/modules.txt>.
CONFIG_INPUT_UINPUT
Say Y here if you want to support user level drivers for input
subsystem accessible under char device 10:223 - /dev/input/uinput.
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 uinput.o. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>.
...@@ -22,7 +22,6 @@ if [ "$CONFIG_INPUT_TSDEV" != "n" ]; then ...@@ -22,7 +22,6 @@ if [ "$CONFIG_INPUT_TSDEV" != "n" ]; then
fi fi
dep_tristate ' Event interface' CONFIG_INPUT_EVDEV $CONFIG_INPUT dep_tristate ' Event interface' CONFIG_INPUT_EVDEV $CONFIG_INPUT
dep_tristate ' Event debugging' CONFIG_INPUT_EVBUG $CONFIG_INPUT dep_tristate ' Event debugging' CONFIG_INPUT_EVBUG $CONFIG_INPUT
dep_tristate ' User level driver support' CONFIG_INPUT_UINPUT $CONFIG_INPUT $CONFIG_EXPERIMENTAL
comment 'Input I/O drivers' comment 'Input I/O drivers'
source drivers/input/gameport/Config.in source drivers/input/gameport/Config.in
...@@ -34,6 +33,7 @@ if [ "$CONFIG_INPUT" != "n" ]; then ...@@ -34,6 +33,7 @@ if [ "$CONFIG_INPUT" != "n" ]; then
source drivers/input/mouse/Config.in source drivers/input/mouse/Config.in
source drivers/input/joystick/Config.in source drivers/input/joystick/Config.in
source drivers/input/touchscreen/Config.in source drivers/input/touchscreen/Config.in
source drivers/input/misc/Config.in
fi fi
endmenu endmenu
...@@ -15,12 +15,12 @@ obj-$(CONFIG_INPUT_EVDEV) += evdev.o ...@@ -15,12 +15,12 @@ obj-$(CONFIG_INPUT_EVDEV) += evdev.o
obj-$(CONFIG_INPUT_TSDEV) += tsdev.o obj-$(CONFIG_INPUT_TSDEV) += tsdev.o
obj-$(CONFIG_INPUT_POWER) += power.o obj-$(CONFIG_INPUT_POWER) += power.o
obj-$(CONFIG_INPUT_EVBUG) += evbug.o obj-$(CONFIG_INPUT_EVBUG) += evbug.o
obj-$(CONFIG_INPUT_UINPUT) += uinput.o
obj-$(CONFIG_INPUT_KEYBOARD) += keyboard/ obj-$(CONFIG_INPUT_KEYBOARD) += keyboard/
obj-$(CONFIG_INPUT_MOUSE) += mouse/ obj-$(CONFIG_INPUT_MOUSE) += mouse/
obj-$(CONFIG_INPUT_JOYSTICK) += joystick/ obj-$(CONFIG_INPUT_JOYSTICK) += joystick/
obj-$(CONFIG_INPUT_TOUCHSCREEN) += touchscreen/ obj-$(CONFIG_INPUT_TOUCHSCREEN) += touchscreen/
obj-$(CONFIG_INPUT_MISC) += misc/
# The global Rules.make. # The global Rules.make.
......
...@@ -105,7 +105,7 @@ void input_event(struct input_dev *dev, unsigned int type, unsigned int code, in ...@@ -105,7 +105,7 @@ void input_event(struct input_dev *dev, unsigned int type, unsigned int code, in
change_bit(code, dev->key); change_bit(code, dev->key);
if (test_bit(EV_REP, dev->evbit) && value) { if (test_bit(EV_REP, dev->evbit) && dev->rep[REP_PERIOD] && value) {
dev->repeat_key = code; dev->repeat_key = code;
mod_timer(&dev->timer, jiffies + dev->rep[REP_DELAY]); mod_timer(&dev->timer, jiffies + dev->rep[REP_DELAY]);
} }
...@@ -165,10 +165,9 @@ void input_event(struct input_dev *dev, unsigned int type, unsigned int code, in ...@@ -165,10 +165,9 @@ void input_event(struct input_dev *dev, unsigned int type, unsigned int code, in
case EV_SND: case EV_SND:
if (code > SND_MAX || !test_bit(code, dev->sndbit) || !!test_bit(code, dev->snd) == value) if (code > SND_MAX || !test_bit(code, dev->sndbit))
return; return;
change_bit(code, dev->snd);
if (dev->event) dev->event(dev, type, code, value); if (dev->event) dev->event(dev, type, code, value);
break; break;
......
...@@ -114,6 +114,8 @@ static int __init amikbd_init(void) ...@@ -114,6 +114,8 @@ static int __init amikbd_init(void)
amikbd_dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REP); amikbd_dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
amikbd_dev.keycode = amikbd_keycode; amikbd_dev.keycode = amikbd_keycode;
amikbd_dev.keycodesize = sizeof(unsigned char);
amikbd_dev.keycodemax = ARRAY_SIZE(amikbd_keycode);
for (i = 0; i < 0x78; i++) for (i = 0; i < 0x78; i++)
if (amikbd_keycode[i]) if (amikbd_keycode[i])
......
...@@ -470,6 +470,8 @@ static void atkbd_connect(struct serio *serio, struct serio_dev *dev) ...@@ -470,6 +470,8 @@ static void atkbd_connect(struct serio *serio, struct serio_dev *dev)
atkbd->serio = serio; atkbd->serio = serio;
atkbd->dev.keycode = atkbd->keycode; atkbd->dev.keycode = atkbd->keycode;
atkbd->dev.keycodesize = sizeof(unsigned char);
atkbd->dev.keycodemax = ARRAY_SIZE(atkbd_set2_keycode);
atkbd->dev.event = atkbd_event; atkbd->dev.event = atkbd_event;
atkbd->dev.private = atkbd; atkbd->dev.private = atkbd;
......
...@@ -94,6 +94,8 @@ void nkbd_connect(struct serio *serio, struct serio_dev *dev) ...@@ -94,6 +94,8 @@ void nkbd_connect(struct serio *serio, struct serio_dev *dev)
nkbd->serio = serio; nkbd->serio = serio;
nkbd->dev.keycode = nkbd->keycode; nkbd->dev.keycode = nkbd->keycode;
nkbd->dev.keycodesize = sizeof(unsigned char);
nkbd->dev.keycodemax = ARRAY_SIZE(nkbd_keycode);
nkbd->dev.private = nkbd; nkbd->dev.private = nkbd;
serio->private = nkbd; serio->private = nkbd;
......
...@@ -245,6 +245,9 @@ static void sunkbd_connect(struct serio *serio, struct serio_dev *dev) ...@@ -245,6 +245,9 @@ static void sunkbd_connect(struct serio *serio, struct serio_dev *dev)
sunkbd->tq.data = sunkbd; sunkbd->tq.data = sunkbd;
sunkbd->dev.keycode = sunkbd->keycode; sunkbd->dev.keycode = sunkbd->keycode;
sunkbd->dev.keycodesize = sizeof(unsigned char);
sunkbd->dev.keycodemax = ARRAY_SIZE(sunkbd_keycode);
sunkbd->dev.event = sunkbd_event; sunkbd->dev.event = sunkbd_event;
sunkbd->dev.private = sunkbd; sunkbd->dev.private = sunkbd;
......
...@@ -101,6 +101,8 @@ void xtkbd_connect(struct serio *serio, struct serio_dev *dev) ...@@ -101,6 +101,8 @@ void xtkbd_connect(struct serio *serio, struct serio_dev *dev)
xtkbd->serio = serio; xtkbd->serio = serio;
xtkbd->dev.keycode = xtkbd->keycode; xtkbd->dev.keycode = xtkbd->keycode;
xtkbd->dev.keycodesize = sizeof(unsigned char);
xtkbd->dev.keycodemax = ARRAY_SIZE(xtkbd_keycode);
xtkbd->dev.private = xtkbd; xtkbd->dev.private = xtkbd;
serio->private = xtkbd; serio->private = xtkbd;
......
CONFIG_INPUT_MISC
Say Y here, and a list of miscellaneous input drivers will be displayed.
Everything that didn't fit into the other categories is here. This option
doesn't affect the kernel.
If unsure, say Y.
CONFIG_INPUT_PCSPKR
Say Y here if you want the standard PC Speaker to be used for
bells and whistles.
If unsure, say Y.
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 pcspkr.o. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>.
CONFIG_INPUT_UINPUT
Say Y here if you want to support user level drivers for input
subsystem accessible under char device 10:223 - /dev/input/uinput.
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 uinput.o. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>.
#
# Input misc drivers configuration
#
bool 'Misc' CONFIG_INPUT_MISC
dep_tristate ' PC Speaker support' CONFIG_INPUT_PCSPKR $CONFIG_INPUT $CONFIG_INPUT_MISC
dep_tristate ' User level driver support' CONFIG_INPUT_UINPUT $CONFIG_INPUT $CONFIG_INPUT_MISC
#
# Makefile for the input misc drivers.
#
# Each configuration option enables a list of files.
obj-$(CONFIG_INPUT_PCSPKR) += pcspkr.o
obj-$(CONFIG_INPUT_UINPUT) += uinput.o
# The global Rules.make.
include $(TOPDIR)/Rules.make
/*
* PC Speaker beeper driver for Linux
*
* Copyright (c) 2002 Vojtech Pavlik
* Copyright (c) 1992 Orest Zborowski
*
*/
/*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published by
* the Free Software Foundation
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/input.h>
#include <asm/io.h>
MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
MODULE_DESCRIPTION("PC Speaker beeper driver");
MODULE_LICENSE("GPL");
static char *pcspkr_name = "PC Speaker";
static char *pcspkr_phys = "isa0061/input0";
static struct input_dev pcspkr_dev;
spinlock_t i8253_beep_lock = SPIN_LOCK_UNLOCKED;
static int pcspkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
{
unsigned int count = 0;
unsigned long flags;
if (type != EV_SND)
return -1;
switch (code) {
case SND_BELL: if (value) value = 1000;
case SND_TONE: break;
default: return -1;
}
if (value > 20 && value < 32767)
count = 1193182 / value;
spin_lock_irqsave(&i8253_beep_lock, flags);
if (count) {
/* enable counter 2 */
outb_p(inb_p(0x61) | 3, 0x61);
/* set command for counter 2, 2 byte write */
outb_p(0xB6, 0x43);
/* select desired HZ */
outb_p(count & 0xff, 0x42);
outb((count >> 8) & 0xff, 0x42);
} else {
/* disable counter 2 */
outb(inb_p(0x61) & 0xFC, 0x61);
}
spin_unlock_irqrestore(&i8253_beep_lock, flags);
return 0;
}
static int __init pcspkr_init(void)
{
pcspkr_dev.evbit[0] = BIT(EV_SND);
pcspkr_dev.sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE);
pcspkr_dev.event = pcspkr_event;
pcspkr_dev.name = pcspkr_name;
pcspkr_dev.phys = pcspkr_phys;
pcspkr_dev.id.bustype = BUS_ISA;
pcspkr_dev.id.vendor = 0x001f;
pcspkr_dev.id.product = 0x0001;
pcspkr_dev.id.version = 0x0100;
input_register_device(&pcspkr_dev);
printk(KERN_INFO "input: %s\n", pcspkr_name);
return 0;
}
static void __exit pcspkr_exit(void)
{
input_unregister_device(&pcspkr_dev);
}
module_init(pcspkr_init);
module_exit(pcspkr_exit);
...@@ -570,6 +570,7 @@ struct input_absinfo { ...@@ -570,6 +570,7 @@ struct input_absinfo {
#define SND_CLICK 0x00 #define SND_CLICK 0x00
#define SND_BELL 0x01 #define SND_BELL 0x01
#define SND_TONE 0x02
#define SND_MAX 0x07 #define SND_MAX 0x07
/* /*
......
...@@ -32,8 +32,8 @@ extern struct vt_struct { ...@@ -32,8 +32,8 @@ extern struct vt_struct {
wait_queue_head_t paste_wait; wait_queue_head_t paste_wait;
} *vt_cons[MAX_NR_CONSOLES]; } *vt_cons[MAX_NR_CONSOLES];
extern void (*kd_mksound)(unsigned int hz, unsigned int ticks); extern void kd_mksound(unsigned int hz, unsigned int ticks);
extern int (*kbd_rate)(struct kbd_repeat *rep); extern int kbd_rate(struct kbd_repeat *rep);
/* console.c */ /* console.c */
......
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