mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-27 19:29:37 +00:00
![Thomas Gleixner](/assets/img/avatar_default.png)
Based on 1 normalized pattern(s): this program is free software you can redistribute it and or modify it under the terms of the gnu general public license as published by the free software foundation either version 2 of the license or at your option any later version extracted by the scancode license scanner the SPDX license identifier GPL-2.0-or-later has been chosen to replace the boilerplate/reference in 3029 file(s). Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Reviewed-by: Allison Randal <allison@lohutok.net> Cc: linux-spdx@vger.kernel.org Link: https://lkml.kernel.org/r/20190527070032.746973796@linutronix.de Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
113 lines
3.2 KiB
C
113 lines
3.2 KiB
C
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
/*
|
|
* HID driver for Gembird Joypad, "PC Game Controller"
|
|
*
|
|
* Copyright (c) 2015 Red Hat, Inc
|
|
* Copyright (c) 2015 Benjamin Tissoires
|
|
*/
|
|
|
|
/*
|
|
*/
|
|
|
|
#include <linux/device.h>
|
|
#include <linux/hid.h>
|
|
#include <linux/module.h>
|
|
|
|
#include "hid-ids.h"
|
|
|
|
#define GEMBIRD_START_FAULTY_RDESC 8
|
|
|
|
static const __u8 gembird_jpd_faulty_rdesc[] = {
|
|
0x75, 0x08, /* Report Size (8) */
|
|
0x95, 0x05, /* Report Count (5) */
|
|
0x15, 0x00, /* Logical Minimum (0) */
|
|
0x26, 0xff, 0x00, /* Logical Maximum (255) */
|
|
0x35, 0x00, /* Physical Minimum (0) */
|
|
0x46, 0xff, 0x00, /* Physical Maximum (255) */
|
|
0x09, 0x30, /* Usage (X) */
|
|
0x09, 0x31, /* Usage (Y) */
|
|
0x09, 0x32, /* Usage (Z) */
|
|
0x09, 0x32, /* Usage (Z) */
|
|
0x09, 0x35, /* Usage (Rz) */
|
|
0x81, 0x02, /* Input (Data,Var,Abs) */
|
|
};
|
|
|
|
/*
|
|
* we fix the report descriptor by:
|
|
* - marking the first Z axis as constant (so it is ignored by HID)
|
|
* - assign the original second Z to Rx
|
|
* - assign the original Rz to Ry
|
|
*/
|
|
static const __u8 gembird_jpd_fixed_rdesc[] = {
|
|
0x75, 0x08, /* Report Size (8) */
|
|
0x95, 0x02, /* Report Count (2) */
|
|
0x15, 0x00, /* Logical Minimum (0) */
|
|
0x26, 0xff, 0x00, /* Logical Maximum (255) */
|
|
0x35, 0x00, /* Physical Minimum (0) */
|
|
0x46, 0xff, 0x00, /* Physical Maximum (255) */
|
|
0x09, 0x30, /* Usage (X) */
|
|
0x09, 0x31, /* Usage (Y) */
|
|
0x81, 0x02, /* Input (Data,Var,Abs) */
|
|
0x95, 0x01, /* Report Count (1) */
|
|
0x09, 0x32, /* Usage (Z) */
|
|
0x81, 0x01, /* Input (Cnst,Arr,Abs) */
|
|
0x95, 0x02, /* Report Count (2) */
|
|
0x09, 0x33, /* Usage (Rx) */
|
|
0x09, 0x34, /* Usage (Ry) */
|
|
0x81, 0x02, /* Input (Data,Var,Abs) */
|
|
};
|
|
|
|
static __u8 *gembird_report_fixup(struct hid_device *hdev, __u8 *rdesc,
|
|
unsigned int *rsize)
|
|
{
|
|
__u8 *new_rdesc;
|
|
/* delta_size is > 0 */
|
|
size_t delta_size = sizeof(gembird_jpd_fixed_rdesc) -
|
|
sizeof(gembird_jpd_faulty_rdesc);
|
|
size_t new_size = *rsize + delta_size;
|
|
|
|
if (*rsize >= 31 && !memcmp(&rdesc[GEMBIRD_START_FAULTY_RDESC],
|
|
gembird_jpd_faulty_rdesc,
|
|
sizeof(gembird_jpd_faulty_rdesc))) {
|
|
new_rdesc = devm_kzalloc(&hdev->dev, new_size, GFP_KERNEL);
|
|
if (new_rdesc == NULL)
|
|
return rdesc;
|
|
|
|
dev_info(&hdev->dev,
|
|
"fixing Gembird JPD-DualForce 2 report descriptor.\n");
|
|
|
|
/* start by copying the end of the rdesc */
|
|
memcpy(new_rdesc + delta_size, rdesc, *rsize);
|
|
|
|
/* add the correct beginning */
|
|
memcpy(new_rdesc, rdesc, GEMBIRD_START_FAULTY_RDESC);
|
|
|
|
/* replace the faulty part with the fixed one */
|
|
memcpy(new_rdesc + GEMBIRD_START_FAULTY_RDESC,
|
|
gembird_jpd_fixed_rdesc,
|
|
sizeof(gembird_jpd_fixed_rdesc));
|
|
|
|
*rsize = new_size;
|
|
rdesc = new_rdesc;
|
|
}
|
|
|
|
return rdesc;
|
|
}
|
|
|
|
static const struct hid_device_id gembird_devices[] = {
|
|
{ HID_USB_DEVICE(USB_VENDOR_ID_GEMBIRD,
|
|
USB_DEVICE_ID_GEMBIRD_JPD_DUALFORCE2) },
|
|
{ }
|
|
};
|
|
MODULE_DEVICE_TABLE(hid, gembird_devices);
|
|
|
|
static struct hid_driver gembird_driver = {
|
|
.name = "gembird",
|
|
.id_table = gembird_devices,
|
|
.report_fixup = gembird_report_fixup,
|
|
};
|
|
module_hid_driver(gembird_driver);
|
|
|
|
MODULE_AUTHOR("Benjamin Tissoires <benjamin.tissoires@gmail.com>");
|
|
MODULE_DESCRIPTION("HID Gembird joypad driver");
|
|
MODULE_LICENSE("GPL");
|