diff options
| author | Gregor Kleen <gkleen@yggdrasil.li> | 2016-05-13 18:45:12 +0200 |
|---|---|---|
| committer | Gregor Kleen <gkleen@yggdrasil.li> | 2016-05-13 18:45:12 +0200 |
| commit | 8be024e136c7426772c3bd8f9a56fe4000d6d24c (patch) | |
| tree | a9c1dfa59aacf39480138ea5710af966114135ba /hel | |
| parent | 189c30a8893989ab12b22cec7f3e6ebacd1d70ae (diff) | |
| download | nixos-8be024e136c7426772c3bd8f9a56fe4000d6d24c.tar nixos-8be024e136c7426772c3bd8f9a56fe4000d6d24c.tar.gz nixos-8be024e136c7426772c3bd8f9a56fe4000d6d24c.tar.bz2 nixos-8be024e136c7426772c3bd8f9a56fe4000d6d24c.tar.xz nixos-8be024e136c7426772c3bd8f9a56fe4000d6d24c.zip | |
Patch for wacom support
Diffstat (limited to 'hel')
| -rw-r--r-- | hel/wacom.patch | 206 |
1 files changed, 206 insertions, 0 deletions
diff --git a/hel/wacom.patch b/hel/wacom.patch new file mode 100644 index 00000000..61500efc --- /dev/null +++ b/hel/wacom.patch | |||
| @@ -0,0 +1,206 @@ | |||
| 1 | From 326ea2a90500fe4add86c5fb95d914d46910e780 Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Jason Gerecke <killertofu@gmail.com> | ||
| 3 | Date: Mon, 4 Apr 2016 11:26:52 -0700 | ||
| 4 | Subject: [PATCH] HID: wacom: Support switching from vendor-defined device mode | ||
| 5 | on G9 and G11 | ||
| 6 | |||
| 7 | A tablet PC booted into Windows may have its pen/touch hardware switched | ||
| 8 | into "Wacom mode" similar to what we do with explicitly-supported hardware. | ||
| 9 | Some devices appear to maintain this state across reboots, preventing their | ||
| 10 | use with the generic HID driver. This patch adds support for detecting the | ||
| 11 | presence of the mode switch feature report used by devices based on the G9 | ||
| 12 | and G11 chips and has the HID codepath always attempt to reset the device | ||
| 13 | back to sending standard HID reports. | ||
| 14 | |||
| 15 | Fixes: https://sourceforge.net/p/linuxwacom/bugs/307/ | ||
| 16 | Fixes: https://sourceforge.net/p/linuxwacom/bugs/310/ | ||
| 17 | Fixes: https://github.com/linuxwacom/input-wacom/issues/15 | ||
| 18 | |||
| 19 | Co-authored-by: Benjamin Tissoires <benjamin.tissoires@redhat.com> | ||
| 20 | Signed-off-by: Jason Gerecke <jason.gerecke@wacom.com> | ||
| 21 | Reviewed-by: Benjamin Tissoires <benjamin.tissoires@redhat.com> | ||
| 22 | Signed-off-by: Jiri Kosina <jkosina@suse.cz> | ||
| 23 | --- | ||
| 24 | drivers/hid/wacom_sys.c | 100 ++++++++++++++++++++++++++++++++++-------------- | ||
| 25 | drivers/hid/wacom_wac.h | 8 ++++ | ||
| 26 | 2 files changed, 80 insertions(+), 28 deletions(-) | ||
| 27 | |||
| 28 | diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c | ||
| 29 | index b338bbf..ccf1883 100644 | ||
| 30 | --- a/drivers/hid/wacom_sys.c | ||
| 31 | +++ b/drivers/hid/wacom_sys.c | ||
| 32 | @@ -152,6 +152,25 @@ static void wacom_feature_mapping(struct hid_device *hdev, | ||
| 33 | hid_data->inputmode = field->report->id; | ||
| 34 | hid_data->inputmode_index = usage->usage_index; | ||
| 35 | break; | ||
| 36 | + | ||
| 37 | + case HID_UP_DIGITIZER: | ||
| 38 | + if (field->report->id == 0x0B && | ||
| 39 | + (field->application == WACOM_G9_DIGITIZER || | ||
| 40 | + field->application == WACOM_G11_DIGITIZER)) { | ||
| 41 | + wacom->wacom_wac.mode_report = field->report->id; | ||
| 42 | + wacom->wacom_wac.mode_value = 0; | ||
| 43 | + } | ||
| 44 | + break; | ||
| 45 | + | ||
| 46 | + case WACOM_G9_PAGE: | ||
| 47 | + case WACOM_G11_PAGE: | ||
| 48 | + if (field->report->id == 0x03 && | ||
| 49 | + (field->application == WACOM_G9_TOUCHSCREEN || | ||
| 50 | + field->application == WACOM_G11_TOUCHSCREEN)) { | ||
| 51 | + wacom->wacom_wac.mode_report = field->report->id; | ||
| 52 | + wacom->wacom_wac.mode_value = 0; | ||
| 53 | + } | ||
| 54 | + break; | ||
| 55 | } | ||
| 56 | } | ||
| 57 | |||
| 58 | @@ -322,26 +341,41 @@ static int wacom_hid_set_device_mode(struct hid_device *hdev) | ||
| 59 | return 0; | ||
| 60 | } | ||
| 61 | |||
| 62 | -static int wacom_set_device_mode(struct hid_device *hdev, int report_id, | ||
| 63 | - int length, int mode) | ||
| 64 | +static int wacom_set_device_mode(struct hid_device *hdev, | ||
| 65 | + struct wacom_wac *wacom_wac) | ||
| 66 | { | ||
| 67 | - unsigned char *rep_data; | ||
| 68 | + u8 *rep_data; | ||
| 69 | + struct hid_report *r; | ||
| 70 | + struct hid_report_enum *re; | ||
| 71 | + int length; | ||
| 72 | int error = -ENOMEM, limit = 0; | ||
| 73 | |||
| 74 | - rep_data = kzalloc(length, GFP_KERNEL); | ||
| 75 | + if (wacom_wac->mode_report < 0) | ||
| 76 | + return 0; | ||
| 77 | + | ||
| 78 | + re = &(hdev->report_enum[HID_FEATURE_REPORT]); | ||
| 79 | + r = re->report_id_hash[wacom_wac->mode_report]; | ||
| 80 | + if (!r) | ||
| 81 | + return -EINVAL; | ||
| 82 | + | ||
| 83 | + rep_data = hid_alloc_report_buf(r, GFP_KERNEL); | ||
| 84 | if (!rep_data) | ||
| 85 | - return error; | ||
| 86 | + return -ENOMEM; | ||
| 87 | + | ||
| 88 | + length = hid_report_len(r); | ||
| 89 | |||
| 90 | do { | ||
| 91 | - rep_data[0] = report_id; | ||
| 92 | - rep_data[1] = mode; | ||
| 93 | + rep_data[0] = wacom_wac->mode_report; | ||
| 94 | + rep_data[1] = wacom_wac->mode_value; | ||
| 95 | |||
| 96 | error = wacom_set_report(hdev, HID_FEATURE_REPORT, rep_data, | ||
| 97 | length, 1); | ||
| 98 | if (error >= 0) | ||
| 99 | error = wacom_get_report(hdev, HID_FEATURE_REPORT, | ||
| 100 | rep_data, length, 1); | ||
| 101 | - } while (error >= 0 && rep_data[1] != mode && limit++ < WAC_MSG_RETRIES); | ||
| 102 | + } while (error >= 0 && | ||
| 103 | + rep_data[1] != wacom_wac->mode_report && | ||
| 104 | + limit++ < WAC_MSG_RETRIES); | ||
| 105 | |||
| 106 | kfree(rep_data); | ||
| 107 | |||
| 108 | @@ -411,32 +445,41 @@ static int wacom_bt_query_tablet_data(struct hid_device *hdev, u8 speed, | ||
| 109 | static int wacom_query_tablet_data(struct hid_device *hdev, | ||
| 110 | struct wacom_features *features) | ||
| 111 | { | ||
| 112 | + struct wacom *wacom = hid_get_drvdata(hdev); | ||
| 113 | + struct wacom_wac *wacom_wac = &wacom->wacom_wac; | ||
| 114 | + | ||
| 115 | if (hdev->bus == BUS_BLUETOOTH) | ||
| 116 | return wacom_bt_query_tablet_data(hdev, 1, features); | ||
| 117 | |||
| 118 | - if (features->type == HID_GENERIC) | ||
| 119 | - return wacom_hid_set_device_mode(hdev); | ||
| 120 | - | ||
| 121 | - if (features->device_type & WACOM_DEVICETYPE_TOUCH) { | ||
| 122 | - if (features->type > TABLETPC) { | ||
| 123 | - /* MT Tablet PC touch */ | ||
| 124 | - return wacom_set_device_mode(hdev, 3, 4, 4); | ||
| 125 | - } | ||
| 126 | - else if (features->type == WACOM_24HDT) { | ||
| 127 | - return wacom_set_device_mode(hdev, 18, 3, 2); | ||
| 128 | - } | ||
| 129 | - else if (features->type == WACOM_27QHDT) { | ||
| 130 | - return wacom_set_device_mode(hdev, 131, 3, 2); | ||
| 131 | - } | ||
| 132 | - else if (features->type == BAMBOO_PAD) { | ||
| 133 | - return wacom_set_device_mode(hdev, 2, 2, 2); | ||
| 134 | - } | ||
| 135 | - } else if (features->device_type & WACOM_DEVICETYPE_PEN) { | ||
| 136 | - if (features->type <= BAMBOO_PT) { | ||
| 137 | - return wacom_set_device_mode(hdev, 2, 2, 2); | ||
| 138 | + if (features->type != HID_GENERIC) { | ||
| 139 | + if (features->device_type & WACOM_DEVICETYPE_TOUCH) { | ||
| 140 | + if (features->type > TABLETPC) { | ||
| 141 | + /* MT Tablet PC touch */ | ||
| 142 | + wacom_wac->mode_report = 3; | ||
| 143 | + wacom_wac->mode_value = 4; | ||
| 144 | + } else if (features->type == WACOM_24HDT) { | ||
| 145 | + wacom_wac->mode_report = 18; | ||
| 146 | + wacom_wac->mode_value = 2; | ||
| 147 | + } else if (features->type == WACOM_27QHDT) { | ||
| 148 | + wacom_wac->mode_report = 131; | ||
| 149 | + wacom_wac->mode_value = 2; | ||
| 150 | + } else if (features->type == BAMBOO_PAD) { | ||
| 151 | + wacom_wac->mode_report = 2; | ||
| 152 | + wacom_wac->mode_value = 2; | ||
| 153 | + } | ||
| 154 | + } else if (features->device_type & WACOM_DEVICETYPE_PEN) { | ||
| 155 | + if (features->type <= BAMBOO_PT) { | ||
| 156 | + wacom_wac->mode_report = 2; | ||
| 157 | + wacom_wac->mode_value = 2; | ||
| 158 | + } | ||
| 159 | } | ||
| 160 | } | ||
| 161 | |||
| 162 | + wacom_set_device_mode(hdev, wacom_wac); | ||
| 163 | + | ||
| 164 | + if (features->type == HID_GENERIC) | ||
| 165 | + return wacom_hid_set_device_mode(hdev); | ||
| 166 | + | ||
| 167 | return 0; | ||
| 168 | } | ||
| 169 | |||
| 170 | @@ -1818,6 +1861,7 @@ static int wacom_probe(struct hid_device *hdev, | ||
| 171 | } | ||
| 172 | |||
| 173 | wacom_wac->hid_data.inputmode = -1; | ||
| 174 | + wacom_wac->mode_report = -1; | ||
| 175 | |||
| 176 | wacom->usbdev = dev; | ||
| 177 | wacom->intf = intf; | ||
| 178 | diff --git a/drivers/hid/wacom_wac.h b/drivers/hid/wacom_wac.h | ||
| 179 | index 25baa7f..e2084d9 100644 | ||
| 180 | --- a/drivers/hid/wacom_wac.h | ||
| 181 | +++ b/drivers/hid/wacom_wac.h | ||
| 182 | @@ -84,6 +84,12 @@ | ||
| 183 | #define WACOM_DEVICETYPE_WL_MONITOR 0x0008 | ||
| 184 | |||
| 185 | #define WACOM_VENDORDEFINED_PEN 0xff0d0001 | ||
| 186 | +#define WACOM_G9_PAGE 0xff090000 | ||
| 187 | +#define WACOM_G9_DIGITIZER (WACOM_G9_PAGE | 0x02) | ||
| 188 | +#define WACOM_G9_TOUCHSCREEN (WACOM_G9_PAGE | 0x11) | ||
| 189 | +#define WACOM_G11_PAGE 0xff110000 | ||
| 190 | +#define WACOM_G11_DIGITIZER (WACOM_G11_PAGE | 0x02) | ||
| 191 | +#define WACOM_G11_TOUCHSCREEN (WACOM_G11_PAGE | 0x11) | ||
| 192 | |||
| 193 | #define WACOM_PEN_FIELD(f) (((f)->logical == HID_DG_STYLUS) || \ | ||
| 194 | ((f)->physical == HID_DG_STYLUS) || \ | ||
| 195 | @@ -238,6 +244,8 @@ struct wacom_wac { | ||
| 196 | int ps_connected; | ||
| 197 | u8 bt_features; | ||
| 198 | u8 bt_high_speed; | ||
| 199 | + int mode_report; | ||
| 200 | + int mode_value; | ||
| 201 | struct hid_data hid_data; | ||
| 202 | }; | ||
| 203 | |||
| 204 | -- | ||
| 205 | 2.1.4 | ||
| 206 | |||
