// SPDX-License-Identifier: GPL-2.0-or-later
/*
* HID driver for Asus notebook built-in keyboard.
* Fixes small logical maximum to match usage maximum.
*
* Currently supported devices are:
* EeeBook X205TA
* VivoBook E200HA
*
* Copyright (c) 2016 Yusuke Fujimaki <usk.fujimaki@gmail.com>
*
* This module based on hid-ortek by
* Copyright (c) 2010 Johnathon Harris <jmharris@gmail.com>
* Copyright (c) 2011 Jiri Kosina
*
* This module has been updated to add support for Asus i2c touchpad.
*
* Copyright (c) 2016 Brendan McGrath <redmcg@redmandi.dyndns.org>
* Copyright (c) 2016 Victor Vlasenko <victor.vlasenko@sysgears.com>
* Copyright (c) 2016 Frederik Wenigwieser <frederik.wenigwieser@gmail.com>
*/
/*
*/
#include <linux/dmi.h>
#include <linux/hid.h>
#include <linux/module.h>
#include <linux/platform_data/x86/asus-wmi.h>
#include <linux/input/mt.h>
#include <linux/usb.h> /* For to_usb_interface for T100 touchpad intf check */
#include <linux/power_supply.h>
#include "hid-ids.h"
MODULE_AUTHOR("Yusuke Fujimaki <usk.fujimaki@gmail.com>");
MODULE_AUTHOR("Brendan McGrath <redmcg@redmandi.dyndns.org>");
MODULE_AUTHOR("Victor Vlasenko <victor.vlasenko@sysgears.com>");
MODULE_AUTHOR("Frederik Wenigwieser <frederik.wenigwieser@gmail.com>");
MODULE_DESCRIPTION("Asus HID Keyboard and TouchPad");
#define T100_TPAD_INTF 2
#define MEDION_E1239T_TPAD_INTF 1
#define E1239T_TP_TOGGLE_REPORT_ID 0x05
#define T100CHI_MOUSE_REPORT_ID 0x06
#define FEATURE_REPORT_ID 0x0d
#define INPUT_REPORT_ID 0x5d
#define FEATURE_KBD_REPORT_ID 0x5a
#define FEATURE_KBD_REPORT_SIZE 16
#define FEATURE_KBD_LED_REPORT_ID1 0x5d
#define FEATURE_KBD_LED_REPORT_ID2 0x5e
#define SUPPORT_KBD_BACKLIGHT BIT(0)
#define MAX_TOUCH_MAJOR 8
#define MAX_PRESSURE 128
#define BTN_LEFT_MASK 0x01
#define CONTACT_TOOL_TYPE_MASK 0x80
#define CONTACT_X_MSB_MASK 0xf0
#define CONTACT_Y_MSB_MASK 0x0f
#define CONTACT_TOUCH_MAJOR_MASK 0x07
#define CONTACT_PRESSURE_MASK 0x7f
#define BATTERY_REPORT_ID (0x03)
#define BATTERY_REPORT_SIZE (1 + 8)
#define BATTERY_LEVEL_MAX ((u8)255)
#define BATTERY_STAT_DISCONNECT (0)
#define BATTERY_STAT_CHARGING (1)
#define BATTERY_STAT_FULL (2)
#define QUIRK_FIX_NOTEBOOK_REPORT BIT(0)
#define QUIRK_NO_INIT_REPORTS BIT(1)
#define QUIRK_SKIP_INPUT_MAPPING BIT(2)
#define QUIRK_IS_MULTITOUCH BIT(3)
#define QUIRK_NO_CONSUMER_USAGES BIT(4)
#define QUIRK_USE_KBD_BACKLIGHT BIT(5)
#define QUIRK_T100_KEYBOARD BIT(6)
#define QUIRK_T100CHI BIT(7)
#define QUIRK_G752_KEYBOARD BIT(8)
#define QUIRK_T90CHI BIT(9)
#define QUIRK_MEDION_E1239T BIT(10)
#define QUIRK_ROG_NKEY_KEYBOARD BIT(11)
#define QUIRK_ROG_CLAYMORE_II_KEYBOARD BIT(12)
#define I2C_KEYBOARD_QUIRKS (QUIRK_FIX_NOTEBOOK_REPORT | \
QUIRK_NO_INIT_REPORTS | \
QUIRK_NO_CONSUMER_USAGES)
#define I2C_TOUCHPAD_QUIRKS (QUIRK_NO_INIT_REPORTS | \
QUIRK_SKIP_INPUT_MAPPING | \
QUIRK_IS_MULTITOUCH)
#define TRKID_SGN ((TRKID_MAX + 1) >> 1)
struct asus_kbd_leds {
struct led_classdev cdev;
struct hid_device *hdev;
struct work_struct work;
unsigned int brightness;
bool removed;
};
struct asus_touchpad_info {
int max_x;
int max_y;
int res_x;
int res_y;
int contact_size;
int max_contacts;
int report_size;
};
struct asus_drvdata {
unsigned long quirks;
struct hid_device *hdev;
struct input_dev *input;
struct input_dev *tp_kbd_input;
struct asus_kbd_leds *kbd_backlight;
const struct asus_touchpad_info *tp;
bool enable_backlight;
struct power_supply *battery;
struct power_supply_desc battery_desc;
int battery_capacity;
int battery_stat;
bool battery_in_query;
unsigned long battery_next_query;
};
static int asus_report_battery(struct asus_drvdata *, u8 *, int);
static const struct asus_touchpad_info asus_i2c_tp = {
.max_x = 2794,
.max_y = 1758,
.contact_size = 5,
.max_contacts = 5,
.report_size = 28 /* 2 byte header + 5 * 5 + 1 byte footer */,
};
static const struct asus_touchpad_info asus_t100ta_tp = {
.max_x = 2240,
.max_y = 1120,
.res_x = 30, /* units/mm */
.res_y = 27, /* units/mm */
.contact_size = 5,
.max_contacts = 5,
.report_size = 28 /* 2 byte header + 5 * 5 + 1 byte footer */,
};
static const struct asus_touchpad_info asus_t100ha_tp = {
.max_x = 2640,
.max_y = 1320,
.res_x = 30,<