From 0372662cb660bd572b4d833f5c55b3551a918f5d Mon Sep 17 00:00:00 2001 From: fat-tire Date: Fri, 15 Jan 2016 01:10:51 -0500 Subject: [PATCH 01/12] Fix MSM_AVTIMER breakage Change-Id: If9d99aa38f988a11be178f1586ab049dbcc8f42b --- drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c index 624337fd8db6..568290e777ca 100755 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c @@ -13,7 +13,9 @@ #include #include #include - +#ifdef CONFIG_MSM_AVTIMER +#include +#endif #include "msm.h" #include "msm_isp_util.h" #include "msm_isp_axi_util.h" From a205fa148e9f88cd677147f3fcbab178bb72277d Mon Sep 17 00:00:00 2001 From: fat-tire Date: Fri, 15 Jan 2016 01:11:41 -0500 Subject: [PATCH 02/12] Enable CPUSETS/MSM_AVTIMER Change-Id: I589d556af3437e82a95959e7d287c85dd6ffbde8 --- arch/arm/configs/apq8084_sec_defconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/configs/apq8084_sec_defconfig b/arch/arm/configs/apq8084_sec_defconfig index a06ec666a9cc..79d312c0f01c 100755 --- a/arch/arm/configs/apq8084_sec_defconfig +++ b/arch/arm/configs/apq8084_sec_defconfig @@ -52,6 +52,8 @@ CONFIG_RCU_FAST_NO_HZ=y # CONFIG_IKCONFIG_PROC is not set CONFIG_CGROUPS=y CONFIG_CGROUP_FREEZER=y +CONFIG_CPUSETS=y +CONFIG_MSM_AVTIMER=y CONFIG_CGROUP_CPUACCT=y CONFIG_RESOURCE_COUNTERS=y CONFIG_CGROUP_SCHED=y From 51f6d5ccbb1adb6c25c47d38a45f831719fb21c0 Mon Sep 17 00:00:00 2001 From: Riley Andrews Date: Fri, 5 Jun 2015 18:59:29 -0700 Subject: [PATCH 03/12] cpuset: Add allow_attach hook for cpusets on android. Change-Id: Ic1b61b2bbb7ce74c9e9422b5e22ee9078251de21 --- kernel/cpuset.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/kernel/cpuset.c b/kernel/cpuset.c index d9dd521ddd6b..ea257be7c2cb 100755 --- a/kernel/cpuset.c +++ b/kernel/cpuset.c @@ -1409,6 +1409,23 @@ static int cpuset_can_attach(struct cgroup *cgrp, struct cgroup_taskset *tset) return ret; } +static int cpuset_allow_attach(struct cgroup *cgrp, + struct cgroup_taskset *tset) +{ + const struct cred *cred = current_cred(), *tcred; + struct task_struct *task; + + cgroup_taskset_for_each(task, cgrp, tset) { + tcred = __task_cred(task); + + if ((current != task) && !capable(CAP_SYS_ADMIN) && + cred->euid != tcred->uid && cred->euid != tcred->suid) + return -EACCES; + } + + return 0; +} + static void cpuset_cancel_attach(struct cgroup *cgrp, struct cgroup_taskset *tset) { @@ -1963,6 +1980,7 @@ struct cgroup_subsys cpuset_subsys = { .css_offline = cpuset_css_offline, .css_free = cpuset_css_free, .can_attach = cpuset_can_attach, + .allow_attach = cpuset_allow_attach, .cancel_attach = cpuset_cancel_attach, .attach = cpuset_attach, .subsys_id = cpuset_subsys_id, From e52da7b67349f7777bd9c224a2b035290546ff21 Mon Sep 17 00:00:00 2001 From: Riley Andrews Date: Fri, 12 Jun 2015 14:36:28 -0700 Subject: [PATCH 04/12] cpuset: Make cpusets restore on hotplug This deliberately changes the behavior of the per-cpuset cpus file to not be effected by hotplug. When a cpu is offlined, it will be removed from the cpuset/cpus file. When a cpu is onlined, if the cpuset originally requested that that cpu was part of the cpuset, that cpu will be restored to the cpuset. The cpus files still have to be hierachical, but the ranges no longer have to be out of the currently online cpus, just the physically present cpus. Change-Id: I3efbae24a1f6384be1e603fb56f0d3baef61d924 --- kernel/cpuset.c | 48 +++++++++++++++++++++++++++++++++--------------- 1 file changed, 33 insertions(+), 15 deletions(-) diff --git a/kernel/cpuset.c b/kernel/cpuset.c index ea257be7c2cb..37efcd1d88f0 100755 --- a/kernel/cpuset.c +++ b/kernel/cpuset.c @@ -85,6 +85,7 @@ struct cpuset { unsigned long flags; /* "unsigned long" so bitops work */ cpumask_var_t cpus_allowed; /* CPUs allowed to tasks in cpuset */ + cpumask_var_t cpus_requested; /* CPUS requested, but not used because of hotplug */ nodemask_t mems_allowed; /* Memory Nodes allowed to tasks */ struct fmeter fmeter; /* memory_pressure filter */ @@ -381,7 +382,7 @@ static void cpuset_update_task_spread_flag(struct cpuset *cs, static int is_cpuset_subset(const struct cpuset *p, const struct cpuset *q) { - return cpumask_subset(p->cpus_allowed, q->cpus_allowed) && + return cpumask_subset(p->cpus_requested, q->cpus_requested) && nodes_subset(p->mems_allowed, q->mems_allowed) && is_cpu_exclusive(p) <= is_cpu_exclusive(q) && is_mem_exclusive(p) <= is_mem_exclusive(q); @@ -472,7 +473,7 @@ static int validate_change(const struct cpuset *cur, const struct cpuset *trial) cpuset_for_each_child(c, cont, par) { if ((is_cpu_exclusive(trial) || is_cpu_exclusive(c)) && c != cur && - cpumask_intersects(trial->cpus_allowed, c->cpus_allowed)) + cpumask_intersects(trial->cpus_requested, c->cpus_requested)) goto out; if ((is_mem_exclusive(trial) || is_mem_exclusive(c)) && c != cur && @@ -881,19 +882,21 @@ static int update_cpumask(struct cpuset *cs, struct cpuset *trialcs, if (!*buf) { cpumask_clear(trialcs->cpus_allowed); } else { - retval = cpulist_parse(buf, trialcs->cpus_allowed); + retval = cpulist_parse(buf, trialcs->cpus_requested); if (retval < 0) return retval; - if (!cpumask_subset(trialcs->cpus_allowed, cpu_active_mask)) + if (!cpumask_subset(trialcs->cpus_requested, cpu_present_mask)) return -EINVAL; + + cpumask_and(trialcs->cpus_allowed, trialcs->cpus_requested, cpu_active_mask); } retval = validate_change(cs, trialcs); if (retval < 0) return retval; /* Nothing to do if the cpus didn't change */ - if (cpumask_equal(cs->cpus_allowed, trialcs->cpus_allowed)) + if (cpumask_equal(cs->cpus_requested, trialcs->cpus_requested)) return 0; retval = heap_init(&heap, PAGE_SIZE, GFP_KERNEL, NULL); @@ -904,6 +907,7 @@ static int update_cpumask(struct cpuset *cs, struct cpuset *trialcs, mutex_lock(&callback_mutex); cpumask_copy(cs->cpus_allowed, trialcs->cpus_allowed); + cpumask_copy(cs->cpus_requested, trialcs->cpus_requested); mutex_unlock(&callback_mutex); /* @@ -1664,7 +1668,7 @@ static size_t cpuset_sprintf_cpulist(char *page, struct cpuset *cs) size_t count; mutex_lock(&callback_mutex); - count = cpulist_scnprintf(page, PAGE_SIZE, cs->cpus_allowed); + count = cpulist_scnprintf(page, PAGE_SIZE, cs->cpus_requested); mutex_unlock(&callback_mutex); return count; @@ -1875,19 +1879,26 @@ static struct cgroup_subsys_state *cpuset_css_alloc(struct cgroup *cont) cs = kzalloc(sizeof(*cs), GFP_KERNEL); if (!cs) return ERR_PTR(-ENOMEM); - if (!alloc_cpumask_var(&cs->cpus_allowed, GFP_KERNEL)) { - kfree(cs); - return ERR_PTR(-ENOMEM); - } + if (!alloc_cpumask_var(&cs->cpus_allowed, GFP_KERNEL)) + goto error_allowed; + if (!alloc_cpumask_var(&cs->cpus_requested, GFP_KERNEL)) + goto error_requested; set_bit(CS_SCHED_LOAD_BALANCE, &cs->flags); cpumask_clear(cs->cpus_allowed); + cpumask_clear(cs->cpus_requested); nodes_clear(cs->mems_allowed); fmeter_init(&cs->fmeter); INIT_WORK(&cs->hotplug_work, cpuset_propagate_hotplug_workfn); cs->relax_domain_level = -1; return &cs->css; + +error_requested: + free_cpumask_var(cs->cpus_allowed); +error_allowed: + kfree(cs); + return ERR_PTR(-ENOMEM); } static int cpuset_css_online(struct cgroup *cgrp) @@ -1938,6 +1949,7 @@ static int cpuset_css_online(struct cgroup *cgrp) mutex_lock(&callback_mutex); cs->mems_allowed = parent->mems_allowed; cpumask_copy(cs->cpus_allowed, parent->cpus_allowed); + cpumask_copy(cs->cpus_requested, parent->cpus_requested); mutex_unlock(&callback_mutex); out_unlock: mutex_unlock(&cpuset_mutex); @@ -1970,6 +1982,7 @@ static void cpuset_css_free(struct cgroup *cont) struct cpuset *cs = cgroup_cs(cont); free_cpumask_var(cs->cpus_allowed); + free_cpumask_var(cs->cpus_requested); kfree(cs); } @@ -2000,8 +2013,11 @@ int __init cpuset_init(void) if (!alloc_cpumask_var(&top_cpuset.cpus_allowed, GFP_KERNEL)) BUG(); + if (!alloc_cpumask_var(&top_cpuset.cpus_requested, GFP_KERNEL)) + BUG(); cpumask_setall(top_cpuset.cpus_allowed); + cpumask_setall(top_cpuset.cpus_requested); nodes_setall(top_cpuset.mems_allowed); fmeter_init(&top_cpuset.fmeter); @@ -2057,20 +2073,22 @@ static void remove_tasks_in_empty_cpuset(struct cpuset *cs) */ static void cpuset_propagate_hotplug_workfn(struct work_struct *work) { - static cpumask_t off_cpus; + static cpumask_t diff, new_allowed; static nodemask_t off_mems, tmp_mems; struct cpuset *cs = container_of(work, struct cpuset, hotplug_work); bool is_empty; mutex_lock(&cpuset_mutex); - cpumask_andnot(&off_cpus, cs->cpus_allowed, top_cpuset.cpus_allowed); + cpumask_and(&new_allowed, cs->cpus_requested, top_cpuset.cpus_allowed); + cpumask_xor(&diff, &new_allowed, cs->cpus_allowed); + nodes_andnot(off_mems, cs->mems_allowed, top_cpuset.mems_allowed); /* remove offline cpus from @cs */ - if (!cpumask_empty(&off_cpus)) { + if (!cpumask_empty(&diff)) { mutex_lock(&callback_mutex); - cpumask_andnot(cs->cpus_allowed, cs->cpus_allowed, &off_cpus); + cpumask_copy(cs->cpus_allowed, &new_allowed); mutex_unlock(&callback_mutex); update_tasks_cpumask(cs, NULL); } @@ -2181,7 +2199,7 @@ static void cpuset_hotplug_workfn(struct work_struct *work) } /* if cpus or mems went down, we need to propagate to descendants */ - if (cpus_offlined || mems_offlined) { + if (cpus_updated || mems_updated) { struct cpuset *cs; struct cgroup *pos_cgrp; From 8bc12a0523a7130b9b121d5ddddbac207aeba976 Mon Sep 17 00:00:00 2001 From: fat-tire Date: Fri, 15 Jan 2016 15:34:20 -0500 Subject: [PATCH 05/12] Remove unneeded obj files Thanks to Pafcholini for catching this. Change-Id: Iccdd69e9e38b2f73a5ea42e16c5062914f046871 --- drivers/misc/Makefile | 7 ------- 1 file changed, 7 deletions(-) diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index 5772137183a9..edea98b598b0 100755 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -76,11 +76,4 @@ obj-$(CONFIG_DM_VERITY) += dmverity_query.o obj-$(CONFIG_SEC_MODEM) += modem_if/ obj-y += dualwave/ -obj-$(CONFIG_HAPTIC_DRV2605) += drv2605.o -obj-$(CONFIG_C55_CTRL) += c55_ctrl.o -obj-$(CONFIG_SENSORS_STM401) += stm401/ -obj-$(CONFIG_ALSA_TO_H2W) += alsa-to-h2w-headset.o -obj-$(CONFIG_MMI_FACTORY) += mmi-factory.o -obj-$(CONFIG_MMI_SAR) += mmi-sar.o -obj-$(CONFIG_CYPRESS_CAPSENSE_PROGRAMMING) += capsense_prog/ obj-$(CONFIG_UID_CPUTIME) += uid_cputime.o From cebf8ce94879b44d697f59964aae058a83a1b028 Mon Sep 17 00:00:00 2001 From: Yevgeny Pats Date: Mon, 11 Jan 2016 12:05:28 +0000 Subject: [PATCH 06/12] KEYS: Fix keyring ref leak in join_session_keyring() If a thread is asked to join as a session keyring the keyring that's already set as its session, we leak a keyring reference. This can be tested with the following program: #include #include #include #include int main(int argc, const char *argv[]) { int i = 0; key_serial_t serial; serial = keyctl(KEYCTL_JOIN_SESSION_KEYRING, "leaked-keyring"); if (serial < 0) { perror("keyctl"); return -1; } if (keyctl(KEYCTL_SETPERM, serial, KEY_POS_ALL | KEY_USR_ALL) < 0) { perror("keyctl"); return -1; } for (i = 0; i < 100; i++) { serial = keyctl(KEYCTL_JOIN_SESSION_KEYRING, "leaked-keyring"); if (serial < 0) { perror("keyctl"); return -1; } } return 0; } If, after the program has run, there something like the following line in /proc/keys: 3f3d898f I--Q--- 100 perm 3f3f0000 0 0 keyring leaked-keyring: empty with a usage count of 100 * the number of times the program has been run, then the kernel is malfunctioning. If leaked-keyring has zero usages or has been garbage collected, then the problem is fixed. Reported-by: Yevgeny Pats Signed-off-by: David Howells --- security/keys/process_keys.c | 1 + 1 file changed, 1 insertion(+) diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c index 42defae1e161..cd871dc8b7c0 100755 --- a/security/keys/process_keys.c +++ b/security/keys/process_keys.c @@ -792,6 +792,7 @@ long join_session_keyring(const char *name) ret = PTR_ERR(keyring); goto error2; } else if (keyring == new->session_keyring) { + key_put(keyring); ret = 0; goto error2; } From 42768c1ed2de61598d4d5f0972360544dbccac70 Mon Sep 17 00:00:00 2001 From: fat-tire Date: Wed, 20 Jan 2016 14:42:36 -0500 Subject: [PATCH 07/12] update wacom drivers from Linux 3.14.58 Change-Id: If8c09b76ab07f371418eab524a5cf5631dea53a2 --- drivers/input/tablet/acecad.c | 1 - drivers/input/tablet/aiptek.c | 1 - drivers/input/tablet/gtco.c | 1 - drivers/input/tablet/hanwang.c | 1 - drivers/input/tablet/kbtab.c | 1 - drivers/input/tablet/wacom.h | 1 - drivers/input/tablet/wacom_sys.c | 199 +++++++++------ drivers/input/tablet/wacom_wac.c | 320 ++++++++++++++++++++---- drivers/input/tablet/wacom_wac.h | 21 +- drivers/input/touchscreen/wacom_i2c.c | 14 +- drivers/input/touchscreen/wacom_w8001.c | 1 - 11 files changed, 416 insertions(+), 145 deletions(-) diff --git a/drivers/input/tablet/acecad.c b/drivers/input/tablet/acecad.c index e062ec899ca1..889f6b77e8cb 100755 --- a/drivers/input/tablet/acecad.c +++ b/drivers/input/tablet/acecad.c @@ -28,7 +28,6 @@ #include #include #include -#include #include /* diff --git a/drivers/input/tablet/aiptek.c b/drivers/input/tablet/aiptek.c index ee83c3904ee8..e7f966da6efa 100755 --- a/drivers/input/tablet/aiptek.c +++ b/drivers/input/tablet/aiptek.c @@ -74,7 +74,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/input/tablet/gtco.c b/drivers/input/tablet/gtco.c index 29e01ab6859f..caecffe8caff 100755 --- a/drivers/input/tablet/gtco.c +++ b/drivers/input/tablet/gtco.c @@ -53,7 +53,6 @@ Scott Hill shill@gtcocalcomp.com #include #include #include -#include #include #include #include diff --git a/drivers/input/tablet/hanwang.c b/drivers/input/tablet/hanwang.c index 5cc04124995c..cd852059b99e 100755 --- a/drivers/input/tablet/hanwang.c +++ b/drivers/input/tablet/hanwang.c @@ -26,7 +26,6 @@ #include #include #include -#include #include #define DRIVER_AUTHOR "Xing Wei " diff --git a/drivers/input/tablet/kbtab.c b/drivers/input/tablet/kbtab.c index 3fba74b9b602..d2ac7c2b5b82 100755 --- a/drivers/input/tablet/kbtab.c +++ b/drivers/input/tablet/kbtab.c @@ -1,7 +1,6 @@ #include #include #include -#include #include #include diff --git a/drivers/input/tablet/wacom.h b/drivers/input/tablet/wacom.h index b79d45198d82..9ebf0ed3b3b3 100755 --- a/drivers/input/tablet/wacom.h +++ b/drivers/input/tablet/wacom.h @@ -86,7 +86,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c index 3d838c0b495d..b16ebef5b911 100755 --- a/drivers/input/tablet/wacom_sys.c +++ b/drivers/input/tablet/wacom_sys.c @@ -221,39 +221,6 @@ static int wacom_calc_hid_res(int logical_extents, int physical_extents, return logical_extents / physical_extents; } -/* - * The physical dimension specified by the HID descriptor is likely not in - * the "100th of a mm" units expected by wacom_calculate_touch_res. This - * function adjusts the value of [xy]_phy based on the unit and exponent - * provided by the HID descriptor. If an error occurs durring conversion - * (e.g. from the unit being left unspecified) [xy]_phy is not modified. - */ -static void wacom_fix_phy_from_hid(struct wacom_features *features) -{ - int xres = wacom_calc_hid_res(features->x_max, features->x_phy, - features->unit, features->unitExpo); - int yres = wacom_calc_hid_res(features->y_max, features->y_phy, - features->unit, features->unitExpo); - - if (xres > 0 && yres > 0) { - features->x_phy = (100 * features->x_max) / xres; - features->y_phy = (100 * features->y_max) / yres; - } -} - -/* - * Static values for max X/Y and resolution of Pen interface is stored in - * features. This mean physical size of active area can be computed. - * This is useful to do when Pen and Touch have same active area of tablet. - * This means for Touch device, we only need to find max X/Y value and we - * have enough information to compute resolution of touch. - */ -static void wacom_set_phy_from_res(struct wacom_features *features) -{ - features->x_phy = (features->x_max * 100) / features->x_resolution; - features->y_phy = (features->y_max * 100) / features->y_resolution; -} - static int wacom_parse_logical_collection(unsigned char *report, struct wacom_features *features) { @@ -265,8 +232,6 @@ static int wacom_parse_logical_collection(unsigned char *report, features->pktlen = WACOM_PKGLEN_BBTOUCH3; features->device_type = BTN_TOOL_FINGER; - wacom_set_phy_from_res(features); - features->x_max = features->y_max = get_unaligned_le16(&report[10]); @@ -562,9 +527,6 @@ static int wacom_set_device_mode(struct usb_interface *intf, int report_id, int error = wacom_set_report(intf, WAC_HID_FEATURE_REPORT, report_id, rep_data, length, 1); - if (error >= 0) - error = wacom_get_report(intf, WAC_HID_FEATURE_REPORT, - report_id, rep_data, length, 1); } while ((error < 0 || rep_data[1] != mode) && limit++ < WAC_MSG_RETRIES); kfree(rep_data); @@ -586,7 +548,7 @@ static int wacom_query_tablet_data(struct usb_interface *intf, struct wacom_feat /* MT Tablet PC touch */ return wacom_set_device_mode(intf, 3, 4, 4); } - else if (features->type == WACOM_24HDT) { + else if (features->type == WACOM_24HDT || features->type == CINTIQ_HYBRID) { return wacom_set_device_mode(intf, 18, 3, 2); } } else if (features->device_type == BTN_TOOL_PEN) { @@ -643,9 +605,6 @@ static int wacom_retrieve_hid_descriptor(struct usb_interface *intf, } } error = wacom_parse_hid(intf, hid_desc, features); - if (error) - goto out; - wacom_fix_phy_from_hid(features); out: return error; @@ -760,7 +719,7 @@ static int wacom_led_control(struct wacom *wacom) return -ENOMEM; if (wacom->wacom_wac.features.type >= INTUOS5S && - wacom->wacom_wac.features.type <= INTUOS5L) { + wacom->wacom_wac.features.type <= INTUOSPL) { /* * Touch Ring and crop mark LED luminance may take on * one of four values: @@ -1022,14 +981,20 @@ static int wacom_initialize_leds(struct wacom *wacom) case INTUOS5S: case INTUOS5: case INTUOS5L: - wacom->led.select[0] = 0; - wacom->led.select[1] = 0; - wacom->led.llv = 32; - wacom->led.hlv = 0; - wacom->led.img_lum = 0; - - error = sysfs_create_group(&wacom->intf->dev.kobj, - &intuos5_led_attr_group); + case INTUOSPS: + case INTUOSPM: + case INTUOSPL: + if (wacom->wacom_wac.features.device_type == BTN_TOOL_PEN) { + wacom->led.select[0] = 0; + wacom->led.select[1] = 0; + wacom->led.llv = 32; + wacom->led.hlv = 0; + wacom->led.img_lum = 0; + + error = sysfs_create_group(&wacom->intf->dev.kobj, + &intuos5_led_attr_group); + } else + return 0; break; default: @@ -1065,13 +1030,18 @@ static void wacom_destroy_leds(struct wacom *wacom) case INTUOS5S: case INTUOS5: case INTUOS5L: - sysfs_remove_group(&wacom->intf->dev.kobj, - &intuos5_led_attr_group); + case INTUOSPS: + case INTUOSPM: + case INTUOSPL: + if (wacom->wacom_wac.features.device_type == BTN_TOOL_PEN) + sysfs_remove_group(&wacom->intf->dev.kobj, + &intuos5_led_attr_group); break; } } static enum power_supply_property wacom_battery_props[] = { + POWER_SUPPLY_PROP_SCOPE, POWER_SUPPLY_PROP_CAPACITY }; @@ -1083,6 +1053,9 @@ static int wacom_battery_get_property(struct power_supply *psy, int ret = 0; switch (psp) { + case POWER_SUPPLY_PROP_SCOPE: + val->intval = POWER_SUPPLY_SCOPE_DEVICE; + break; case POWER_SUPPLY_PROP_CAPACITY: val->intval = wacom->wacom_wac.battery_capacity * 100 / 31; @@ -1222,38 +1195,84 @@ static void wacom_wireless_work(struct work_struct *work) wacom_wac1->features = *((struct wacom_features *)id->driver_info); wacom_wac1->features.device_type = BTN_TOOL_PEN; + snprintf(wacom_wac1->name, WACOM_NAME_MAX, "%s (WL) Pen", + wacom_wac1->features.name); + wacom_wac1->shared->touch_max = wacom_wac1->features.touch_max; + wacom_wac1->shared->type = wacom_wac1->features.type; error = wacom_register_input(wacom1); if (error) - goto fail1; + goto fail; /* Touch interface */ - wacom_wac2->features = - *((struct wacom_features *)id->driver_info); - wacom_wac2->features.pktlen = WACOM_PKGLEN_BBTOUCH3; - wacom_wac2->features.device_type = BTN_TOOL_FINGER; - wacom_set_phy_from_res(&wacom_wac2->features); - wacom_wac2->features.x_max = wacom_wac2->features.y_max = 4096; - error = wacom_register_input(wacom2); - if (error) - goto fail2; + if (wacom_wac1->features.touch_max || + wacom_wac1->features.type == INTUOSHT) { + wacom_wac2->features = + *((struct wacom_features *)id->driver_info); + wacom_wac2->features.pktlen = WACOM_PKGLEN_BBTOUCH3; + wacom_wac2->features.device_type = BTN_TOOL_FINGER; + wacom_wac2->features.x_max = wacom_wac2->features.y_max = 4096; + if (wacom_wac2->features.touch_max) + snprintf(wacom_wac2->name, WACOM_NAME_MAX, + "%s (WL) Finger",wacom_wac2->features.name); + else + snprintf(wacom_wac2->name, WACOM_NAME_MAX, + "%s (WL) Pad",wacom_wac2->features.name); + error = wacom_register_input(wacom2); + if (error) + goto fail; + + if (wacom_wac1->features.type == INTUOSHT && + wacom_wac1->features.touch_max) + wacom_wac->shared->touch_input = wacom_wac2->input; + } error = wacom_initialize_battery(wacom); if (error) - goto fail3; + goto fail; } return; -fail3: - input_unregister_device(wacom_wac2->input); - wacom_wac2->input = NULL; -fail2: - input_unregister_device(wacom_wac1->input); - wacom_wac1->input = NULL; -fail1: +fail: + if (wacom_wac2->input) { + input_unregister_device(wacom_wac2->input); + wacom_wac2->input = NULL; + } + + if (wacom_wac1->input) { + input_unregister_device(wacom_wac1->input); + wacom_wac1->input = NULL; + } return; } +/* + * Not all devices report physical dimensions from HID. + * Compute the default from hardcoded logical dimension + * and resolution before driver overwrites them. + */ +static void wacom_set_default_phy(struct wacom_features *features) +{ + if (features->x_resolution) { + features->x_phy = (features->x_max * 100) / + features->x_resolution; + features->y_phy = (features->y_max * 100) / + features->y_resolution; + } +} + +static void wacom_calculate_res(struct wacom_features *features) +{ + features->x_resolution = wacom_calc_hid_res(features->x_max, + features->x_phy, + features->unit, + features->unitExpo); + features->y_resolution = wacom_calc_hid_res(features->y_max, + features->y_phy, + features->unit, + features->unitExpo); +} + static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *id) { struct usb_device *dev = interface_to_usbdev(intf); @@ -1300,6 +1319,9 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i endpoint = &intf->cur_altsetting->endpoint[0].desc; + /* set the default size in case we do not get them from hid */ + wacom_set_default_phy(features); + /* Retrieve the physical and logical size for touch devices */ error = wacom_retrieve_hid_descriptor(intf, features); if (error) @@ -1310,13 +1332,11 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i * HID descriptor. If this is the touch interface (wMaxPacketSize * of WACOM_PKGLEN_BBTOUCH3), override the table values. */ - if (features->type >= INTUOS5S && features->type <= INTUOS5L) { + if (features->type >= INTUOS5S && features->type <= INTUOSHT) { if (endpoint->wMaxPacketSize == WACOM_PKGLEN_BBTOUCH3) { features->device_type = BTN_TOOL_FINGER; features->pktlen = WACOM_PKGLEN_BBTOUCH3; - wacom_set_phy_from_res(features); - features->x_max = 4096; features->y_max = 4096; } else { @@ -1326,17 +1346,25 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i wacom_setup_device_quirks(features); + /* set unit to "100th of a mm" for devices not reported by HID */ + if (!features->unit) { + features->unit = 0x11; + features->unitExpo = 16 - 3; + } + wacom_calculate_res(features); + strlcpy(wacom_wac->name, features->name, sizeof(wacom_wac->name)); if (features->quirks & WACOM_QUIRK_MULTI_INPUT) { struct usb_device *other_dev; /* Append the device type to the name */ - strlcat(wacom_wac->name, - features->device_type == BTN_TOOL_PEN ? - " Pen" : " Finger", - sizeof(wacom_wac->name)); - + if (features->device_type != BTN_TOOL_FINGER) + strlcat(wacom_wac->name, " Pen", WACOM_NAME_MAX); + else if (features->touch_max) + strlcat(wacom_wac->name, " Finger", WACOM_NAME_MAX); + else + strlcat(wacom_wac->name, " Pad", WACOM_NAME_MAX); other_dev = wacom_get_sibling(dev, features->oVid, features->oPid); if (other_dev == NULL || wacom_get_usbdev_data(other_dev) == NULL) @@ -1369,8 +1397,15 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i usb_set_intfdata(intf, wacom); if (features->quirks & WACOM_QUIRK_MONITOR) { - if (usb_submit_urb(wacom->irq, GFP_KERNEL)) + if (usb_submit_urb(wacom->irq, GFP_KERNEL)) { + error = -EIO; goto fail5; + } + } + + if (wacom_wac->features.type == INTUOSHT && wacom_wac->features.touch_max) { + if (wacom_wac->features.device_type == BTN_TOOL_FINGER) + wacom_wac->shared->touch_input = wacom_wac->input; } return 0; @@ -1425,8 +1460,8 @@ static int wacom_resume(struct usb_interface *intf) wacom_query_tablet_data(intf, features); wacom_led_control(wacom); - if ((wacom->open || features->quirks & WACOM_QUIRK_MONITOR) - && usb_submit_urb(wacom->irq, GFP_NOIO) < 0) + if ((wacom->open || (features->quirks & WACOM_QUIRK_MONITOR)) && + usb_submit_urb(wacom->irq, GFP_NOIO) < 0) rv = -EIO; mutex_unlock(&wacom->lock); diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c index 384fbcd0cee0..d4b0a31ab66b 100755 --- a/drivers/input/tablet/wacom_wac.c +++ b/drivers/input/tablet/wacom_wac.c @@ -210,6 +210,62 @@ static int wacom_dtu_irq(struct wacom_wac *wacom) return 1; } +static int wacom_dtus_irq(struct wacom_wac *wacom) +{ + char *data = wacom->data; + struct input_dev *input = wacom->input; + unsigned short prox, pressure = 0; + + if (data[0] != WACOM_REPORT_DTUS && data[0] != WACOM_REPORT_DTUSPAD) { + dev_dbg(input->dev.parent, + "%s: received unknown report #%d", __func__, data[0]); + return 0; + } else if (data[0] == WACOM_REPORT_DTUSPAD) { + input_report_key(input, BTN_0, (data[1] & 0x01)); + input_report_key(input, BTN_1, (data[1] & 0x02)); + input_report_key(input, BTN_2, (data[1] & 0x04)); + input_report_key(input, BTN_3, (data[1] & 0x08)); + input_report_abs(input, ABS_MISC, + data[1] & 0x0f ? PAD_DEVICE_ID : 0); + /* + * Serial number is required when expresskeys are + * reported through pen interface. + */ + input_event(input, EV_MSC, MSC_SERIAL, 0xf0); + return 1; + } else { + prox = data[1] & 0x80; + if (prox) { + switch ((data[1] >> 3) & 3) { + case 1: /* Rubber */ + wacom->tool[0] = BTN_TOOL_RUBBER; + wacom->id[0] = ERASER_DEVICE_ID; + break; + + case 2: /* Pen */ + wacom->tool[0] = BTN_TOOL_PEN; + wacom->id[0] = STYLUS_DEVICE_ID; + break; + } + } + + input_report_key(input, BTN_STYLUS, data[1] & 0x20); + input_report_key(input, BTN_STYLUS2, data[1] & 0x40); + input_report_abs(input, ABS_X, get_unaligned_be16(&data[3])); + input_report_abs(input, ABS_Y, get_unaligned_be16(&data[5])); + pressure = ((data[1] & 0x03) << 8) | (data[2] & 0xff); + input_report_abs(input, ABS_PRESSURE, pressure); + input_report_key(input, BTN_TOUCH, pressure > 10); + + if (!prox) /* out-prox */ + wacom->id[0] = 0; + input_report_key(input, wacom->tool[0], prox); + input_report_abs(input, ABS_MISC, wacom->id[0]); + input_event(input, EV_MSC, MSC_SERIAL, 1); + return 1; + } +} + static int wacom_graphire_irq(struct wacom_wac *wacom) { struct wacom_features *features = &wacom->features; @@ -331,7 +387,7 @@ static int wacom_intuos_inout(struct wacom_wac *wacom) /* Enter report */ if ((data[1] & 0xfc) == 0xc0) { - if (features->quirks == WACOM_QUIRK_MULTI_INPUT) + if (features->quirks & WACOM_QUIRK_MULTI_INPUT) wacom->shared->stylus_in_proximity = true; /* serial number of the tool */ @@ -427,9 +483,16 @@ static int wacom_intuos_inout(struct wacom_wac *wacom) (features->type == WACOM_21UX2)) return 1; + /* Range Report */ + if ((data[1] & 0xfe) == 0x20) { + input_report_key(input, BTN_TOUCH, 0); + input_report_abs(input, ABS_PRESSURE, 0); + input_report_abs(input, ABS_DISTANCE, wacom->features.distance_max); + } + /* Exit report */ if ((data[1] & 0xfe) == 0x80) { - if (features->quirks == WACOM_QUIRK_MULTI_INPUT) + if (features->quirks & WACOM_QUIRK_MULTI_INPUT) wacom->shared->stylus_in_proximity = false; /* @@ -477,7 +540,7 @@ static void wacom_intuos_general(struct wacom_wac *wacom) /* general pen packet */ if ((data[1] & 0xb8) == 0xa0) { t = (data[6] << 2) | ((data[7] >> 6) & 3); - if (features->type >= INTUOS4S && features->type <= WACOM_24HD) { + if (features->type >= INTUOS4S && features->type <= CINTIQ_HYBRID) { t = (t << 1) | (data[1] & 1); } input_report_abs(input, ABS_PRESSURE, t); @@ -621,14 +684,36 @@ static int wacom_intuos_irq(struct wacom_wac *wacom) } else { input_report_abs(input, ABS_MISC, 0); } - } else if (features->type >= INTUOS5S && features->type <= INTUOS5L) { + } else if (features->type == CINTIQ_HYBRID) { + /* + * Do not send hardware buttons under Android. They + * are already sent to the system through GPIO (and + * have different meaning). + */ + input_report_key(input, BTN_1, (data[4] & 0x01)); + input_report_key(input, BTN_2, (data[4] & 0x02)); + input_report_key(input, BTN_3, (data[4] & 0x04)); + input_report_key(input, BTN_4, (data[4] & 0x08)); + + input_report_key(input, BTN_5, (data[4] & 0x10)); /* Right */ + input_report_key(input, BTN_6, (data[4] & 0x20)); /* Up */ + input_report_key(input, BTN_7, (data[4] & 0x40)); /* Left */ + input_report_key(input, BTN_8, (data[4] & 0x80)); /* Down */ + input_report_key(input, BTN_0, (data[3] & 0x01)); /* Center */ + + if (data[4] | (data[3] & 0x01)) { + input_report_abs(input, ABS_MISC, PAD_DEVICE_ID); + } else { + input_report_abs(input, ABS_MISC, 0); + } + } else if (features->type >= INTUOS5S && features->type <= INTUOSPL) { int i; /* Touch ring mode switch has no capacitive sensor */ input_report_key(input, BTN_0, (data[3] & 0x01)); /* - * ExpressKeys on Intuos5 have a capacitive sensor in + * ExpressKeys on Intuos5/Intuos Pro have a capacitive sensor in * addition to the mechanical switch. Switch data is * stored in data[4], capacitive data in data[5]. */ @@ -716,7 +801,9 @@ static int wacom_intuos_irq(struct wacom_wac *wacom) features->type == INTUOS4 || features->type == INTUOS4S || features->type == INTUOS5 || - features->type == INTUOS5S)) { + features->type == INTUOS5S || + features->type == INTUOSPM || + features->type == INTUOSPS)) { return 0; } @@ -769,8 +856,7 @@ static int wacom_intuos_irq(struct wacom_wac *wacom) } else if (wacom->tool[idx] == BTN_TOOL_MOUSE) { /* I4 mouse */ - if ((features->type >= INTUOS4S && features->type <= INTUOS4L) || - (features->type >= INTUOS5S && features->type <= INTUOS5L)) { + if (features->type >= INTUOS4S && features->type <= INTUOSPL) { input_report_key(input, BTN_LEFT, data[6] & 0x01); input_report_key(input, BTN_MIDDLE, data[6] & 0x02); input_report_key(input, BTN_RIGHT, data[6] & 0x04); @@ -797,7 +883,8 @@ static int wacom_intuos_irq(struct wacom_wac *wacom) } } } else if ((features->type < INTUOS3S || features->type == INTUOS3L || - features->type == INTUOS4L || features->type == INTUOS5L) && + features->type == INTUOS4L || features->type == INTUOS5L || + features->type == INTUOSPL) && wacom->tool[idx] == BTN_TOOL_LENS) { /* Lens cursor packets */ input_report_key(input, BTN_LEFT, data[8] & 0x01); @@ -1107,6 +1194,7 @@ static int wacom_bpt_touch(struct wacom_wac *wacom) static void wacom_bpt3_touch_msg(struct wacom_wac *wacom, unsigned char *data) { + struct wacom_features *features = &wacom->features; struct input_dev *input = wacom->input; bool touch = data[1] & 0x80; int slot = input_mt_get_slot_by_key(input, data[0]); @@ -1122,14 +1210,23 @@ static void wacom_bpt3_touch_msg(struct wacom_wac *wacom, unsigned char *data) if (touch) { int x = (data[2] << 4) | (data[4] >> 4); int y = (data[3] << 4) | (data[4] & 0x0f); - int a = data[5]; + int width, height; - // "a" is a scaled-down area which we assume is roughly - // circular and which can be described as: a=(pi*r^2)/C. - int x_res = input_abs_get_res(input, ABS_X); - int y_res = input_abs_get_res(input, ABS_Y); - int width = 2 * int_sqrt(a * WACOM_CONTACT_AREA_SCALE); - int height = width * y_res / x_res; + if (features->type >= INTUOSPS && features->type <= INTUOSPL) { + width = data[5] * 100; + height = data[6] * 100; + } else { + /* + * "a" is a scaled-down area which we assume is + * roughly circular and which can be described as: + * a=(pi*r^2)/C. + */ + int a = data[5]; + int x_res = input_abs_get_res(input, ABS_X); + int y_res = input_abs_get_res(input, ABS_Y); + width = 2 * int_sqrt(a * WACOM_CONTACT_AREA_SCALE); + height = width * y_res / x_res; + } input_report_abs(input, ABS_MT_POSITION_X, x); input_report_abs(input, ABS_MT_POSITION_Y, y); @@ -1141,10 +1238,16 @@ static void wacom_bpt3_touch_msg(struct wacom_wac *wacom, unsigned char *data) static void wacom_bpt3_button_msg(struct wacom_wac *wacom, unsigned char *data) { struct input_dev *input = wacom->input; + struct wacom_features *features = &wacom->features; - input_report_key(input, BTN_LEFT, (data[1] & 0x08) != 0); + if (features->type == INTUOSHT) { + input_report_key(input, BTN_LEFT, (data[1] & 0x02) != 0); + input_report_key(input, BTN_BACK, (data[1] & 0x08) != 0); + } else { + input_report_key(input, BTN_BACK, (data[1] & 0x02) != 0); + input_report_key(input, BTN_LEFT, (data[1] & 0x08) != 0); + } input_report_key(input, BTN_FORWARD, (data[1] & 0x04) != 0); - input_report_key(input, BTN_BACK, (data[1] & 0x02) != 0); input_report_key(input, BTN_RIGHT, (data[1] & 0x01) != 0); } @@ -1178,13 +1281,23 @@ static int wacom_bpt3_touch(struct wacom_wac *wacom) static int wacom_bpt_pen(struct wacom_wac *wacom) { + struct wacom_features *features = &wacom->features; struct input_dev *input = wacom->input; unsigned char *data = wacom->data; int prox = 0, x = 0, y = 0, p = 0, d = 0, pen = 0, btn1 = 0, btn2 = 0; - if (data[0] != 0x02) + if (data[0] != WACOM_REPORT_PENABLED && data[0] != WACOM_REPORT_USB) return 0; + if (data[0] == WACOM_REPORT_USB) { + if (features->type == INTUOSHT && features->touch_max) { + input_report_switch(wacom->shared->touch_input, + SW_MUTE_DEVICE, data[8] & 0x40); + input_sync(wacom->shared->touch_input); + } + return 0; + } + prox = (data[1] & 0x20) == 0x20; /* @@ -1217,8 +1330,8 @@ static int wacom_bpt_pen(struct wacom_wac *wacom) * touching and applying pressure; do not report negative * distance. */ - if (data[8] <= wacom->features.distance_max) - d = wacom->features.distance_max - data[8]; + if (data[8] <= features->distance_max) + d = features->distance_max - data[8]; pen = data[1] & 0x01; btn1 = data[1] & 0x02; @@ -1262,13 +1375,20 @@ static int wacom_wireless_irq(struct wacom_wac *wacom, size_t len) unsigned char *data = wacom->data; int connected; - if (len != WACOM_PKGLEN_WIRELESS || data[0] != 0x80) + if (len != WACOM_PKGLEN_WIRELESS || data[0] != WACOM_REPORT_WL) return 0; connected = data[1] & 0x01; if (connected) { int pid, battery; + if ((wacom->shared->type == INTUOSHT) && + wacom->shared->touch_max) { + input_report_switch(wacom->shared->touch_input, + SW_MUTE_DEVICE, data[5] & 0x40); + input_sync(wacom->shared->touch_input); + } + pid = get_unaligned_be16(&data[6]); battery = data[5] & 0x3f; if (wacom->pid != pid) { @@ -1313,6 +1433,10 @@ void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len) sync = wacom_dtu_irq(wacom_wac); break; + case DTUS: + sync = wacom_dtus_irq(wacom_wac); + break; + case INTUOS: case INTUOS3S: case INTUOS3: @@ -1327,6 +1451,7 @@ void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len) case WACOM_22HD: case WACOM_24HD: case DTK: + case CINTIQ_HYBRID: sync = wacom_intuos_irq(wacom_wac); break; @@ -1337,6 +1462,9 @@ void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len) case INTUOS5S: case INTUOS5: case INTUOS5L: + case INTUOSPS: + case INTUOSPM: + case INTUOSPL: if (len == WACOM_PKGLEN_BBTOUCH3) sync = wacom_bpt3_touch(wacom_wac); else @@ -1352,6 +1480,7 @@ void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len) break; case BAMBOO_PT: + case INTUOSHT: sync = wacom_bpt_irq(wacom_wac, len); break; @@ -1420,7 +1549,7 @@ void wacom_setup_device_quirks(struct wacom_features *features) /* these device have multiple inputs */ if (features->type >= WIRELESS || - (features->type >= INTUOS5S && features->type <= INTUOS5L) || + (features->type >= INTUOS5S && features->type <= INTUOSHT) || (features->oVid && features->oPid)) features->quirks |= WACOM_QUIRK_MULTI_INPUT; @@ -1445,13 +1574,6 @@ void wacom_setup_device_quirks(struct wacom_features *features) } } -static unsigned int wacom_calculate_touch_res(unsigned int logical_max, - unsigned int physical_max) -{ - /* Touch physical dimensions are in 100th of mm */ - return (logical_max * 100) / physical_max; -} - static void wacom_abs_set_axis(struct input_dev *input_dev, struct wacom_wac *wacom_wac) { @@ -1475,11 +1597,9 @@ static void wacom_abs_set_axis(struct input_dev *input_dev, input_set_abs_params(input_dev, ABS_Y, 0, features->y_max, features->y_fuzz, 0); input_abs_set_res(input_dev, ABS_X, - wacom_calculate_touch_res(features->x_max, - features->x_phy)); + features->x_resolution); input_abs_set_res(input_dev, ABS_Y, - wacom_calculate_touch_res(features->y_max, - features->y_phy)); + features->y_resolution); } if (features->touch_max > 1) { @@ -1488,11 +1608,9 @@ static void wacom_abs_set_axis(struct input_dev *input_dev, input_set_abs_params(input_dev, ABS_MT_POSITION_Y, 0, features->y_max, features->y_fuzz, 0); input_abs_set_res(input_dev, ABS_MT_POSITION_X, - wacom_calculate_touch_res(features->x_max, - features->x_phy)); + features->x_resolution); input_abs_set_res(input_dev, ABS_MT_POSITION_Y, - wacom_calculate_touch_res(features->y_max, - features->y_phy)); + features->y_resolution); } } } @@ -1510,7 +1628,7 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev, wacom_abs_set_axis(input_dev, wacom_wac); - switch (wacom_wac->features.type) { + switch (features->type) { case WACOM_MO: input_set_abs_params(input_dev, ABS_WHEEL, 0, 71, 0, 0); /* fall through */ @@ -1638,6 +1756,8 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev, case INTUOS5: case INTUOS5L: + case INTUOSPM: + case INTUOSPL: if (features->device_type == BTN_TOOL_PEN) { __set_bit(BTN_7, input_dev->keybit); __set_bit(BTN_8, input_dev->keybit); @@ -1645,6 +1765,7 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev, /* fall through */ case INTUOS5S: + case INTUOSPS: __set_bit(INPUT_PROP_POINTER, input_dev->propbit); if (features->device_type == BTN_TOOL_PEN) { @@ -1718,8 +1839,14 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev, /* fall through */ + case DTUS: case PL: case DTU: + if (features->type == DTUS) { + input_set_capability(input_dev, EV_MSC, MSC_SERIAL); + for (i = 0; i < 3; i++) + __set_bit(BTN_0 + i, input_dev->keybit); + } __set_bit(BTN_TOOL_PEN, input_dev->keybit); __set_bit(BTN_TOOL_RUBBER, input_dev->keybit); __set_bit(BTN_STYLUS, input_dev->keybit); @@ -1740,33 +1867,50 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev, __set_bit(INPUT_PROP_POINTER, input_dev->propbit); break; + case INTUOSHT: + if (features->touch_max && + features->device_type == BTN_TOOL_FINGER) { + input_dev->evbit[0] |= BIT_MASK(EV_SW); + __set_bit(SW_MUTE_DEVICE, input_dev->swbit); + } + /* fall through */ + case BAMBOO_PT: __clear_bit(ABS_MISC, input_dev->absbit); - __set_bit(INPUT_PROP_POINTER, input_dev->propbit); - if (features->device_type == BTN_TOOL_FINGER) { - unsigned int flags = INPUT_MT_POINTER; __set_bit(BTN_LEFT, input_dev->keybit); __set_bit(BTN_FORWARD, input_dev->keybit); __set_bit(BTN_BACK, input_dev->keybit); __set_bit(BTN_RIGHT, input_dev->keybit); - if (features->pktlen == WACOM_PKGLEN_BBTOUCH3) { - input_set_abs_params(input_dev, + if (features->touch_max) { + /* touch interface */ + unsigned int flags = INPUT_MT_POINTER; + + __set_bit(INPUT_PROP_POINTER, input_dev->propbit); + if (features->pktlen == WACOM_PKGLEN_BBTOUCH3) { + input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0, features->x_max, 0, 0); - input_set_abs_params(input_dev, + input_set_abs_params(input_dev, ABS_MT_TOUCH_MINOR, 0, features->y_max, 0, 0); + } else { + __set_bit(BTN_TOOL_FINGER, input_dev->keybit); + __set_bit(BTN_TOOL_DOUBLETAP, input_dev->keybit); + flags = 0; + } + input_mt_init_slots(input_dev, features->touch_max, flags); } else { - __set_bit(BTN_TOOL_FINGER, input_dev->keybit); - __set_bit(BTN_TOOL_DOUBLETAP, input_dev->keybit); - flags = 0; + /* buttons/keys only interface */ + __clear_bit(ABS_X, input_dev->absbit); + __clear_bit(ABS_Y, input_dev->absbit); + __clear_bit(BTN_TOUCH, input_dev->keybit); } - input_mt_init_slots(input_dev, features->touch_max, flags); } else if (features->device_type == BTN_TOOL_PEN) { + __set_bit(INPUT_PROP_POINTER, input_dev->propbit); __set_bit(BTN_TOOL_RUBBER, input_dev->keybit); __set_bit(BTN_TOOL_PEN, input_dev->keybit); __set_bit(BTN_STYLUS, input_dev->keybit); @@ -1776,6 +1920,24 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev, 0, 0); } break; + + case CINTIQ_HYBRID: + __set_bit(BTN_1, input_dev->keybit); + __set_bit(BTN_2, input_dev->keybit); + __set_bit(BTN_3, input_dev->keybit); + __set_bit(BTN_4, input_dev->keybit); + + __set_bit(BTN_5, input_dev->keybit); + __set_bit(BTN_6, input_dev->keybit); + __set_bit(BTN_7, input_dev->keybit); + __set_bit(BTN_8, input_dev->keybit); + __set_bit(BTN_0, input_dev->keybit); + + input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0); + __set_bit(INPUT_PROP_DIRECT, input_dev->propbit); + + wacom_setup_cintiq(wacom_wac); + break; } return 0; } @@ -1963,6 +2125,18 @@ static const struct wacom_features wacom_features_0x29 = static const struct wacom_features wacom_features_0x2A = { "Wacom Intuos5 M", WACOM_PKGLEN_INTUOS, 44704, 27940, 2047, 63, INTUOS5, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; +static const struct wacom_features wacom_features_0x314 = + { "Wacom Intuos Pro S", WACOM_PKGLEN_INTUOS, 31496, 19685, 2047, + 63, INTUOSPS, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, + .touch_max = 16 }; +static const struct wacom_features wacom_features_0x315 = + { "Wacom Intuos Pro M", WACOM_PKGLEN_INTUOS, 44704, 27940, 2047, + 63, INTUOSPM, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, + .touch_max = 16 }; +static const struct wacom_features wacom_features_0x317 = + { "Wacom Intuos Pro L", WACOM_PKGLEN_INTUOS, 65024, 40640, 2047, + 63, INTUOSPL, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, + .touch_max = 16 }; static const struct wacom_features wacom_features_0xF4 = { "Wacom Cintiq 24HD", WACOM_PKGLEN_INTUOS, 104480, 65600, 2047, 63, WACOM_24HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; @@ -1994,6 +2168,9 @@ static const struct wacom_features wacom_features_0xCE = static const struct wacom_features wacom_features_0xF0 = { "Wacom DTU1631", WACOM_PKGLEN_GRAPHIRE, 34623, 19553, 511, 0, DTU, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; +static const struct wacom_features wacom_features_0xFB = + { "Wacom DTU1031", WACOM_PKGLEN_DTUS, 22096, 13960, 511, + 0, DTUS, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; static const struct wacom_features wacom_features_0x57 = { "Wacom DTK2241", WACOM_PKGLEN_INTUOS, 95840, 54260, 2047, 63, DTK, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES}; @@ -2065,6 +2242,12 @@ static const struct wacom_features wacom_features_0x101 = static const struct wacom_features wacom_features_0x10D = { "Wacom ISDv4 10D", WACOM_PKGLEN_MTTPC, 26202, 16325, 255, 0, MTTPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; +static const struct wacom_features wacom_features_0x10E = + { "Wacom ISDv4 10E", WACOM_PKGLEN_MTTPC, 27760, 15694, 255, + 0, MTTPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; +static const struct wacom_features wacom_features_0x10F = + { "Wacom ISDv4 10F", WACOM_PKGLEN_MTTPC, 27760, 15694, 255, + 0, MTTPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; static const struct wacom_features wacom_features_0x4001 = { "Wacom ISDv4 4001", WACOM_PKGLEN_MTTPC, 26202, 16325, 255, 0, MTTPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; @@ -2112,7 +2295,7 @@ static const struct wacom_features wacom_features_0xDA = { "Wacom Bamboo 2FG 4x5 SE", WACOM_PKGLEN_BBFUN, 14720, 9200, 1023, 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 2 }; -static struct wacom_features wacom_features_0xDB = +static const struct wacom_features wacom_features_0xDB = { "Wacom Bamboo 2FG 6x8 SE", WACOM_PKGLEN_BBFUN, 21648, 13700, 1023, 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 2 }; @@ -2127,9 +2310,33 @@ static const struct wacom_features wacom_features_0xDF = { "Wacom Bamboo 16FG 6x8", WACOM_PKGLEN_BBPEN, 21648, 13700, 1023, 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 16 }; +static const struct wacom_features wacom_features_0x300 = + { "Wacom Bamboo One S", WACOM_PKGLEN_BBPEN, 14720, 9225, 1023, + 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; +static const struct wacom_features wacom_features_0x301 = + { "Wacom Bamboo One M", WACOM_PKGLEN_BBPEN, 21648, 13530, 1023, + 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; +static const struct wacom_features wacom_features_0x302 = + { "Wacom Intuos PT S", WACOM_PKGLEN_BBPEN, 15200, 9500, 1023, + 31, INTUOSHT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, + .touch_max = 16 }; +static const struct wacom_features wacom_features_0x303 = + { "Wacom Intuos PT M", WACOM_PKGLEN_BBPEN, 21600, 13500, 1023, + 31, INTUOSHT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, + .touch_max = 16 }; +static const struct wacom_features wacom_features_0x30E = + { "Wacom Intuos S", WACOM_PKGLEN_BBPEN, 15200, 9500, 1023, + 31, INTUOSHT, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; static const struct wacom_features wacom_features_0x6004 = { "ISD-V4", WACOM_PKGLEN_GRAPHIRE, 12800, 8000, 255, 0, TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; +static const struct wacom_features wacom_features_0x0307 = + { "Wacom ISDv5 307", WACOM_PKGLEN_INTUOS, 59552, 33848, 2047, + 63, CINTIQ_HYBRID, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, + .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x309 }; +static const struct wacom_features wacom_features_0x0309 = + { "Wacom ISDv5 309", .type = WACOM_24HDT, /* Touch */ + .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x0307, .touch_max = 10 }; #define USB_DEVICE_WACOM(prod) \ USB_DEVICE(USB_VENDOR_ID_WACOM, prod), \ @@ -2253,13 +2460,26 @@ const struct usb_device_id wacom_ids[] = { { USB_DEVICE_WACOM(0x100) }, { USB_DEVICE_WACOM(0x101) }, { USB_DEVICE_WACOM(0x10D) }, + { USB_DEVICE_WACOM(0x10E) }, + { USB_DEVICE_WACOM(0x10F) }, + { USB_DEVICE_WACOM(0x300) }, + { USB_DEVICE_WACOM(0x301) }, + { USB_DEVICE_DETAILED(0x302, USB_CLASS_HID, 0, 0) }, + { USB_DEVICE_DETAILED(0x303, USB_CLASS_HID, 0, 0) }, + { USB_DEVICE_DETAILED(0x30E, USB_CLASS_HID, 0, 0) }, { USB_DEVICE_WACOM(0x304) }, + { USB_DEVICE_DETAILED(0x314, USB_CLASS_HID, 0, 0) }, + { USB_DEVICE_DETAILED(0x315, USB_CLASS_HID, 0, 0) }, + { USB_DEVICE_DETAILED(0x317, USB_CLASS_HID, 0, 0) }, { USB_DEVICE_WACOM(0x4001) }, { USB_DEVICE_WACOM(0x47) }, { USB_DEVICE_WACOM(0xF4) }, { USB_DEVICE_WACOM(0xF8) }, { USB_DEVICE_DETAILED(0xF6, USB_CLASS_HID, 0, 0) }, { USB_DEVICE_WACOM(0xFA) }, + { USB_DEVICE_WACOM(0xFB) }, + { USB_DEVICE_WACOM(0x0307) }, + { USB_DEVICE_DETAILED(0x0309, USB_CLASS_HID, 0, 0) }, { USB_DEVICE_LENOVO(0x6004) }, { } }; diff --git a/drivers/input/tablet/wacom_wac.h b/drivers/input/tablet/wacom_wac.h index dfc9e08e7f70..f69c0ebe7fa9 100755 --- a/drivers/input/tablet/wacom_wac.h +++ b/drivers/input/tablet/wacom_wac.h @@ -12,7 +12,9 @@ #include /* maximum packet length for USB devices */ -#define WACOM_PKGLEN_MAX 64 +#define WACOM_PKGLEN_MAX 68 + +#define WACOM_NAME_MAX 64 /* packet length for individual models */ #define WACOM_PKGLEN_PENPRTN 7 @@ -27,6 +29,7 @@ #define WACOM_PKGLEN_WIRELESS 32 #define WACOM_PKGLEN_MTOUCH 62 #define WACOM_PKGLEN_MTTPC 40 +#define WACOM_PKGLEN_DTUS 68 /* wacom data size per MT contact */ #define WACOM_BYTES_PER_MT_PACKET 11 @@ -45,13 +48,17 @@ #define WACOM_REPORT_INTUOSWRITE 6 #define WACOM_REPORT_INTUOSPAD 12 #define WACOM_REPORT_INTUOS5PAD 3 +#define WACOM_REPORT_DTUSPAD 21 #define WACOM_REPORT_TPC1FG 6 #define WACOM_REPORT_TPC2FG 13 #define WACOM_REPORT_TPCMT 13 #define WACOM_REPORT_TPCHID 15 #define WACOM_REPORT_TPCST 16 +#define WACOM_REPORT_DTUS 17 #define WACOM_REPORT_TPC1FGE 18 #define WACOM_REPORT_24HDT 1 +#define WACOM_REPORT_WL 128 +#define WACOM_REPORT_USB 192 /* device quirks */ #define WACOM_QUIRK_MULTI_INPUT 0x0001 @@ -66,6 +73,7 @@ enum { PTU, PL, DTU, + DTUS, INTUOS, INTUOS3S, INTUOS3, @@ -76,10 +84,15 @@ enum { INTUOS5S, INTUOS5, INTUOS5L, + INTUOSPS, + INTUOSPM, + INTUOSPL, + INTUOSHT, WACOM_21UX2, WACOM_22HD, DTK, WACOM_24HD, + CINTIQ_HYBRID, CINTIQ, WACOM_BEE, WACOM_13HD, @@ -123,10 +136,14 @@ struct wacom_features { struct wacom_shared { bool stylus_in_proximity; bool touch_down; + /* for wireless device to access USB interfaces */ + unsigned touch_max; + int type; + struct input_dev *touch_input; }; struct wacom_wac { - char name[64]; + char name[WACOM_NAME_MAX]; unsigned char *data; int tool[2]; int id[2]; diff --git a/drivers/input/touchscreen/wacom_i2c.c b/drivers/input/touchscreen/wacom_i2c.c index bf0d07620bac..7ccaa1b12b05 100755 --- a/drivers/input/touchscreen/wacom_i2c.c +++ b/drivers/input/touchscreen/wacom_i2c.c @@ -1,7 +1,7 @@ /* * Wacom Penabled Driver for I2C * - * Copyright (c) 2011 Tatsunosuke Tobita, Wacom. + * Copyright (c) 2011 - 2013 Tatsunosuke Tobita, Wacom. * * * This program is free software; you can redistribute it @@ -27,7 +27,6 @@ #define WACOM_CMD_THROW0 0x05 #define WACOM_CMD_THROW1 0x00 #define WACOM_QUERY_SIZE 19 -#define WACOM_RETRY_CNT 100 struct wacom_features { int x_max; @@ -40,6 +39,8 @@ struct wacom_i2c { struct i2c_client *client; struct input_dev *input; u8 data[WACOM_QUERY_SIZE]; + bool prox; + int tool; }; static int wacom_query_device(struct i2c_client *client, @@ -112,9 +113,14 @@ static irqreturn_t wacom_i2c_irq(int irq, void *dev_id) y = le16_to_cpup((__le16 *)&data[6]); pressure = le16_to_cpup((__le16 *)&data[8]); + if (!wac_i2c->prox) + wac_i2c->tool = (data[3] & 0x0c) ? + BTN_TOOL_RUBBER : BTN_TOOL_PEN; + + wac_i2c->prox = data[3] & 0x20; + input_report_key(input, BTN_TOUCH, tsw || ers); - input_report_key(input, BTN_TOOL_PEN, tsw); - input_report_key(input, BTN_TOOL_RUBBER, ers); + input_report_key(input, wac_i2c->tool, wac_i2c->prox); input_report_key(input, BTN_STYLUS, f1); input_report_key(input, BTN_STYLUS2, f2); input_report_abs(input, ABS_X, x); diff --git a/drivers/input/touchscreen/wacom_w8001.c b/drivers/input/touchscreen/wacom_w8001.c index 9a83be6b6584..2792ca397dd0 100755 --- a/drivers/input/touchscreen/wacom_w8001.c +++ b/drivers/input/touchscreen/wacom_w8001.c @@ -18,7 +18,6 @@ #include #include #include -#include #include #include From 832469c438b78de6160ff1e3c2659ecacf33839d Mon Sep 17 00:00:00 2001 From: agsola Date: Thu, 28 Jan 2016 08:49:49 +0100 Subject: [PATCH 08/12] Update cpu.c to keep CPU cores 0 and 1 always on By Pafcholini: https://github.com/Emotroid-Team/emotion_tw_caf_kernel/blob/55b2ba483c4c0128bb8616d412e5671fb49c3614/kernel/cpu.c --- kernel/cpu.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/kernel/cpu.c b/kernel/cpu.c index a6c9e7f0290f..5d396402c7dd 100755 --- a/kernel/cpu.c +++ b/kernel/cpu.c @@ -371,6 +371,13 @@ int __ref cpu_down(unsigned int cpu) cpu_maps_update_begin(); + // Keep CPU cores 0 and 1 always on + if ((cpu == 0) || (cpu == 1)) + { + err = -EBUSY; + goto out; + } + if (cpu_hotplug_disabled) { err = -EBUSY; goto out; From ae96dd9a0ebf9744c5331cdb4c6052d5f5bd1dd2 Mon Sep 17 00:00:00 2001 From: Michael Wawrzyniak Date: Thu, 10 Mar 2016 11:19:31 -0500 Subject: [PATCH 09/12] Revert "Update cpu.c to keep CPU cores 0 and 1 always on" This reverts commit 832469c438b78de6160ff1e3c2659ecacf33839d. --- kernel/cpu.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/kernel/cpu.c b/kernel/cpu.c index 5d396402c7dd..a6c9e7f0290f 100755 --- a/kernel/cpu.c +++ b/kernel/cpu.c @@ -371,13 +371,6 @@ int __ref cpu_down(unsigned int cpu) cpu_maps_update_begin(); - // Keep CPU cores 0 and 1 always on - if ((cpu == 0) || (cpu == 1)) - { - err = -EBUSY; - goto out; - } - if (cpu_hotplug_disabled) { err = -EBUSY; goto out; From 0663661745200014b9eb1724ba5d0475ba25c9b1 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Tue, 16 Jun 2015 22:11:06 +0100 Subject: [PATCH 10/12] pipe: iovec: Fix memory corruption when retrying atomic copy as non-atomic pipe_iov_copy_{from,to}_user() may be tried twice with the same iovec, the first time atomically and the second time not. The second attempt needs to continue from the iovec position, pipe buffer offset and remaining length where the first attempt failed, but currently the pipe buffer offset and remaining length are reset. This will corrupt the piped data (possibly also leading to an information leak between processes) and may also corrupt kernel memory. This was fixed upstream by commits f0d1bec9d58d ("new helper: copy_page_from_iter()") and 637b58c2887e ("switch pipe_read() to copy_page_to_iter()"), but those aren't suitable for stable. This fix for older kernel versions was made by Seth Jennings for RHEL and I have extracted it from their update. CVE-2015-1805 Bug: 27275324 Change-Id: I459adb9076fcd50ff1f1c557089c4e421b036ec4 References: https://bugzilla.redhat.com/show_bug.cgi?id=1202855 Signed-off-by: Ben Hutchings Signed-off-by: Greg Kroah-Hartman (cherry picked from commit 85c34d007116f8a8aafb173966a605fb03532f45) --- fs/pipe.c | 55 ++++++++++++++++++++++++++++++++----------------------- 1 file changed, 32 insertions(+), 23 deletions(-) diff --git a/fs/pipe.c b/fs/pipe.c index 0e0752ef2715..3e7ab278bb0c 100755 --- a/fs/pipe.c +++ b/fs/pipe.c @@ -117,25 +117,27 @@ void pipe_wait(struct pipe_inode_info *pipe) } static int -pipe_iov_copy_from_user(void *to, struct iovec *iov, unsigned long len, - int atomic) +pipe_iov_copy_from_user(void *addr, int *offset, struct iovec *iov, + size_t *remaining, int atomic) { unsigned long copy; - while (len > 0) { + while (*remaining > 0) { while (!iov->iov_len) iov++; - copy = min_t(unsigned long, len, iov->iov_len); + copy = min_t(unsigned long, *remaining, iov->iov_len); if (atomic) { - if (__copy_from_user_inatomic(to, iov->iov_base, copy)) + if (__copy_from_user_inatomic(addr + *offset, + iov->iov_base, copy)) return -EFAULT; } else { - if (copy_from_user(to, iov->iov_base, copy)) + if (copy_from_user(addr + *offset, + iov->iov_base, copy)) return -EFAULT; } - to += copy; - len -= copy; + *offset += copy; + *remaining -= copy; iov->iov_base += copy; iov->iov_len -= copy; } @@ -143,25 +145,27 @@ pipe_iov_copy_from_user(void *to, struct iovec *iov, unsigned long len, } static int -pipe_iov_copy_to_user(struct iovec *iov, const void *from, unsigned long len, - int atomic) +pipe_iov_copy_to_user(struct iovec *iov, void *addr, int *offset, + size_t *remaining, int atomic) { unsigned long copy; - while (len > 0) { + while (*remaining > 0) { while (!iov->iov_len) iov++; - copy = min_t(unsigned long, len, iov->iov_len); + copy = min_t(unsigned long, *remaining, iov->iov_len); if (atomic) { - if (__copy_to_user_inatomic(iov->iov_base, from, copy)) + if (__copy_to_user_inatomic(iov->iov_base, + addr + *offset, copy)) return -EFAULT; } else { - if (copy_to_user(iov->iov_base, from, copy)) + if (copy_to_user(iov->iov_base, + addr + *offset, copy)) return -EFAULT; } - from += copy; - len -= copy; + *offset += copy; + *remaining -= copy; iov->iov_base += copy; iov->iov_len -= copy; } @@ -395,7 +399,7 @@ pipe_read(struct kiocb *iocb, const struct iovec *_iov, struct pipe_buffer *buf = pipe->bufs + curbuf; const struct pipe_buf_operations *ops = buf->ops; void *addr; - size_t chars = buf->len; + size_t chars = buf->len, remaining; int error, atomic; if (chars > total_len) @@ -409,9 +413,11 @@ pipe_read(struct kiocb *iocb, const struct iovec *_iov, } atomic = !iov_fault_in_pages_write(iov, chars); + remaining = chars; redo: addr = ops->map(pipe, buf, atomic); - error = pipe_iov_copy_to_user(iov, addr + buf->offset, chars, atomic); + error = pipe_iov_copy_to_user(iov, addr, &buf->offset, + &remaining, atomic); ops->unmap(pipe, buf, addr); if (unlikely(error)) { /* @@ -426,7 +432,6 @@ pipe_read(struct kiocb *iocb, const struct iovec *_iov, break; } ret += chars; - buf->offset += chars; buf->len -= chars; /* Was it a packet buffer? Clean up and exit */ @@ -531,6 +536,7 @@ pipe_write(struct kiocb *iocb, const struct iovec *_iov, if (ops->can_merge && offset + chars <= PAGE_SIZE) { int error, atomic = 1; void *addr; + size_t remaining = chars; error = ops->confirm(pipe, buf); if (error) @@ -539,8 +545,8 @@ pipe_write(struct kiocb *iocb, const struct iovec *_iov, iov_fault_in_pages_read(iov, chars); redo1: addr = ops->map(pipe, buf, atomic); - error = pipe_iov_copy_from_user(offset + addr, iov, - chars, atomic); + error = pipe_iov_copy_from_user(addr, &offset, iov, + &remaining, atomic); ops->unmap(pipe, buf, addr); ret = error; do_wakeup = 1; @@ -575,6 +581,8 @@ pipe_write(struct kiocb *iocb, const struct iovec *_iov, struct page *page = pipe->tmp_page; char *src; int error, atomic = 1; + int offset = 0; + size_t remaining; if (!page) { page = alloc_page(GFP_HIGHUSER); @@ -595,14 +603,15 @@ pipe_write(struct kiocb *iocb, const struct iovec *_iov, chars = total_len; iov_fault_in_pages_read(iov, chars); + remaining = chars; redo2: if (atomic) src = kmap_atomic(page); else src = kmap(page); - error = pipe_iov_copy_from_user(src, iov, chars, - atomic); + error = pipe_iov_copy_from_user(src, &offset, iov, + &remaining, atomic); if (atomic) kunmap_atomic(src); else From f0e6842aab870b174a19e7194e09b208ff91f1fb Mon Sep 17 00:00:00 2001 From: dcd Date: Wed, 4 May 2016 21:04:02 -0500 Subject: [PATCH 11/12] trlte: fix CROSS_COMPILE Change-Id: Idecd984814dbd4bfd2432150ddd0b10b0e675e2a --- Makefile | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index ca6205148352..7c8bbbd50524 100755 --- a/Makefile +++ b/Makefile @@ -192,9 +192,8 @@ SUBARCH := $(shell uname -m | sed -e s/i.86/x86/ -e s/x86_64/x86/ \ # "make" in the configured kernel build directory always uses that. # Default value for CROSS_COMPILE is not to prefix executables # Note: Some architectures assign CROSS_COMPILE in their arch/*/Makefile -ARCH ?=arm -CROSS_COMPILE = ../PLATFORM/prebuilts/gcc/linux-x86/arm/arm-eabi-4.8/bin/arm-eabi- - +ARCH ?= $(SUBARCH) +CROSS_COMPILE ?= $(CONFIG_CROSS_COMPILE:"%"=%) # Architecture as present in compile.h UTS_MACHINE := $(ARCH) From e839b7b0d6d9ea77fcb3d47989a7798c3e13169f Mon Sep 17 00:00:00 2001 From: Sunil Khatri Date: Wed, 22 Jun 2016 14:45:31 +0530 Subject: [PATCH 12/12] ashmem: Validate ashmem memory with fops pointer Validate the ashmem memory entry against f_op pointer rather then comparing its name with path of the dentry. This is to avoid any invalid access to ashmem area in cases where some one deliberately set the dentry name to /ashmem. Change-Id: I74e50cd244f68cb13009cf2355e528485f4de34b Signed-off-by: Sunil Khatri --- drivers/staging/android/ashmem.c | 42 +++++++++++++++----------------- 1 file changed, 20 insertions(+), 22 deletions(-) diff --git a/drivers/staging/android/ashmem.c b/drivers/staging/android/ashmem.c index 105c7ca1a0d3..fc979bf308bc 100755 --- a/drivers/staging/android/ashmem.c +++ b/drivers/staging/android/ashmem.c @@ -833,11 +833,28 @@ static long compat_ashmem_ioctl(struct file *file, unsigned int cmd, unsigned lo } #endif +static const struct file_operations ashmem_fops = { + .owner = THIS_MODULE, + .open = ashmem_open, + .release = ashmem_release, + .read = ashmem_read, + .llseek = ashmem_llseek, + .mmap = ashmem_mmap, + .unlocked_ioctl = ashmem_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = compat_ashmem_ioctl, +#endif +}; + +static struct miscdevice ashmem_misc = { + .minor = MISC_DYNAMIC_MINOR, + .name = "ashmem", + .fops = &ashmem_fops, +}; + static int is_ashmem_file(struct file *file) { - char fname[256], *name; - name = dentry_path(file->f_dentry, fname, 256); - return strcmp(name, "/ashmem") ? 0 : 1; + return (file->f_op == &ashmem_fops); } int get_ashmem_file(int fd, struct file **filp, struct file **vm_file, @@ -886,25 +903,6 @@ void put_ashmem_file(struct file *file) } EXPORT_SYMBOL(put_ashmem_file); -static const struct file_operations ashmem_fops = { - .owner = THIS_MODULE, - .open = ashmem_open, - .release = ashmem_release, - .read = ashmem_read, - .llseek = ashmem_llseek, - .mmap = ashmem_mmap, - .unlocked_ioctl = ashmem_ioctl, -#ifdef CONFIG_COMPAT - .compat_ioctl = compat_ashmem_ioctl, -#endif -}; - -static struct miscdevice ashmem_misc = { - .minor = MISC_DYNAMIC_MINOR, - .name = "ashmem", - .fops = &ashmem_fops, -}; - static int __init ashmem_init(void) { int ret;