linux/drivers/input/keyboard/atkbd.c

// SPDX-License-Identifier: GPL-2.0-only
/*
 * AT and PS/2 keyboard driver
 *
 * Copyright (c) 1999-2002 Vojtech Pavlik
 */


/*
 * This driver can handle standard AT keyboards and PS/2 keyboards in
 * Translated and Raw Set 2 and Set 3, as well as AT keyboards on dumb
 * input-only controllers and AT keyboards connected over a one way RS232
 * converter.
 */

#include <linux/delay.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/interrupt.h>
#include <linux/init.h>
#include <linux/input.h>
#include <linux/input/vivaldi-fmap.h>
#include <linux/serio.h>
#include <linux/workqueue.h>
#include <linux/libps2.h>
#include <linux/mutex.h>
#include <linux/dmi.h>
#include <linux/property.h>

#define DRIVER_DESC

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

static int atkbd_set =;
module_param_named(set, atkbd_set, int, 0);
MODULE_PARM_DESC();

#if defined(__i386__) || defined(__x86_64__) || defined(__hppa__)
static bool atkbd_reset;
#else
static bool atkbd_reset = true;
#endif
module_param_named(reset, atkbd_reset, bool, 0);
MODULE_PARM_DESC();

static bool atkbd_softrepeat;
module_param_named(softrepeat, atkbd_softrepeat, bool, 0);
MODULE_PARM_DESC();

static bool atkbd_softraw =;
module_param_named(softraw, atkbd_softraw, bool, 0);
MODULE_PARM_DESC();

static bool atkbd_scroll;
module_param_named(scroll, atkbd_scroll, bool, 0);
MODULE_PARM_DESC();

static bool atkbd_extra;
module_param_named(extra, atkbd_extra, bool, 0);
MODULE_PARM_DESC();

static bool atkbd_terminal;
module_param_named(terminal, atkbd_terminal, bool, 0);
MODULE_PARM_DESC();

#define SCANCODE(keymap)
#define KEYCODE(keymap)

/*
 * Scancode to keycode tables. These are just the default setting, and
 * are loadable via a userland utility.
 */

#define ATKBD_KEYMAP_SIZE

static const unsigned short atkbd_set2_keycode[ATKBD_KEYMAP_SIZE] =;

static const unsigned short atkbd_set3_keycode[ATKBD_KEYMAP_SIZE] =;

static const unsigned short atkbd_unxlate_table[128] =;

#define ATKBD_CMD_SETLEDS
#define ATKBD_CMD_GSCANSET
#define ATKBD_CMD_SSCANSET
#define ATKBD_CMD_GETID
#define ATKBD_CMD_SETREP
#define ATKBD_CMD_ENABLE
#define ATKBD_CMD_RESET_DIS
#define ATKBD_CMD_RESET_DEF
#define ATKBD_CMD_SETALL_MB
#define ATKBD_CMD_SETALL_MBR
#define ATKBD_CMD_RESET_BAT
#define ATKBD_CMD_RESEND
#define ATKBD_CMD_EX_ENABLE
#define ATKBD_CMD_EX_SETLEDS
#define ATKBD_CMD_OK_GETID

#define ATKBD_RET_ACK
#define ATKBD_RET_NAK
#define ATKBD_RET_BAT
#define ATKBD_RET_EMUL0
#define ATKBD_RET_EMUL1
#define ATKBD_RET_RELEASE
#define ATKBD_RET_HANJA
#define ATKBD_RET_HANGEUL
#define ATKBD_RET_ERR

#define ATKBD_KEY_UNKNOWN
#define ATKBD_KEY_NULL

#define ATKBD_SCR_1
#define ATKBD_SCR_2
#define ATKBD_SCR_4
#define ATKBD_SCR_8
#define ATKBD_SCR_CLICK
#define ATKBD_SCR_LEFT
#define ATKBD_SCR_RIGHT

#define ATKBD_SPECIAL

#define ATKBD_LED_EVENT_BIT
#define ATKBD_REP_EVENT_BIT

#define ATKBD_XL_ERR
#define ATKBD_XL_BAT
#define ATKBD_XL_ACK
#define ATKBD_XL_NAK
#define ATKBD_XL_HANGEUL
#define ATKBD_XL_HANJA

static const struct {} atkbd_scroll_keys[] =;

/*
 * The atkbd control structure
 */

struct atkbd {};

/*
 * System-specific keymap fixup routine
 */
static void (*atkbd_platform_fixup)(struct atkbd *, const void *data);
static void *atkbd_platform_fixup_data;
static unsigned int (*atkbd_platform_scancode_fixup)(struct atkbd *, unsigned int);

/*
 * Certain keyboards to not like ATKBD_CMD_RESET_DIS and stop responding
 * to many commands until full reset (ATKBD_CMD_RESET_BAT) is performed.
 */
static bool atkbd_skip_deactivate;

static ssize_t atkbd_attr_show_helper(struct device *dev, char *buf,
				ssize_t (*handler)(struct atkbd *, char *));
static ssize_t atkbd_attr_set_helper(struct device *dev, const char *buf, size_t count,
				ssize_t (*handler)(struct atkbd *, const char *, size_t));
#define ATKBD_DEFINE_ATTR(_name)

ATKBD_DEFINE_ATTR(extra);
ATKBD_DEFINE_ATTR(force_release);
ATKBD_DEFINE_ATTR(scroll);
ATKBD_DEFINE_ATTR(set);
ATKBD_DEFINE_ATTR(softrepeat);
ATKBD_DEFINE_ATTR(softraw);

#define ATKBD_DEFINE_RO_ATTR(_name)

ATKBD_DEFINE_RO_ATTR(err_count);
ATKBD_DEFINE_RO_ATTR(function_row_physmap);

static struct attribute *atkbd_attributes[] =;

static ssize_t atkbd_show_function_row_physmap(struct atkbd *atkbd, char *buf)
{}

static struct atkbd *atkbd_from_serio(struct serio *serio)
{}

static umode_t atkbd_attr_is_visible(struct kobject *kobj,
				struct attribute *attr, int i)
{}

static const struct attribute_group atkbd_attribute_group =;

__ATTRIBUTE_GROUPS();

static const unsigned int xl_table[] =;

/*
 * Checks if we should mangle the scancode to extract 'release' bit
 * in translated mode.
 */
static bool atkbd_need_xlate(unsigned long xl_bit, unsigned char code)
{}

/*
 * Calculates new value of xl_bit so the driver can distinguish
 * between make/break pair of scancodes for select keys and PS/2
 * protocol responses.
 */
static void atkbd_calculate_xl_bit(struct atkbd *atkbd, unsigned char code)
{}

/*
 * Encode the scancode, 0xe0 prefix, and high bit into a single integer,
 * keeping kernel 2.4 compatibility for set 2
 */
static unsigned int atkbd_compat_scancode(struct atkbd *atkbd, unsigned int code)
{}

/*
 * Tries to handle frame or parity error by requesting the keyboard controller
 * to resend the last byte. This historically not done on x86 as controllers
 * there typically do not implement this command.
 */
static bool __maybe_unused atkbd_handle_frame_error(struct ps2dev *ps2dev,
						    u8 data, unsigned int flags)
{}

static enum ps2_disposition atkbd_pre_receive_byte(struct ps2dev *ps2dev,
						   u8 data, unsigned int flags)
{}

static void atkbd_receive_byte(struct ps2dev *ps2dev, u8 data)
{}

static int atkbd_set_repeat_rate(struct atkbd *atkbd)
{}

static int atkbd_set_leds(struct atkbd *atkbd)
{}

/*
 * atkbd_event_work() is used to complete processing of events that
 * can not be processed by input_event() which is often called from
 * interrupt context.
 */

static void atkbd_event_work(struct work_struct *work)
{}

/*
 * Schedule switch for execution. We need to throttle requests,
 * otherwise keyboard may become unresponsive.
 */
static void atkbd_schedule_event_work(struct atkbd *atkbd, int event_bit)
{}

/*
 * Event callback from the input module. Events that change the state of
 * the hardware are processed here. If action can not be performed in
 * interrupt context it is offloaded to atkbd_event_work.
 */

static int atkbd_event(struct input_dev *dev,
			unsigned int type, unsigned int code, int value)
{}

/*
 * atkbd_enable() signals that interrupt handler is allowed to
 * generate input events.
 */

static inline void atkbd_enable(struct atkbd *atkbd)
{}

/*
 * atkbd_disable() tells input handler that all incoming data except
 * for ACKs and command response should be dropped.
 */

static inline void atkbd_disable(struct atkbd *atkbd)
{}

static int atkbd_activate(struct atkbd *atkbd)
{}

/*
 * atkbd_deactivate() resets and disables the keyboard from sending
 * keystrokes.
 */

static void atkbd_deactivate(struct atkbd *atkbd)
{}

#ifdef CONFIG_X86
static bool atkbd_is_portable_device(void)
{}

/*
 * On many modern laptops ATKBD_CMD_GETID may cause problems, on these laptops
 * the controller is always in translated mode. In this mode mice/touchpads will
 * not work. So in this case simply assume a keyboard is connected to avoid
 * confusing some laptop keyboards.
 *
 * Skipping ATKBD_CMD_GETID ends up using a fake keyboard id. Using the standard
 * 0xab83 id is ok in translated mode, only atkbd_select_set() checks atkbd->id
 * and in translated mode that is a no-op.
 */
static bool atkbd_skip_getid(struct atkbd *atkbd)
{}
#else
static inline bool atkbd_skip_getid(struct atkbd *atkbd) { return false; }
#endif

/*
 * atkbd_probe() probes for an AT keyboard on a serio port.
 */

static int atkbd_probe(struct atkbd *atkbd)
{}

/*
 * atkbd_select_set checks if a keyboard has a working Set 3 support, and
 * sets it into that. Unfortunately there are keyboards that can be switched
 * to Set 3, but don't work well in that (BTC Multimedia ...)
 */

static int atkbd_select_set(struct atkbd *atkbd, int target_set, int allow_extra)
{}

static int atkbd_reset_state(struct atkbd *atkbd)
{}

/*
 * atkbd_cleanup() restores the keyboard state so that BIOS is happy after a
 * reboot.
 */

static void atkbd_cleanup(struct serio *serio)
{}


/*
 * atkbd_disconnect() closes and frees.
 */

static void atkbd_disconnect(struct serio *serio)
{}

/*
 * generate release events for the keycodes given in data
 */
static void atkbd_apply_forced_release_keylist(struct atkbd* atkbd,
						const void *data)
{}

/*
 * Most special keys (Fn+F?) on Dell laptops do not generate release
 * events so we have to do it ourselves.
 */
static unsigned int atkbd_dell_laptop_forced_release_keys[] =;

/*
 * Perform fixup for HP system that doesn't generate release
 * for its video switch
 */
static unsigned int atkbd_hp_forced_release_keys[] =;

/*
 * Samsung NC10,NC20 with Fn+F? key release not working
 */
static unsigned int atkbd_samsung_forced_release_keys[] =;

/*
 * Amilo Pi 3525 key release for Fn+Volume keys not working
 */
static unsigned int atkbd_amilo_pi3525_forced_release_keys[] =;

/*
 * Amilo Xi 3650 key release for light touch bar not working
 */
static unsigned int atkbd_amilo_xi3650_forced_release_keys[] =;

/*
 * Soltech TA12 system with broken key release on volume keys and mute key
 */
static unsigned int atkdb_soltech_ta12_forced_release_keys[] =;

/*
 * Many notebooks don't send key release event for volume up/down
 * keys, with key list below common among them
 */
static unsigned int atkbd_volume_forced_release_keys[] =;

/*
 * OQO 01+ multimedia keys (64--66) generate e0 6x upon release whereas
 * they should be generating e4-e6 (0x80 | code).
 */
static unsigned int atkbd_oqo_01plus_scancode_fixup(struct atkbd *atkbd,
						    unsigned int code)
{}

static int atkbd_get_keymap_from_fwnode(struct atkbd *atkbd)
{}

/*
 * atkbd_set_keycode_table() initializes keyboard's keycode table
 * according to the selected scancode set
 */

static void atkbd_set_keycode_table(struct atkbd *atkbd)
{}

/*
 * atkbd_set_device_attrs() sets up keyboard's input device structure
 */

static void atkbd_set_device_attrs(struct atkbd *atkbd)
{}

static void atkbd_parse_fwnode_data(struct serio *serio)
{}

/*
 * atkbd_connect() is called when the serio module finds an interface
 * that isn't handled yet by an appropriate device driver. We check if
 * there is an AT keyboard out there and if yes, we register ourselves
 * to the input module.
 */

static int atkbd_connect(struct serio *serio, struct serio_driver *drv)
{}

/*
 * atkbd_reconnect() tries to restore keyboard into a sane state and is
 * most likely called on resume.
 */

static int atkbd_reconnect(struct serio *serio)
{}

static const struct serio_device_id atkbd_serio_ids[] =;

MODULE_DEVICE_TABLE(serio, atkbd_serio_ids);

static struct serio_driver atkbd_drv =;

static ssize_t atkbd_attr_show_helper(struct device *dev, char *buf,
				ssize_t (*handler)(struct atkbd *, char *))
{}

static ssize_t atkbd_attr_set_helper(struct device *dev, const char *buf, size_t count,
				ssize_t (*handler)(struct atkbd *, const char *, size_t))
{}

static ssize_t atkbd_show_extra(struct atkbd *atkbd, char *buf)
{}

static ssize_t atkbd_set_extra(struct atkbd *atkbd, const char *buf, size_t count)
{}

static ssize_t atkbd_show_force_release(struct atkbd *atkbd, char *buf)
{}

static ssize_t atkbd_set_force_release(struct atkbd *atkbd,
					const char *buf, size_t count)
{}


static ssize_t atkbd_show_scroll(struct atkbd *atkbd, char *buf)
{}

static ssize_t atkbd_set_scroll(struct atkbd *atkbd, const char *buf, size_t count)
{}

static ssize_t atkbd_show_set(struct atkbd *atkbd, char *buf)
{}

static ssize_t atkbd_set_set(struct atkbd *atkbd, const char *buf, size_t count)
{}

static ssize_t atkbd_show_softrepeat(struct atkbd *atkbd, char *buf)
{}

static ssize_t atkbd_set_softrepeat(struct atkbd *atkbd, const char *buf, size_t count)
{}


static ssize_t atkbd_show_softraw(struct atkbd *atkbd, char *buf)
{}

static ssize_t atkbd_set_softraw(struct atkbd *atkbd, const char *buf, size_t count)
{}

static ssize_t atkbd_show_err_count(struct atkbd *atkbd, char *buf)
{}

static int __init atkbd_setup_forced_release(const struct dmi_system_id *id)
{}

static int __init atkbd_setup_scancode_fixup(const struct dmi_system_id *id)
{}

static int __init atkbd_deactivate_fixup(const struct dmi_system_id *id)
{}

/*
 * NOTE: do not add any more "force release" quirks to this table.  The
 * task of adjusting list of keys that should be "released" automatically
 * by the driver is now delegated to userspace tools, such as udev, so
 * submit such quirks there.
 */
static const struct dmi_system_id atkbd_dmi_quirk_table[] __initconst =;

static int __init atkbd_init(void)
{}

static void __exit atkbd_exit(void)
{}

module_init();
module_exit(atkbd_exit);