^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0+
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * LED & force feedback support for BigBen Interactive
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * 0x146b:0x0902 "Bigben Interactive Bigben Game Pad"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * "Kid-friendly Wired Controller" PS3OFMINIPAD SONY
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * sold for use with the PS3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * Copyright (c) 2018 Hanno Zulla <kontakt@hanno.de>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/input.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/leds.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/hid.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include "hid-ids.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) * The original descriptor for 0x146b:0x0902
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) * 0x05, 0x01, // Usage Page (Generic Desktop Ctrls)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) * 0x09, 0x05, // Usage (Game Pad)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) * 0xA1, 0x01, // Collection (Application)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) * 0x15, 0x00, // Logical Minimum (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) * 0x25, 0x01, // Logical Maximum (1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) * 0x35, 0x00, // Physical Minimum (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) * 0x45, 0x01, // Physical Maximum (1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) * 0x75, 0x01, // Report Size (1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) * 0x95, 0x0D, // Report Count (13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) * 0x05, 0x09, // Usage Page (Button)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) * 0x19, 0x01, // Usage Minimum (0x01)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) * 0x29, 0x0D, // Usage Maximum (0x0D)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) * 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) * 0x95, 0x03, // Report Count (3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) * 0x81, 0x01, // Input (Const,Array,Abs,No Wrap,Linear,Preferred State,No Null Position)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) * 0x05, 0x01, // Usage Page (Generic Desktop Ctrls)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) * 0x25, 0x07, // Logical Maximum (7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) * 0x46, 0x3B, 0x01, // Physical Maximum (315)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) * 0x75, 0x04, // Report Size (4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) * 0x95, 0x01, // Report Count (1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) * 0x65, 0x14, // Unit (System: English Rotation, Length: Centimeter)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) * 0x09, 0x39, // Usage (Hat switch)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) * 0x81, 0x42, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,Null State)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) * 0x65, 0x00, // Unit (None)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) * 0x95, 0x01, // Report Count (1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) * 0x81, 0x01, // Input (Const,Array,Abs,No Wrap,Linear,Preferred State,No Null Position)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) * 0x26, 0xFF, 0x00, // Logical Maximum (255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) * 0x46, 0xFF, 0x00, // Physical Maximum (255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) * 0x09, 0x30, // Usage (X)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) * 0x09, 0x31, // Usage (Y)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) * 0x09, 0x32, // Usage (Z)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) * 0x09, 0x35, // Usage (Rz)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) * 0x75, 0x08, // Report Size (8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) * 0x95, 0x04, // Report Count (4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) * 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) * 0x06, 0x00, 0xFF, // Usage Page (Vendor Defined 0xFF00)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) * 0x09, 0x20, // Usage (0x20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) * 0x09, 0x21, // Usage (0x21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) * 0x09, 0x22, // Usage (0x22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) * 0x09, 0x23, // Usage (0x23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) * 0x09, 0x24, // Usage (0x24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) * 0x09, 0x25, // Usage (0x25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) * 0x09, 0x26, // Usage (0x26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) * 0x09, 0x27, // Usage (0x27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) * 0x09, 0x28, // Usage (0x28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) * 0x09, 0x29, // Usage (0x29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) * 0x09, 0x2A, // Usage (0x2A)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) * 0x09, 0x2B, // Usage (0x2B)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) * 0x95, 0x0C, // Report Count (12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) * 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) * 0x0A, 0x21, 0x26, // Usage (0x2621)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) * 0x95, 0x08, // Report Count (8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) * 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) * 0x0A, 0x21, 0x26, // Usage (0x2621)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) * 0x91, 0x02, // Output (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) * 0x26, 0xFF, 0x03, // Logical Maximum (1023)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) * 0x46, 0xFF, 0x03, // Physical Maximum (1023)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) * 0x09, 0x2C, // Usage (0x2C)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) * 0x09, 0x2D, // Usage (0x2D)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) * 0x09, 0x2E, // Usage (0x2E)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) * 0x09, 0x2F, // Usage (0x2F)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) * 0x75, 0x10, // Report Size (16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) * 0x95, 0x04, // Report Count (4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) * 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) * 0xC0, // End Collection
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) #define PID0902_RDESC_ORIG_SIZE 137
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) * The fixed descriptor for 0x146b:0x0902
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) * - map buttons according to gamepad.rst
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) * - assign right stick from Z/Rz to Rx/Ry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) * - map previously unused analog trigger data to Z/RZ
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) * - simplify feature and output descriptor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) static __u8 pid0902_rdesc_fixed[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 0x05, 0x01, /* Usage Page (Generic Desktop Ctrls) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 0x09, 0x05, /* Usage (Game Pad) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 0xA1, 0x01, /* Collection (Application) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 0x15, 0x00, /* Logical Minimum (0) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 0x25, 0x01, /* Logical Maximum (1) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 0x35, 0x00, /* Physical Minimum (0) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 0x45, 0x01, /* Physical Maximum (1) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 0x75, 0x01, /* Report Size (1) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 0x95, 0x0D, /* Report Count (13) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 0x05, 0x09, /* Usage Page (Button) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 0x09, 0x05, /* Usage (BTN_WEST) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 0x09, 0x01, /* Usage (BTN_SOUTH) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 0x09, 0x02, /* Usage (BTN_EAST) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 0x09, 0x04, /* Usage (BTN_NORTH) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 0x09, 0x07, /* Usage (BTN_TL) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 0x09, 0x08, /* Usage (BTN_TR) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 0x09, 0x09, /* Usage (BTN_TL2) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 0x09, 0x0A, /* Usage (BTN_TR2) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 0x09, 0x0B, /* Usage (BTN_SELECT) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 0x09, 0x0C, /* Usage (BTN_START) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 0x09, 0x0E, /* Usage (BTN_THUMBL) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 0x09, 0x0F, /* Usage (BTN_THUMBR) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 0x09, 0x0D, /* Usage (BTN_MODE) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 0x81, 0x02, /* Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 0x75, 0x01, /* Report Size (1) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 0x95, 0x03, /* Report Count (3) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 0x81, 0x01, /* Input (Const,Array,Abs,No Wrap,Linear,Preferred State,No Null Position) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 0x05, 0x01, /* Usage Page (Generic Desktop Ctrls) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 0x25, 0x07, /* Logical Maximum (7) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 0x46, 0x3B, 0x01, /* Physical Maximum (315) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 0x75, 0x04, /* Report Size (4) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 0x95, 0x01, /* Report Count (1) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 0x65, 0x14, /* Unit (System: English Rotation, Length: Centimeter) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 0x09, 0x39, /* Usage (Hat switch) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 0x81, 0x42, /* Input (Data,Var,Abs,No Wrap,Linear,Preferred State,Null State) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 0x65, 0x00, /* Unit (None) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 0x95, 0x01, /* Report Count (1) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 0x81, 0x01, /* Input (Const,Array,Abs,No Wrap,Linear,Preferred State,No Null Position) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 0x26, 0xFF, 0x00, /* Logical Maximum (255) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 0x46, 0xFF, 0x00, /* Physical Maximum (255) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 0x09, 0x30, /* Usage (X) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 0x09, 0x31, /* Usage (Y) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 0x09, 0x33, /* Usage (Rx) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 0x09, 0x34, /* Usage (Ry) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 0x75, 0x08, /* Report Size (8) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 0x95, 0x04, /* Report Count (4) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 0x81, 0x02, /* Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 0x95, 0x0A, /* Report Count (10) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 0x81, 0x01, /* Input (Const,Array,Abs,No Wrap,Linear,Preferred State,No Null Position) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 0x05, 0x01, /* Usage Page (Generic Desktop Ctrls) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 0x26, 0xFF, 0x00, /* Logical Maximum (255) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 0x46, 0xFF, 0x00, /* Physical Maximum (255) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 0x09, 0x32, /* Usage (Z) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 0x09, 0x35, /* Usage (Rz) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 0x95, 0x02, /* Report Count (2) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 0x81, 0x02, /* Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 0x95, 0x08, /* Report Count (8) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 0x81, 0x01, /* Input (Const,Array,Abs,No Wrap,Linear,Preferred State,No Null Position) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 0x06, 0x00, 0xFF, /* Usage Page (Vendor Defined 0xFF00) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 0xB1, 0x02, /* Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 0x0A, 0x21, 0x26, /* Usage (0x2621) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 0x95, 0x08, /* Report Count (8) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 0x91, 0x02, /* Output (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 0x0A, 0x21, 0x26, /* Usage (0x2621) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 0x95, 0x08, /* Report Count (8) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 0x81, 0x02, /* Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 0xC0, /* End Collection */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) #define NUM_LEDS 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) struct bigben_device {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) struct hid_device *hid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) struct hid_report *report;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) bool removed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) u8 led_state; /* LED1 = 1 .. LED4 = 8 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) u8 right_motor_on; /* right motor off/on 0/1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) u8 left_motor_force; /* left motor force 0-255 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) struct led_classdev *leds[NUM_LEDS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) bool work_led;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) bool work_ff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) struct work_struct worker;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) static void bigben_worker(struct work_struct *work)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) struct bigben_device *bigben = container_of(work,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) struct bigben_device, worker);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) struct hid_field *report_field = bigben->report->field[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) if (bigben->removed || !report_field)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) if (bigben->work_led) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) bigben->work_led = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) report_field->value[0] = 0x01; /* 1 = led message */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) report_field->value[1] = 0x08; /* reserved value, always 8 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) report_field->value[2] = bigben->led_state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) report_field->value[3] = 0x00; /* padding */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) report_field->value[4] = 0x00; /* padding */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) report_field->value[5] = 0x00; /* padding */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) report_field->value[6] = 0x00; /* padding */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) report_field->value[7] = 0x00; /* padding */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) hid_hw_request(bigben->hid, bigben->report, HID_REQ_SET_REPORT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) if (bigben->work_ff) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) bigben->work_ff = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) report_field->value[0] = 0x02; /* 2 = rumble effect message */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) report_field->value[1] = 0x08; /* reserved value, always 8 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) report_field->value[2] = bigben->right_motor_on;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) report_field->value[3] = bigben->left_motor_force;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) report_field->value[4] = 0xff; /* duration 0-254 (255 = nonstop) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) report_field->value[5] = 0x00; /* padding */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) report_field->value[6] = 0x00; /* padding */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) report_field->value[7] = 0x00; /* padding */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) hid_hw_request(bigben->hid, bigben->report, HID_REQ_SET_REPORT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) static int hid_bigben_play_effect(struct input_dev *dev, void *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) struct ff_effect *effect)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) struct hid_device *hid = input_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) struct bigben_device *bigben = hid_get_drvdata(hid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) u8 right_motor_on;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) u8 left_motor_force;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) if (!bigben) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) hid_err(hid, "no device data\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) if (effect->type != FF_RUMBLE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) right_motor_on = effect->u.rumble.weak_magnitude ? 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) left_motor_force = effect->u.rumble.strong_magnitude / 256;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) if (right_motor_on != bigben->right_motor_on ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) left_motor_force != bigben->left_motor_force) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) bigben->right_motor_on = right_motor_on;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) bigben->left_motor_force = left_motor_force;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) bigben->work_ff = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) schedule_work(&bigben->worker);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) static void bigben_set_led(struct led_classdev *led,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) enum led_brightness value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) struct device *dev = led->dev->parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) struct hid_device *hid = to_hid_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) struct bigben_device *bigben = hid_get_drvdata(hid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) int n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) bool work;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) if (!bigben) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) hid_err(hid, "no device data\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) for (n = 0; n < NUM_LEDS; n++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) if (led == bigben->leds[n]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) if (value == LED_OFF) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) work = (bigben->led_state & BIT(n));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) bigben->led_state &= ~BIT(n);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) work = !(bigben->led_state & BIT(n));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) bigben->led_state |= BIT(n);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) if (work) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) bigben->work_led = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) schedule_work(&bigben->worker);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) static enum led_brightness bigben_get_led(struct led_classdev *led)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) struct device *dev = led->dev->parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) struct hid_device *hid = to_hid_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) struct bigben_device *bigben = hid_get_drvdata(hid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) int n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) if (!bigben) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) hid_err(hid, "no device data\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) return LED_OFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) for (n = 0; n < NUM_LEDS; n++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) if (led == bigben->leds[n])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) return (bigben->led_state & BIT(n)) ? LED_ON : LED_OFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) return LED_OFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) static void bigben_remove(struct hid_device *hid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) struct bigben_device *bigben = hid_get_drvdata(hid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) bigben->removed = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) cancel_work_sync(&bigben->worker);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) hid_hw_stop(hid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) static int bigben_probe(struct hid_device *hid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) const struct hid_device_id *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) struct bigben_device *bigben;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) struct hid_input *hidinput;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) struct list_head *report_list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) struct led_classdev *led;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) char *name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) size_t name_sz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) int n, error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) bigben = devm_kzalloc(&hid->dev, sizeof(*bigben), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) if (!bigben)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) hid_set_drvdata(hid, bigben);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) bigben->hid = hid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) bigben->removed = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) error = hid_parse(hid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) if (error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) hid_err(hid, "parse failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) error = hid_hw_start(hid, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) if (error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) hid_err(hid, "hw start failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) bigben->report = list_entry(report_list->next,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) struct hid_report, list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) hidinput = list_first_entry(&hid->inputs, struct hid_input, list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) set_bit(FF_RUMBLE, hidinput->input->ffbit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) INIT_WORK(&bigben->worker, bigben_worker);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) error = input_ff_create_memless(hidinput->input, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) hid_bigben_play_effect);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) goto error_hw_stop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) name_sz = strlen(dev_name(&hid->dev)) + strlen(":red:bigben#") + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) for (n = 0; n < NUM_LEDS; n++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) led = devm_kzalloc(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) &hid->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) sizeof(struct led_classdev) + name_sz,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) GFP_KERNEL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) if (!led) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) error = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) goto error_hw_stop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) name = (void *)(&led[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) snprintf(name, name_sz,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) "%s:red:bigben%d",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) dev_name(&hid->dev), n + 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) led->name = name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) led->brightness = (n == 0) ? LED_ON : LED_OFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) led->max_brightness = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) led->brightness_get = bigben_get_led;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) led->brightness_set = bigben_set_led;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) bigben->leds[n] = led;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) error = devm_led_classdev_register(&hid->dev, led);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) goto error_hw_stop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) /* initial state: LED1 is on, no rumble effect */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) bigben->led_state = BIT(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) bigben->right_motor_on = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) bigben->left_motor_force = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) bigben->work_led = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) bigben->work_ff = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) schedule_work(&bigben->worker);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) hid_info(hid, "LED and force feedback support for BigBen gamepad\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) error_hw_stop:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) hid_hw_stop(hid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) static __u8 *bigben_report_fixup(struct hid_device *hid, __u8 *rdesc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) unsigned int *rsize)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) if (*rsize == PID0902_RDESC_ORIG_SIZE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) rdesc = pid0902_rdesc_fixed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) *rsize = sizeof(pid0902_rdesc_fixed);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) hid_warn(hid, "unexpected rdesc, please submit for review\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) return rdesc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) static const struct hid_device_id bigben_devices[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) { HID_USB_DEVICE(USB_VENDOR_ID_BIGBEN, USB_DEVICE_ID_BIGBEN_PS3OFMINIPAD) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) { }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) MODULE_DEVICE_TABLE(hid, bigben_devices);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) static struct hid_driver bigben_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) .name = "bigben",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) .id_table = bigben_devices,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) .probe = bigben_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) .report_fixup = bigben_report_fixup,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) .remove = bigben_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) module_hid_driver(bigben_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) MODULE_LICENSE("GPL");