linux/drivers/input/keyboard/lkkbd.c

// SPDX-License-Identifier: GPL-2.0-or-later
/*
 *  Copyright (C) 2004 by Jan-Benedict Glaw <[email protected]>
 */

/*
 * LK keyboard driver for Linux, based on sunkbd.c (C) by Vojtech Pavlik
 */

/*
 * DEC LK201 and LK401 keyboard driver for Linux (primary for DECstations
 * and VAXstations, but can also be used on any standard RS232 with an
 * adaptor).
 *
 * DISCLAIMER: This works for _me_. If you break anything by using the
 * information given below, I will _not_ be liable!
 *
 * RJ10 pinout:		To DE9:		Or DB25:
 *	1 - RxD <---->	Pin 3 (TxD) <->	Pin 2 (TxD)
 *	2 - GND <---->	Pin 5 (GND) <->	Pin 7 (GND)
 *	4 - TxD <---->	Pin 2 (RxD) <->	Pin 3 (RxD)
 *	3 - +12V (from HDD drive connector), DON'T connect to DE9 or DB25!!!
 *
 * Pin numbers for DE9 and DB25 are noted on the plug (quite small:). For
 * RJ10, it's like this:
 *
 *      __=__	Hold the plug in front of you, cable downwards,
 *     /___/|	nose is hidden behind the plug. Now, pin 1 is at
 *    |1234||	the left side, pin 4 at the right and 2 and 3 are
 *    |IIII||	in between, of course:)
 *    |    ||
 *    |____|/
 *      ||	So the adaptor consists of three connected cables
 *      ||	for data transmission (RxD and TxD) and signal ground.
 *		Additionally, you have to get +12V from somewhere.
 * Most easily, you'll get that from a floppy or HDD power connector.
 * It's the yellow cable there (black is ground and red is +5V).
 *
 * The keyboard and all the commands it understands are documented in
 * "VCB02 Video Subsystem - Technical Manual", EK-104AA-TM-001. This
 * document is LK201 specific, but LK401 is mostly compatible. It comes
 * up in LK201 mode and doesn't report any of the additional keys it
 * has. These need to be switched on with the LK_CMD_ENABLE_LK401
 * command. You'll find this document (scanned .pdf file) on MANX,
 * a search engine specific to DEC documentation. Try
 * http://www.vt100.net/manx/details?pn=EK-104AA-TM-001;id=21;cp=1
 */

#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/input.h>
#include <linux/serio.h>
#include <linux/workqueue.h>

#define DRIVER_DESC

MODULE_AUTHOR();
MODULE_DESCRIPTION();
MODULE_LICENSE();

/*
 * Known parameters:
 *	bell_volume
 *	keyclick_volume
 *	ctrlclick_volume
 *
 * Please notice that there's not yet an API to set these at runtime.
 */
static int bell_volume =; /* % */
module_param(bell_volume, int, 0);
MODULE_PARM_DESC();

static int keyclick_volume =; /* % */
module_param(keyclick_volume, int, 0);
MODULE_PARM_DESC();

static int ctrlclick_volume =; /* % */
module_param(ctrlclick_volume, int, 0);
MODULE_PARM_DESC();

static int lk201_compose_is_alt;
module_param(lk201_compose_is_alt, int, 0);
MODULE_PARM_DESC();



#undef LKKBD_DEBUG
#ifdef LKKBD_DEBUG
#define DBG
#else
#define DBG(x...)
#endif

/* LED control */
#define LK_LED_WAIT
#define LK_LED_COMPOSE
#define LK_LED_SHIFTLOCK
#define LK_LED_SCROLLLOCK
#define LK_CMD_LED_ON
#define LK_CMD_LED_OFF

/* Mode control */
#define LK_MODE_DOWN
#define LK_MODE_AUTODOWN
#define LK_MODE_UPDOWN
#define LK_CMD_SET_MODE(mode, div)

/* Misc commands */
#define LK_CMD_ENABLE_KEYCLICK
#define LK_CMD_DISABLE_KEYCLICK
#define LK_CMD_DISABLE_BELL
#define LK_CMD_SOUND_BELL
#define LK_CMD_ENABLE_BELL
#define LK_CMD_DISABLE_CTRCLICK
#define LK_CMD_ENABLE_CTRCLICK
#define LK_CMD_SET_DEFAULTS
#define LK_CMD_POWERCYCLE_RESET
#define LK_CMD_ENABLE_LK401
#define LK_CMD_REQUEST_ID

/* Misc responses from keyboard */
#define LK_STUCK_KEY
#define LK_SELFTEST_FAILED
#define LK_ALL_KEYS_UP
#define LK_METRONOME
#define LK_OUTPUT_ERROR
#define LK_INPUT_ERROR
#define LK_KBD_LOCKED
#define LK_KBD_TEST_MODE_ACK
#define LK_PREFIX_KEY_DOWN
#define LK_MODE_CHANGE_ACK
#define LK_RESPONSE_RESERVED

#define LK_NUM_KEYCODES
#define LK_NUM_IGNORE_BYTES

static unsigned short lkkbd_keycode[LK_NUM_KEYCODES] =;

#define CHECK_LED(LK, VAR_ON, VAR_OFF, LED, BITS)

/*
 * Per-keyboard data
 */
struct lkkbd {};

#ifdef LKKBD_DEBUG
/*
 * Responses from the keyboard and mapping back to their names.
 */
static struct {
	unsigned char value;
	unsigned char *name;
} lk_response[] = {
#define RESPONSE
	RESPONSE(LK_STUCK_KEY),
	RESPONSE(LK_SELFTEST_FAILED),
	RESPONSE(LK_ALL_KEYS_UP),
	RESPONSE(LK_METRONOME),
	RESPONSE(LK_OUTPUT_ERROR),
	RESPONSE(LK_INPUT_ERROR),
	RESPONSE(LK_KBD_LOCKED),
	RESPONSE(LK_KBD_TEST_MODE_ACK),
	RESPONSE(LK_PREFIX_KEY_DOWN),
	RESPONSE(LK_MODE_CHANGE_ACK),
	RESPONSE(LK_RESPONSE_RESERVED),
#undef RESPONSE
};

static unsigned char *response_name(unsigned char value)
{
	int i;

	for (i = 0; i < ARRAY_SIZE(lk_response); i++)
		if (lk_response[i].value == value)
			return lk_response[i].name;

	return "<unknown>";
}
#endif /* LKKBD_DEBUG */

/*
 * Calculate volume parameter byte for a given volume.
 */
static unsigned char volume_to_hw(int volume_percent)
{}

static void lkkbd_detection_done(struct lkkbd *lk)
{}

/*
 * lkkbd_interrupt() is called by the low level driver when a character
 * is received.
 */
static irqreturn_t lkkbd_interrupt(struct serio *serio,
				   unsigned char data, unsigned int flags)
{}

static void lkkbd_toggle_leds(struct lkkbd *lk)
{}

static void lkkbd_toggle_keyclick(struct lkkbd *lk, bool on)
{}

/*
 * lkkbd_event() handles events from the input module.
 */
static int lkkbd_event(struct input_dev *dev,
			unsigned int type, unsigned int code, int value)
{}

/*
 * lkkbd_reinit() sets leds and beeps to a state the computer remembers they
 * were in.
 */
static void lkkbd_reinit(struct work_struct *work)
{}

/*
 * lkkbd_connect() probes for a LK keyboard and fills the necessary structures.
 */
static int lkkbd_connect(struct serio *serio, struct serio_driver *drv)
{}

/*
 * lkkbd_disconnect() unregisters and closes behind us.
 */
static void lkkbd_disconnect(struct serio *serio)
{}

static const struct serio_device_id lkkbd_serio_ids[] =;

MODULE_DEVICE_TABLE(serio, lkkbd_serio_ids);

static struct serio_driver lkkbd_drv =;

module_serio_driver();