patch-2.4.19 linux-2.4.19/drivers/tc/lk201.c

Next file: linux-2.4.19/drivers/tc/lk201.h
Previous file: linux-2.4.19/drivers/sound/ymfpci.h
Back to the patch index
Back to the overall index

diff -urN linux-2.4.18/drivers/tc/lk201.c linux-2.4.19/drivers/tc/lk201.c
@@ -4,13 +4,22 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
+ * Copyright (C) 2001 Maciej W. Rozycki <macro@ds2.pg.gda.pl>
  */
+
+#include <linux/config.h>
+
 #include <linux/errno.h>
+#include <linux/sched.h>
 #include <linux/tty.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/kbd_ll.h>
+#include <linux/kbd_kern.h>
+#include <linux/vt_kern.h>
+
+#include <asm/keyboard.h>
 #include <asm/wbflush.h>
 #include <asm/dec/tc.h>
 #include <asm/dec/machtype.h>
@@ -27,6 +36,8 @@
  */
 unsigned char lk201_sysrq_xlate[128];
 unsigned char *kbd_sysrq_xlate = lk201_sysrq_xlate;
+
+unsigned char kbd_sysrq_key = -1;
 #endif
 
 #define KEYB_LINE	3
@@ -71,6 +82,8 @@
 	LK_CMD_LEDS_OFF, LK_PARAM_LED_MASK(0xf)
 };
 
+static struct dec_serial* lk201kbd_info;
+
 static int __init lk201_reset(struct dec_serial *info)
 {
 	int i;
@@ -83,9 +96,115 @@
 	return 0;
 }
 
+#define DEFAULT_KEYB_REP_DELAY	(250/5)	/* [5ms] */
+#define DEFAULT_KEYB_REP_RATE	30	/* [cps] */
+
+static struct kbd_repeat kbdrate = {
+	DEFAULT_KEYB_REP_DELAY,
+	DEFAULT_KEYB_REP_RATE
+};
+
+static void parse_kbd_rate(struct kbd_repeat *r)
+{
+	if (r->delay <= 0)
+		r->delay = kbdrate.delay;
+	if (r->rate <= 0)
+		r->rate = kbdrate.rate;
+
+	if (r->delay < 5)
+		r->delay = 5;
+	if (r->delay > 630)
+		r->delay = 630;
+	if (r->rate < 12)
+		r->rate = 12;
+	if (r->rate > 127)
+		r->rate = 127;
+	if (r->rate == 125)
+		r->rate = 124;
+}
+
+static int write_kbd_rate(struct kbd_repeat *rep)
+{
+	struct dec_serial* info = lk201kbd_info;
+	int delay, rate;
+	int i;
+
+	delay = rep->delay / 5;
+	rate = rep->rate;
+	for (i = 0; i < 4; i++) {
+		if (info->hook->poll_tx_char(info, LK_CMD_RPT_RATE(i)))
+			return 1;
+		if (info->hook->poll_tx_char(info, LK_PARAM_DELAY(delay)))
+			return 1;
+		if (info->hook->poll_tx_char(info, LK_PARAM_RATE(rate)))
+			return 1;
+	}
+	return 0;
+}
+
+static int lk201kbd_rate(struct kbd_repeat *rep)
+{
+	if (rep == NULL)
+		return -EINVAL;
+
+	parse_kbd_rate(rep);
+
+	if (write_kbd_rate(rep)) {
+		memcpy(rep, &kbdrate, sizeof(struct kbd_repeat));
+		return -EIO;
+	}
+
+	memcpy(&kbdrate, rep, sizeof(struct kbd_repeat));
+
+	return 0;
+}
+
+static void lk201kd_mksound(unsigned int hz, unsigned int ticks)
+{
+	struct dec_serial* info = lk201kbd_info;
+
+	if (!ticks)
+		return;
+
+	/*
+	 * Can't set frequency and we "approximate"
+	 * duration by volume. ;-)
+	 */
+	ticks /= HZ / 32;
+	if (ticks > 7)
+		ticks = 7;
+	ticks = 7 - ticks;
+
+	if (info->hook->poll_tx_char(info, LK_CMD_ENB_BELL))
+		return;
+	if (info->hook->poll_tx_char(info, LK_PARAM_VOLUME(ticks)))
+		return;
+	if (info->hook->poll_tx_char(info, LK_CMD_BELL))
+		return;
+}
+
 void kbd_leds(unsigned char leds)
 {
-	return;
+	struct dec_serial* info = lk201kbd_info;
+	unsigned char l = 0;
+
+	if (!info)		/* FIXME */
+		return;
+
+	/* FIXME -- Only Hold and Lock LEDs for now. --macro */
+	if (leds & LED_SCR)
+		l |= LK_LED_HOLD;
+	if (leds & LED_CAP)
+		l |= LK_LED_LOCK;
+
+	if (info->hook->poll_tx_char(info, LK_CMD_LEDS_ON))
+		return;
+	if (info->hook->poll_tx_char(info, LK_PARAM_LED_MASK(l)))
+		return;
+	if (info->hook->poll_tx_char(info, LK_CMD_LEDS_OFF))
+		return;
+	if (info->hook->poll_tx_char(info, LK_PARAM_LED_MASK(~l)))
+		return;
 }
 
 int kbd_setkeycode(unsigned int scancode, unsigned int keycode)
@@ -118,7 +237,12 @@
 
 	if (!stat || stat == 4) {
 		switch (ch) {
-		case LK_KEY_ACK:
+		case LK_STAT_RESUME_ERR:
+		case LK_STAT_ERROR:
+		case LK_STAT_INHIBIT_ACK:
+		case LK_STAT_TEST_ACK:
+		case LK_STAT_MODE_KEYDOWN:
+		case LK_STAT_MODE_ACK:
 			break;
 		case LK_KEY_LOCK:
 			shift_state ^= LK_LOCK;
@@ -157,6 +281,7 @@
 		}
 	} else
 		printk("Error reading LKx01 keyboard: 0x%02x\n", stat);
+	tasklet_schedule(&keyboard_tasklet);
 }
 
 static void __init lk201_info(struct dec_serial *info)
@@ -200,6 +325,10 @@
 	 */
 	info->hook->rx_char = lk201_kbd_rx_char;
 
+	lk201kbd_info = info;
+	kbd_rate = lk201kbd_rate;
+	kd_mksound = lk201kd_mksound;
+
 	return 0;
 }
 
@@ -231,7 +360,3 @@
 		printk("LK201 Support for DS3100 not yet ready ...\n");
 	}
 }
-
-
-
-

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)