From 532c236e53d6e76b73dbb0b70b401a655e1daf07 Mon Sep 17 00:00:00 2001 From: Vojtech Pavlik Date: Sun, 25 Aug 2002 19:21:22 +0200 Subject: [PATCH] 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. --- drivers/char/keyboard.c | 126 +++++++++++++++++++++++++---- drivers/char/vt.c | 72 ----------------- drivers/input/Config.help | 9 --- drivers/input/Config.in | 2 +- drivers/input/Makefile | 2 +- drivers/input/input.c | 5 +- drivers/input/keyboard/amikbd.c | 2 + drivers/input/keyboard/atkbd.c | 2 + drivers/input/keyboard/newtonkbd.c | 2 + drivers/input/keyboard/sunkbd.c | 3 + drivers/input/keyboard/xtkbd.c | 2 + drivers/input/misc/Config.help | 28 +++++++ drivers/input/misc/Config.in | 8 ++ drivers/input/misc/Makefile | 12 +++ drivers/input/misc/pcspkr.c | 94 +++++++++++++++++++++ drivers/input/{ => misc}/uinput.c | 0 include/linux/input.h | 1 + include/linux/vt_kern.h | 4 +- 18 files changed, 270 insertions(+), 104 deletions(-) create mode 100644 drivers/input/misc/Config.help create mode 100644 drivers/input/misc/Config.in create mode 100644 drivers/input/misc/Makefile create mode 100644 drivers/input/misc/pcspkr.c rename drivers/input/{ => misc}/uinput.c (100%) diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c index e74583042660..d773e736e427 100644 --- a/drivers/char/keyboard.c +++ b/drivers/char/keyboard.c @@ -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. */ diff --git a/drivers/char/vt.c b/drivers/char/vt.c index a432564866bf..a932da89770e 100644 --- a/drivers/char/vt.c +++ b/drivers/char/vt.c @@ -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) diff --git a/drivers/input/Config.help b/drivers/input/Config.help index 8ebdeaea24a7..2e3ff3acd8c9 100644 --- a/drivers/input/Config.help +++ b/drivers/input/Config.help @@ -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 . - -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 . diff --git a/drivers/input/Config.in b/drivers/input/Config.in index f1c79594f041..0568cfd77e2d 100644 --- a/drivers/input/Config.in +++ b/drivers/input/Config.in @@ -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 diff --git a/drivers/input/Makefile b/drivers/input/Makefile index 64983696a66f..f7232ccdf1ec 100644 --- a/drivers/input/Makefile +++ b/drivers/input/Makefile @@ -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. diff --git a/drivers/input/input.c b/drivers/input/input.c index 0bd17fbd49fd..da4ed6e6dcf5 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c @@ -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; diff --git a/drivers/input/keyboard/amikbd.c b/drivers/input/keyboard/amikbd.c index c3ea9648ec59..d9db20739a26 100644 --- a/drivers/input/keyboard/amikbd.c +++ b/drivers/input/keyboard/amikbd.c @@ -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]) diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c index 479e0ab9fe5d..63ae062f92a6 100644 --- a/drivers/input/keyboard/atkbd.c +++ b/drivers/input/keyboard/atkbd.c @@ -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; diff --git a/drivers/input/keyboard/newtonkbd.c b/drivers/input/keyboard/newtonkbd.c index 2c7fff08b1ab..11e08e58d9ac 100644 --- a/drivers/input/keyboard/newtonkbd.c +++ b/drivers/input/keyboard/newtonkbd.c @@ -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; diff --git a/drivers/input/keyboard/sunkbd.c b/drivers/input/keyboard/sunkbd.c index 8e41f20ad590..4145d5a04ecb 100644 --- a/drivers/input/keyboard/sunkbd.c +++ b/drivers/input/keyboard/sunkbd.c @@ -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; diff --git a/drivers/input/keyboard/xtkbd.c b/drivers/input/keyboard/xtkbd.c index bcf4eb098fdf..57c6a06afba9 100644 --- a/drivers/input/keyboard/xtkbd.c +++ b/drivers/input/keyboard/xtkbd.c @@ -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; diff --git a/drivers/input/misc/Config.help b/drivers/input/misc/Config.help new file mode 100644 index 000000000000..8aa138cf520d --- /dev/null +++ b/drivers/input/misc/Config.help @@ -0,0 +1,28 @@ +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 . + + +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 . diff --git a/drivers/input/misc/Config.in b/drivers/input/misc/Config.in new file mode 100644 index 000000000000..ac5ff787314b --- /dev/null +++ b/drivers/input/misc/Config.in @@ -0,0 +1,8 @@ +# +# 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 diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile new file mode 100644 index 000000000000..9d8fc29e0ec4 --- /dev/null +++ b/drivers/input/misc/Makefile @@ -0,0 +1,12 @@ +# +# 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 diff --git a/drivers/input/misc/pcspkr.c b/drivers/input/misc/pcspkr.c new file mode 100644 index 000000000000..198fee230bdd --- /dev/null +++ b/drivers/input/misc/pcspkr.c @@ -0,0 +1,94 @@ +/* + * 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 +#include +#include +#include +#include + +MODULE_AUTHOR("Vojtech Pavlik "); +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); diff --git a/drivers/input/uinput.c b/drivers/input/misc/uinput.c similarity index 100% rename from drivers/input/uinput.c rename to drivers/input/misc/uinput.c diff --git a/include/linux/input.h b/include/linux/input.h index 30eb4d242b3b..cd2a6856e2a9 100644 --- a/include/linux/input.h +++ b/include/linux/input.h @@ -570,6 +570,7 @@ struct input_absinfo { #define SND_CLICK 0x00 #define SND_BELL 0x01 +#define SND_TONE 0x02 #define SND_MAX 0x07 /* diff --git a/include/linux/vt_kern.h b/include/linux/vt_kern.h index 6f668c171107..6d0b234f5a61 100644 --- a/include/linux/vt_kern.h +++ b/include/linux/vt_kern.h @@ -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 */ -- 2.39.5