Skip to content

Commit 5a4abb3

Browse files
whotbentiss
authored andcommitted
HID: core: process the Resolution Multiplier
The Resolution Multiplier is a feature report that modifies the value of Usages within the same Logical Collection. If the multiplier is set to anything but 1, the hardware reports (value * multiplier) for the same amount of physical movement, i.e. the value we receive in the kernel is pre-multiplied. The hardware may either send a single (value * multiplier), or by sending multiplier as many reports with the same value, or a combination of these two options. For example, when the Microsoft Sculpt Ergonomic mouse Resolution Multiplier is set to 12, the Wheel sends out 12 for every detent but AC Pan sends out a value of 3 at 4 times the frequency. The effective multiplier is based on the physical min/max of the multiplier field, a logical min/max of [0,1] with a physical min/max of [1,8] means the multiplier is either 1 or 8. The Resolution Multiplier was introduced for high-resolution scrolling in Windows Vista and is commonly used on Microsoft mice. The recommendation for the Resolution Multiplier is to default to 1 for backwards compatibility. This patch adds an arbitrary upper limit at 255. The only known use case for the Resolution Multiplier is for scroll wheels where the multiplier has to be a fraction of 120 to work with Windows. Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net> Verified-by: Harry Cutts <hcutts@chromium.org> Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
1 parent c53431e commit 5a4abb3

File tree

2 files changed

+175
-0
lines changed

2 files changed

+175
-0
lines changed

drivers/hid/hid-core.c

Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,7 @@ static int hid_add_field(struct hid_parser *parser, unsigned report_type, unsign
294294
field->usage[i].collection_index =
295295
parser->local.collection_index[j];
296296
field->usage[i].usage_index = i;
297+
field->usage[i].resolution_multiplier = 1;
297298
}
298299

299300
field->maxusage = usages;
@@ -947,6 +948,167 @@ struct hid_report *hid_validate_values(struct hid_device *hid,
947948
}
948949
EXPORT_SYMBOL_GPL(hid_validate_values);
949950

951+
static int hid_calculate_multiplier(struct hid_device *hid,
952+
struct hid_field *multiplier)
953+
{
954+
int m;
955+
__s32 v = *multiplier->value;
956+
__s32 lmin = multiplier->logical_minimum;
957+
__s32 lmax = multiplier->logical_maximum;
958+
__s32 pmin = multiplier->physical_minimum;
959+
__s32 pmax = multiplier->physical_maximum;
960+
961+
/*
962+
* "Because OS implementations will generally divide the control's
963+
* reported count by the Effective Resolution Multiplier, designers
964+
* should take care not to establish a potential Effective
965+
* Resolution Multiplier of zero."
966+
* HID Usage Table, v1.12, Section 4.3.1, p31
967+
*/
968+
if (lmax - lmin == 0)
969+
return 1;
970+
/*
971+
* Handling the unit exponent is left as an exercise to whoever
972+
* finds a device where that exponent is not 0.
973+
*/
974+
m = ((v - lmin)/(lmax - lmin) * (pmax - pmin) + pmin);
975+
if (unlikely(multiplier->unit_exponent != 0)) {
976+
hid_warn(hid,
977+
"unsupported Resolution Multiplier unit exponent %d\n",
978+
multiplier->unit_exponent);
979+
}
980+
981+
/* There are no devices with an effective multiplier > 255 */
982+
if (unlikely(m == 0 || m > 255 || m < -255)) {
983+
hid_warn(hid, "unsupported Resolution Multiplier %d\n", m);
984+
m = 1;
985+
}
986+
987+
return m;
988+
}
989+
990+
static void hid_apply_multiplier_to_field(struct hid_device *hid,
991+
struct hid_field *field,
992+
struct hid_collection *multiplier_collection,
993+
int effective_multiplier)
994+
{
995+
struct hid_collection *collection;
996+
struct hid_usage *usage;
997+
int i;
998+
999+
/*
1000+
* If multiplier_collection is NULL, the multiplier applies
1001+
* to all fields in the report.
1002+
* Otherwise, it is the Logical Collection the multiplier applies to
1003+
* but our field may be in a subcollection of that collection.
1004+
*/
1005+
for (i = 0; i < field->maxusage; i++) {
1006+
usage = &field->usage[i];
1007+
1008+
collection = &hid->collection[usage->collection_index];
1009+
while (collection && collection != multiplier_collection)
1010+
collection = collection->parent;
1011+
1012+
if (collection || multiplier_collection == NULL)
1013+
usage->resolution_multiplier = effective_multiplier;
1014+
1015+
}
1016+
}
1017+
1018+
static void hid_apply_multiplier(struct hid_device *hid,
1019+
struct hid_field *multiplier)
1020+
{
1021+
struct hid_report_enum *rep_enum;
1022+
struct hid_report *rep;
1023+
struct hid_field *field;
1024+
struct hid_collection *multiplier_collection;
1025+
int effective_multiplier;
1026+
int i;
1027+
1028+
/*
1029+
* "The Resolution Multiplier control must be contained in the same
1030+
* Logical Collection as the control(s) to which it is to be applied.
1031+
* If no Resolution Multiplier is defined, then the Resolution
1032+
* Multiplier defaults to 1. If more than one control exists in a
1033+
* Logical Collection, the Resolution Multiplier is associated with
1034+
* all controls in the collection. If no Logical Collection is
1035+
* defined, the Resolution Multiplier is associated with all
1036+
* controls in the report."
1037+
* HID Usage Table, v1.12, Section 4.3.1, p30
1038+
*
1039+
* Thus, search from the current collection upwards until we find a
1040+
* logical collection. Then search all fields for that same parent
1041+
* collection. Those are the fields the multiplier applies to.
1042+
*
1043+
* If we have more than one multiplier, it will overwrite the
1044+
* applicable fields later.
1045+
*/
1046+
multiplier_collection = &hid->collection[multiplier->usage->collection_index];
1047+
while (multiplier_collection &&
1048+
multiplier_collection->type != HID_COLLECTION_LOGICAL)
1049+
multiplier_collection = multiplier_collection->parent;
1050+
1051+
effective_multiplier = hid_calculate_multiplier(hid, multiplier);
1052+
1053+
rep_enum = &hid->report_enum[HID_INPUT_REPORT];
1054+
list_for_each_entry(rep, &rep_enum->report_list, list) {
1055+
for (i = 0; i < rep->maxfield; i++) {
1056+
field = rep->field[i];
1057+
hid_apply_multiplier_to_field(hid, field,
1058+
multiplier_collection,
1059+
effective_multiplier);
1060+
}
1061+
}
1062+
}
1063+
1064+
/*
1065+
* hid_setup_resolution_multiplier - set up all resolution multipliers
1066+
*
1067+
* @device: hid device
1068+
*
1069+
* Search for all Resolution Multiplier Feature Reports and apply their
1070+
* value to all matching Input items. This only updates the internal struct
1071+
* fields.
1072+
*
1073+
* The Resolution Multiplier is applied by the hardware. If the multiplier
1074+
* is anything other than 1, the hardware will send pre-multiplied events
1075+
* so that the same physical interaction generates an accumulated
1076+
* accumulated_value = value * * multiplier
1077+
* This may be achieved by sending
1078+
* - "value * multiplier" for each event, or
1079+
* - "value" but "multiplier" times as frequently, or
1080+
* - a combination of the above
1081+
* The only guarantee is that the same physical interaction always generates
1082+
* an accumulated 'value * multiplier'.
1083+
*
1084+
* This function must be called before any event processing and after
1085+
* any SetRequest to the Resolution Multiplier.
1086+
*/
1087+
void hid_setup_resolution_multiplier(struct hid_device *hid)
1088+
{
1089+
struct hid_report_enum *rep_enum;
1090+
struct hid_report *rep;
1091+
struct hid_usage *usage;
1092+
int i, j;
1093+
1094+
rep_enum = &hid->report_enum[HID_FEATURE_REPORT];
1095+
list_for_each_entry(rep, &rep_enum->report_list, list) {
1096+
for (i = 0; i < rep->maxfield; i++) {
1097+
/* Ignore if report count is out of bounds. */
1098+
if (rep->field[i]->report_count < 1)
1099+
continue;
1100+
1101+
for (j = 0; j < rep->field[i]->maxusage; j++) {
1102+
usage = &rep->field[i]->usage[j];
1103+
if (usage->hid == HID_GD_RESOLUTION_MULTIPLIER)
1104+
hid_apply_multiplier(hid,
1105+
rep->field[i]);
1106+
}
1107+
}
1108+
}
1109+
}
1110+
EXPORT_SYMBOL_GPL(hid_setup_resolution_multiplier);
1111+
9501112
/**
9511113
* hid_open_report - open a driver-specific device report
9521114
*
@@ -1043,9 +1205,17 @@ int hid_open_report(struct hid_device *device)
10431205
hid_err(device, "unbalanced delimiter at end of report description\n");
10441206
goto err;
10451207
}
1208+
1209+
/*
1210+
* fetch initial values in case the device's
1211+
* default multiplier isn't the recommended 1
1212+
*/
1213+
hid_setup_resolution_multiplier(device);
1214+
10461215
kfree(parser->collection_stack);
10471216
vfree(parser);
10481217
device->status |= HID_STAT_PARSED;
1218+
10491219
return 0;
10501220
}
10511221
}

include/linux/hid.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,7 @@ struct hid_item {
219219
#define HID_GD_VBRZ 0x00010045
220220
#define HID_GD_VNO 0x00010046
221221
#define HID_GD_FEATURE 0x00010047
222+
#define HID_GD_RESOLUTION_MULTIPLIER 0x00010048
222223
#define HID_GD_SYSTEM_CONTROL 0x00010080
223224
#define HID_GD_UP 0x00010090
224225
#define HID_GD_DOWN 0x00010091
@@ -437,6 +438,8 @@ struct hid_usage {
437438
unsigned hid; /* hid usage code */
438439
unsigned collection_index; /* index into collection array */
439440
unsigned usage_index; /* index into usage array */
441+
__s8 resolution_multiplier;/* Effective Resolution Multiplier
442+
(HUT v1.12, 4.3.1), default: 1 */
440443
/* hidinput data */
441444
__u16 code; /* input driver code */
442445
__u8 type; /* input driver type */
@@ -894,6 +897,8 @@ struct hid_report *hid_validate_values(struct hid_device *hid,
894897
unsigned int type, unsigned int id,
895898
unsigned int field_index,
896899
unsigned int report_counts);
900+
901+
void hid_setup_resolution_multiplier(struct hid_device *hid);
897902
int hid_open_report(struct hid_device *device);
898903
int hid_check_keys_pressed(struct hid_device *hid);
899904
int hid_connect(struct hid_device *hid, unsigned int connect_mask);

0 commit comments

Comments
 (0)