HID: wacom: Add support for MobileStudio Pro
Subsystems (2)
cover HID: wacom: Add support for MobileStudio Pro
Wacom announced two new "MobileStudio Pro" tablets yesterday, a third iteration of the Cintiq Companion line of mobile PCs which can double as external pen displays.
Unlike Wacom's prior professional-grade devices, the HID descriptor for the MobileStudio Pro includes a rudimentary (but standard!) "Digitizer" application collection that is usable by the existing HID_GENERIC codepath. Additionally, a second vendor-defined application collection exists which fully defines reports that enable full tablet functionality. The numerous vendor-defined usages are planned to be used in future professional devices as well, allowing us to finally gain some of the same forward compatibility benefits we've had for ISDv4 devices since 3.17.
* Patches 1-3 perform some basic cleanups.
* Patches 4-6 work on the operation of the driver for all HID_GENERIC devices, correcting minor issues and adding some missing features.
* Patches 7-19 implement support for the vendor defined usages that are used in the MobileStudio Pro, and which are planned to be used in future professional devices as well.
Jiri: Could you let me know whether it would be possible to schedule these for the currently-open 4.9 merge window?
Jason Gerecke (19):
HID: wacom: Update vendor-defined usage names to better match
standards
HID: wacom: Have WACOM_PEN_FIELD and WACOM_FINGER_FIELD recgonize more
fields
HID: wacom: Refactor button-to-key translation into function
HID: wacom: Detect and correct descriptors missing
HID_DG_BARRELSWITCH2
HID: wacom: generic: Strip off excessive name prefixing
HID: wacom: generic: Add support for height, tilt, and twist usages
HID: wacom: generic: Support and use 'Custom HID' mode and usages
HID: wacom: generic: Add support for vendor-defined "Distance" usage
HID: wacom: generic: Add support for vendor-defined "Fingerwheel"
usage
HID: wacom: generic: Add support for vendor-defined "Sense" usage
HID: wacom: Read and internally use corrected Intuos tool IDs
HID: wacom: generic: Support tool ID and additional tool types
HID: wacom: generic: Pass 'hdev' to 'wacom_map_usage'
HID: wacom: Fix sensor outbounds and redefine as offsets from each
edge
HID: wacom: generic: Add support for sensor offsets
HID: wacom: generic: Introduce pad support
HID: wacom: generic: Add support for battery status on pen and pad
interfaces
HID: wacom: generic: Extend pad support
HID: input: Recognize ABS_WHEEL in hidinput_calc_abs_res
drivers/hid/hid-input.c | 1 + drivers/hid/wacom_sys.c | 92 ++++++-- drivers/hid/wacom_wac.c | 544 +++++++++++++++++++++++++++++++++++++++--------- drivers/hid/wacom_wac.h | 73 ++++++- include/linux/hid.h | 4 + 5 files changed, 595 insertions(+), 119 deletions(-)
Signature · 1 line
2.10.0
PATCH 1/19 HID: wacom: Update vendor-defined usage names to better match standards
Our loose use of "pen" and "digitizer" in the naming of several of our vendor-defined usages may be a source of confusion given that the terms have specific meaning within the HID specification. "Pen" specifically refers to "an integrated display that allows the use of a stylus" (e.g. something like a tablet PC or Cintiq) wheras "Digitizer" is a better fit for opaque tablets like an Intuos.
While we're at it, go ahead and rename the definitions to make them more distinct and better match up with the convention used by HID (e.g. the use of '_UP_' for usage pages) and make them more distinct.
--- drivers/hid/wacom_sys.c | 12 ++++++------ drivers/hid/wacom_wac.c | 2 +- drivers/hid/wacom_wac.h | 17 +++++++++-------- 3 files changed, 16 insertions(+), 15 deletions(-)
drivers/hid/wacom_sys.c +6 -6
@@ -159,18 +159,18 @@ static void wacom_feature_mapping(struct hid_device *hdev,case HID_UP_DIGITIZER :if (field->report->id ==0x0B && - (field->application ==WACOM_G9_DIGITIZER || - field->application ==WACOM_G11_DIGITIZER )) { + (field->application ==WACOM_HID_G9_PEN || + field->application ==WACOM_HID_G11_PEN )) { wacom->wacom_wac.mode_report = field->report->id; wacom->wacom_wac.mode_value =0 ; }break ; -case WACOM_G9_PAGE : -case WACOM_G11_PAGE : +case WACOM_HID_UP_G9 : +case WACOM_HID_UP_G11 :if (field->report->id ==0x03 && - (field->application ==WACOM_G9_TOUCHSCREEN || - field->application ==WACOM_G11_TOUCHSCREEN )) { + (field->application ==WACOM_HID_G9_TOUCHSCREEN || + field->application ==WACOM_HID_G11_TOUCHSCREEN )) { wacom->wacom_wac.mode_report = field->report->id; wacom->wacom_wac.mode_value =0 ; }
drivers/hid/wacom_wac.c +1 -1
@@ -2458,7 +2458,7 @@ void wacom_setup_device_quirks(struct wacom *wacom)/* * Raw Wacom-mode pen and touch events both come from interface * 0, whose HID descriptor has an application usage of 0xFF0D -* (i.e., WACOM_VENDORDEFINED_PEN). We route pen packets back +* (i.e., WACOM_HID_WD_DIGITIZER). We route pen packets back * out through the HID_GENERIC device created for interface 1, * so rewrite this one to be of type WACOM_DEVICETYPE_TOUCH. */
drivers/hid/wacom_wac.h +9 -8
@@ -84,20 +84,21 @@#define WACOM_DEVICETYPE_WL_MONITOR 0x0008#define WACOM_DEVICETYPE_DIRECT 0x0010 -#define WACOM_VENDORDEFINED_PEN 0xff0d0001 -#define WACOM_G9_PAGE 0xff090000 -#define WACOM_G9_DIGITIZER (WACOM_G9_PAGE | 0x02) -#define WACOM_G9_TOUCHSCREEN (WACOM_G9_PAGE | 0x11) -#define WACOM_G11_PAGE 0xff110000 -#define WACOM_G11_DIGITIZER (WACOM_G11_PAGE | 0x02) -#define WACOM_G11_TOUCHSCREEN (WACOM_G11_PAGE | 0x11) +#define WACOM_HID_UP_WACOMDIGITIZER 0xff0d0000 +#define WACOM_HID_WD_DIGITIZER (WACOM_HID_UP_WACOMDIGITIZER | 0x01) +#define WACOM_HID_UP_G9 0xff090000 +#define WACOM_HID_G9_PEN (WACOM_HID_UP_G9 | 0x02) +#define WACOM_HID_G9_TOUCHSCREEN (WACOM_HID_UP_G9 | 0x11) +#define WACOM_HID_UP_G11 0xff110000 +#define WACOM_HID_G11_PEN (WACOM_HID_UP_G11 | 0x02) +#define WACOM_HID_G11_TOUCHSCREEN (WACOM_HID_UP_G11 | 0x11)#define WACOM_PEN_FIELD (f) (((f)->logical == HID_DG_STYLUS) || \ ((f)->physical == HID_DG_STYLUS) || \ ((f)->physical == HID_DG_PEN) || \ ((f)->application == HID_DG_PEN) || \ ((f)->application == HID_DG_DIGITIZER) || \ - ((f)->application == WACOM_VENDORDEFINED_PEN)) + ((f)->application == WACOM_HID_WD_DIGITIZER))#define WACOM_FINGER_FIELD (f) (((f)->logical == HID_DG_FINGER) || \ ((f)->physical == HID_DG_FINGER) || \ ((f)->application == HID_DG_TOUCHSCREEN))
Signature · 1 line
2.10.0
PATCH 2/19 HID: wacom: Have WACOM_PEN_FIELD and WACOM_FINGER_FIELD recgonize more fields
In reply to Jason GereckeWe've defined several new usages (e.g. WACOM_G9_PEN and WACOM_G9_TOUCHSCREEN) which aren't checked by the WACOM_PEN_FIELD and WACOM_FINGER_FIELD macros but probably should be.
--- drivers/hid/wacom_wac.h | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
drivers/hid/wacom_wac.h +6 -2
@@ -98,10 +98,14 @@ ((f)->physical == HID_DG_PEN) || \ ((f)->application == HID_DG_PEN) || \ ((f)->application == HID_DG_DIGITIZER) || \ - ((f)->application == WACOM_HID_WD_DIGITIZER)) + ((f)->application == WACOM_HID_WD_DIGITIZER) || \ + ((f)->application == WACOM_HID_G9_PEN) || \ + ((f)->application == WACOM_HID_G11_PEN))#define WACOM_FINGER_FIELD (f) (((f)->logical == HID_DG_FINGER) || \ ((f)->physical == HID_DG_FINGER) || \ - ((f)->application == HID_DG_TOUCHSCREEN)) + ((f)->application == HID_DG_TOUCHSCREEN) || \ + ((f)->application == WACOM_HID_G9_TOUCHSCREEN) || \ + ((f)->application == WACOM_HID_G11_TOUCHSCREEN))enum {PENPARTNER =0 ,
Signature · 1 line
2.10.0
PATCH 3/19 HID: wacom: Refactor button-to-key translation into function
In reply to Jason GereckeThis just centralizes the logic used in both wacom_setup_numbered_buttons and wacom_report_numbered_buttons so that they don't drift out of sync.
--- drivers/hid/wacom_wac.c | 36 ++++++++++++++++++++++++------------ 1 file changed, 24 insertions(+), 12 deletions(-)
drivers/hid/wacom_wac.c +24 -12
@@ -2779,17 +2779,29 @@ int wacom_setup_touch_input_capabilities(struct input_dev *input_dev,return 0 ; } +static int wacom_numbered_button_to_key (int n) +{ +if (n <10 ) +return BTN_0 + n; +else if (n <16 ) +return BTN_A + (n-10 ); +else if (n <18 ) +return BTN_BASE + (n-16 ); +else +return 0 ; +} +static void wacom_setup_numbered_buttons (struct input_dev *input_dev,int button_count) {int i; -for (i =0 ; i < button_count && i <10 ; i++) -__set_bit (BTN_0 + i, input_dev->keybit); -for (i =10 ; i < button_count && i <16 ; i++) -__set_bit (BTN_A + (i-10 ), input_dev->keybit); -for (i =16 ; i < button_count && i <18 ; i++) -__set_bit (BTN_BASE + (i-16 ), input_dev->keybit); +for (i =0 ; i < button_count; i++) { +int key =wacom_numbered_button_to_key (i); + +if (key) +__set_bit (key, input_dev->keybit); + } }static void wacom_24hd_update_leds (struct wacom *wacom,int mask,int group)
@@ -2891,12 +2903,12 @@ static void wacom_report_numbered_buttons(struct input_dev *input_dev,for (i =0 ; i < wacom->led.count; i++)wacom_update_led (wacom, button_count, mask, i); -for (i =0 ; i < button_count && i <10 ; i++) -input_report_key (input_dev,BTN_0 + i, mask & (1 << i)); -for (i =10 ; i < button_count && i <16 ; i++) -input_report_key (input_dev,BTN_A + (i-10 ), mask & (1 << i)); -for (i =16 ; i < button_count && i <18 ; i++) -input_report_key (input_dev,BTN_BASE + (i-16 ), mask & (1 << i)); +for (i =0 ; i < button_count; i++) { +int key =wacom_numbered_button_to_key (i); + +if (key) +input_report_key (input_dev, key, mask & (1 << i)); + } } int wacom_setup_pad_input_capabilities(struct input_dev *input_dev,
Signature · 1 line
2.10.0
PATCH 4/19 HID: wacom: Detect and correct descriptors missing HID_DG_BARRELSWITCH2
In reply to Jason GereckeISDv4 devices have long supported reporting data from each of two barrel switches, but HID_DG_BARRELSWITCH2 itself was only recently standardized. Prior to its adoption, ISDv4 devices would associate the bit indicating the state of the second barrel switch with the "Undefined" 0x000D0000 usage. Although most such devices have explicit support, a few use the HID_GENERIC codepath which ignores the "Undefined" usage.
This patch adds code which detects the presence of a pre-standard second barrel switch and corrects the usage value so that the HID_GENERIC code will declare its presence and report its state.
--- drivers/hid/wacom_sys.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+)
drivers/hid/wacom_sys.c +24 -0
@@ -240,6 +240,30 @@ static void wacom_usage_mapping(struct hid_device *hdev, features->touch_max =1 ; } +/* +* ISDv4 devices which predate HID's adoption of the +* HID_DG_BARELSWITCH2 usage use 0x000D0000 in its +* position instead. We can accurately detect if a +* usage with that value should be HID_DG_BARRELSWITCH2 +* based on the surrounding usages, which have remained +* constant across generations. +*/ +if (features->type ==HID_GENERIC && + usage->hid ==0x000D0000 && + field->application ==HID_DG_PEN && + field->physical ==HID_DG_STYLUS ) { +int i = usage->usage_index; + +if (i-4 >=0 && i+1 < field->maxusage && + field->usage[i-4 ].hid ==HID_DG_TIPSWITCH && + field->usage[i-3 ].hid ==HID_DG_BARRELSWITCH && + field->usage[i-2 ].hid ==HID_DG_ERASER && + field->usage[i-1 ].hid ==HID_DG_INVERT && + field->usage[i+1 ].hid ==HID_DG_INRANGE ) { + usage->hid =HID_DG_BARRELSWITCH2 ; + } + } +switch (usage->hid) {case HID_GD_X : features->x_max = field->logical_maximum;
Signature · 1 line
2.10.0
PATCH 5/19 HID: wacom: generic: Strip off excessive name prefixing
In reply to Jason GereckeThe product name received from the string descriptor in the new MobileStudio Pro line of tablets begins with "Wacom", which leads to unnecessary visual noise in the device name when appended to the vendor name which also includes "Wacom". Look for and fix cases like this.
--- drivers/hid/wacom_sys.c | 13 +++++++++++++ 1 file changed, 13 insertions(+)
drivers/hid/wacom_sys.c +13 -0
@@ -1940,6 +1940,19 @@ static void wacom_update_name(struct wacom *wacom, const char *suffix)/* shift everything including the terminator */ memmove (gap, gap+1 ,strlen (gap)); } + +/* strip off excessive prefixing */ +if (strstr (name,"Wacom Co.,Ltd. Wacom " ) == name) { +int n =strlen (name); +int x =strlen ("Wacom Co.,Ltd. " ); +memmove (name, name+x, n-x+1 ); + } +if (strstr (name,"Wacom Co., Ltd. Wacom " ) == name) { +int n =strlen (name); +int x =strlen ("Wacom Co., Ltd. " ); +memmove (name, name+x, n-x+1 ); + } +/* get rid of trailing whitespace */ if (name[strlen (name)-1 ] ==' ' ) name[strlen (name)-1 ] ='\0' ;
Signature · 1 line
2.10.0
PATCH 6/19 HID: wacom: generic: Add support for height, tilt, and twist usages
In reply to Jason GereckeThe HID standard defines usages that allow digitizers to report the pen's height, tilt, and rotation and which are used by Wacom's new "MobileStudio Pro" devices.
Note that 'hidinput_calc_abs_res' expects ABS_Z (historically used by our driver to report twist) to have linear units. To ensure it calculates a resolution with the actually-angular units provided in the HID descriptor we nedd to lie and tell it we're calculating it for the (rotational) ABS_RZ axis instead.
--- drivers/hid/wacom_wac.c | 28 ++++++++++++++++++++++++++-- include/linux/hid.h | 3 +++ 2 files changed, 29 insertions(+), 2 deletions(-)
drivers/hid/wacom_wac.c +26 -2
@@ -1440,6 +1440,11 @@ static void wacom_map_usage(struct input_dev *input, struct hid_usage *usage, {int fmin = field->logical_minimum;int fmax = field->logical_maximum; +int resolution_code = code; + +if (usage->hid ==HID_DG_TWIST ) { + resolution_code =ABS_RZ ; + } usage->type = type; usage->code = code;
@@ -1450,7 +1455,7 @@ static void wacom_map_usage(struct input_dev *input, struct hid_usage *usage,case EV_ABS :input_set_abs_params (input, code, fmin, fmax, fuzz,0 );input_abs_set_res (input, code, -hidinput_calc_abs_res (field, code)); +hidinput_calc_abs_res (field, resolution_code));break ;case EV_KEY :input_set_capability (input,EV_KEY , code);
@@ -1475,6 +1480,9 @@ static void wacom_wac_pen_usage_mapping(struct hid_device *hdev,case HID_GD_Y :wacom_map_usage (input, usage, field,EV_ABS ,ABS_Y ,4 );break ; +case HID_GD_Z : +wacom_map_usage (input, usage, field,EV_ABS ,ABS_DISTANCE ,0 ); +break ;case HID_DG_TIPPRESSURE :wacom_map_usage (input, usage, field,EV_ABS ,ABS_PRESSURE ,0 );break ;
@@ -1485,6 +1493,15 @@ static void wacom_wac_pen_usage_mapping(struct hid_device *hdev,wacom_map_usage (input, usage, field,EV_KEY ,BTN_TOOL_RUBBER ,0 );break ; +case HID_DG_TILT_X : +wacom_map_usage (input, usage, field,EV_ABS ,ABS_TILT_X ,0 ); +break ; +case HID_DG_TILT_Y : +wacom_map_usage (input, usage, field,EV_ABS ,ABS_TILT_Y ,0 ); +break ; +case HID_DG_TWIST : +wacom_map_usage (input, usage, field,EV_ABS ,ABS_Z ,0 ); +break ;case HID_DG_ERASER :case HID_DG_TIPSWITCH :wacom_map_usage (input, usage, field,EV_KEY ,BTN_TOUCH ,0 );
@@ -1508,8 +1525,15 @@ static int wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field,struct wacom_wac *wacom_wac = &wacom->wacom_wac;struct input_dev *input = wacom_wac->pen_input; -/* checking which Tool / tip switch to send */ switch (usage->hid) { +case HID_GD_Z : +/* +* HID_GD_Z "should increase as the control's position is +* moved from high to low", while ABS_DISTANCE instead +* increases in value as the tool moves from low to high. +*/ + value = field->logical_maximum - value; +break ;case HID_DG_INRANGE : wacom_wac->hid_data.inrange_state = value;return 0 ;
include/linux/hid.h +3 -0
@@ -232,6 +232,9 @@ struct hid_item {#define HID_DG_TABLETFUNCTIONKEY 0x000d0039#define HID_DG_PROGRAMCHANGEKEY 0x000d003a#define HID_DG_INVERT 0x000d003c +#define HID_DG_TILT_X 0x000d003d +#define HID_DG_TILT_Y 0x000d003e +#define HID_DG_TWIST 0x000d0041#define HID_DG_TIPSWITCH 0x000d0042#define HID_DG_TIPSWITCH2 0x000d0043#define HID_DG_BARRELSWITCH 0x000d0044
Signature · 1 line
2.10.0
PATCH 7/19 HID: wacom: generic: Support and use 'Custom HID' mode and usages
In reply to Jason GereckeWacom's new "MobileStudio Pro" tablets are the first devices in their branded product line-up to include a usable HID descriptor for the pen interface. Like prior branded products, the device can operate in one of two modes: 'Standard HID', and 'Wacom Custom HID'. Although the first mode is usable by the HID_GENERIC codepath as-is (huzzah!), it is subject to some restrictions -- most notably pressure being limited to 2048 levels instead of 8192. To ensure tablets that include support for Custom HID mode work optimally, we add support for its usages and switch the device to Custom HID mode if possible.
The usages defined for Custom HID mode are often numerically similar to their standard HID equivalents, allowing us to write a simple translation function that takes arbitrary HID usages as input and which returns the corresponding standard HID usage as output (if one exists). Switching on this translated usage instead of the actual usage allows the existing cases to apply to both modes of operation without having to explicitly define every Custom HID usage.
--- drivers/hid/wacom_sys.c | 5 +++++ drivers/hid/wacom_wac.c | 37 +++++++++++++++++++++++++++++++------ drivers/hid/wacom_wac.h | 3 +++ 3 files changed, 39 insertions(+), 6 deletions(-)
drivers/hid/wacom_sys.c +5 -0
@@ -166,6 +166,11 @@ static void wacom_feature_mapping(struct hid_device *hdev, }break ; +case WACOM_HID_WD_DATAMODE : + wacom->wacom_wac.mode_report = field->report->id; + wacom->wacom_wac.mode_value =2 ; +break ; +case WACOM_HID_UP_G9 :case WACOM_HID_UP_G11 : if (field->report->id == 0x03 &&
drivers/hid/wacom_wac.c +31 -6
@@ -1435,14 +1435,35 @@ static int wacom_tpc_irq(struct wacom_wac *wacom, size_t len)return 0 ; } +static int wacom_equivalent_usage (int usage) +{ +if ((usage &HID_USAGE_PAGE ) ==WACOM_HID_UP_WACOMDIGITIZER ) { +int subpage = (usage &0xFF00 ) <<8 ; +int subusage = (usage &0xFF ); + +if (subpage ==WACOM_HID_SP_DIGITIZER || + subpage ==WACOM_HID_SP_DIGITIZERINFO ) { +return usage; + } + +if (subpage ==HID_UP_UNDEFINED ) + subpage =HID_UP_DIGITIZER ; + +return subpage | subusage; + } + +return usage; +} +static void wacom_map_usage (struct input_dev *input,struct hid_usage *usage,struct hid_field *field,__u8 type,__u16 code,int fuzz) {int fmin = field->logical_minimum;int fmax = field->logical_maximum; +unsigned int equivalent_usage =wacom_equivalent_usage (usage->hid);int resolution_code = code; -if (usage->hid ==HID_DG_TWIST ) { +if (equivalent_usage ==HID_DG_TWIST ) { resolution_code =ABS_RZ ; }
@@ -1472,8 +1493,9 @@ static void wacom_wac_pen_usage_mapping(struct hid_device *hdev,struct wacom *wacom =hid_get_drvdata (hdev);struct wacom_wac *wacom_wac = &wacom->wacom_wac;struct input_dev *input = wacom_wac->pen_input; +unsigned equivalent_usage =wacom_equivalent_usage (usage->hid); -switch (usage->hid) { +switch (equivalent_usage) {case HID_GD_X :wacom_map_usage (input, usage, field,EV_ABS ,ABS_X ,4 );break ;
@@ -1524,8 +1546,9 @@ static int wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field,struct wacom *wacom =hid_get_drvdata (hdev);struct wacom_wac *wacom_wac = &wacom->wacom_wac;struct input_dev *input = wacom_wac->pen_input; +unsigned equivalent_usage =wacom_equivalent_usage (usage->hid); -switch (usage->hid) { +switch (equivalent_usage) {case HID_GD_Z :/* * HID_GD_Z "should increase as the control's position is
@@ -1598,8 +1621,9 @@ static void wacom_wac_finger_usage_mapping(struct hid_device *hdev,struct wacom_features *features = &wacom_wac->features;struct input_dev *input = wacom_wac->touch_input;unsigned touch_max = wacom_wac->features.touch_max; +unsigned equivalent_usage =wacom_equivalent_usage (usage->hid); -switch (usage->hid) { +switch (equivalent_usage) {case HID_GD_X : features->last_slot_field = usage->hid;if (touch_max ==1 )
@@ -1687,8 +1711,9 @@ static int wacom_wac_finger_event(struct hid_device *hdev, {struct wacom *wacom =hid_get_drvdata (hdev);struct wacom_wac *wacom_wac = &wacom->wacom_wac; +unsigned equivalent_usage =wacom_equivalent_usage (usage->hid); -switch (usage->hid) { +switch (equivalent_usage) {case HID_GD_X : wacom_wac->hid_data.x = value;break ;
@@ -1711,7 +1736,7 @@ static int wacom_wac_finger_event(struct hid_device *hdev,if (usage->usage_index +1 == field->report_count) { -if (usage->hid == wacom_wac->features.last_slot_field) +if (equivalent_usage == wacom_wac->features.last_slot_field)wacom_wac_finger_slot (wacom_wac, wacom_wac->touch_input); }
drivers/hid/wacom_wac.h +3 -0
@@ -85,7 +85,10 @@#define WACOM_DEVICETYPE_DIRECT 0x0010#define WACOM_HID_UP_WACOMDIGITIZER 0xff0d0000 +#define WACOM_HID_SP_DIGITIZER 0x000d0000 +#define WACOM_HID_SP_DIGITIZERINFO 0x00100000#define WACOM_HID_WD_DIGITIZER (WACOM_HID_UP_WACOMDIGITIZER | 0x01) +#define WACOM_HID_WD_DATAMODE (WACOM_HID_UP_WACOMDIGITIZER | 0x1002)#define WACOM_HID_UP_G9 0xff090000#define WACOM_HID_G9_PEN (WACOM_HID_UP_G9 | 0x02)#define WACOM_HID_G9_TOUCHSCREEN (WACOM_HID_UP_G9 | 0x11)
Signature · 1 line
2.10.0
PATCH 8/19 HID: wacom: generic: Add support for vendor-defined "Distance" usage
In reply to Jason GereckeThe vendor-defined 0xFF0D01032 ("Distance") usage is nearly equivalent to HID_GD_Z, except that the axis direction is inverted. Unlike HID_GD_Z which increases in value as the pen-to-surface distance is decreased, this usage decreases. Treat this usage as a special case to ensure we don't invert the scale to be ABS_DISTANCE compatible like we do for HID_GD_Z.
--- drivers/hid/wacom_wac.c | 4 +++- drivers/hid/wacom_wac.h | 1 + 2 files changed, 4 insertions(+), 1 deletion(-)
drivers/hid/wacom_wac.c +3 -1
@@ -1442,7 +1442,8 @@ static int wacom_equivalent_usage(int usage)int subusage = (usage &0xFF );if (subpage ==WACOM_HID_SP_DIGITIZER || - subpage ==WACOM_HID_SP_DIGITIZERINFO ) { + subpage ==WACOM_HID_SP_DIGITIZERINFO || + usage ==WACOM_HID_WD_DISTANCE ) {return usage; }
@@ -1502,6 +1503,7 @@ static void wacom_wac_pen_usage_mapping(struct hid_device *hdev,case HID_GD_Y :wacom_map_usage (input, usage, field,EV_ABS ,ABS_Y ,4 );break ; +case WACOM_HID_WD_DISTANCE :case HID_GD_Z :wacom_map_usage (input, usage, field,EV_ABS ,ABS_DISTANCE ,0 );break ;
drivers/hid/wacom_wac.h +1 -0
@@ -88,6 +88,7 @@#define WACOM_HID_SP_DIGITIZER 0x000d0000#define WACOM_HID_SP_DIGITIZERINFO 0x00100000#define WACOM_HID_WD_DIGITIZER (WACOM_HID_UP_WACOMDIGITIZER | 0x01) +#define WACOM_HID_WD_DISTANCE (WACOM_HID_UP_WACOMDIGITIZER | 0x0132)#define WACOM_HID_WD_DATAMODE (WACOM_HID_UP_WACOMDIGITIZER | 0x1002)#define WACOM_HID_UP_G9 0xff090000#define WACOM_HID_G9_PEN (WACOM_HID_UP_G9 | 0x02)
Signature · 1 line
2.10.0
PATCH 9/19 HID: wacom: generic: Add support for vendor-defined "Fingerwheel" usage
In reply to Jason GereckeThe airbrush fingerwheel does not have a usage that corresponds cleanly with a standard HID usage, so we add explicit support for it via its vendor-defined usage.
--- drivers/hid/wacom_wac.c | 3 +++ drivers/hid/wacom_wac.h | 1 + 2 files changed, 4 insertions(+)
drivers/hid/wacom_wac.c +3 -0
@@ -1539,6 +1539,9 @@ static void wacom_wac_pen_usage_mapping(struct hid_device *hdev,case HID_DG_TOOLSERIALNUMBER :wacom_map_usage (input, usage, field,EV_MSC ,MSC_SERIAL ,0 );break ; +case WACOM_HID_WD_FINGERWHEEL : +wacom_map_usage (input, usage, field,EV_ABS ,ABS_WHEEL ,0 ); +break ; } }
drivers/hid/wacom_wac.h +1 -0
@@ -89,6 +89,7 @@#define WACOM_HID_SP_DIGITIZERINFO 0x00100000#define WACOM_HID_WD_DIGITIZER (WACOM_HID_UP_WACOMDIGITIZER | 0x01)#define WACOM_HID_WD_DISTANCE (WACOM_HID_UP_WACOMDIGITIZER | 0x0132) +#define WACOM_HID_WD_FINGERWHEEL (WACOM_HID_UP_WACOMDIGITIZER | 0x0d03)#define WACOM_HID_WD_DATAMODE (WACOM_HID_UP_WACOMDIGITIZER | 0x1002)#define WACOM_HID_UP_G9 0xff090000#define WACOM_HID_G9_PEN (WACOM_HID_UP_G9 | 0x02)
Signature · 1 line
2.10.0
PATCH 10/19 HID: wacom: generic: Add support for vendor-defined "Sense" usage
In reply to Jason GereckeWacom's professional tablets beginning with the Intuos4 are capable of reporting an intermediate degree of proximity where the pen is no longer close enough to communicate with ("in prox"), but still close enough to be sensed ("in range"). This additional state is particularly useful for performing palm rejection as it allows the driver to disable the touch sensor while the pen is a greater distance from the tablet.
Like other professional tablets, the new MobileStudio Pro also reports this intermeidate "in range" proximity state. Its descriptor assigns usage 0xff0d0036 to this bit. Normally 'wacom_equivalent_usage' would translate this to the standard HID "Quality" usage, but since this has a different meaning we have it explicitly ignore the usage and define it ourselves as "Sense" (since "In Range" is already defined by the HID standard and interpreted by our driver as meaning "in prox").
--- drivers/hid/wacom_wac.c | 26 +++++++++++++++++++++++--- drivers/hid/wacom_wac.h | 3 +++ 2 files changed, 26 insertions(+), 3 deletions(-)
drivers/hid/wacom_wac.c +23 -3
@@ -1443,6 +1443,7 @@ static int wacom_equivalent_usage(int usage)if (subpage ==WACOM_HID_SP_DIGITIZER || subpage ==WACOM_HID_SP_DIGITIZERINFO || + usage ==WACOM_HID_WD_SENSE || usage ==WACOM_HID_WD_DISTANCE ) {return usage; }
@@ -1493,6 +1494,7 @@ static void wacom_wac_pen_usage_mapping(struct hid_device *hdev, {struct wacom *wacom =hid_get_drvdata (hdev);struct wacom_wac *wacom_wac = &wacom->wacom_wac; +struct wacom_features *features = &wacom_wac->features;struct input_dev *input = wacom_wac->pen_input;unsigned equivalent_usage =wacom_equivalent_usage (usage->hid);
@@ -1539,6 +1541,10 @@ static void wacom_wac_pen_usage_mapping(struct hid_device *hdev,case HID_DG_TOOLSERIALNUMBER :wacom_map_usage (input, usage, field,EV_MSC ,MSC_SERIAL ,0 );break ; +case WACOM_HID_WD_SENSE : + features->quirks |=WACOM_QUIRK_SENSE ; +wacom_map_usage (input, usage, field,EV_KEY ,BTN_TOOL_PEN ,0 ); +break ;case WACOM_HID_WD_FINGERWHEEL :wacom_map_usage (input, usage, field,EV_ABS ,ABS_WHEEL ,0 );break ;
@@ -1550,6 +1556,7 @@ static int wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field, {struct wacom *wacom =hid_get_drvdata (hdev);struct wacom_wac *wacom_wac = &wacom->wacom_wac; +struct wacom_features *features = &wacom_wac->features;struct input_dev *input = wacom_wac->pen_input;unsigned equivalent_usage =wacom_equivalent_usage (usage->hid);
@@ -1564,6 +1571,8 @@ static int wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field,break ;case HID_DG_INRANGE : wacom_wac->hid_data.inrange_state = value; +if (!(features->quirks &WACOM_QUIRK_SENSE )) + wacom_wac->hid_data.sense_state = value;return 0 ;case HID_DG_INVERT : wacom_wac->hid_data.invert_state = value;
@@ -1572,6 +1581,9 @@ static int wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field,case HID_DG_TIPSWITCH : wacom_wac->hid_data.tipswitch |= value;return 0 ; +case WACOM_HID_WD_SENSE : + wacom_wac->hid_data.sense_state = value; +return 0 ; }/* send pen events only when touch is up or forced out
@@ -1580,6 +1592,10 @@ static int wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field,if (!usage->type ||delay_pen_events (wacom_wac))return 0 ; +/* send pen events only when the pen is in/entering/leaving proximity */ +if (!wacom_wac->hid_data.inrange_state && !wacom_wac->tool[0 ]) +return 0 ; +input_event (input, usage->type, usage->code, value);return 0 ;
@@ -1598,16 +1614,17 @@ static void wacom_wac_pen_report(struct hid_device *hdev,struct wacom_wac *wacom_wac = &wacom->wacom_wac;struct input_dev *input = wacom_wac->pen_input;bool prox = wacom_wac->hid_data.inrange_state; +bool range = wacom_wac->hid_data.sense_state; -if (!wacom_wac->shared->stylus_in_proximity)/* first in prox */ +if (!wacom_wac->tool[0 ] && prox)/* first in prox */ /* Going into proximity select tool */ wacom_wac->tool[0 ] = wacom_wac->hid_data.invert_state ?BTN_TOOL_RUBBER :BTN_TOOL_PEN ;/* keep pen state for touch events */ - wacom_wac->shared->stylus_in_proximity = prox; + wacom_wac->shared->stylus_in_proximity = range; -if (!delay_pen_events (wacom_wac)) { +if (!delay_pen_events (wacom_wac) && wacom_wac->tool[0 ]) {input_report_key (input,BTN_TOUCH , wacom_wac->hid_data.tipswitch);input_report_key (input, wacom_wac->tool[0 ], prox);
@@ -1616,6 +1633,9 @@ static void wacom_wac_pen_report(struct hid_device *hdev,input_sync (input); } + +if (!prox) + wacom_wac->tool[0 ] =0 ; } static void wacom_wac_finger_usage_mapping(struct hid_device *hdev,
drivers/hid/wacom_wac.h +3 -0
@@ -74,6 +74,7 @@/* device quirks */ #define WACOM_QUIRK_BBTOUCH_LOWRES 0x0001 +#define WACOM_QUIRK_SENSE 0x0002#define WACOM_QUIRK_BATTERY 0x0008/* device types */
@@ -88,6 +89,7 @@#define WACOM_HID_SP_DIGITIZER 0x000d0000#define WACOM_HID_SP_DIGITIZERINFO 0x00100000#define WACOM_HID_WD_DIGITIZER (WACOM_HID_UP_WACOMDIGITIZER | 0x01) +#define WACOM_HID_WD_SENSE (WACOM_HID_UP_WACOMDIGITIZER | 0x36)#define WACOM_HID_WD_DISTANCE (WACOM_HID_UP_WACOMDIGITIZER | 0x0132)#define WACOM_HID_WD_FINGERWHEEL (WACOM_HID_UP_WACOMDIGITIZER | 0x0d03)#define WACOM_HID_WD_DATAMODE (WACOM_HID_UP_WACOMDIGITIZER | 0x1002)
@@ -213,6 +215,7 @@ struct wacom_shared {struct hid_data {__s16 inputmode;/* InputMode HID feature, -1 if non-existent */ __s16 inputmode_index;/* InputMode HID feature index in the report */ +bool sense_state;bool inrange_state;bool invert_state;bool tipswitch;
Signature · 1 line
2.10.0
PATCH 11/19 HID: wacom: Read and internally use corrected Intuos tool IDs
In reply to Jason GereckeThe 'wacom_intuos_inout' function incorrectly assmebles tool IDs from the proximity report, shifting the higher values of the ID four bits farther than intended. This problem was not detected until too late, but has not caused any issues since the incorrect IDs still fit in a 32-bit integer and userspace programs have not required the value to match the hardware (just that the values are unique and constant).
The tool IDs reported by the new MobileStudio Pro (or any future HID_GENERIC device that supports them) do not suffer from the same assembly issue, however. In order for 'wacom_intuos_get_tool_type' to work for with both codepaths, we correct this issue internally and have 'wacom_intuos_general' only mangle the ID when it is posted to userspace.
--- drivers/hid/wacom_wac.c | 38 ++++++++++++++++++++++---------------- 1 file changed, 22 insertions(+), 16 deletions(-)
drivers/hid/wacom_wac.c +22 -16
@@ -588,6 +588,11 @@ static int wacom_intuos_pad(struct wacom_wac *wacom)return 1 ; } +static int wacom_intuos_id_mangle (int tool_id) +{ +return (tool_id & ~0xFFF ) <<4 | (tool_id &0xFFF ); +} +static int wacom_intuos_get_tool_type (int tool_id) {int tool_type;
@@ -595,7 +600,7 @@ static int wacom_intuos_get_tool_type(int tool_id)switch (tool_id) {case 0x812 :/* Inking pen */ case 0x801 :/* Intuos3 Inking pen */ -case 0x120802 :/* Intuos4/5 Inking Pen */ +case 0x12802 :/* Intuos4/5 Inking Pen */ case 0x012 : tool_type =BTN_TOOL_PENCIL ;break ;
@@ -610,11 +615,11 @@ static int wacom_intuos_get_tool_type(int tool_id)case 0x804 :/* Intuos4/5 13HD/24HD Marker Pen */ case 0x8e2 :/* IntuosHT2 pen */ case 0x022 : -case 0x100804 :/* Intuos4/5 13HD/24HD Art Pen */ -case 0x140802 :/* Intuos4/5 13HD/24HD Classic Pen */ -case 0x160802 :/* Cintiq 13HD Pro Pen */ -case 0x180802 :/* DTH2242 Pen */ -case 0x100802 :/* Intuos4/5 13HD/24HD General Pen */ +case 0x10804 :/* Intuos4/5 13HD/24HD Art Pen */ +case 0x14802 :/* Intuos4/5 13HD/24HD Classic Pen */ +case 0x16802 :/* Cintiq 13HD Pro Pen */ +case 0x18802 :/* DTH2242 Pen */ +case 0x10802 :/* Intuos4/5 13HD/24HD General Pen */ tool_type =BTN_TOOL_PEN ;break ;
@@ -648,12 +653,12 @@ static int wacom_intuos_get_tool_type(int tool_id)case 0x80c :/* Intuos4/5 13HD/24HD Marker Pen Eraser */ case 0x80a :/* Intuos4/5 13HD/24HD General Pen Eraser */ case 0x90a :/* Intuos4/5 13HD/24HD Airbrush Eraser */ -case 0x14080a :/* Intuos4/5 13HD/24HD Classic Pen Eraser */ -case 0x10090a :/* Intuos4/5 13HD/24HD Airbrush Eraser */ -case 0x10080c :/* Intuos4/5 13HD/24HD Art Pen Eraser */ -case 0x16080a :/* Cintiq 13HD Pro Pen Eraser */ -case 0x18080a :/* DTH2242 Eraser */ -case 0x10080a :/* Intuos4/5 13HD/24HD General Pen Eraser */ +case 0x1480a :/* Intuos4/5 13HD/24HD Classic Pen Eraser */ +case 0x1090a :/* Intuos4/5 13HD/24HD Airbrush Eraser */ +case 0x1080c :/* Intuos4/5 13HD/24HD Art Pen Eraser */ +case 0x1680a :/* Cintiq 13HD Pro Pen Eraser */ +case 0x1880a :/* DTH2242 Eraser */ +case 0x1080a :/* Intuos4/5 13HD/24HD General Pen Eraser */ tool_type =BTN_TOOL_RUBBER ;break ;
@@ -662,7 +667,7 @@ static int wacom_intuos_get_tool_type(int tool_id)case 0x112 :case 0x913 :/* Intuos3 Airbrush */ case 0x902 :/* Intuos4/5 13HD/24HD Airbrush */ -case 0x100902 :/* Intuos4/5 13HD/24HD Airbrush */ +case 0x10902 :/* Intuos4/5 13HD/24HD Airbrush */ tool_type =BTN_TOOL_AIRBRUSH ;break ;
@@ -693,7 +698,7 @@ static int wacom_intuos_inout(struct wacom_wac *wacom) (data[6 ] <<4 ) + (data[7 ] >>4 ); wacom->id[idx] = (data[2 ] <<4 ) | (data[3 ] >>4 ) | - ((data[7 ] &0x0f ) <<20 ) | ((data[8 ] &0xf0 ) <<12 ); + ((data[7 ] &0x0f ) <<16 ) | ((data[8 ] &0xf0 ) <<8 ); wacom->tool[idx] =wacom_intuos_get_tool_type (wacom->id[idx]);
@@ -923,7 +928,7 @@ static int wacom_intuos_general(struct wacom_wac *wacom)* don't report events for invalid data */ /* older I4 styli don't work with new Cintiqs */ - if ((!((wacom->id[idx] >> 20) & 0x01) && + if ((!((wacom->id[idx] >> 16) & 0x01) && (features->type == WACOM_21UX2)) || /* Only large Intuos support Lense Cursor */ (wacom->tool[idx] == BTN_TOOL_LENS &&
@@ -1059,7 +1064,8 @@ static int wacom_intuos_general(struct wacom_wac *wacom)break ; } -input_report_abs (input,ABS_MISC , wacom->id[idx]);/* report tool id */ +input_report_abs (input,ABS_MISC , +wacom_intuos_id_mangle (wacom->id[idx]));/* report tool id */ input_report_key (input, wacom->tool[idx],1 );input_event (input,EV_MSC ,MSC_SERIAL , wacom->serial[idx]); wacom->reporting_data = true;
Signature · 1 line
2.10.0
PATCH 12/19 HID: wacom: generic: Support tool ID and additional tool types
In reply to Jason GereckeDevices following the new Custom HID mode specification (as well as even some recent component sensors which use the same standard HID usage) are capable of reporting tool ID information that we need to relay to userspace. This patch adds support for reading and relaying the tool type information, which is (unfortunately) split across two usages. We also advertise the existence of tool types beyond BTN_TOOL_PEN that might be available.
--- drivers/hid/wacom_wac.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++--- drivers/hid/wacom_wac.h | 4 ++- 2 files changed, 71 insertions(+), 5 deletions(-)
drivers/hid/wacom_wac.c +68 -4
@@ -1450,6 +1450,8 @@ static int wacom_equivalent_usage(int usage)if (subpage ==WACOM_HID_SP_DIGITIZER || subpage ==WACOM_HID_SP_DIGITIZERINFO || usage ==WACOM_HID_WD_SENSE || + usage ==WACOM_HID_WD_SERIALHI || + usage ==WACOM_HID_WD_TOOLTYPE || usage ==WACOM_HID_WD_DISTANCE ) {return usage; }
@@ -1551,6 +1553,17 @@ static void wacom_wac_pen_usage_mapping(struct hid_device *hdev, features->quirks |=WACOM_QUIRK_SENSE ;wacom_map_usage (input, usage, field,EV_KEY ,BTN_TOOL_PEN ,0 );break ; +case WACOM_HID_WD_SERIALHI : +wacom_map_usage (input, usage, field,EV_ABS ,ABS_MISC ,0 ); +set_bit (EV_KEY , input->evbit); +input_set_capability (input,EV_KEY ,BTN_TOOL_PEN ); +input_set_capability (input,EV_KEY ,BTN_TOOL_RUBBER ); +input_set_capability (input,EV_KEY ,BTN_TOOL_BRUSH ); +input_set_capability (input,EV_KEY ,BTN_TOOL_PENCIL ); +input_set_capability (input,EV_KEY ,BTN_TOOL_AIRBRUSH ); +input_set_capability (input,EV_KEY ,BTN_TOOL_MOUSE ); +input_set_capability (input,EV_KEY ,BTN_TOOL_LENS ); +break ;case WACOM_HID_WD_FINGERWHEEL :wacom_map_usage (input, usage, field,EV_ABS ,ABS_WHEEL ,0 );break ;
@@ -1587,9 +1600,35 @@ static int wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field,case HID_DG_TIPSWITCH : wacom_wac->hid_data.tipswitch |= value;return 0 ; +case HID_DG_TOOLSERIALNUMBER : + wacom_wac->serial[0 ] = (wacom_wac->serial[0 ] & ~0xFFFFFFFF ); + wacom_wac->serial[0 ] |= value; +return 0 ;case WACOM_HID_WD_SENSE : wacom_wac->hid_data.sense_state = value;return 0 ; +case WACOM_HID_WD_SERIALHI : + wacom_wac->serial[0 ] = (wacom_wac->serial[0 ] &0xFFFFFFFF ); + wacom_wac->serial[0 ] |= ((__u64 )value) <<32 ; +/* +* Non-USI EMR devices may contain additional tool type +* information here. See WACOM_HID_WD_TOOLTYPE case for +* more details. +*/ +if (value >>20 ==1 ) { + wacom_wac->id[0 ] |= value &0xFFFFF ; + } +return 0 ; +case WACOM_HID_WD_TOOLTYPE : +/* +* Some devices (MobileStudio Pro, and possibly later +* devices as well) do not return the complete tool +* type in their WACOM_HID_WD_TOOLTYPE usage. Use a +* bitwise OR so the complete value can be built +* up over time :( +*/ + wacom_wac->id[0 ] |= value; +return 0 ; }/* send pen events only when touch is up or forced out
@@ -1622,26 +1661,51 @@ static void wacom_wac_pen_report(struct hid_device *hdev,bool prox = wacom_wac->hid_data.inrange_state;bool range = wacom_wac->hid_data.sense_state; -if (!wacom_wac->tool[0 ] && prox)/* first in prox */ +if (!wacom_wac->tool[0 ] && prox) {/* first in prox */ /* Going into proximity select tool */ - wacom_wac->tool[0 ] = wacom_wac->hid_data.invert_state ? -BTN_TOOL_RUBBER :BTN_TOOL_PEN ; +if (wacom_wac->hid_data.invert_state) + wacom_wac->tool[0 ] =BTN_TOOL_RUBBER ; +else if (wacom_wac->id[0 ]) + wacom_wac->tool[0 ] =wacom_intuos_get_tool_type (wacom_wac->id[0 ]); +else + wacom_wac->tool[0 ] =BTN_TOOL_PEN ; + }/* keep pen state for touch events */ wacom_wac->shared->stylus_in_proximity = range;if (!delay_pen_events (wacom_wac) && wacom_wac->tool[0 ]) { +int id = wacom_wac->id[0 ]; + +/* +* Non-USI EMR tools should have their IDs mangled to +* match the legacy behavior of wacom_intuos_general +*/ +if (wacom_wac->serial[0 ] >>52 ==1 ) + id =wacom_intuos_id_mangle (id); + +/* +* To ensure compatibility with xf86-input-wacom, we should +* report the BTN_TOOL_* event prior to the ABS_MISC or +* MSC_SERIAL events. +*/ input_report_key (input,BTN_TOUCH , wacom_wac->hid_data.tipswitch);input_report_key (input, wacom_wac->tool[0 ], prox); +if (wacom_wac->serial[0 ]) { +input_event (input,EV_MSC ,MSC_SERIAL , wacom_wac->serial[0 ]); +input_report_abs (input,ABS_MISC , id); + } wacom_wac->hid_data.tipswitch = false;input_sync (input); } -if (!prox) +if (!prox) { wacom_wac->tool[0 ] =0 ; + wacom_wac->id[0 ] =0 ; + } } static void wacom_wac_finger_usage_mapping(struct hid_device *hdev,
drivers/hid/wacom_wac.h +3 -1
@@ -90,6 +90,8 @@#define WACOM_HID_SP_DIGITIZERINFO 0x00100000#define WACOM_HID_WD_DIGITIZER (WACOM_HID_UP_WACOMDIGITIZER | 0x01)#define WACOM_HID_WD_SENSE (WACOM_HID_UP_WACOMDIGITIZER | 0x36) +#define WACOM_HID_WD_SERIALHI (WACOM_HID_UP_WACOMDIGITIZER | 0x5c) +#define WACOM_HID_WD_TOOLTYPE (WACOM_HID_UP_WACOMDIGITIZER | 0x77)#define WACOM_HID_WD_DISTANCE (WACOM_HID_UP_WACOMDIGITIZER | 0x0132)#define WACOM_HID_WD_FINGERWHEEL (WACOM_HID_UP_WACOMDIGITIZER | 0x0d03)#define WACOM_HID_WD_DATAMODE (WACOM_HID_UP_WACOMDIGITIZER | 0x1002)
@@ -247,7 +249,7 @@ struct wacom_wac {unsigned char data[WACOM_PKGLEN_MAX ];int tool[2 ];int id[2 ]; -__u32 serial[2 ]; +__u64 serial[2 ];bool reporting_data;struct wacom_features features;struct wacom_shared *shared;
Signature · 1 line
2.10.0
PATCH 13/19 HID: wacom: generic: Pass 'hdev' to 'wacom_map_usage'
In reply to Jason GereckeIn the following "Add support for sensor offsets" patch we'll need access to the 'features' struct within 'wacom_map_usage', so update the function signature and calls to include a reference to the HID device so this can be done.
--- drivers/hid/wacom_wac.c | 53 ++++++++++++++++++++++++++----------------------- 1 file changed, 28 insertions(+), 25 deletions(-)
drivers/hid/wacom_wac.c +28 -25
@@ -1465,9 +1465,12 @@ static int wacom_equivalent_usage(int usage)return usage; } -static void wacom_map_usage (struct input_dev *input,struct hid_usage *usage, -struct hid_field *field,__u8 type,__u16 code,int fuzz) +static void wacom_map_usage (struct input_dev *input,struct hid_device *hdev, +struct hid_usage *usage,struct hid_field *field,__u8 type, +__u16 code,int fuzz) { +struct wacom *wacom =hid_get_drvdata (hdev); +struct wacom_wac *wacom_wac = &wacom->wacom_wac;int fmin = field->logical_minimum;int fmax = field->logical_maximum;unsigned int equivalent_usage =wacom_equivalent_usage (usage->hid);
@@ -1508,53 +1511,53 @@ static void wacom_wac_pen_usage_mapping(struct hid_device *hdev,switch (equivalent_usage) {case HID_GD_X : -wacom_map_usage (input, usage, field,EV_ABS ,ABS_X ,4 ); +wacom_map_usage (input, hdev, usage, field,EV_ABS ,ABS_X ,4 );break ;case HID_GD_Y : -wacom_map_usage (input, usage, field,EV_ABS ,ABS_Y ,4 ); +wacom_map_usage (input, hdev, usage, field,EV_ABS ,ABS_Y ,4 );break ;case WACOM_HID_WD_DISTANCE :case HID_GD_Z : -wacom_map_usage (input, usage, field,EV_ABS ,ABS_DISTANCE ,0 ); +wacom_map_usage (input, hdev, usage, field,EV_ABS ,ABS_DISTANCE ,0 );break ;case HID_DG_TIPPRESSURE : -wacom_map_usage (input, usage, field,EV_ABS ,ABS_PRESSURE ,0 ); +wacom_map_usage (input, hdev, usage, field,EV_ABS ,ABS_PRESSURE ,0 );break ;case HID_DG_INRANGE : -wacom_map_usage (input, usage, field,EV_KEY ,BTN_TOOL_PEN ,0 ); +wacom_map_usage (input, hdev, usage, field,EV_KEY ,BTN_TOOL_PEN ,0 );break ;case HID_DG_INVERT : -wacom_map_usage (input, usage, field,EV_KEY , +wacom_map_usage (input, hdev, usage, field,EV_KEY ,BTN_TOOL_RUBBER ,0 );break ;case HID_DG_TILT_X : -wacom_map_usage (input, usage, field,EV_ABS ,ABS_TILT_X ,0 ); +wacom_map_usage (input, hdev, usage, field,EV_ABS ,ABS_TILT_X ,0 );break ;case HID_DG_TILT_Y : -wacom_map_usage (input, usage, field,EV_ABS ,ABS_TILT_Y ,0 ); +wacom_map_usage (input, hdev, usage, field,EV_ABS ,ABS_TILT_Y ,0 );break ;case HID_DG_TWIST : -wacom_map_usage (input, usage, field,EV_ABS ,ABS_Z ,0 ); +wacom_map_usage (input, hdev, usage, field,EV_ABS ,ABS_Z ,0 );break ;case HID_DG_ERASER :case HID_DG_TIPSWITCH : -wacom_map_usage (input, usage, field,EV_KEY ,BTN_TOUCH ,0 ); +wacom_map_usage (input, hdev, usage, field,EV_KEY ,BTN_TOUCH ,0 );break ;case HID_DG_BARRELSWITCH : -wacom_map_usage (input, usage, field,EV_KEY ,BTN_STYLUS ,0 ); +wacom_map_usage (input, hdev, usage, field,EV_KEY ,BTN_STYLUS ,0 );break ;case HID_DG_BARRELSWITCH2 : -wacom_map_usage (input, usage, field,EV_KEY ,BTN_STYLUS2 ,0 ); +wacom_map_usage (input, hdev, usage, field,EV_KEY ,BTN_STYLUS2 ,0 );break ;case HID_DG_TOOLSERIALNUMBER : -wacom_map_usage (input, usage, field,EV_MSC ,MSC_SERIAL ,0 ); +wacom_map_usage (input, hdev, usage, field,EV_MSC ,MSC_SERIAL ,0 );break ;case WACOM_HID_WD_SENSE : features->quirks |=WACOM_QUIRK_SENSE ; -wacom_map_usage (input, usage, field,EV_KEY ,BTN_TOOL_PEN ,0 ); +wacom_map_usage (input, hdev, usage, field,EV_KEY ,BTN_TOOL_PEN ,0 );break ;case WACOM_HID_WD_SERIALHI : -wacom_map_usage (input, usage, field,EV_ABS ,ABS_MISC ,0 ); +wacom_map_usage (input, hdev, usage, field,EV_ABS ,ABS_MISC ,0 );set_bit (EV_KEY , input->evbit);input_set_capability (input,EV_KEY ,BTN_TOOL_PEN );input_set_capability (input,EV_KEY ,BTN_TOOL_RUBBER );
@@ -1565,7 +1568,7 @@ static void wacom_wac_pen_usage_mapping(struct hid_device *hdev,input_set_capability (input,EV_KEY ,BTN_TOOL_LENS );break ;case WACOM_HID_WD_FINGERWHEEL : -wacom_map_usage (input, usage, field,EV_ABS ,ABS_WHEEL ,0 ); +wacom_map_usage (input, hdev, usage, field,EV_ABS ,ABS_WHEEL ,0 );break ; } }
@@ -1722,24 +1725,24 @@ static void wacom_wac_finger_usage_mapping(struct hid_device *hdev,case HID_GD_X : features->last_slot_field = usage->hid;if (touch_max ==1 ) -wacom_map_usage (input, usage, field,EV_ABS ,ABS_X ,4 ); +wacom_map_usage (input, hdev, usage, field,EV_ABS ,ABS_X ,4 );else -wacom_map_usage (input, usage, field,EV_ABS , +wacom_map_usage (input, hdev, usage, field,EV_ABS ,ABS_MT_POSITION_X ,4 );break ;case HID_GD_Y : features->last_slot_field = usage->hid;if (touch_max ==1 ) -wacom_map_usage (input, usage, field,EV_ABS ,ABS_Y ,4 ); +wacom_map_usage (input, hdev, usage, field,EV_ABS ,ABS_Y ,4 );else -wacom_map_usage (input, usage, field,EV_ABS , +wacom_map_usage (input, hdev, usage, field,EV_ABS ,ABS_MT_POSITION_Y ,4 );break ;case HID_DG_WIDTH :case HID_DG_HEIGHT : features->last_slot_field = usage->hid; -wacom_map_usage (input, usage, field,EV_ABS ,ABS_MT_TOUCH_MAJOR ,0 ); -wacom_map_usage (input, usage, field,EV_ABS ,ABS_MT_TOUCH_MINOR ,0 ); +wacom_map_usage (input, hdev, usage, field,EV_ABS ,ABS_MT_TOUCH_MAJOR ,0 ); +wacom_map_usage (input, hdev, usage, field,EV_ABS ,ABS_MT_TOUCH_MINOR ,0 );input_set_abs_params (input,ABS_MT_ORIENTATION ,0 ,1 ,0 ,0 );break ;case HID_DG_CONTACTID :
@@ -1753,7 +1756,7 @@ static void wacom_wac_finger_usage_mapping(struct hid_device *hdev,break ;case HID_DG_TIPSWITCH : features->last_slot_field = usage->hid; -wacom_map_usage (input, usage, field,EV_KEY ,BTN_TOUCH ,0 ); +wacom_map_usage (input, hdev, usage, field,EV_KEY ,BTN_TOUCH ,0 );break ;case HID_DG_CONTACTCOUNT : wacom_wac->hid_data.cc_report = field->report->id;
Signature · 1 line
2.10.0
Re: [PATCH 13/19] HID: wacom: generic: Pass 'hdev' to 'wacom_map_usage'
Quoted 15 lines · Jason Gerecke
In the following "Add support for sensor offsets" patch we'll need access to the 'features' struct within '
wacom_map_usage', so update the function signature and calls to include a reference to the HID device so this can be done.Signed-off-by Jason Gerecke <[email protected]>--- drivers/hid/wacom_wac.c | 53 ++++++++++++++++++++++++++----------------------- 1 file changed, 28 insertions(+), 25 deletions(-)drivers/hid/wacom_wac.c +0
-0
drivers/hid/wacom_wac.c static int wacom_equivalent_usage(int usage) · line 1472
Quoted 10 lines
drivers/hid/wacom_wac.c +4
-2@@ -1465,9 +1465,12 @@ static int wacom_equivalent_usage(int usage)return usage; } -static void wacom_map_usage (struct input_dev *input,struct hid_usage *usage, -struct hid_field *field,__u8 type,__u16 code,int fuzz) +static void wacom_map_usage (struct input_dev *input,struct hid_device *hdev, +struct hid_usage *usage,struct hid_field *field,__u8 type, +__u16 code,int fuzz) { +struct wacom *wacom =hid_get_drvdata (hdev);
This might not be entirely relevant, but given the inputs are created through wacom_allocate_input() and struct wacom * being stored in the driver data, a simple call to input_get_drvdata(input) would provide the struct wacom. Then from here, the hid_device can be retrieved from struct wacom directly.
So I don't know if it's worth resending the series just for this and if this has caveats... (my rev-by still applies).
Cheers,
Benjamin
Quoted 125 lines
drivers/hid/wacom_wac.c +24
-23+struct wacom_wac *wacom_wac = &wacom->wacom_wac;int fmin = field->logical_minimum;int fmax = field->logical_maximum;unsigned int equivalent_usage =wacom_equivalent_usage (usage->hid);@@ -1508,53 +1511,53 @@ static void wacom_wac_pen_usage_mapping(struct hid_device *hdev,switch (equivalent_usage) {case HID_GD_X : -wacom_map_usage (input, usage, field,EV_ABS ,ABS_X ,4 ); +wacom_map_usage (input, hdev, usage, field,EV_ABS ,ABS_X ,4 );break ;case HID_GD_Y : -wacom_map_usage (input, usage, field,EV_ABS ,ABS_Y ,4 ); +wacom_map_usage (input, hdev, usage, field,EV_ABS ,ABS_Y ,4 );break ;case WACOM_HID_WD_DISTANCE :case HID_GD_Z : -wacom_map_usage (input, usage, field,EV_ABS ,ABS_DISTANCE ,0 ); +wacom_map_usage (input, hdev, usage, field,EV_ABS ,ABS_DISTANCE ,0 );break ;case HID_DG_TIPPRESSURE : -wacom_map_usage (input, usage, field,EV_ABS ,ABS_PRESSURE ,0 ); +wacom_map_usage (input, hdev, usage, field,EV_ABS ,ABS_PRESSURE ,0 );break ;case HID_DG_INRANGE : -wacom_map_usage (input, usage, field,EV_KEY ,BTN_TOOL_PEN ,0 ); +wacom_map_usage (input, hdev, usage, field,EV_KEY ,BTN_TOOL_PEN ,0 );break ;case HID_DG_INVERT : -wacom_map_usage (input, usage, field,EV_KEY , +wacom_map_usage (input, hdev, usage, field,EV_KEY ,BTN_TOOL_RUBBER ,0 );break ;case HID_DG_TILT_X : -wacom_map_usage (input, usage, field,EV_ABS ,ABS_TILT_X ,0 ); +wacom_map_usage (input, hdev, usage, field,EV_ABS ,ABS_TILT_X ,0 );break ;case HID_DG_TILT_Y : -wacom_map_usage (input, usage, field,EV_ABS ,ABS_TILT_Y ,0 ); +wacom_map_usage (input, hdev, usage, field,EV_ABS ,ABS_TILT_Y ,0 );break ;case HID_DG_TWIST : -wacom_map_usage (input, usage, field,EV_ABS ,ABS_Z ,0 ); +wacom_map_usage (input, hdev, usage, field,EV_ABS ,ABS_Z ,0 );break ;case HID_DG_ERASER :case HID_DG_TIPSWITCH : -wacom_map_usage (input, usage, field,EV_KEY ,BTN_TOUCH ,0 ); +wacom_map_usage (input, hdev, usage, field,EV_KEY ,BTN_TOUCH ,0 );break ;case HID_DG_BARRELSWITCH : -wacom_map_usage (input, usage, field,EV_KEY ,BTN_STYLUS ,0 ); +wacom_map_usage (input, hdev, usage, field,EV_KEY ,BTN_STYLUS ,0 );break ;case HID_DG_BARRELSWITCH2 : -wacom_map_usage (input, usage, field,EV_KEY ,BTN_STYLUS2 ,0 ); +wacom_map_usage (input, hdev, usage, field,EV_KEY ,BTN_STYLUS2 ,0 );break ;case HID_DG_TOOLSERIALNUMBER : -wacom_map_usage (input, usage, field,EV_MSC ,MSC_SERIAL ,0 ); +wacom_map_usage (input, hdev, usage, field,EV_MSC ,MSC_SERIAL ,0 );break ;case WACOM_HID_WD_SENSE : features->quirks |=WACOM_QUIRK_SENSE ; -wacom_map_usage (input, usage, field,EV_KEY ,BTN_TOOL_PEN ,0 ); +wacom_map_usage (input, hdev, usage, field,EV_KEY ,BTN_TOOL_PEN ,0 );break ;case WACOM_HID_WD_SERIALHI : -wacom_map_usage (input, usage, field,EV_ABS ,ABS_MISC ,0 ); +wacom_map_usage (input, hdev, usage, field,EV_ABS ,ABS_MISC ,0 );set_bit (EV_KEY , input->evbit);input_set_capability (input,EV_KEY ,BTN_TOOL_PEN );input_set_capability (input,EV_KEY ,BTN_TOOL_RUBBER );@@ -1565,7 +1568,7 @@ static void wacom_wac_pen_usage_mapping(struct hid_device *hdev,input_set_capability (input,EV_KEY ,BTN_TOOL_LENS );break ;case WACOM_HID_WD_FINGERWHEEL : -wacom_map_usage (input, usage, field,EV_ABS ,ABS_WHEEL ,0 ); +wacom_map_usage (input, hdev, usage, field,EV_ABS ,ABS_WHEEL ,0 );break ; } }@@ -1722,24 +1725,24 @@ static void wacom_wac_finger_usage_mapping(struct hid_device *hdev,case HID_GD_X : features->last_slot_field = usage->hid;if (touch_max ==1 ) -wacom_map_usage (input, usage, field,EV_ABS ,ABS_X ,4 ); +wacom_map_usage (input, hdev, usage, field,EV_ABS ,ABS_X ,4 );else -wacom_map_usage (input, usage, field,EV_ABS , +wacom_map_usage (input, hdev, usage, field,EV_ABS ,ABS_MT_POSITION_X ,4 );break ;case HID_GD_Y : features->last_slot_field = usage->hid;if (touch_max ==1 ) -wacom_map_usage (input, usage, field,EV_ABS ,ABS_Y ,4 ); +wacom_map_usage (input, hdev, usage, field,EV_ABS ,ABS_Y ,4 );else -wacom_map_usage (input, usage, field,EV_ABS , +wacom_map_usage (input, hdev, usage, field,EV_ABS ,ABS_MT_POSITION_Y ,4 );break ;case HID_DG_WIDTH :case HID_DG_HEIGHT : features->last_slot_field = usage->hid; -wacom_map_usage (input, usage, field,EV_ABS ,ABS_MT_TOUCH_MAJOR ,0 ); -wacom_map_usage (input, usage, field,EV_ABS ,ABS_MT_TOUCH_MINOR ,0 ); +wacom_map_usage (input, hdev, usage, field,EV_ABS ,ABS_MT_TOUCH_MAJOR ,0 ); +wacom_map_usage (input, hdev, usage, field,EV_ABS ,ABS_MT_TOUCH_MINOR ,0 );input_set_abs_params (input,ABS_MT_ORIENTATION ,0 ,1 ,0 ,0 );break ;case HID_DG_CONTACTID :@@ -1753,7 +1756,7 @@ static void wacom_wac_finger_usage_mapping(struct hid_device *hdev,break ;case HID_DG_TIPSWITCH : features->last_slot_field = usage->hid; -wacom_map_usage (input, usage, field,EV_KEY ,BTN_TOUCH ,0 ); +wacom_map_usage (input, hdev, usage, field,EV_KEY ,BTN_TOUCH ,0 );break ;case HID_DG_CONTACTCOUNT : wacom_wac->hid_data.cc_report = field->report->id;Signature · 1 line
2.10.0
Re: [PATCH 13/19] HID: wacom: generic: Pass 'hdev' to 'wacom_map_usage'
Quoted 33 lines · Benjamin Tissoires
Quoted 15 lines · Jason Gerecke
In the following "Add support for sensor offsets" patch we'll need access to the 'features' struct within '
wacom_map_usage', so update the function signature and calls to include a reference to the HID device so this can be done.Signed-off-by Jason Gerecke <[email protected]>--- drivers/hid/wacom_wac.c | 53 ++++++++++++++++++++++++++----------------------- 1 file changed, 28 insertions(+), 25 deletions(-)drivers/hid/wacom_wac.c +0
-0drivers/hid/wacom_wac.c static int wacom_equivalent_usage(int usage) · line 1472
Quoted 10 lines
drivers/hid/wacom_wac.c +4
-2@@ -1465,9 +1465,12 @@ static int wacom_equivalent_usage(int usage)return usage; } -static void wacom_map_usage (struct input_dev *input,struct hid_usage *usage, -struct hid_field *field,__u8 type,__u16 code,int fuzz) +static void wacom_map_usage (struct input_dev *input,struct hid_device *hdev, +struct hid_usage *usage,struct hid_field *field,__u8 type, +__u16 code,int fuzz) { +struct wacom *wacom =hid_get_drvdata (hdev);This might not be entirely relevant, but given the inputs are created through
wacom_allocate_input()and struct wacom * being stored in the driver data, a simple call toinput_get_drvdata(input)would provide the struct wacom. Then from here, thehid_devicecan be retrieved from struct wacom directly.
Quoted 6 lines
So I don't know if it's worth resending the series just for this and if this has caveats... (my rev-by still applies).
Cheers,
Benjamin
I'd be happy with dropping this patch and using input_get_drvdata instead. I hadn't remotely considered that we could access the wacom structure from there as well. As noisy as it might be, I'll send a V2 with your rev-by and the change.
Jason
---
Now instead of four in the eights place /
you’ve got three, ‘Cause you added one /
(That is to say, eight) to the two, /
But you can’t take seven from three, /
So you look at the sixty-fours....
Quoted 125 lines
Quoted 125 lines
drivers/hid/wacom_wac.c +24
-23+struct wacom_wac *wacom_wac = &wacom->wacom_wac;int fmin = field->logical_minimum;int fmax = field->logical_maximum;unsigned int equivalent_usage =wacom_equivalent_usage (usage->hid);@@ -1508,53 +1511,53 @@ static void wacom_wac_pen_usage_mapping(struct hid_device *hdev,switch (equivalent_usage) {case HID_GD_X : -wacom_map_usage (input, usage, field,EV_ABS ,ABS_X ,4 ); +wacom_map_usage (input, hdev, usage, field,EV_ABS ,ABS_X ,4 );break ;case HID_GD_Y : -wacom_map_usage (input, usage, field,EV_ABS ,ABS_Y ,4 ); +wacom_map_usage (input, hdev, usage, field,EV_ABS ,ABS_Y ,4 );break ;case WACOM_HID_WD_DISTANCE :case HID_GD_Z : -wacom_map_usage (input, usage, field,EV_ABS ,ABS_DISTANCE ,0 ); +wacom_map_usage (input, hdev, usage, field,EV_ABS ,ABS_DISTANCE ,0 );break ;case HID_DG_TIPPRESSURE : -wacom_map_usage (input, usage, field,EV_ABS ,ABS_PRESSURE ,0 ); +wacom_map_usage (input, hdev, usage, field,EV_ABS ,ABS_PRESSURE ,0 );break ;case HID_DG_INRANGE : -wacom_map_usage (input, usage, field,EV_KEY ,BTN_TOOL_PEN ,0 ); +wacom_map_usage (input, hdev, usage, field,EV_KEY ,BTN_TOOL_PEN ,0 );break ;case HID_DG_INVERT : -wacom_map_usage (input, usage, field,EV_KEY , +wacom_map_usage (input, hdev, usage, field,EV_KEY ,BTN_TOOL_RUBBER ,0 );break ;case HID_DG_TILT_X : -wacom_map_usage (input, usage, field,EV_ABS ,ABS_TILT_X ,0 ); +wacom_map_usage (input, hdev, usage, field,EV_ABS ,ABS_TILT_X ,0 );break ;case HID_DG_TILT_Y : -wacom_map_usage (input, usage, field,EV_ABS ,ABS_TILT_Y ,0 ); +wacom_map_usage (input, hdev, usage, field,EV_ABS ,ABS_TILT_Y ,0 );break ;case HID_DG_TWIST : -wacom_map_usage (input, usage, field,EV_ABS ,ABS_Z ,0 ); +wacom_map_usage (input, hdev, usage, field,EV_ABS ,ABS_Z ,0 );break ;case HID_DG_ERASER :case HID_DG_TIPSWITCH : -wacom_map_usage (input, usage, field,EV_KEY ,BTN_TOUCH ,0 ); +wacom_map_usage (input, hdev, usage, field,EV_KEY ,BTN_TOUCH ,0 );break ;case HID_DG_BARRELSWITCH : -wacom_map_usage (input, usage, field,EV_KEY ,BTN_STYLUS ,0 ); +wacom_map_usage (input, hdev, usage, field,EV_KEY ,BTN_STYLUS ,0 );break ;case HID_DG_BARRELSWITCH2 : -wacom_map_usage (input, usage, field,EV_KEY ,BTN_STYLUS2 ,0 ); +wacom_map_usage (input, hdev, usage, field,EV_KEY ,BTN_STYLUS2 ,0 );break ;case HID_DG_TOOLSERIALNUMBER : -wacom_map_usage (input, usage, field,EV_MSC ,MSC_SERIAL ,0 ); +wacom_map_usage (input, hdev, usage, field,EV_MSC ,MSC_SERIAL ,0 );break ;case WACOM_HID_WD_SENSE : features->quirks |=WACOM_QUIRK_SENSE ; -wacom_map_usage (input, usage, field,EV_KEY ,BTN_TOOL_PEN ,0 ); +wacom_map_usage (input, hdev, usage, field,EV_KEY ,BTN_TOOL_PEN ,0 );break ;case WACOM_HID_WD_SERIALHI : -wacom_map_usage (input, usage, field,EV_ABS ,ABS_MISC ,0 ); +wacom_map_usage (input, hdev, usage, field,EV_ABS ,ABS_MISC ,0 );set_bit (EV_KEY , input->evbit);input_set_capability (input,EV_KEY ,BTN_TOOL_PEN );input_set_capability (input,EV_KEY ,BTN_TOOL_RUBBER );@@ -1565,7 +1568,7 @@ static void wacom_wac_pen_usage_mapping(struct hid_device *hdev,input_set_capability (input,EV_KEY ,BTN_TOOL_LENS );break ;case WACOM_HID_WD_FINGERWHEEL : -wacom_map_usage (input, usage, field,EV_ABS ,ABS_WHEEL ,0 ); +wacom_map_usage (input, hdev, usage, field,EV_ABS ,ABS_WHEEL ,0 );break ; } }@@ -1722,24 +1725,24 @@ static void wacom_wac_finger_usage_mapping(struct hid_device *hdev,case HID_GD_X : features->last_slot_field = usage->hid;if (touch_max ==1 ) -wacom_map_usage (input, usage, field,EV_ABS ,ABS_X ,4 ); +wacom_map_usage (input, hdev, usage, field,EV_ABS ,ABS_X ,4 );else -wacom_map_usage (input, usage, field,EV_ABS , +wacom_map_usage (input, hdev, usage, field,EV_ABS ,ABS_MT_POSITION_X ,4 );break ;case HID_GD_Y : features->last_slot_field = usage->hid;if (touch_max ==1 ) -wacom_map_usage (input, usage, field,EV_ABS ,ABS_Y ,4 ); +wacom_map_usage (input, hdev, usage, field,EV_ABS ,ABS_Y ,4 );else -wacom_map_usage (input, usage, field,EV_ABS , +wacom_map_usage (input, hdev, usage, field,EV_ABS ,ABS_MT_POSITION_Y ,4 );break ;case HID_DG_WIDTH :case HID_DG_HEIGHT : features->last_slot_field = usage->hid; -wacom_map_usage (input, usage, field,EV_ABS ,ABS_MT_TOUCH_MAJOR ,0 ); -wacom_map_usage (input, usage, field,EV_ABS ,ABS_MT_TOUCH_MINOR ,0 ); +wacom_map_usage (input, hdev, usage, field,EV_ABS ,ABS_MT_TOUCH_MAJOR ,0 ); +wacom_map_usage (input, hdev, usage, field,EV_ABS ,ABS_MT_TOUCH_MINOR ,0 );input_set_abs_params (input,ABS_MT_ORIENTATION ,0 ,1 ,0 ,0 );break ;case HID_DG_CONTACTID :@@ -1753,7 +1756,7 @@ static void wacom_wac_finger_usage_mapping(struct hid_device *hdev,break ;case HID_DG_TIPSWITCH : features->last_slot_field = usage->hid; -wacom_map_usage (input, usage, field,EV_KEY ,BTN_TOUCH ,0 ); +wacom_map_usage (input, hdev, usage, field,EV_KEY ,BTN_TOUCH ,0 );break ;case HID_DG_CONTACTCOUNT : wacom_wac->hid_data.cc_report = field->report->id;Signature · 1 line
2.10.0
PATCH 14/19 HID: wacom: Fix sensor outbounds and redefine as offsets from each edge
In reply to Jason GereckeMany of Wacom's display tablets include an "outbound" area where pen digitizing is possible but outside of the display area. To ensure that pen coordinates are mapped to the correct on-screen location, the driver sets the minimum and maximum axis values of X and Y to those coordinates which coincide with the screen edge. These values are simply the hardware minimum/maximum plus/minus the outbound size for a particular edge.
When outbound support was added/updated in ac414da, fa77034, and ecd618d, we decided to have the wacom_features structs store the desired minimum and maximum values directly. In hindsight, this was perhaps not the best choice since it has allowed minor errors to crop up unnoticed. Some tablets have had their coordinates over-corrected (e.g. most of the devices "fixed" in ecd618d were already adjusted in ac414da), while others never had a correction applied (e.g. the ISDv5 325, whose declared maximum the hardware maximum instead of the outbound maximum).
A less error-prone method of handling the outbound is to let the driver calculate the correct minimum/maximum values by providing it with both the actual hardware maximums and the size of the outbound on each edge. These values are more easy to verify as correct since the values can be trivially compared against specifications.
This patch reverts the declared maximum values to the actual hardware maximums, e.g. as declared prior to ac414da (values for these and other display tablets that were subsuquently introduced have been verified against specs). Per-edge outbound sizes are stored in the wacom_features struct as offset_{left,right,top,bottom} and used in combination with the hardware ranges to calculate effective axis ranges for ABS_X and ABS_Y.
--- drivers/hid/wacom_wac.c | 62 ++++++++++++++++++++++++++++++++----------------- drivers/hid/wacom_wac.h | 6 +++-- 2 files changed, 45 insertions(+), 23 deletions(-)
drivers/hid/wacom_wac.c +41 -21
@@ -2687,10 +2687,12 @@ int wacom_setup_pen_input_capabilities(struct input_dev *input_dev,__set_bit (BTN_TOUCH , input_dev->keybit);__set_bit (ABS_MISC , input_dev->absbit); -input_set_abs_params (input_dev,ABS_X , features->x_min, - features->x_max, features->x_fuzz,0 ); -input_set_abs_params (input_dev,ABS_Y , features->y_min, - features->y_max, features->y_fuzz,0 ); +input_set_abs_params (input_dev,ABS_X ,0 + features->offset_left, + features->x_max - features->offset_right, + features->x_fuzz,0 ); +input_set_abs_params (input_dev,ABS_Y ,0 + features->offset_top, + features->y_max - features->offset_bottom, + features->y_fuzz,0 );input_set_abs_params (input_dev,ABS_PRESSURE ,0 , features->pressure_max, features->pressure_fuzz,0 );
@@ -3402,26 +3404,30 @@ static const struct wacom_features wacom_features_0x317 = INTUOSPL, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 9, .touch_max = 16, .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE };static const struct wacom_features wacom_features_0xF4 = - {"Wacom Cintiq 24HD" ,104080 ,65200 ,2047 ,63 , + {"Wacom Cintiq 24HD" ,104480 ,65600 ,2047 ,63 ,WACOM_24HD ,WACOM_INTUOS3_RES ,WACOM_INTUOS3_RES ,16 , +WACOM_CINTIQ_OFFSET ,WACOM_CINTIQ_OFFSET ,WACOM_CINTIQ_OFFSET ,WACOM_CINTIQ_OFFSET };static const struct wacom_features wacom_features_0xF8 = - {"Wacom Cintiq 24HD touch" ,104080 ,65200 ,2047 ,63 ,/* Pen */ + {"Wacom Cintiq 24HD touch" ,104480 ,65600 ,2047 ,63 ,/* Pen */ WACOM_24HD ,WACOM_INTUOS3_RES ,WACOM_INTUOS3_RES ,16 ,WACOM_CINTIQ_OFFSET ,WACOM_CINTIQ_OFFSET , +WACOM_CINTIQ_OFFSET ,WACOM_CINTIQ_OFFSET , .oVid =USB_VENDOR_ID_WACOM , .oPid =0xf6 };static const struct wacom_features wacom_features_0xF6 = {"Wacom Cintiq 24HD touch" , .type =WACOM_24HDT ,/* Touch */ .oVid =USB_VENDOR_ID_WACOM , .oPid =0xf8 , .touch_max =10 , .check_for_hid_type = true, .hid_type =HID_TYPE_USBNONE };static const struct wacom_features wacom_features_0x32A = - {"Wacom Cintiq 27QHD" ,119740 ,67520 ,2047 ,63 , + {"Wacom Cintiq 27QHD" ,120140 ,67920 ,2047 ,63 ,WACOM_27QHD ,WACOM_INTUOS3_RES ,WACOM_INTUOS3_RES ,0 , +WACOM_CINTIQ_OFFSET ,WACOM_CINTIQ_OFFSET ,WACOM_CINTIQ_OFFSET ,WACOM_CINTIQ_OFFSET };static const struct wacom_features wacom_features_0x32B = - {"Wacom Cintiq 27QHD touch" ,119740 ,67520 ,2047 ,63 , + {"Wacom Cintiq 27QHD touch" ,120140 ,67920 ,2047 ,63 ,WACOM_27QHD ,WACOM_INTUOS3_RES ,WACOM_INTUOS3_RES ,0 ,WACOM_CINTIQ_OFFSET ,WACOM_CINTIQ_OFFSET , +WACOM_CINTIQ_OFFSET ,WACOM_CINTIQ_OFFSET , .oVid =USB_VENDOR_ID_WACOM , .oPid =0x32C };static const struct wacom_features wacom_features_0x32C = {"Wacom Cintiq 27QHD touch" , .type =WACOM_27QHDT ,
@@ -3436,13 +3442,15 @@ static const struct wacom_features wacom_features_0xC6 = {"Wacom Cintiq 12WX" ,53020 ,33440 ,1023 ,63 , WACOM_BEE, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 10 };static const struct wacom_features wacom_features_0x304 = - {"Wacom Cintiq 13HD" ,59152 ,33448 ,1023 ,63 , + {"Wacom Cintiq 13HD" ,59552 ,33848 ,1023 ,63 ,WACOM_13HD ,WACOM_INTUOS3_RES ,WACOM_INTUOS3_RES ,9 , +WACOM_CINTIQ_OFFSET ,WACOM_CINTIQ_OFFSET ,WACOM_CINTIQ_OFFSET ,WACOM_CINTIQ_OFFSET };static const struct wacom_features wacom_features_0x333 = - {"Wacom Cintiq 13HD touch" ,59152 ,33448 ,2047 ,63 , + {"Wacom Cintiq 13HD touch" ,59552 ,33848 ,2047 ,63 ,WACOM_13HD ,WACOM_INTUOS3_RES ,WACOM_INTUOS3_RES ,9 ,WACOM_CINTIQ_OFFSET ,WACOM_CINTIQ_OFFSET , +WACOM_CINTIQ_OFFSET ,WACOM_CINTIQ_OFFSET , .oVid =USB_VENDOR_ID_WACOM , .oPid =0x335 };static const struct wacom_features wacom_features_0x335 = { "Wacom Cintiq 13HD touch", .type = WACOM_24HDT, /* Touch */
@@ -3459,42 +3467,50 @@ static const struct wacom_features wacom_features_0xF0 = {"Wacom DTU1631" ,34623 ,19553 ,511 ,0 , DTU, WACOM_INTUOS_RES, WACOM_INTUOS_RES };static const struct wacom_features wacom_features_0xFB = - {"Wacom DTU1031" ,21896 ,13760 ,511 ,0 , + {"Wacom DTU1031" ,22096 ,13960 ,511 ,0 ,DTUS ,WACOM_INTUOS_RES ,WACOM_INTUOS_RES ,4 , +WACOM_DTU_OFFSET ,WACOM_DTU_OFFSET ,WACOM_DTU_OFFSET ,WACOM_DTU_OFFSET };static const struct wacom_features wacom_features_0x32F = - {"Wacom DTU1031X" ,22472 ,12728 ,511 ,0 , + {"Wacom DTU1031X" ,22672 ,12928 ,511 ,0 ,DTUSX ,WACOM_INTUOS_RES ,WACOM_INTUOS_RES ,0 , +WACOM_DTU_OFFSET ,WACOM_DTU_OFFSET ,WACOM_DTU_OFFSET ,WACOM_DTU_OFFSET };static const struct wacom_features wacom_features_0x336 = - {"Wacom DTU1141" ,23472 ,13203 ,1023 ,0 , + {"Wacom DTU1141" ,23672 ,13403 ,1023 ,0 ,DTUS ,WACOM_INTUOS_RES ,WACOM_INTUOS_RES ,4 , +WACOM_DTU_OFFSET ,WACOM_DTU_OFFSET ,WACOM_DTU_OFFSET ,WACOM_DTU_OFFSET };static const struct wacom_features wacom_features_0x57 = - {"Wacom DTK2241" ,95640 ,54060 ,2047 ,63 , + {"Wacom DTK2241" ,95840 ,54260 ,2047 ,63 ,DTK ,WACOM_INTUOS3_RES ,WACOM_INTUOS3_RES ,6 , +WACOM_CINTIQ_OFFSET ,WACOM_CINTIQ_OFFSET ,WACOM_CINTIQ_OFFSET ,WACOM_CINTIQ_OFFSET };static const struct wacom_features wacom_features_0x59 =/* Pen */ - {"Wacom DTH2242" ,95640 ,54060 ,2047 ,63 , + {"Wacom DTH2242" ,95840 ,54260 ,2047 ,63 ,DTK ,WACOM_INTUOS3_RES ,WACOM_INTUOS3_RES ,6 ,WACOM_CINTIQ_OFFSET ,WACOM_CINTIQ_OFFSET , +WACOM_CINTIQ_OFFSET ,WACOM_CINTIQ_OFFSET , .oVid =USB_VENDOR_ID_WACOM , .oPid =0x5D };static const struct wacom_features wacom_features_0x5D =/* Touch */ {"Wacom DTH2242" , .type =WACOM_24HDT , .oVid =USB_VENDOR_ID_WACOM , .oPid =0x59 , .touch_max =10 , .check_for_hid_type = true, .hid_type =HID_TYPE_USBNONE };static const struct wacom_features wacom_features_0xCC = - {"Wacom Cintiq 21UX2" ,86800 ,65200 ,2047 ,63 , + {"Wacom Cintiq 21UX2" ,87200 ,65600 ,2047 ,63 ,WACOM_21UX2 ,WACOM_INTUOS3_RES ,WACOM_INTUOS3_RES ,18 , +WACOM_CINTIQ_OFFSET ,WACOM_CINTIQ_OFFSET ,WACOM_CINTIQ_OFFSET ,WACOM_CINTIQ_OFFSET };static const struct wacom_features wacom_features_0xFA = - {"Wacom Cintiq 22HD" ,95440 ,53860 ,2047 ,63 , + {"Wacom Cintiq 22HD" ,95840 ,54260 ,2047 ,63 ,WACOM_22HD ,WACOM_INTUOS3_RES ,WACOM_INTUOS3_RES ,18 , +WACOM_CINTIQ_OFFSET ,WACOM_CINTIQ_OFFSET ,WACOM_CINTIQ_OFFSET ,WACOM_CINTIQ_OFFSET };static const struct wacom_features wacom_features_0x5B = - {"Wacom Cintiq 22HDT" ,95440 ,53860 ,2047 ,63 , + {"Wacom Cintiq 22HDT" ,95840 ,54260 ,2047 ,63 ,WACOM_22HD ,WACOM_INTUOS3_RES ,WACOM_INTUOS3_RES ,18 ,WACOM_CINTIQ_OFFSET ,WACOM_CINTIQ_OFFSET , +WACOM_CINTIQ_OFFSET ,WACOM_CINTIQ_OFFSET , .oVid =USB_VENDOR_ID_WACOM , .oPid =0x5e };static const struct wacom_features wacom_features_0x5E = { "Wacom Cintiq 22HDT", .type = WACOM_24HDT,
@@ -3638,18 +3654,20 @@ static const struct wacom_features wacom_features_0x6004 = {"ISD-V4" ,12800 ,8000 ,255 ,0 , TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };static const struct wacom_features wacom_features_0x307 = - {"Wacom ISDv5 307" ,59152 ,33448 ,2047 ,63 , + {"Wacom ISDv5 307" ,59552 ,33848 ,2047 ,63 ,CINTIQ_HYBRID ,WACOM_INTUOS3_RES ,WACOM_INTUOS3_RES ,9 ,WACOM_CINTIQ_OFFSET ,WACOM_CINTIQ_OFFSET , +WACOM_CINTIQ_OFFSET ,WACOM_CINTIQ_OFFSET , .oVid =USB_VENDOR_ID_WACOM , .oPid =0x309 };static const struct wacom_features wacom_features_0x309 = {"Wacom ISDv5 309" , .type =WACOM_24HDT ,/* Touch */ .oVid =USB_VENDOR_ID_WACOM , .oPid =0x0307 , .touch_max =10 , .check_for_hid_type = true, .hid_type =HID_TYPE_USBNONE };static const struct wacom_features wacom_features_0x30A = - {"Wacom ISDv5 30A" ,59152 ,33448 ,2047 ,63 , + {"Wacom ISDv5 30A" ,59552 ,33848 ,2047 ,63 ,CINTIQ_HYBRID ,WACOM_INTUOS3_RES ,WACOM_INTUOS3_RES ,9 ,WACOM_CINTIQ_OFFSET ,WACOM_CINTIQ_OFFSET , +WACOM_CINTIQ_OFFSET ,WACOM_CINTIQ_OFFSET , .oVid =USB_VENDOR_ID_WACOM , .oPid =0x30C };static const struct wacom_features wacom_features_0x30C = { "Wacom ISDv5 30C", .type = WACOM_24HDT, /* Touch */
@@ -3665,6 +3683,7 @@ static const struct wacom_features wacom_features_0x325 = {"Wacom ISDv5 325" ,59552 ,33848 ,2047 ,63 ,CINTIQ_COMPANION_2 ,WACOM_INTUOS3_RES ,WACOM_INTUOS3_RES ,11 ,WACOM_CINTIQ_OFFSET ,WACOM_CINTIQ_OFFSET , +WACOM_CINTIQ_OFFSET ,WACOM_CINTIQ_OFFSET , .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x326 };static const struct wacom_features wacom_features_0x326 =/* Touch */ { "Wacom ISDv5 326", .type = HID_GENERIC, .oVid = USB_VENDOR_ID_WACOM,
@@ -3694,8 +3713,9 @@ static const struct wacom_features wacom_features_0x33E = INTUOSHT2, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 16, .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE };static const struct wacom_features wacom_features_0x343 = - {"Wacom DTK1651" ,34616 ,19559 ,1023 ,0 , + {"Wacom DTK1651" ,34816 ,19759 ,1023 ,0 ,DTUS ,WACOM_INTUOS_RES ,WACOM_INTUOS_RES ,4 , +WACOM_DTU_OFFSET ,WACOM_DTU_OFFSET ,WACOM_DTU_OFFSET ,WACOM_DTU_OFFSET }; static const struct wacom_features wacom_features_HID_ANY_ID =
drivers/hid/wacom_wac.h +4 -2
@@ -181,8 +181,10 @@ struct wacom_features {int x_resolution;int y_resolution;int numbered_buttons; -int x_min; -int y_min; +int offset_left; +int offset_right; +int offset_top; +int offset_bottom;int device_type;int x_phy;int y_phy;
Signature · 1 line
2.10.0
PATCH 15/19 HID: wacom: generic: Add support for sensor offsets
In reply to Jason GereckeMany of Wacom's display tablets include an "outbound" area where pen digitizing is possible but outside of the display area. To accommodate such sensors in the HID_GENERIC codepath, we add support for the necessary vendor-defined HID feature usages and adjust the min/max values of the X and Y axes accordingly, similar to what is done in the non-generic codepath.
--- drivers/hid/wacom_sys.c | 38 ++++++++++++++++++++++++++++++-------- drivers/hid/wacom_wac.c | 38 ++++++++++++++++++++++++++++++++++++++ drivers/hid/wacom_wac.h | 4 ++++ 3 files changed, 72 insertions(+), 8 deletions(-)
drivers/hid/wacom_sys.c +30 -8
@@ -122,6 +122,7 @@ static void wacom_feature_mapping(struct hid_device *hdev,struct hid_data *hid_data = &wacom->wacom_wac.hid_data;u8 *data;int ret; +int n;switch (usage->hid) {case HID_DG_CONTACTMAX :
@@ -180,6 +181,27 @@ static void wacom_feature_mapping(struct hid_device *hdev, wacom->wacom_wac.mode_value =0 ; }break ; +case WACOM_HID_WD_OFFSETLEFT : +case WACOM_HID_WD_OFFSETTOP : +case WACOM_HID_WD_OFFSETRIGHT : +case WACOM_HID_WD_OFFSETBOTTOM : +/* read manually */ + n =hid_report_len (field->report); + data =hid_alloc_report_buf (field->report,GFP_KERNEL ); +if (!data) +break ; + data[0 ] = field->report->id; + ret =wacom_get_report (hdev,HID_FEATURE_REPORT , + data, n,WAC_CMD_RETRIES ); +if (ret == n) { + ret =hid_report_raw_event (hdev,HID_FEATURE_REPORT , + data, n,0 ); + }else { +hid_warn (hdev,"%s: could not retrieve sensor offsets\n" , + __func__); + } +kfree (data); +break ; } }
@@ -718,11 +740,6 @@ static int wacom_add_shared_data(struct hid_device *hdev)return retval; } -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; - out:mutex_unlock (&wacom_udev_list_lock);return retval;
@@ -2019,6 +2036,10 @@ static int wacom_parse_and_register(struct wacom *wacom, bool wireless)if (error) goto fail; + error =wacom_add_shared_data (hdev); +if (error) + goto fail; +/* * Bamboo Pad has a generic hid handling for the Pen, and we switch it * into debug mode for the touch part.
@@ -2059,9 +2080,10 @@ static int wacom_parse_and_register(struct wacom *wacom, bool wireless)wacom_update_name (wacom, wireless ?" (WL)" :"" ); - error =wacom_add_shared_data (hdev); -if (error) - goto fail; +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;if (!(features->device_type &WACOM_DEVICETYPE_WL_MONITOR ) && (features->quirks &WACOM_QUIRK_BATTERY )) {
drivers/hid/wacom_wac.c +38 -0
@@ -1471,6 +1471,7 @@ static void wacom_map_usage(struct input_dev *input, struct hid_device *hdev, {struct wacom *wacom =hid_get_drvdata (hdev);struct wacom_wac *wacom_wac = &wacom->wacom_wac; +struct wacom_features *features = &wacom_wac->features;int fmin = field->logical_minimum;int fmax = field->logical_maximum;unsigned int equivalent_usage =wacom_equivalent_usage (usage->hid);
@@ -1480,6 +1481,15 @@ static void wacom_map_usage(struct input_dev *input, struct hid_device *hdev, resolution_code =ABS_RZ ; } +if (equivalent_usage ==HID_GD_X ) { + fmin += features->offset_left; + fmax -= features->offset_right; + } +if (equivalent_usage ==HID_GD_Y ) { + fmin += features->offset_top; + fmax -= features->offset_bottom; + } + usage->type = type; usage->code = code;
@@ -1632,6 +1642,34 @@ static int wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field,*/ wacom_wac->id[0 ] |= value;return 0 ; +case WACOM_HID_WD_OFFSETLEFT : +if (features->offset_left && value != features->offset_left) +hid_warn (hdev,"%s: overriding exising left offset " +"%d -> %d\n" , __func__, value, + features->offset_left); + features->offset_left = value; +return 0 ; +case WACOM_HID_WD_OFFSETRIGHT : +if (features->offset_right && value != features->offset_right) +hid_warn (hdev,"%s: overriding exising right offset " +"%d -> %d\n" , __func__, value, + features->offset_right); + features->offset_right = value; +return 0 ; +case WACOM_HID_WD_OFFSETTOP : +if (features->offset_top && value != features->offset_top) +hid_warn (hdev,"%s: overriding exising top offset " +"%d -> %d\n" , __func__, value, + features->offset_top); + features->offset_top = value; +return 0 ; +case WACOM_HID_WD_OFFSETBOTTOM : +if (features->offset_bottom && value != features->offset_bottom) +hid_warn (hdev,"%s: overriding exising bottom offset " +"%d -> %d\n" , __func__, value, + features->offset_bottom); + features->offset_bottom = value; +return 0 ; }/* send pen events only when touch is up or forced out
drivers/hid/wacom_wac.h +4 -0
@@ -94,6 +94,10 @@#define WACOM_HID_WD_TOOLTYPE (WACOM_HID_UP_WACOMDIGITIZER | 0x77)#define WACOM_HID_WD_DISTANCE (WACOM_HID_UP_WACOMDIGITIZER | 0x0132)#define WACOM_HID_WD_FINGERWHEEL (WACOM_HID_UP_WACOMDIGITIZER | 0x0d03) +#define WACOM_HID_WD_OFFSETLEFT (WACOM_HID_UP_WACOMDIGITIZER | 0x0d30) +#define WACOM_HID_WD_OFFSETTOP (WACOM_HID_UP_WACOMDIGITIZER | 0x0d31) +#define WACOM_HID_WD_OFFSETRIGHT (WACOM_HID_UP_WACOMDIGITIZER | 0x0d32) +#define WACOM_HID_WD_OFFSETBOTTOM (WACOM_HID_UP_WACOMDIGITIZER | 0x0d33)#define WACOM_HID_WD_DATAMODE (WACOM_HID_UP_WACOMDIGITIZER | 0x1002)#define WACOM_HID_UP_G9 0xff090000#define WACOM_HID_G9_PEN (WACOM_HID_UP_G9 | 0x02)
Signature · 1 line
2.10.0
PATCH 16/19 HID: wacom: generic: Introduce pad support
In reply to Jason GereckeAs with usages for the pen, the Custom HID specificiation includes usages for the pad. Here we add functions to map and handle most of the pad usages present on the MobileStudio Pro.
--- drivers/hid/wacom_wac.c | 143 ++++++++++++++++++++++++++++++++++++++++++------ drivers/hid/wacom_wac.h | 19 +++++++ 2 files changed, 146 insertions(+), 16 deletions(-)
drivers/hid/wacom_wac.c +127 -16
@@ -41,6 +41,8 @@ MODULE_PARM_DESC(touch_arbitration, " on (Y) off (N)");static void wacom_report_numbered_buttons (struct input_dev *input_dev,int button_count,int mask); +static int wacom_numbered_button_to_key (int n); +/* * Percent of battery capacity for Graphire. * 8th value means AC online and show 100% capacity.
@@ -1447,12 +1449,16 @@ static int wacom_equivalent_usage(int usage)int subpage = (usage &0xFF00 ) <<8 ;int subusage = (usage &0xFF ); -if (subpage ==WACOM_HID_SP_DIGITIZER || +if (subpage ==WACOM_HID_SP_PAD || + subpage ==WACOM_HID_SP_BUTTON || + subpage ==WACOM_HID_SP_DIGITIZER || subpage ==WACOM_HID_SP_DIGITIZERINFO || usage ==WACOM_HID_WD_SENSE || usage ==WACOM_HID_WD_SERIALHI || usage ==WACOM_HID_WD_TOOLTYPE || - usage ==WACOM_HID_WD_DISTANCE ) { + usage ==WACOM_HID_WD_DISTANCE || + usage ==WACOM_HID_WD_TOUCHRING || + usage ==WACOM_HID_WD_TOUCHRINGSTATUS ) {return usage; }
@@ -1510,6 +1516,98 @@ static void wacom_map_usage(struct input_dev *input, struct hid_device *hdev, } } +static void wacom_wac_pad_usage_mapping (struct hid_device *hdev, +struct hid_field *field,struct hid_usage *usage) +{ +struct wacom *wacom =hid_get_drvdata (hdev); +struct wacom_wac *wacom_wac = &wacom->wacom_wac; +struct wacom_features *features = &wacom_wac->features; +struct input_dev *input = wacom_wac->pad_input; +unsigned equivalent_usage =wacom_equivalent_usage (usage->hid); + +switch (equivalent_usage) { +case WACOM_HID_WD_ACCELEROMETER_X : +__set_bit (INPUT_PROP_ACCELEROMETER , input->propbit); +wacom_map_usage (input, hdev, usage, field,EV_ABS ,ABS_X ,0 ); +break ; +case WACOM_HID_WD_ACCELEROMETER_Y : +__set_bit (INPUT_PROP_ACCELEROMETER , input->propbit); +wacom_map_usage (input, hdev, usage, field,EV_ABS ,ABS_Y ,0 ); +break ; +case WACOM_HID_WD_ACCELEROMETER_Z : +__set_bit (INPUT_PROP_ACCELEROMETER , input->propbit); +wacom_map_usage (input, hdev, usage, field,EV_ABS ,ABS_Z ,0 ); +break ; +case WACOM_HID_WD_BUTTONHOME : +case WACOM_HID_WD_BUTTONUP : +case WACOM_HID_WD_BUTTONDOWN : +case WACOM_HID_WD_BUTTONLEFT : +case WACOM_HID_WD_BUTTONRIGHT : +wacom_map_usage (input, hdev, usage, field,EV_KEY , +wacom_numbered_button_to_key (features->numbered_buttons), +0 ); + features->numbered_buttons++; +break ; +case WACOM_HID_WD_TOUCHRING : +wacom_map_usage (input, hdev, usage, field,EV_ABS ,ABS_WHEEL ,0 ); +break ; + } + +switch (equivalent_usage &0xfffffff0 ) { +case WACOM_HID_WD_EXPRESSKEY00 : +wacom_map_usage (input, hdev, usage, field,EV_KEY , +wacom_numbered_button_to_key (features->numbered_buttons), +0 ); + features->numbered_buttons++; +break ; + } +} + +static int wacom_wac_pad_event (struct hid_device *hdev,struct hid_field *field, +struct hid_usage *usage,__s32 value) +{ +struct wacom *wacom =hid_get_drvdata (hdev); +struct wacom_wac *wacom_wac = &wacom->wacom_wac; +struct input_dev *input = wacom_wac->pad_input; +unsigned equivalent_usage =wacom_equivalent_usage (usage->hid); + +if (wacom_equivalent_usage (field->physical) ==HID_DG_TABLETFUNCTIONKEY ) { + wacom_wac->hid_data.inrange_state |= value; + } + +if (equivalent_usage !=WACOM_HID_WD_TOUCHRINGSTATUS ) +input_event (input, usage->type, usage->code, value); + +return 0 ; +} + +static void wacom_wac_pad_pre_report (struct hid_device *hdev, +struct hid_report *report) +{ +struct wacom *wacom =hid_get_drvdata (hdev); +struct wacom_wac *wacom_wac = &wacom->wacom_wac; + + wacom_wac->hid_data.inrange_state =0 ; +} + +static void wacom_wac_pad_report (struct hid_device *hdev, +struct hid_report *report) +{ +struct wacom *wacom =hid_get_drvdata (hdev); +struct wacom_wac *wacom_wac = &wacom->wacom_wac; +struct input_dev *input = wacom_wac->pad_input; +bool active = wacom_wac->hid_data.inrange_state !=0 ; + +/* +* don't report prox for events like accelerometer +* or battery status +*/ +if (wacom_equivalent_usage (report->field[0 ]->physical) ==HID_DG_TABLETFUNCTIONKEY ) +input_event (input,EV_ABS ,ABS_MISC , active ?PAD_DEVICE_ID :0 ); + +input_sync (input); +} +static void wacom_wac_pen_usage_mapping (struct hid_device *hdev,struct hid_field *field,struct hid_usage *usage) {
@@ -1957,10 +2055,11 @@ void wacom_wac_usage_mapping(struct hid_device *hdev,/* currently, only direct devices have proper hid report descriptors */ features->device_type |=WACOM_DEVICETYPE_DIRECT ; -if (WACOM_PEN_FIELD (field)) +if (WACOM_PAD_FIELD (field)) +return wacom_wac_pad_usage_mapping (hdev, field, usage); +else if (WACOM_PEN_FIELD (field))return wacom_wac_pen_usage_mapping (hdev, field, usage); - -if (WACOM_FINGER_FIELD (field)) +else if (WACOM_FINGER_FIELD (field))return wacom_wac_finger_usage_mapping (hdev, field, usage); }
@@ -1972,10 +2071,11 @@ int wacom_wac_event(struct hid_device *hdev, struct hid_field *field,if (wacom->wacom_wac.features.type !=HID_GENERIC )return 0 ; -if (WACOM_PEN_FIELD (field)) +if (WACOM_PAD_FIELD (field)) +return wacom_wac_pad_event (hdev, field, usage, value); +else if (WACOM_PEN_FIELD (field))return wacom_wac_pen_event (hdev, field, usage, value); - -if (WACOM_FINGER_FIELD (field)) +else if (WACOM_FINGER_FIELD (field))return wacom_wac_finger_event (hdev, field, usage, value);return 0 ;
@@ -2009,18 +2109,20 @@ void wacom_wac_report(struct hid_device *hdev, struct hid_report *report)if (wacom_wac->features.type !=HID_GENERIC )return ; -if (WACOM_PEN_FIELD (field)) +if (WACOM_PAD_FIELD (field)) +wacom_wac_pad_pre_report (hdev, report); +else if (WACOM_PEN_FIELD (field))wacom_wac_pen_pre_report (hdev, report); - -if (WACOM_FINGER_FIELD (field)) +else if (WACOM_FINGER_FIELD (field))wacom_wac_finger_pre_report (hdev, report);wacom_report_events (hdev, report); -if (WACOM_PEN_FIELD (field)) +if (WACOM_PAD_FIELD (field)) +return wacom_wac_pad_report (hdev, report); +else if (WACOM_PEN_FIELD (field))return wacom_wac_pen_report (hdev, report); - -if (WACOM_FINGER_FIELD (field)) +else if (WACOM_FINGER_FIELD (field))return wacom_wac_finger_report (hdev, report); }
@@ -2594,6 +2696,8 @@ void wacom_setup_device_quirks(struct wacom *wacom)struct wacom_features *features = &wacom->wacom_wac.features;/* The pen and pad share the same interface on most devices */ +if (features->numbered_buttons >0 ) + features->device_type |=WACOM_DEVICETYPE_PAD ;if (features->type ==GRAPHIRE_BT || features->type ==WACOM_G4 || features->type ==DTUS || (features->type >=INTUOS3S && features->type <=WACOM_MO )) {
@@ -3115,8 +3219,12 @@ int wacom_setup_pad_input_capabilities(struct input_dev *input_dev,__set_bit (ABS_MISC , input_dev->absbit);/* kept for making legacy xf86-input-wacom accepting the pad */ -input_set_abs_params (input_dev,ABS_X ,0 ,1 ,0 ,0 ); -input_set_abs_params (input_dev,ABS_Y ,0 ,1 ,0 ,0 ); +if (!(input_dev->absinfo && (input_dev->absinfo[ABS_X ].minimum || + input_dev->absinfo[ABS_X ].maximum))) +input_set_abs_params (input_dev,ABS_X ,0 ,1 ,0 ,0 ); +if (!(input_dev->absinfo && (input_dev->absinfo[ABS_Y ].minimum || + input_dev->absinfo[ABS_Y ].maximum))) +input_set_abs_params (input_dev,ABS_Y ,0 ,1 ,0 ,0 );/* kept for making udev and libwacom accepting the pad */ __set_bit (BTN_STYLUS , input_dev->keybit);
@@ -3236,6 +3344,9 @@ int wacom_setup_pad_input_capabilities(struct input_dev *input_dev,input_set_abs_params (input_dev,ABS_WHEEL ,0 ,71 ,0 ,0 );break ; +case HID_GENERIC : +break ; +default :/* no pad supported */ return -ENODEV ;
drivers/hid/wacom_wac.h +19 -0
@@ -86,19 +86,34 @@#define WACOM_DEVICETYPE_DIRECT 0x0010#define WACOM_HID_UP_WACOMDIGITIZER 0xff0d0000 +#define WACOM_HID_SP_PAD 0x00040000 +#define WACOM_HID_SP_BUTTON 0x00090000#define WACOM_HID_SP_DIGITIZER 0x000d0000#define WACOM_HID_SP_DIGITIZERINFO 0x00100000#define WACOM_HID_WD_DIGITIZER (WACOM_HID_UP_WACOMDIGITIZER | 0x01)#define WACOM_HID_WD_SENSE (WACOM_HID_UP_WACOMDIGITIZER | 0x36) +#define WACOM_HID_WD_DIGITIZERFNKEYS (WACOM_HID_UP_WACOMDIGITIZER | 0x39)#define WACOM_HID_WD_SERIALHI (WACOM_HID_UP_WACOMDIGITIZER | 0x5c)#define WACOM_HID_WD_TOOLTYPE (WACOM_HID_UP_WACOMDIGITIZER | 0x77)#define WACOM_HID_WD_DISTANCE (WACOM_HID_UP_WACOMDIGITIZER | 0x0132) +#define WACOM_HID_WD_TOUCHRING (WACOM_HID_UP_WACOMDIGITIZER | 0x0138) +#define WACOM_HID_WD_TOUCHRINGSTATUS (WACOM_HID_UP_WACOMDIGITIZER | 0x0139) +#define WACOM_HID_WD_ACCELEROMETER_X (WACOM_HID_UP_WACOMDIGITIZER | 0x0401) +#define WACOM_HID_WD_ACCELEROMETER_Y (WACOM_HID_UP_WACOMDIGITIZER | 0x0402) +#define WACOM_HID_WD_ACCELEROMETER_Z (WACOM_HID_UP_WACOMDIGITIZER | 0x0403) +#define WACOM_HID_WD_EXPRESSKEY00 (WACOM_HID_UP_WACOMDIGITIZER | 0x0910) +#define WACOM_HID_WD_BUTTONHOME (WACOM_HID_UP_WACOMDIGITIZER | 0x0990) +#define WACOM_HID_WD_BUTTONUP (WACOM_HID_UP_WACOMDIGITIZER | 0x0991) +#define WACOM_HID_WD_BUTTONDOWN (WACOM_HID_UP_WACOMDIGITIZER | 0x0992) +#define WACOM_HID_WD_BUTTONLEFT (WACOM_HID_UP_WACOMDIGITIZER | 0x0993) +#define WACOM_HID_WD_BUTTONRIGHT (WACOM_HID_UP_WACOMDIGITIZER | 0x0994)#define WACOM_HID_WD_FINGERWHEEL (WACOM_HID_UP_WACOMDIGITIZER | 0x0d03)#define WACOM_HID_WD_OFFSETLEFT (WACOM_HID_UP_WACOMDIGITIZER | 0x0d30)#define WACOM_HID_WD_OFFSETTOP (WACOM_HID_UP_WACOMDIGITIZER | 0x0d31)#define WACOM_HID_WD_OFFSETRIGHT (WACOM_HID_UP_WACOMDIGITIZER | 0x0d32)#define WACOM_HID_WD_OFFSETBOTTOM (WACOM_HID_UP_WACOMDIGITIZER | 0x0d33)#define WACOM_HID_WD_DATAMODE (WACOM_HID_UP_WACOMDIGITIZER | 0x1002) +#define WACOM_HID_WD_DIGITIZERINFO (WACOM_HID_UP_WACOMDIGITIZER | 0x1013)#define WACOM_HID_UP_G9 0xff090000#define WACOM_HID_G9_PEN (WACOM_HID_UP_G9 | 0x02)#define WACOM_HID_G9_TOUCHSCREEN (WACOM_HID_UP_G9 | 0x11)
@@ -106,6 +121,10 @@#define WACOM_HID_G11_PEN (WACOM_HID_UP_G11 | 0x02)#define WACOM_HID_G11_TOUCHSCREEN (WACOM_HID_UP_G11 | 0x11) +#define WACOM_PAD_FIELD (f) (((f)->physical == HID_DG_TABLETFUNCTIONKEY) || \ + ((f)->physical == WACOM_HID_WD_DIGITIZERFNKEYS) || \ + ((f)->physical == WACOM_HID_WD_DIGITIZERINFO)) +#define WACOM_PEN_FIELD (f) (((f)->logical == HID_DG_STYLUS) || \ ((f)->physical == HID_DG_STYLUS) || \ ((f)->physical == HID_DG_PEN) || \
Signature · 1 line
2.10.0
PATCH 17/19 HID: wacom: generic: Add support for battery status on pen and pad interfaces
In reply to Jason GereckeAdds support for usages that may appear on the pen or pad interface which report the state of the tablet battery.
--- drivers/hid/wacom_wac.c | 41 ++++++++++++++++++++++++++++++++++++++++- drivers/hid/wacom_wac.h | 6 ++++++ include/linux/hid.h | 1 + 3 files changed, 47 insertions(+), 1 deletion(-)
drivers/hid/wacom_wac.c +40 -1
@@ -1526,6 +1526,10 @@ static void wacom_wac_pad_usage_mapping(struct hid_device *hdev,unsigned equivalent_usage =wacom_equivalent_usage (usage->hid);switch (equivalent_usage) { +case WACOM_HID_WD_BATTERY_LEVEL : +case WACOM_HID_WD_BATTERY_CHARGING : + features->quirks |=WACOM_QUIRK_BATTERY ; +break ;case WACOM_HID_WD_ACCELEROMETER_X :__set_bit (INPUT_PROP_ACCELEROMETER , input->propbit);wacom_map_usage (input, hdev, usage, field,EV_ABS ,ABS_X ,0 );
@@ -1575,8 +1579,25 @@ static int wacom_wac_pad_event(struct hid_device *hdev, struct hid_field *field, wacom_wac->hid_data.inrange_state |= value; } -if (equivalent_usage !=WACOM_HID_WD_TOUCHRINGSTATUS ) +switch (equivalent_usage) { +case WACOM_HID_WD_BATTERY_LEVEL : + wacom_wac->hid_data.battery_capacity = value; + wacom_wac->hid_data.bat_connected =1 ; +return 0 ; + +case WACOM_HID_WD_BATTERY_CHARGING : + wacom_wac->hid_data.bat_charging = value; + wacom_wac->hid_data.ps_connected = value; + wacom_wac->hid_data.bat_connected =1 ; +return 0 ; + +case WACOM_HID_WD_TOUCHRINGSTATUS : +return 0 ; + +default :input_event (input, usage->type, usage->code, value); +break ; + }return 0 ; }
@@ -1595,6 +1616,7 @@ static void wacom_wac_pad_report(struct hid_device *hdev, {struct wacom *wacom =hid_get_drvdata (hdev);struct wacom_wac *wacom_wac = &wacom->wacom_wac; +struct wacom_features *features = &wacom_wac->features;struct input_dev *input = wacom_wac->pad_input;bool active = wacom_wac->hid_data.inrange_state !=0 ;
@@ -1605,6 +1627,16 @@ static void wacom_wac_pad_report(struct hid_device *hdev,if (wacom_equivalent_usage (report->field[0 ]->physical) ==HID_DG_TABLETFUNCTIONKEY )input_event (input,EV_ABS ,ABS_MISC , active ?PAD_DEVICE_ID :0 ); +if (features->quirks &WACOM_QUIRK_BATTERY ) { +int capacity = wacom_wac->hid_data.battery_capacity; +bool charging = wacom_wac->hid_data.bat_charging; +bool connected = wacom_wac->hid_data.bat_connected; +bool powered = wacom_wac->hid_data.ps_connected; + +wacom_notify_battery (wacom_wac, capacity, charging, + connected, powered); + } +input_sync (input); }
@@ -1634,6 +1666,9 @@ static void wacom_wac_pen_usage_mapping(struct hid_device *hdev,case HID_DG_INRANGE :wacom_map_usage (input, hdev, usage, field,EV_KEY ,BTN_TOOL_PEN ,0 );break ; +case HID_DG_BATTERYSTRENGTH : + features->quirks |=WACOM_QUIRK_BATTERY ; +break ;case HID_DG_INVERT :wacom_map_usage (input, hdev, usage, field,EV_KEY ,BTN_TOOL_RUBBER ,0 );
@@ -1704,6 +1739,10 @@ static int wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field,if (!(features->quirks &WACOM_QUIRK_SENSE )) wacom_wac->hid_data.sense_state = value;return 0 ; +case HID_DG_BATTERYSTRENGTH : + wacom_wac->hid_data.battery_capacity = value; + wacom_wac->hid_data.bat_connected =1 ; +break ;case HID_DG_INVERT : wacom_wac->hid_data.invert_state = value;return 0 ;
drivers/hid/wacom_wac.h +6 -0
@@ -101,6 +101,8 @@#define WACOM_HID_WD_ACCELEROMETER_X (WACOM_HID_UP_WACOMDIGITIZER | 0x0401)#define WACOM_HID_WD_ACCELEROMETER_Y (WACOM_HID_UP_WACOMDIGITIZER | 0x0402)#define WACOM_HID_WD_ACCELEROMETER_Z (WACOM_HID_UP_WACOMDIGITIZER | 0x0403) +#define WACOM_HID_WD_BATTERY_CHARGING (WACOM_HID_UP_WACOMDIGITIZER | 0x0404) +#define WACOM_HID_WD_BATTERY_LEVEL (WACOM_HID_UP_WACOMDIGITIZER | 0x043b)#define WACOM_HID_WD_EXPRESSKEY00 (WACOM_HID_UP_WACOMDIGITIZER | 0x0910)#define WACOM_HID_WD_BUTTONHOME (WACOM_HID_UP_WACOMDIGITIZER | 0x0990)#define WACOM_HID_WD_BUTTONUP (WACOM_HID_UP_WACOMDIGITIZER | 0x0991)
@@ -257,6 +259,10 @@ struct hid_data {int cc_value_index;int num_expected;int num_received; +int battery_capacity; +int bat_charging; +int bat_connected; +int ps_connected; };struct wacom_remote_data {
include/linux/hid.h +1 -0
@@ -231,6 +231,7 @@ struct hid_item {#define HID_DG_TAP 0x000d0035#define HID_DG_TABLETFUNCTIONKEY 0x000d0039#define HID_DG_PROGRAMCHANGEKEY 0x000d003a +#define HID_DG_BATTERYSTRENGTH 0x000d003b#define HID_DG_INVERT 0x000d003c#define HID_DG_TILT_X 0x000d003d#define HID_DG_TILT_Y 0x000d003e
Signature · 1 line
2.10.0
PATCH 18/19 HID: wacom: generic: Extend pad support
In reply to Jason GereckeThe HID specification that the MobileStudio Pro follows includes usages for several values that would be good to support so that future devices "just work" out of the box. Extend the HID_GENERIC pad codepath to handle these usages.
--- drivers/hid/wacom_wac.c | 15 +++++++++++++++ drivers/hid/wacom_wac.h | 5 +++++ 2 files changed, 20 insertions(+)
drivers/hid/wacom_wac.c +15 -0
@@ -1457,6 +1457,8 @@ static int wacom_equivalent_usage(int usage) usage ==WACOM_HID_WD_SERIALHI || usage ==WACOM_HID_WD_TOOLTYPE || usage ==WACOM_HID_WD_DISTANCE || + usage ==WACOM_HID_WD_TOUCHSTRIP || + usage ==WACOM_HID_WD_TOUCHSTRIP2 || usage ==WACOM_HID_WD_TOUCHRING || usage == WACOM_HID_WD_TOUCHRINGSTATUS) { return usage;
@@ -1513,6 +1515,9 @@ static void wacom_map_usage(struct input_dev *input, struct hid_device *hdev,case EV_MSC :input_set_capability (input,EV_MSC , code);break ; +case EV_SW : +input_set_capability (input,EV_SW , code); +break ; } }
@@ -1547,11 +1552,21 @@ static void wacom_wac_pad_usage_mapping(struct hid_device *hdev,case WACOM_HID_WD_BUTTONDOWN :case WACOM_HID_WD_BUTTONLEFT :case WACOM_HID_WD_BUTTONRIGHT : +case WACOM_HID_WD_BUTTONCENTER :wacom_map_usage (input, hdev, usage, field,EV_KEY ,wacom_numbered_button_to_key (features->numbered_buttons),0 ); features->numbered_buttons++;break ; +case WACOM_HID_WD_TOUCHONOFF : +wacom_map_usage (input, hdev, usage, field,EV_SW ,SW_MUTE_DEVICE ,0 ); +break ; +case WACOM_HID_WD_TOUCHSTRIP : +wacom_map_usage (input, hdev, usage, field,EV_ABS ,ABS_RX ,0 ); +break ; +case WACOM_HID_WD_TOUCHSTRIP2 : +wacom_map_usage (input, hdev, usage, field,EV_ABS ,ABS_RY ,0 ); +break ;case WACOM_HID_WD_TOUCHRING :wacom_map_usage (input, hdev, usage, field,EV_ABS ,ABS_WHEEL ,0 );break ;
drivers/hid/wacom_wac.h +5 -0
@@ -96,6 +96,8 @@#define WACOM_HID_WD_SERIALHI (WACOM_HID_UP_WACOMDIGITIZER | 0x5c)#define WACOM_HID_WD_TOOLTYPE (WACOM_HID_UP_WACOMDIGITIZER | 0x77)#define WACOM_HID_WD_DISTANCE (WACOM_HID_UP_WACOMDIGITIZER | 0x0132) +#define WACOM_HID_WD_TOUCHSTRIP (WACOM_HID_UP_WACOMDIGITIZER | 0x0136) +#define WACOM_HID_WD_TOUCHSTRIP2 (WACOM_HID_UP_WACOMDIGITIZER | 0x0137)#define WACOM_HID_WD_TOUCHRING (WACOM_HID_UP_WACOMDIGITIZER | 0x0138)#define WACOM_HID_WD_TOUCHRINGSTATUS (WACOM_HID_UP_WACOMDIGITIZER | 0x0139)#define WACOM_HID_WD_ACCELEROMETER_X (WACOM_HID_UP_WACOMDIGITIZER | 0x0401)
@@ -104,11 +106,14 @@#define WACOM_HID_WD_BATTERY_CHARGING (WACOM_HID_UP_WACOMDIGITIZER | 0x0404)#define WACOM_HID_WD_BATTERY_LEVEL (WACOM_HID_UP_WACOMDIGITIZER | 0x043b)#define WACOM_HID_WD_EXPRESSKEY00 (WACOM_HID_UP_WACOMDIGITIZER | 0x0910) +#define WACOM_HID_WD_EXPRESSKEYCAP00 (WACOM_HID_UP_WACOMDIGITIZER | 0x0950)#define WACOM_HID_WD_BUTTONHOME (WACOM_HID_UP_WACOMDIGITIZER | 0x0990)#define WACOM_HID_WD_BUTTONUP (WACOM_HID_UP_WACOMDIGITIZER | 0x0991)#define WACOM_HID_WD_BUTTONDOWN (WACOM_HID_UP_WACOMDIGITIZER | 0x0992)#define WACOM_HID_WD_BUTTONLEFT (WACOM_HID_UP_WACOMDIGITIZER | 0x0993)#define WACOM_HID_WD_BUTTONRIGHT (WACOM_HID_UP_WACOMDIGITIZER | 0x0994) +#define WACOM_HID_WD_BUTTONCENTER (WACOM_HID_UP_WACOMDIGITIZER | 0x0995) +#define WACOM_HID_WD_TOUCHONOFF (WACOM_HID_UP_WACOMDIGITIZER | 0x0996)#define WACOM_HID_WD_FINGERWHEEL (WACOM_HID_UP_WACOMDIGITIZER | 0x0d03)#define WACOM_HID_WD_OFFSETLEFT (WACOM_HID_UP_WACOMDIGITIZER | 0x0d30)#define WACOM_HID_WD_OFFSETTOP (WACOM_HID_UP_WACOMDIGITIZER | 0x0d31)
Signature · 1 line
2.10.0
PATCH 19/19 HID: input: Recognize ABS_WHEEL in hidinput_calc_abs_res
In reply to Jason GereckeThe "Steering" usage (HID_UP_SIMULATION | 0xc8) is defined in HUT 1.12 as follows:
"A steering wheel is a single degree-of-freedom device that rotates about an axis. The zero position is always the neutral or 'straight ahead' position, with positive values turning clockwise and negative values turning counterclockwise. If the Coordinate Values Wrap attribute is set, the steering wheel can be turned past 360 degrees."
The hidinput_configure_usage function canonically maps this usage to the ABS_WHEEL axis, but hidinput_calc_abs_res does not recognize this axis as one for which it can calculate a resolution. This effectively prevents wheels from being assigned a proper resolution that userspace can use to determine the precise angle of input.
This commit adds ABS_WHEEL as a rotational axis to hidinput_calc_abs_res.
--- drivers/hid/hid-input.c | 1 + 1 file changed, 1 insertion(+)
drivers/hid/hid-input.c +1 -0
@@ -253,6 +253,7 @@ __s32 hidinput_calc_abs_res(const struct hid_field *field, __u16 code)case ABS_RX :case ABS_RY :case ABS_RZ : +case ABS_WHEEL :case ABS_TILT_X :case ABS_TILT_Y :if (field->unit ==0x14 ) {/* If degrees */
Signature · 1 line
2.10.0
Quoted 18 lines · Jason Gerecke
Wacom announced two new "MobileStudio Pro" tablets yesterday, a third iteration of the Cintiq Companion line of mobile PCs which can double as external pen displays.
Unlike Wacom's prior professional-grade devices, the HID descriptor for the MobileStudio Pro includes a rudimentary (but standard!) "Digitizer" application collection that is usable by the existing
HID_GENERICcodepath. Additionally, a second vendor-defined application collection exists which fully defines reports that enable full tablet functionality. The numerous vendor-defined usages are planned to be used in future professional devices as well, allowing us to finally gain some of the same forward compatibility benefits we've had for ISDv4 devices since 3.17.* Patches 1-3 perform some basic cleanups.
* Patches 4-6 work on the operation of the driver for all
HID_GENERICdevices, correcting minor issues and adding some missing features.
Quoted 7 lines
* Patches 7-19 implement support for the vendor defined usages that are used in the MobileStudio Pro, and which are planned to be used in future professional devices as well.
Jiri: Could you let me know whether it would be possible to schedule these for the currently-open 4.9 merge window?
Jiri, FYI, I have already made 2 (or 3) internal reviews of this series. I just have one/two nitpicks here and there (I noticed few if statements with braces while only one statement was done after), but nothing preventing from pulling the series IMO.
I have been staring the series for too long now, and I can't find anything useful (besides in patch 13, but not a biggy).
Quoted 1 line
From what I can tell, the series has little impact on existing devices
(patches 1, 3, 11, 14), and I assume Jason and the other Wacom engineers made extensive tests for these patches.
Patch 19 for hid-input should also be safe :)
The series is:
Cheers,
Benjamin
Quoted 39 lines
Jason Gerecke (19):
HID: wacom: Update vendor-defined usage names to better match
standards
HID: wacom: HaveWACOM_PEN_FIELDandWACOM_FINGER_FIELDrecgonize more
fields
HID: wacom: Refactor button-to-key translation into function
HID: wacom: Detect and correct descriptors missing
HID_DG_BARRELSWITCH2
HID: wacom: generic: Strip off excessive name prefixing
HID: wacom: generic: Add support for height, tilt, and twist usages
HID: wacom: generic: Support and use 'Custom HID' mode and usages
HID: wacom: generic: Add support for vendor-defined "Distance" usage
HID: wacom: generic: Add support for vendor-defined "Fingerwheel"
usage
HID: wacom: generic: Add support for vendor-defined "Sense" usage
HID: wacom: Read and internally use corrected Intuos tool IDs
HID: wacom: generic: Support tool ID and additional tool types
HID: wacom: generic: Pass 'hdev' to 'wacom_map_usage'
HID: wacom: Fix sensor outbounds and redefine as offsets from each
edge
HID: wacom: generic: Add support for sensor offsets
HID: wacom: generic: Introduce pad support
HID: wacom: generic: Add support for battery status on pen and pad
interfaces
HID: wacom: generic: Extend pad support
HID: input: RecognizeABS_WHEELinhidinput_calc_abs_resdrivers/hid/hid-input.c | 1 + drivers/hid/wacom_sys.c | 92 ++++++-- drivers/hid/wacom_wac.c | 544 +++++++++++++++++++++++++++++++++++++++--------- drivers/hid/wacom_wac.h | 73 ++++++- include/linux/hid.h | 4 + 5 files changed, 595 insertions(+), 119 deletions(-)Signature · 1 line
2.10.0
PATCH v2 1/18 HID: wacom: Update vendor-defined usage names to better match standards
In reply to Jason GereckeOur loose use of "pen" and "digitizer" in the naming of several of our vendor-defined usages may be a source of confusion given that the terms have specific meaning within the HID specification. "Pen" specifically refers to "an integrated display that allows the use of a stylus" (e.g. something like a tablet PC or Cintiq) wheras "Digitizer" is a better fit for opaque tablets like an Intuos.
While we're at it, go ahead and rename the definitions to make them more distinct and better match up with the convention used by HID (e.g. the use of '_UP_' for usage pages) and make them more distinct.
--- drivers/hid/wacom_sys.c | 12 ++++++------ drivers/hid/wacom_wac.c | 2 +- drivers/hid/wacom_wac.h | 17 +++++++++-------- 3 files changed, 16 insertions(+), 15 deletions(-)
drivers/hid/wacom_sys.c +6 -6
@@ -159,18 +159,18 @@ static void wacom_feature_mapping(struct hid_device *hdev,case HID_UP_DIGITIZER :if (field->report->id ==0x0B && - (field->application ==WACOM_G9_DIGITIZER || - field->application ==WACOM_G11_DIGITIZER )) { + (field->application ==WACOM_HID_G9_PEN || + field->application ==WACOM_HID_G11_PEN )) { wacom->wacom_wac.mode_report = field->report->id; wacom->wacom_wac.mode_value =0 ; }break ; -case WACOM_G9_PAGE : -case WACOM_G11_PAGE : +case WACOM_HID_UP_G9 : +case WACOM_HID_UP_G11 :if (field->report->id ==0x03 && - (field->application ==WACOM_G9_TOUCHSCREEN || - field->application ==WACOM_G11_TOUCHSCREEN )) { + (field->application ==WACOM_HID_G9_TOUCHSCREEN || + field->application ==WACOM_HID_G11_TOUCHSCREEN )) { wacom->wacom_wac.mode_report = field->report->id; wacom->wacom_wac.mode_value =0 ; }
drivers/hid/wacom_wac.c +1 -1
@@ -2458,7 +2458,7 @@ void wacom_setup_device_quirks(struct wacom *wacom)/* * Raw Wacom-mode pen and touch events both come from interface * 0, whose HID descriptor has an application usage of 0xFF0D -* (i.e., WACOM_VENDORDEFINED_PEN). We route pen packets back +* (i.e., WACOM_HID_WD_DIGITIZER). We route pen packets back * out through the HID_GENERIC device created for interface 1, * so rewrite this one to be of type WACOM_DEVICETYPE_TOUCH. */
drivers/hid/wacom_wac.h +9 -8
@@ -84,20 +84,21 @@#define WACOM_DEVICETYPE_WL_MONITOR 0x0008#define WACOM_DEVICETYPE_DIRECT 0x0010 -#define WACOM_VENDORDEFINED_PEN 0xff0d0001 -#define WACOM_G9_PAGE 0xff090000 -#define WACOM_G9_DIGITIZER (WACOM_G9_PAGE | 0x02) -#define WACOM_G9_TOUCHSCREEN (WACOM_G9_PAGE | 0x11) -#define WACOM_G11_PAGE 0xff110000 -#define WACOM_G11_DIGITIZER (WACOM_G11_PAGE | 0x02) -#define WACOM_G11_TOUCHSCREEN (WACOM_G11_PAGE | 0x11) +#define WACOM_HID_UP_WACOMDIGITIZER 0xff0d0000 +#define WACOM_HID_WD_DIGITIZER (WACOM_HID_UP_WACOMDIGITIZER | 0x01) +#define WACOM_HID_UP_G9 0xff090000 +#define WACOM_HID_G9_PEN (WACOM_HID_UP_G9 | 0x02) +#define WACOM_HID_G9_TOUCHSCREEN (WACOM_HID_UP_G9 | 0x11) +#define WACOM_HID_UP_G11 0xff110000 +#define WACOM_HID_G11_PEN (WACOM_HID_UP_G11 | 0x02) +#define WACOM_HID_G11_TOUCHSCREEN (WACOM_HID_UP_G11 | 0x11)#define WACOM_PEN_FIELD (f) (((f)->logical == HID_DG_STYLUS) || \ ((f)->physical == HID_DG_STYLUS) || \ ((f)->physical == HID_DG_PEN) || \ ((f)->application == HID_DG_PEN) || \ ((f)->application == HID_DG_DIGITIZER) || \ - ((f)->application == WACOM_VENDORDEFINED_PEN)) + ((f)->application == WACOM_HID_WD_DIGITIZER))#define WACOM_FINGER_FIELD (f) (((f)->logical == HID_DG_FINGER) || \ ((f)->physical == HID_DG_FINGER) || \ ((f)->application == HID_DG_TOUCHSCREEN))
Signature · 1 line
2.10.0
PATCH v2 2/18 HID: wacom: Have WACOM_PEN_FIELD and WACOM_FINGER_FIELD recgonize more fields
We've defined several new usages (e.g. WACOM_G9_PEN and WACOM_G9_TOUCHSCREEN) which aren't checked by the WACOM_PEN_FIELD and WACOM_FINGER_FIELD macros but probably should be.
--- drivers/hid/wacom_wac.h | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
drivers/hid/wacom_wac.h +6 -2
@@ -98,10 +98,14 @@ ((f)->physical == HID_DG_PEN) || \ ((f)->application == HID_DG_PEN) || \ ((f)->application == HID_DG_DIGITIZER) || \ - ((f)->application == WACOM_HID_WD_DIGITIZER)) + ((f)->application == WACOM_HID_WD_DIGITIZER) || \ + ((f)->application == WACOM_HID_G9_PEN) || \ + ((f)->application == WACOM_HID_G11_PEN))#define WACOM_FINGER_FIELD (f) (((f)->logical == HID_DG_FINGER) || \ ((f)->physical == HID_DG_FINGER) || \ - ((f)->application == HID_DG_TOUCHSCREEN)) + ((f)->application == HID_DG_TOUCHSCREEN) || \ + ((f)->application == WACOM_HID_G9_TOUCHSCREEN) || \ + ((f)->application == WACOM_HID_G11_TOUCHSCREEN))enum {PENPARTNER =0 ,
Signature · 1 line
2.10.0
PATCH v2 3/18 HID: wacom: Refactor button-to-key translation into function
In reply to Jason GereckeThis just centralizes the logic used in both wacom_setup_numbered_buttons and wacom_report_numbered_buttons so that they don't drift out of sync.
--- drivers/hid/wacom_wac.c | 36 ++++++++++++++++++++++++------------ 1 file changed, 24 insertions(+), 12 deletions(-)
drivers/hid/wacom_wac.c +24 -12
@@ -2779,17 +2779,29 @@ int wacom_setup_touch_input_capabilities(struct input_dev *input_dev,return 0 ; } +static int wacom_numbered_button_to_key (int n) +{ +if (n <10 ) +return BTN_0 + n; +else if (n <16 ) +return BTN_A + (n-10 ); +else if (n <18 ) +return BTN_BASE + (n-16 ); +else +return 0 ; +} +static void wacom_setup_numbered_buttons (struct input_dev *input_dev,int button_count) {int i; -for (i =0 ; i < button_count && i <10 ; i++) -__set_bit (BTN_0 + i, input_dev->keybit); -for (i =10 ; i < button_count && i <16 ; i++) -__set_bit (BTN_A + (i-10 ), input_dev->keybit); -for (i =16 ; i < button_count && i <18 ; i++) -__set_bit (BTN_BASE + (i-16 ), input_dev->keybit); +for (i =0 ; i < button_count; i++) { +int key =wacom_numbered_button_to_key (i); + +if (key) +__set_bit (key, input_dev->keybit); + } }static void wacom_24hd_update_leds (struct wacom *wacom,int mask,int group)
@@ -2891,12 +2903,12 @@ static void wacom_report_numbered_buttons(struct input_dev *input_dev,for (i =0 ; i < wacom->led.count; i++)wacom_update_led (wacom, button_count, mask, i); -for (i =0 ; i < button_count && i <10 ; i++) -input_report_key (input_dev,BTN_0 + i, mask & (1 << i)); -for (i =10 ; i < button_count && i <16 ; i++) -input_report_key (input_dev,BTN_A + (i-10 ), mask & (1 << i)); -for (i =16 ; i < button_count && i <18 ; i++) -input_report_key (input_dev,BTN_BASE + (i-16 ), mask & (1 << i)); +for (i =0 ; i < button_count; i++) { +int key =wacom_numbered_button_to_key (i); + +if (key) +input_report_key (input_dev, key, mask & (1 << i)); + } } int wacom_setup_pad_input_capabilities(struct input_dev *input_dev,
Signature · 1 line
2.10.0
PATCH v2 4/18 HID: wacom: Detect and correct descriptors missing HID_DG_BARRELSWITCH2
In reply to Jason GereckeISDv4 devices have long supported reporting data from each of two barrel switches, but HID_DG_BARRELSWITCH2 itself was only recently standardized. Prior to its adoption, ISDv4 devices would associate the bit indicating the state of the second barrel switch with the "Undefined" 0x000D0000 usage. Although most such devices have explicit support, a few use the HID_GENERIC codepath which ignores the "Undefined" usage.
This patch adds code which detects the presence of a pre-standard second barrel switch and corrects the usage value so that the HID_GENERIC code will declare its presence and report its state.
--- drivers/hid/wacom_sys.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+)
drivers/hid/wacom_sys.c +24 -0
@@ -240,6 +240,30 @@ static void wacom_usage_mapping(struct hid_device *hdev, features->touch_max =1 ; } +/* +* ISDv4 devices which predate HID's adoption of the +* HID_DG_BARELSWITCH2 usage use 0x000D0000 in its +* position instead. We can accurately detect if a +* usage with that value should be HID_DG_BARRELSWITCH2 +* based on the surrounding usages, which have remained +* constant across generations. +*/ +if (features->type ==HID_GENERIC && + usage->hid ==0x000D0000 && + field->application ==HID_DG_PEN && + field->physical ==HID_DG_STYLUS ) { +int i = usage->usage_index; + +if (i-4 >=0 && i+1 < field->maxusage && + field->usage[i-4 ].hid ==HID_DG_TIPSWITCH && + field->usage[i-3 ].hid ==HID_DG_BARRELSWITCH && + field->usage[i-2 ].hid ==HID_DG_ERASER && + field->usage[i-1 ].hid ==HID_DG_INVERT && + field->usage[i+1 ].hid ==HID_DG_INRANGE ) { + usage->hid =HID_DG_BARRELSWITCH2 ; + } + } +switch (usage->hid) {case HID_GD_X : features->x_max = field->logical_maximum;
Signature · 1 line
2.10.0
PATCH v2 5/18 HID: wacom: generic: Strip off excessive name prefixing
In reply to Jason GereckeThe product name received from the string descriptor in the new MobileStudio Pro line of tablets begins with "Wacom", which leads to unnecessary visual noise in the device name when appended to the vendor name which also includes "Wacom". Look for and fix cases like this.
--- drivers/hid/wacom_sys.c | 13 +++++++++++++ 1 file changed, 13 insertions(+)
drivers/hid/wacom_sys.c +13 -0
@@ -1940,6 +1940,19 @@ static void wacom_update_name(struct wacom *wacom, const char *suffix)/* shift everything including the terminator */ memmove (gap, gap+1 ,strlen (gap)); } + +/* strip off excessive prefixing */ +if (strstr (name,"Wacom Co.,Ltd. Wacom " ) == name) { +int n =strlen (name); +int x =strlen ("Wacom Co.,Ltd. " ); +memmove (name, name+x, n-x+1 ); + } +if (strstr (name,"Wacom Co., Ltd. Wacom " ) == name) { +int n =strlen (name); +int x =strlen ("Wacom Co., Ltd. " ); +memmove (name, name+x, n-x+1 ); + } +/* get rid of trailing whitespace */ if (name[strlen (name)-1 ] ==' ' ) name[strlen (name)-1 ] ='\0' ;
Signature · 1 line
2.10.0
PATCH v2 6/18 HID: wacom: generic: Add support for height, tilt, and twist usages
In reply to Jason GereckeThe HID standard defines usages that allow digitizers to report the pen's height, tilt, and rotation and which are used by Wacom's new "MobileStudio Pro" devices.
Note that 'hidinput_calc_abs_res' expects ABS_Z (historically used by our driver to report twist) to have linear units. To ensure it calculates a resolution with the actually-angular units provided in the HID descriptor we nedd to lie and tell it we're calculating it for the (rotational) ABS_RZ axis instead.
--- drivers/hid/wacom_wac.c | 28 ++++++++++++++++++++++++++-- include/linux/hid.h | 3 +++ 2 files changed, 29 insertions(+), 2 deletions(-)
drivers/hid/wacom_wac.c +26 -2
@@ -1440,6 +1440,11 @@ static void wacom_map_usage(struct input_dev *input, struct hid_usage *usage, {int fmin = field->logical_minimum;int fmax = field->logical_maximum; +int resolution_code = code; + +if (usage->hid ==HID_DG_TWIST ) { + resolution_code =ABS_RZ ; + } usage->type = type; usage->code = code;
@@ -1450,7 +1455,7 @@ static void wacom_map_usage(struct input_dev *input, struct hid_usage *usage,case EV_ABS :input_set_abs_params (input, code, fmin, fmax, fuzz,0 );input_abs_set_res (input, code, -hidinput_calc_abs_res (field, code)); +hidinput_calc_abs_res (field, resolution_code));break ;case EV_KEY :input_set_capability (input,EV_KEY , code);
@@ -1475,6 +1480,9 @@ static void wacom_wac_pen_usage_mapping(struct hid_device *hdev,case HID_GD_Y :wacom_map_usage (input, usage, field,EV_ABS ,ABS_Y ,4 );break ; +case HID_GD_Z : +wacom_map_usage (input, usage, field,EV_ABS ,ABS_DISTANCE ,0 ); +break ;case HID_DG_TIPPRESSURE :wacom_map_usage (input, usage, field,EV_ABS ,ABS_PRESSURE ,0 );break ;
@@ -1485,6 +1493,15 @@ static void wacom_wac_pen_usage_mapping(struct hid_device *hdev,wacom_map_usage (input, usage, field,EV_KEY ,BTN_TOOL_RUBBER ,0 );break ; +case HID_DG_TILT_X : +wacom_map_usage (input, usage, field,EV_ABS ,ABS_TILT_X ,0 ); +break ; +case HID_DG_TILT_Y : +wacom_map_usage (input, usage, field,EV_ABS ,ABS_TILT_Y ,0 ); +break ; +case HID_DG_TWIST : +wacom_map_usage (input, usage, field,EV_ABS ,ABS_Z ,0 ); +break ;case HID_DG_ERASER :case HID_DG_TIPSWITCH :wacom_map_usage (input, usage, field,EV_KEY ,BTN_TOUCH ,0 );
@@ -1508,8 +1525,15 @@ static int wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field,struct wacom_wac *wacom_wac = &wacom->wacom_wac;struct input_dev *input = wacom_wac->pen_input; -/* checking which Tool / tip switch to send */ switch (usage->hid) { +case HID_GD_Z : +/* +* HID_GD_Z "should increase as the control's position is +* moved from high to low", while ABS_DISTANCE instead +* increases in value as the tool moves from low to high. +*/ + value = field->logical_maximum - value; +break ;case HID_DG_INRANGE : wacom_wac->hid_data.inrange_state = value;return 0 ;
include/linux/hid.h +3 -0
@@ -232,6 +232,9 @@ struct hid_item {#define HID_DG_TABLETFUNCTIONKEY 0x000d0039#define HID_DG_PROGRAMCHANGEKEY 0x000d003a#define HID_DG_INVERT 0x000d003c +#define HID_DG_TILT_X 0x000d003d +#define HID_DG_TILT_Y 0x000d003e +#define HID_DG_TWIST 0x000d0041#define HID_DG_TIPSWITCH 0x000d0042#define HID_DG_TIPSWITCH2 0x000d0043#define HID_DG_BARRELSWITCH 0x000d0044
Signature · 1 line
2.10.0
PATCH v2 7/18 HID: wacom: generic: Support and use 'Custom HID' mode and usages
In reply to Jason GereckeWacom's new "MobileStudio Pro" tablets are the first devices in their branded product line-up to include a usable HID descriptor for the pen interface. Like prior branded products, the device can operate in one of two modes: 'Standard HID', and 'Wacom Custom HID'. Although the first mode is usable by the HID_GENERIC codepath as-is (huzzah!), it is subject to some restrictions -- most notably pressure being limited to 2048 levels instead of 8192. To ensure tablets that include support for Custom HID mode work optimally, we add support for its usages and switch the device to Custom HID mode if possible.
The usages defined for Custom HID mode are often numerically similar to their standard HID equivalents, allowing us to write a simple translation function that takes arbitrary HID usages as input and which returns the corresponding standard HID usage as output (if one exists). Switching on this translated usage instead of the actual usage allows the existing cases to apply to both modes of operation without having to explicitly define every Custom HID usage.
--- drivers/hid/wacom_sys.c | 5 +++++ drivers/hid/wacom_wac.c | 37 +++++++++++++++++++++++++++++++------ drivers/hid/wacom_wac.h | 3 +++ 3 files changed, 39 insertions(+), 6 deletions(-)
drivers/hid/wacom_sys.c +5 -0
@@ -166,6 +166,11 @@ static void wacom_feature_mapping(struct hid_device *hdev, }break ; +case WACOM_HID_WD_DATAMODE : + wacom->wacom_wac.mode_report = field->report->id; + wacom->wacom_wac.mode_value =2 ; +break ; +case WACOM_HID_UP_G9 :case WACOM_HID_UP_G11 : if (field->report->id == 0x03 &&
drivers/hid/wacom_wac.c +31 -6
@@ -1435,14 +1435,35 @@ static int wacom_tpc_irq(struct wacom_wac *wacom, size_t len)return 0 ; } +static int wacom_equivalent_usage (int usage) +{ +if ((usage &HID_USAGE_PAGE ) ==WACOM_HID_UP_WACOMDIGITIZER ) { +int subpage = (usage &0xFF00 ) <<8 ; +int subusage = (usage &0xFF ); + +if (subpage ==WACOM_HID_SP_DIGITIZER || + subpage ==WACOM_HID_SP_DIGITIZERINFO ) { +return usage; + } + +if (subpage ==HID_UP_UNDEFINED ) + subpage =HID_UP_DIGITIZER ; + +return subpage | subusage; + } + +return usage; +} +static void wacom_map_usage (struct input_dev *input,struct hid_usage *usage,struct hid_field *field,__u8 type,__u16 code,int fuzz) {int fmin = field->logical_minimum;int fmax = field->logical_maximum; +unsigned int equivalent_usage =wacom_equivalent_usage (usage->hid);int resolution_code = code; -if (usage->hid ==HID_DG_TWIST ) { +if (equivalent_usage ==HID_DG_TWIST ) { resolution_code =ABS_RZ ; }
@@ -1472,8 +1493,9 @@ static void wacom_wac_pen_usage_mapping(struct hid_device *hdev,struct wacom *wacom =hid_get_drvdata (hdev);struct wacom_wac *wacom_wac = &wacom->wacom_wac;struct input_dev *input = wacom_wac->pen_input; +unsigned equivalent_usage =wacom_equivalent_usage (usage->hid); -switch (usage->hid) { +switch (equivalent_usage) {case HID_GD_X :wacom_map_usage (input, usage, field,EV_ABS ,ABS_X ,4 );break ;
@@ -1524,8 +1546,9 @@ static int wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field,struct wacom *wacom =hid_get_drvdata (hdev);struct wacom_wac *wacom_wac = &wacom->wacom_wac;struct input_dev *input = wacom_wac->pen_input; +unsigned equivalent_usage =wacom_equivalent_usage (usage->hid); -switch (usage->hid) { +switch (equivalent_usage) {case HID_GD_Z :/* * HID_GD_Z "should increase as the control's position is
@@ -1598,8 +1621,9 @@ static void wacom_wac_finger_usage_mapping(struct hid_device *hdev,struct wacom_features *features = &wacom_wac->features;struct input_dev *input = wacom_wac->touch_input;unsigned touch_max = wacom_wac->features.touch_max; +unsigned equivalent_usage =wacom_equivalent_usage (usage->hid); -switch (usage->hid) { +switch (equivalent_usage) {case HID_GD_X : features->last_slot_field = usage->hid;if (touch_max ==1 )
@@ -1687,8 +1711,9 @@ static int wacom_wac_finger_event(struct hid_device *hdev, {struct wacom *wacom =hid_get_drvdata (hdev);struct wacom_wac *wacom_wac = &wacom->wacom_wac; +unsigned equivalent_usage =wacom_equivalent_usage (usage->hid); -switch (usage->hid) { +switch (equivalent_usage) {case HID_GD_X : wacom_wac->hid_data.x = value;break ;
@@ -1711,7 +1736,7 @@ static int wacom_wac_finger_event(struct hid_device *hdev,if (usage->usage_index +1 == field->report_count) { -if (usage->hid == wacom_wac->features.last_slot_field) +if (equivalent_usage == wacom_wac->features.last_slot_field)wacom_wac_finger_slot (wacom_wac, wacom_wac->touch_input); }
drivers/hid/wacom_wac.h +3 -0
@@ -85,7 +85,10 @@#define WACOM_DEVICETYPE_DIRECT 0x0010#define WACOM_HID_UP_WACOMDIGITIZER 0xff0d0000 +#define WACOM_HID_SP_DIGITIZER 0x000d0000 +#define WACOM_HID_SP_DIGITIZERINFO 0x00100000#define WACOM_HID_WD_DIGITIZER (WACOM_HID_UP_WACOMDIGITIZER | 0x01) +#define WACOM_HID_WD_DATAMODE (WACOM_HID_UP_WACOMDIGITIZER | 0x1002)#define WACOM_HID_UP_G9 0xff090000#define WACOM_HID_G9_PEN (WACOM_HID_UP_G9 | 0x02)#define WACOM_HID_G9_TOUCHSCREEN (WACOM_HID_UP_G9 | 0x11)
Signature · 1 line
2.10.0
Jiri Kosina
maintainerRe: [PATCH v2 07/18] HID: wacom: generic: Support and use 'Custom HID' mode and usages
drivers/hid/wacom_wac.c static int wacom_wac_finger_event(struct hid_device *hdev, · line 1739
Quoted 6 lines · Jason Gerecke
drivers/hid/wacom_wac.c +1
-1@@ -1711,7 +1736,7 @@ static int wacom_wac_finger_event(struct hid_device *hdev,if (usage->usage_index +1 == field->report_count) { -if (usage->hid == wacom_wac->features.last_slot_field) +if (equivalent_usage == wacom_wac->features.last_slot_field)
What tree is this based on please? In all the codebase I have, last_slot_field is a member field of wacom_wac's hid_data, not a member of struct wacom_features.
Signature · 2 lines
Jiri Kosina SUSE Labs
Re: [PATCH v2 07/18] HID: wacom: generic: Support and use 'Custom HID' mode and usages
Quoted 5 lines · Jiri Kosina
Quoted 3 lines · Jason Gerecke
(quoted diff) +0
-0@@ -1711,7 +1736,7 @@ static int wacom_wac_finger_event(struct hid_device *hdev,
Quoted 8 lines
drivers/hid/wacom_wac.c static int wacom_wac_finger_event(struct hid_device *hdev, · line 1739
Quoted 3 lines
drivers/hid/wacom_wac.c +1
-1if (usage->usage_index +1 == field->report_count) { -if (usage->hid == wacom_wac->features.last_slot_field) +if (equivalent_usage == wacom_wac->features.last_slot_field)What tree is this based on please? In all the codebase I have,
last_slot_fieldis a member field of wacom_wac'shid_data, not a member of structwacom_features.
This was based on your for-4.9/wacom tree, whose tip (for me) was commit 1924e05 ("HID: wacom - add touch_arbitration parameter to wacom module").
It looks like my tree only has commit 601a22f ("HID: wacom: Report input events for each finger on generic devices") but not commit 003f50a ("HID: wacom: Update last_slot_field during pre_report phase"). Not sure why though.
What would you like me to do?
Jason
---
Now instead of four in the eights place /
you’ve got three, ‘Cause you added one /
(That is to say, eight) to the two, /
But you can’t take seven from three, /
So you look at the sixty-fours....
Jiri Kosina
maintainerRe: [PATCH v2 07/18] HID: wacom: generic: Support and use 'Custom HID' mode and usages
Quoted 9 lines · Jason Gerecke
Quoted 8 lines
drivers/hid/wacom_wac.c static int wacom_wac_finger_event(struct hid_device *hdev, · line 1739
Quoted 3 lines
drivers/hid/wacom_wac.c +1
-1if (usage->usage_index +1 == field->report_count) { -if (usage->hid == wacom_wac->features.last_slot_field) +if (equivalent_usage == wacom_wac->features.last_slot_field)What tree is this based on please? In all the codebase I have,
last_slot_fieldis a member field of wacom_wac'shid_data, not a member of structwacom_features.
Quoted 5 lines
This was based on your for-4.9/wacom tree, whose tip (for me) was commit 1924e05 ("HID: wacom - add
touch_arbitrationparameter to wacom module").It looks like my tree only has commit 601a22f ("HID: wacom: Report input events for each finger on generic devices")
Pardon me? That commit is from 2014 (3.19-rc1). It really shouldn't be used as a basis for a development.
Quoted 2 lines
but not commit 003f50a ("HID: wacom: Update
last_slot_fieldduringpre_reportphase").
That's a commit that went in for 4.9-rc1 (authored by you).
Quoted 3 lines
Not sure why though.
What would you like me to do?
Dunno where the confusion is coming from really. Could you please just rebase the patchset on top of something up to date (such as or Linus' git, master branch in my tree, or whatnot), and resubmit?
Thanks,
Signature · 2 lines
Jiri Kosina SUSE Labs
Re: [PATCH v2 07/18] HID: wacom: generic: Support and use 'Custom HID' mode and usages
Quoted 27 lines · Jiri Kosina
Quoted 9 lines · Jason Gerecke
Quoted 8 lines
drivers/hid/wacom_wac.c static int wacom_wac_finger_event(struct hid_device *hdev, · line 1739
Quoted 3 lines
drivers/hid/wacom_wac.c +1
-1if (usage->usage_index +1 == field->report_count) { -if (usage->hid == wacom_wac->features.last_slot_field) +if (equivalent_usage == wacom_wac->features.last_slot_field)What tree is this based on please? In all the codebase I have,
last_slot_fieldis a member field of wacom_wac'shid_data, not a member of structwacom_features.Quoted 5 lines
This was based on your for-4.9/wacom tree, whose tip (for me) was commit 1924e05 ("HID: wacom - add
touch_arbitrationparameter to wacom module").It looks like my tree only has commit 601a22f ("HID: wacom: Report input events for each finger on generic devices")
Pardon me? That commit is from 2014 (3.19-rc1). It really shouldn't be used as a basis for a development.
Quoted 2 lines
but not commit 003f50a ("HID: wacom: Update
last_slot_fieldduringpre_reportphase").That's a commit that went in for 4.9-rc1 (authored by you).
Quoted 2 lines
Not sure why though.
Quoted 8 lines
Quoted 1 line
What would you like me to do?
Dunno where the confusion is coming from really. Could you please just rebase the patchset on top of something up to date (such as or Linus' git, master branch in my tree, or whatnot), and resubmit?
Thanks,
New v3 patches submitted based on your master branch.
Jason
---
Now instead of four in the eights place / you’ve got three, ‘Cause you added one / (That is to say, eight) to the two, / But you can’t take seven from three, / So you look at the sixty-fours....
Re: [PATCH v2 07/18] HID: wacom: generic: Support and use 'Custom HID' mode and usages
Quoted 1 line · Jason Gerecke
New v3 patches submitted based on your master branch.
Applied to for-4.10/wacom/mobile-studio-pro, thanks.
Signature · 2 lines
Jiri Kosina SUSE Labs
PATCH v2 8/18 HID: wacom: generic: Add support for vendor-defined "Distance" usage
In reply to Jason GereckeThe vendor-defined 0xFF0D01032 ("Distance") usage is nearly equivalent to HID_GD_Z, except that the axis direction is inverted. Unlike HID_GD_Z which increases in value as the pen-to-surface distance is decreased, this usage decreases. Treat this usage as a special case to ensure we don't invert the scale to be ABS_DISTANCE compatible like we do for HID_GD_Z.
--- drivers/hid/wacom_wac.c | 4 +++- drivers/hid/wacom_wac.h | 1 + 2 files changed, 4 insertions(+), 1 deletion(-)
drivers/hid/wacom_wac.c +3 -1
@@ -1442,7 +1442,8 @@ static int wacom_equivalent_usage(int usage)int subusage = (usage &0xFF );if (subpage ==WACOM_HID_SP_DIGITIZER || - subpage ==WACOM_HID_SP_DIGITIZERINFO ) { + subpage ==WACOM_HID_SP_DIGITIZERINFO || + usage ==WACOM_HID_WD_DISTANCE ) {return usage; }
@@ -1502,6 +1503,7 @@ static void wacom_wac_pen_usage_mapping(struct hid_device *hdev,case HID_GD_Y :wacom_map_usage (input, usage, field,EV_ABS ,ABS_Y ,4 );break ; +case WACOM_HID_WD_DISTANCE :case HID_GD_Z :wacom_map_usage (input, usage, field,EV_ABS ,ABS_DISTANCE ,0 );break ;
drivers/hid/wacom_wac.h +1 -0
@@ -88,6 +88,7 @@#define WACOM_HID_SP_DIGITIZER 0x000d0000#define WACOM_HID_SP_DIGITIZERINFO 0x00100000#define WACOM_HID_WD_DIGITIZER (WACOM_HID_UP_WACOMDIGITIZER | 0x01) +#define WACOM_HID_WD_DISTANCE (WACOM_HID_UP_WACOMDIGITIZER | 0x0132)#define WACOM_HID_WD_DATAMODE (WACOM_HID_UP_WACOMDIGITIZER | 0x1002)#define WACOM_HID_UP_G9 0xff090000#define WACOM_HID_G9_PEN (WACOM_HID_UP_G9 | 0x02)
Signature · 1 line
2.10.0
PATCH v2 9/18 HID: wacom: generic: Add support for vendor-defined "Fingerwheel" usage
In reply to Jason GereckeThe airbrush fingerwheel does not have a usage that corresponds cleanly with a standard HID usage, so we add explicit support for it via its vendor-defined usage.
--- drivers/hid/wacom_wac.c | 3 +++ drivers/hid/wacom_wac.h | 1 + 2 files changed, 4 insertions(+)
drivers/hid/wacom_wac.c +3 -0
@@ -1539,6 +1539,9 @@ static void wacom_wac_pen_usage_mapping(struct hid_device *hdev,case HID_DG_TOOLSERIALNUMBER :wacom_map_usage (input, usage, field,EV_MSC ,MSC_SERIAL ,0 );break ; +case WACOM_HID_WD_FINGERWHEEL : +wacom_map_usage (input, usage, field,EV_ABS ,ABS_WHEEL ,0 ); +break ; } }
drivers/hid/wacom_wac.h +1 -0
@@ -89,6 +89,7 @@#define WACOM_HID_SP_DIGITIZERINFO 0x00100000#define WACOM_HID_WD_DIGITIZER (WACOM_HID_UP_WACOMDIGITIZER | 0x01)#define WACOM_HID_WD_DISTANCE (WACOM_HID_UP_WACOMDIGITIZER | 0x0132) +#define WACOM_HID_WD_FINGERWHEEL (WACOM_HID_UP_WACOMDIGITIZER | 0x0d03)#define WACOM_HID_WD_DATAMODE (WACOM_HID_UP_WACOMDIGITIZER | 0x1002)#define WACOM_HID_UP_G9 0xff090000#define WACOM_HID_G9_PEN (WACOM_HID_UP_G9 | 0x02)
Signature · 1 line
2.10.0
PATCH v2 10/18 HID: wacom: generic: Add support for vendor-defined "Sense" usage
In reply to Jason GereckeWacom's professional tablets beginning with the Intuos4 are capable of reporting an intermediate degree of proximity where the pen is no longer close enough to communicate with ("in prox"), but still close enough to be sensed ("in range"). This additional state is particularly useful for performing palm rejection as it allows the driver to disable the touch sensor while the pen is a greater distance from the tablet.
Like other professional tablets, the new MobileStudio Pro also reports this intermeidate "in range" proximity state. Its descriptor assigns usage 0xff0d0036 to this bit. Normally 'wacom_equivalent_usage' would translate this to the standard HID "Quality" usage, but since this has a different meaning we have it explicitly ignore the usage and define it ourselves as "Sense" (since "In Range" is already defined by the HID standard and interpreted by our driver as meaning "in prox").
--- drivers/hid/wacom_wac.c | 26 +++++++++++++++++++++++--- drivers/hid/wacom_wac.h | 3 +++ 2 files changed, 26 insertions(+), 3 deletions(-)
drivers/hid/wacom_wac.c +23 -3
@@ -1443,6 +1443,7 @@ static int wacom_equivalent_usage(int usage)if (subpage ==WACOM_HID_SP_DIGITIZER || subpage ==WACOM_HID_SP_DIGITIZERINFO || + usage ==WACOM_HID_WD_SENSE || usage ==WACOM_HID_WD_DISTANCE ) {return usage; }
@@ -1493,6 +1494,7 @@ static void wacom_wac_pen_usage_mapping(struct hid_device *hdev, {struct wacom *wacom =hid_get_drvdata (hdev);struct wacom_wac *wacom_wac = &wacom->wacom_wac; +struct wacom_features *features = &wacom_wac->features;struct input_dev *input = wacom_wac->pen_input;unsigned equivalent_usage =wacom_equivalent_usage (usage->hid);
@@ -1539,6 +1541,10 @@ static void wacom_wac_pen_usage_mapping(struct hid_device *hdev,case HID_DG_TOOLSERIALNUMBER :wacom_map_usage (input, usage, field,EV_MSC ,MSC_SERIAL ,0 );break ; +case WACOM_HID_WD_SENSE : + features->quirks |=WACOM_QUIRK_SENSE ; +wacom_map_usage (input, usage, field,EV_KEY ,BTN_TOOL_PEN ,0 ); +break ;case WACOM_HID_WD_FINGERWHEEL :wacom_map_usage (input, usage, field,EV_ABS ,ABS_WHEEL ,0 );break ;
@@ -1550,6 +1556,7 @@ static int wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field, {struct wacom *wacom =hid_get_drvdata (hdev);struct wacom_wac *wacom_wac = &wacom->wacom_wac; +struct wacom_features *features = &wacom_wac->features;struct input_dev *input = wacom_wac->pen_input;unsigned equivalent_usage =wacom_equivalent_usage (usage->hid);
@@ -1564,6 +1571,8 @@ static int wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field,break ;case HID_DG_INRANGE : wacom_wac->hid_data.inrange_state = value; +if (!(features->quirks &WACOM_QUIRK_SENSE )) + wacom_wac->hid_data.sense_state = value;return 0 ;case HID_DG_INVERT : wacom_wac->hid_data.invert_state = value;
@@ -1572,6 +1581,9 @@ static int wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field,case HID_DG_TIPSWITCH : wacom_wac->hid_data.tipswitch |= value;return 0 ; +case WACOM_HID_WD_SENSE : + wacom_wac->hid_data.sense_state = value; +return 0 ; }/* send pen events only when touch is up or forced out
@@ -1580,6 +1592,10 @@ static int wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field,if (!usage->type ||delay_pen_events (wacom_wac))return 0 ; +/* send pen events only when the pen is in/entering/leaving proximity */ +if (!wacom_wac->hid_data.inrange_state && !wacom_wac->tool[0 ]) +return 0 ; +input_event (input, usage->type, usage->code, value);return 0 ;
@@ -1598,16 +1614,17 @@ static void wacom_wac_pen_report(struct hid_device *hdev,struct wacom_wac *wacom_wac = &wacom->wacom_wac;struct input_dev *input = wacom_wac->pen_input;bool prox = wacom_wac->hid_data.inrange_state; +bool range = wacom_wac->hid_data.sense_state; -if (!wacom_wac->shared->stylus_in_proximity)/* first in prox */ +if (!wacom_wac->tool[0 ] && prox)/* first in prox */ /* Going into proximity select tool */ wacom_wac->tool[0 ] = wacom_wac->hid_data.invert_state ?BTN_TOOL_RUBBER :BTN_TOOL_PEN ;/* keep pen state for touch events */ - wacom_wac->shared->stylus_in_proximity = prox; + wacom_wac->shared->stylus_in_proximity = range; -if (!delay_pen_events (wacom_wac)) { +if (!delay_pen_events (wacom_wac) && wacom_wac->tool[0 ]) {input_report_key (input,BTN_TOUCH , wacom_wac->hid_data.tipswitch);input_report_key (input, wacom_wac->tool[0 ], prox);
@@ -1616,6 +1633,9 @@ static void wacom_wac_pen_report(struct hid_device *hdev,input_sync (input); } + +if (!prox) + wacom_wac->tool[0 ] =0 ; } static void wacom_wac_finger_usage_mapping(struct hid_device *hdev,
drivers/hid/wacom_wac.h +3 -0
@@ -74,6 +74,7 @@/* device quirks */ #define WACOM_QUIRK_BBTOUCH_LOWRES 0x0001 +#define WACOM_QUIRK_SENSE 0x0002#define WACOM_QUIRK_BATTERY 0x0008/* device types */
@@ -88,6 +89,7 @@#define WACOM_HID_SP_DIGITIZER 0x000d0000#define WACOM_HID_SP_DIGITIZERINFO 0x00100000#define WACOM_HID_WD_DIGITIZER (WACOM_HID_UP_WACOMDIGITIZER | 0x01) +#define WACOM_HID_WD_SENSE (WACOM_HID_UP_WACOMDIGITIZER | 0x36)#define WACOM_HID_WD_DISTANCE (WACOM_HID_UP_WACOMDIGITIZER | 0x0132)#define WACOM_HID_WD_FINGERWHEEL (WACOM_HID_UP_WACOMDIGITIZER | 0x0d03)#define WACOM_HID_WD_DATAMODE (WACOM_HID_UP_WACOMDIGITIZER | 0x1002)
@@ -213,6 +215,7 @@ struct wacom_shared {struct hid_data {__s16 inputmode;/* InputMode HID feature, -1 if non-existent */ __s16 inputmode_index;/* InputMode HID feature index in the report */ +bool sense_state;bool inrange_state;bool invert_state;bool tipswitch;
Signature · 1 line
2.10.0
PATCH v2 11/18 HID: wacom: Read and internally use corrected Intuos tool IDs
In reply to Jason GereckeThe 'wacom_intuos_inout' function incorrectly assmebles tool IDs from the proximity report, shifting the higher values of the ID four bits farther than intended. This problem was not detected until too late, but has not caused any issues since the incorrect IDs still fit in a 32-bit integer and userspace programs have not required the value to match the hardware (just that the values are unique and constant).
The tool IDs reported by the new MobileStudio Pro (or any future HID_GENERIC device that supports them) do not suffer from the same assembly issue, however. In order for 'wacom_intuos_get_tool_type' to work for with both codepaths, we correct this issue internally and have 'wacom_intuos_general' only mangle the ID when it is posted to userspace.
--- drivers/hid/wacom_wac.c | 38 ++++++++++++++++++++++---------------- 1 file changed, 22 insertions(+), 16 deletions(-)
drivers/hid/wacom_wac.c +22 -16
@@ -588,6 +588,11 @@ static int wacom_intuos_pad(struct wacom_wac *wacom)return 1 ; } +static int wacom_intuos_id_mangle (int tool_id) +{ +return (tool_id & ~0xFFF ) <<4 | (tool_id &0xFFF ); +} +static int wacom_intuos_get_tool_type (int tool_id) {int tool_type;
@@ -595,7 +600,7 @@ static int wacom_intuos_get_tool_type(int tool_id)switch (tool_id) {case 0x812 :/* Inking pen */ case 0x801 :/* Intuos3 Inking pen */ -case 0x120802 :/* Intuos4/5 Inking Pen */ +case 0x12802 :/* Intuos4/5 Inking Pen */ case 0x012 : tool_type =BTN_TOOL_PENCIL ;break ;
@@ -610,11 +615,11 @@ static int wacom_intuos_get_tool_type(int tool_id)case 0x804 :/* Intuos4/5 13HD/24HD Marker Pen */ case 0x8e2 :/* IntuosHT2 pen */ case 0x022 : -case 0x100804 :/* Intuos4/5 13HD/24HD Art Pen */ -case 0x140802 :/* Intuos4/5 13HD/24HD Classic Pen */ -case 0x160802 :/* Cintiq 13HD Pro Pen */ -case 0x180802 :/* DTH2242 Pen */ -case 0x100802 :/* Intuos4/5 13HD/24HD General Pen */ +case 0x10804 :/* Intuos4/5 13HD/24HD Art Pen */ +case 0x14802 :/* Intuos4/5 13HD/24HD Classic Pen */ +case 0x16802 :/* Cintiq 13HD Pro Pen */ +case 0x18802 :/* DTH2242 Pen */ +case 0x10802 :/* Intuos4/5 13HD/24HD General Pen */ tool_type =BTN_TOOL_PEN ;break ;
@@ -648,12 +653,12 @@ static int wacom_intuos_get_tool_type(int tool_id)case 0x80c :/* Intuos4/5 13HD/24HD Marker Pen Eraser */ case 0x80a :/* Intuos4/5 13HD/24HD General Pen Eraser */ case 0x90a :/* Intuos4/5 13HD/24HD Airbrush Eraser */ -case 0x14080a :/* Intuos4/5 13HD/24HD Classic Pen Eraser */ -case 0x10090a :/* Intuos4/5 13HD/24HD Airbrush Eraser */ -case 0x10080c :/* Intuos4/5 13HD/24HD Art Pen Eraser */ -case 0x16080a :/* Cintiq 13HD Pro Pen Eraser */ -case 0x18080a :/* DTH2242 Eraser */ -case 0x10080a :/* Intuos4/5 13HD/24HD General Pen Eraser */ +case 0x1480a :/* Intuos4/5 13HD/24HD Classic Pen Eraser */ +case 0x1090a :/* Intuos4/5 13HD/24HD Airbrush Eraser */ +case 0x1080c :/* Intuos4/5 13HD/24HD Art Pen Eraser */ +case 0x1680a :/* Cintiq 13HD Pro Pen Eraser */ +case 0x1880a :/* DTH2242 Eraser */ +case 0x1080a :/* Intuos4/5 13HD/24HD General Pen Eraser */ tool_type =BTN_TOOL_RUBBER ;break ;
@@ -662,7 +667,7 @@ static int wacom_intuos_get_tool_type(int tool_id)case 0x112 :case 0x913 :/* Intuos3 Airbrush */ case 0x902 :/* Intuos4/5 13HD/24HD Airbrush */ -case 0x100902 :/* Intuos4/5 13HD/24HD Airbrush */ +case 0x10902 :/* Intuos4/5 13HD/24HD Airbrush */ tool_type =BTN_TOOL_AIRBRUSH ;break ;
@@ -693,7 +698,7 @@ static int wacom_intuos_inout(struct wacom_wac *wacom) (data[6 ] <<4 ) + (data[7 ] >>4 ); wacom->id[idx] = (data[2 ] <<4 ) | (data[3 ] >>4 ) | - ((data[7 ] &0x0f ) <<20 ) | ((data[8 ] &0xf0 ) <<12 ); + ((data[7 ] &0x0f ) <<16 ) | ((data[8 ] &0xf0 ) <<8 ); wacom->tool[idx] =wacom_intuos_get_tool_type (wacom->id[idx]);
@@ -923,7 +928,7 @@ static int wacom_intuos_general(struct wacom_wac *wacom)* don't report events for invalid data */ /* older I4 styli don't work with new Cintiqs */ - if ((!((wacom->id[idx] >> 20) & 0x01) && + if ((!((wacom->id[idx] >> 16) & 0x01) && (features->type == WACOM_21UX2)) || /* Only large Intuos support Lense Cursor */ (wacom->tool[idx] == BTN_TOOL_LENS &&
@@ -1059,7 +1064,8 @@ static int wacom_intuos_general(struct wacom_wac *wacom)break ; } -input_report_abs (input,ABS_MISC , wacom->id[idx]);/* report tool id */ +input_report_abs (input,ABS_MISC , +wacom_intuos_id_mangle (wacom->id[idx]));/* report tool id */ input_report_key (input, wacom->tool[idx],1 );input_event (input,EV_MSC ,MSC_SERIAL , wacom->serial[idx]); wacom->reporting_data = true;
Signature · 1 line
2.10.0
PATCH v2 12/18 HID: wacom: generic: Support tool ID and additional tool types
In reply to Jason GereckeDevices following the new Custom HID mode specification (as well as even some recent component sensors which use the same standard HID usage) are capable of reporting tool ID information that we need to relay to userspace. This patch adds support for reading and relaying the tool type information, which is (unfortunately) split across two usages. We also advertise the existence of tool types beyond BTN_TOOL_PEN that might be available.
--- drivers/hid/wacom_wac.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++--- drivers/hid/wacom_wac.h | 4 ++- 2 files changed, 71 insertions(+), 5 deletions(-)
drivers/hid/wacom_wac.c +68 -4
@@ -1450,6 +1450,8 @@ static int wacom_equivalent_usage(int usage)if (subpage ==WACOM_HID_SP_DIGITIZER || subpage ==WACOM_HID_SP_DIGITIZERINFO || usage ==WACOM_HID_WD_SENSE || + usage ==WACOM_HID_WD_SERIALHI || + usage ==WACOM_HID_WD_TOOLTYPE || usage ==WACOM_HID_WD_DISTANCE ) {return usage; }
@@ -1551,6 +1553,17 @@ static void wacom_wac_pen_usage_mapping(struct hid_device *hdev, features->quirks |=WACOM_QUIRK_SENSE ;wacom_map_usage (input, usage, field,EV_KEY ,BTN_TOOL_PEN ,0 );break ; +case WACOM_HID_WD_SERIALHI : +wacom_map_usage (input, usage, field,EV_ABS ,ABS_MISC ,0 ); +set_bit (EV_KEY , input->evbit); +input_set_capability (input,EV_KEY ,BTN_TOOL_PEN ); +input_set_capability (input,EV_KEY ,BTN_TOOL_RUBBER ); +input_set_capability (input,EV_KEY ,BTN_TOOL_BRUSH ); +input_set_capability (input,EV_KEY ,BTN_TOOL_PENCIL ); +input_set_capability (input,EV_KEY ,BTN_TOOL_AIRBRUSH ); +input_set_capability (input,EV_KEY ,BTN_TOOL_MOUSE ); +input_set_capability (input,EV_KEY ,BTN_TOOL_LENS ); +break ;case WACOM_HID_WD_FINGERWHEEL :wacom_map_usage (input, usage, field,EV_ABS ,ABS_WHEEL ,0 );break ;
@@ -1587,9 +1600,35 @@ static int wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field,case HID_DG_TIPSWITCH : wacom_wac->hid_data.tipswitch |= value;return 0 ; +case HID_DG_TOOLSERIALNUMBER : + wacom_wac->serial[0 ] = (wacom_wac->serial[0 ] & ~0xFFFFFFFF ); + wacom_wac->serial[0 ] |= value; +return 0 ;case WACOM_HID_WD_SENSE : wacom_wac->hid_data.sense_state = value;return 0 ; +case WACOM_HID_WD_SERIALHI : + wacom_wac->serial[0 ] = (wacom_wac->serial[0 ] &0xFFFFFFFF ); + wacom_wac->serial[0 ] |= ((__u64 )value) <<32 ; +/* +* Non-USI EMR devices may contain additional tool type +* information here. See WACOM_HID_WD_TOOLTYPE case for +* more details. +*/ +if (value >>20 ==1 ) { + wacom_wac->id[0 ] |= value &0xFFFFF ; + } +return 0 ; +case WACOM_HID_WD_TOOLTYPE : +/* +* Some devices (MobileStudio Pro, and possibly later +* devices as well) do not return the complete tool +* type in their WACOM_HID_WD_TOOLTYPE usage. Use a +* bitwise OR so the complete value can be built +* up over time :( +*/ + wacom_wac->id[0 ] |= value; +return 0 ; }/* send pen events only when touch is up or forced out
@@ -1622,26 +1661,51 @@ static void wacom_wac_pen_report(struct hid_device *hdev,bool prox = wacom_wac->hid_data.inrange_state;bool range = wacom_wac->hid_data.sense_state; -if (!wacom_wac->tool[0 ] && prox)/* first in prox */ +if (!wacom_wac->tool[0 ] && prox) {/* first in prox */ /* Going into proximity select tool */ - wacom_wac->tool[0 ] = wacom_wac->hid_data.invert_state ? -BTN_TOOL_RUBBER :BTN_TOOL_PEN ; +if (wacom_wac->hid_data.invert_state) + wacom_wac->tool[0 ] =BTN_TOOL_RUBBER ; +else if (wacom_wac->id[0 ]) + wacom_wac->tool[0 ] =wacom_intuos_get_tool_type (wacom_wac->id[0 ]); +else + wacom_wac->tool[0 ] =BTN_TOOL_PEN ; + }/* keep pen state for touch events */ wacom_wac->shared->stylus_in_proximity = range;if (!delay_pen_events (wacom_wac) && wacom_wac->tool[0 ]) { +int id = wacom_wac->id[0 ]; + +/* +* Non-USI EMR tools should have their IDs mangled to +* match the legacy behavior of wacom_intuos_general +*/ +if (wacom_wac->serial[0 ] >>52 ==1 ) + id =wacom_intuos_id_mangle (id); + +/* +* To ensure compatibility with xf86-input-wacom, we should +* report the BTN_TOOL_* event prior to the ABS_MISC or +* MSC_SERIAL events. +*/ input_report_key (input,BTN_TOUCH , wacom_wac->hid_data.tipswitch);input_report_key (input, wacom_wac->tool[0 ], prox); +if (wacom_wac->serial[0 ]) { +input_event (input,EV_MSC ,MSC_SERIAL , wacom_wac->serial[0 ]); +input_report_abs (input,ABS_MISC , id); + } wacom_wac->hid_data.tipswitch = false;input_sync (input); } -if (!prox) +if (!prox) { wacom_wac->tool[0 ] =0 ; + wacom_wac->id[0 ] =0 ; + } } static void wacom_wac_finger_usage_mapping(struct hid_device *hdev,
drivers/hid/wacom_wac.h +3 -1
@@ -90,6 +90,8 @@#define WACOM_HID_SP_DIGITIZERINFO 0x00100000#define WACOM_HID_WD_DIGITIZER (WACOM_HID_UP_WACOMDIGITIZER | 0x01)#define WACOM_HID_WD_SENSE (WACOM_HID_UP_WACOMDIGITIZER | 0x36) +#define WACOM_HID_WD_SERIALHI (WACOM_HID_UP_WACOMDIGITIZER | 0x5c) +#define WACOM_HID_WD_TOOLTYPE (WACOM_HID_UP_WACOMDIGITIZER | 0x77)#define WACOM_HID_WD_DISTANCE (WACOM_HID_UP_WACOMDIGITIZER | 0x0132)#define WACOM_HID_WD_FINGERWHEEL (WACOM_HID_UP_WACOMDIGITIZER | 0x0d03)#define WACOM_HID_WD_DATAMODE (WACOM_HID_UP_WACOMDIGITIZER | 0x1002)
@@ -247,7 +249,7 @@ struct wacom_wac {unsigned char data[WACOM_PKGLEN_MAX ];int tool[2 ];int id[2 ]; -__u32 serial[2 ]; +__u64 serial[2 ];bool reporting_data;struct wacom_features features;struct wacom_shared *shared;
Signature · 1 line
2.10.0
PATCH v2 13/18 HID: wacom: Fix sensor outbounds and redefine as offsets from each edge
In reply to Jason GereckeMany of Wacom's display tablets include an "outbound" area where pen digitizing is possible but outside of the display area. To ensure that pen coordinates are mapped to the correct on-screen location, the driver sets the minimum and maximum axis values of X and Y to those coordinates which coincide with the screen edge. These values are simply the hardware minimum/maximum plus/minus the outbound size for a particular edge.
When outbound support was added/updated in ac414da, fa77034, and ecd618d, we decided to have the wacom_features structs store the desired minimum and maximum values directly. In hindsight, this was perhaps not the best choice since it has allowed minor errors to crop up unnoticed. Some tablets have had their coordinates over-corrected (e.g. most of the devices "fixed" in ecd618d were already adjusted in ac414da), while others never had a correction applied (e.g. the ISDv5 325, whose declared maximum the hardware maximum instead of the outbound maximum).
A less error-prone method of handling the outbound is to let the driver calculate the correct minimum/maximum values by providing it with both the actual hardware maximums and the size of the outbound on each edge. These values are more easy to verify as correct since the values can be trivially compared against specifications.
This patch reverts the declared maximum values to the actual hardware maximums, e.g. as declared prior to ac414da (values for these and other display tablets that were subsuquently introduced have been verified against specs). Per-edge outbound sizes are stored in the wacom_features struct as offset_{left,right,top,bottom} and used in combination with the hardware ranges to calculate effective axis ranges for ABS_X and ABS_Y.
--- drivers/hid/wacom_wac.c | 62 ++++++++++++++++++++++++++++++++----------------- drivers/hid/wacom_wac.h | 6 +++-- 2 files changed, 45 insertions(+), 23 deletions(-)
drivers/hid/wacom_wac.c +41 -21
@@ -2684,10 +2684,12 @@ int wacom_setup_pen_input_capabilities(struct input_dev *input_dev,__set_bit (BTN_TOUCH , input_dev->keybit);__set_bit (ABS_MISC , input_dev->absbit); -input_set_abs_params (input_dev,ABS_X , features->x_min, - features->x_max, features->x_fuzz,0 ); -input_set_abs_params (input_dev,ABS_Y , features->y_min, - features->y_max, features->y_fuzz,0 ); +input_set_abs_params (input_dev,ABS_X ,0 + features->offset_left, + features->x_max - features->offset_right, + features->x_fuzz,0 ); +input_set_abs_params (input_dev,ABS_Y ,0 + features->offset_top, + features->y_max - features->offset_bottom, + features->y_fuzz,0 );input_set_abs_params (input_dev,ABS_PRESSURE ,0 , features->pressure_max, features->pressure_fuzz,0 );
@@ -3399,26 +3401,30 @@ static const struct wacom_features wacom_features_0x317 = INTUOSPL, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 9, .touch_max = 16, .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE };static const struct wacom_features wacom_features_0xF4 = - {"Wacom Cintiq 24HD" ,104080 ,65200 ,2047 ,63 , + {"Wacom Cintiq 24HD" ,104480 ,65600 ,2047 ,63 ,WACOM_24HD ,WACOM_INTUOS3_RES ,WACOM_INTUOS3_RES ,16 , +WACOM_CINTIQ_OFFSET ,WACOM_CINTIQ_OFFSET ,WACOM_CINTIQ_OFFSET ,WACOM_CINTIQ_OFFSET };static const struct wacom_features wacom_features_0xF8 = - {"Wacom Cintiq 24HD touch" ,104080 ,65200 ,2047 ,63 ,/* Pen */ + {"Wacom Cintiq 24HD touch" ,104480 ,65600 ,2047 ,63 ,/* Pen */ WACOM_24HD ,WACOM_INTUOS3_RES ,WACOM_INTUOS3_RES ,16 ,WACOM_CINTIQ_OFFSET ,WACOM_CINTIQ_OFFSET , +WACOM_CINTIQ_OFFSET ,WACOM_CINTIQ_OFFSET , .oVid =USB_VENDOR_ID_WACOM , .oPid =0xf6 };static const struct wacom_features wacom_features_0xF6 = {"Wacom Cintiq 24HD touch" , .type =WACOM_24HDT ,/* Touch */ .oVid =USB_VENDOR_ID_WACOM , .oPid =0xf8 , .touch_max =10 , .check_for_hid_type = true, .hid_type =HID_TYPE_USBNONE };static const struct wacom_features wacom_features_0x32A = - {"Wacom Cintiq 27QHD" ,119740 ,67520 ,2047 ,63 , + {"Wacom Cintiq 27QHD" ,120140 ,67920 ,2047 ,63 ,WACOM_27QHD ,WACOM_INTUOS3_RES ,WACOM_INTUOS3_RES ,0 , +WACOM_CINTIQ_OFFSET ,WACOM_CINTIQ_OFFSET ,WACOM_CINTIQ_OFFSET ,WACOM_CINTIQ_OFFSET };static const struct wacom_features wacom_features_0x32B = - {"Wacom Cintiq 27QHD touch" ,119740 ,67520 ,2047 ,63 , + {"Wacom Cintiq 27QHD touch" ,120140 ,67920 ,2047 ,63 ,WACOM_27QHD ,WACOM_INTUOS3_RES ,WACOM_INTUOS3_RES ,0 ,WACOM_CINTIQ_OFFSET ,WACOM_CINTIQ_OFFSET , +WACOM_CINTIQ_OFFSET ,WACOM_CINTIQ_OFFSET , .oVid =USB_VENDOR_ID_WACOM , .oPid =0x32C };static const struct wacom_features wacom_features_0x32C = {"Wacom Cintiq 27QHD touch" , .type =WACOM_27QHDT ,
@@ -3433,13 +3439,15 @@ static const struct wacom_features wacom_features_0xC6 = {"Wacom Cintiq 12WX" ,53020 ,33440 ,1023 ,63 , WACOM_BEE, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 10 };static const struct wacom_features wacom_features_0x304 = - {"Wacom Cintiq 13HD" ,59152 ,33448 ,1023 ,63 , + {"Wacom Cintiq 13HD" ,59552 ,33848 ,1023 ,63 ,WACOM_13HD ,WACOM_INTUOS3_RES ,WACOM_INTUOS3_RES ,9 , +WACOM_CINTIQ_OFFSET ,WACOM_CINTIQ_OFFSET ,WACOM_CINTIQ_OFFSET ,WACOM_CINTIQ_OFFSET };static const struct wacom_features wacom_features_0x333 = - {"Wacom Cintiq 13HD touch" ,59152 ,33448 ,2047 ,63 , + {"Wacom Cintiq 13HD touch" ,59552 ,33848 ,2047 ,63 ,WACOM_13HD ,WACOM_INTUOS3_RES ,WACOM_INTUOS3_RES ,9 ,WACOM_CINTIQ_OFFSET ,WACOM_CINTIQ_OFFSET , +WACOM_CINTIQ_OFFSET ,WACOM_CINTIQ_OFFSET , .oVid =USB_VENDOR_ID_WACOM , .oPid =0x335 };static const struct wacom_features wacom_features_0x335 = { "Wacom Cintiq 13HD touch", .type = WACOM_24HDT, /* Touch */
@@ -3456,42 +3464,50 @@ static const struct wacom_features wacom_features_0xF0 = {"Wacom DTU1631" ,34623 ,19553 ,511 ,0 , DTU, WACOM_INTUOS_RES, WACOM_INTUOS_RES };static const struct wacom_features wacom_features_0xFB = - {"Wacom DTU1031" ,21896 ,13760 ,511 ,0 , + {"Wacom DTU1031" ,22096 ,13960 ,511 ,0 ,DTUS ,WACOM_INTUOS_RES ,WACOM_INTUOS_RES ,4 , +WACOM_DTU_OFFSET ,WACOM_DTU_OFFSET ,WACOM_DTU_OFFSET ,WACOM_DTU_OFFSET };static const struct wacom_features wacom_features_0x32F = - {"Wacom DTU1031X" ,22472 ,12728 ,511 ,0 , + {"Wacom DTU1031X" ,22672 ,12928 ,511 ,0 ,DTUSX ,WACOM_INTUOS_RES ,WACOM_INTUOS_RES ,0 , +WACOM_DTU_OFFSET ,WACOM_DTU_OFFSET ,WACOM_DTU_OFFSET ,WACOM_DTU_OFFSET };static const struct wacom_features wacom_features_0x336 = - {"Wacom DTU1141" ,23472 ,13203 ,1023 ,0 , + {"Wacom DTU1141" ,23672 ,13403 ,1023 ,0 ,DTUS ,WACOM_INTUOS_RES ,WACOM_INTUOS_RES ,4 , +WACOM_DTU_OFFSET ,WACOM_DTU_OFFSET ,WACOM_DTU_OFFSET ,WACOM_DTU_OFFSET };static const struct wacom_features wacom_features_0x57 = - {"Wacom DTK2241" ,95640 ,54060 ,2047 ,63 , + {"Wacom DTK2241" ,95840 ,54260 ,2047 ,63 ,DTK ,WACOM_INTUOS3_RES ,WACOM_INTUOS3_RES ,6 , +WACOM_CINTIQ_OFFSET ,WACOM_CINTIQ_OFFSET ,WACOM_CINTIQ_OFFSET ,WACOM_CINTIQ_OFFSET };static const struct wacom_features wacom_features_0x59 =/* Pen */ - {"Wacom DTH2242" ,95640 ,54060 ,2047 ,63 , + {"Wacom DTH2242" ,95840 ,54260 ,2047 ,63 ,DTK ,WACOM_INTUOS3_RES ,WACOM_INTUOS3_RES ,6 ,WACOM_CINTIQ_OFFSET ,WACOM_CINTIQ_OFFSET , +WACOM_CINTIQ_OFFSET ,WACOM_CINTIQ_OFFSET , .oVid =USB_VENDOR_ID_WACOM , .oPid =0x5D };static const struct wacom_features wacom_features_0x5D =/* Touch */ {"Wacom DTH2242" , .type =WACOM_24HDT , .oVid =USB_VENDOR_ID_WACOM , .oPid =0x59 , .touch_max =10 , .check_for_hid_type = true, .hid_type =HID_TYPE_USBNONE };static const struct wacom_features wacom_features_0xCC = - {"Wacom Cintiq 21UX2" ,86800 ,65200 ,2047 ,63 , + {"Wacom Cintiq 21UX2" ,87200 ,65600 ,2047 ,63 ,WACOM_21UX2 ,WACOM_INTUOS3_RES ,WACOM_INTUOS3_RES ,18 , +WACOM_CINTIQ_OFFSET ,WACOM_CINTIQ_OFFSET ,WACOM_CINTIQ_OFFSET ,WACOM_CINTIQ_OFFSET };static const struct wacom_features wacom_features_0xFA = - {"Wacom Cintiq 22HD" ,95440 ,53860 ,2047 ,63 , + {"Wacom Cintiq 22HD" ,95840 ,54260 ,2047 ,63 ,WACOM_22HD ,WACOM_INTUOS3_RES ,WACOM_INTUOS3_RES ,18 , +WACOM_CINTIQ_OFFSET ,WACOM_CINTIQ_OFFSET ,WACOM_CINTIQ_OFFSET ,WACOM_CINTIQ_OFFSET };static const struct wacom_features wacom_features_0x5B = - {"Wacom Cintiq 22HDT" ,95440 ,53860 ,2047 ,63 , + {"Wacom Cintiq 22HDT" ,95840 ,54260 ,2047 ,63 ,WACOM_22HD ,WACOM_INTUOS3_RES ,WACOM_INTUOS3_RES ,18 ,WACOM_CINTIQ_OFFSET ,WACOM_CINTIQ_OFFSET , +WACOM_CINTIQ_OFFSET ,WACOM_CINTIQ_OFFSET , .oVid =USB_VENDOR_ID_WACOM , .oPid =0x5e };static const struct wacom_features wacom_features_0x5E = { "Wacom Cintiq 22HDT", .type = WACOM_24HDT,
@@ -3635,18 +3651,20 @@ static const struct wacom_features wacom_features_0x6004 = {"ISD-V4" ,12800 ,8000 ,255 ,0 , TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };static const struct wacom_features wacom_features_0x307 = - {"Wacom ISDv5 307" ,59152 ,33448 ,2047 ,63 , + {"Wacom ISDv5 307" ,59552 ,33848 ,2047 ,63 ,CINTIQ_HYBRID ,WACOM_INTUOS3_RES ,WACOM_INTUOS3_RES ,9 ,WACOM_CINTIQ_OFFSET ,WACOM_CINTIQ_OFFSET , +WACOM_CINTIQ_OFFSET ,WACOM_CINTIQ_OFFSET , .oVid =USB_VENDOR_ID_WACOM , .oPid =0x309 };static const struct wacom_features wacom_features_0x309 = {"Wacom ISDv5 309" , .type =WACOM_24HDT ,/* Touch */ .oVid =USB_VENDOR_ID_WACOM , .oPid =0x0307 , .touch_max =10 , .check_for_hid_type = true, .hid_type =HID_TYPE_USBNONE };static const struct wacom_features wacom_features_0x30A = - {"Wacom ISDv5 30A" ,59152 ,33448 ,2047 ,63 , + {"Wacom ISDv5 30A" ,59552 ,33848 ,2047 ,63 ,CINTIQ_HYBRID ,WACOM_INTUOS3_RES ,WACOM_INTUOS3_RES ,9 ,WACOM_CINTIQ_OFFSET ,WACOM_CINTIQ_OFFSET , +WACOM_CINTIQ_OFFSET ,WACOM_CINTIQ_OFFSET , .oVid =USB_VENDOR_ID_WACOM , .oPid =0x30C };static const struct wacom_features wacom_features_0x30C = { "Wacom ISDv5 30C", .type = WACOM_24HDT, /* Touch */
@@ -3662,6 +3680,7 @@ static const struct wacom_features wacom_features_0x325 = {"Wacom ISDv5 325" ,59552 ,33848 ,2047 ,63 ,CINTIQ_COMPANION_2 ,WACOM_INTUOS3_RES ,WACOM_INTUOS3_RES ,11 ,WACOM_CINTIQ_OFFSET ,WACOM_CINTIQ_OFFSET , +WACOM_CINTIQ_OFFSET ,WACOM_CINTIQ_OFFSET , .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x326 };static const struct wacom_features wacom_features_0x326 =/* Touch */ { "Wacom ISDv5 326", .type = HID_GENERIC, .oVid = USB_VENDOR_ID_WACOM,
@@ -3691,8 +3710,9 @@ static const struct wacom_features wacom_features_0x33E = INTUOSHT2, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 16, .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE };static const struct wacom_features wacom_features_0x343 = - {"Wacom DTK1651" ,34616 ,19559 ,1023 ,0 , + {"Wacom DTK1651" ,34816 ,19759 ,1023 ,0 ,DTUS ,WACOM_INTUOS_RES ,WACOM_INTUOS_RES ,4 , +WACOM_DTU_OFFSET ,WACOM_DTU_OFFSET ,WACOM_DTU_OFFSET ,WACOM_DTU_OFFSET }; static const struct wacom_features wacom_features_HID_ANY_ID =
drivers/hid/wacom_wac.h +4 -2
@@ -181,8 +181,10 @@ struct wacom_features {int x_resolution;int y_resolution;int numbered_buttons; -int x_min; -int y_min; +int offset_left; +int offset_right; +int offset_top; +int offset_bottom;int device_type;int x_phy;int y_phy;
Signature · 1 line
2.10.0
PATCH v2 14/18 HID: wacom: generic: Add support for sensor offsets
In reply to Jason GereckeMany of Wacom's display tablets include an "outbound" area where pen digitizing is possible but outside of the display area. To accommodate such sensors in the HID_GENERIC codepath, we add support for the necessary vendor-defined HID feature usages and adjust the min/max values of the X and Y axes accordingly, similar to what is done in the non-generic codepath.
---
Changes from v1:
* Use input_get_drvdata instead of hid_get_drvdata. This removes the need for a "Pass 'hdev' to 'wacom_map_usage'" patch, which is no longer part of the v2 set.
drivers/hid/wacom_sys.c | 38 ++++++++++++++++++++++++++++++-------- drivers/hid/wacom_wac.c | 40 ++++++++++++++++++++++++++++++++++++++++ drivers/hid/wacom_wac.h | 4 ++++ 3 files changed, 74 insertions(+), 8 deletions(-)
drivers/hid/wacom_sys.c +30 -8
@@ -122,6 +122,7 @@ static void wacom_feature_mapping(struct hid_device *hdev,struct hid_data *hid_data = &wacom->wacom_wac.hid_data;u8 *data;int ret; +int n;switch (usage->hid) {case HID_DG_CONTACTMAX :
@@ -180,6 +181,27 @@ static void wacom_feature_mapping(struct hid_device *hdev, wacom->wacom_wac.mode_value =0 ; }break ; +case WACOM_HID_WD_OFFSETLEFT : +case WACOM_HID_WD_OFFSETTOP : +case WACOM_HID_WD_OFFSETRIGHT : +case WACOM_HID_WD_OFFSETBOTTOM : +/* read manually */ + n =hid_report_len (field->report); + data =hid_alloc_report_buf (field->report,GFP_KERNEL ); +if (!data) +break ; + data[0 ] = field->report->id; + ret =wacom_get_report (hdev,HID_FEATURE_REPORT , + data, n,WAC_CMD_RETRIES ); +if (ret == n) { + ret =hid_report_raw_event (hdev,HID_FEATURE_REPORT , + data, n,0 ); + }else { +hid_warn (hdev,"%s: could not retrieve sensor offsets\n" , + __func__); + } +kfree (data); +break ; } }
@@ -718,11 +740,6 @@ static int wacom_add_shared_data(struct hid_device *hdev)return retval; } -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; - out:mutex_unlock (&wacom_udev_list_lock);return retval;
@@ -2019,6 +2036,10 @@ static int wacom_parse_and_register(struct wacom *wacom, bool wireless)if (error) goto fail; + error =wacom_add_shared_data (hdev); +if (error) + goto fail; +/* * Bamboo Pad has a generic hid handling for the Pen, and we switch it * into debug mode for the touch part.
@@ -2059,9 +2080,10 @@ static int wacom_parse_and_register(struct wacom *wacom, bool wireless)wacom_update_name (wacom, wireless ?" (WL)" :"" ); - error =wacom_add_shared_data (hdev); -if (error) - goto fail; +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;if (!(features->device_type &WACOM_DEVICETYPE_WL_MONITOR ) && (features->quirks &WACOM_QUIRK_BATTERY )) {
drivers/hid/wacom_wac.c +40 -0
@@ -1468,6 +1468,9 @@ static int wacom_equivalent_usage(int usage)static void wacom_map_usage (struct input_dev *input,struct hid_usage *usage,struct hid_field *field,__u8 type,__u16 code,int fuzz) { +struct wacom *wacom =input_get_drvdata (input); +struct wacom_wac *wacom_wac = &wacom->wacom_wac; +struct wacom_features *features = &wacom_wac->features;int fmin = field->logical_minimum;int fmax = field->logical_maximum;unsigned int equivalent_usage =wacom_equivalent_usage (usage->hid);
@@ -1477,6 +1480,15 @@ static void wacom_map_usage(struct input_dev *input, struct hid_usage *usage, resolution_code =ABS_RZ ; } +if (equivalent_usage ==HID_GD_X ) { + fmin += features->offset_left; + fmax -= features->offset_right; + } +if (equivalent_usage ==HID_GD_Y ) { + fmin += features->offset_top; + fmax -= features->offset_bottom; + } + usage->type = type; usage->code = code;
@@ -1629,6 +1641,34 @@ static int wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field,*/ wacom_wac->id[0 ] |= value;return 0 ; +case WACOM_HID_WD_OFFSETLEFT : +if (features->offset_left && value != features->offset_left) +hid_warn (hdev,"%s: overriding exising left offset " +"%d -> %d\n" , __func__, value, + features->offset_left); + features->offset_left = value; +return 0 ; +case WACOM_HID_WD_OFFSETRIGHT : +if (features->offset_right && value != features->offset_right) +hid_warn (hdev,"%s: overriding exising right offset " +"%d -> %d\n" , __func__, value, + features->offset_right); + features->offset_right = value; +return 0 ; +case WACOM_HID_WD_OFFSETTOP : +if (features->offset_top && value != features->offset_top) +hid_warn (hdev,"%s: overriding exising top offset " +"%d -> %d\n" , __func__, value, + features->offset_top); + features->offset_top = value; +return 0 ; +case WACOM_HID_WD_OFFSETBOTTOM : +if (features->offset_bottom && value != features->offset_bottom) +hid_warn (hdev,"%s: overriding exising bottom offset " +"%d -> %d\n" , __func__, value, + features->offset_bottom); + features->offset_bottom = value; +return 0 ; }/* send pen events only when touch is up or forced out
drivers/hid/wacom_wac.h +4 -0
@@ -94,6 +94,10 @@#define WACOM_HID_WD_TOOLTYPE (WACOM_HID_UP_WACOMDIGITIZER | 0x77)#define WACOM_HID_WD_DISTANCE (WACOM_HID_UP_WACOMDIGITIZER | 0x0132)#define WACOM_HID_WD_FINGERWHEEL (WACOM_HID_UP_WACOMDIGITIZER | 0x0d03) +#define WACOM_HID_WD_OFFSETLEFT (WACOM_HID_UP_WACOMDIGITIZER | 0x0d30) +#define WACOM_HID_WD_OFFSETTOP (WACOM_HID_UP_WACOMDIGITIZER | 0x0d31) +#define WACOM_HID_WD_OFFSETRIGHT (WACOM_HID_UP_WACOMDIGITIZER | 0x0d32) +#define WACOM_HID_WD_OFFSETBOTTOM (WACOM_HID_UP_WACOMDIGITIZER | 0x0d33)#define WACOM_HID_WD_DATAMODE (WACOM_HID_UP_WACOMDIGITIZER | 0x1002)#define WACOM_HID_UP_G9 0xff090000#define WACOM_HID_G9_PEN (WACOM_HID_UP_G9 | 0x02)
Signature · 1 line
2.10.0
PATCH v2 15/18 HID: wacom: generic: Introduce pad support
In reply to Jason GereckeAs with usages for the pen, the Custom HID specificiation includes usages for the pad. Here we add functions to map and handle most of the pad usages present on the MobileStudio Pro.
--- drivers/hid/wacom_wac.c | 143 ++++++++++++++++++++++++++++++++++++++++++------ drivers/hid/wacom_wac.h | 19 +++++++ 2 files changed, 146 insertions(+), 16 deletions(-)
drivers/hid/wacom_wac.c +127 -16
@@ -41,6 +41,8 @@ MODULE_PARM_DESC(touch_arbitration, " on (Y) off (N)");static void wacom_report_numbered_buttons (struct input_dev *input_dev,int button_count,int mask); +static int wacom_numbered_button_to_key (int n); +/* * Percent of battery capacity for Graphire. * 8th value means AC online and show 100% capacity.
@@ -1447,12 +1449,16 @@ static int wacom_equivalent_usage(int usage)int subpage = (usage &0xFF00 ) <<8 ;int subusage = (usage &0xFF ); -if (subpage ==WACOM_HID_SP_DIGITIZER || +if (subpage ==WACOM_HID_SP_PAD || + subpage ==WACOM_HID_SP_BUTTON || + subpage ==WACOM_HID_SP_DIGITIZER || subpage ==WACOM_HID_SP_DIGITIZERINFO || usage ==WACOM_HID_WD_SENSE || usage ==WACOM_HID_WD_SERIALHI || usage ==WACOM_HID_WD_TOOLTYPE || - usage ==WACOM_HID_WD_DISTANCE ) { + usage ==WACOM_HID_WD_DISTANCE || + usage ==WACOM_HID_WD_TOUCHRING || + usage ==WACOM_HID_WD_TOUCHRINGSTATUS ) {return usage; }
@@ -1509,6 +1515,98 @@ static void wacom_map_usage(struct input_dev *input, struct hid_usage *usage, } } +static void wacom_wac_pad_usage_mapping (struct hid_device *hdev, +struct hid_field *field,struct hid_usage *usage) +{ +struct wacom *wacom =hid_get_drvdata (hdev); +struct wacom_wac *wacom_wac = &wacom->wacom_wac; +struct wacom_features *features = &wacom_wac->features; +struct input_dev *input = wacom_wac->pad_input; +unsigned equivalent_usage =wacom_equivalent_usage (usage->hid); + +switch (equivalent_usage) { +case WACOM_HID_WD_ACCELEROMETER_X : +__set_bit (INPUT_PROP_ACCELEROMETER , input->propbit); +wacom_map_usage (input, usage, field,EV_ABS ,ABS_X ,0 ); +break ; +case WACOM_HID_WD_ACCELEROMETER_Y : +__set_bit (INPUT_PROP_ACCELEROMETER , input->propbit); +wacom_map_usage (input, usage, field,EV_ABS ,ABS_Y ,0 ); +break ; +case WACOM_HID_WD_ACCELEROMETER_Z : +__set_bit (INPUT_PROP_ACCELEROMETER , input->propbit); +wacom_map_usage (input, usage, field,EV_ABS ,ABS_Z ,0 ); +break ; +case WACOM_HID_WD_BUTTONHOME : +case WACOM_HID_WD_BUTTONUP : +case WACOM_HID_WD_BUTTONDOWN : +case WACOM_HID_WD_BUTTONLEFT : +case WACOM_HID_WD_BUTTONRIGHT : +wacom_map_usage (input, usage, field,EV_KEY , +wacom_numbered_button_to_key (features->numbered_buttons), +0 ); + features->numbered_buttons++; +break ; +case WACOM_HID_WD_TOUCHRING : +wacom_map_usage (input, usage, field,EV_ABS ,ABS_WHEEL ,0 ); +break ; + } + +switch (equivalent_usage &0xfffffff0 ) { +case WACOM_HID_WD_EXPRESSKEY00 : +wacom_map_usage (input, usage, field,EV_KEY , +wacom_numbered_button_to_key (features->numbered_buttons), +0 ); + features->numbered_buttons++; +break ; + } +} + +static int wacom_wac_pad_event (struct hid_device *hdev,struct hid_field *field, +struct hid_usage *usage,__s32 value) +{ +struct wacom *wacom =hid_get_drvdata (hdev); +struct wacom_wac *wacom_wac = &wacom->wacom_wac; +struct input_dev *input = wacom_wac->pad_input; +unsigned equivalent_usage =wacom_equivalent_usage (usage->hid); + +if (wacom_equivalent_usage (field->physical) ==HID_DG_TABLETFUNCTIONKEY ) { + wacom_wac->hid_data.inrange_state |= value; + } + +if (equivalent_usage !=WACOM_HID_WD_TOUCHRINGSTATUS ) +input_event (input, usage->type, usage->code, value); + +return 0 ; +} + +static void wacom_wac_pad_pre_report (struct hid_device *hdev, +struct hid_report *report) +{ +struct wacom *wacom =hid_get_drvdata (hdev); +struct wacom_wac *wacom_wac = &wacom->wacom_wac; + + wacom_wac->hid_data.inrange_state =0 ; +} + +static void wacom_wac_pad_report (struct hid_device *hdev, +struct hid_report *report) +{ +struct wacom *wacom =hid_get_drvdata (hdev); +struct wacom_wac *wacom_wac = &wacom->wacom_wac; +struct input_dev *input = wacom_wac->pad_input; +bool active = wacom_wac->hid_data.inrange_state !=0 ; + +/* +* don't report prox for events like accelerometer +* or battery status +*/ +if (wacom_equivalent_usage (report->field[0 ]->physical) ==HID_DG_TABLETFUNCTIONKEY ) +input_event (input,EV_ABS ,ABS_MISC , active ?PAD_DEVICE_ID :0 ); + +input_sync (input); +} +static void wacom_wac_pen_usage_mapping (struct hid_device *hdev,struct hid_field *field,struct hid_usage *usage) {
@@ -1956,10 +2054,11 @@ void wacom_wac_usage_mapping(struct hid_device *hdev,/* currently, only direct devices have proper hid report descriptors */ features->device_type |=WACOM_DEVICETYPE_DIRECT ; -if (WACOM_PEN_FIELD (field)) +if (WACOM_PAD_FIELD (field)) +return wacom_wac_pad_usage_mapping (hdev, field, usage); +else if (WACOM_PEN_FIELD (field))return wacom_wac_pen_usage_mapping (hdev, field, usage); - -if (WACOM_FINGER_FIELD (field)) +else if (WACOM_FINGER_FIELD (field))return wacom_wac_finger_usage_mapping (hdev, field, usage); }
@@ -1971,10 +2070,11 @@ int wacom_wac_event(struct hid_device *hdev, struct hid_field *field,if (wacom->wacom_wac.features.type !=HID_GENERIC )return 0 ; -if (WACOM_PEN_FIELD (field)) +if (WACOM_PAD_FIELD (field)) +return wacom_wac_pad_event (hdev, field, usage, value); +else if (WACOM_PEN_FIELD (field))return wacom_wac_pen_event (hdev, field, usage, value); - -if (WACOM_FINGER_FIELD (field)) +else if (WACOM_FINGER_FIELD (field))return wacom_wac_finger_event (hdev, field, usage, value);return 0 ;
@@ -2008,18 +2108,20 @@ void wacom_wac_report(struct hid_device *hdev, struct hid_report *report)if (wacom_wac->features.type !=HID_GENERIC )return ; -if (WACOM_PEN_FIELD (field)) +if (WACOM_PAD_FIELD (field)) +wacom_wac_pad_pre_report (hdev, report); +else if (WACOM_PEN_FIELD (field))wacom_wac_pen_pre_report (hdev, report); - -if (WACOM_FINGER_FIELD (field)) +else if (WACOM_FINGER_FIELD (field))wacom_wac_finger_pre_report (hdev, report);wacom_report_events (hdev, report); -if (WACOM_PEN_FIELD (field)) +if (WACOM_PAD_FIELD (field)) +return wacom_wac_pad_report (hdev, report); +else if (WACOM_PEN_FIELD (field))return wacom_wac_pen_report (hdev, report); - -if (WACOM_FINGER_FIELD (field)) +else if (WACOM_FINGER_FIELD (field))return wacom_wac_finger_report (hdev, report); }
@@ -2593,6 +2695,8 @@ void wacom_setup_device_quirks(struct wacom *wacom)struct wacom_features *features = &wacom->wacom_wac.features;/* The pen and pad share the same interface on most devices */ +if (features->numbered_buttons >0 ) + features->device_type |=WACOM_DEVICETYPE_PAD ;if (features->type ==GRAPHIRE_BT || features->type ==WACOM_G4 || features->type ==DTUS || (features->type >=INTUOS3S && features->type <=WACOM_MO )) {
@@ -3114,8 +3218,12 @@ int wacom_setup_pad_input_capabilities(struct input_dev *input_dev,__set_bit (ABS_MISC , input_dev->absbit);/* kept for making legacy xf86-input-wacom accepting the pad */ -input_set_abs_params (input_dev,ABS_X ,0 ,1 ,0 ,0 ); -input_set_abs_params (input_dev,ABS_Y ,0 ,1 ,0 ,0 ); +if (!(input_dev->absinfo && (input_dev->absinfo[ABS_X ].minimum || + input_dev->absinfo[ABS_X ].maximum))) +input_set_abs_params (input_dev,ABS_X ,0 ,1 ,0 ,0 ); +if (!(input_dev->absinfo && (input_dev->absinfo[ABS_Y ].minimum || + input_dev->absinfo[ABS_Y ].maximum))) +input_set_abs_params (input_dev,ABS_Y ,0 ,1 ,0 ,0 );/* kept for making udev and libwacom accepting the pad */ __set_bit (BTN_STYLUS , input_dev->keybit);
@@ -3235,6 +3343,9 @@ int wacom_setup_pad_input_capabilities(struct input_dev *input_dev,input_set_abs_params (input_dev,ABS_WHEEL ,0 ,71 ,0 ,0 );break ; +case HID_GENERIC : +break ; +default :/* no pad supported */ return -ENODEV ;
drivers/hid/wacom_wac.h +19 -0
@@ -86,19 +86,34 @@#define WACOM_DEVICETYPE_DIRECT 0x0010#define WACOM_HID_UP_WACOMDIGITIZER 0xff0d0000 +#define WACOM_HID_SP_PAD 0x00040000 +#define WACOM_HID_SP_BUTTON 0x00090000#define WACOM_HID_SP_DIGITIZER 0x000d0000#define WACOM_HID_SP_DIGITIZERINFO 0x00100000#define WACOM_HID_WD_DIGITIZER (WACOM_HID_UP_WACOMDIGITIZER | 0x01)#define WACOM_HID_WD_SENSE (WACOM_HID_UP_WACOMDIGITIZER | 0x36) +#define WACOM_HID_WD_DIGITIZERFNKEYS (WACOM_HID_UP_WACOMDIGITIZER | 0x39)#define WACOM_HID_WD_SERIALHI (WACOM_HID_UP_WACOMDIGITIZER | 0x5c)#define WACOM_HID_WD_TOOLTYPE (WACOM_HID_UP_WACOMDIGITIZER | 0x77)#define WACOM_HID_WD_DISTANCE (WACOM_HID_UP_WACOMDIGITIZER | 0x0132) +#define WACOM_HID_WD_TOUCHRING (WACOM_HID_UP_WACOMDIGITIZER | 0x0138) +#define WACOM_HID_WD_TOUCHRINGSTATUS (WACOM_HID_UP_WACOMDIGITIZER | 0x0139) +#define WACOM_HID_WD_ACCELEROMETER_X (WACOM_HID_UP_WACOMDIGITIZER | 0x0401) +#define WACOM_HID_WD_ACCELEROMETER_Y (WACOM_HID_UP_WACOMDIGITIZER | 0x0402) +#define WACOM_HID_WD_ACCELEROMETER_Z (WACOM_HID_UP_WACOMDIGITIZER | 0x0403) +#define WACOM_HID_WD_EXPRESSKEY00 (WACOM_HID_UP_WACOMDIGITIZER | 0x0910) +#define WACOM_HID_WD_BUTTONHOME (WACOM_HID_UP_WACOMDIGITIZER | 0x0990) +#define WACOM_HID_WD_BUTTONUP (WACOM_HID_UP_WACOMDIGITIZER | 0x0991) +#define WACOM_HID_WD_BUTTONDOWN (WACOM_HID_UP_WACOMDIGITIZER | 0x0992) +#define WACOM_HID_WD_BUTTONLEFT (WACOM_HID_UP_WACOMDIGITIZER | 0x0993) +#define WACOM_HID_WD_BUTTONRIGHT (WACOM_HID_UP_WACOMDIGITIZER | 0x0994)#define WACOM_HID_WD_FINGERWHEEL (WACOM_HID_UP_WACOMDIGITIZER | 0x0d03)#define WACOM_HID_WD_OFFSETLEFT (WACOM_HID_UP_WACOMDIGITIZER | 0x0d30)#define WACOM_HID_WD_OFFSETTOP (WACOM_HID_UP_WACOMDIGITIZER | 0x0d31)#define WACOM_HID_WD_OFFSETRIGHT (WACOM_HID_UP_WACOMDIGITIZER | 0x0d32)#define WACOM_HID_WD_OFFSETBOTTOM (WACOM_HID_UP_WACOMDIGITIZER | 0x0d33)#define WACOM_HID_WD_DATAMODE (WACOM_HID_UP_WACOMDIGITIZER | 0x1002) +#define WACOM_HID_WD_DIGITIZERINFO (WACOM_HID_UP_WACOMDIGITIZER | 0x1013)#define WACOM_HID_UP_G9 0xff090000#define WACOM_HID_G9_PEN (WACOM_HID_UP_G9 | 0x02)#define WACOM_HID_G9_TOUCHSCREEN (WACOM_HID_UP_G9 | 0x11)
@@ -106,6 +121,10 @@#define WACOM_HID_G11_PEN (WACOM_HID_UP_G11 | 0x02)#define WACOM_HID_G11_TOUCHSCREEN (WACOM_HID_UP_G11 | 0x11) +#define WACOM_PAD_FIELD (f) (((f)->physical == HID_DG_TABLETFUNCTIONKEY) || \ + ((f)->physical == WACOM_HID_WD_DIGITIZERFNKEYS) || \ + ((f)->physical == WACOM_HID_WD_DIGITIZERINFO)) +#define WACOM_PEN_FIELD (f) (((f)->logical == HID_DG_STYLUS) || \ ((f)->physical == HID_DG_STYLUS) || \ ((f)->physical == HID_DG_PEN) || \
Signature · 1 line
2.10.0
PATCH v2 16/18 HID: wacom: generic: Add support for battery status on pen and pad interfaces
In reply to Jason GereckeAdds support for usages that may appear on the pen or pad interface which report the state of the tablet battery.
--- drivers/hid/wacom_wac.c | 41 ++++++++++++++++++++++++++++++++++++++++- drivers/hid/wacom_wac.h | 6 ++++++ include/linux/hid.h | 1 + 3 files changed, 47 insertions(+), 1 deletion(-)
drivers/hid/wacom_wac.c +40 -1
@@ -1525,6 +1525,10 @@ static void wacom_wac_pad_usage_mapping(struct hid_device *hdev,unsigned equivalent_usage =wacom_equivalent_usage (usage->hid);switch (equivalent_usage) { +case WACOM_HID_WD_BATTERY_LEVEL : +case WACOM_HID_WD_BATTERY_CHARGING : + features->quirks |=WACOM_QUIRK_BATTERY ; +break ;case WACOM_HID_WD_ACCELEROMETER_X :__set_bit (INPUT_PROP_ACCELEROMETER , input->propbit);wacom_map_usage (input, usage, field,EV_ABS ,ABS_X ,0 );
@@ -1574,8 +1578,25 @@ static int wacom_wac_pad_event(struct hid_device *hdev, struct hid_field *field, wacom_wac->hid_data.inrange_state |= value; } -if (equivalent_usage !=WACOM_HID_WD_TOUCHRINGSTATUS ) +switch (equivalent_usage) { +case WACOM_HID_WD_BATTERY_LEVEL : + wacom_wac->hid_data.battery_capacity = value; + wacom_wac->hid_data.bat_connected =1 ; +return 0 ; + +case WACOM_HID_WD_BATTERY_CHARGING : + wacom_wac->hid_data.bat_charging = value; + wacom_wac->hid_data.ps_connected = value; + wacom_wac->hid_data.bat_connected =1 ; +return 0 ; + +case WACOM_HID_WD_TOUCHRINGSTATUS : +return 0 ; + +default :input_event (input, usage->type, usage->code, value); +break ; + }return 0 ; }
@@ -1594,6 +1615,7 @@ static void wacom_wac_pad_report(struct hid_device *hdev, {struct wacom *wacom =hid_get_drvdata (hdev);struct wacom_wac *wacom_wac = &wacom->wacom_wac; +struct wacom_features *features = &wacom_wac->features;struct input_dev *input = wacom_wac->pad_input;bool active = wacom_wac->hid_data.inrange_state !=0 ;
@@ -1604,6 +1626,16 @@ static void wacom_wac_pad_report(struct hid_device *hdev,if (wacom_equivalent_usage (report->field[0 ]->physical) ==HID_DG_TABLETFUNCTIONKEY )input_event (input,EV_ABS ,ABS_MISC , active ?PAD_DEVICE_ID :0 ); +if (features->quirks &WACOM_QUIRK_BATTERY ) { +int capacity = wacom_wac->hid_data.battery_capacity; +bool charging = wacom_wac->hid_data.bat_charging; +bool connected = wacom_wac->hid_data.bat_connected; +bool powered = wacom_wac->hid_data.ps_connected; + +wacom_notify_battery (wacom_wac, capacity, charging, + connected, powered); + } +input_sync (input); }
@@ -1633,6 +1665,9 @@ static void wacom_wac_pen_usage_mapping(struct hid_device *hdev,case HID_DG_INRANGE :wacom_map_usage (input, usage, field,EV_KEY ,BTN_TOOL_PEN ,0 );break ; +case HID_DG_BATTERYSTRENGTH : + features->quirks |=WACOM_QUIRK_BATTERY ; +break ;case HID_DG_INVERT :wacom_map_usage (input, usage, field,EV_KEY ,BTN_TOOL_RUBBER ,0 );
@@ -1703,6 +1738,10 @@ static int wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field,if (!(features->quirks &WACOM_QUIRK_SENSE )) wacom_wac->hid_data.sense_state = value;return 0 ; +case HID_DG_BATTERYSTRENGTH : + wacom_wac->hid_data.battery_capacity = value; + wacom_wac->hid_data.bat_connected =1 ; +break ;case HID_DG_INVERT : wacom_wac->hid_data.invert_state = value;return 0 ;
drivers/hid/wacom_wac.h +6 -0
@@ -101,6 +101,8 @@#define WACOM_HID_WD_ACCELEROMETER_X (WACOM_HID_UP_WACOMDIGITIZER | 0x0401)#define WACOM_HID_WD_ACCELEROMETER_Y (WACOM_HID_UP_WACOMDIGITIZER | 0x0402)#define WACOM_HID_WD_ACCELEROMETER_Z (WACOM_HID_UP_WACOMDIGITIZER | 0x0403) +#define WACOM_HID_WD_BATTERY_CHARGING (WACOM_HID_UP_WACOMDIGITIZER | 0x0404) +#define WACOM_HID_WD_BATTERY_LEVEL (WACOM_HID_UP_WACOMDIGITIZER | 0x043b)#define WACOM_HID_WD_EXPRESSKEY00 (WACOM_HID_UP_WACOMDIGITIZER | 0x0910)#define WACOM_HID_WD_BUTTONHOME (WACOM_HID_UP_WACOMDIGITIZER | 0x0990)#define WACOM_HID_WD_BUTTONUP (WACOM_HID_UP_WACOMDIGITIZER | 0x0991)
@@ -257,6 +259,10 @@ struct hid_data {int cc_value_index;int num_expected;int num_received; +int battery_capacity; +int bat_charging; +int bat_connected; +int ps_connected; };struct wacom_remote_data {
include/linux/hid.h +1 -0
@@ -231,6 +231,7 @@ struct hid_item {#define HID_DG_TAP 0x000d0035#define HID_DG_TABLETFUNCTIONKEY 0x000d0039#define HID_DG_PROGRAMCHANGEKEY 0x000d003a +#define HID_DG_BATTERYSTRENGTH 0x000d003b#define HID_DG_INVERT 0x000d003c#define HID_DG_TILT_X 0x000d003d#define HID_DG_TILT_Y 0x000d003e
Signature · 1 line
2.10.0
PATCH v2 17/18 HID: wacom: generic: Extend pad support
In reply to Jason GereckeThe HID specification that the MobileStudio Pro follows includes usages for several values that would be good to support so that future devices "just work" out of the box. Extend the HID_GENERIC pad codepath to handle these usages.
--- drivers/hid/wacom_wac.c | 15 +++++++++++++++ drivers/hid/wacom_wac.h | 5 +++++ 2 files changed, 20 insertions(+)
drivers/hid/wacom_wac.c +15 -0
@@ -1457,6 +1457,8 @@ static int wacom_equivalent_usage(int usage) usage ==WACOM_HID_WD_SERIALHI || usage ==WACOM_HID_WD_TOOLTYPE || usage ==WACOM_HID_WD_DISTANCE || + usage ==WACOM_HID_WD_TOUCHSTRIP || + usage ==WACOM_HID_WD_TOUCHSTRIP2 || usage ==WACOM_HID_WD_TOUCHRING || usage == WACOM_HID_WD_TOUCHRINGSTATUS) { return usage;
@@ -1512,6 +1514,9 @@ static void wacom_map_usage(struct input_dev *input, struct hid_usage *usage,case EV_MSC :input_set_capability (input,EV_MSC , code);break ; +case EV_SW : +input_set_capability (input,EV_SW , code); +break ; } }
@@ -1546,11 +1551,21 @@ static void wacom_wac_pad_usage_mapping(struct hid_device *hdev,case WACOM_HID_WD_BUTTONDOWN :case WACOM_HID_WD_BUTTONLEFT :case WACOM_HID_WD_BUTTONRIGHT : +case WACOM_HID_WD_BUTTONCENTER :wacom_map_usage (input, usage, field,EV_KEY ,wacom_numbered_button_to_key (features->numbered_buttons),0 ); features->numbered_buttons++;break ; +case WACOM_HID_WD_TOUCHONOFF : +wacom_map_usage (input, usage, field,EV_SW ,SW_MUTE_DEVICE ,0 ); +break ; +case WACOM_HID_WD_TOUCHSTRIP : +wacom_map_usage (input, usage, field,EV_ABS ,ABS_RX ,0 ); +break ; +case WACOM_HID_WD_TOUCHSTRIP2 : +wacom_map_usage (input, usage, field,EV_ABS ,ABS_RY ,0 ); +break ;case WACOM_HID_WD_TOUCHRING :wacom_map_usage (input, usage, field,EV_ABS ,ABS_WHEEL ,0 );break ;
drivers/hid/wacom_wac.h +5 -0
@@ -96,6 +96,8 @@#define WACOM_HID_WD_SERIALHI (WACOM_HID_UP_WACOMDIGITIZER | 0x5c)#define WACOM_HID_WD_TOOLTYPE (WACOM_HID_UP_WACOMDIGITIZER | 0x77)#define WACOM_HID_WD_DISTANCE (WACOM_HID_UP_WACOMDIGITIZER | 0x0132) +#define WACOM_HID_WD_TOUCHSTRIP (WACOM_HID_UP_WACOMDIGITIZER | 0x0136) +#define WACOM_HID_WD_TOUCHSTRIP2 (WACOM_HID_UP_WACOMDIGITIZER | 0x0137)#define WACOM_HID_WD_TOUCHRING (WACOM_HID_UP_WACOMDIGITIZER | 0x0138)#define WACOM_HID_WD_TOUCHRINGSTATUS (WACOM_HID_UP_WACOMDIGITIZER | 0x0139)#define WACOM_HID_WD_ACCELEROMETER_X (WACOM_HID_UP_WACOMDIGITIZER | 0x0401)
@@ -104,11 +106,14 @@#define WACOM_HID_WD_BATTERY_CHARGING (WACOM_HID_UP_WACOMDIGITIZER | 0x0404)#define WACOM_HID_WD_BATTERY_LEVEL (WACOM_HID_UP_WACOMDIGITIZER | 0x043b)#define WACOM_HID_WD_EXPRESSKEY00 (WACOM_HID_UP_WACOMDIGITIZER | 0x0910) +#define WACOM_HID_WD_EXPRESSKEYCAP00 (WACOM_HID_UP_WACOMDIGITIZER | 0x0950)#define WACOM_HID_WD_BUTTONHOME (WACOM_HID_UP_WACOMDIGITIZER | 0x0990)#define WACOM_HID_WD_BUTTONUP (WACOM_HID_UP_WACOMDIGITIZER | 0x0991)#define WACOM_HID_WD_BUTTONDOWN (WACOM_HID_UP_WACOMDIGITIZER | 0x0992)#define WACOM_HID_WD_BUTTONLEFT (WACOM_HID_UP_WACOMDIGITIZER | 0x0993)#define WACOM_HID_WD_BUTTONRIGHT (WACOM_HID_UP_WACOMDIGITIZER | 0x0994) +#define WACOM_HID_WD_BUTTONCENTER (WACOM_HID_UP_WACOMDIGITIZER | 0x0995) +#define WACOM_HID_WD_TOUCHONOFF (WACOM_HID_UP_WACOMDIGITIZER | 0x0996)#define WACOM_HID_WD_FINGERWHEEL (WACOM_HID_UP_WACOMDIGITIZER | 0x0d03)#define WACOM_HID_WD_OFFSETLEFT (WACOM_HID_UP_WACOMDIGITIZER | 0x0d30)#define WACOM_HID_WD_OFFSETTOP (WACOM_HID_UP_WACOMDIGITIZER | 0x0d31)
Signature · 1 line
2.10.0
PATCH v2 18/18 HID: input: Recognize ABS_WHEEL in hidinput_calc_abs_res
In reply to Jason GereckeThe "Steering" usage (HID_UP_SIMULATION | 0xc8) is defined in HUT 1.12 as follows:
"A steering wheel is a single degree-of-freedom device that rotates about an axis. The zero position is always the neutral or 'straight ahead' position, with positive values turning clockwise and negative values turning counterclockwise. If the Coordinate Values Wrap attribute is set, the steering wheel can be turned past 360 degrees."
The hidinput_configure_usage function canonically maps this usage to the ABS_WHEEL axis, but hidinput_calc_abs_res does not recognize this axis as one for which it can calculate a resolution. This effectively prevents wheels from being assigned a proper resolution that userspace can use to determine the precise angle of input.
This commit adds ABS_WHEEL as a rotational axis to hidinput_calc_abs_res.
--- drivers/hid/hid-input.c | 1 + 1 file changed, 1 insertion(+)
drivers/hid/hid-input.c +1 -0
@@ -253,6 +253,7 @@ __s32 hidinput_calc_abs_res(const struct hid_field *field, __u16 code)case ABS_RX :case ABS_RY :case ABS_RZ : +case ABS_WHEEL :case ABS_TILT_X :case ABS_TILT_Y :if (field->unit ==0x14 ) {/* If degrees */
Signature · 1 line
2.10.0
PATCH v3 1/18 HID: wacom: Update vendor-defined usage names to better match standards
In reply to Jason GereckeOur loose use of "pen" and "digitizer" in the naming of several of our vendor-defined usages may be a source of confusion given that the terms have specific meaning within the HID specification. "Pen" specifically refers to "an integrated display that allows the use of a stylus" (e.g. something like a tablet PC or Cintiq) wheras "Digitizer" is a better fit for opaque tablets like an Intuos.
While we're at it, go ahead and rename the definitions to make them more distinct and better match up with the convention used by HID (e.g. the use of '_UP_' for usage pages) and make them more distinct.
--- drivers/hid/wacom_sys.c | 12 ++++++------ drivers/hid/wacom_wac.c | 2 +- drivers/hid/wacom_wac.h | 17 +++++++++-------- 3 files changed, 16 insertions(+), 15 deletions(-)
drivers/hid/wacom_sys.c +6 -6
@@ -159,18 +159,18 @@ static void wacom_feature_mapping(struct hid_device *hdev,case HID_UP_DIGITIZER :if (field->report->id ==0x0B && - (field->application ==WACOM_G9_DIGITIZER || - field->application ==WACOM_G11_DIGITIZER )) { + (field->application ==WACOM_HID_G9_PEN || + field->application ==WACOM_HID_G11_PEN )) { wacom->wacom_wac.mode_report = field->report->id; wacom->wacom_wac.mode_value =0 ; }break ; -case WACOM_G9_PAGE : -case WACOM_G11_PAGE : +case WACOM_HID_UP_G9 : +case WACOM_HID_UP_G11 :if (field->report->id ==0x03 && - (field->application ==WACOM_G9_TOUCHSCREEN || - field->application ==WACOM_G11_TOUCHSCREEN )) { + (field->application ==WACOM_HID_G9_TOUCHSCREEN || + field->application ==WACOM_HID_G11_TOUCHSCREEN )) { wacom->wacom_wac.mode_report = field->report->id; wacom->wacom_wac.mode_value =0 ; }
drivers/hid/wacom_wac.c +1 -1
@@ -2448,7 +2448,7 @@ void wacom_setup_device_quirks(struct wacom *wacom)/* * Raw Wacom-mode pen and touch events both come from interface * 0, whose HID descriptor has an application usage of 0xFF0D -* (i.e., WACOM_VENDORDEFINED_PEN). We route pen packets back +* (i.e., WACOM_HID_WD_DIGITIZER). We route pen packets back * out through the HID_GENERIC device created for interface 1, * so rewrite this one to be of type WACOM_DEVICETYPE_TOUCH. */
drivers/hid/wacom_wac.h +9 -8
@@ -84,20 +84,21 @@#define WACOM_DEVICETYPE_WL_MONITOR 0x0008#define WACOM_DEVICETYPE_DIRECT 0x0010 -#define WACOM_VENDORDEFINED_PEN 0xff0d0001 -#define WACOM_G9_PAGE 0xff090000 -#define WACOM_G9_DIGITIZER (WACOM_G9_PAGE | 0x02) -#define WACOM_G9_TOUCHSCREEN (WACOM_G9_PAGE | 0x11) -#define WACOM_G11_PAGE 0xff110000 -#define WACOM_G11_DIGITIZER (WACOM_G11_PAGE | 0x02) -#define WACOM_G11_TOUCHSCREEN (WACOM_G11_PAGE | 0x11) +#define WACOM_HID_UP_WACOMDIGITIZER 0xff0d0000 +#define WACOM_HID_WD_DIGITIZER (WACOM_HID_UP_WACOMDIGITIZER | 0x01) +#define WACOM_HID_UP_G9 0xff090000 +#define WACOM_HID_G9_PEN (WACOM_HID_UP_G9 | 0x02) +#define WACOM_HID_G9_TOUCHSCREEN (WACOM_HID_UP_G9 | 0x11) +#define WACOM_HID_UP_G11 0xff110000 +#define WACOM_HID_G11_PEN (WACOM_HID_UP_G11 | 0x02) +#define WACOM_HID_G11_TOUCHSCREEN (WACOM_HID_UP_G11 | 0x11)#define WACOM_PEN_FIELD (f) (((f)->logical == HID_DG_STYLUS) || \ ((f)->physical == HID_DG_STYLUS) || \ ((f)->physical == HID_DG_PEN) || \ ((f)->application == HID_DG_PEN) || \ ((f)->application == HID_DG_DIGITIZER) || \ - ((f)->application == WACOM_VENDORDEFINED_PEN)) + ((f)->application == WACOM_HID_WD_DIGITIZER))#define WACOM_FINGER_FIELD (f) (((f)->logical == HID_DG_FINGER) || \ ((f)->physical == HID_DG_FINGER) || \ ((f)->application == HID_DG_TOUCHSCREEN))
Signature · 1 line
2.10.0
PATCH v3 2/18 HID: wacom: Have WACOM_PEN_FIELD and WACOM_FINGER_FIELD recgonize more fields
We've defined several new usages (e.g. WACOM_G9_PEN and WACOM_G9_TOUCHSCREEN) which aren't checked by the WACOM_PEN_FIELD and WACOM_FINGER_FIELD macros but probably should be.
--- drivers/hid/wacom_wac.h | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
drivers/hid/wacom_wac.h +6 -2
@@ -98,10 +98,14 @@ ((f)->physical == HID_DG_PEN) || \ ((f)->application == HID_DG_PEN) || \ ((f)->application == HID_DG_DIGITIZER) || \ - ((f)->application == WACOM_HID_WD_DIGITIZER)) + ((f)->application == WACOM_HID_WD_DIGITIZER) || \ + ((f)->application == WACOM_HID_G9_PEN) || \ + ((f)->application == WACOM_HID_G11_PEN))#define WACOM_FINGER_FIELD (f) (((f)->logical == HID_DG_FINGER) || \ ((f)->physical == HID_DG_FINGER) || \ - ((f)->application == HID_DG_TOUCHSCREEN)) + ((f)->application == HID_DG_TOUCHSCREEN) || \ + ((f)->application == WACOM_HID_G9_TOUCHSCREEN) || \ + ((f)->application == WACOM_HID_G11_TOUCHSCREEN))enum {PENPARTNER =0 ,
Signature · 1 line
2.10.0
PATCH v3 3/18 HID: wacom: Refactor button-to-key translation into function
In reply to Jason GereckeThis just centralizes the logic used in both wacom_setup_numbered_buttons and wacom_report_numbered_buttons so that they don't drift out of sync.
--- drivers/hid/wacom_wac.c | 36 ++++++++++++++++++++++++------------ 1 file changed, 24 insertions(+), 12 deletions(-)
drivers/hid/wacom_wac.c +24 -12
@@ -2769,17 +2769,29 @@ int wacom_setup_touch_input_capabilities(struct input_dev *input_dev,return 0 ; } +static int wacom_numbered_button_to_key (int n) +{ +if (n <10 ) +return BTN_0 + n; +else if (n <16 ) +return BTN_A + (n-10 ); +else if (n <18 ) +return BTN_BASE + (n-16 ); +else +return 0 ; +} +static void wacom_setup_numbered_buttons (struct input_dev *input_dev,int button_count) {int i; -for (i =0 ; i < button_count && i <10 ; i++) -__set_bit (BTN_0 + i, input_dev->keybit); -for (i =10 ; i < button_count && i <16 ; i++) -__set_bit (BTN_A + (i-10 ), input_dev->keybit); -for (i =16 ; i < button_count && i <18 ; i++) -__set_bit (BTN_BASE + (i-16 ), input_dev->keybit); +for (i =0 ; i < button_count; i++) { +int key =wacom_numbered_button_to_key (i); + +if (key) +__set_bit (key, input_dev->keybit); + } }static void wacom_24hd_update_leds (struct wacom *wacom,int mask,int group)
@@ -2881,12 +2893,12 @@ static void wacom_report_numbered_buttons(struct input_dev *input_dev,for (i =0 ; i < wacom->led.count; i++)wacom_update_led (wacom, button_count, mask, i); -for (i =0 ; i < button_count && i <10 ; i++) -input_report_key (input_dev,BTN_0 + i, mask & (1 << i)); -for (i =10 ; i < button_count && i <16 ; i++) -input_report_key (input_dev,BTN_A + (i-10 ), mask & (1 << i)); -for (i =16 ; i < button_count && i <18 ; i++) -input_report_key (input_dev,BTN_BASE + (i-16 ), mask & (1 << i)); +for (i =0 ; i < button_count; i++) { +int key =wacom_numbered_button_to_key (i); + +if (key) +input_report_key (input_dev, key, mask & (1 << i)); + } } int wacom_setup_pad_input_capabilities(struct input_dev *input_dev,
Signature · 1 line
2.10.0
PATCH v3 4/18 HID: wacom: Detect and correct descriptors missing HID_DG_BARRELSWITCH2
In reply to Jason GereckeISDv4 devices have long supported reporting data from each of two barrel switches, but HID_DG_BARRELSWITCH2 itself was only recently standardized. Prior to its adoption, ISDv4 devices would associate the bit indicating the state of the second barrel switch with the "Undefined" 0x000D0000 usage. Although most such devices have explicit support, a few use the HID_GENERIC codepath which ignores the "Undefined" usage.
This patch adds code which detects the presence of a pre-standard second barrel switch and corrects the usage value so that the HID_GENERIC code will declare its presence and report its state.
--- drivers/hid/wacom_sys.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+)
drivers/hid/wacom_sys.c +24 -0
@@ -240,6 +240,30 @@ static void wacom_usage_mapping(struct hid_device *hdev, features->touch_max =1 ; } +/* +* ISDv4 devices which predate HID's adoption of the +* HID_DG_BARELSWITCH2 usage use 0x000D0000 in its +* position instead. We can accurately detect if a +* usage with that value should be HID_DG_BARRELSWITCH2 +* based on the surrounding usages, which have remained +* constant across generations. +*/ +if (features->type ==HID_GENERIC && + usage->hid ==0x000D0000 && + field->application ==HID_DG_PEN && + field->physical ==HID_DG_STYLUS ) { +int i = usage->usage_index; + +if (i-4 >=0 && i+1 < field->maxusage && + field->usage[i-4 ].hid ==HID_DG_TIPSWITCH && + field->usage[i-3 ].hid ==HID_DG_BARRELSWITCH && + field->usage[i-2 ].hid ==HID_DG_ERASER && + field->usage[i-1 ].hid ==HID_DG_INVERT && + field->usage[i+1 ].hid ==HID_DG_INRANGE ) { + usage->hid =HID_DG_BARRELSWITCH2 ; + } + } +switch (usage->hid) {case HID_GD_X : features->x_max = field->logical_maximum;
Signature · 1 line
2.10.0
PATCH v3 5/18 HID: wacom: generic: Strip off excessive name prefixing
In reply to Jason GereckeThe product name received from the string descriptor in the new MobileStudio Pro line of tablets begins with "Wacom", which leads to unnecessary visual noise in the device name when appended to the vendor name which also includes "Wacom". Look for and fix cases like this.
--- drivers/hid/wacom_sys.c | 13 +++++++++++++ 1 file changed, 13 insertions(+)
drivers/hid/wacom_sys.c +13 -0
@@ -1940,6 +1940,19 @@ static void wacom_update_name(struct wacom *wacom, const char *suffix)/* shift everything including the terminator */ memmove (gap, gap+1 ,strlen (gap)); } + +/* strip off excessive prefixing */ +if (strstr (name,"Wacom Co.,Ltd. Wacom " ) == name) { +int n =strlen (name); +int x =strlen ("Wacom Co.,Ltd. " ); +memmove (name, name+x, n-x+1 ); + } +if (strstr (name,"Wacom Co., Ltd. Wacom " ) == name) { +int n =strlen (name); +int x =strlen ("Wacom Co., Ltd. " ); +memmove (name, name+x, n-x+1 ); + } +/* get rid of trailing whitespace */ if (name[strlen (name)-1 ] ==' ' ) name[strlen (name)-1 ] ='\0' ;
Signature · 1 line
2.10.0
PATCH v3 6/18 HID: wacom: generic: Add support for height, tilt, and twist usages
In reply to Jason GereckeThe HID standard defines usages that allow digitizers to report the pen's height, tilt, and rotation and which are used by Wacom's new "MobileStudio Pro" devices.
Note that 'hidinput_calc_abs_res' expects ABS_Z (historically used by our driver to report twist) to have linear units. To ensure it calculates a resolution with the actually-angular units provided in the HID descriptor we nedd to lie and tell it we're calculating it for the (rotational) ABS_RZ axis instead.
--- drivers/hid/wacom_wac.c | 28 ++++++++++++++++++++++++++-- include/linux/hid.h | 3 +++ 2 files changed, 29 insertions(+), 2 deletions(-)
drivers/hid/wacom_wac.c +26 -2
@@ -1440,6 +1440,11 @@ static void wacom_map_usage(struct input_dev *input, struct hid_usage *usage, {int fmin = field->logical_minimum;int fmax = field->logical_maximum; +int resolution_code = code; + +if (usage->hid ==HID_DG_TWIST ) { + resolution_code =ABS_RZ ; + } usage->type = type; usage->code = code;
@@ -1450,7 +1455,7 @@ static void wacom_map_usage(struct input_dev *input, struct hid_usage *usage,case EV_ABS :input_set_abs_params (input, code, fmin, fmax, fuzz,0 );input_abs_set_res (input, code, -hidinput_calc_abs_res (field, code)); +hidinput_calc_abs_res (field, resolution_code));break ;case EV_KEY :input_set_capability (input,EV_KEY , code);
@@ -1475,6 +1480,9 @@ static void wacom_wac_pen_usage_mapping(struct hid_device *hdev,case HID_GD_Y :wacom_map_usage (input, usage, field,EV_ABS ,ABS_Y ,4 );break ; +case HID_GD_Z : +wacom_map_usage (input, usage, field,EV_ABS ,ABS_DISTANCE ,0 ); +break ;case HID_DG_TIPPRESSURE :wacom_map_usage (input, usage, field,EV_ABS ,ABS_PRESSURE ,0 );break ;
@@ -1485,6 +1493,15 @@ static void wacom_wac_pen_usage_mapping(struct hid_device *hdev,wacom_map_usage (input, usage, field,EV_KEY ,BTN_TOOL_RUBBER ,0 );break ; +case HID_DG_TILT_X : +wacom_map_usage (input, usage, field,EV_ABS ,ABS_TILT_X ,0 ); +break ; +case HID_DG_TILT_Y : +wacom_map_usage (input, usage, field,EV_ABS ,ABS_TILT_Y ,0 ); +break ; +case HID_DG_TWIST : +wacom_map_usage (input, usage, field,EV_ABS ,ABS_Z ,0 ); +break ;case HID_DG_ERASER :case HID_DG_TIPSWITCH :wacom_map_usage (input, usage, field,EV_KEY ,BTN_TOUCH ,0 );
@@ -1508,8 +1525,15 @@ static int wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field,struct wacom_wac *wacom_wac = &wacom->wacom_wac;struct input_dev *input = wacom_wac->pen_input; -/* checking which Tool / tip switch to send */ switch (usage->hid) { +case HID_GD_Z : +/* +* HID_GD_Z "should increase as the control's position is +* moved from high to low", while ABS_DISTANCE instead +* increases in value as the tool moves from low to high. +*/ + value = field->logical_maximum - value; +break ;case HID_DG_INRANGE : wacom_wac->hid_data.inrange_state = value;return 0 ;
include/linux/hid.h +3 -0
@@ -232,6 +232,9 @@ struct hid_item {#define HID_DG_TABLETFUNCTIONKEY 0x000d0039#define HID_DG_PROGRAMCHANGEKEY 0x000d003a#define HID_DG_INVERT 0x000d003c +#define HID_DG_TILT_X 0x000d003d +#define HID_DG_TILT_Y 0x000d003e +#define HID_DG_TWIST 0x000d0041#define HID_DG_TIPSWITCH 0x000d0042#define HID_DG_TIPSWITCH2 0x000d0043#define HID_DG_BARRELSWITCH 0x000d0044
Signature · 1 line
2.10.0
PATCH v3 7/18 HID: wacom: generic: Support and use 'Custom HID' mode and usages
In reply to Jason GereckeWacom's new "MobileStudio Pro" tablets are the first devices in their branded product line-up to include a usable HID descriptor for the pen interface. Like prior branded products, the device can operate in one of two modes: 'Standard HID', and 'Wacom Custom HID'. Although the first mode is usable by the HID_GENERIC codepath as-is (huzzah!), it is subject to some restrictions -- most notably pressure being limited to 2048 levels instead of 8192. To ensure tablets that include support for Custom HID mode work optimally, we add support for its usages and switch the device to Custom HID mode if possible.
The usages defined for Custom HID mode are often numerically similar to their standard HID equivalents, allowing us to write a simple translation function that takes arbitrary HID usages as input and which returns the corresponding standard HID usage as output (if one exists). Switching on this translated usage instead of the actual usage allows the existing cases to apply to both modes of operation without having to explicitly define every Custom HID usage.
--- drivers/hid/wacom_sys.c | 5 +++++ drivers/hid/wacom_wac.c | 37 +++++++++++++++++++++++++++++++------ drivers/hid/wacom_wac.h | 3 +++ 3 files changed, 39 insertions(+), 6 deletions(-)
drivers/hid/wacom_sys.c +5 -0
@@ -166,6 +166,11 @@ static void wacom_feature_mapping(struct hid_device *hdev, }break ; +case WACOM_HID_WD_DATAMODE : + wacom->wacom_wac.mode_report = field->report->id; + wacom->wacom_wac.mode_value =2 ; +break ; +case WACOM_HID_UP_G9 :case WACOM_HID_UP_G11 : if (field->report->id == 0x03 &&
drivers/hid/wacom_wac.c +31 -6
@@ -1435,14 +1435,35 @@ static int wacom_tpc_irq(struct wacom_wac *wacom, size_t len)return 0 ; } +static int wacom_equivalent_usage (int usage) +{ +if ((usage &HID_USAGE_PAGE ) ==WACOM_HID_UP_WACOMDIGITIZER ) { +int subpage = (usage &0xFF00 ) <<8 ; +int subusage = (usage &0xFF ); + +if (subpage ==WACOM_HID_SP_DIGITIZER || + subpage ==WACOM_HID_SP_DIGITIZERINFO ) { +return usage; + } + +if (subpage ==HID_UP_UNDEFINED ) + subpage =HID_UP_DIGITIZER ; + +return subpage | subusage; + } + +return usage; +} +static void wacom_map_usage (struct input_dev *input,struct hid_usage *usage,struct hid_field *field,__u8 type,__u16 code,int fuzz) {int fmin = field->logical_minimum;int fmax = field->logical_maximum; +unsigned int equivalent_usage =wacom_equivalent_usage (usage->hid);int resolution_code = code; -if (usage->hid ==HID_DG_TWIST ) { +if (equivalent_usage ==HID_DG_TWIST ) { resolution_code =ABS_RZ ; }
@@ -1472,8 +1493,9 @@ static void wacom_wac_pen_usage_mapping(struct hid_device *hdev,struct wacom *wacom =hid_get_drvdata (hdev);struct wacom_wac *wacom_wac = &wacom->wacom_wac;struct input_dev *input = wacom_wac->pen_input; +unsigned equivalent_usage =wacom_equivalent_usage (usage->hid); -switch (usage->hid) { +switch (equivalent_usage) {case HID_GD_X :wacom_map_usage (input, usage, field,EV_ABS ,ABS_X ,4 );break ;
@@ -1524,8 +1546,9 @@ static int wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field,struct wacom *wacom =hid_get_drvdata (hdev);struct wacom_wac *wacom_wac = &wacom->wacom_wac;struct input_dev *input = wacom_wac->pen_input; +unsigned equivalent_usage =wacom_equivalent_usage (usage->hid); -switch (usage->hid) { +switch (equivalent_usage) {case HID_GD_Z :/* * HID_GD_Z "should increase as the control's position is
@@ -1597,8 +1620,9 @@ static void wacom_wac_finger_usage_mapping(struct hid_device *hdev,struct wacom_wac *wacom_wac = &wacom->wacom_wac;struct input_dev *input = wacom_wac->touch_input;unsigned touch_max = wacom_wac->features.touch_max; +unsigned equivalent_usage =wacom_equivalent_usage (usage->hid); -switch (usage->hid) { +switch (equivalent_usage) {case HID_GD_X :if (touch_max ==1 )wacom_map_usage (input, usage, field,EV_ABS ,ABS_X ,4 );
@@ -1673,8 +1697,9 @@ static int wacom_wac_finger_event(struct hid_device *hdev, {struct wacom *wacom =hid_get_drvdata (hdev);struct wacom_wac *wacom_wac = &wacom->wacom_wac; +unsigned equivalent_usage =wacom_equivalent_usage (usage->hid); -switch (usage->hid) { +switch (equivalent_usage) {case HID_GD_X : wacom_wac->hid_data.x = value;break ;
@@ -1697,7 +1722,7 @@ static int wacom_wac_finger_event(struct hid_device *hdev,if (usage->usage_index +1 == field->report_count) { -if (usage->hid == wacom_wac->hid_data.last_slot_field) +if (equivalent_usage == wacom_wac->hid_data.last_slot_field)wacom_wac_finger_slot (wacom_wac, wacom_wac->touch_input); }
drivers/hid/wacom_wac.h +3 -0
@@ -85,7 +85,10 @@#define WACOM_DEVICETYPE_DIRECT 0x0010#define WACOM_HID_UP_WACOMDIGITIZER 0xff0d0000 +#define WACOM_HID_SP_DIGITIZER 0x000d0000 +#define WACOM_HID_SP_DIGITIZERINFO 0x00100000#define WACOM_HID_WD_DIGITIZER (WACOM_HID_UP_WACOMDIGITIZER | 0x01) +#define WACOM_HID_WD_DATAMODE (WACOM_HID_UP_WACOMDIGITIZER | 0x1002)#define WACOM_HID_UP_G9 0xff090000#define WACOM_HID_G9_PEN (WACOM_HID_UP_G9 | 0x02)#define WACOM_HID_G9_TOUCHSCREEN (WACOM_HID_UP_G9 | 0x11)
Signature · 1 line
2.10.0
PATCH v3 8/18 HID: wacom: generic: Add support for vendor-defined "Distance" usage
In reply to Jason GereckeThe vendor-defined 0xFF0D01032 ("Distance") usage is nearly equivalent to HID_GD_Z, except that the axis direction is inverted. Unlike HID_GD_Z which increases in value as the pen-to-surface distance is decreased, this usage decreases. Treat this usage as a special case to ensure we don't invert the scale to be ABS_DISTANCE compatible like we do for HID_GD_Z.
--- drivers/hid/wacom_wac.c | 4 +++- drivers/hid/wacom_wac.h | 1 + 2 files changed, 4 insertions(+), 1 deletion(-)
drivers/hid/wacom_wac.c +3 -1
@@ -1442,7 +1442,8 @@ static int wacom_equivalent_usage(int usage)int subusage = (usage &0xFF );if (subpage ==WACOM_HID_SP_DIGITIZER || - subpage ==WACOM_HID_SP_DIGITIZERINFO ) { + subpage ==WACOM_HID_SP_DIGITIZERINFO || + usage ==WACOM_HID_WD_DISTANCE ) {return usage; }
@@ -1502,6 +1503,7 @@ static void wacom_wac_pen_usage_mapping(struct hid_device *hdev,case HID_GD_Y :wacom_map_usage (input, usage, field,EV_ABS ,ABS_Y ,4 );break ; +case WACOM_HID_WD_DISTANCE :case HID_GD_Z :wacom_map_usage (input, usage, field,EV_ABS ,ABS_DISTANCE ,0 );break ;
drivers/hid/wacom_wac.h +1 -0
@@ -88,6 +88,7 @@#define WACOM_HID_SP_DIGITIZER 0x000d0000#define WACOM_HID_SP_DIGITIZERINFO 0x00100000#define WACOM_HID_WD_DIGITIZER (WACOM_HID_UP_WACOMDIGITIZER | 0x01) +#define WACOM_HID_WD_DISTANCE (WACOM_HID_UP_WACOMDIGITIZER | 0x0132)#define WACOM_HID_WD_DATAMODE (WACOM_HID_UP_WACOMDIGITIZER | 0x1002)#define WACOM_HID_UP_G9 0xff090000#define WACOM_HID_G9_PEN (WACOM_HID_UP_G9 | 0x02)
Signature · 1 line
2.10.0
PATCH v3 9/18 HID: wacom: generic: Add support for vendor-defined "Fingerwheel" usage
In reply to Jason GereckeThe airbrush fingerwheel does not have a usage that corresponds cleanly with a standard HID usage, so we add explicit support for it via its vendor-defined usage.
--- drivers/hid/wacom_wac.c | 3 +++ drivers/hid/wacom_wac.h | 1 + 2 files changed, 4 insertions(+)
drivers/hid/wacom_wac.c +3 -0
@@ -1539,6 +1539,9 @@ static void wacom_wac_pen_usage_mapping(struct hid_device *hdev,case HID_DG_TOOLSERIALNUMBER :wacom_map_usage (input, usage, field,EV_MSC ,MSC_SERIAL ,0 );break ; +case WACOM_HID_WD_FINGERWHEEL : +wacom_map_usage (input, usage, field,EV_ABS ,ABS_WHEEL ,0 ); +break ; } }
drivers/hid/wacom_wac.h +1 -0
@@ -89,6 +89,7 @@#define WACOM_HID_SP_DIGITIZERINFO 0x00100000#define WACOM_HID_WD_DIGITIZER (WACOM_HID_UP_WACOMDIGITIZER | 0x01)#define WACOM_HID_WD_DISTANCE (WACOM_HID_UP_WACOMDIGITIZER | 0x0132) +#define WACOM_HID_WD_FINGERWHEEL (WACOM_HID_UP_WACOMDIGITIZER | 0x0d03)#define WACOM_HID_WD_DATAMODE (WACOM_HID_UP_WACOMDIGITIZER | 0x1002)#define WACOM_HID_UP_G9 0xff090000#define WACOM_HID_G9_PEN (WACOM_HID_UP_G9 | 0x02)
Signature · 1 line
2.10.0
PATCH v3 10/18 HID: wacom: generic: Add support for vendor-defined "Sense" usage
In reply to Jason GereckeWacom's professional tablets beginning with the Intuos4 are capable of reporting an intermediate degree of proximity where the pen is no longer close enough to communicate with ("in prox"), but still close enough to be sensed ("in range"). This additional state is particularly useful for performing palm rejection as it allows the driver to disable the touch sensor while the pen is a greater distance from the tablet.
Like other professional tablets, the new MobileStudio Pro also reports this intermeidate "in range" proximity state. Its descriptor assigns usage 0xff0d0036 to this bit. Normally 'wacom_equivalent_usage' would translate this to the standard HID "Quality" usage, but since this has a different meaning we have it explicitly ignore the usage and define it ourselves as "Sense" (since "In Range" is already defined by the HID standard and interpreted by our driver as meaning "in prox").
--- drivers/hid/wacom_wac.c | 26 +++++++++++++++++++++++--- drivers/hid/wacom_wac.h | 3 +++ 2 files changed, 26 insertions(+), 3 deletions(-)
drivers/hid/wacom_wac.c +23 -3
@@ -1443,6 +1443,7 @@ static int wacom_equivalent_usage(int usage)if (subpage ==WACOM_HID_SP_DIGITIZER || subpage ==WACOM_HID_SP_DIGITIZERINFO || + usage ==WACOM_HID_WD_SENSE || usage ==WACOM_HID_WD_DISTANCE ) {return usage; }
@@ -1493,6 +1494,7 @@ static void wacom_wac_pen_usage_mapping(struct hid_device *hdev, {struct wacom *wacom =hid_get_drvdata (hdev);struct wacom_wac *wacom_wac = &wacom->wacom_wac; +struct wacom_features *features = &wacom_wac->features;struct input_dev *input = wacom_wac->pen_input;unsigned equivalent_usage =wacom_equivalent_usage (usage->hid);
@@ -1539,6 +1541,10 @@ static void wacom_wac_pen_usage_mapping(struct hid_device *hdev,case HID_DG_TOOLSERIALNUMBER :wacom_map_usage (input, usage, field,EV_MSC ,MSC_SERIAL ,0 );break ; +case WACOM_HID_WD_SENSE : + features->quirks |=WACOM_QUIRK_SENSE ; +wacom_map_usage (input, usage, field,EV_KEY ,BTN_TOOL_PEN ,0 ); +break ;case WACOM_HID_WD_FINGERWHEEL :wacom_map_usage (input, usage, field,EV_ABS ,ABS_WHEEL ,0 );break ;
@@ -1550,6 +1556,7 @@ static int wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field, {struct wacom *wacom =hid_get_drvdata (hdev);struct wacom_wac *wacom_wac = &wacom->wacom_wac; +struct wacom_features *features = &wacom_wac->features;struct input_dev *input = wacom_wac->pen_input;unsigned equivalent_usage =wacom_equivalent_usage (usage->hid);
@@ -1564,6 +1571,8 @@ static int wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field,break ;case HID_DG_INRANGE : wacom_wac->hid_data.inrange_state = value; +if (!(features->quirks &WACOM_QUIRK_SENSE )) + wacom_wac->hid_data.sense_state = value;return 0 ;case HID_DG_INVERT : wacom_wac->hid_data.invert_state = value;
@@ -1572,6 +1581,9 @@ static int wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field,case HID_DG_TIPSWITCH : wacom_wac->hid_data.tipswitch |= value;return 0 ; +case WACOM_HID_WD_SENSE : + wacom_wac->hid_data.sense_state = value; +return 0 ; }/* send pen events only when touch is up or forced out
@@ -1580,6 +1592,10 @@ static int wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field,if (!usage->type ||delay_pen_events (wacom_wac))return 0 ; +/* send pen events only when the pen is in/entering/leaving proximity */ +if (!wacom_wac->hid_data.inrange_state && !wacom_wac->tool[0 ]) +return 0 ; +input_event (input, usage->type, usage->code, value);return 0 ;
@@ -1598,16 +1614,17 @@ static void wacom_wac_pen_report(struct hid_device *hdev,struct wacom_wac *wacom_wac = &wacom->wacom_wac;struct input_dev *input = wacom_wac->pen_input;bool prox = wacom_wac->hid_data.inrange_state; +bool range = wacom_wac->hid_data.sense_state; -if (!wacom_wac->shared->stylus_in_proximity)/* first in prox */ +if (!wacom_wac->tool[0 ] && prox)/* first in prox */ /* Going into proximity select tool */ wacom_wac->tool[0 ] = wacom_wac->hid_data.invert_state ?BTN_TOOL_RUBBER :BTN_TOOL_PEN ;/* keep pen state for touch events */ - wacom_wac->shared->stylus_in_proximity = prox; + wacom_wac->shared->stylus_in_proximity = range; -if (!delay_pen_events (wacom_wac)) { +if (!delay_pen_events (wacom_wac) && wacom_wac->tool[0 ]) {input_report_key (input,BTN_TOUCH , wacom_wac->hid_data.tipswitch);input_report_key (input, wacom_wac->tool[0 ], prox);
@@ -1616,6 +1633,9 @@ static void wacom_wac_pen_report(struct hid_device *hdev,input_sync (input); } + +if (!prox) + wacom_wac->tool[0 ] =0 ; } static void wacom_wac_finger_usage_mapping(struct hid_device *hdev,
drivers/hid/wacom_wac.h +3 -0
@@ -74,6 +74,7 @@/* device quirks */ #define WACOM_QUIRK_BBTOUCH_LOWRES 0x0001 +#define WACOM_QUIRK_SENSE 0x0002#define WACOM_QUIRK_BATTERY 0x0008/* device types */
@@ -88,6 +89,7 @@#define WACOM_HID_SP_DIGITIZER 0x000d0000#define WACOM_HID_SP_DIGITIZERINFO 0x00100000#define WACOM_HID_WD_DIGITIZER (WACOM_HID_UP_WACOMDIGITIZER | 0x01) +#define WACOM_HID_WD_SENSE (WACOM_HID_UP_WACOMDIGITIZER | 0x36)#define WACOM_HID_WD_DISTANCE (WACOM_HID_UP_WACOMDIGITIZER | 0x0132)#define WACOM_HID_WD_FINGERWHEEL (WACOM_HID_UP_WACOMDIGITIZER | 0x0d03)#define WACOM_HID_WD_DATAMODE (WACOM_HID_UP_WACOMDIGITIZER | 0x1002)
@@ -212,6 +214,7 @@ struct wacom_shared {struct hid_data {__s16 inputmode;/* InputMode HID feature, -1 if non-existent */ __s16 inputmode_index;/* InputMode HID feature index in the report */ +bool sense_state;bool inrange_state;bool invert_state;bool tipswitch;
Signature · 1 line
2.10.0
PATCH v3 11/18 HID: wacom: Read and internally use corrected Intuos tool IDs
In reply to Jason GereckeThe 'wacom_intuos_inout' function incorrectly assmebles tool IDs from the proximity report, shifting the higher values of the ID four bits farther than intended. This problem was not detected until too late, but has not caused any issues since the incorrect IDs still fit in a 32-bit integer and userspace programs have not required the value to match the hardware (just that the values are unique and constant).
The tool IDs reported by the new MobileStudio Pro (or any future HID_GENERIC device that supports them) do not suffer from the same assembly issue, however. In order for 'wacom_intuos_get_tool_type' to work for with both codepaths, we correct this issue internally and have 'wacom_intuos_general' only mangle the ID when it is posted to userspace.
--- drivers/hid/wacom_wac.c | 38 ++++++++++++++++++++++---------------- 1 file changed, 22 insertions(+), 16 deletions(-)
drivers/hid/wacom_wac.c +22 -16
@@ -588,6 +588,11 @@ static int wacom_intuos_pad(struct wacom_wac *wacom)return 1 ; } +static int wacom_intuos_id_mangle (int tool_id) +{ +return (tool_id & ~0xFFF ) <<4 | (tool_id &0xFFF ); +} +static int wacom_intuos_get_tool_type (int tool_id) {int tool_type;
@@ -595,7 +600,7 @@ static int wacom_intuos_get_tool_type(int tool_id)switch (tool_id) {case 0x812 :/* Inking pen */ case 0x801 :/* Intuos3 Inking pen */ -case 0x120802 :/* Intuos4/5 Inking Pen */ +case 0x12802 :/* Intuos4/5 Inking Pen */ case 0x012 : tool_type =BTN_TOOL_PENCIL ;break ;
@@ -610,11 +615,11 @@ static int wacom_intuos_get_tool_type(int tool_id)case 0x804 :/* Intuos4/5 13HD/24HD Marker Pen */ case 0x8e2 :/* IntuosHT2 pen */ case 0x022 : -case 0x100804 :/* Intuos4/5 13HD/24HD Art Pen */ -case 0x140802 :/* Intuos4/5 13HD/24HD Classic Pen */ -case 0x160802 :/* Cintiq 13HD Pro Pen */ -case 0x180802 :/* DTH2242 Pen */ -case 0x100802 :/* Intuos4/5 13HD/24HD General Pen */ +case 0x10804 :/* Intuos4/5 13HD/24HD Art Pen */ +case 0x14802 :/* Intuos4/5 13HD/24HD Classic Pen */ +case 0x16802 :/* Cintiq 13HD Pro Pen */ +case 0x18802 :/* DTH2242 Pen */ +case 0x10802 :/* Intuos4/5 13HD/24HD General Pen */ tool_type =BTN_TOOL_PEN ;break ;
@@ -648,12 +653,12 @@ static int wacom_intuos_get_tool_type(int tool_id)case 0x80c :/* Intuos4/5 13HD/24HD Marker Pen Eraser */ case 0x80a :/* Intuos4/5 13HD/24HD General Pen Eraser */ case 0x90a :/* Intuos4/5 13HD/24HD Airbrush Eraser */ -case 0x14080a :/* Intuos4/5 13HD/24HD Classic Pen Eraser */ -case 0x10090a :/* Intuos4/5 13HD/24HD Airbrush Eraser */ -case 0x10080c :/* Intuos4/5 13HD/24HD Art Pen Eraser */ -case 0x16080a :/* Cintiq 13HD Pro Pen Eraser */ -case 0x18080a :/* DTH2242 Eraser */ -case 0x10080a :/* Intuos4/5 13HD/24HD General Pen Eraser */ +case 0x1480a :/* Intuos4/5 13HD/24HD Classic Pen Eraser */ +case 0x1090a :/* Intuos4/5 13HD/24HD Airbrush Eraser */ +case 0x1080c :/* Intuos4/5 13HD/24HD Art Pen Eraser */ +case 0x1680a :/* Cintiq 13HD Pro Pen Eraser */ +case 0x1880a :/* DTH2242 Eraser */ +case 0x1080a :/* Intuos4/5 13HD/24HD General Pen Eraser */ tool_type =BTN_TOOL_RUBBER ;break ;
@@ -662,7 +667,7 @@ static int wacom_intuos_get_tool_type(int tool_id)case 0x112 :case 0x913 :/* Intuos3 Airbrush */ case 0x902 :/* Intuos4/5 13HD/24HD Airbrush */ -case 0x100902 :/* Intuos4/5 13HD/24HD Airbrush */ +case 0x10902 :/* Intuos4/5 13HD/24HD Airbrush */ tool_type =BTN_TOOL_AIRBRUSH ;break ;
@@ -693,7 +698,7 @@ static int wacom_intuos_inout(struct wacom_wac *wacom) (data[6 ] <<4 ) + (data[7 ] >>4 ); wacom->id[idx] = (data[2 ] <<4 ) | (data[3 ] >>4 ) | - ((data[7 ] &0x0f ) <<20 ) | ((data[8 ] &0xf0 ) <<12 ); + ((data[7 ] &0x0f ) <<16 ) | ((data[8 ] &0xf0 ) <<8 ); wacom->tool[idx] =wacom_intuos_get_tool_type (wacom->id[idx]);
@@ -923,7 +928,7 @@ static int wacom_intuos_general(struct wacom_wac *wacom)* don't report events for invalid data */ /* older I4 styli don't work with new Cintiqs */ - if ((!((wacom->id[idx] >> 20) & 0x01) && + if ((!((wacom->id[idx] >> 16) & 0x01) && (features->type == WACOM_21UX2)) || /* Only large Intuos support Lense Cursor */ (wacom->tool[idx] == BTN_TOOL_LENS &&
@@ -1059,7 +1064,8 @@ static int wacom_intuos_general(struct wacom_wac *wacom)break ; } -input_report_abs (input,ABS_MISC , wacom->id[idx]);/* report tool id */ +input_report_abs (input,ABS_MISC , +wacom_intuos_id_mangle (wacom->id[idx]));/* report tool id */ input_report_key (input, wacom->tool[idx],1 );input_event (input,EV_MSC ,MSC_SERIAL , wacom->serial[idx]); wacom->reporting_data = true;
Signature · 1 line
2.10.0
PATCH v3 12/18 HID: wacom: generic: Support tool ID and additional tool types
In reply to Jason GereckeDevices following the new Custom HID mode specification (as well as even some recent component sensors which use the same standard HID usage) are capable of reporting tool ID information that we need to relay to userspace. This patch adds support for reading and relaying the tool type information, which is (unfortunately) split across two usages. We also advertise the existence of tool types beyond BTN_TOOL_PEN that might be available.
--- drivers/hid/wacom_wac.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++--- drivers/hid/wacom_wac.h | 4 ++- 2 files changed, 71 insertions(+), 5 deletions(-)
drivers/hid/wacom_wac.c +68 -4
@@ -1450,6 +1450,8 @@ static int wacom_equivalent_usage(int usage)if (subpage ==WACOM_HID_SP_DIGITIZER || subpage ==WACOM_HID_SP_DIGITIZERINFO || usage ==WACOM_HID_WD_SENSE || + usage ==WACOM_HID_WD_SERIALHI || + usage ==WACOM_HID_WD_TOOLTYPE || usage ==WACOM_HID_WD_DISTANCE ) {return usage; }
@@ -1551,6 +1553,17 @@ static void wacom_wac_pen_usage_mapping(struct hid_device *hdev, features->quirks |=WACOM_QUIRK_SENSE ;wacom_map_usage (input, usage, field,EV_KEY ,BTN_TOOL_PEN ,0 );break ; +case WACOM_HID_WD_SERIALHI : +wacom_map_usage (input, usage, field,EV_ABS ,ABS_MISC ,0 ); +set_bit (EV_KEY , input->evbit); +input_set_capability (input,EV_KEY ,BTN_TOOL_PEN ); +input_set_capability (input,EV_KEY ,BTN_TOOL_RUBBER ); +input_set_capability (input,EV_KEY ,BTN_TOOL_BRUSH ); +input_set_capability (input,EV_KEY ,BTN_TOOL_PENCIL ); +input_set_capability (input,EV_KEY ,BTN_TOOL_AIRBRUSH ); +input_set_capability (input,EV_KEY ,BTN_TOOL_MOUSE ); +input_set_capability (input,EV_KEY ,BTN_TOOL_LENS ); +break ;case WACOM_HID_WD_FINGERWHEEL :wacom_map_usage (input, usage, field,EV_ABS ,ABS_WHEEL ,0 );break ;
@@ -1587,9 +1600,35 @@ static int wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field,case HID_DG_TIPSWITCH : wacom_wac->hid_data.tipswitch |= value;return 0 ; +case HID_DG_TOOLSERIALNUMBER : + wacom_wac->serial[0 ] = (wacom_wac->serial[0 ] & ~0xFFFFFFFF ); + wacom_wac->serial[0 ] |= value; +return 0 ;case WACOM_HID_WD_SENSE : wacom_wac->hid_data.sense_state = value;return 0 ; +case WACOM_HID_WD_SERIALHI : + wacom_wac->serial[0 ] = (wacom_wac->serial[0 ] &0xFFFFFFFF ); + wacom_wac->serial[0 ] |= ((__u64 )value) <<32 ; +/* +* Non-USI EMR devices may contain additional tool type +* information here. See WACOM_HID_WD_TOOLTYPE case for +* more details. +*/ +if (value >>20 ==1 ) { + wacom_wac->id[0 ] |= value &0xFFFFF ; + } +return 0 ; +case WACOM_HID_WD_TOOLTYPE : +/* +* Some devices (MobileStudio Pro, and possibly later +* devices as well) do not return the complete tool +* type in their WACOM_HID_WD_TOOLTYPE usage. Use a +* bitwise OR so the complete value can be built +* up over time :( +*/ + wacom_wac->id[0 ] |= value; +return 0 ; }/* send pen events only when touch is up or forced out
@@ -1622,26 +1661,51 @@ static void wacom_wac_pen_report(struct hid_device *hdev,bool prox = wacom_wac->hid_data.inrange_state;bool range = wacom_wac->hid_data.sense_state; -if (!wacom_wac->tool[0 ] && prox)/* first in prox */ +if (!wacom_wac->tool[0 ] && prox) {/* first in prox */ /* Going into proximity select tool */ - wacom_wac->tool[0 ] = wacom_wac->hid_data.invert_state ? -BTN_TOOL_RUBBER :BTN_TOOL_PEN ; +if (wacom_wac->hid_data.invert_state) + wacom_wac->tool[0 ] =BTN_TOOL_RUBBER ; +else if (wacom_wac->id[0 ]) + wacom_wac->tool[0 ] =wacom_intuos_get_tool_type (wacom_wac->id[0 ]); +else + wacom_wac->tool[0 ] =BTN_TOOL_PEN ; + }/* keep pen state for touch events */ wacom_wac->shared->stylus_in_proximity = range;if (!delay_pen_events (wacom_wac) && wacom_wac->tool[0 ]) { +int id = wacom_wac->id[0 ]; + +/* +* Non-USI EMR tools should have their IDs mangled to +* match the legacy behavior of wacom_intuos_general +*/ +if (wacom_wac->serial[0 ] >>52 ==1 ) + id =wacom_intuos_id_mangle (id); + +/* +* To ensure compatibility with xf86-input-wacom, we should +* report the BTN_TOOL_* event prior to the ABS_MISC or +* MSC_SERIAL events. +*/ input_report_key (input,BTN_TOUCH , wacom_wac->hid_data.tipswitch);input_report_key (input, wacom_wac->tool[0 ], prox); +if (wacom_wac->serial[0 ]) { +input_event (input,EV_MSC ,MSC_SERIAL , wacom_wac->serial[0 ]); +input_report_abs (input,ABS_MISC , id); + } wacom_wac->hid_data.tipswitch = false;input_sync (input); } -if (!prox) +if (!prox) { wacom_wac->tool[0 ] =0 ; + wacom_wac->id[0 ] =0 ; + } } static void wacom_wac_finger_usage_mapping(struct hid_device *hdev,
drivers/hid/wacom_wac.h +3 -1
@@ -90,6 +90,8 @@#define WACOM_HID_SP_DIGITIZERINFO 0x00100000#define WACOM_HID_WD_DIGITIZER (WACOM_HID_UP_WACOMDIGITIZER | 0x01)#define WACOM_HID_WD_SENSE (WACOM_HID_UP_WACOMDIGITIZER | 0x36) +#define WACOM_HID_WD_SERIALHI (WACOM_HID_UP_WACOMDIGITIZER | 0x5c) +#define WACOM_HID_WD_TOOLTYPE (WACOM_HID_UP_WACOMDIGITIZER | 0x77)#define WACOM_HID_WD_DISTANCE (WACOM_HID_UP_WACOMDIGITIZER | 0x0132)#define WACOM_HID_WD_FINGERWHEEL (WACOM_HID_UP_WACOMDIGITIZER | 0x0d03)#define WACOM_HID_WD_DATAMODE (WACOM_HID_UP_WACOMDIGITIZER | 0x1002)
@@ -247,7 +249,7 @@ struct wacom_wac {unsigned char data[WACOM_PKGLEN_MAX ];int tool[2 ];int id[2 ]; -__u32 serial[2 ]; +__u64 serial[2 ];bool reporting_data;struct wacom_features features;struct wacom_shared *shared;
Signature · 1 line
2.10.0
PATCH v3 13/18 HID: wacom: Fix sensor outbounds and redefine as offsets from each edge
In reply to Jason GereckeMany of Wacom's display tablets include an "outbound" area where pen digitizing is possible but outside of the display area. To ensure that pen coordinates are mapped to the correct on-screen location, the driver sets the minimum and maximum axis values of X and Y to those coordinates which coincide with the screen edge. These values are simply the hardware minimum/maximum plus/minus the outbound size for a particular edge.
When outbound support was added/updated in ac414da, fa77034, and ecd618d, we decided to have the wacom_features structs store the desired minimum and maximum values directly. In hindsight, this was perhaps not the best choice since it has allowed minor errors to crop up unnoticed. Some tablets have had their coordinates over-corrected (e.g. most of the devices "fixed" in ecd618d were already adjusted in ac414da), while others never had a correction applied (e.g. the ISDv5 325, whose declared maximum the hardware maximum instead of the outbound maximum).
A less error-prone method of handling the outbound is to let the driver calculate the correct minimum/maximum values by providing it with both the actual hardware maximums and the size of the outbound on each edge. These values are more easy to verify as correct since the values can be trivially compared against specifications.
This patch reverts the declared maximum values to the actual hardware maximums, e.g. as declared prior to ac414da (values for these and other display tablets that were subsuquently introduced have been verified against specs). Per-edge outbound sizes are stored in the wacom_features struct as offset_{left,right,top,bottom} and used in combination with the hardware ranges to calculate effective axis ranges for ABS_X and ABS_Y.
--- drivers/hid/wacom_wac.c | 62 ++++++++++++++++++++++++++++++++----------------- drivers/hid/wacom_wac.h | 6 +++-- 2 files changed, 45 insertions(+), 23 deletions(-)
drivers/hid/wacom_wac.c +41 -21
@@ -2674,10 +2674,12 @@ int wacom_setup_pen_input_capabilities(struct input_dev *input_dev,__set_bit (BTN_TOUCH , input_dev->keybit);__set_bit (ABS_MISC , input_dev->absbit); -input_set_abs_params (input_dev,ABS_X , features->x_min, - features->x_max, features->x_fuzz,0 ); -input_set_abs_params (input_dev,ABS_Y , features->y_min, - features->y_max, features->y_fuzz,0 ); +input_set_abs_params (input_dev,ABS_X ,0 + features->offset_left, + features->x_max - features->offset_right, + features->x_fuzz,0 ); +input_set_abs_params (input_dev,ABS_Y ,0 + features->offset_top, + features->y_max - features->offset_bottom, + features->y_fuzz,0 );input_set_abs_params (input_dev,ABS_PRESSURE ,0 , features->pressure_max, features->pressure_fuzz,0 );
@@ -3389,26 +3391,30 @@ static const struct wacom_features wacom_features_0x317 = INTUOSPL, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 9, .touch_max = 16, .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE };static const struct wacom_features wacom_features_0xF4 = - {"Wacom Cintiq 24HD" ,104080 ,65200 ,2047 ,63 , + {"Wacom Cintiq 24HD" ,104480 ,65600 ,2047 ,63 ,WACOM_24HD ,WACOM_INTUOS3_RES ,WACOM_INTUOS3_RES ,16 , +WACOM_CINTIQ_OFFSET ,WACOM_CINTIQ_OFFSET ,WACOM_CINTIQ_OFFSET ,WACOM_CINTIQ_OFFSET };static const struct wacom_features wacom_features_0xF8 = - {"Wacom Cintiq 24HD touch" ,104080 ,65200 ,2047 ,63 ,/* Pen */ + {"Wacom Cintiq 24HD touch" ,104480 ,65600 ,2047 ,63 ,/* Pen */ WACOM_24HD ,WACOM_INTUOS3_RES ,WACOM_INTUOS3_RES ,16 ,WACOM_CINTIQ_OFFSET ,WACOM_CINTIQ_OFFSET , +WACOM_CINTIQ_OFFSET ,WACOM_CINTIQ_OFFSET , .oVid =USB_VENDOR_ID_WACOM , .oPid =0xf6 };static const struct wacom_features wacom_features_0xF6 = {"Wacom Cintiq 24HD touch" , .type =WACOM_24HDT ,/* Touch */ .oVid =USB_VENDOR_ID_WACOM , .oPid =0xf8 , .touch_max =10 , .check_for_hid_type = true, .hid_type =HID_TYPE_USBNONE };static const struct wacom_features wacom_features_0x32A = - {"Wacom Cintiq 27QHD" ,119740 ,67520 ,2047 ,63 , + {"Wacom Cintiq 27QHD" ,120140 ,67920 ,2047 ,63 ,WACOM_27QHD ,WACOM_INTUOS3_RES ,WACOM_INTUOS3_RES ,0 , +WACOM_CINTIQ_OFFSET ,WACOM_CINTIQ_OFFSET ,WACOM_CINTIQ_OFFSET ,WACOM_CINTIQ_OFFSET };static const struct wacom_features wacom_features_0x32B = - {"Wacom Cintiq 27QHD touch" ,119740 ,67520 ,2047 ,63 , + {"Wacom Cintiq 27QHD touch" ,120140 ,67920 ,2047 ,63 ,WACOM_27QHD ,WACOM_INTUOS3_RES ,WACOM_INTUOS3_RES ,0 ,WACOM_CINTIQ_OFFSET ,WACOM_CINTIQ_OFFSET , +WACOM_CINTIQ_OFFSET ,WACOM_CINTIQ_OFFSET , .oVid =USB_VENDOR_ID_WACOM , .oPid =0x32C };static const struct wacom_features wacom_features_0x32C = {"Wacom Cintiq 27QHD touch" , .type =WACOM_27QHDT ,
@@ -3423,13 +3429,15 @@ static const struct wacom_features wacom_features_0xC6 = {"Wacom Cintiq 12WX" ,53020 ,33440 ,1023 ,63 , WACOM_BEE, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 10 };static const struct wacom_features wacom_features_0x304 = - {"Wacom Cintiq 13HD" ,59152 ,33448 ,1023 ,63 , + {"Wacom Cintiq 13HD" ,59552 ,33848 ,1023 ,63 ,WACOM_13HD ,WACOM_INTUOS3_RES ,WACOM_INTUOS3_RES ,9 , +WACOM_CINTIQ_OFFSET ,WACOM_CINTIQ_OFFSET ,WACOM_CINTIQ_OFFSET ,WACOM_CINTIQ_OFFSET };static const struct wacom_features wacom_features_0x333 = - {"Wacom Cintiq 13HD touch" ,59152 ,33448 ,2047 ,63 , + {"Wacom Cintiq 13HD touch" ,59552 ,33848 ,2047 ,63 ,WACOM_13HD ,WACOM_INTUOS3_RES ,WACOM_INTUOS3_RES ,9 ,WACOM_CINTIQ_OFFSET ,WACOM_CINTIQ_OFFSET , +WACOM_CINTIQ_OFFSET ,WACOM_CINTIQ_OFFSET , .oVid =USB_VENDOR_ID_WACOM , .oPid =0x335 };static const struct wacom_features wacom_features_0x335 = { "Wacom Cintiq 13HD touch", .type = WACOM_24HDT, /* Touch */
@@ -3446,42 +3454,50 @@ static const struct wacom_features wacom_features_0xF0 = {"Wacom DTU1631" ,34623 ,19553 ,511 ,0 , DTU, WACOM_INTUOS_RES, WACOM_INTUOS_RES };static const struct wacom_features wacom_features_0xFB = - {"Wacom DTU1031" ,21896 ,13760 ,511 ,0 , + {"Wacom DTU1031" ,22096 ,13960 ,511 ,0 ,DTUS ,WACOM_INTUOS_RES ,WACOM_INTUOS_RES ,4 , +WACOM_DTU_OFFSET ,WACOM_DTU_OFFSET ,WACOM_DTU_OFFSET ,WACOM_DTU_OFFSET };static const struct wacom_features wacom_features_0x32F = - {"Wacom DTU1031X" ,22472 ,12728 ,511 ,0 , + {"Wacom DTU1031X" ,22672 ,12928 ,511 ,0 ,DTUSX ,WACOM_INTUOS_RES ,WACOM_INTUOS_RES ,0 , +WACOM_DTU_OFFSET ,WACOM_DTU_OFFSET ,WACOM_DTU_OFFSET ,WACOM_DTU_OFFSET };static const struct wacom_features wacom_features_0x336 = - {"Wacom DTU1141" ,23472 ,13203 ,1023 ,0 , + {"Wacom DTU1141" ,23672 ,13403 ,1023 ,0 ,DTUS ,WACOM_INTUOS_RES ,WACOM_INTUOS_RES ,4 , +WACOM_DTU_OFFSET ,WACOM_DTU_OFFSET ,WACOM_DTU_OFFSET ,WACOM_DTU_OFFSET };static const struct wacom_features wacom_features_0x57 = - {"Wacom DTK2241" ,95640 ,54060 ,2047 ,63 , + {"Wacom DTK2241" ,95840 ,54260 ,2047 ,63 ,DTK ,WACOM_INTUOS3_RES ,WACOM_INTUOS3_RES ,6 , +WACOM_CINTIQ_OFFSET ,WACOM_CINTIQ_OFFSET ,WACOM_CINTIQ_OFFSET ,WACOM_CINTIQ_OFFSET };static const struct wacom_features wacom_features_0x59 =/* Pen */ - {"Wacom DTH2242" ,95640 ,54060 ,2047 ,63 , + {"Wacom DTH2242" ,95840 ,54260 ,2047 ,63 ,DTK ,WACOM_INTUOS3_RES ,WACOM_INTUOS3_RES ,6 ,WACOM_CINTIQ_OFFSET ,WACOM_CINTIQ_OFFSET , +WACOM_CINTIQ_OFFSET ,WACOM_CINTIQ_OFFSET , .oVid =USB_VENDOR_ID_WACOM , .oPid =0x5D };static const struct wacom_features wacom_features_0x5D =/* Touch */ {"Wacom DTH2242" , .type =WACOM_24HDT , .oVid =USB_VENDOR_ID_WACOM , .oPid =0x59 , .touch_max =10 , .check_for_hid_type = true, .hid_type =HID_TYPE_USBNONE };static const struct wacom_features wacom_features_0xCC = - {"Wacom Cintiq 21UX2" ,86800 ,65200 ,2047 ,63 , + {"Wacom Cintiq 21UX2" ,87200 ,65600 ,2047 ,63 ,WACOM_21UX2 ,WACOM_INTUOS3_RES ,WACOM_INTUOS3_RES ,18 , +WACOM_CINTIQ_OFFSET ,WACOM_CINTIQ_OFFSET ,WACOM_CINTIQ_OFFSET ,WACOM_CINTIQ_OFFSET };static const struct wacom_features wacom_features_0xFA = - {"Wacom Cintiq 22HD" ,95440 ,53860 ,2047 ,63 , + {"Wacom Cintiq 22HD" ,95840 ,54260 ,2047 ,63 ,WACOM_22HD ,WACOM_INTUOS3_RES ,WACOM_INTUOS3_RES ,18 , +WACOM_CINTIQ_OFFSET ,WACOM_CINTIQ_OFFSET ,WACOM_CINTIQ_OFFSET ,WACOM_CINTIQ_OFFSET };static const struct wacom_features wacom_features_0x5B = - {"Wacom Cintiq 22HDT" ,95440 ,53860 ,2047 ,63 , + {"Wacom Cintiq 22HDT" ,95840 ,54260 ,2047 ,63 ,WACOM_22HD ,WACOM_INTUOS3_RES ,WACOM_INTUOS3_RES ,18 ,WACOM_CINTIQ_OFFSET ,WACOM_CINTIQ_OFFSET , +WACOM_CINTIQ_OFFSET ,WACOM_CINTIQ_OFFSET , .oVid =USB_VENDOR_ID_WACOM , .oPid =0x5e };static const struct wacom_features wacom_features_0x5E = { "Wacom Cintiq 22HDT", .type = WACOM_24HDT,
@@ -3625,18 +3641,20 @@ static const struct wacom_features wacom_features_0x6004 = {"ISD-V4" ,12800 ,8000 ,255 ,0 , TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };static const struct wacom_features wacom_features_0x307 = - {"Wacom ISDv5 307" ,59152 ,33448 ,2047 ,63 , + {"Wacom ISDv5 307" ,59552 ,33848 ,2047 ,63 ,CINTIQ_HYBRID ,WACOM_INTUOS3_RES ,WACOM_INTUOS3_RES ,9 ,WACOM_CINTIQ_OFFSET ,WACOM_CINTIQ_OFFSET , +WACOM_CINTIQ_OFFSET ,WACOM_CINTIQ_OFFSET , .oVid =USB_VENDOR_ID_WACOM , .oPid =0x309 };static const struct wacom_features wacom_features_0x309 = {"Wacom ISDv5 309" , .type =WACOM_24HDT ,/* Touch */ .oVid =USB_VENDOR_ID_WACOM , .oPid =0x0307 , .touch_max =10 , .check_for_hid_type = true, .hid_type =HID_TYPE_USBNONE };static const struct wacom_features wacom_features_0x30A = - {"Wacom ISDv5 30A" ,59152 ,33448 ,2047 ,63 , + {"Wacom ISDv5 30A" ,59552 ,33848 ,2047 ,63 ,CINTIQ_HYBRID ,WACOM_INTUOS3_RES ,WACOM_INTUOS3_RES ,9 ,WACOM_CINTIQ_OFFSET ,WACOM_CINTIQ_OFFSET , +WACOM_CINTIQ_OFFSET ,WACOM_CINTIQ_OFFSET , .oVid =USB_VENDOR_ID_WACOM , .oPid =0x30C };static const struct wacom_features wacom_features_0x30C = { "Wacom ISDv5 30C", .type = WACOM_24HDT, /* Touch */
@@ -3652,6 +3670,7 @@ static const struct wacom_features wacom_features_0x325 = {"Wacom ISDv5 325" ,59552 ,33848 ,2047 ,63 ,CINTIQ_COMPANION_2 ,WACOM_INTUOS3_RES ,WACOM_INTUOS3_RES ,11 ,WACOM_CINTIQ_OFFSET ,WACOM_CINTIQ_OFFSET , +WACOM_CINTIQ_OFFSET ,WACOM_CINTIQ_OFFSET , .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x326 };static const struct wacom_features wacom_features_0x326 =/* Touch */ { "Wacom ISDv5 326", .type = HID_GENERIC, .oVid = USB_VENDOR_ID_WACOM,
@@ -3681,8 +3700,9 @@ static const struct wacom_features wacom_features_0x33E = INTUOSHT2, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 16, .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE };static const struct wacom_features wacom_features_0x343 = - {"Wacom DTK1651" ,34616 ,19559 ,1023 ,0 , + {"Wacom DTK1651" ,34816 ,19759 ,1023 ,0 ,DTUS ,WACOM_INTUOS_RES ,WACOM_INTUOS_RES ,4 , +WACOM_DTU_OFFSET ,WACOM_DTU_OFFSET ,WACOM_DTU_OFFSET ,WACOM_DTU_OFFSET }; static const struct wacom_features wacom_features_HID_ANY_ID =
drivers/hid/wacom_wac.h +4 -2
@@ -181,8 +181,10 @@ struct wacom_features {int x_resolution;int y_resolution;int numbered_buttons; -int x_min; -int y_min; +int offset_left; +int offset_right; +int offset_top; +int offset_bottom;int device_type;int x_phy;int y_phy;
Signature · 1 line
2.10.0
PATCH v3 14/18 HID: wacom: generic: Add support for sensor offsets
In reply to Jason GereckeMany of Wacom's display tablets include an "outbound" area where pen digitizing is possible but outside of the display area. To accommodate such sensors in the HID_GENERIC codepath, we add support for the necessary vendor-defined HID feature usages and adjust the min/max values of the X and Y axes accordingly, similar to what is done in the non-generic codepath.
--- drivers/hid/wacom_sys.c | 38 ++++++++++++++++++++++++++++++-------- drivers/hid/wacom_wac.c | 40 ++++++++++++++++++++++++++++++++++++++++ drivers/hid/wacom_wac.h | 4 ++++ 3 files changed, 74 insertions(+), 8 deletions(-)
drivers/hid/wacom_sys.c +30 -8
@@ -122,6 +122,7 @@ static void wacom_feature_mapping(struct hid_device *hdev,struct hid_data *hid_data = &wacom->wacom_wac.hid_data;u8 *data;int ret; +int n;switch (usage->hid) {case HID_DG_CONTACTMAX :
@@ -180,6 +181,27 @@ static void wacom_feature_mapping(struct hid_device *hdev, wacom->wacom_wac.mode_value =0 ; }break ; +case WACOM_HID_WD_OFFSETLEFT : +case WACOM_HID_WD_OFFSETTOP : +case WACOM_HID_WD_OFFSETRIGHT : +case WACOM_HID_WD_OFFSETBOTTOM : +/* read manually */ + n =hid_report_len (field->report); + data =hid_alloc_report_buf (field->report,GFP_KERNEL ); +if (!data) +break ; + data[0 ] = field->report->id; + ret =wacom_get_report (hdev,HID_FEATURE_REPORT , + data, n,WAC_CMD_RETRIES ); +if (ret == n) { + ret =hid_report_raw_event (hdev,HID_FEATURE_REPORT , + data, n,0 ); + }else { +hid_warn (hdev,"%s: could not retrieve sensor offsets\n" , + __func__); + } +kfree (data); +break ; } }
@@ -718,11 +740,6 @@ static int wacom_add_shared_data(struct hid_device *hdev)return retval; } -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; - out:mutex_unlock (&wacom_udev_list_lock);return retval;
@@ -2019,6 +2036,10 @@ static int wacom_parse_and_register(struct wacom *wacom, bool wireless)if (error) goto fail; + error =wacom_add_shared_data (hdev); +if (error) + goto fail; +/* * Bamboo Pad has a generic hid handling for the Pen, and we switch it * into debug mode for the touch part.
@@ -2059,9 +2080,10 @@ static int wacom_parse_and_register(struct wacom *wacom, bool wireless)wacom_update_name (wacom, wireless ?" (WL)" :"" ); - error =wacom_add_shared_data (hdev); -if (error) - goto fail; +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;if (!(features->device_type &WACOM_DEVICETYPE_WL_MONITOR ) && (features->quirks &WACOM_QUIRK_BATTERY )) {
drivers/hid/wacom_wac.c +40 -0
@@ -1468,6 +1468,9 @@ static int wacom_equivalent_usage(int usage)static void wacom_map_usage (struct input_dev *input,struct hid_usage *usage,struct hid_field *field,__u8 type,__u16 code,int fuzz) { +struct wacom *wacom =input_get_drvdata (input); +struct wacom_wac *wacom_wac = &wacom->wacom_wac; +struct wacom_features *features = &wacom_wac->features;int fmin = field->logical_minimum;int fmax = field->logical_maximum;unsigned int equivalent_usage =wacom_equivalent_usage (usage->hid);
@@ -1477,6 +1480,15 @@ static void wacom_map_usage(struct input_dev *input, struct hid_usage *usage, resolution_code =ABS_RZ ; } +if (equivalent_usage ==HID_GD_X ) { + fmin += features->offset_left; + fmax -= features->offset_right; + } +if (equivalent_usage ==HID_GD_Y ) { + fmin += features->offset_top; + fmax -= features->offset_bottom; + } + usage->type = type; usage->code = code;
@@ -1629,6 +1641,34 @@ static int wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field,*/ wacom_wac->id[0 ] |= value;return 0 ; +case WACOM_HID_WD_OFFSETLEFT : +if (features->offset_left && value != features->offset_left) +hid_warn (hdev,"%s: overriding exising left offset " +"%d -> %d\n" , __func__, value, + features->offset_left); + features->offset_left = value; +return 0 ; +case WACOM_HID_WD_OFFSETRIGHT : +if (features->offset_right && value != features->offset_right) +hid_warn (hdev,"%s: overriding exising right offset " +"%d -> %d\n" , __func__, value, + features->offset_right); + features->offset_right = value; +return 0 ; +case WACOM_HID_WD_OFFSETTOP : +if (features->offset_top && value != features->offset_top) +hid_warn (hdev,"%s: overriding exising top offset " +"%d -> %d\n" , __func__, value, + features->offset_top); + features->offset_top = value; +return 0 ; +case WACOM_HID_WD_OFFSETBOTTOM : +if (features->offset_bottom && value != features->offset_bottom) +hid_warn (hdev,"%s: overriding exising bottom offset " +"%d -> %d\n" , __func__, value, + features->offset_bottom); + features->offset_bottom = value; +return 0 ; }/* send pen events only when touch is up or forced out
drivers/hid/wacom_wac.h +4 -0
@@ -94,6 +94,10 @@#define WACOM_HID_WD_TOOLTYPE (WACOM_HID_UP_WACOMDIGITIZER | 0x77)#define WACOM_HID_WD_DISTANCE (WACOM_HID_UP_WACOMDIGITIZER | 0x0132)#define WACOM_HID_WD_FINGERWHEEL (WACOM_HID_UP_WACOMDIGITIZER | 0x0d03) +#define WACOM_HID_WD_OFFSETLEFT (WACOM_HID_UP_WACOMDIGITIZER | 0x0d30) +#define WACOM_HID_WD_OFFSETTOP (WACOM_HID_UP_WACOMDIGITIZER | 0x0d31) +#define WACOM_HID_WD_OFFSETRIGHT (WACOM_HID_UP_WACOMDIGITIZER | 0x0d32) +#define WACOM_HID_WD_OFFSETBOTTOM (WACOM_HID_UP_WACOMDIGITIZER | 0x0d33)#define WACOM_HID_WD_DATAMODE (WACOM_HID_UP_WACOMDIGITIZER | 0x1002)#define WACOM_HID_UP_G9 0xff090000#define WACOM_HID_G9_PEN (WACOM_HID_UP_G9 | 0x02)
Signature · 1 line
2.10.0
PATCH v3 15/18 HID: wacom: generic: Introduce pad support
In reply to Jason GereckeAs with usages for the pen, the Custom HID specificiation includes usages for the pad. Here we add functions to map and handle most of the pad usages present on the MobileStudio Pro.
--- drivers/hid/wacom_wac.c | 143 ++++++++++++++++++++++++++++++++++++++++++------ drivers/hid/wacom_wac.h | 19 +++++++ 2 files changed, 146 insertions(+), 16 deletions(-)
drivers/hid/wacom_wac.c +127 -16
@@ -41,6 +41,8 @@ MODULE_PARM_DESC(touch_arbitration, " on (Y) off (N)");static void wacom_report_numbered_buttons (struct input_dev *input_dev,int button_count,int mask); +static int wacom_numbered_button_to_key (int n); +/* * Percent of battery capacity for Graphire. * 8th value means AC online and show 100% capacity.
@@ -1447,12 +1449,16 @@ static int wacom_equivalent_usage(int usage)int subpage = (usage &0xFF00 ) <<8 ;int subusage = (usage &0xFF ); -if (subpage ==WACOM_HID_SP_DIGITIZER || +if (subpage ==WACOM_HID_SP_PAD || + subpage ==WACOM_HID_SP_BUTTON || + subpage ==WACOM_HID_SP_DIGITIZER || subpage ==WACOM_HID_SP_DIGITIZERINFO || usage ==WACOM_HID_WD_SENSE || usage ==WACOM_HID_WD_SERIALHI || usage ==WACOM_HID_WD_TOOLTYPE || - usage ==WACOM_HID_WD_DISTANCE ) { + usage ==WACOM_HID_WD_DISTANCE || + usage ==WACOM_HID_WD_TOUCHRING || + usage ==WACOM_HID_WD_TOUCHRINGSTATUS ) {return usage; }
@@ -1509,6 +1515,98 @@ static void wacom_map_usage(struct input_dev *input, struct hid_usage *usage, } } +static void wacom_wac_pad_usage_mapping (struct hid_device *hdev, +struct hid_field *field,struct hid_usage *usage) +{ +struct wacom *wacom =hid_get_drvdata (hdev); +struct wacom_wac *wacom_wac = &wacom->wacom_wac; +struct wacom_features *features = &wacom_wac->features; +struct input_dev *input = wacom_wac->pad_input; +unsigned equivalent_usage =wacom_equivalent_usage (usage->hid); + +switch (equivalent_usage) { +case WACOM_HID_WD_ACCELEROMETER_X : +__set_bit (INPUT_PROP_ACCELEROMETER , input->propbit); +wacom_map_usage (input, usage, field,EV_ABS ,ABS_X ,0 ); +break ; +case WACOM_HID_WD_ACCELEROMETER_Y : +__set_bit (INPUT_PROP_ACCELEROMETER , input->propbit); +wacom_map_usage (input, usage, field,EV_ABS ,ABS_Y ,0 ); +break ; +case WACOM_HID_WD_ACCELEROMETER_Z : +__set_bit (INPUT_PROP_ACCELEROMETER , input->propbit); +wacom_map_usage (input, usage, field,EV_ABS ,ABS_Z ,0 ); +break ; +case WACOM_HID_WD_BUTTONHOME : +case WACOM_HID_WD_BUTTONUP : +case WACOM_HID_WD_BUTTONDOWN : +case WACOM_HID_WD_BUTTONLEFT : +case WACOM_HID_WD_BUTTONRIGHT : +wacom_map_usage (input, usage, field,EV_KEY , +wacom_numbered_button_to_key (features->numbered_buttons), +0 ); + features->numbered_buttons++; +break ; +case WACOM_HID_WD_TOUCHRING : +wacom_map_usage (input, usage, field,EV_ABS ,ABS_WHEEL ,0 ); +break ; + } + +switch (equivalent_usage &0xfffffff0 ) { +case WACOM_HID_WD_EXPRESSKEY00 : +wacom_map_usage (input, usage, field,EV_KEY , +wacom_numbered_button_to_key (features->numbered_buttons), +0 ); + features->numbered_buttons++; +break ; + } +} + +static int wacom_wac_pad_event (struct hid_device *hdev,struct hid_field *field, +struct hid_usage *usage,__s32 value) +{ +struct wacom *wacom =hid_get_drvdata (hdev); +struct wacom_wac *wacom_wac = &wacom->wacom_wac; +struct input_dev *input = wacom_wac->pad_input; +unsigned equivalent_usage =wacom_equivalent_usage (usage->hid); + +if (wacom_equivalent_usage (field->physical) ==HID_DG_TABLETFUNCTIONKEY ) { + wacom_wac->hid_data.inrange_state |= value; + } + +if (equivalent_usage !=WACOM_HID_WD_TOUCHRINGSTATUS ) +input_event (input, usage->type, usage->code, value); + +return 0 ; +} + +static void wacom_wac_pad_pre_report (struct hid_device *hdev, +struct hid_report *report) +{ +struct wacom *wacom =hid_get_drvdata (hdev); +struct wacom_wac *wacom_wac = &wacom->wacom_wac; + + wacom_wac->hid_data.inrange_state =0 ; +} + +static void wacom_wac_pad_report (struct hid_device *hdev, +struct hid_report *report) +{ +struct wacom *wacom =hid_get_drvdata (hdev); +struct wacom_wac *wacom_wac = &wacom->wacom_wac; +struct input_dev *input = wacom_wac->pad_input; +bool active = wacom_wac->hid_data.inrange_state !=0 ; + +/* +* don't report prox for events like accelerometer +* or battery status +*/ +if (wacom_equivalent_usage (report->field[0 ]->physical) ==HID_DG_TABLETFUNCTIONKEY ) +input_event (input,EV_ABS ,ABS_MISC , active ?PAD_DEVICE_ID :0 ); + +input_sync (input); +} +static void wacom_wac_pen_usage_mapping (struct hid_device *hdev,struct hid_field *field,struct hid_usage *usage) {
@@ -1946,10 +2044,11 @@ void wacom_wac_usage_mapping(struct hid_device *hdev,/* currently, only direct devices have proper hid report descriptors */ features->device_type |=WACOM_DEVICETYPE_DIRECT ; -if (WACOM_PEN_FIELD (field)) +if (WACOM_PAD_FIELD (field)) +return wacom_wac_pad_usage_mapping (hdev, field, usage); +else if (WACOM_PEN_FIELD (field))return wacom_wac_pen_usage_mapping (hdev, field, usage); - -if (WACOM_FINGER_FIELD (field)) +else if (WACOM_FINGER_FIELD (field))return wacom_wac_finger_usage_mapping (hdev, field, usage); }
@@ -1961,10 +2060,11 @@ int wacom_wac_event(struct hid_device *hdev, struct hid_field *field,if (wacom->wacom_wac.features.type !=HID_GENERIC )return 0 ; -if (WACOM_PEN_FIELD (field)) +if (WACOM_PAD_FIELD (field)) +return wacom_wac_pad_event (hdev, field, usage, value); +else if (WACOM_PEN_FIELD (field))return wacom_wac_pen_event (hdev, field, usage, value); - -if (WACOM_FINGER_FIELD (field)) +else if (WACOM_FINGER_FIELD (field))return wacom_wac_finger_event (hdev, field, usage, value);return 0 ;
@@ -1998,18 +2098,20 @@ void wacom_wac_report(struct hid_device *hdev, struct hid_report *report)if (wacom_wac->features.type !=HID_GENERIC )return ; -if (WACOM_PEN_FIELD (field)) +if (WACOM_PAD_FIELD (field)) +wacom_wac_pad_pre_report (hdev, report); +else if (WACOM_PEN_FIELD (field))wacom_wac_pen_pre_report (hdev, report); - -if (WACOM_FINGER_FIELD (field)) +else if (WACOM_FINGER_FIELD (field))wacom_wac_finger_pre_report (hdev, report);wacom_report_events (hdev, report); -if (WACOM_PEN_FIELD (field)) +if (WACOM_PAD_FIELD (field)) +return wacom_wac_pad_report (hdev, report); +else if (WACOM_PEN_FIELD (field))return wacom_wac_pen_report (hdev, report); - -if (WACOM_FINGER_FIELD (field)) +else if (WACOM_FINGER_FIELD (field))return wacom_wac_finger_report (hdev, report); }
@@ -2583,6 +2685,8 @@ void wacom_setup_device_quirks(struct wacom *wacom)struct wacom_features *features = &wacom->wacom_wac.features;/* The pen and pad share the same interface on most devices */ +if (features->numbered_buttons >0 ) + features->device_type |=WACOM_DEVICETYPE_PAD ;if (features->type ==GRAPHIRE_BT || features->type ==WACOM_G4 || features->type ==DTUS || (features->type >=INTUOS3S && features->type <=WACOM_MO )) {
@@ -3104,8 +3208,12 @@ int wacom_setup_pad_input_capabilities(struct input_dev *input_dev,__set_bit (ABS_MISC , input_dev->absbit);/* kept for making legacy xf86-input-wacom accepting the pad */ -input_set_abs_params (input_dev,ABS_X ,0 ,1 ,0 ,0 ); -input_set_abs_params (input_dev,ABS_Y ,0 ,1 ,0 ,0 ); +if (!(input_dev->absinfo && (input_dev->absinfo[ABS_X ].minimum || + input_dev->absinfo[ABS_X ].maximum))) +input_set_abs_params (input_dev,ABS_X ,0 ,1 ,0 ,0 ); +if (!(input_dev->absinfo && (input_dev->absinfo[ABS_Y ].minimum || + input_dev->absinfo[ABS_Y ].maximum))) +input_set_abs_params (input_dev,ABS_Y ,0 ,1 ,0 ,0 );/* kept for making udev and libwacom accepting the pad */ __set_bit (BTN_STYLUS , input_dev->keybit);
@@ -3225,6 +3333,9 @@ int wacom_setup_pad_input_capabilities(struct input_dev *input_dev,input_set_abs_params (input_dev,ABS_WHEEL ,0 ,71 ,0 ,0 );break ; +case HID_GENERIC : +break ; +default :/* no pad supported */ return -ENODEV ;
drivers/hid/wacom_wac.h +19 -0
@@ -86,19 +86,34 @@#define WACOM_DEVICETYPE_DIRECT 0x0010#define WACOM_HID_UP_WACOMDIGITIZER 0xff0d0000 +#define WACOM_HID_SP_PAD 0x00040000 +#define WACOM_HID_SP_BUTTON 0x00090000#define WACOM_HID_SP_DIGITIZER 0x000d0000#define WACOM_HID_SP_DIGITIZERINFO 0x00100000#define WACOM_HID_WD_DIGITIZER (WACOM_HID_UP_WACOMDIGITIZER | 0x01)#define WACOM_HID_WD_SENSE (WACOM_HID_UP_WACOMDIGITIZER | 0x36) +#define WACOM_HID_WD_DIGITIZERFNKEYS (WACOM_HID_UP_WACOMDIGITIZER | 0x39)#define WACOM_HID_WD_SERIALHI (WACOM_HID_UP_WACOMDIGITIZER | 0x5c)#define WACOM_HID_WD_TOOLTYPE (WACOM_HID_UP_WACOMDIGITIZER | 0x77)#define WACOM_HID_WD_DISTANCE (WACOM_HID_UP_WACOMDIGITIZER | 0x0132) +#define WACOM_HID_WD_TOUCHRING (WACOM_HID_UP_WACOMDIGITIZER | 0x0138) +#define WACOM_HID_WD_TOUCHRINGSTATUS (WACOM_HID_UP_WACOMDIGITIZER | 0x0139) +#define WACOM_HID_WD_ACCELEROMETER_X (WACOM_HID_UP_WACOMDIGITIZER | 0x0401) +#define WACOM_HID_WD_ACCELEROMETER_Y (WACOM_HID_UP_WACOMDIGITIZER | 0x0402) +#define WACOM_HID_WD_ACCELEROMETER_Z (WACOM_HID_UP_WACOMDIGITIZER | 0x0403) +#define WACOM_HID_WD_EXPRESSKEY00 (WACOM_HID_UP_WACOMDIGITIZER | 0x0910) +#define WACOM_HID_WD_BUTTONHOME (WACOM_HID_UP_WACOMDIGITIZER | 0x0990) +#define WACOM_HID_WD_BUTTONUP (WACOM_HID_UP_WACOMDIGITIZER | 0x0991) +#define WACOM_HID_WD_BUTTONDOWN (WACOM_HID_UP_WACOMDIGITIZER | 0x0992) +#define WACOM_HID_WD_BUTTONLEFT (WACOM_HID_UP_WACOMDIGITIZER | 0x0993) +#define WACOM_HID_WD_BUTTONRIGHT (WACOM_HID_UP_WACOMDIGITIZER | 0x0994)#define WACOM_HID_WD_FINGERWHEEL (WACOM_HID_UP_WACOMDIGITIZER | 0x0d03)#define WACOM_HID_WD_OFFSETLEFT (WACOM_HID_UP_WACOMDIGITIZER | 0x0d30)#define WACOM_HID_WD_OFFSETTOP (WACOM_HID_UP_WACOMDIGITIZER | 0x0d31)#define WACOM_HID_WD_OFFSETRIGHT (WACOM_HID_UP_WACOMDIGITIZER | 0x0d32)#define WACOM_HID_WD_OFFSETBOTTOM (WACOM_HID_UP_WACOMDIGITIZER | 0x0d33)#define WACOM_HID_WD_DATAMODE (WACOM_HID_UP_WACOMDIGITIZER | 0x1002) +#define WACOM_HID_WD_DIGITIZERINFO (WACOM_HID_UP_WACOMDIGITIZER | 0x1013)#define WACOM_HID_UP_G9 0xff090000#define WACOM_HID_G9_PEN (WACOM_HID_UP_G9 | 0x02)#define WACOM_HID_G9_TOUCHSCREEN (WACOM_HID_UP_G9 | 0x11)
@@ -106,6 +121,10 @@#define WACOM_HID_G11_PEN (WACOM_HID_UP_G11 | 0x02)#define WACOM_HID_G11_TOUCHSCREEN (WACOM_HID_UP_G11 | 0x11) +#define WACOM_PAD_FIELD (f) (((f)->physical == HID_DG_TABLETFUNCTIONKEY) || \ + ((f)->physical == WACOM_HID_WD_DIGITIZERFNKEYS) || \ + ((f)->physical == WACOM_HID_WD_DIGITIZERINFO)) +#define WACOM_PEN_FIELD (f) (((f)->logical == HID_DG_STYLUS) || \ ((f)->physical == HID_DG_STYLUS) || \ ((f)->physical == HID_DG_PEN) || \
Signature · 1 line
2.10.0
PATCH v3 16/18 HID: wacom: generic: Add support for battery status on pen and pad interfaces
In reply to Jason GereckeAdds support for usages that may appear on the pen or pad interface which report the state of the tablet battery.
--- drivers/hid/wacom_wac.c | 41 ++++++++++++++++++++++++++++++++++++++++- drivers/hid/wacom_wac.h | 6 ++++++ include/linux/hid.h | 1 + 3 files changed, 47 insertions(+), 1 deletion(-)
drivers/hid/wacom_wac.c +40 -1
@@ -1525,6 +1525,10 @@ static void wacom_wac_pad_usage_mapping(struct hid_device *hdev,unsigned equivalent_usage =wacom_equivalent_usage (usage->hid);switch (equivalent_usage) { +case WACOM_HID_WD_BATTERY_LEVEL : +case WACOM_HID_WD_BATTERY_CHARGING : + features->quirks |=WACOM_QUIRK_BATTERY ; +break ;case WACOM_HID_WD_ACCELEROMETER_X :__set_bit (INPUT_PROP_ACCELEROMETER , input->propbit);wacom_map_usage (input, usage, field,EV_ABS ,ABS_X ,0 );
@@ -1574,8 +1578,25 @@ static int wacom_wac_pad_event(struct hid_device *hdev, struct hid_field *field, wacom_wac->hid_data.inrange_state |= value; } -if (equivalent_usage !=WACOM_HID_WD_TOUCHRINGSTATUS ) +switch (equivalent_usage) { +case WACOM_HID_WD_BATTERY_LEVEL : + wacom_wac->hid_data.battery_capacity = value; + wacom_wac->hid_data.bat_connected =1 ; +return 0 ; + +case WACOM_HID_WD_BATTERY_CHARGING : + wacom_wac->hid_data.bat_charging = value; + wacom_wac->hid_data.ps_connected = value; + wacom_wac->hid_data.bat_connected =1 ; +return 0 ; + +case WACOM_HID_WD_TOUCHRINGSTATUS : +return 0 ; + +default :input_event (input, usage->type, usage->code, value); +break ; + }return 0 ; }
@@ -1594,6 +1615,7 @@ static void wacom_wac_pad_report(struct hid_device *hdev, {struct wacom *wacom =hid_get_drvdata (hdev);struct wacom_wac *wacom_wac = &wacom->wacom_wac; +struct wacom_features *features = &wacom_wac->features;struct input_dev *input = wacom_wac->pad_input;bool active = wacom_wac->hid_data.inrange_state !=0 ;
@@ -1604,6 +1626,16 @@ static void wacom_wac_pad_report(struct hid_device *hdev,if (wacom_equivalent_usage (report->field[0 ]->physical) ==HID_DG_TABLETFUNCTIONKEY )input_event (input,EV_ABS ,ABS_MISC , active ?PAD_DEVICE_ID :0 ); +if (features->quirks &WACOM_QUIRK_BATTERY ) { +int capacity = wacom_wac->hid_data.battery_capacity; +bool charging = wacom_wac->hid_data.bat_charging; +bool connected = wacom_wac->hid_data.bat_connected; +bool powered = wacom_wac->hid_data.ps_connected; + +wacom_notify_battery (wacom_wac, capacity, charging, + connected, powered); + } +input_sync (input); }
@@ -1633,6 +1665,9 @@ static void wacom_wac_pen_usage_mapping(struct hid_device *hdev,case HID_DG_INRANGE :wacom_map_usage (input, usage, field,EV_KEY ,BTN_TOOL_PEN ,0 );break ; +case HID_DG_BATTERYSTRENGTH : + features->quirks |=WACOM_QUIRK_BATTERY ; +break ;case HID_DG_INVERT :wacom_map_usage (input, usage, field,EV_KEY ,BTN_TOOL_RUBBER ,0 );
@@ -1703,6 +1738,10 @@ static int wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field,if (!(features->quirks &WACOM_QUIRK_SENSE )) wacom_wac->hid_data.sense_state = value;return 0 ; +case HID_DG_BATTERYSTRENGTH : + wacom_wac->hid_data.battery_capacity = value; + wacom_wac->hid_data.bat_connected =1 ; +break ;case HID_DG_INVERT : wacom_wac->hid_data.invert_state = value;return 0 ;
drivers/hid/wacom_wac.h +6 -0
@@ -101,6 +101,8 @@#define WACOM_HID_WD_ACCELEROMETER_X (WACOM_HID_UP_WACOMDIGITIZER | 0x0401)#define WACOM_HID_WD_ACCELEROMETER_Y (WACOM_HID_UP_WACOMDIGITIZER | 0x0402)#define WACOM_HID_WD_ACCELEROMETER_Z (WACOM_HID_UP_WACOMDIGITIZER | 0x0403) +#define WACOM_HID_WD_BATTERY_CHARGING (WACOM_HID_UP_WACOMDIGITIZER | 0x0404) +#define WACOM_HID_WD_BATTERY_LEVEL (WACOM_HID_UP_WACOMDIGITIZER | 0x043b)#define WACOM_HID_WD_EXPRESSKEY00 (WACOM_HID_UP_WACOMDIGITIZER | 0x0910)#define WACOM_HID_WD_BUTTONHOME (WACOM_HID_UP_WACOMDIGITIZER | 0x0990)#define WACOM_HID_WD_BUTTONUP (WACOM_HID_UP_WACOMDIGITIZER | 0x0991)
@@ -257,6 +259,10 @@ struct hid_data {int last_slot_field;int num_expected;int num_received; +int battery_capacity; +int bat_charging; +int bat_connected; +int ps_connected; };struct wacom_remote_data {
include/linux/hid.h +1 -0
@@ -231,6 +231,7 @@ struct hid_item {#define HID_DG_TAP 0x000d0035#define HID_DG_TABLETFUNCTIONKEY 0x000d0039#define HID_DG_PROGRAMCHANGEKEY 0x000d003a +#define HID_DG_BATTERYSTRENGTH 0x000d003b#define HID_DG_INVERT 0x000d003c#define HID_DG_TILT_X 0x000d003d#define HID_DG_TILT_Y 0x000d003e
Signature · 1 line
2.10.0
PATCH v3 17/18 HID: wacom: generic: Extend pad support
In reply to Jason GereckeThe HID specification that the MobileStudio Pro follows includes usages for several values that would be good to support so that future devices "just work" out of the box. Extend the HID_GENERIC pad codepath to handle these usages.
--- drivers/hid/wacom_wac.c | 15 +++++++++++++++ drivers/hid/wacom_wac.h | 5 +++++ 2 files changed, 20 insertions(+)
drivers/hid/wacom_wac.c +15 -0
@@ -1457,6 +1457,8 @@ static int wacom_equivalent_usage(int usage) usage ==WACOM_HID_WD_SERIALHI || usage ==WACOM_HID_WD_TOOLTYPE || usage ==WACOM_HID_WD_DISTANCE || + usage ==WACOM_HID_WD_TOUCHSTRIP || + usage ==WACOM_HID_WD_TOUCHSTRIP2 || usage ==WACOM_HID_WD_TOUCHRING || usage == WACOM_HID_WD_TOUCHRINGSTATUS) { return usage;
@@ -1512,6 +1514,9 @@ static void wacom_map_usage(struct input_dev *input, struct hid_usage *usage,case EV_MSC :input_set_capability (input,EV_MSC , code);break ; +case EV_SW : +input_set_capability (input,EV_SW , code); +break ; } }
@@ -1546,11 +1551,21 @@ static void wacom_wac_pad_usage_mapping(struct hid_device *hdev,case WACOM_HID_WD_BUTTONDOWN :case WACOM_HID_WD_BUTTONLEFT :case WACOM_HID_WD_BUTTONRIGHT : +case WACOM_HID_WD_BUTTONCENTER :wacom_map_usage (input, usage, field,EV_KEY ,wacom_numbered_button_to_key (features->numbered_buttons),0 ); features->numbered_buttons++;break ; +case WACOM_HID_WD_TOUCHONOFF : +wacom_map_usage (input, usage, field,EV_SW ,SW_MUTE_DEVICE ,0 ); +break ; +case WACOM_HID_WD_TOUCHSTRIP : +wacom_map_usage (input, usage, field,EV_ABS ,ABS_RX ,0 ); +break ; +case WACOM_HID_WD_TOUCHSTRIP2 : +wacom_map_usage (input, usage, field,EV_ABS ,ABS_RY ,0 ); +break ;case WACOM_HID_WD_TOUCHRING :wacom_map_usage (input, usage, field,EV_ABS ,ABS_WHEEL ,0 );break ;
drivers/hid/wacom_wac.h +5 -0
@@ -96,6 +96,8 @@#define WACOM_HID_WD_SERIALHI (WACOM_HID_UP_WACOMDIGITIZER | 0x5c)#define WACOM_HID_WD_TOOLTYPE (WACOM_HID_UP_WACOMDIGITIZER | 0x77)#define WACOM_HID_WD_DISTANCE (WACOM_HID_UP_WACOMDIGITIZER | 0x0132) +#define WACOM_HID_WD_TOUCHSTRIP (WACOM_HID_UP_WACOMDIGITIZER | 0x0136) +#define WACOM_HID_WD_TOUCHSTRIP2 (WACOM_HID_UP_WACOMDIGITIZER | 0x0137)#define WACOM_HID_WD_TOUCHRING (WACOM_HID_UP_WACOMDIGITIZER | 0x0138)#define WACOM_HID_WD_TOUCHRINGSTATUS (WACOM_HID_UP_WACOMDIGITIZER | 0x0139)#define WACOM_HID_WD_ACCELEROMETER_X (WACOM_HID_UP_WACOMDIGITIZER | 0x0401)
@@ -104,11 +106,14 @@#define WACOM_HID_WD_BATTERY_CHARGING (WACOM_HID_UP_WACOMDIGITIZER | 0x0404)#define WACOM_HID_WD_BATTERY_LEVEL (WACOM_HID_UP_WACOMDIGITIZER | 0x043b)#define WACOM_HID_WD_EXPRESSKEY00 (WACOM_HID_UP_WACOMDIGITIZER | 0x0910) +#define WACOM_HID_WD_EXPRESSKEYCAP00 (WACOM_HID_UP_WACOMDIGITIZER | 0x0950)#define WACOM_HID_WD_BUTTONHOME (WACOM_HID_UP_WACOMDIGITIZER | 0x0990)#define WACOM_HID_WD_BUTTONUP (WACOM_HID_UP_WACOMDIGITIZER | 0x0991)#define WACOM_HID_WD_BUTTONDOWN (WACOM_HID_UP_WACOMDIGITIZER | 0x0992)#define WACOM_HID_WD_BUTTONLEFT (WACOM_HID_UP_WACOMDIGITIZER | 0x0993)#define WACOM_HID_WD_BUTTONRIGHT (WACOM_HID_UP_WACOMDIGITIZER | 0x0994) +#define WACOM_HID_WD_BUTTONCENTER (WACOM_HID_UP_WACOMDIGITIZER | 0x0995) +#define WACOM_HID_WD_TOUCHONOFF (WACOM_HID_UP_WACOMDIGITIZER | 0x0996)#define WACOM_HID_WD_FINGERWHEEL (WACOM_HID_UP_WACOMDIGITIZER | 0x0d03)#define WACOM_HID_WD_OFFSETLEFT (WACOM_HID_UP_WACOMDIGITIZER | 0x0d30)#define WACOM_HID_WD_OFFSETTOP (WACOM_HID_UP_WACOMDIGITIZER | 0x0d31)
Signature · 1 line
2.10.0
PATCH v3 18/18 HID: input: Recognize ABS_WHEEL in hidinput_calc_abs_res
In reply to Jason GereckeThe "Steering" usage (HID_UP_SIMULATION | 0xc8) is defined in HUT 1.12 as follows:
"A steering wheel is a single degree-of-freedom device that rotates about an axis. The zero position is always the neutral or 'straight ahead' position, with positive values turning clockwise and negative values turning counterclockwise. If the Coordinate Values Wrap attribute is set, the steering wheel can be turned past 360 degrees."
The hidinput_configure_usage function canonically maps this usage to the ABS_WHEEL axis, but hidinput_calc_abs_res does not recognize this axis as one for which it can calculate a resolution. This effectively prevents wheels from being assigned a proper resolution that userspace can use to determine the precise angle of input.
This commit adds ABS_WHEEL as a rotational axis to hidinput_calc_abs_res.
--- drivers/hid/hid-input.c | 1 + 1 file changed, 1 insertion(+)
drivers/hid/hid-input.c +1 -0
@@ -253,6 +253,7 @@ __s32 hidinput_calc_abs_res(const struct hid_field *field, __u16 code)case ABS_RX :case ABS_RY :case ABS_RZ : +case ABS_WHEEL :case ABS_TILT_X :case ABS_TILT_Y :if (field->unit ==0x14 ) {/* If degrees */
Signature · 1 line
2.10.0