cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

mac_hid.c (5885B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * drivers/macintosh/mac_hid.c
      4 *
      5 * HID support stuff for Macintosh computers.
      6 *
      7 * Copyright (C) 2000 Franz Sirl.
      8 *
      9 * This file will soon be removed in favor of an uinput userspace tool.
     10 */
     11
     12#include <linux/init.h>
     13#include <linux/proc_fs.h>
     14#include <linux/sysctl.h>
     15#include <linux/input.h>
     16#include <linux/module.h>
     17#include <linux/slab.h>
     18
     19MODULE_LICENSE("GPL");
     20
     21static int mouse_emulate_buttons;
     22static int mouse_button2_keycode = KEY_RIGHTCTRL;	/* right control key */
     23static int mouse_button3_keycode = KEY_RIGHTALT;	/* right option key */
     24
     25static struct input_dev *mac_hid_emumouse_dev;
     26
     27static DEFINE_MUTEX(mac_hid_emumouse_mutex);
     28
     29static int mac_hid_create_emumouse(void)
     30{
     31	static struct lock_class_key mac_hid_emumouse_dev_event_class;
     32	static struct lock_class_key mac_hid_emumouse_dev_mutex_class;
     33	int err;
     34
     35	mac_hid_emumouse_dev = input_allocate_device();
     36	if (!mac_hid_emumouse_dev)
     37		return -ENOMEM;
     38
     39	lockdep_set_class(&mac_hid_emumouse_dev->event_lock,
     40			  &mac_hid_emumouse_dev_event_class);
     41	lockdep_set_class(&mac_hid_emumouse_dev->mutex,
     42			  &mac_hid_emumouse_dev_mutex_class);
     43
     44	mac_hid_emumouse_dev->name = "Macintosh mouse button emulation";
     45	mac_hid_emumouse_dev->id.bustype = BUS_ADB;
     46	mac_hid_emumouse_dev->id.vendor = 0x0001;
     47	mac_hid_emumouse_dev->id.product = 0x0001;
     48	mac_hid_emumouse_dev->id.version = 0x0100;
     49
     50	mac_hid_emumouse_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL);
     51	mac_hid_emumouse_dev->keybit[BIT_WORD(BTN_MOUSE)] =
     52		BIT_MASK(BTN_LEFT) | BIT_MASK(BTN_MIDDLE) | BIT_MASK(BTN_RIGHT);
     53	mac_hid_emumouse_dev->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y);
     54
     55	err = input_register_device(mac_hid_emumouse_dev);
     56	if (err) {
     57		input_free_device(mac_hid_emumouse_dev);
     58		mac_hid_emumouse_dev = NULL;
     59		return err;
     60	}
     61
     62	return 0;
     63}
     64
     65static void mac_hid_destroy_emumouse(void)
     66{
     67	input_unregister_device(mac_hid_emumouse_dev);
     68	mac_hid_emumouse_dev = NULL;
     69}
     70
     71static bool mac_hid_emumouse_filter(struct input_handle *handle,
     72				    unsigned int type, unsigned int code,
     73				    int value)
     74{
     75	unsigned int btn;
     76
     77	if (type != EV_KEY)
     78		return false;
     79
     80	if (code == mouse_button2_keycode)
     81		btn = BTN_MIDDLE;
     82	else if (code == mouse_button3_keycode)
     83		btn = BTN_RIGHT;
     84	else
     85		return false;
     86
     87	input_report_key(mac_hid_emumouse_dev, btn, value);
     88	input_sync(mac_hid_emumouse_dev);
     89
     90	return true;
     91}
     92
     93static int mac_hid_emumouse_connect(struct input_handler *handler,
     94				    struct input_dev *dev,
     95				    const struct input_device_id *id)
     96{
     97	struct input_handle *handle;
     98	int error;
     99
    100	/* Don't bind to ourselves */
    101	if (dev == mac_hid_emumouse_dev)
    102		return -ENODEV;
    103
    104	handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL);
    105	if (!handle)
    106		return -ENOMEM;
    107
    108	handle->dev = dev;
    109	handle->handler = handler;
    110	handle->name = "mac-button-emul";
    111
    112	error = input_register_handle(handle);
    113	if (error) {
    114		printk(KERN_ERR
    115			"mac_hid: Failed to register button emulation handle, "
    116			"error %d\n", error);
    117		goto err_free;
    118	}
    119
    120	error = input_open_device(handle);
    121	if (error) {
    122		printk(KERN_ERR
    123			"mac_hid: Failed to open input device, error %d\n",
    124			error);
    125		goto err_unregister;
    126	}
    127
    128	return 0;
    129
    130 err_unregister:
    131	input_unregister_handle(handle);
    132 err_free:
    133	kfree(handle);
    134	return error;
    135}
    136
    137static void mac_hid_emumouse_disconnect(struct input_handle *handle)
    138{
    139	input_close_device(handle);
    140	input_unregister_handle(handle);
    141	kfree(handle);
    142}
    143
    144static const struct input_device_id mac_hid_emumouse_ids[] = {
    145	{
    146		.flags = INPUT_DEVICE_ID_MATCH_EVBIT,
    147		.evbit = { BIT_MASK(EV_KEY) },
    148	},
    149	{ },
    150};
    151
    152MODULE_DEVICE_TABLE(input, mac_hid_emumouse_ids);
    153
    154static struct input_handler mac_hid_emumouse_handler = {
    155	.filter		= mac_hid_emumouse_filter,
    156	.connect	= mac_hid_emumouse_connect,
    157	.disconnect	= mac_hid_emumouse_disconnect,
    158	.name		= "mac-button-emul",
    159	.id_table	= mac_hid_emumouse_ids,
    160};
    161
    162static int mac_hid_start_emulation(void)
    163{
    164	int err;
    165
    166	err = mac_hid_create_emumouse();
    167	if (err)
    168		return err;
    169
    170	err = input_register_handler(&mac_hid_emumouse_handler);
    171	if (err) {
    172		mac_hid_destroy_emumouse();
    173		return err;
    174	}
    175
    176	return 0;
    177}
    178
    179static void mac_hid_stop_emulation(void)
    180{
    181	input_unregister_handler(&mac_hid_emumouse_handler);
    182	mac_hid_destroy_emumouse();
    183}
    184
    185static int mac_hid_toggle_emumouse(struct ctl_table *table, int write,
    186				   void *buffer, size_t *lenp, loff_t *ppos)
    187{
    188	int *valp = table->data;
    189	int old_val = *valp;
    190	int rc;
    191
    192	rc = mutex_lock_killable(&mac_hid_emumouse_mutex);
    193	if (rc)
    194		return rc;
    195
    196	rc = proc_dointvec(table, write, buffer, lenp, ppos);
    197
    198	if (rc == 0 && write && *valp != old_val) {
    199		if (*valp == 1)
    200			rc = mac_hid_start_emulation();
    201		else if (*valp == 0)
    202			mac_hid_stop_emulation();
    203		else
    204			rc = -EINVAL;
    205	}
    206
    207	/* Restore the old value in case of error */
    208	if (rc)
    209		*valp = old_val;
    210
    211	mutex_unlock(&mac_hid_emumouse_mutex);
    212
    213	return rc;
    214}
    215
    216/* file(s) in /proc/sys/dev/mac_hid */
    217static struct ctl_table mac_hid_files[] = {
    218	{
    219		.procname	= "mouse_button_emulation",
    220		.data		= &mouse_emulate_buttons,
    221		.maxlen		= sizeof(int),
    222		.mode		= 0644,
    223		.proc_handler	= mac_hid_toggle_emumouse,
    224	},
    225	{
    226		.procname	= "mouse_button2_keycode",
    227		.data		= &mouse_button2_keycode,
    228		.maxlen		= sizeof(int),
    229		.mode		= 0644,
    230		.proc_handler	= proc_dointvec,
    231	},
    232	{
    233		.procname	= "mouse_button3_keycode",
    234		.data		= &mouse_button3_keycode,
    235		.maxlen		= sizeof(int),
    236		.mode		= 0644,
    237		.proc_handler	= proc_dointvec,
    238	},
    239	{ }
    240};
    241
    242static struct ctl_table_header *mac_hid_sysctl_header;
    243
    244static int __init mac_hid_init(void)
    245{
    246	mac_hid_sysctl_header = register_sysctl("dev/mac_hid", mac_hid_files);
    247	if (!mac_hid_sysctl_header)
    248		return -ENOMEM;
    249
    250	return 0;
    251}
    252module_init(mac_hid_init);
    253
    254static void __exit mac_hid_exit(void)
    255{
    256	unregister_sysctl_table(mac_hid_sysctl_header);
    257
    258	if (mouse_emulate_buttons)
    259		mac_hid_stop_emulation();
    260}
    261module_exit(mac_hid_exit);