^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * HID driver for Logitech receivers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (c) 2011 Logitech
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/hid.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/kfifo.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/usb.h> /* For to_usb_interface for kvm extra intf check */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <asm/unaligned.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include "hid-ids.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #define DJ_MAX_PAIRED_DEVICES 7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #define DJ_MAX_NUMBER_NOTIFS 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #define DJ_RECEIVER_INDEX 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #define DJ_DEVICE_INDEX_MIN 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #define DJ_DEVICE_INDEX_MAX 7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #define DJREPORT_SHORT_LENGTH 15
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #define DJREPORT_LONG_LENGTH 32
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #define REPORT_ID_DJ_SHORT 0x20
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #define REPORT_ID_DJ_LONG 0x21
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #define REPORT_ID_HIDPP_SHORT 0x10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define REPORT_ID_HIDPP_LONG 0x11
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #define REPORT_ID_HIDPP_VERY_LONG 0x12
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #define HIDPP_REPORT_SHORT_LENGTH 7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #define HIDPP_REPORT_LONG_LENGTH 20
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #define HIDPP_RECEIVER_INDEX 0xff
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #define REPORT_TYPE_RFREPORT_FIRST 0x01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #define REPORT_TYPE_RFREPORT_LAST 0x1F
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) /* Command Switch to DJ mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #define REPORT_TYPE_CMD_SWITCH 0x80
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #define CMD_SWITCH_PARAM_DEVBITFIELD 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #define CMD_SWITCH_PARAM_TIMEOUT_SECONDS 0x01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #define TIMEOUT_NO_KEEPALIVE 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) /* Command to Get the list of Paired devices */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #define REPORT_TYPE_CMD_GET_PAIRED_DEVICES 0x81
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) /* Device Paired Notification */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #define REPORT_TYPE_NOTIF_DEVICE_PAIRED 0x41
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) #define SPFUNCTION_MORE_NOTIF_EXPECTED 0x01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) #define SPFUNCTION_DEVICE_LIST_EMPTY 0x02
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) #define DEVICE_PAIRED_PARAM_SPFUNCTION 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) #define DEVICE_PAIRED_PARAM_EQUAD_ID_LSB 0x01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) #define DEVICE_PAIRED_PARAM_EQUAD_ID_MSB 0x02
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) #define DEVICE_PAIRED_RF_REPORT_TYPE 0x03
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) /* Device Un-Paired Notification */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) #define REPORT_TYPE_NOTIF_DEVICE_UNPAIRED 0x40
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) /* Connection Status Notification */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) #define REPORT_TYPE_NOTIF_CONNECTION_STATUS 0x42
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) #define CONNECTION_STATUS_PARAM_STATUS 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) #define STATUS_LINKLOSS 0x01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) /* Error Notification */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) #define REPORT_TYPE_NOTIF_ERROR 0x7F
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) #define NOTIF_ERROR_PARAM_ETYPE 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) #define ETYPE_KEEPALIVE_TIMEOUT 0x01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) /* supported DJ HID && RF report types */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) #define REPORT_TYPE_KEYBOARD 0x01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) #define REPORT_TYPE_MOUSE 0x02
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) #define REPORT_TYPE_CONSUMER_CONTROL 0x03
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) #define REPORT_TYPE_SYSTEM_CONTROL 0x04
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) #define REPORT_TYPE_MEDIA_CENTER 0x08
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) #define REPORT_TYPE_LEDS 0x0E
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) /* RF Report types bitfield */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) #define STD_KEYBOARD BIT(1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) #define STD_MOUSE BIT(2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) #define MULTIMEDIA BIT(3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) #define POWER_KEYS BIT(4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) #define MEDIA_CENTER BIT(8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) #define KBD_LEDS BIT(14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) /* Fake (bitnr > NUMBER_OF_HID_REPORTS) bit to track HID++ capability */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) #define HIDPP BIT_ULL(63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) /* HID++ Device Connected Notification */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) #define REPORT_TYPE_NOTIF_DEVICE_CONNECTED 0x41
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) #define HIDPP_PARAM_PROTO_TYPE 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) #define HIDPP_PARAM_DEVICE_INFO 0x01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) #define HIDPP_PARAM_EQUAD_LSB 0x02
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) #define HIDPP_PARAM_EQUAD_MSB 0x03
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) #define HIDPP_PARAM_27MHZ_DEVID 0x03
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) #define HIDPP_DEVICE_TYPE_MASK GENMASK(3, 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) #define HIDPP_LINK_STATUS_MASK BIT(6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) #define HIDPP_MANUFACTURER_MASK BIT(7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) #define HIDPP_DEVICE_TYPE_KEYBOARD 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) #define HIDPP_DEVICE_TYPE_MOUSE 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) #define HIDPP_SET_REGISTER 0x80
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) #define HIDPP_GET_LONG_REGISTER 0x83
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) #define HIDPP_REG_CONNECTION_STATE 0x02
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) #define HIDPP_REG_PAIRING_INFORMATION 0xB5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) #define HIDPP_PAIRING_INFORMATION 0x20
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) #define HIDPP_FAKE_DEVICE_ARRIVAL 0x02
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) enum recvr_type {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) recvr_type_dj,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) recvr_type_hidpp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) recvr_type_gaming_hidpp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) recvr_type_mouse_only,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) recvr_type_27mhz,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) recvr_type_bluetooth,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) struct dj_report {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) u8 report_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) u8 device_index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) u8 report_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) u8 report_params[DJREPORT_SHORT_LENGTH - 3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) struct hidpp_event {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) u8 report_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) u8 device_index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) u8 sub_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) u8 params[HIDPP_REPORT_LONG_LENGTH - 3U];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) } __packed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) struct dj_receiver_dev {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) struct hid_device *mouse;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) struct hid_device *keyboard;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) struct hid_device *hidpp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) struct dj_device *paired_dj_devices[DJ_MAX_PAIRED_DEVICES +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) DJ_DEVICE_INDEX_MIN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) struct list_head list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) struct kref kref;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) struct work_struct work;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) struct kfifo notif_fifo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) unsigned long last_query; /* in jiffies */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) bool ready;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) enum recvr_type type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) unsigned int unnumbered_application;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) spinlock_t lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) struct dj_device {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) struct hid_device *hdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) struct dj_receiver_dev *dj_receiver_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) u64 reports_supported;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) u8 device_index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) #define WORKITEM_TYPE_EMPTY 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) #define WORKITEM_TYPE_PAIRED 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) #define WORKITEM_TYPE_UNPAIRED 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) #define WORKITEM_TYPE_UNKNOWN 255
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) struct dj_workitem {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) u8 type; /* WORKITEM_TYPE_* */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) u8 device_index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) u8 device_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) u8 quad_id_msb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) u8 quad_id_lsb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) u64 reports_supported;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) /* Keyboard descriptor (1) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) static const char kbd_descriptor[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 0x05, 0x01, /* USAGE_PAGE (generic Desktop) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 0x09, 0x06, /* USAGE (Keyboard) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 0xA1, 0x01, /* COLLECTION (Application) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 0x85, 0x01, /* REPORT_ID (1) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 0x95, 0x08, /* REPORT_COUNT (8) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 0x75, 0x01, /* REPORT_SIZE (1) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 0x15, 0x00, /* LOGICAL_MINIMUM (0) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 0x05, 0x07, /* USAGE_PAGE (Keyboard) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 0x19, 0xE0, /* USAGE_MINIMUM (Left Control) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 0x29, 0xE7, /* USAGE_MAXIMUM (Right GUI) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 0x81, 0x02, /* INPUT (Data,Var,Abs) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 0x95, 0x06, /* REPORT_COUNT (6) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 0x75, 0x08, /* REPORT_SIZE (8) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 0x15, 0x00, /* LOGICAL_MINIMUM (0) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 0x26, 0xFF, 0x00, /* LOGICAL_MAXIMUM (255) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 0x05, 0x07, /* USAGE_PAGE (Keyboard) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 0x19, 0x00, /* USAGE_MINIMUM (no event) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 0x2A, 0xFF, 0x00, /* USAGE_MAXIMUM (reserved) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 0x81, 0x00, /* INPUT (Data,Ary,Abs) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 0x85, 0x0e, /* REPORT_ID (14) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 0x05, 0x08, /* USAGE PAGE (LED page) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 0x95, 0x05, /* REPORT COUNT (5) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 0x75, 0x01, /* REPORT SIZE (1) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 0x15, 0x00, /* LOGICAL_MINIMUM (0) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 0x19, 0x01, /* USAGE MINIMUM (1) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 0x29, 0x05, /* USAGE MAXIMUM (5) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 0x91, 0x02, /* OUTPUT (Data, Variable, Absolute) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) 0x95, 0x01, /* REPORT COUNT (1) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) 0x75, 0x03, /* REPORT SIZE (3) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 0x91, 0x01, /* OUTPUT (Constant) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) 0xC0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) /* Mouse descriptor (2) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) static const char mse_descriptor[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) 0x09, 0x02, /* USAGE (Mouse) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) 0xA1, 0x01, /* COLLECTION (Application) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) 0x85, 0x02, /* REPORT_ID = 2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) 0x09, 0x01, /* USAGE (pointer) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) 0xA1, 0x00, /* COLLECTION (physical) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) 0x05, 0x09, /* USAGE_PAGE (buttons) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) 0x19, 0x01, /* USAGE_MIN (1) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) 0x29, 0x10, /* USAGE_MAX (16) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) 0x15, 0x00, /* LOGICAL_MIN (0) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) 0x25, 0x01, /* LOGICAL_MAX (1) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) 0x95, 0x10, /* REPORT_COUNT (16) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) 0x75, 0x01, /* REPORT_SIZE (1) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) 0x81, 0x02, /* INPUT (data var abs) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) 0x05, 0x01, /* USAGE_PAGE (generic desktop) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) 0x16, 0x01, 0xF8, /* LOGICAL_MIN (-2047) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) 0x26, 0xFF, 0x07, /* LOGICAL_MAX (2047) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) 0x75, 0x0C, /* REPORT_SIZE (12) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) 0x95, 0x02, /* REPORT_COUNT (2) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) 0x09, 0x30, /* USAGE (X) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) 0x09, 0x31, /* USAGE (Y) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 0x81, 0x06, /* INPUT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) 0x15, 0x81, /* LOGICAL_MIN (-127) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) 0x25, 0x7F, /* LOGICAL_MAX (127) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) 0x75, 0x08, /* REPORT_SIZE (8) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) 0x95, 0x01, /* REPORT_COUNT (1) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) 0x09, 0x38, /* USAGE (wheel) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) 0x81, 0x06, /* INPUT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) 0x05, 0x0C, /* USAGE_PAGE(consumer) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) 0x0A, 0x38, 0x02, /* USAGE(AC Pan) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) 0x95, 0x01, /* REPORT_COUNT (1) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) 0x81, 0x06, /* INPUT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) 0xC0, /* END_COLLECTION */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) 0xC0, /* END_COLLECTION */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) /* Mouse descriptor (2) for 27 MHz receiver, only 8 buttons */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) static const char mse_27mhz_descriptor[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) 0x09, 0x02, /* USAGE (Mouse) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) 0xA1, 0x01, /* COLLECTION (Application) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) 0x85, 0x02, /* REPORT_ID = 2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) 0x09, 0x01, /* USAGE (pointer) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) 0xA1, 0x00, /* COLLECTION (physical) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) 0x05, 0x09, /* USAGE_PAGE (buttons) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) 0x19, 0x01, /* USAGE_MIN (1) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) 0x29, 0x08, /* USAGE_MAX (8) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) 0x15, 0x00, /* LOGICAL_MIN (0) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) 0x25, 0x01, /* LOGICAL_MAX (1) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) 0x95, 0x08, /* REPORT_COUNT (8) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) 0x75, 0x01, /* REPORT_SIZE (1) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) 0x81, 0x02, /* INPUT (data var abs) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) 0x05, 0x01, /* USAGE_PAGE (generic desktop) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) 0x16, 0x01, 0xF8, /* LOGICAL_MIN (-2047) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) 0x26, 0xFF, 0x07, /* LOGICAL_MAX (2047) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) 0x75, 0x0C, /* REPORT_SIZE (12) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) 0x95, 0x02, /* REPORT_COUNT (2) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) 0x09, 0x30, /* USAGE (X) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) 0x09, 0x31, /* USAGE (Y) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) 0x81, 0x06, /* INPUT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) 0x15, 0x81, /* LOGICAL_MIN (-127) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) 0x25, 0x7F, /* LOGICAL_MAX (127) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) 0x75, 0x08, /* REPORT_SIZE (8) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) 0x95, 0x01, /* REPORT_COUNT (1) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) 0x09, 0x38, /* USAGE (wheel) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) 0x81, 0x06, /* INPUT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) 0x05, 0x0C, /* USAGE_PAGE(consumer) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) 0x0A, 0x38, 0x02, /* USAGE(AC Pan) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) 0x95, 0x01, /* REPORT_COUNT (1) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) 0x81, 0x06, /* INPUT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) 0xC0, /* END_COLLECTION */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) 0xC0, /* END_COLLECTION */
^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) /* Mouse descriptor (2) for Bluetooth receiver, low-res hwheel, 12 buttons */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) static const char mse_bluetooth_descriptor[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) 0x09, 0x02, /* USAGE (Mouse) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) 0xA1, 0x01, /* COLLECTION (Application) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) 0x85, 0x02, /* REPORT_ID = 2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) 0x09, 0x01, /* USAGE (pointer) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) 0xA1, 0x00, /* COLLECTION (physical) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) 0x05, 0x09, /* USAGE_PAGE (buttons) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) 0x19, 0x01, /* USAGE_MIN (1) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) 0x29, 0x08, /* USAGE_MAX (8) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) 0x15, 0x00, /* LOGICAL_MIN (0) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) 0x25, 0x01, /* LOGICAL_MAX (1) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) 0x95, 0x08, /* REPORT_COUNT (8) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) 0x75, 0x01, /* REPORT_SIZE (1) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) 0x81, 0x02, /* INPUT (data var abs) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) 0x05, 0x01, /* USAGE_PAGE (generic desktop) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) 0x16, 0x01, 0xF8, /* LOGICAL_MIN (-2047) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) 0x26, 0xFF, 0x07, /* LOGICAL_MAX (2047) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) 0x75, 0x0C, /* REPORT_SIZE (12) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) 0x95, 0x02, /* REPORT_COUNT (2) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) 0x09, 0x30, /* USAGE (X) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) 0x09, 0x31, /* USAGE (Y) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) 0x81, 0x06, /* INPUT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) 0x15, 0x81, /* LOGICAL_MIN (-127) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) 0x25, 0x7F, /* LOGICAL_MAX (127) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) 0x75, 0x08, /* REPORT_SIZE (8) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) 0x95, 0x01, /* REPORT_COUNT (1) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) 0x09, 0x38, /* USAGE (wheel) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) 0x81, 0x06, /* INPUT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) 0x05, 0x0C, /* USAGE_PAGE(consumer) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) 0x0A, 0x38, 0x02, /* USAGE(AC Pan) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) 0x15, 0xF9, /* LOGICAL_MIN (-7) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) 0x25, 0x07, /* LOGICAL_MAX (7) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) 0x75, 0x04, /* REPORT_SIZE (4) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) 0x95, 0x01, /* REPORT_COUNT (1) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) 0x81, 0x06, /* INPUT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) 0x05, 0x09, /* USAGE_PAGE (buttons) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) 0x19, 0x09, /* USAGE_MIN (9) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) 0x29, 0x0C, /* USAGE_MAX (12) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) 0x15, 0x00, /* LOGICAL_MIN (0) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) 0x25, 0x01, /* LOGICAL_MAX (1) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) 0x75, 0x01, /* REPORT_SIZE (1) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) 0x95, 0x04, /* REPORT_COUNT (4) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) 0x81, 0x02, /* INPUT (Data,Var,Abs) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) 0xC0, /* END_COLLECTION */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) 0xC0, /* END_COLLECTION */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) /* Gaming Mouse descriptor (2) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) static const char mse_high_res_descriptor[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) 0x09, 0x02, /* USAGE (Mouse) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) 0xA1, 0x01, /* COLLECTION (Application) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) 0x85, 0x02, /* REPORT_ID = 2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) 0x09, 0x01, /* USAGE (pointer) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) 0xA1, 0x00, /* COLLECTION (physical) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) 0x05, 0x09, /* USAGE_PAGE (buttons) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) 0x19, 0x01, /* USAGE_MIN (1) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) 0x29, 0x10, /* USAGE_MAX (16) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) 0x15, 0x00, /* LOGICAL_MIN (0) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) 0x25, 0x01, /* LOGICAL_MAX (1) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) 0x95, 0x10, /* REPORT_COUNT (16) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) 0x75, 0x01, /* REPORT_SIZE (1) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) 0x81, 0x02, /* INPUT (data var abs) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) 0x05, 0x01, /* USAGE_PAGE (generic desktop) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) 0x16, 0x01, 0x80, /* LOGICAL_MIN (-32767) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) 0x26, 0xFF, 0x7F, /* LOGICAL_MAX (32767) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) 0x75, 0x10, /* REPORT_SIZE (16) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) 0x95, 0x02, /* REPORT_COUNT (2) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) 0x09, 0x30, /* USAGE (X) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) 0x09, 0x31, /* USAGE (Y) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) 0x81, 0x06, /* INPUT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) 0x15, 0x81, /* LOGICAL_MIN (-127) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) 0x25, 0x7F, /* LOGICAL_MAX (127) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) 0x75, 0x08, /* REPORT_SIZE (8) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) 0x95, 0x01, /* REPORT_COUNT (1) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) 0x09, 0x38, /* USAGE (wheel) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) 0x81, 0x06, /* INPUT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) 0x05, 0x0C, /* USAGE_PAGE(consumer) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) 0x0A, 0x38, 0x02, /* USAGE(AC Pan) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) 0x95, 0x01, /* REPORT_COUNT (1) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) 0x81, 0x06, /* INPUT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) 0xC0, /* END_COLLECTION */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) 0xC0, /* END_COLLECTION */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) /* Consumer Control descriptor (3) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) static const char consumer_descriptor[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) 0x05, 0x0C, /* USAGE_PAGE (Consumer Devices) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) 0x09, 0x01, /* USAGE (Consumer Control) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) 0xA1, 0x01, /* COLLECTION (Application) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) 0x85, 0x03, /* REPORT_ID = 3 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) 0x75, 0x10, /* REPORT_SIZE (16) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) 0x95, 0x02, /* REPORT_COUNT (2) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) 0x15, 0x01, /* LOGICAL_MIN (1) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) 0x26, 0xFF, 0x02, /* LOGICAL_MAX (767) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) 0x19, 0x01, /* USAGE_MIN (1) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) 0x2A, 0xFF, 0x02, /* USAGE_MAX (767) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) 0x81, 0x00, /* INPUT (Data Ary Abs) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) 0xC0, /* END_COLLECTION */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) }; /* */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) /* System control descriptor (4) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) static const char syscontrol_descriptor[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) 0x09, 0x80, /* USAGE (System Control) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) 0xA1, 0x01, /* COLLECTION (Application) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) 0x85, 0x04, /* REPORT_ID = 4 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) 0x75, 0x02, /* REPORT_SIZE (2) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) 0x95, 0x01, /* REPORT_COUNT (1) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) 0x15, 0x01, /* LOGICAL_MIN (1) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) 0x25, 0x03, /* LOGICAL_MAX (3) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) 0x09, 0x82, /* USAGE (System Sleep) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) 0x09, 0x81, /* USAGE (System Power Down) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) 0x09, 0x83, /* USAGE (System Wake Up) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) 0x81, 0x60, /* INPUT (Data Ary Abs NPrf Null) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) 0x75, 0x06, /* REPORT_SIZE (6) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) 0x81, 0x03, /* INPUT (Cnst Var Abs) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) 0xC0, /* END_COLLECTION */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) /* Media descriptor (8) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) static const char media_descriptor[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) 0x06, 0xbc, 0xff, /* Usage Page 0xffbc */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) 0x09, 0x88, /* Usage 0x0088 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) 0xa1, 0x01, /* BeginCollection */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) 0x85, 0x08, /* Report ID 8 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) 0x19, 0x01, /* Usage Min 0x0001 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) 0x29, 0xff, /* Usage Max 0x00ff */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) 0x15, 0x01, /* Logical Min 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) 0x26, 0xff, 0x00, /* Logical Max 255 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) 0x75, 0x08, /* Report Size 8 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) 0x95, 0x01, /* Report Count 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) 0x81, 0x00, /* Input */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) 0xc0, /* EndCollection */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) }; /* */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) /* HIDPP descriptor */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) static const char hidpp_descriptor[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) 0x06, 0x00, 0xff, /* Usage Page (Vendor Defined Page 1) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) 0x09, 0x01, /* Usage (Vendor Usage 1) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) 0xa1, 0x01, /* Collection (Application) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) 0x85, 0x10, /* Report ID (16) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) 0x75, 0x08, /* Report Size (8) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) 0x95, 0x06, /* Report Count (6) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) 0x15, 0x00, /* Logical Minimum (0) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) 0x26, 0xff, 0x00, /* Logical Maximum (255) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) 0x09, 0x01, /* Usage (Vendor Usage 1) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) 0x81, 0x00, /* Input (Data,Arr,Abs) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) 0x09, 0x01, /* Usage (Vendor Usage 1) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) 0x91, 0x00, /* Output (Data,Arr,Abs) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) 0xc0, /* End Collection */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) 0x06, 0x00, 0xff, /* Usage Page (Vendor Defined Page 1) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) 0x09, 0x02, /* Usage (Vendor Usage 2) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) 0xa1, 0x01, /* Collection (Application) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) 0x85, 0x11, /* Report ID (17) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) 0x75, 0x08, /* Report Size (8) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) 0x95, 0x13, /* Report Count (19) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) 0x15, 0x00, /* Logical Minimum (0) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) 0x26, 0xff, 0x00, /* Logical Maximum (255) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) 0x09, 0x02, /* Usage (Vendor Usage 2) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) 0x81, 0x00, /* Input (Data,Arr,Abs) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) 0x09, 0x02, /* Usage (Vendor Usage 2) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) 0x91, 0x00, /* Output (Data,Arr,Abs) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) 0xc0, /* End Collection */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) 0x06, 0x00, 0xff, /* Usage Page (Vendor Defined Page 1) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) 0x09, 0x04, /* Usage (Vendor Usage 0x04) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) 0xa1, 0x01, /* Collection (Application) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) 0x85, 0x20, /* Report ID (32) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) 0x75, 0x08, /* Report Size (8) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) 0x95, 0x0e, /* Report Count (14) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) 0x15, 0x00, /* Logical Minimum (0) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) 0x26, 0xff, 0x00, /* Logical Maximum (255) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) 0x09, 0x41, /* Usage (Vendor Usage 0x41) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) 0x81, 0x00, /* Input (Data,Arr,Abs) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) 0x09, 0x41, /* Usage (Vendor Usage 0x41) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) 0x91, 0x00, /* Output (Data,Arr,Abs) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) 0x85, 0x21, /* Report ID (33) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) 0x95, 0x1f, /* Report Count (31) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) 0x15, 0x00, /* Logical Minimum (0) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) 0x26, 0xff, 0x00, /* Logical Maximum (255) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) 0x09, 0x42, /* Usage (Vendor Usage 0x42) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) 0x81, 0x00, /* Input (Data,Arr,Abs) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) 0x09, 0x42, /* Usage (Vendor Usage 0x42) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) 0x91, 0x00, /* Output (Data,Arr,Abs) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) 0xc0, /* End Collection */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) /* Maximum size of all defined hid reports in bytes (including report id) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) #define MAX_REPORT_SIZE 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) /* Make sure all descriptors are present here */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) #define MAX_RDESC_SIZE \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) (sizeof(kbd_descriptor) + \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) sizeof(mse_bluetooth_descriptor) + \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) sizeof(consumer_descriptor) + \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) sizeof(syscontrol_descriptor) + \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) sizeof(media_descriptor) + \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) sizeof(hidpp_descriptor))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) /* Number of possible hid report types that can be created by this driver.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) * Right now, RF report types have the same report types (or report id's)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) * than the hid report created from those RF reports. In the future
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) * this doesnt have to be true.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) * For instance, RF report type 0x01 which has a size of 8 bytes, corresponds
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) * to hid report id 0x01, this is standard keyboard. Same thing applies to mice
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) * reports and consumer control, etc. If a new RF report is created, it doesn't
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) * has to have the same report id as its corresponding hid report, so an
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) * translation may have to take place for future report types.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) #define NUMBER_OF_HID_REPORTS 32
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) static const u8 hid_reportid_size_map[NUMBER_OF_HID_REPORTS] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) [1] = 8, /* Standard keyboard */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) [2] = 8, /* Standard mouse */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) [3] = 5, /* Consumer control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) [4] = 2, /* System control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) [8] = 2, /* Media Center */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) #define LOGITECH_DJ_INTERFACE_NUMBER 0x02
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) static struct hid_ll_driver logi_dj_ll_driver;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) static int logi_dj_recv_query_paired_devices(struct dj_receiver_dev *djrcv_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) static void delayedwork_callback(struct work_struct *work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) static LIST_HEAD(dj_hdev_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) static DEFINE_MUTEX(dj_hdev_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) * dj/HID++ receivers are really a single logical entity, but for BIOS/Windows
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) * compatibility they have multiple USB interfaces. On HID++ receivers we need
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) * to listen for input reports on both interfaces. The functions below are used
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) * to create a single struct dj_receiver_dev for all interfaces belonging to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) * a single USB-device / receiver.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) static struct dj_receiver_dev *dj_find_receiver_dev(struct hid_device *hdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) enum recvr_type type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) struct dj_receiver_dev *djrcv_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) char sep;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) * The bluetooth receiver contains a built-in hub and has separate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) * USB-devices for the keyboard and mouse interfaces.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) sep = (type == recvr_type_bluetooth) ? '.' : '/';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) /* Try to find an already-probed interface from the same device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) list_for_each_entry(djrcv_dev, &dj_hdev_list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) if (djrcv_dev->mouse &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) hid_compare_device_paths(hdev, djrcv_dev->mouse, sep)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) kref_get(&djrcv_dev->kref);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) return djrcv_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) if (djrcv_dev->keyboard &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) hid_compare_device_paths(hdev, djrcv_dev->keyboard, sep)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) kref_get(&djrcv_dev->kref);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) return djrcv_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) if (djrcv_dev->hidpp &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) hid_compare_device_paths(hdev, djrcv_dev->hidpp, sep)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) kref_get(&djrcv_dev->kref);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) return djrcv_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) static void dj_release_receiver_dev(struct kref *kref)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) struct dj_receiver_dev *djrcv_dev = container_of(kref, struct dj_receiver_dev, kref);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) list_del(&djrcv_dev->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) kfifo_free(&djrcv_dev->notif_fifo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) kfree(djrcv_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) static void dj_put_receiver_dev(struct hid_device *hdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) struct dj_receiver_dev *djrcv_dev = hid_get_drvdata(hdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) mutex_lock(&dj_hdev_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) if (djrcv_dev->mouse == hdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) djrcv_dev->mouse = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) if (djrcv_dev->keyboard == hdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) djrcv_dev->keyboard = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) if (djrcv_dev->hidpp == hdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) djrcv_dev->hidpp = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) kref_put(&djrcv_dev->kref, dj_release_receiver_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) mutex_unlock(&dj_hdev_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) static struct dj_receiver_dev *dj_get_receiver_dev(struct hid_device *hdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) enum recvr_type type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) unsigned int application,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) bool is_hidpp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) struct dj_receiver_dev *djrcv_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) mutex_lock(&dj_hdev_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) djrcv_dev = dj_find_receiver_dev(hdev, type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) if (!djrcv_dev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) djrcv_dev = kzalloc(sizeof(*djrcv_dev), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) if (!djrcv_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) INIT_WORK(&djrcv_dev->work, delayedwork_callback);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) spin_lock_init(&djrcv_dev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) if (kfifo_alloc(&djrcv_dev->notif_fifo,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) DJ_MAX_NUMBER_NOTIFS * sizeof(struct dj_workitem),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) GFP_KERNEL)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) kfree(djrcv_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) djrcv_dev = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) kref_init(&djrcv_dev->kref);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) list_add_tail(&djrcv_dev->list, &dj_hdev_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) djrcv_dev->last_query = jiffies;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) djrcv_dev->type = type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) if (application == HID_GD_KEYBOARD)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) djrcv_dev->keyboard = hdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) if (application == HID_GD_MOUSE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) djrcv_dev->mouse = hdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) if (is_hidpp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) djrcv_dev->hidpp = hdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) hid_set_drvdata(hdev, djrcv_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) mutex_unlock(&dj_hdev_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) return djrcv_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) static void logi_dj_recv_destroy_djhid_device(struct dj_receiver_dev *djrcv_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) struct dj_workitem *workitem)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) /* Called in delayed work context */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) struct dj_device *dj_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) spin_lock_irqsave(&djrcv_dev->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) dj_dev = djrcv_dev->paired_dj_devices[workitem->device_index];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) djrcv_dev->paired_dj_devices[workitem->device_index] = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) spin_unlock_irqrestore(&djrcv_dev->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) if (dj_dev != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) hid_destroy_device(dj_dev->hdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) kfree(dj_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) hid_err(djrcv_dev->hidpp, "%s: can't destroy a NULL device\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) static void logi_dj_recv_add_djhid_device(struct dj_receiver_dev *djrcv_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) struct dj_workitem *workitem)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) /* Called in delayed work context */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) struct hid_device *djrcv_hdev = djrcv_dev->hidpp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) struct hid_device *dj_hiddev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) struct dj_device *dj_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) u8 device_index = workitem->device_index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) /* Device index goes from 1 to 6, we need 3 bytes to store the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) * semicolon, the index, and a null terminator
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) unsigned char tmpstr[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) /* We are the only one ever adding a device, no need to lock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) if (djrcv_dev->paired_dj_devices[device_index]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) /* The device is already known. No need to reallocate it. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) dbg_hid("%s: device is already known\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) dj_hiddev = hid_allocate_device();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) if (IS_ERR(dj_hiddev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) hid_err(djrcv_hdev, "%s: hid_allocate_dev failed\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) dj_hiddev->ll_driver = &logi_dj_ll_driver;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) dj_hiddev->dev.parent = &djrcv_hdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) dj_hiddev->bus = BUS_USB;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) dj_hiddev->vendor = djrcv_hdev->vendor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) dj_hiddev->product = (workitem->quad_id_msb << 8) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) workitem->quad_id_lsb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) if (workitem->device_type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) const char *type_str = "Device";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) switch (workitem->device_type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) case 0x01: type_str = "Keyboard"; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) case 0x02: type_str = "Mouse"; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) case 0x03: type_str = "Numpad"; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) case 0x04: type_str = "Presenter"; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) case 0x07: type_str = "Remote Control"; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) case 0x08: type_str = "Trackball"; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) case 0x09: type_str = "Touchpad"; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) snprintf(dj_hiddev->name, sizeof(dj_hiddev->name),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) "Logitech Wireless %s PID:%04x",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) type_str, dj_hiddev->product);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) snprintf(dj_hiddev->name, sizeof(dj_hiddev->name),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) "Logitech Wireless Device PID:%04x",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) dj_hiddev->product);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) if (djrcv_dev->type == recvr_type_27mhz)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) dj_hiddev->group = HID_GROUP_LOGITECH_27MHZ_DEVICE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) dj_hiddev->group = HID_GROUP_LOGITECH_DJ_DEVICE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) memcpy(dj_hiddev->phys, djrcv_hdev->phys, sizeof(djrcv_hdev->phys));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) snprintf(tmpstr, sizeof(tmpstr), ":%d", device_index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) strlcat(dj_hiddev->phys, tmpstr, sizeof(dj_hiddev->phys));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) dj_dev = kzalloc(sizeof(struct dj_device), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) if (!dj_dev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) hid_err(djrcv_hdev, "%s: failed allocating dj_dev\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) goto dj_device_allocate_fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) dj_dev->reports_supported = workitem->reports_supported;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) dj_dev->hdev = dj_hiddev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) dj_dev->dj_receiver_dev = djrcv_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) dj_dev->device_index = device_index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) dj_hiddev->driver_data = dj_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) spin_lock_irqsave(&djrcv_dev->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) djrcv_dev->paired_dj_devices[device_index] = dj_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) spin_unlock_irqrestore(&djrcv_dev->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) if (hid_add_device(dj_hiddev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) hid_err(djrcv_hdev, "%s: failed adding dj_device\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) goto hid_add_device_fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) hid_add_device_fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) spin_lock_irqsave(&djrcv_dev->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) djrcv_dev->paired_dj_devices[device_index] = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) spin_unlock_irqrestore(&djrcv_dev->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) kfree(dj_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) dj_device_allocate_fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) hid_destroy_device(dj_hiddev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) static void delayedwork_callback(struct work_struct *work)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) struct dj_receiver_dev *djrcv_dev =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) container_of(work, struct dj_receiver_dev, work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) struct dj_workitem workitem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) int count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) int retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) dbg_hid("%s\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) spin_lock_irqsave(&djrcv_dev->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) * Since we attach to multiple interfaces, we may get scheduled before
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) * we are bound to the HID++ interface, catch this.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) if (!djrcv_dev->ready) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) pr_warn("%s: delayedwork queued before hidpp interface was enumerated\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) spin_unlock_irqrestore(&djrcv_dev->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) count = kfifo_out(&djrcv_dev->notif_fifo, &workitem, sizeof(workitem));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) if (count != sizeof(workitem)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) spin_unlock_irqrestore(&djrcv_dev->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) if (!kfifo_is_empty(&djrcv_dev->notif_fifo))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) schedule_work(&djrcv_dev->work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) spin_unlock_irqrestore(&djrcv_dev->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) switch (workitem.type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) case WORKITEM_TYPE_PAIRED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) logi_dj_recv_add_djhid_device(djrcv_dev, &workitem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) case WORKITEM_TYPE_UNPAIRED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) logi_dj_recv_destroy_djhid_device(djrcv_dev, &workitem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) case WORKITEM_TYPE_UNKNOWN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) retval = logi_dj_recv_query_paired_devices(djrcv_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) if (retval) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) hid_err(djrcv_dev->hidpp, "%s: logi_dj_recv_query_paired_devices error: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) __func__, retval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) case WORKITEM_TYPE_EMPTY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) dbg_hid("%s: device list is empty\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) * Sometimes we receive reports for which we do not have a paired dj_device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) * associated with the device_index or report-type to forward the report to.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) * This means that the original "device paired" notification corresponding
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) * to the dj_device never arrived to this driver. Possible reasons for this are:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) * 1) hid-core discards all packets coming from a device during probe().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) * 2) if the receiver is plugged into a KVM switch then the pairing reports
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) * are only forwarded to it if the focus is on this PC.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) * This function deals with this by re-asking the receiver for the list of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) * connected devices in the delayed work callback.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) * This function MUST be called with djrcv->lock held.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) static void logi_dj_recv_queue_unknown_work(struct dj_receiver_dev *djrcv_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) struct dj_workitem workitem = { .type = WORKITEM_TYPE_UNKNOWN };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) /* Rate limit queries done because of unhandled reports to 2/sec */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) if (time_before(jiffies, djrcv_dev->last_query + HZ / 2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) kfifo_in(&djrcv_dev->notif_fifo, &workitem, sizeof(workitem));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) schedule_work(&djrcv_dev->work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) static void logi_dj_recv_queue_notification(struct dj_receiver_dev *djrcv_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) struct dj_report *dj_report)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) /* We are called from atomic context (tasklet && djrcv->lock held) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) struct dj_workitem workitem = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) .device_index = dj_report->device_index,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) switch (dj_report->report_type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) case REPORT_TYPE_NOTIF_DEVICE_PAIRED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) workitem.type = WORKITEM_TYPE_PAIRED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) if (dj_report->report_params[DEVICE_PAIRED_PARAM_SPFUNCTION] &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) SPFUNCTION_DEVICE_LIST_EMPTY) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) workitem.type = WORKITEM_TYPE_EMPTY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) case REPORT_TYPE_NOTIF_DEVICE_UNPAIRED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) workitem.quad_id_msb =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) dj_report->report_params[DEVICE_PAIRED_PARAM_EQUAD_ID_MSB];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) workitem.quad_id_lsb =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) dj_report->report_params[DEVICE_PAIRED_PARAM_EQUAD_ID_LSB];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) workitem.reports_supported = get_unaligned_le32(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) dj_report->report_params +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) DEVICE_PAIRED_RF_REPORT_TYPE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) workitem.reports_supported |= HIDPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) if (dj_report->report_type == REPORT_TYPE_NOTIF_DEVICE_UNPAIRED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) workitem.type = WORKITEM_TYPE_UNPAIRED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) logi_dj_recv_queue_unknown_work(djrcv_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) kfifo_in(&djrcv_dev->notif_fifo, &workitem, sizeof(workitem));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) schedule_work(&djrcv_dev->work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) * Some quad/bluetooth keyboards have a builtin touchpad in this case we see
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) * only 1 paired device with a device_type of REPORT_TYPE_KEYBOARD. For the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) * touchpad to work we must also forward mouse input reports to the dj_hiddev
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) * created for the keyboard (instead of forwarding them to a second paired
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) * device with a device_type of REPORT_TYPE_MOUSE as we normally would).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) static const u16 kbd_builtin_touchpad_ids[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) 0xb309, /* Dinovo Edge */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) 0xb30c, /* Dinovo Mini */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) static void logi_hidpp_dev_conn_notif_equad(struct hid_device *hdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) struct hidpp_event *hidpp_report,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) struct dj_workitem *workitem)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) struct dj_receiver_dev *djrcv_dev = hid_get_drvdata(hdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) int i, id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) workitem->type = WORKITEM_TYPE_PAIRED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) workitem->device_type = hidpp_report->params[HIDPP_PARAM_DEVICE_INFO] &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) HIDPP_DEVICE_TYPE_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) workitem->quad_id_msb = hidpp_report->params[HIDPP_PARAM_EQUAD_MSB];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) workitem->quad_id_lsb = hidpp_report->params[HIDPP_PARAM_EQUAD_LSB];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) switch (workitem->device_type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) case REPORT_TYPE_KEYBOARD:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) workitem->reports_supported |= STD_KEYBOARD | MULTIMEDIA |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) POWER_KEYS | MEDIA_CENTER |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) HIDPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) id = (workitem->quad_id_msb << 8) | workitem->quad_id_lsb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) for (i = 0; i < ARRAY_SIZE(kbd_builtin_touchpad_ids); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) if (id == kbd_builtin_touchpad_ids[i]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) workitem->reports_supported |= STD_MOUSE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) case REPORT_TYPE_MOUSE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) workitem->reports_supported |= STD_MOUSE | HIDPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) if (djrcv_dev->type == recvr_type_mouse_only)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) workitem->reports_supported |= MULTIMEDIA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) static void logi_hidpp_dev_conn_notif_27mhz(struct hid_device *hdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) struct hidpp_event *hidpp_report,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) struct dj_workitem *workitem)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) workitem->type = WORKITEM_TYPE_PAIRED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) workitem->quad_id_lsb = hidpp_report->params[HIDPP_PARAM_27MHZ_DEVID];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) switch (hidpp_report->device_index) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) case 1: /* Index 1 is always a mouse */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) case 2: /* Index 2 is always a mouse */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) workitem->device_type = HIDPP_DEVICE_TYPE_MOUSE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) workitem->reports_supported |= STD_MOUSE | HIDPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) case 3: /* Index 3 is always the keyboard */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) case 4: /* Index 4 is used for an optional separate numpad */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) workitem->device_type = HIDPP_DEVICE_TYPE_KEYBOARD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) workitem->reports_supported |= STD_KEYBOARD | MULTIMEDIA |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) POWER_KEYS | HIDPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) hid_warn(hdev, "%s: unexpected device-index %d", __func__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) hidpp_report->device_index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) static void logi_hidpp_recv_queue_notif(struct hid_device *hdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) struct hidpp_event *hidpp_report)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) /* We are called from atomic context (tasklet && djrcv->lock held) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) struct dj_receiver_dev *djrcv_dev = hid_get_drvdata(hdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) const char *device_type = "UNKNOWN";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) struct dj_workitem workitem = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) .type = WORKITEM_TYPE_EMPTY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) .device_index = hidpp_report->device_index,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) switch (hidpp_report->params[HIDPP_PARAM_PROTO_TYPE]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) case 0x01:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) device_type = "Bluetooth";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) /* Bluetooth connect packet contents is the same as (e)QUAD */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) logi_hidpp_dev_conn_notif_equad(hdev, hidpp_report, &workitem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) if (!(hidpp_report->params[HIDPP_PARAM_DEVICE_INFO] &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) HIDPP_MANUFACTURER_MASK)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) hid_info(hdev, "Non Logitech device connected on slot %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) hidpp_report->device_index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) workitem.reports_supported &= ~HIDPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) case 0x02:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) device_type = "27 Mhz";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) logi_hidpp_dev_conn_notif_27mhz(hdev, hidpp_report, &workitem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) case 0x03:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) device_type = "QUAD or eQUAD";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) logi_hidpp_dev_conn_notif_equad(hdev, hidpp_report, &workitem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) case 0x04:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) device_type = "eQUAD step 4 DJ";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) logi_hidpp_dev_conn_notif_equad(hdev, hidpp_report, &workitem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) case 0x05:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) device_type = "DFU Lite";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) case 0x06:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) device_type = "eQUAD step 4 Lite";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) logi_hidpp_dev_conn_notif_equad(hdev, hidpp_report, &workitem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) case 0x07:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) device_type = "eQUAD step 4 Gaming";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) logi_hidpp_dev_conn_notif_equad(hdev, hidpp_report, &workitem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) workitem.reports_supported |= STD_KEYBOARD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) case 0x08:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) device_type = "eQUAD step 4 for gamepads";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) case 0x0a:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) device_type = "eQUAD nano Lite";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) logi_hidpp_dev_conn_notif_equad(hdev, hidpp_report, &workitem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) case 0x0c:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) device_type = "eQUAD Lightspeed 1";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) logi_hidpp_dev_conn_notif_equad(hdev, hidpp_report, &workitem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) workitem.reports_supported |= STD_KEYBOARD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) case 0x0d:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) device_type = "eQUAD Lightspeed 1.1";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) logi_hidpp_dev_conn_notif_equad(hdev, hidpp_report, &workitem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) workitem.reports_supported |= STD_KEYBOARD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) case 0x0f:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) case 0x11:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) device_type = "eQUAD Lightspeed 1.2";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) logi_hidpp_dev_conn_notif_equad(hdev, hidpp_report, &workitem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) workitem.reports_supported |= STD_KEYBOARD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) /* custom receiver device (eg. powerplay) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) if (hidpp_report->device_index == 7) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) workitem.reports_supported |= HIDPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) if (workitem.type == WORKITEM_TYPE_EMPTY) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) hid_warn(hdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) "unusable device of type %s (0x%02x) connected on slot %d",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) device_type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) hidpp_report->params[HIDPP_PARAM_PROTO_TYPE],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) hidpp_report->device_index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) hid_info(hdev, "device of type %s (0x%02x) connected on slot %d",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) device_type, hidpp_report->params[HIDPP_PARAM_PROTO_TYPE],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) hidpp_report->device_index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) kfifo_in(&djrcv_dev->notif_fifo, &workitem, sizeof(workitem));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) schedule_work(&djrcv_dev->work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) static void logi_dj_recv_forward_null_report(struct dj_receiver_dev *djrcv_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) struct dj_report *dj_report)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) /* We are called from atomic context (tasklet && djrcv->lock held) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) u8 reportbuffer[MAX_REPORT_SIZE];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) struct dj_device *djdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) djdev = djrcv_dev->paired_dj_devices[dj_report->device_index];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) memset(reportbuffer, 0, sizeof(reportbuffer));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) for (i = 0; i < NUMBER_OF_HID_REPORTS; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) if (djdev->reports_supported & (1 << i)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) reportbuffer[0] = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) if (hid_input_report(djdev->hdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) HID_INPUT_REPORT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) reportbuffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) hid_reportid_size_map[i], 1)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) dbg_hid("hid_input_report error sending null "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) "report\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) static void logi_dj_recv_forward_dj(struct dj_receiver_dev *djrcv_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) struct dj_report *dj_report)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) /* We are called from atomic context (tasklet && djrcv->lock held) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) struct dj_device *dj_device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) dj_device = djrcv_dev->paired_dj_devices[dj_report->device_index];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) if ((dj_report->report_type > ARRAY_SIZE(hid_reportid_size_map) - 1) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) (hid_reportid_size_map[dj_report->report_type] == 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) dbg_hid("invalid report type:%x\n", dj_report->report_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) if (hid_input_report(dj_device->hdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) HID_INPUT_REPORT, &dj_report->report_type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) hid_reportid_size_map[dj_report->report_type], 1)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) dbg_hid("hid_input_report error\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) static void logi_dj_recv_forward_report(struct dj_device *dj_dev, u8 *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) int size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) /* We are called from atomic context (tasklet && djrcv->lock held) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) if (hid_input_report(dj_dev->hdev, HID_INPUT_REPORT, data, size, 1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) dbg_hid("hid_input_report error\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) static void logi_dj_recv_forward_input_report(struct hid_device *hdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) u8 *data, int size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) struct dj_receiver_dev *djrcv_dev = hid_get_drvdata(hdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) struct dj_device *dj_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) u8 report = data[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) if (report > REPORT_TYPE_RFREPORT_LAST) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) hid_err(hdev, "Unexpected input report number %d\n", report);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) spin_lock_irqsave(&djrcv_dev->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) for (i = 0; i < (DJ_MAX_PAIRED_DEVICES + DJ_DEVICE_INDEX_MIN); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) dj_dev = djrcv_dev->paired_dj_devices[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) if (dj_dev && (dj_dev->reports_supported & BIT(report))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) logi_dj_recv_forward_report(dj_dev, data, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) spin_unlock_irqrestore(&djrcv_dev->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) logi_dj_recv_queue_unknown_work(djrcv_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) spin_unlock_irqrestore(&djrcv_dev->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) dbg_hid("No dj-devs handling input report number %d\n", report);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) static int logi_dj_recv_send_report(struct dj_receiver_dev *djrcv_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) struct dj_report *dj_report)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) struct hid_device *hdev = djrcv_dev->hidpp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) struct hid_report *report;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) struct hid_report_enum *output_report_enum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) u8 *data = (u8 *)(&dj_report->device_index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) output_report_enum = &hdev->report_enum[HID_OUTPUT_REPORT];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) report = output_report_enum->report_id_hash[REPORT_ID_DJ_SHORT];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) if (!report) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) hid_err(hdev, "%s: unable to find dj report\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) for (i = 0; i < DJREPORT_SHORT_LENGTH - 1; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) report->field[0]->value[i] = data[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) hid_hw_request(hdev, report, HID_REQ_SET_REPORT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) static int logi_dj_recv_query_hidpp_devices(struct dj_receiver_dev *djrcv_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) static const u8 template[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) REPORT_ID_HIDPP_SHORT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) HIDPP_RECEIVER_INDEX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) HIDPP_SET_REGISTER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) HIDPP_REG_CONNECTION_STATE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) HIDPP_FAKE_DEVICE_ARRIVAL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) 0x00, 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) u8 *hidpp_report;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) int retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) hidpp_report = kmemdup(template, sizeof(template), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) if (!hidpp_report)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) retval = hid_hw_raw_request(djrcv_dev->hidpp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) REPORT_ID_HIDPP_SHORT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) hidpp_report, sizeof(template),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) HID_OUTPUT_REPORT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) HID_REQ_SET_REPORT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) kfree(hidpp_report);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) return (retval < 0) ? retval : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) static int logi_dj_recv_query_paired_devices(struct dj_receiver_dev *djrcv_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) struct dj_report *dj_report;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) int retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) djrcv_dev->last_query = jiffies;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) if (djrcv_dev->type != recvr_type_dj)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) return logi_dj_recv_query_hidpp_devices(djrcv_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) dj_report = kzalloc(sizeof(struct dj_report), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) if (!dj_report)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) dj_report->report_id = REPORT_ID_DJ_SHORT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) dj_report->device_index = HIDPP_RECEIVER_INDEX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) dj_report->report_type = REPORT_TYPE_CMD_GET_PAIRED_DEVICES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) retval = logi_dj_recv_send_report(djrcv_dev, dj_report);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) kfree(dj_report);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) return retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) static int logi_dj_recv_switch_to_dj_mode(struct dj_receiver_dev *djrcv_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) unsigned timeout)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) struct hid_device *hdev = djrcv_dev->hidpp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) struct dj_report *dj_report;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) u8 *buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) int retval = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) dj_report = kzalloc(sizeof(struct dj_report), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) if (!dj_report)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) if (djrcv_dev->type == recvr_type_dj) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) dj_report->report_id = REPORT_ID_DJ_SHORT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) dj_report->device_index = HIDPP_RECEIVER_INDEX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) dj_report->report_type = REPORT_TYPE_CMD_SWITCH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) dj_report->report_params[CMD_SWITCH_PARAM_DEVBITFIELD] = 0x3F;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) dj_report->report_params[CMD_SWITCH_PARAM_TIMEOUT_SECONDS] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) (u8)timeout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) retval = logi_dj_recv_send_report(djrcv_dev, dj_report);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) * Ugly sleep to work around a USB 3.0 bug when the receiver is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) * still processing the "switch-to-dj" command while we send an
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) * other command.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) * 50 msec should gives enough time to the receiver to be ready.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) msleep(50);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) * Magical bits to set up hidpp notifications when the dj devices
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) * are connected/disconnected.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) * We can reuse dj_report because HIDPP_REPORT_SHORT_LENGTH is smaller
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) * than DJREPORT_SHORT_LENGTH.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) buf = (u8 *)dj_report;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) memset(buf, 0, HIDPP_REPORT_SHORT_LENGTH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) buf[0] = REPORT_ID_HIDPP_SHORT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) buf[1] = HIDPP_RECEIVER_INDEX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) buf[2] = 0x80;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) buf[3] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) buf[4] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) buf[5] = 0x09;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) buf[6] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) hid_hw_raw_request(hdev, REPORT_ID_HIDPP_SHORT, buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) HIDPP_REPORT_SHORT_LENGTH, HID_OUTPUT_REPORT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) HID_REQ_SET_REPORT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) kfree(dj_report);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) return retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) static int logi_dj_ll_open(struct hid_device *hid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) dbg_hid("%s: %s\n", __func__, hid->phys);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) static void logi_dj_ll_close(struct hid_device *hid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) dbg_hid("%s: %s\n", __func__, hid->phys);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) * Register 0xB5 is "pairing information". It is solely intended for the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) * receiver, so do not overwrite the device index.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) static u8 unifying_pairing_query[] = { REPORT_ID_HIDPP_SHORT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) HIDPP_RECEIVER_INDEX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) HIDPP_GET_LONG_REGISTER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) HIDPP_REG_PAIRING_INFORMATION };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) static u8 unifying_pairing_answer[] = { REPORT_ID_HIDPP_LONG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) HIDPP_RECEIVER_INDEX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) HIDPP_GET_LONG_REGISTER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) HIDPP_REG_PAIRING_INFORMATION };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) static int logi_dj_ll_raw_request(struct hid_device *hid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) unsigned char reportnum, __u8 *buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) size_t count, unsigned char report_type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) int reqtype)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) struct dj_device *djdev = hid->driver_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) struct dj_receiver_dev *djrcv_dev = djdev->dj_receiver_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) u8 *out_buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) if ((buf[0] == REPORT_ID_HIDPP_SHORT) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) (buf[0] == REPORT_ID_HIDPP_LONG) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) (buf[0] == REPORT_ID_HIDPP_VERY_LONG)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) if (count < 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) /* special case where we should not overwrite
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) * the device_index */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) if (count == 7 && !memcmp(buf, unifying_pairing_query,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) sizeof(unifying_pairing_query)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) buf[4] = (buf[4] & 0xf0) | (djdev->device_index - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) buf[1] = djdev->device_index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) return hid_hw_raw_request(djrcv_dev->hidpp, reportnum, buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) count, report_type, reqtype);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) if (buf[0] != REPORT_TYPE_LEDS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) if (djrcv_dev->type != recvr_type_dj && count >= 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) if (!djrcv_dev->keyboard) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) hid_warn(hid, "Received REPORT_TYPE_LEDS request before the keyboard interface was enumerated\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) /* usbhid overrides the report ID and ignores the first byte */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) return hid_hw_raw_request(djrcv_dev->keyboard, 0, buf, count,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) report_type, reqtype);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) out_buf = kzalloc(DJREPORT_SHORT_LENGTH, GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) if (!out_buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) if (count > DJREPORT_SHORT_LENGTH - 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) count = DJREPORT_SHORT_LENGTH - 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) out_buf[0] = REPORT_ID_DJ_SHORT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) out_buf[1] = djdev->device_index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) memcpy(out_buf + 2, buf, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) ret = hid_hw_raw_request(djrcv_dev->hidpp, out_buf[0], out_buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) DJREPORT_SHORT_LENGTH, report_type, reqtype);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) kfree(out_buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) static void rdcat(char *rdesc, unsigned int *rsize, const char *data, unsigned int size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) memcpy(rdesc + *rsize, data, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) *rsize += size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) static int logi_dj_ll_parse(struct hid_device *hid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) struct dj_device *djdev = hid->driver_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) unsigned int rsize = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) char *rdesc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) int retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) dbg_hid("%s\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) djdev->hdev->version = 0x0111;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) djdev->hdev->country = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) rdesc = kmalloc(MAX_RDESC_SIZE, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) if (!rdesc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) if (djdev->reports_supported & STD_KEYBOARD) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) dbg_hid("%s: sending a kbd descriptor, reports_supported: %llx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) __func__, djdev->reports_supported);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) rdcat(rdesc, &rsize, kbd_descriptor, sizeof(kbd_descriptor));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) if (djdev->reports_supported & STD_MOUSE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) dbg_hid("%s: sending a mouse descriptor, reports_supported: %llx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) __func__, djdev->reports_supported);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) if (djdev->dj_receiver_dev->type == recvr_type_gaming_hidpp ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) djdev->dj_receiver_dev->type == recvr_type_mouse_only)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) rdcat(rdesc, &rsize, mse_high_res_descriptor,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) sizeof(mse_high_res_descriptor));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) else if (djdev->dj_receiver_dev->type == recvr_type_27mhz)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) rdcat(rdesc, &rsize, mse_27mhz_descriptor,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) sizeof(mse_27mhz_descriptor));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) else if (djdev->dj_receiver_dev->type == recvr_type_bluetooth)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) rdcat(rdesc, &rsize, mse_bluetooth_descriptor,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) sizeof(mse_bluetooth_descriptor));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) rdcat(rdesc, &rsize, mse_descriptor,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) sizeof(mse_descriptor));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) if (djdev->reports_supported & MULTIMEDIA) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) dbg_hid("%s: sending a multimedia report descriptor: %llx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) __func__, djdev->reports_supported);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) rdcat(rdesc, &rsize, consumer_descriptor, sizeof(consumer_descriptor));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) if (djdev->reports_supported & POWER_KEYS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) dbg_hid("%s: sending a power keys report descriptor: %llx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) __func__, djdev->reports_supported);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) rdcat(rdesc, &rsize, syscontrol_descriptor, sizeof(syscontrol_descriptor));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) if (djdev->reports_supported & MEDIA_CENTER) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) dbg_hid("%s: sending a media center report descriptor: %llx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) __func__, djdev->reports_supported);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) rdcat(rdesc, &rsize, media_descriptor, sizeof(media_descriptor));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) if (djdev->reports_supported & KBD_LEDS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) dbg_hid("%s: need to send kbd leds report descriptor: %llx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) __func__, djdev->reports_supported);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) if (djdev->reports_supported & HIDPP) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) dbg_hid("%s: sending a HID++ descriptor, reports_supported: %llx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) __func__, djdev->reports_supported);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) rdcat(rdesc, &rsize, hidpp_descriptor,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) sizeof(hidpp_descriptor));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) retval = hid_parse_report(hid, rdesc, rsize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) kfree(rdesc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) return retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) static int logi_dj_ll_start(struct hid_device *hid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) dbg_hid("%s\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) static void logi_dj_ll_stop(struct hid_device *hid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) dbg_hid("%s\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) static struct hid_ll_driver logi_dj_ll_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) .parse = logi_dj_ll_parse,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) .start = logi_dj_ll_start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) .stop = logi_dj_ll_stop,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) .open = logi_dj_ll_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) .close = logi_dj_ll_close,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) .raw_request = logi_dj_ll_raw_request,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) static int logi_dj_dj_event(struct hid_device *hdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437) struct hid_report *report, u8 *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) int size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440) struct dj_receiver_dev *djrcv_dev = hid_get_drvdata(hdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441) struct dj_report *dj_report = (struct dj_report *) data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) * Here we receive all data coming from iface 2, there are 3 cases:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) * 1) Data is intended for this driver i. e. data contains arrival,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448) * departure, etc notifications, in which case we queue them for delayed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) * processing by the work queue. We return 1 to hid-core as no further
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450) * processing is required from it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452) * 2) Data informs a connection change, if the change means rf link
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) * loss, then we must send a null report to the upper layer to discard
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) * potentially pressed keys that may be repeated forever by the input
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) * layer. Return 1 to hid-core as no further processing is required.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) * 3) Data is an actual input event from a paired DJ device in which
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458) * case we forward it to the correct hid device (via hid_input_report()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459) * ) and return 1 so hid-core does not anything else with it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462) if ((dj_report->device_index < DJ_DEVICE_INDEX_MIN) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463) (dj_report->device_index > DJ_DEVICE_INDEX_MAX)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465) * Device index is wrong, bail out.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) * This driver can ignore safely the receiver notifications,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467) * so ignore those reports too.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469) if (dj_report->device_index != DJ_RECEIVER_INDEX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470) hid_err(hdev, "%s: invalid device index:%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471) __func__, dj_report->device_index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475) spin_lock_irqsave(&djrcv_dev->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477) if (!djrcv_dev->paired_dj_devices[dj_report->device_index]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478) /* received an event for an unknown device, bail out */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479) logi_dj_recv_queue_notification(djrcv_dev, dj_report);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483) switch (dj_report->report_type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484) case REPORT_TYPE_NOTIF_DEVICE_PAIRED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485) /* pairing notifications are handled above the switch */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487) case REPORT_TYPE_NOTIF_DEVICE_UNPAIRED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488) logi_dj_recv_queue_notification(djrcv_dev, dj_report);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490) case REPORT_TYPE_NOTIF_CONNECTION_STATUS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491) if (dj_report->report_params[CONNECTION_STATUS_PARAM_STATUS] ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492) STATUS_LINKLOSS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493) logi_dj_recv_forward_null_report(djrcv_dev, dj_report);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497) logi_dj_recv_forward_dj(djrcv_dev, dj_report);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501) spin_unlock_irqrestore(&djrcv_dev->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506) static int logi_dj_hidpp_event(struct hid_device *hdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507) struct hid_report *report, u8 *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508) int size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510) struct dj_receiver_dev *djrcv_dev = hid_get_drvdata(hdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511) struct hidpp_event *hidpp_report = (struct hidpp_event *) data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512) struct dj_device *dj_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514) u8 device_index = hidpp_report->device_index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516) if (device_index == HIDPP_RECEIVER_INDEX) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517) /* special case were the device wants to know its unifying
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518) * name */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519) if (size == HIDPP_REPORT_LONG_LENGTH &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520) !memcmp(data, unifying_pairing_answer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521) sizeof(unifying_pairing_answer)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522) device_index = (data[4] & 0x0F) + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1527) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1528) * Data is from the HID++ collection, in this case, we forward the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1529) * data to the corresponding child dj device and return 0 to hid-core
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1530) * so he data also goes to the hidraw device of the receiver. This
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1531) * allows a user space application to implement the full HID++ routing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1532) * via the receiver.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1533) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1534)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1535) if ((device_index < DJ_DEVICE_INDEX_MIN) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1536) (device_index > DJ_DEVICE_INDEX_MAX)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1537) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1538) * Device index is wrong, bail out.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1539) * This driver can ignore safely the receiver notifications,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1540) * so ignore those reports too.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1541) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1542) hid_err(hdev, "%s: invalid device index:%d\n", __func__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1543) hidpp_report->device_index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1544) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1545) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1546)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1547) spin_lock_irqsave(&djrcv_dev->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1548)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1549) dj_dev = djrcv_dev->paired_dj_devices[device_index];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1550)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1551) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1552) * With 27 MHz receivers, we do not get an explicit unpair event,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1553) * remove the old device if the user has paired a *different* device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1554) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1555) if (djrcv_dev->type == recvr_type_27mhz && dj_dev &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1556) hidpp_report->sub_id == REPORT_TYPE_NOTIF_DEVICE_CONNECTED &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1557) hidpp_report->params[HIDPP_PARAM_PROTO_TYPE] == 0x02 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1558) hidpp_report->params[HIDPP_PARAM_27MHZ_DEVID] !=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1559) dj_dev->hdev->product) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1560) struct dj_workitem workitem = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1561) .device_index = hidpp_report->device_index,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1562) .type = WORKITEM_TYPE_UNPAIRED,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1563) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1564) kfifo_in(&djrcv_dev->notif_fifo, &workitem, sizeof(workitem));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1565) /* logi_hidpp_recv_queue_notif will queue the work */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1566) dj_dev = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1567) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1568)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1569) if (dj_dev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1570) logi_dj_recv_forward_report(dj_dev, data, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1571) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1572) if (hidpp_report->sub_id == REPORT_TYPE_NOTIF_DEVICE_CONNECTED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1573) logi_hidpp_recv_queue_notif(hdev, hidpp_report);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1574) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1575) logi_dj_recv_queue_unknown_work(djrcv_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1576) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1577)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1578) spin_unlock_irqrestore(&djrcv_dev->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1579)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1580) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1581) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1582)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1583) static int logi_dj_raw_event(struct hid_device *hdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1584) struct hid_report *report, u8 *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1585) int size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1586) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1587) struct dj_receiver_dev *djrcv_dev = hid_get_drvdata(hdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1588) dbg_hid("%s, size:%d\n", __func__, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1589)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1590) if (!djrcv_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1591) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1592)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1593) if (!hdev->report_enum[HID_INPUT_REPORT].numbered) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1594)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1595) if (djrcv_dev->unnumbered_application == HID_GD_KEYBOARD) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1596) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1597) * For the keyboard, we can reuse the same report by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1598) * using the second byte which is constant in the USB
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1599) * HID report descriptor.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1600) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1601) data[1] = data[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1602) data[0] = REPORT_TYPE_KEYBOARD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1603)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1604) logi_dj_recv_forward_input_report(hdev, data, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1605)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1606) /* restore previous state */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1607) data[0] = data[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1608) data[1] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1609) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1610) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1611) * Mouse-only receivers send unnumbered mouse data. The 27 MHz
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1612) * receiver uses 6 byte packets, the nano receiver 8 bytes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1613) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1614) if (djrcv_dev->unnumbered_application == HID_GD_MOUSE &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1615) size <= 8) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1616) u8 mouse_report[9];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1617)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1618) /* Prepend report id */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1619) mouse_report[0] = REPORT_TYPE_MOUSE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1620) memcpy(mouse_report + 1, data, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1621) logi_dj_recv_forward_input_report(hdev, mouse_report,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1622) size + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1623) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1624)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1625) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1626) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1627)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1628) switch (data[0]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1629) case REPORT_ID_DJ_SHORT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1630) if (size != DJREPORT_SHORT_LENGTH) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1631) hid_err(hdev, "Short DJ report bad size (%d)", size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1632) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1633) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1634) return logi_dj_dj_event(hdev, report, data, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1635) case REPORT_ID_DJ_LONG:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1636) if (size != DJREPORT_LONG_LENGTH) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1637) hid_err(hdev, "Long DJ report bad size (%d)", size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1638) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1639) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1640) return logi_dj_dj_event(hdev, report, data, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1641) case REPORT_ID_HIDPP_SHORT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1642) if (size != HIDPP_REPORT_SHORT_LENGTH) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1643) hid_err(hdev, "Short HID++ report bad size (%d)", size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1644) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1645) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1646) return logi_dj_hidpp_event(hdev, report, data, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1647) case REPORT_ID_HIDPP_LONG:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1648) if (size != HIDPP_REPORT_LONG_LENGTH) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1649) hid_err(hdev, "Long HID++ report bad size (%d)", size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1650) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1651) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1652) return logi_dj_hidpp_event(hdev, report, data, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1653) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1654)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1655) logi_dj_recv_forward_input_report(hdev, data, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1656)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1657) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1658) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1659)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1660) static int logi_dj_probe(struct hid_device *hdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1661) const struct hid_device_id *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1662) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1663) struct hid_report_enum *rep_enum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1664) struct hid_report *rep;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1665) struct dj_receiver_dev *djrcv_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1666) struct usb_interface *intf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1667) unsigned int no_dj_interfaces = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1668) bool has_hidpp = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1669) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1670) int retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1671)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1672) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1673) * Call to usbhid to fetch the HID descriptors of the current
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1674) * interface subsequently call to the hid/hid-core to parse the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1675) * fetched descriptors.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1676) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1677) retval = hid_parse(hdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1678) if (retval) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1679) hid_err(hdev, "%s: parse failed\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1680) return retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1681) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1682)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1683) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1684) * Some KVMs add an extra interface for e.g. mouse emulation. If we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1685) * treat these as logitech-dj interfaces then this causes input events
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1686) * reported through this extra interface to not be reported correctly.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1687) * To avoid this, we treat these as generic-hid devices.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1688) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1689) switch (id->driver_data) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1690) case recvr_type_dj: no_dj_interfaces = 3; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1691) case recvr_type_hidpp: no_dj_interfaces = 2; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1692) case recvr_type_gaming_hidpp: no_dj_interfaces = 3; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1693) case recvr_type_mouse_only: no_dj_interfaces = 2; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1694) case recvr_type_27mhz: no_dj_interfaces = 2; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1695) case recvr_type_bluetooth: no_dj_interfaces = 2; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1696) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1697) if (hid_is_usb(hdev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1698) intf = to_usb_interface(hdev->dev.parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1699) if (intf && intf->altsetting->desc.bInterfaceNumber >=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1700) no_dj_interfaces) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1701) hdev->quirks |= HID_QUIRK_INPUT_PER_APP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1702) return hid_hw_start(hdev, HID_CONNECT_DEFAULT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1703) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1704) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1705)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1706) rep_enum = &hdev->report_enum[HID_INPUT_REPORT];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1707)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1708) /* no input reports, bail out */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1709) if (list_empty(&rep_enum->report_list))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1710) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1711)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1712) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1713) * Check for the HID++ application.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1714) * Note: we should theoretically check for HID++ and DJ
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1715) * collections, but this will do.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1716) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1717) list_for_each_entry(rep, &rep_enum->report_list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1718) if (rep->application == 0xff000001)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1719) has_hidpp = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1720) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1721)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1722) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1723) * Ignore interfaces without DJ/HID++ collection, they will not carry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1724) * any data, dont create any hid_device for them.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1725) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1726) if (!has_hidpp && id->driver_data == recvr_type_dj)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1727) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1728)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1729) /* get the current application attached to the node */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1730) rep = list_first_entry(&rep_enum->report_list, struct hid_report, list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1731) djrcv_dev = dj_get_receiver_dev(hdev, id->driver_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1732) rep->application, has_hidpp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1733) if (!djrcv_dev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1734) hid_err(hdev, "%s: dj_get_receiver_dev failed\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1735) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1736) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1737)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1738) if (!rep_enum->numbered)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1739) djrcv_dev->unnumbered_application = rep->application;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1740)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1741) /* Starts the usb device and connects to upper interfaces hiddev and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1742) * hidraw */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1743) retval = hid_hw_start(hdev, HID_CONNECT_HIDRAW|HID_CONNECT_HIDDEV);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1744) if (retval) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1745) hid_err(hdev, "%s: hid_hw_start returned error\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1746) goto hid_hw_start_fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1747) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1748)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1749) if (has_hidpp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1750) retval = logi_dj_recv_switch_to_dj_mode(djrcv_dev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1751) if (retval < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1752) hid_err(hdev, "%s: logi_dj_recv_switch_to_dj_mode returned error:%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1753) __func__, retval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1754) goto switch_to_dj_mode_fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1755) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1756) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1757)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1758) /* This is enabling the polling urb on the IN endpoint */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1759) retval = hid_hw_open(hdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1760) if (retval < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1761) hid_err(hdev, "%s: hid_hw_open returned error:%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1762) __func__, retval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1763) goto llopen_failed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1764) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1765)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1766) /* Allow incoming packets to arrive: */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1767) hid_device_io_start(hdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1768)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1769) if (has_hidpp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1770) spin_lock_irqsave(&djrcv_dev->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1771) djrcv_dev->ready = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1772) spin_unlock_irqrestore(&djrcv_dev->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1773) retval = logi_dj_recv_query_paired_devices(djrcv_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1774) if (retval < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1775) hid_err(hdev, "%s: logi_dj_recv_query_paired_devices error:%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1776) __func__, retval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1777) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1778) * This can happen with a KVM, let the probe succeed,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1779) * logi_dj_recv_queue_unknown_work will retry later.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1780) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1781) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1782) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1783)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1784) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1785)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1786) llopen_failed:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1787) switch_to_dj_mode_fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1788) hid_hw_stop(hdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1789)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1790) hid_hw_start_fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1791) dj_put_receiver_dev(hdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1792) return retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1793) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1794)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1795) #ifdef CONFIG_PM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1796) static int logi_dj_reset_resume(struct hid_device *hdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1797) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1798) int retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1799) struct dj_receiver_dev *djrcv_dev = hid_get_drvdata(hdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1800)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1801) if (!djrcv_dev || djrcv_dev->hidpp != hdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1802) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1803)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1804) retval = logi_dj_recv_switch_to_dj_mode(djrcv_dev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1805) if (retval < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1806) hid_err(hdev, "%s: logi_dj_recv_switch_to_dj_mode returned error:%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1807) __func__, retval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1808) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1809)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1810) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1811) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1812) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1813)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1814) static void logi_dj_remove(struct hid_device *hdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1815) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1816) struct dj_receiver_dev *djrcv_dev = hid_get_drvdata(hdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1817) struct dj_device *dj_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1818) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1819) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1820)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1821) dbg_hid("%s\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1822)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1823) if (!djrcv_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1824) return hid_hw_stop(hdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1825)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1826) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1827) * This ensures that if the work gets requeued from another
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1828) * interface of the same receiver it will be a no-op.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1829) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1830) spin_lock_irqsave(&djrcv_dev->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1831) djrcv_dev->ready = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1832) spin_unlock_irqrestore(&djrcv_dev->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1833)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1834) cancel_work_sync(&djrcv_dev->work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1835)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1836) hid_hw_close(hdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1837) hid_hw_stop(hdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1838)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1839) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1840) * For proper operation we need access to all interfaces, so we destroy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1841) * the paired devices when we're unbound from any interface.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1842) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1843) * Note we may still be bound to other interfaces, sharing the same
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1844) * djrcv_dev, so we need locking here.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1845) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1846) for (i = 0; i < (DJ_MAX_PAIRED_DEVICES + DJ_DEVICE_INDEX_MIN); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1847) spin_lock_irqsave(&djrcv_dev->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1848) dj_dev = djrcv_dev->paired_dj_devices[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1849) djrcv_dev->paired_dj_devices[i] = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1850) spin_unlock_irqrestore(&djrcv_dev->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1851) if (dj_dev != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1852) hid_destroy_device(dj_dev->hdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1853) kfree(dj_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1854) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1855) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1856)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1857) dj_put_receiver_dev(hdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1858) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1859)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1860) static const struct hid_device_id logi_dj_receivers[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1861) {HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1862) USB_DEVICE_ID_LOGITECH_UNIFYING_RECEIVER),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1863) .driver_data = recvr_type_dj},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1864) {HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1865) USB_DEVICE_ID_LOGITECH_UNIFYING_RECEIVER_2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1866) .driver_data = recvr_type_dj},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1867) { /* Logitech Nano mouse only receiver */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1868) HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1869) USB_DEVICE_ID_LOGITECH_NANO_RECEIVER),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1870) .driver_data = recvr_type_mouse_only},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1871) { /* Logitech Nano (non DJ) receiver */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1872) HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1873) USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1874) .driver_data = recvr_type_hidpp},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1875) { /* Logitech G700(s) receiver (0xc531) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1876) HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1877) 0xc531),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1878) .driver_data = recvr_type_gaming_hidpp},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1879) { /* Logitech G602 receiver (0xc537) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1880) HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1881) 0xc537),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1882) .driver_data = recvr_type_gaming_hidpp},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1883) { /* Logitech lightspeed receiver (0xc539) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1884) HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1885) USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_LIGHTSPEED_1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1886) .driver_data = recvr_type_gaming_hidpp},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1887) { /* Logitech lightspeed receiver (0xc53f) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1888) HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1889) USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_LIGHTSPEED_1_1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1890) .driver_data = recvr_type_gaming_hidpp},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1891) { /* Logitech 27 MHz HID++ 1.0 receiver (0xc513) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1892) HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1893) .driver_data = recvr_type_27mhz},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1894) { /* Logitech powerplay receiver (0xc53a) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1895) HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1896) USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_POWERPLAY),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1897) .driver_data = recvr_type_gaming_hidpp},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1898) { /* Logitech 27 MHz HID++ 1.0 receiver (0xc517) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1899) HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1900) USB_DEVICE_ID_S510_RECEIVER_2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1901) .driver_data = recvr_type_27mhz},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1902) { /* Logitech 27 MHz HID++ 1.0 mouse-only receiver (0xc51b) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1903) HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1904) USB_DEVICE_ID_LOGITECH_27MHZ_MOUSE_RECEIVER),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1905) .driver_data = recvr_type_27mhz},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1906) { /* Logitech MX5000 HID++ / bluetooth receiver keyboard intf. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1907) HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1908) 0xc70e),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1909) .driver_data = recvr_type_bluetooth},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1910) { /* Logitech MX5000 HID++ / bluetooth receiver mouse intf. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1911) HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1912) 0xc70a),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1913) .driver_data = recvr_type_bluetooth},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1914) { /* Logitech MX5500 HID++ / bluetooth receiver keyboard intf. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1915) HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1916) 0xc71b),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1917) .driver_data = recvr_type_bluetooth},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1918) { /* Logitech MX5500 HID++ / bluetooth receiver mouse intf. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1919) HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1920) 0xc71c),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1921) .driver_data = recvr_type_bluetooth},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1922) {}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1923) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1924)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1925) MODULE_DEVICE_TABLE(hid, logi_dj_receivers);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1926)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1927) static struct hid_driver logi_djreceiver_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1928) .name = "logitech-djreceiver",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1929) .id_table = logi_dj_receivers,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1930) .probe = logi_dj_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1931) .remove = logi_dj_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1932) .raw_event = logi_dj_raw_event,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1933) #ifdef CONFIG_PM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1934) .reset_resume = logi_dj_reset_resume,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1935) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1936) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1937)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1938) module_hid_driver(logi_djreceiver_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1939)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1940) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1941) MODULE_AUTHOR("Logitech");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1942) MODULE_AUTHOR("Nestor Lopez Casado");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1943) MODULE_AUTHOR("nlopezcasad@logitech.com");