linux/drivers/input/misc/ideapad_slidebar.c

// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * Input driver for slidebars on some Lenovo IdeaPad laptops
 *
 * Copyright (C) 2013 Andrey Moiseev <[email protected]>
 *
 * Reverse-engineered from Lenovo SlideNav software (SBarHook.dll).
 *
 * Trademarks are the property of their respective owners.
 */

/*
 * Currently tested and works on:
 *	Lenovo IdeaPad Y550
 *	Lenovo IdeaPad Y550P
 *
 * Other models can be added easily. To test,
 * load with 'force' parameter set 'true'.
 *
 * LEDs blinking and input mode are managed via sysfs,
 * (hex, unsigned byte value):
 * /sys/devices/platform/ideapad_slidebar/slidebar_mode
 *
 * The value is in byte range, however, I only figured out
 * how bits 0b10011001 work. Some other bits, probably,
 * are meaningfull too.
 *
 * Possible states:
 *
 * STD_INT, ONMOV_INT, OFF_INT, LAST_POLL, OFF_POLL
 *
 * Meaning:
 *           released      touched
 * STD       'heartbeat'   lights follow the finger
 * ONMOV     no lights     lights follow the finger
 * LAST      at last pos   lights follow the finger
 * OFF       no lights     no lights
 *
 * INT       all input events are generated, interrupts are used
 * POLL      no input events by default, to get them,
 *	     send 0b10000000 (read below)
 *
 * Commands: write
 *
 * All      |  0b01001 -> STD_INT
 * possible |  0b10001 -> ONMOV_INT
 * states   |  0b01000 -> OFF_INT
 *
 *                      |  0b0 -> LAST_POLL
 * STD_INT or ONMOV_INT |
 *                      |  0b1 -> STD_INT
 *
 *                      |  0b0 -> OFF_POLL
 * OFF_INT or OFF_POLL  |
 *                      |  0b1 -> OFF_INT
 *
 * Any state |   0b10000000 ->  if the slidebar has updated data,
 *				produce one input event (last position),
 *				switch to respective POLL mode
 *				(like 0x0), if not in POLL mode yet.
 *
 * Get current state: read
 *
 * masked by 0x11 read value means:
 *
 * 0x00   LAST
 * 0x01   STD
 * 0x10   OFF
 * 0x11   ONMOV
 */

#define pr_fmt(fmt)

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/dmi.h>
#include <linux/spinlock.h>
#include <linux/platform_device.h>
#include <linux/input.h>
#include <linux/io.h>
#include <linux/ioport.h>
#include <linux/i8042.h>
#include <linux/serio.h>

#define IDEAPAD_BASE

static bool force;
module_param(force, bool, 0);
MODULE_PARM_DESC();

static DEFINE_SPINLOCK(io_lock);

static struct input_dev *slidebar_input_dev;
static struct platform_device *slidebar_platform_dev;

static u8 slidebar_pos_get(void)
{}

static u8 slidebar_mode_get(void)
{}

static void slidebar_mode_set(u8 mode)
{}

static bool slidebar_i8042_filter(unsigned char data, unsigned char str,
				  struct serio *port)
{}

static ssize_t show_slidebar_mode(struct device *dev,
				  struct device_attribute *attr,
				  char *buf)
{}

static ssize_t store_slidebar_mode(struct device *dev,
				   struct device_attribute *attr,
				   const char *buf, size_t count)
{}

static DEVICE_ATTR(slidebar_mode, S_IWUSR | S_IRUGO,
		   show_slidebar_mode, store_slidebar_mode);

static struct attribute *ideapad_attrs[] =;

static struct attribute_group ideapad_attr_group =;

static const struct attribute_group *ideapad_attr_groups[] =;

static int __init ideapad_probe(struct platform_device* pdev)
{}

static void ideapad_remove(struct platform_device *pdev)
{}

static struct platform_driver slidebar_drv =;

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

static const struct dmi_system_id ideapad_dmi[] __initconst =;
MODULE_DEVICE_TABLE(dmi, ideapad_dmi);

static int __init slidebar_init(void)
{}

static void __exit slidebar_exit(void)
{}

module_init();
module_exit(slidebar_exit);

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