aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBenjamin Tissoires <benjamin.tissoires@redhat.com>2018-07-13 10:13:49 -0400
committerJiri Kosina <jkosina@suse.cz>2018-07-17 09:33:47 -0400
commitba6b055e0f3b4ff4942e4ab273260affcfad9bff (patch)
tree021c6fbfcdeb4b1aa7493b3259f9c60adb7727da
parent01eaac7e57134cae4e75b36195a10d525939c7bf (diff)
HID: input: enable Totem on the Dell Canvas 27
The Dell Canvas 27 has a tool that can be put on the surface and acts as a dial. The firmware processes the detection of the tool and forward regular HID reports with X, Y, Azimuth, rotation, width/height. The firmware also exports Contact ID, Countact Count which may hint that several totems can be used at the same time (the FW only supports one). We can tell that MT_TOOL_DIAL will be reported by setting the min/max of ABS_MT_TOOL_TYPE to MT_TOOL_DIAL. This tool is aimed at being used by the system and not the applications, so the user space processing should not go through the regular touch inputs. We set INPUT_PROP_DIRECT which applies ID_INPUT_TOUCHSCREEN to this new type of devices, but we will counter this for the time being with the special udev hwdb entry mentioned above. Link: https://bugzilla.redhat.com/show_bug.cgi?id=1511846 Acked-by: Peter Hutterer <peter.hutterer@who-t.net> Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
-rw-r--r--drivers/hid/hid-input.c3
-rw-r--r--drivers/hid/hid-multitouch.c48
-rw-r--r--include/linux/hid.h6
3 files changed, 43 insertions, 14 deletions
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
index ab93dd5927c3..4e94ea3e280a 100644
--- a/drivers/hid/hid-input.c
+++ b/drivers/hid/hid-input.c
@@ -1550,6 +1550,9 @@ static struct hid_input *hidinput_allocate(struct hid_device *hid,
1550 case HID_GD_WIRELESS_RADIO_CTLS: 1550 case HID_GD_WIRELESS_RADIO_CTLS:
1551 suffix = "Wireless Radio Control"; 1551 suffix = "Wireless Radio Control";
1552 break; 1552 break;
1553 case HID_GD_SYSTEM_MULTIAXIS:
1554 suffix = "System Multi Axis";
1555 break;
1553 default: 1556 default:
1554 break; 1557 break;
1555 } 1558 }
diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
index 346e9caef6f3..a4a274ebfbef 100644
--- a/drivers/hid/hid-multitouch.c
+++ b/drivers/hid/hid-multitouch.c
@@ -665,7 +665,8 @@ static int mt_touch_input_mapping(struct hid_device *hdev, struct hid_input *hi,
665 /* 665 /*
666 * Model touchscreens providing buttons as touchpads. 666 * Model touchscreens providing buttons as touchpads.
667 */ 667 */
668 if ((usage->hid & HID_USAGE_PAGE) == HID_UP_BUTTON) { 668 if (field->application == HID_DG_TOUCHSCREEN &&
669 (usage->hid & HID_USAGE_PAGE) == HID_UP_BUTTON) {
669 app->mt_flags |= INPUT_MT_POINTER; 670 app->mt_flags |= INPUT_MT_POINTER;
670 td->inputmode_value = MT_INPUTMODE_TOUCHPAD; 671 td->inputmode_value = MT_INPUTMODE_TOUCHPAD;
671 } 672 }
@@ -692,6 +693,19 @@ static int mt_touch_input_mapping(struct hid_device *hdev, struct hid_input *hi,
692 693
693 set_abs(hi->input, code, field, cls->sn_move); 694 set_abs(hi->input, code, field, cls->sn_move);
694 695
696 /*
697 * A system multi-axis that exports X and Y has a high
698 * chance of being used directly on a surface
699 */
700 if (field->application == HID_GD_SYSTEM_MULTIAXIS) {
701 __set_bit(INPUT_PROP_DIRECT,
702 hi->input->propbit);
703 input_set_abs_params(hi->input,
704 ABS_MT_TOOL_TYPE,
705 MT_TOOL_DIAL,
706 MT_TOOL_DIAL, 0, 0);
707 }
708
695 return 1; 709 return 1;
696 case HID_GD_Y: 710 case HID_GD_Y:
697 if (prev_usage && (prev_usage->hid == usage->hid)) { 711 if (prev_usage && (prev_usage->hid == usage->hid)) {
@@ -725,7 +739,9 @@ static int mt_touch_input_mapping(struct hid_device *hdev, struct hid_input *hi,
725 MT_STORE_FIELD(confidence_state); 739 MT_STORE_FIELD(confidence_state);
726 return 1; 740 return 1;
727 case HID_DG_TIPSWITCH: 741 case HID_DG_TIPSWITCH:
728 input_set_capability(hi->input, EV_KEY, BTN_TOUCH); 742 if (field->application != HID_GD_SYSTEM_MULTIAXIS)
743 input_set_capability(hi->input,
744 EV_KEY, BTN_TOUCH);
729 MT_STORE_FIELD(tip_state); 745 MT_STORE_FIELD(tip_state);
730 return 1; 746 return 1;
731 case HID_DG_CONTACTID: 747 case HID_DG_CONTACTID:
@@ -802,6 +818,10 @@ static int mt_touch_input_mapping(struct hid_device *hdev, struct hid_input *hi,
802 field->application == HID_DG_TOUCHPAD && 818 field->application == HID_DG_TOUCHPAD &&
803 (usage->hid & HID_USAGE) > 1) 819 (usage->hid & HID_USAGE) > 1)
804 code--; 820 code--;
821
822 if (field->application == HID_GD_SYSTEM_MULTIAXIS)
823 code = BTN_0 + ((usage->hid - 1) & HID_USAGE);
824
805 hid_map_usage(hi, usage, bit, max, EV_KEY, code); 825 hid_map_usage(hi, usage, bit, max, EV_KEY, code);
806 input_set_capability(hi->input, EV_KEY, code); 826 input_set_capability(hi->input, EV_KEY, code);
807 return 1; 827 return 1;
@@ -899,6 +919,7 @@ static int mt_process_slot(struct mt_device *td, struct input_dev *input,
899 bool inrange_state = false; 919 bool inrange_state = false;
900 int active; 920 int active;
901 int slotnum; 921 int slotnum;
922 int tool = MT_TOOL_FINGER;
902 923
903 if (!slot) 924 if (!slot)
904 return -EINVAL; 925 return -EINVAL;
@@ -939,8 +960,11 @@ static int mt_process_slot(struct mt_device *td, struct input_dev *input,
939 960
940 active = (*slot->tip_state || inrange_state) && confidence_state; 961 active = (*slot->tip_state || inrange_state) && confidence_state;
941 962
963 if (app->application == HID_GD_SYSTEM_MULTIAXIS)
964 tool = MT_TOOL_DIAL;
965
942 input_mt_slot(input, slotnum); 966 input_mt_slot(input, slotnum);
943 input_mt_report_slot_state(input, MT_TOOL_FINGER, active); 967 input_mt_report_slot_state(input, tool, active);
944 if (active) { 968 if (active) {
945 /* this finger is in proximity of the sensor */ 969 /* this finger is in proximity of the sensor */
946 int wide = (*slot->w > *slot->h); 970 int wide = (*slot->w > *slot->h);
@@ -1203,6 +1227,7 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
1203 field->application != HID_GD_SYSTEM_CONTROL && 1227 field->application != HID_GD_SYSTEM_CONTROL &&
1204 field->application != HID_CP_CONSUMER_CONTROL && 1228 field->application != HID_CP_CONSUMER_CONTROL &&
1205 field->application != HID_GD_WIRELESS_RADIO_CTLS && 1229 field->application != HID_GD_WIRELESS_RADIO_CTLS &&
1230 field->application != HID_GD_SYSTEM_MULTIAXIS &&
1206 !(field->application == HID_VD_ASUS_CUSTOM_MEDIA_KEYS && 1231 !(field->application == HID_VD_ASUS_CUSTOM_MEDIA_KEYS &&
1207 application->quirks & MT_QUIRK_ASUS_CUSTOM_UP)) 1232 application->quirks & MT_QUIRK_ASUS_CUSTOM_UP))
1208 return -1; 1233 return -1;
@@ -1230,9 +1255,7 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
1230 return 1; 1255 return 1;
1231 } 1256 }
1232 1257
1233 if (rdata->is_mt_collection && 1258 if (rdata->is_mt_collection)
1234 (field->application == HID_DG_TOUCHSCREEN ||
1235 field->application == HID_DG_TOUCHPAD))
1236 return mt_touch_input_mapping(hdev, hi, field, usage, bit, max, 1259 return mt_touch_input_mapping(hdev, hi, field, usage, bit, max,
1237 application); 1260 application);
1238 1261
@@ -1244,15 +1267,11 @@ static int mt_input_mapped(struct hid_device *hdev, struct hid_input *hi,
1244 struct hid_field *field, struct hid_usage *usage, 1267 struct hid_field *field, struct hid_usage *usage,
1245 unsigned long **bit, int *max) 1268 unsigned long **bit, int *max)
1246{ 1269{
1247 /* 1270 struct mt_device *td = hid_get_drvdata(hdev);
1248 * some egalax touchscreens have "application == HID_DG_TOUCHSCREEN" 1271 struct mt_report_data *rdata;
1249 * for the stylus.
1250 */
1251 if (field->physical == HID_DG_STYLUS)
1252 return 0;
1253 1272
1254 if (field->application == HID_DG_TOUCHSCREEN || 1273 rdata = mt_find_report_data(td, field->report);
1255 field->application == HID_DG_TOUCHPAD) { 1274 if (rdata && rdata->is_mt_collection) {
1256 /* We own these mappings, tell hid-input to ignore them */ 1275 /* We own these mappings, tell hid-input to ignore them */
1257 return -1; 1276 return -1;
1258 } 1277 }
@@ -1460,6 +1479,7 @@ static int mt_input_configured(struct hid_device *hdev, struct hid_input *hi)
1460 case HID_GD_SYSTEM_CONTROL: 1479 case HID_GD_SYSTEM_CONTROL:
1461 case HID_CP_CONSUMER_CONTROL: 1480 case HID_CP_CONSUMER_CONTROL:
1462 case HID_GD_WIRELESS_RADIO_CTLS: 1481 case HID_GD_WIRELESS_RADIO_CTLS:
1482 case HID_GD_SYSTEM_MULTIAXIS:
1463 /* already handled by hid core */ 1483 /* already handled by hid core */
1464 break; 1484 break;
1465 case HID_DG_TOUCHSCREEN: 1485 case HID_DG_TOUCHSCREEN:
diff --git a/include/linux/hid.h b/include/linux/hid.h
index 773bcb1d4044..2e4498d52a2f 100644
--- a/include/linux/hid.h
+++ b/include/linux/hid.h
@@ -190,6 +190,12 @@ struct hid_item {
190 * http://www.usb.org/developers/hidpage/HUTRR40RadioHIDUsagesFinal.pdf 190 * http://www.usb.org/developers/hidpage/HUTRR40RadioHIDUsagesFinal.pdf
191 */ 191 */
192#define HID_GD_WIRELESS_RADIO_CTLS 0x0001000c 192#define HID_GD_WIRELESS_RADIO_CTLS 0x0001000c
193/*
194 * System Multi-Axis, see:
195 * http://www.usb.org/developers/hidpage/HUTRR62_-_Generic_Desktop_CA_for_System_Multi-Axis_Controllers.txt
196 */
197#define HID_GD_SYSTEM_MULTIAXIS 0x0001000e
198
193#define HID_GD_X 0x00010030 199#define HID_GD_X 0x00010030
194#define HID_GD_Y 0x00010031 200#define HID_GD_Y 0x00010031
195#define HID_GD_Z 0x00010032 201#define HID_GD_Z 0x00010032