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;
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 */
......@@ -98,21 +98,7 @@ static struct kbd_struct *kbd = kbd_table;
int spawnpid, spawnsig;
/*
* Translation of scancodes to keycodes.
*/
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
* Variables exported for vt.c
*/
int shift_state = 0;
......@@ -138,6 +124,114 @@ static struct ledptr {
unsigned char valid:1;
} 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.
*/
......
......@@ -75,78 +75,6 @@ unsigned int video_scan_lines;
#define GPLAST 0x3df
#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 s (tmp.kb_table)
#define v (tmp.kb_value)
......
......@@ -88,12 +88,3 @@ CONFIG_INPUT_EVBUG
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
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
fi
dep_tristate ' Event interface' CONFIG_INPUT_EVDEV $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'
source drivers/input/gameport/Config.in
......@@ -34,6 +33,7 @@ if [ "$CONFIG_INPUT" != "n" ]; then
source drivers/input/mouse/Config.in
source drivers/input/joystick/Config.in
source drivers/input/touchscreen/Config.in
source drivers/input/misc/Config.in
fi
endmenu
......@@ -15,12 +15,12 @@ obj-$(CONFIG_INPUT_EVDEV) += evdev.o
obj-$(CONFIG_INPUT_TSDEV) += tsdev.o
obj-$(CONFIG_INPUT_POWER) += power.o
obj-$(CONFIG_INPUT_EVBUG) += evbug.o
obj-$(CONFIG_INPUT_UINPUT) += uinput.o
obj-$(CONFIG_INPUT_KEYBOARD) += keyboard/
obj-$(CONFIG_INPUT_MOUSE) += mouse/
obj-$(CONFIG_INPUT_JOYSTICK) += joystick/
obj-$(CONFIG_INPUT_TOUCHSCREEN) += touchscreen/
obj-$(CONFIG_INPUT_MISC) += misc/
# The global Rules.make.
......
......@@ -105,7 +105,7 @@ void input_event(struct input_dev *dev, unsigned int type, unsigned int code, in
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;
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
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;
change_bit(code, dev->snd);
if (dev->event) dev->event(dev, type, code, value);
break;
......
......@@ -114,6 +114,8 @@ static int __init amikbd_init(void)
amikbd_dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
amikbd_dev.keycode = amikbd_keycode;
amikbd_dev.keycodesize = sizeof(unsigned char);
amikbd_dev.keycodemax = ARRAY_SIZE(amikbd_keycode);
for (i = 0; i < 0x78; i++)
if (amikbd_keycode[i])
......
......@@ -470,6 +470,8 @@ static void atkbd_connect(struct serio *serio, struct serio_dev *dev)
atkbd->serio = serio;
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.private = atkbd;
......
......@@ -94,6 +94,8 @@ void nkbd_connect(struct serio *serio, struct serio_dev *dev)
nkbd->serio = serio;
nkbd->dev.keycode = nkbd->keycode;
nkbd->dev.keycodesize = sizeof(unsigned char);
nkbd->dev.keycodemax = ARRAY_SIZE(nkbd_keycode);
nkbd->dev.private = nkbd;
serio->private = nkbd;
......
......@@ -245,6 +245,9 @@ static void sunkbd_connect(struct serio *serio, struct serio_dev *dev)
sunkbd->tq.data = sunkbd;
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.private = sunkbd;
......
......@@ -101,6 +101,8 @@ void xtkbd_connect(struct serio *serio, struct serio_dev *dev)
xtkbd->serio = serio;
xtkbd->dev.keycode = xtkbd->keycode;
xtkbd->dev.keycodesize = sizeof(unsigned char);
xtkbd->dev.keycodemax = ARRAY_SIZE(xtkbd_keycode);
xtkbd->dev.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 {
#define SND_CLICK 0x00
#define SND_BELL 0x01
#define SND_TONE 0x02
#define SND_MAX 0x07
/*
......
......@@ -32,8 +32,8 @@ extern struct vt_struct {
wait_queue_head_t paste_wait;
} *vt_cons[MAX_NR_CONSOLES];
extern void (*kd_mksound)(unsigned int hz, unsigned int ticks);
extern int (*kbd_rate)(struct kbd_repeat *rep);
extern void kd_mksound(unsigned int hz, unsigned int ticks);
extern int kbd_rate(struct kbd_repeat *rep);
/* 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