mirror of
https://github.com/torvalds/linux.git
synced 2026-11-06 21:58:01 +01:00
Merge branch 'for-7.4/wacom' into for-linus
- UAF fixes (Lee Jones) - SW_MUTE_DEVICE semantics fix (Lee Jones, Ping Cheng)
This commit is contained in:
commit
8460eef1b9
|
|
@ -82,7 +82,7 @@
|
|||
#include <linux/kernel.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/mod_devicetable.h>
|
||||
#include <linux/device-id/hid.h>
|
||||
#include <linux/hid.h>
|
||||
#include <linux/kfifo.h>
|
||||
#include <linux/leds.h>
|
||||
|
|
|
|||
|
|
@ -758,27 +758,47 @@ static void wacom_retrieve_hid_descriptor(struct hid_device *hdev,
|
|||
struct wacom_hdev_data {
|
||||
struct list_head list;
|
||||
struct kref kref;
|
||||
struct hid_device *dev;
|
||||
char phys[64];
|
||||
__u32 vendor;
|
||||
__u32 product;
|
||||
__u32 device_type;
|
||||
struct wacom_shared shared;
|
||||
};
|
||||
|
||||
static bool wacom_compare_device_paths(struct hid_device *hdev_a,
|
||||
const char *phys_b, char separator)
|
||||
{
|
||||
const char *p1 = strrchr(hdev_a->phys, separator);
|
||||
const char *p2 = strrchr(phys_b, separator);
|
||||
int n1, n2;
|
||||
|
||||
if (!p1 || !p2)
|
||||
return false;
|
||||
|
||||
n1 = p1 - hdev_a->phys;
|
||||
n2 = p2 - phys_b;
|
||||
|
||||
if (n1 != n2 || n1 <= 0 || n2 <= 0)
|
||||
return false;
|
||||
|
||||
return !strncmp(hdev_a->phys, phys_b, n1);
|
||||
}
|
||||
|
||||
static LIST_HEAD(wacom_udev_list);
|
||||
static DEFINE_MUTEX(wacom_udev_list_lock);
|
||||
|
||||
static bool wacom_are_sibling(struct hid_device *hdev,
|
||||
struct hid_device *sibling)
|
||||
struct wacom_hdev_data *data)
|
||||
{
|
||||
struct wacom *wacom = hid_get_drvdata(hdev);
|
||||
struct wacom_features *features = &wacom->wacom_wac.features;
|
||||
struct wacom *sibling_wacom = hid_get_drvdata(sibling);
|
||||
struct wacom_features *sibling_features = &sibling_wacom->wacom_wac.features;
|
||||
__u32 oVid = features->oVid ? features->oVid : hdev->vendor;
|
||||
__u32 oPid = features->oPid ? features->oPid : hdev->product;
|
||||
|
||||
/* The defined oVid/oPid must match that of the sibling */
|
||||
if (features->oVid != HID_ANY_ID && sibling->vendor != oVid)
|
||||
if (features->oVid != HID_ANY_ID && data->vendor != oVid)
|
||||
return false;
|
||||
if (features->oPid != HID_ANY_ID && sibling->product != oPid)
|
||||
if (features->oPid != HID_ANY_ID && data->product != oPid)
|
||||
return false;
|
||||
|
||||
/*
|
||||
|
|
@ -786,11 +806,11 @@ static bool wacom_are_sibling(struct hid_device *hdev,
|
|||
* device path, while those with different VID/PID must share
|
||||
* the same physical parent device path.
|
||||
*/
|
||||
if (hdev->vendor == sibling->vendor && hdev->product == sibling->product) {
|
||||
if (!hid_compare_device_paths(hdev, sibling, '/'))
|
||||
if (hdev->vendor == data->vendor && hdev->product == data->product) {
|
||||
if (!wacom_compare_device_paths(hdev, data->phys, '/'))
|
||||
return false;
|
||||
} else {
|
||||
if (!hid_compare_device_paths(hdev, sibling, '.'))
|
||||
if (!wacom_compare_device_paths(hdev, data->phys, '.'))
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -803,7 +823,7 @@ static bool wacom_are_sibling(struct hid_device *hdev,
|
|||
* devices.
|
||||
*/
|
||||
if ((features->device_type & WACOM_DEVICETYPE_DIRECT) &&
|
||||
!(sibling_features->device_type & WACOM_DEVICETYPE_DIRECT))
|
||||
!(data->device_type & WACOM_DEVICETYPE_DIRECT))
|
||||
return false;
|
||||
|
||||
/*
|
||||
|
|
@ -811,17 +831,17 @@ static bool wacom_are_sibling(struct hid_device *hdev,
|
|||
* devices.
|
||||
*/
|
||||
if (!(features->device_type & WACOM_DEVICETYPE_DIRECT) &&
|
||||
(sibling_features->device_type & WACOM_DEVICETYPE_DIRECT))
|
||||
(data->device_type & WACOM_DEVICETYPE_DIRECT))
|
||||
return false;
|
||||
|
||||
/* Pen devices may only be siblings of touch devices */
|
||||
if ((features->device_type & WACOM_DEVICETYPE_PEN) &&
|
||||
!(sibling_features->device_type & WACOM_DEVICETYPE_TOUCH))
|
||||
!(data->device_type & WACOM_DEVICETYPE_TOUCH))
|
||||
return false;
|
||||
|
||||
/* Touch devices may only be siblings of pen devices */
|
||||
if ((features->device_type & WACOM_DEVICETYPE_TOUCH) &&
|
||||
!(sibling_features->device_type & WACOM_DEVICETYPE_PEN))
|
||||
!(data->device_type & WACOM_DEVICETYPE_PEN))
|
||||
return false;
|
||||
|
||||
/*
|
||||
|
|
@ -837,7 +857,7 @@ static struct wacom_hdev_data *wacom_get_hdev_data(struct hid_device *hdev)
|
|||
|
||||
/* Try to find an already-probed interface from the same device */
|
||||
list_for_each_entry(data, &wacom_udev_list, list) {
|
||||
if (hid_compare_device_paths(hdev, data->dev, '/')) {
|
||||
if (wacom_compare_device_paths(hdev, data->phys, '/')) {
|
||||
kref_get(&data->kref);
|
||||
return data;
|
||||
}
|
||||
|
|
@ -845,7 +865,7 @@ static struct wacom_hdev_data *wacom_get_hdev_data(struct hid_device *hdev)
|
|||
|
||||
/* Fallback to finding devices that appear to be "siblings" */
|
||||
list_for_each_entry(data, &wacom_udev_list, list) {
|
||||
if (wacom_are_sibling(hdev, data->dev)) {
|
||||
if (wacom_are_sibling(hdev, data)) {
|
||||
kref_get(&data->kref);
|
||||
return data;
|
||||
}
|
||||
|
|
@ -859,29 +879,41 @@ static void wacom_release_shared_data(struct kref *kref)
|
|||
struct wacom_hdev_data *data =
|
||||
container_of(kref, struct wacom_hdev_data, kref);
|
||||
|
||||
mutex_lock(&wacom_udev_list_lock);
|
||||
list_del(&data->list);
|
||||
mutex_unlock(&wacom_udev_list_lock);
|
||||
|
||||
kfree(data);
|
||||
}
|
||||
|
||||
static void wacom_remove_shared_data(void *res)
|
||||
{
|
||||
struct wacom *wacom = res;
|
||||
struct wacom *res_wacom = res;
|
||||
struct wacom_hdev_data *data;
|
||||
struct wacom_wac *wacom_wac = &wacom->wacom_wac;
|
||||
struct wacom_wac *wacom_wac = &res_wacom->wacom_wac;
|
||||
|
||||
if (wacom_wac->shared) {
|
||||
data = container_of(wacom_wac->shared, struct wacom_hdev_data,
|
||||
shared);
|
||||
|
||||
if (wacom_wac->shared->touch == wacom->hdev)
|
||||
wacom_wac->shared->touch = NULL;
|
||||
else if (wacom_wac->shared->pen == wacom->hdev)
|
||||
wacom_wac->shared->pen = NULL;
|
||||
scoped_guard(mutex, &wacom_udev_list_lock) {
|
||||
struct hid_device *touch =
|
||||
rcu_dereference_protected(wacom_wac->shared->touch,
|
||||
lockdep_is_held(&wacom_udev_list_lock));
|
||||
struct hid_device *pen =
|
||||
rcu_dereference_protected(wacom_wac->shared->pen,
|
||||
lockdep_is_held(&wacom_udev_list_lock));
|
||||
|
||||
if (touch == res_wacom->hdev) {
|
||||
rcu_assign_pointer(wacom_wac->shared->touch, NULL);
|
||||
rcu_assign_pointer(wacom_wac->shared->touch_input, NULL);
|
||||
} else if (pen == res_wacom->hdev) {
|
||||
rcu_assign_pointer(wacom_wac->shared->pen, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
synchronize_rcu();
|
||||
|
||||
if (kref_put_mutex(&data->kref, wacom_release_shared_data, &wacom_udev_list_lock))
|
||||
mutex_unlock(&wacom_udev_list_lock);
|
||||
|
||||
kref_put(&data->kref, wacom_release_shared_data);
|
||||
wacom_wac->shared = NULL;
|
||||
}
|
||||
}
|
||||
|
|
@ -904,22 +936,21 @@ static int wacom_add_shared_data(struct hid_device *hdev)
|
|||
}
|
||||
|
||||
kref_init(&data->kref);
|
||||
data->dev = hdev;
|
||||
strscpy(data->phys, hdev->phys, sizeof(data->phys));
|
||||
data->vendor = hdev->vendor;
|
||||
data->product = hdev->product;
|
||||
data->device_type = wacom_wac->features.device_type;
|
||||
list_add_tail(&data->list, &wacom_udev_list);
|
||||
}
|
||||
|
||||
mutex_unlock(&wacom_udev_list_lock);
|
||||
|
||||
wacom_wac->shared = &data->shared;
|
||||
|
||||
retval = devm_add_action_or_reset(&hdev->dev, wacom_remove_shared_data, wacom);
|
||||
if (retval)
|
||||
return retval;
|
||||
if (wacom_wac->has_mute_touch_switch)
|
||||
WRITE_ONCE(wacom_wac->shared->has_mute_touch_switch, true);
|
||||
|
||||
if (wacom_wac->features.device_type & WACOM_DEVICETYPE_TOUCH)
|
||||
wacom_wac->shared->touch = hdev;
|
||||
else if (wacom_wac->features.device_type & WACOM_DEVICETYPE_PEN)
|
||||
wacom_wac->shared->pen = hdev;
|
||||
mutex_unlock(&wacom_udev_list_lock);
|
||||
|
||||
retval = devm_add_action_or_reset(&hdev->dev, wacom_remove_shared_data, wacom);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
|
@ -2344,30 +2375,88 @@ static void wacom_release_resources(struct wacom *wacom)
|
|||
|
||||
static void wacom_set_shared_values(struct wacom_wac *wacom_wac)
|
||||
{
|
||||
if (wacom_wac->features.device_type & WACOM_DEVICETYPE_TOUCH) {
|
||||
wacom_wac->shared->type = wacom_wac->features.type;
|
||||
wacom_wac->shared->touch_input = wacom_wac->touch_input;
|
||||
}
|
||||
struct wacom *wacom = container_of(wacom_wac, struct wacom, wacom_wac);
|
||||
|
||||
guard(mutex)(&wacom_udev_list_lock);
|
||||
|
||||
if (wacom_wac->has_mute_touch_switch) {
|
||||
wacom_wac->shared->has_mute_touch_switch = true;
|
||||
WRITE_ONCE(wacom_wac->shared->has_mute_touch_switch, true);
|
||||
/* Hardware touch switch may be off. Wait until
|
||||
* we know the switch state to decide is_touch_on.
|
||||
* Softkey state should be initialized to "on" to
|
||||
* match historic default.
|
||||
*/
|
||||
if (wacom_wac->is_soft_touch_switch)
|
||||
wacom_wac->shared->is_touch_on = true;
|
||||
WRITE_ONCE(wacom_wac->shared->is_touch_on, true);
|
||||
}
|
||||
|
||||
if (wacom_wac->shared->has_mute_touch_switch &&
|
||||
wacom_wac->shared->touch_input) {
|
||||
set_bit(EV_SW, wacom_wac->shared->touch_input->evbit);
|
||||
input_set_capability(wacom_wac->shared->touch_input, EV_SW,
|
||||
SW_MUTE_DEVICE);
|
||||
if (wacom_wac->features.device_type & WACOM_DEVICETYPE_TOUCH) {
|
||||
struct hid_device *touch =
|
||||
rcu_dereference_protected(wacom_wac->shared->touch,
|
||||
lockdep_is_held(&wacom_udev_list_lock));
|
||||
|
||||
if (touch == wacom->hdev || !touch) {
|
||||
wacom_wac->shared->type = wacom_wac->features.type;
|
||||
rcu_assign_pointer(wacom_wac->shared->touch, wacom->hdev);
|
||||
rcu_assign_pointer(wacom_wac->shared->touch_input, wacom_wac->touch_input);
|
||||
}
|
||||
} else if (wacom_wac->features.device_type & WACOM_DEVICETYPE_PEN) {
|
||||
rcu_assign_pointer(wacom_wac->shared->pen, wacom->hdev);
|
||||
}
|
||||
}
|
||||
|
||||
static bool wacom_sibling_pending(struct wacom *wacom)
|
||||
{
|
||||
const struct wacom_features *features = &wacom->wacom_wac.features;
|
||||
struct hid_device *hdev = wacom->hdev;
|
||||
struct usb_interface *sibling_intf;
|
||||
int ifnum;
|
||||
|
||||
if (features->type != HID_GENERIC ||
|
||||
!(features->device_type & WACOM_DEVICETYPE_TOUCH))
|
||||
return false;
|
||||
|
||||
if (wacom->wacom_wac.shared) {
|
||||
if (rcu_access_pointer(wacom->wacom_wac.shared->pen))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!hid_is_usb(hdev) || !wacom->usbdev || !wacom->intf ||
|
||||
!wacom->intf->cur_altsetting)
|
||||
return false;
|
||||
|
||||
ifnum = wacom->intf->cur_altsetting->desc.bInterfaceNumber;
|
||||
|
||||
/*
|
||||
* On composite Wacom devices, the Pen interface is always interface 0.
|
||||
* If the Touch interface is interface 0, there is no sibling Pen
|
||||
* interface on this device (standalone touch device).
|
||||
*/
|
||||
if (ifnum == 0)
|
||||
return false;
|
||||
|
||||
/* Look for the sibling Pen interface at interface 0 */
|
||||
sibling_intf = usb_ifnum_to_if(wacom->usbdev, 0);
|
||||
if (!sibling_intf || !sibling_intf->cur_altsetting)
|
||||
return false;
|
||||
|
||||
if (sibling_intf->cur_altsetting->desc.bInterfaceClass !=
|
||||
USB_INTERFACE_CLASS_HID)
|
||||
return false;
|
||||
|
||||
if (sibling_intf->cur_altsetting->desc.bInterfaceSubClass == 1 &&
|
||||
(sibling_intf->cur_altsetting->desc.bInterfaceProtocol == 1 ||
|
||||
sibling_intf->cur_altsetting->desc.bInterfaceProtocol == 2))
|
||||
return false;
|
||||
|
||||
/*
|
||||
* Interface 0 is a candidate HID interface on this composite device
|
||||
* whose probe has not completed yet (shared->pen is NULL). Defer until
|
||||
* interface 0 finishes probing and registers shared values.
|
||||
*/
|
||||
return true;
|
||||
}
|
||||
|
||||
static int wacom_parse_and_register(struct wacom *wacom, bool wireless)
|
||||
{
|
||||
struct wacom_wac *wacom_wac = &wacom->wacom_wac;
|
||||
|
|
@ -2445,6 +2534,11 @@ static int wacom_parse_and_register(struct wacom *wacom, bool wireless)
|
|||
if (error)
|
||||
goto fail;
|
||||
|
||||
if (wacom_sibling_pending(wacom)) {
|
||||
error = -EPROBE_DEFER;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
error = wacom_setup_inputs(wacom);
|
||||
if (error)
|
||||
goto fail;
|
||||
|
|
@ -2502,6 +2596,7 @@ static int wacom_parse_and_register(struct wacom *wacom, bool wireless)
|
|||
|
||||
fail_hw_stop:
|
||||
hid_hw_stop(hdev);
|
||||
cancel_delayed_work_sync(&wacom->init_work);
|
||||
fail:
|
||||
wacom_release_resources(wacom);
|
||||
return error;
|
||||
|
|
@ -2789,16 +2884,19 @@ static void wacom_mode_change_work(struct work_struct *work)
|
|||
bool is_direct = wacom->wacom_wac.is_direct_mode;
|
||||
int error = 0;
|
||||
|
||||
if (shared->pen) {
|
||||
wacom1 = hid_get_drvdata(shared->pen);
|
||||
struct hid_device *pen = rcu_access_pointer(shared->pen);
|
||||
struct hid_device *touch = rcu_access_pointer(shared->touch);
|
||||
|
||||
if (pen) {
|
||||
wacom1 = hid_get_drvdata(pen);
|
||||
wacom_release_resources(wacom1);
|
||||
hid_hw_stop(wacom1->hdev);
|
||||
wacom1->wacom_wac.has_mode_change = true;
|
||||
wacom1->wacom_wac.is_direct_mode = is_direct;
|
||||
}
|
||||
|
||||
if (shared->touch) {
|
||||
wacom2 = hid_get_drvdata(shared->touch);
|
||||
if (touch) {
|
||||
wacom2 = hid_get_drvdata(touch);
|
||||
wacom_release_resources(wacom2);
|
||||
hid_hw_stop(wacom2->hdev);
|
||||
wacom2->wacom_wac.has_mode_change = true;
|
||||
|
|
|
|||
|
|
@ -510,6 +510,18 @@ static void wacom_intuos_schedule_prox_event(struct wacom_wac *wacom_wac)
|
|||
}
|
||||
}
|
||||
|
||||
static void wacom_report_touch_mute(struct wacom_wac *wacom_wac, bool mute)
|
||||
{
|
||||
struct input_dev *touch_input;
|
||||
|
||||
guard(rcu)();
|
||||
touch_input = rcu_dereference(wacom_wac->shared->touch_input);
|
||||
if (touch_input) {
|
||||
input_report_switch(touch_input, SW_MUTE_DEVICE, mute);
|
||||
input_sync(touch_input);
|
||||
}
|
||||
}
|
||||
|
||||
static int wacom_intuos_pad(struct wacom_wac *wacom)
|
||||
{
|
||||
struct wacom_features *features = &wacom->features;
|
||||
|
|
@ -650,12 +662,8 @@ static int wacom_intuos_pad(struct wacom_wac *wacom)
|
|||
input_report_key(input, KEY_CONTROLPANEL, menu);
|
||||
input_report_key(input, KEY_INFO, info);
|
||||
|
||||
if (wacom->shared && wacom->shared->touch_input) {
|
||||
input_report_switch(wacom->shared->touch_input,
|
||||
SW_MUTE_DEVICE,
|
||||
!wacom->shared->is_touch_on);
|
||||
input_sync(wacom->shared->touch_input);
|
||||
}
|
||||
if (wacom->shared)
|
||||
wacom_report_touch_mute(wacom, !wacom->shared->is_touch_on);
|
||||
|
||||
input_report_abs(input, ABS_RX, strip1);
|
||||
input_report_abs(input, ABS_RY, strip2);
|
||||
|
|
@ -2168,7 +2176,7 @@ static void wacom_wac_pad_event(struct hid_device *hdev, struct hid_field *field
|
|||
*/
|
||||
if ((equivalent_usage == WACOM_HID_WD_MUTE_DEVICE) ||
|
||||
(equivalent_usage == WACOM_HID_WD_TOUCHONOFF)) {
|
||||
if (wacom_wac->shared->touch_input) {
|
||||
if (wacom_wac->shared) {
|
||||
bool *is_touch_on = &wacom_wac->shared->is_touch_on;
|
||||
|
||||
if (equivalent_usage == WACOM_HID_WD_MUTE_DEVICE && value)
|
||||
|
|
@ -2176,9 +2184,7 @@ static void wacom_wac_pad_event(struct hid_device *hdev, struct hid_field *field
|
|||
else if (equivalent_usage == WACOM_HID_WD_TOUCHONOFF)
|
||||
*is_touch_on = value;
|
||||
|
||||
input_report_switch(wacom_wac->shared->touch_input,
|
||||
SW_MUTE_DEVICE, !(*is_touch_on));
|
||||
input_sync(wacom_wac->shared->touch_input);
|
||||
wacom_report_touch_mute(wacom_wac, !(*is_touch_on));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
|
@ -3301,6 +3307,7 @@ static int wacom_bpt_irq(struct wacom_wac *wacom, size_t len)
|
|||
static void wacom_bamboo_pad_pen_event(struct wacom_wac *wacom,
|
||||
unsigned char *data)
|
||||
{
|
||||
struct hid_device *pen;
|
||||
unsigned char prefix;
|
||||
|
||||
/*
|
||||
|
|
@ -3313,13 +3320,11 @@ static void wacom_bamboo_pad_pen_event(struct wacom_wac *wacom,
|
|||
prefix = data[0];
|
||||
data[0] = WACOM_REPORT_BPAD_PEN;
|
||||
|
||||
/*
|
||||
* actually reroute the event.
|
||||
* No need to check if wacom->shared->pen is valid, hid_input_report()
|
||||
* will check for us.
|
||||
*/
|
||||
hid_input_report(wacom->shared->pen, HID_INPUT_REPORT, data,
|
||||
WACOM_PKGLEN_PENABLED, 1);
|
||||
guard(rcu)();
|
||||
pen = rcu_dereference(wacom->shared->pen);
|
||||
if (pen)
|
||||
hid_input_report(pen, HID_INPUT_REPORT, data,
|
||||
WACOM_PKGLEN_PENABLED, 1);
|
||||
|
||||
data[0] = prefix;
|
||||
}
|
||||
|
|
@ -3396,11 +3401,8 @@ static int wacom_wireless_irq(struct wacom_wac *wacom, size_t len)
|
|||
|
||||
if ((wacom->shared->type == INTUOSHT ||
|
||||
wacom->shared->type == INTUOSHT2) &&
|
||||
wacom->shared->touch_input &&
|
||||
wacom->shared->touch_max) {
|
||||
input_report_switch(wacom->shared->touch_input,
|
||||
SW_MUTE_DEVICE, data[5] & 0x40);
|
||||
input_sync(wacom->shared->touch_input);
|
||||
wacom_report_touch_mute(wacom, data[5] & 0x40);
|
||||
}
|
||||
|
||||
pid = get_unaligned_be16(&data[6]);
|
||||
|
|
@ -3435,11 +3437,8 @@ static int wacom_status_irq(struct wacom_wac *wacom_wac, size_t len)
|
|||
|
||||
if ((features->type == INTUOSHT ||
|
||||
features->type == INTUOSHT2) &&
|
||||
wacom_wac->shared->touch_input &&
|
||||
features->touch_max) {
|
||||
input_report_switch(wacom_wac->shared->touch_input,
|
||||
SW_MUTE_DEVICE, data[8] & 0x40);
|
||||
input_sync(wacom_wac->shared->touch_input);
|
||||
wacom_report_touch_mute(wacom_wac, data[8] & 0x40);
|
||||
}
|
||||
|
||||
if (data[9] & 0x02) { /* wireless module is attached */
|
||||
|
|
@ -3966,8 +3965,8 @@ int wacom_setup_pen_input_capabilities(struct input_dev *input_dev,
|
|||
int wacom_setup_touch_input_capabilities(struct input_dev *input_dev,
|
||||
struct wacom_wac *wacom_wac)
|
||||
{
|
||||
struct hid_device *hdev = container_of(wacom_wac, struct wacom, wacom_wac)->hdev;
|
||||
struct wacom_features *features = &wacom_wac->features;
|
||||
|
||||
if (!(features->device_type & WACOM_DEVICETYPE_TOUCH))
|
||||
return -ENODEV;
|
||||
|
||||
|
|
@ -3976,9 +3975,24 @@ int wacom_setup_touch_input_capabilities(struct input_dev *input_dev,
|
|||
else
|
||||
__set_bit(INPUT_PROP_POINTER, input_dev->propbit);
|
||||
|
||||
if (features->type == HID_GENERIC)
|
||||
if (features->type == HID_GENERIC) {
|
||||
hid_dbg(hdev, "generic touch setup\n");
|
||||
|
||||
/*
|
||||
* This is to setup the touch switch for those devices that report
|
||||
* pen interface first. The setup can only be done here since this
|
||||
* routine is only called once. When we are here, the shared
|
||||
* has_mute_touch_switch has been set by the pad.
|
||||
|
||||
* There are two ways of reporting inputs from firmware: stylus first
|
||||
* or touch first. This path covers the stylus input first case.
|
||||
*/
|
||||
if (wacom_wac->shared && READ_ONCE(wacom_wac->shared->has_mute_touch_switch)) {
|
||||
input_set_capability(input_dev, EV_SW, SW_MUTE_DEVICE);
|
||||
}
|
||||
/* setup has already been done */
|
||||
return 0;
|
||||
}
|
||||
|
||||
input_dev->evbit[0] |= BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
|
||||
__set_bit(BTN_TOUCH, input_dev->keybit);
|
||||
|
|
@ -4010,19 +4024,17 @@ int wacom_setup_touch_input_capabilities(struct input_dev *input_dev,
|
|||
input_dev->evbit[0] |= BIT_MASK(EV_SW);
|
||||
__set_bit(SW_MUTE_DEVICE, input_dev->swbit);
|
||||
|
||||
if (wacom_wac->shared->touch->product == 0x361) {
|
||||
if (hdev->product == 0x361) {
|
||||
input_set_abs_params(input_dev, ABS_MT_POSITION_X,
|
||||
0, 12440, 4, 0);
|
||||
input_set_abs_params(input_dev, ABS_MT_POSITION_Y,
|
||||
0, 8640, 4, 0);
|
||||
}
|
||||
else if (wacom_wac->shared->touch->product == 0x360) {
|
||||
} else if (hdev->product == 0x360) {
|
||||
input_set_abs_params(input_dev, ABS_MT_POSITION_X,
|
||||
0, 8960, 4, 0);
|
||||
input_set_abs_params(input_dev, ABS_MT_POSITION_Y,
|
||||
0, 5920, 4, 0);
|
||||
}
|
||||
else if (wacom_wac->shared->touch->product == 0x393) {
|
||||
} else if (hdev->product == 0x393) {
|
||||
input_set_abs_params(input_dev, ABS_MT_POSITION_X,
|
||||
0, 6400, 4, 0);
|
||||
input_set_abs_params(input_dev, ABS_MT_POSITION_Y,
|
||||
|
|
@ -4052,8 +4064,8 @@ int wacom_setup_touch_input_capabilities(struct input_dev *input_dev,
|
|||
fallthrough;
|
||||
|
||||
case WACOM_27QHDT:
|
||||
if (wacom_wac->shared->touch->product == 0x32C ||
|
||||
wacom_wac->shared->touch->product == 0xF6) {
|
||||
if (hdev->product == 0x32C ||
|
||||
hdev->product == 0xF6) {
|
||||
input_dev->evbit[0] |= BIT_MASK(EV_SW);
|
||||
__set_bit(SW_MUTE_DEVICE, input_dev->swbit);
|
||||
wacom_wac->has_mute_touch_switch = true;
|
||||
|
|
@ -4399,7 +4411,26 @@ int wacom_setup_pad_input_capabilities(struct input_dev *input_dev,
|
|||
break;
|
||||
|
||||
case INTUOSHT3_BT:
|
||||
break;
|
||||
|
||||
case HID_GENERIC:
|
||||
if (wacom_wac->shared) {
|
||||
/*
|
||||
* The setup of touch switch capability can only be done
|
||||
* here for those devices, such as Cintiq Pro 13 and 16,
|
||||
* that have touch input registered before stylus and pad
|
||||
* inputs.
|
||||
*
|
||||
* There are two ways of reporting inputs from firmware:
|
||||
* stylus first or touch first. This path covers the touch
|
||||
* input first case.
|
||||
*/
|
||||
if (wacom_wac->has_mute_touch_switch &&
|
||||
wacom_wac->shared->touch_input) {
|
||||
input_set_capability(wacom_wac->shared->touch_input,
|
||||
EV_SW, SW_MUTE_DEVICE);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
|
|||
|
|
@ -285,9 +285,9 @@ struct wacom_shared {
|
|||
/* for wireless device to access USB interfaces */
|
||||
unsigned touch_max;
|
||||
int type;
|
||||
struct input_dev *touch_input;
|
||||
struct hid_device *pen;
|
||||
struct hid_device *touch;
|
||||
struct input_dev __rcu *touch_input;
|
||||
struct hid_device __rcu *pen;
|
||||
struct hid_device __rcu *touch;
|
||||
bool has_mute_touch_switch;
|
||||
bool is_touch_on;
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user