cregit-Linux how code gets into the kernel

Release 4.7 drivers/hid/hid-gembird.c

Directory: drivers/hid
/*
 *  HID driver for Gembird Joypad, "PC Game Controller"
 *
 *  Copyright (c) 2015 Red Hat, Inc
 *  Copyright (c) 2015 Benjamin Tissoires
 */

/*
 * 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.
 */

#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; }

Contributors

PersonTokensPropCommitsCommitProp
benjamin tissoiresbenjamin tissoires156100.00%1100.00%
Total156100.00%1100.00%

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");

Overall Contributors

PersonTokensPropCommitsCommitProp
benjamin tissoiresbenjamin tissoires410100.00%1100.00%
Total410100.00%1100.00%
Directory: drivers/hid
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
{% endraw %}