Commit 19591e1a authored by Jason Gerecke's avatar Jason Gerecke Committed by Jiri Kosina
Browse files

HID: wacom: Support devices with two touchrings



If a device has more than one touchring, we want to be sure that userspace
is able to distinguish them. Following previous standards, the first
absolute ring will be reported as ABS_WHEEL and the second as ABS_THROTTLE.
Relative rings will use REL_WHEEL_HI_RES / REL_WHEEL for the first and
REL_HWHEEL_HI_RES / REL_HWHEEL for the second.

Signed-off-by: default avatarJason Gerecke <jason.gerecke@wacom.com>
Signed-off-by: default avatarJiri Kosina <jkosina@suse.com>
parent 7ca234e3
Loading
Loading
Loading
Loading
+46 −12
Original line number Diff line number Diff line
@@ -2047,10 +2047,21 @@ static void wacom_wac_pad_usage_mapping(struct hid_device *hdev,
		break;
	case WACOM_HID_WD_TOUCHRING:
		if (field->flags & HID_MAIN_ITEM_RELATIVE) {
			wacom_wac->relring_count++;
			if (wacom_wac->relring_count == 1) {
				wacom_map_usage(input, usage, field, EV_REL, REL_WHEEL_HI_RES, 0);
				set_bit(REL_WHEEL, input->relbit);
			}
			else if (wacom_wac->relring_count == 2) {
				wacom_map_usage(input, usage, field, EV_REL, REL_HWHEEL_HI_RES, 0);
				set_bit(REL_HWHEEL, input->relbit);
			}
		} else {
			wacom_wac->absring_count++;
			if (wacom_wac->absring_count == 1)
				wacom_map_usage(input, usage, field, EV_ABS, ABS_WHEEL, 0);
			else if (wacom_wac->absring_count == 2)
				wacom_map_usage(input, usage, field, EV_ABS, ABS_THROTTLE, 0);
		}
		features->device_type |= WACOM_DEVICETYPE_PAD;
		break;
@@ -2173,14 +2184,37 @@ static void wacom_wac_pad_event(struct hid_device *hdev, struct hid_field *field
				value = wacom_offset_rotation(input, usage, value, 1, 2);
		}
		else if (field->flags & HID_MAIN_ITEM_RELATIVE) {
			int hires_value = value * 120 / usage->resolution_multiplier;
			int *ring_value;
			int lowres_code;

			if (usage->code == REL_WHEEL_HI_RES) {
				/* We must invert the sign for vertical
			 * relative scrolling. Clockwise rotation
			 * produces positive values from HW, but
			 * userspace treats positive REL_WHEEL as a
			 * scroll *up*!
				 * relative scrolling. Clockwise
				 * rotation produces positive values
				 * from HW, but userspace treats
				 * positive REL_WHEEL as a scroll *up*!
				 */
				hires_value = -hires_value;
				ring_value = &wacom_wac->hid_data.ring_value;
				lowres_code = REL_WHEEL;
			}
			else if (usage->code == REL_HWHEEL_HI_RES) {
				/* No need to invert the sign for
				 * horizontal relative scrolling.
				 * Clockwise rotation produces positive
				 * values from HW and userspace treats
				 * positive REL_HWHEEL as a scroll
				 * right.
				 */
			int hires_value = -value * 120 / usage->resolution_multiplier;
			int *ring_value = &wacom_wac->hid_data.ring_value;
				ring_value = &wacom_wac->hid_data.ring2_value;
				lowres_code = REL_HWHEEL;
			}
			else {
				hid_err(wacom->hdev, "unrecognized relative wheel with code %d\n",
					usage->code);
				break;
			}

			value = hires_value;
			*ring_value += hires_value;
@@ -2191,7 +2225,7 @@ static void wacom_wac_pad_event(struct hid_device *hdev, struct hid_field *field
			if (*ring_value >= 120 || *ring_value <= -120) {
				int clicks = *ring_value / 120;

				input_event(input, usage->type, REL_WHEEL, clicks);
				input_event(input, usage->type, lowres_code, clicks);
				*ring_value -= clicks * 120;
			}
		}
+3 −0
Original line number Diff line number Diff line
@@ -313,6 +313,7 @@ struct hid_data {
	int height;
	int id;
	int ring_value;
	int ring2_value;
	int cc_report;
	int cc_index;
	int cc_value_index;
@@ -356,6 +357,8 @@ struct wacom_wac {
	int num_contacts_left;
	u8 bt_features;
	u8 bt_high_speed;
	u8 absring_count;
	u8 relring_count;
	int mode_report;
	int mode_value;
	struct hid_data hid_data;