Add a HID_QUIRK_X_INVERT/HID_QUIRK_Y_INVERT quirk that can be used
to invert the X/Y values.
Signed-off-by: Alistair Francis <[email protected]>
---
drivers/hid/hid-input.c | 6 ++++++
include/linux/hid.h | 2 ++
2 files changed, 8 insertions(+)
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
index 4b5ebeacd283..4babf369184f 100644
--- a/drivers/hid/hid-input.c
+++ b/drivers/hid/hid-input.c
@@ -1328,6 +1328,12 @@ void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct
input = field->hidinput->input;
+ if (usage->type == EV_ABS &&
+ ((*quirks & HID_QUIRK_X_INVERT) && usage->code == ABS_X ||
+ (*quirks & HID_QUIRK_Y_INVERT) && usage->code == ABS_Y)) {
+ value = field->logical_maximum - value;
+ }
+
if (usage->hat_min < usage->hat_max || usage->hat_dir) {
int hat_dir = usage->hat_dir;
if (!hat_dir)
diff --git a/include/linux/hid.h b/include/linux/hid.h
index 9e067f937dbc..4959385ca588 100644
--- a/include/linux/hid.h
+++ b/include/linux/hid.h
@@ -349,6 +349,8 @@ struct hid_item {
/* BIT(9) reserved for backward compatibility, was NO_INIT_INPUT_REPORTS */
#define HID_QUIRK_ALWAYS_POLL BIT(10)
#define HID_QUIRK_INPUT_PER_APP BIT(11)
+#define HID_QUIRK_X_INVERT BIT(12)
+#define HID_QUIRK_Y_INVERT BIT(13)
#define HID_QUIRK_SKIP_OUTPUT_REPORTS BIT(16)
#define HID_QUIRK_SKIP_OUTPUT_REPORT_ID BIT(17)
#define HID_QUIRK_NO_OUTPUT_REPORTS_ON_INTR_EP BIT(18)
--
2.31.1
Hi Alistair,
Thank you for the patch! Perhaps something to improve:
[auto build test WARNING on hid/for-next]
[also build test WARNING on dtor-input/next robh/for-next v5.15-rc7 next-20211026]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]
url: https://github.com/0day-ci/linux/commits/Alistair-Francis/HID-quirks-Allow-inverting-the-absolute-X-Y-values/20211025-184729
base: https://git.kernel.org/pub/scm/linux/kernel/git/hid/hid.git for-next
config: ia64-defconfig (attached as .config)
compiler: ia64-linux-gcc (GCC) 11.2.0
reproduce (this is a W=1 build):
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# https://github.com/0day-ci/linux/commit/ccc9b072f0233da9c215622b32ed61852df33627
git remote add linux-review https://github.com/0day-ci/linux
git fetch --no-tags linux-review Alistair-Francis/HID-quirks-Allow-inverting-the-absolute-X-Y-values/20211025-184729
git checkout ccc9b072f0233da9c215622b32ed61852df33627
# save the attached .config to linux build tree
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-11.2.0 make.cross ARCH=ia64
If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <[email protected]>
All warnings (new ones prefixed by >>):
drivers/hid/hid-input.c: In function 'hidinput_hid_event':
>> drivers/hid/hid-input.c:1333:49: warning: suggest parentheses around '&&' within '||' [-Wparentheses]
1333 | ((*quirks & HID_QUIRK_X_INVERT) && usage->code == ABS_X ||
vim +1333 drivers/hid/hid-input.c
1313
1314 void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct hid_usage *usage, __s32 value)
1315 {
1316 struct input_dev *input;
1317 unsigned *quirks = &hid->quirks;
1318
1319 if (!usage->type)
1320 return;
1321
1322 if (usage->type == EV_PWR) {
1323 hidinput_update_battery(hid, value);
1324 return;
1325 }
1326
1327 if (!field->hidinput)
1328 return;
1329
1330 input = field->hidinput->input;
1331
1332 if (usage->type == EV_ABS &&
> 1333 ((*quirks & HID_QUIRK_X_INVERT) && usage->code == ABS_X ||
1334 (*quirks & HID_QUIRK_Y_INVERT) && usage->code == ABS_Y)) {
1335 value = field->logical_maximum - value;
1336 }
1337
1338 if (usage->hat_min < usage->hat_max || usage->hat_dir) {
1339 int hat_dir = usage->hat_dir;
1340 if (!hat_dir)
1341 hat_dir = (value - usage->hat_min) * 8 / (usage->hat_max - usage->hat_min + 1) + 1;
1342 if (hat_dir < 0 || hat_dir > 8) hat_dir = 0;
1343 input_event(input, usage->type, usage->code , hid_hat_to_axis[hat_dir].x);
1344 input_event(input, usage->type, usage->code + 1, hid_hat_to_axis[hat_dir].y);
1345 return;
1346 }
1347
1348 if (usage->hid == HID_DG_INVERT) {
1349 *quirks = value ? (*quirks | HID_QUIRK_INVERT) : (*quirks & ~HID_QUIRK_INVERT);
1350 return;
1351 }
1352
1353 if (usage->hid == HID_DG_INRANGE) {
1354 if (value) {
1355 input_event(input, usage->type, (*quirks & HID_QUIRK_INVERT) ? BTN_TOOL_RUBBER : usage->code, 1);
1356 return;
1357 }
1358 input_event(input, usage->type, usage->code, 0);
1359 input_event(input, usage->type, BTN_TOOL_RUBBER, 0);
1360 return;
1361 }
1362
1363 if (usage->hid == HID_DG_TIPPRESSURE && (*quirks & HID_QUIRK_NOTOUCH)) {
1364 int a = field->logical_minimum;
1365 int b = field->logical_maximum;
1366 input_event(input, EV_KEY, BTN_TOUCH, value > a + ((b - a) >> 3));
1367 }
1368
1369 if (usage->hid == (HID_UP_PID | 0x83UL)) { /* Simultaneous Effects Max */
1370 dbg_hid("Maximum Effects - %d\n",value);
1371 return;
1372 }
1373
1374 if (usage->hid == (HID_UP_PID | 0x7fUL)) {
1375 dbg_hid("PID Pool Report\n");
1376 return;
1377 }
1378
1379 if ((usage->type == EV_KEY) && (usage->code == 0)) /* Key 0 is "unassigned", not KEY_UNKNOWN */
1380 return;
1381
1382 if ((usage->type == EV_REL) && (usage->code == REL_WHEEL_HI_RES ||
1383 usage->code == REL_HWHEEL_HI_RES)) {
1384 hidinput_handle_scroll(usage, input, value);
1385 return;
1386 }
1387
1388 if ((usage->type == EV_ABS) && (field->flags & HID_MAIN_ITEM_RELATIVE) &&
1389 (usage->code == ABS_VOLUME)) {
1390 int count = abs(value);
1391 int direction = value > 0 ? KEY_VOLUMEUP : KEY_VOLUMEDOWN;
1392 int i;
1393
1394 for (i = 0; i < count; i++) {
1395 input_event(input, EV_KEY, direction, 1);
1396 input_sync(input);
1397 input_event(input, EV_KEY, direction, 0);
1398 input_sync(input);
1399 }
1400 return;
1401 }
1402
1403 /*
1404 * Ignore out-of-range values as per HID specification,
1405 * section 5.10 and 6.2.25, when NULL state bit is present.
1406 * When it's not, clamp the value to match Microsoft's input
1407 * driver as mentioned in "Required HID usages for digitizers":
1408 * https://msdn.microsoft.com/en-us/library/windows/hardware/dn672278(v=vs.85).asp
1409 *
1410 * The logical_minimum < logical_maximum check is done so that we
1411 * don't unintentionally discard values sent by devices which
1412 * don't specify logical min and max.
1413 */
1414 if ((field->flags & HID_MAIN_ITEM_VARIABLE) &&
1415 (field->logical_minimum < field->logical_maximum)) {
1416 if (field->flags & HID_MAIN_ITEM_NULL_STATE &&
1417 (value < field->logical_minimum ||
1418 value > field->logical_maximum)) {
1419 dbg_hid("Ignoring out-of-range value %x\n", value);
1420 return;
1421 }
1422 value = clamp(value,
1423 field->logical_minimum,
1424 field->logical_maximum);
1425 }
1426
1427 /*
1428 * Ignore reports for absolute data if the data didn't change. This is
1429 * not only an optimization but also fixes 'dead' key reports. Some
1430 * RollOver implementations for localized keys (like BACKSLASH/PIPE; HID
1431 * 0x31 and 0x32) report multiple keys, even though a localized keyboard
1432 * can only have one of them physically available. The 'dead' keys
1433 * report constant 0. As all map to the same keycode, they'd confuse
1434 * the input layer. If we filter the 'dead' keys on the HID level, we
1435 * skip the keycode translation and only forward real events.
1436 */
1437 if (!(field->flags & (HID_MAIN_ITEM_RELATIVE |
1438 HID_MAIN_ITEM_BUFFERED_BYTE)) &&
1439 (field->flags & HID_MAIN_ITEM_VARIABLE) &&
1440 usage->usage_index < field->maxusage &&
1441 value == field->value[usage->usage_index])
1442 return;
1443
1444 /* report the usage code as scancode if the key status has changed */
1445 if (usage->type == EV_KEY &&
1446 (!test_bit(usage->code, input->key)) == value)
1447 input_event(input, EV_MSC, MSC_SCAN, usage->hid);
1448
1449 input_event(input, usage->type, usage->code, value);
1450
1451 if ((field->flags & HID_MAIN_ITEM_RELATIVE) &&
1452 usage->type == EV_KEY && value) {
1453 input_sync(input);
1454 input_event(input, usage->type, usage->code, 0);
1455 }
1456 }
1457
---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/[email protected]