summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGiedrius Statkevicius <giedriuswork@gmail.com>2014-10-30 18:57:47 +0200
committerDarren Hart <dvhart@linux.intel.com>2014-11-07 10:37:03 -0800
commita4c724d0723b078e4ab4670e557cda1795036a7a (patch)
tree209e1ba0ed1f18d6e83099c0f1894b105a5df487
parented78bb846e8bc1a8589fa6e0d9bf2b0f518893d5 (diff)
platform: hp_accel: add a i8042 filter to remove HPQ6000 data from kb bus stream
Add a i8042 filter to hp_accel to remove accelerometer's data with acpi id HPQ6000 from keyboard bus stream. The codes sent by accelerometer are e0 25, e0 26, e0 27 and e0 28. The relevant information is already passed through /dev/freefall so no need to send these undocumented weird signals through the keyboard bus. Also, unclogs `dmesg` because atkbd complained about weird scan codes, saves processing power and disk space. Signed-off-by: Giedrius Statkevičius <giedriuswork@gmail.com> Acked-by: Dmitry Torokhov <dmitry.torokhov@gmail.com> Reviewed-by: Éric Piel <eric.piel@tremplin-utc.net> Signed-off-by: Darren Hart <dvhart@linux.intel.com>
-rw-r--r--drivers/platform/x86/hp_accel.c44
1 files changed, 44 insertions, 0 deletions
diff --git a/drivers/platform/x86/hp_accel.c b/drivers/platform/x86/hp_accel.c
index 13e14ec1d3d7..6bec745b6b92 100644
--- a/drivers/platform/x86/hp_accel.c
+++ b/drivers/platform/x86/hp_accel.c
@@ -37,6 +37,8 @@
#include <linux/leds.h>
#include <linux/atomic.h>
#include <linux/acpi.h>
+#include <linux/i8042.h>
+#include <linux/serio.h>
#include "../../misc/lis3lv02d/lis3lv02d.h"
#define DRIVER_NAME "hp_accel"
@@ -73,6 +75,13 @@ static inline void delayed_sysfs_set(struct led_classdev *led_cdev,
/* HP-specific accelerometer driver ------------------------------------ */
+/* e0 25, e0 26, e0 27, e0 28 are scan codes that the accelerometer with acpi id
+ * HPQ6000 sends through the keyboard bus */
+#define ACCEL_1 0x25
+#define ACCEL_2 0x26
+#define ACCEL_3 0x27
+#define ACCEL_4 0x28
+
/* For automatic insertion of the module */
static const struct acpi_device_id lis3lv02d_device_ids[] = {
{"HPQ0004", 0}, /* HP Mobile Data Protection System PNP */
@@ -294,6 +303,35 @@ static void lis3lv02d_enum_resources(struct acpi_device *device)
printk(KERN_DEBUG DRIVER_NAME ": Error getting resources\n");
}
+static bool hp_accel_i8042_filter(unsigned char data, unsigned char str,
+ struct serio *port)
+{
+ static bool extended;
+
+ if (str & I8042_STR_AUXDATA)
+ return false;
+
+ if (data == 0xe0) {
+ extended = true;
+ return true;
+ } else if (unlikely(extended)) {
+ extended = false;
+
+ switch (data) {
+ case ACCEL_1:
+ case ACCEL_2:
+ case ACCEL_3:
+ case ACCEL_4:
+ return true;
+ default:
+ serio_interrupt(port, 0xe0, 0);
+ return false;
+ }
+ }
+
+ return false;
+}
+
static int lis3lv02d_add(struct acpi_device *device)
{
int ret;
@@ -326,6 +364,11 @@ static int lis3lv02d_add(struct acpi_device *device)
if (ret)
return ret;
+ /* filter to remove HPQ6000 accelerometer data
+ * from keyboard bus stream */
+ if (strstr(dev_name(&device->dev), "HPQ6000"))
+ i8042_install_filter(hp_accel_i8042_filter);
+
INIT_WORK(&hpled_led.work, delayed_set_status_worker);
ret = led_classdev_register(NULL, &hpled_led.led_classdev);
if (ret) {
@@ -343,6 +386,7 @@ static int lis3lv02d_remove(struct acpi_device *device)
if (!device)
return -EINVAL;
+ i8042_remove_filter(hp_accel_i8042_filter);
lis3lv02d_joystick_disable(&lis3_dev);
lis3lv02d_poweroff(&lis3_dev);