From: Benjamin Tissoires <benjamin.tissoires@redhat.com>
To: Dmitry Torokhov <dmitry.torokhov@gmail.com>,
Jiri Kosina <jkosina@suse.cz>, Ping Cheng <pinglinux@gmail.com>,
Jason Gerecke <killertofu@gmail.com>
Cc: linux-kernel@vger.kernel.org, linux-input@vger.kernel.org
Subject: [PATCH v2 19/23] Input - wacom: use in-kernel HID parser
Date: Tue, 15 Jul 2014 14:45:42 -0400 [thread overview]
Message-ID: <1405449946-11515-20-git-send-email-benjamin.tissoires@redhat.com> (raw)
In-Reply-To: <1405449946-11515-1-git-send-email-benjamin.tissoires@redhat.com>
HID already parses the report descriptor, so use it instead of implementing
our own.
The special case for Bamboo PT 3rd gen is also removed and handled in the
same way Intuos 5 is treated, by hardcoding it in the driver.
Last, the unit_exponent stored into the hid field already is signed, so
there is no need to handle a two's complement anymore.
Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
Reviewed-by: Jason Gerecke <killertofu@gmail.com>
Tested-by: Jason Gerecke <killertofu@gmail.com>
---
no changes in v2
drivers/input/tablet/wacom_sys.c | 348 +++++++++++++--------------------------
drivers/input/tablet/wacom_wac.h | 4 +-
2 files changed, 114 insertions(+), 238 deletions(-)
diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c
index 2c1d984..ed27e7d 100644
--- a/drivers/input/tablet/wacom_sys.c
+++ b/drivers/input/tablet/wacom_sys.c
@@ -15,13 +15,6 @@
#include "wacom.h"
#include <linux/hid.h>
-#define HID_HDESC_USAGE_UNDEFINED 0x00
-#define HID_HDESC_USAGE_PAGE 0x05
-#define HID_HDESC_USAGE 0x09
-#define HID_HDESC_COLLECTION 0xa1
-#define HID_HDESC_COLLECTION_LOGICAL 0x02
-#define HID_HDESC_COLLECTION_END 0xc0
-
#define WAC_MSG_RETRIES 5
#define WAC_CMD_LED_CONTROL 0x20
@@ -96,19 +89,15 @@ static void wacom_close(struct input_dev *dev)
* This function is little more than hidinput_calc_abs_res stripped down.
*/
static int wacom_calc_hid_res(int logical_extents, int physical_extents,
- unsigned char unit, unsigned char exponent)
+ unsigned unit, int exponent)
{
- int prev, unit_exponent;
+ int prev;
+ int unit_exponent = exponent;
/* Check if the extents are sane */
if (logical_extents <= 0 || physical_extents <= 0)
return 0;
- /* Get signed value of nybble-sized twos-compliment exponent */
- unit_exponent = exponent;
- if (unit_exponent > 7)
- unit_exponent -= 16;
-
/* Convert physical_extents to millimeters */
if (unit == 0x11) { /* If centimeters */
unit_exponent += 1;
@@ -141,42 +130,18 @@ static int wacom_calc_hid_res(int logical_extents, int physical_extents,
return logical_extents / physical_extents;
}
-static int wacom_parse_logical_collection(unsigned char *report,
- struct wacom_features *features)
-{
- int length = 0;
-
- if (features->type == BAMBOO_PT) {
-
- /* Logical collection is only used by 3rd gen Bamboo Touch */
- features->device_type = BTN_TOOL_FINGER;
-
- features->x_max = features->y_max =
- get_unaligned_le16(&report[10]);
-
- length = 11;
- }
- return length;
-}
-
-static void wacom_retrieve_report_data(struct hid_device *hdev,
- struct wacom_features *features)
+static void wacom_feature_mapping(struct hid_device *hdev,
+ struct hid_field *field, struct hid_usage *usage)
{
- int result = 0;
- unsigned char *rep_data;
-
- rep_data = kmalloc(2, GFP_KERNEL);
- if (rep_data) {
-
- rep_data[0] = 12;
- result = wacom_get_report(hdev, HID_FEATURE_REPORT,
- rep_data[0], rep_data, 2,
- WAC_MSG_RETRIES);
-
- if (result >= 0 && rep_data[1] > 2)
- features->touch_max = rep_data[1];
+ struct wacom *wacom = hid_get_drvdata(hdev);
+ struct wacom_features *features = &wacom->wacom_wac.features;
- kfree(rep_data);
+ switch (usage->hid) {
+ case HID_DG_CONTACTMAX:
+ /* leave touch_max as is if predefined */
+ if (!features->touch_max)
+ features->touch_max = field->value[0];
+ break;
}
}
@@ -209,190 +174,96 @@ static void wacom_retrieve_report_data(struct hid_device *hdev,
* interfaces haven't supported pressure or distance, this is enough
* information to override invalid values in the wacom_features table.
*
- * 3rd gen Bamboo Touch no longer define a Digitizer-Finger Pysical
- * Collection. Instead they define a Logical Collection with a single
- * Logical Maximum for both X and Y.
- *
- * Intuos5 touch interface does not contain useful data. We deal with
- * this after returning from this function.
+ * Intuos5 touch interface and 3rd gen Bamboo Touch do not contain useful
+ * data. We deal with them after returning from this function.
*/
-static int wacom_parse_hid(struct hid_device *hdev,
- struct wacom_features *features)
+static void wacom_usage_mapping(struct hid_device *hdev,
+ struct hid_field *field, struct hid_usage *usage)
{
- /* result has to be defined as int for some devices */
- int result = 0, touch_max = 0;
- int i = 0, page = 0, finger = 0, pen = 0;
- unsigned char *report = hdev->rdesc;
-
- for (i = 0; i < hdev->rsize; i++) {
-
- switch (report[i]) {
- case HID_HDESC_USAGE_PAGE:
- page = report[i + 1];
- i++;
- break;
-
- case HID_HDESC_USAGE:
- switch (page << 16 | report[i + 1]) {
- case HID_GD_X:
- if (finger) {
- features->device_type = BTN_TOOL_FINGER;
- /* touch device at least supports one touch point */
- touch_max = 1;
-
- switch (features->type) {
- case BAMBOO_PT:
- features->x_phy =
- get_unaligned_le16(&report[i + 5]);
- features->x_max =
- get_unaligned_le16(&report[i + 8]);
- i += 15;
- break;
-
- case WACOM_24HDT:
- features->x_max =
- get_unaligned_le16(&report[i + 3]);
- features->x_phy =
- get_unaligned_le16(&report[i + 8]);
- features->unit = report[i - 1];
- features->unitExpo = report[i - 3];
- i += 12;
- break;
-
- case MTTPC_B:
- features->x_max =
- get_unaligned_le16(&report[i + 3]);
- features->x_phy =
- get_unaligned_le16(&report[i + 6]);
- features->unit = report[i - 5];
- features->unitExpo = report[i - 3];
- i += 9;
- break;
-
- default:
- features->x_max =
- get_unaligned_le16(&report[i + 3]);
- features->x_phy =
- get_unaligned_le16(&report[i + 6]);
- features->unit = report[i + 9];
- features->unitExpo = report[i + 11];
- i += 12;
- break;
- }
- } else if (pen) {
- /* penabled only accepts exact bytes of data */
- features->device_type = BTN_TOOL_PEN;
- features->x_max =
- get_unaligned_le16(&report[i + 3]);
- i += 4;
- }
- break;
-
- case HID_GD_Y:
- if (finger) {
- switch (features->type) {
- case TABLETPC2FG:
- case MTSCREEN:
- case MTTPC:
- features->y_max =
- get_unaligned_le16(&report[i + 3]);
- features->y_phy =
- get_unaligned_le16(&report[i + 6]);
- i += 7;
- break;
-
- case WACOM_24HDT:
- features->y_max =
- get_unaligned_le16(&report[i + 3]);
- features->y_phy =
- get_unaligned_le16(&report[i - 2]);
- i += 7;
- break;
-
- case BAMBOO_PT:
- features->y_phy =
- get_unaligned_le16(&report[i + 3]);
- features->y_max =
- get_unaligned_le16(&report[i + 6]);
- i += 12;
- break;
-
- case MTTPC_B:
- features->y_max =
- get_unaligned_le16(&report[i + 3]);
- features->y_phy =
- get_unaligned_le16(&report[i + 6]);
- i += 9;
- break;
-
- default:
- features->y_max =
- features->x_max;
- features->y_phy =
- get_unaligned_le16(&report[i + 3]);
- i += 4;
- break;
- }
- } else if (pen) {
- features->y_max =
- get_unaligned_le16(&report[i + 3]);
- i += 4;
- }
- break;
-
- case HID_DG_FINGER:
- finger = 1;
- i++;
- break;
-
- /*
- * Requiring Stylus Usage will ignore boot mouse
- * X/Y values and some cases of invalid Digitizer X/Y
- * values commonly reported.
- */
- case HID_DG_STYLUS:
- pen = 1;
- i++;
- break;
-
- case HID_DG_CONTACTMAX:
- /* leave touch_max as is if predefined */
- if (!features->touch_max)
- wacom_retrieve_report_data(hdev, features);
- i++;
- break;
+ struct wacom *wacom = hid_get_drvdata(hdev);
+ struct wacom_features *features = &wacom->wacom_wac.features;
+ bool finger = (field->logical == HID_DG_FINGER) ||
+ (field->physical == HID_DG_FINGER);
+ bool pen = (field->logical == HID_DG_STYLUS) ||
+ (field->physical == HID_DG_STYLUS);
- case HID_DG_TIPPRESSURE:
- if (pen) {
- features->pressure_max =
- get_unaligned_le16(&report[i + 3]);
- i += 4;
- }
- break;
+ /*
+ * Requiring Stylus Usage will ignore boot mouse
+ * X/Y values and some cases of invalid Digitizer X/Y
+ * values commonly reported.
+ */
+ if (!pen && !finger)
+ return;
+
+ if (finger && !features->touch_max)
+ /* touch device at least supports one touch point */
+ features->touch_max = 1;
+
+ switch (usage->hid) {
+ case HID_GD_X:
+ features->x_max = field->logical_maximum;
+ if (finger) {
+ features->device_type = BTN_TOOL_FINGER;
+ features->x_phy = field->physical_maximum;
+ if (features->type != BAMBOO_PT) {
+ features->unit = field->unit;
+ features->unitExpo = field->unit_exponent;
}
- break;
-
- case HID_HDESC_COLLECTION_END:
- /* reset UsagePage and Finger */
- finger = page = 0;
- break;
+ } else {
+ features->device_type = BTN_TOOL_PEN;
+ }
+ break;
+ case HID_GD_Y:
+ features->y_max = field->logical_maximum;
+ if (finger) {
+ features->y_phy = field->physical_maximum;
+ if (features->type != BAMBOO_PT) {
+ features->unit = field->unit;
+ features->unitExpo = field->unit_exponent;
+ }
+ }
+ break;
+ case HID_DG_TIPPRESSURE:
+ if (pen)
+ features->pressure_max = field->logical_maximum;
+ break;
+ }
+}
- case HID_HDESC_COLLECTION:
- i++;
- switch (report[i]) {
- case HID_HDESC_COLLECTION_LOGICAL:
- i += wacom_parse_logical_collection(&report[i],
- features);
- break;
+static void wacom_parse_hid(struct hid_device *hdev,
+ struct wacom_features *features)
+{
+ struct hid_report_enum *rep_enum;
+ struct hid_report *hreport;
+ int i, j;
+
+ /* check features first */
+ rep_enum = &hdev->report_enum[HID_FEATURE_REPORT];
+ list_for_each_entry(hreport, &rep_enum->report_list, list) {
+ for (i = 0; i < hreport->maxfield; i++) {
+ /* Ignore if report count is out of bounds. */
+ if (hreport->field[i]->report_count < 1)
+ continue;
+
+ for (j = 0; j < hreport->field[i]->maxusage; j++) {
+ wacom_feature_mapping(hdev, hreport->field[i],
+ hreport->field[i]->usage + j);
}
- break;
}
}
- if (!features->touch_max && touch_max)
- features->touch_max = touch_max;
- result = 0;
- return result;
+ /* now check the input usages */
+ rep_enum = &hdev->report_enum[HID_INPUT_REPORT];
+ list_for_each_entry(hreport, &rep_enum->report_list, list) {
+
+ if (!hreport->maxfield)
+ continue;
+
+ for (i = 0; i < hreport->maxfield; i++)
+ for (j = 0; j < hreport->field[i]->maxusage; j++)
+ wacom_usage_mapping(hdev, hreport->field[i],
+ hreport->field[i]->usage + j);
+ }
}
static int wacom_set_device_mode(struct hid_device *hdev, int report_id,
@@ -448,10 +319,9 @@ static int wacom_query_tablet_data(struct hid_device *hdev,
return 0;
}
-static int wacom_retrieve_hid_descriptor(struct hid_device *hdev,
+static void wacom_retrieve_hid_descriptor(struct hid_device *hdev,
struct wacom_features *features)
{
- int error = 0;
struct wacom *wacom = hid_get_drvdata(hdev);
struct usb_interface *intf = wacom->intf;
@@ -478,14 +348,10 @@ static int wacom_retrieve_hid_descriptor(struct hid_device *hdev,
}
/* only devices that support touch need to retrieve the info */
- if (features->type < BAMBOO_PT) {
- goto out;
- }
+ if (features->type < BAMBOO_PT)
+ return;
- error = wacom_parse_hid(hdev, features);
-
- out:
- return error;
+ wacom_parse_hid(hdev, features);
}
struct wacom_hdev_data {
@@ -1275,9 +1141,7 @@ static int wacom_probe(struct hid_device *hdev,
wacom_set_default_phy(features);
/* Retrieve the physical and logical size for touch devices */
- error = wacom_retrieve_hid_descriptor(hdev, features);
- if (error)
- goto fail1;
+ wacom_retrieve_hid_descriptor(hdev, features);
/*
* Intuos5 has no useful data about its touch interface in its
@@ -1295,12 +1159,24 @@ static int wacom_probe(struct hid_device *hdev,
}
}
+ /*
+ * Same thing for Bamboo 3rd gen.
+ */
+ if ((features->type == BAMBOO_PT) &&
+ (features->pktlen == WACOM_PKGLEN_BBTOUCH3) &&
+ (features->device_type == BTN_TOOL_PEN)) {
+ features->device_type = BTN_TOOL_FINGER;
+
+ features->x_max = 4096;
+ features->y_max = 4096;
+ }
+
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;
+ features->unitExpo = -3;
}
wacom_calculate_res(features);
diff --git a/drivers/input/tablet/wacom_wac.h b/drivers/input/tablet/wacom_wac.h
index 8821a51..2a7612a 100644
--- a/drivers/input/tablet/wacom_wac.h
+++ b/drivers/input/tablet/wacom_wac.h
@@ -127,8 +127,8 @@ struct wacom_features {
int device_type;
int x_phy;
int y_phy;
- unsigned char unit;
- unsigned char unitExpo;
+ unsigned unit;
+ int unitExpo;
int x_fuzz;
int y_fuzz;
int pressure_fuzz;
--
2.0.0
next prev parent reply other threads:[~2014-07-15 18:45 UTC|newest]
Thread overview: 25+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-07-15 18:45 [PATCH v2 00/23] Wacom queued patches Benjamin Tissoires
2014-07-15 18:45 ` [PATCH v2 01/23] Revert "Input: wacom - testing result shows get_report is unnecessary." Benjamin Tissoires
2014-07-15 18:45 ` [PATCH v2 02/23] Input - wacom: assign phys field from struct wacom into input_dev Benjamin Tissoires
2014-07-15 18:45 ` [PATCH v2 03/23] Input - wacom: create a separate input device for pads Benjamin Tissoires
2014-07-15 18:45 ` [PATCH v2 04/23] Input - wacom: split out the pad device for Intuos/Cintiq Benjamin Tissoires
2014-07-15 18:45 ` [PATCH v2 05/23] Input - wacom: split out the pad device for Bamboos Benjamin Tissoires
2014-07-15 18:45 ` [PATCH v2 06/23] Input - wacom: split out the pad device for DTUS Benjamin Tissoires
2014-07-15 18:45 ` [PATCH v2 07/23] Input - wacom: split out the pad device for Graphire G4 and MO Benjamin Tissoires
2014-07-15 18:45 ` [PATCH v2 08/23] Input - wacom: split out the pad device for the wireless receiver Benjamin Tissoires
2014-07-15 18:45 ` [PATCH v2 09/23] Input - wacom: include and use linux/hid.h Benjamin Tissoires
2014-07-15 18:45 ` [PATCH v2 10/23] Input - wacom: switch from an USB driver to a HID driver Benjamin Tissoires
2014-07-15 18:45 ` [PATCH v2 11/23] Input - wacom: use hid communication instead of plain usb Benjamin Tissoires
2014-07-15 18:45 ` [PATCH v2 12/23] Input - wacom: use HID core to actually fetch the report descriptor Benjamin Tissoires
2014-07-15 18:45 ` [PATCH v2 13/23] Input - wacom: compute the HID report size to get the actual packet size Benjamin Tissoires
2014-07-15 18:45 ` [PATCH v2 14/23] Input - wacom: install LED/OLED sysfs files in the HID device instead of USB Benjamin Tissoires
2014-07-15 18:45 ` [PATCH v2 15/23] Input - wacom: register the input devices on top of the HID one Benjamin Tissoires
2014-07-15 18:45 ` [PATCH v2 16/23] Input - wacom: remove usb dependency for siblings devices Benjamin Tissoires
2014-07-15 18:45 ` [PATCH v2 17/23] Input - wacom: register power device at the HID level Benjamin Tissoires
2014-07-15 18:45 ` [PATCH v2 18/23] Input - wacom: use hid_info instead of plain dev_info Benjamin Tissoires
2014-07-15 18:45 ` Benjamin Tissoires [this message]
2014-07-15 18:45 ` [PATCH v2 20/23] Input - wacom: use hidinput_calc_abs_res instead of duplicating its code Benjamin Tissoires
2014-07-15 18:45 ` [PATCH v2 21/23] Input - wacom: remove field pktlen declaration in the list of devices Benjamin Tissoires
2014-07-15 18:45 ` [PATCH v2 22/23] Input - wacom: keep wacom_ids ordered Benjamin Tissoires
2014-07-15 18:45 ` [PATCH v2 23/23] Input - wacom: Move the USB (now hid) Wacom driver in drivers/hid Benjamin Tissoires
2014-07-24 20:25 ` Dmitry Torokhov
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1405449946-11515-20-git-send-email-benjamin.tissoires@redhat.com \
--to=benjamin.tissoires@redhat.com \
--cc=dmitry.torokhov@gmail.com \
--cc=jkosina@suse.cz \
--cc=killertofu@gmail.com \
--cc=linux-input@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=pinglinux@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).