HID: logitech-dj: add support for 27 MHz receivers
Most Logitech wireless keyboard and mice using the 27 MHz are hidpp10 devices, add support to logitech-dj for their receivers. Doing so leads to 2 improvements: 1) All these devices share the same USB product-id for their receiver, making it impossible to properly map some special keys / buttons which differ from device to device. Adding support to logitech-dj to see these as hidpp10 devices allows us to get the actual device-id from the keyboard / mouse. 2) It enables battery-monitoring of these devices This patch uses a new HID group for 27Mhz devices, since the logitech-hidpp code needs to be able to differentiate them from other devices instantiated by the logitech-dj code. Signed-off-by: Hans de Goede <hdegoede@redhat.com> Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
This commit is contained in:
Родитель
f5fb57a74e
Коммит
c9121cf637
|
@ -876,8 +876,6 @@ static const struct hid_device_id lg_devices[] = {
|
|||
.driver_data = LG_RDESC | LG_WIRELESS },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER),
|
||||
.driver_data = LG_RDESC | LG_WIRELESS },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER_2),
|
||||
.driver_data = LG_RDESC | LG_WIRELESS },
|
||||
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RECEIVER),
|
||||
.driver_data = LG_BAD_RELATIVE_KEYS },
|
||||
|
|
|
@ -106,6 +106,7 @@
|
|||
#define HIDPP_PARAM_DEVICE_INFO 0x01
|
||||
#define HIDPP_PARAM_EQUAD_LSB 0x02
|
||||
#define HIDPP_PARAM_EQUAD_MSB 0x03
|
||||
#define HIDPP_PARAM_27MHZ_DEVID 0x03
|
||||
#define HIDPP_DEVICE_TYPE_MASK GENMASK(3, 0)
|
||||
#define HIDPP_LINK_STATUS_MASK BIT(6)
|
||||
|
||||
|
@ -120,6 +121,7 @@ enum recvr_type {
|
|||
recvr_type_dj,
|
||||
recvr_type_hidpp,
|
||||
recvr_type_gaming_hidpp,
|
||||
recvr_type_27mhz,
|
||||
};
|
||||
|
||||
struct dj_report {
|
||||
|
@ -248,6 +250,44 @@ static const char mse_descriptor[] = {
|
|||
0xC0, /* END_COLLECTION */
|
||||
};
|
||||
|
||||
/* Mouse descriptor (2) for 27 MHz receiver, only 8 buttons */
|
||||
static const char mse_27mhz_descriptor[] = {
|
||||
0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */
|
||||
0x09, 0x02, /* USAGE (Mouse) */
|
||||
0xA1, 0x01, /* COLLECTION (Application) */
|
||||
0x85, 0x02, /* REPORT_ID = 2 */
|
||||
0x09, 0x01, /* USAGE (pointer) */
|
||||
0xA1, 0x00, /* COLLECTION (physical) */
|
||||
0x05, 0x09, /* USAGE_PAGE (buttons) */
|
||||
0x19, 0x01, /* USAGE_MIN (1) */
|
||||
0x29, 0x08, /* USAGE_MAX (8) */
|
||||
0x15, 0x00, /* LOGICAL_MIN (0) */
|
||||
0x25, 0x01, /* LOGICAL_MAX (1) */
|
||||
0x95, 0x08, /* REPORT_COUNT (8) */
|
||||
0x75, 0x01, /* REPORT_SIZE (1) */
|
||||
0x81, 0x02, /* INPUT (data var abs) */
|
||||
0x05, 0x01, /* USAGE_PAGE (generic desktop) */
|
||||
0x16, 0x01, 0xF8, /* LOGICAL_MIN (-2047) */
|
||||
0x26, 0xFF, 0x07, /* LOGICAL_MAX (2047) */
|
||||
0x75, 0x0C, /* REPORT_SIZE (12) */
|
||||
0x95, 0x02, /* REPORT_COUNT (2) */
|
||||
0x09, 0x30, /* USAGE (X) */
|
||||
0x09, 0x31, /* USAGE (Y) */
|
||||
0x81, 0x06, /* INPUT */
|
||||
0x15, 0x81, /* LOGICAL_MIN (-127) */
|
||||
0x25, 0x7F, /* LOGICAL_MAX (127) */
|
||||
0x75, 0x08, /* REPORT_SIZE (8) */
|
||||
0x95, 0x01, /* REPORT_COUNT (1) */
|
||||
0x09, 0x38, /* USAGE (wheel) */
|
||||
0x81, 0x06, /* INPUT */
|
||||
0x05, 0x0C, /* USAGE_PAGE(consumer) */
|
||||
0x0A, 0x38, 0x02, /* USAGE(AC Pan) */
|
||||
0x95, 0x01, /* REPORT_COUNT (1) */
|
||||
0x81, 0x06, /* INPUT */
|
||||
0xC0, /* END_COLLECTION */
|
||||
0xC0, /* END_COLLECTION */
|
||||
};
|
||||
|
||||
/* Gaming Mouse descriptor (2) */
|
||||
static const char mse_high_res_descriptor[] = {
|
||||
0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */
|
||||
|
@ -596,7 +636,10 @@ static void logi_dj_recv_add_djhid_device(struct dj_receiver_dev *djrcv_dev,
|
|||
"Logitech Unifying Device. Wireless PID:%04x",
|
||||
dj_hiddev->product);
|
||||
|
||||
dj_hiddev->group = HID_GROUP_LOGITECH_DJ_DEVICE;
|
||||
if (djrcv_dev->type == recvr_type_27mhz)
|
||||
dj_hiddev->group = HID_GROUP_LOGITECH_27MHZ_DEVICE;
|
||||
else
|
||||
dj_hiddev->group = HID_GROUP_LOGITECH_DJ_DEVICE;
|
||||
|
||||
memcpy(dj_hiddev->phys, djrcv_hdev->phys, sizeof(djrcv_hdev->phys));
|
||||
snprintf(tmpstr, sizeof(tmpstr), ":%d", device_index);
|
||||
|
@ -782,6 +825,28 @@ static void logi_hidpp_dev_conn_notif_equad(struct hidpp_event *hidpp_report,
|
|||
}
|
||||
}
|
||||
|
||||
static void logi_hidpp_dev_conn_notif_27mhz(struct hid_device *hdev,
|
||||
struct hidpp_event *hidpp_report,
|
||||
struct dj_workitem *workitem)
|
||||
{
|
||||
workitem->type = WORKITEM_TYPE_PAIRED;
|
||||
workitem->quad_id_lsb = hidpp_report->params[HIDPP_PARAM_27MHZ_DEVID];
|
||||
switch (hidpp_report->device_index) {
|
||||
case 1: /* Index 1 is always a mouse */
|
||||
case 2: /* Index 2 is always a mouse */
|
||||
workitem->reports_supported |= STD_MOUSE;
|
||||
break;
|
||||
case 3: /* Index 3 is always the keyboard */
|
||||
case 4: /* Index 4 is used for an optional separate numpad */
|
||||
workitem->reports_supported |= STD_KEYBOARD | MULTIMEDIA |
|
||||
POWER_KEYS;
|
||||
break;
|
||||
default:
|
||||
hid_warn(hdev, "%s: unexpected device-index %d", __func__,
|
||||
hidpp_report->device_index);
|
||||
}
|
||||
}
|
||||
|
||||
static void logi_hidpp_recv_queue_notif(struct hid_device *hdev,
|
||||
struct hidpp_event *hidpp_report)
|
||||
{
|
||||
|
@ -799,6 +864,7 @@ static void logi_hidpp_recv_queue_notif(struct hid_device *hdev,
|
|||
break;
|
||||
case 0x02:
|
||||
device_type = "27 Mhz";
|
||||
logi_hidpp_dev_conn_notif_27mhz(hdev, hidpp_report, &workitem);
|
||||
break;
|
||||
case 0x03:
|
||||
device_type = "QUAD or eQUAD";
|
||||
|
@ -1186,6 +1252,9 @@ static int logi_dj_ll_parse(struct hid_device *hid)
|
|||
if (djdev->dj_receiver_dev->type == recvr_type_gaming_hidpp)
|
||||
rdcat(rdesc, &rsize, mse_high_res_descriptor,
|
||||
sizeof(mse_high_res_descriptor));
|
||||
else if (djdev->dj_receiver_dev->type == recvr_type_27mhz)
|
||||
rdcat(rdesc, &rsize, mse_27mhz_descriptor,
|
||||
sizeof(mse_27mhz_descriptor));
|
||||
else
|
||||
rdcat(rdesc, &rsize, mse_descriptor,
|
||||
sizeof(mse_descriptor));
|
||||
|
@ -1357,6 +1426,25 @@ static int logi_dj_hidpp_event(struct hid_device *hdev,
|
|||
spin_lock_irqsave(&djrcv_dev->lock, flags);
|
||||
|
||||
dj_dev = djrcv_dev->paired_dj_devices[device_index];
|
||||
|
||||
/*
|
||||
* With 27 MHz receivers, we do not get an explicit unpair event,
|
||||
* remove the old device if the user has paired a *different* device.
|
||||
*/
|
||||
if (djrcv_dev->type == recvr_type_27mhz && dj_dev &&
|
||||
hidpp_report->sub_id == REPORT_TYPE_NOTIF_DEVICE_CONNECTED &&
|
||||
hidpp_report->params[HIDPP_PARAM_PROTO_TYPE] == 0x02 &&
|
||||
hidpp_report->params[HIDPP_PARAM_27MHZ_DEVID] !=
|
||||
dj_dev->hdev->product) {
|
||||
struct dj_workitem workitem = {
|
||||
.device_index = hidpp_report->device_index,
|
||||
.type = WORKITEM_TYPE_UNPAIRED,
|
||||
};
|
||||
kfifo_in(&djrcv_dev->notif_fifo, &workitem, sizeof(workitem));
|
||||
/* logi_hidpp_recv_queue_notif will queue the work */
|
||||
dj_dev = NULL;
|
||||
}
|
||||
|
||||
if (dj_dev) {
|
||||
logi_dj_recv_forward_report(dj_dev, data, size);
|
||||
} else {
|
||||
|
@ -1628,6 +1716,10 @@ static const struct hid_device_id logi_dj_receivers[] = {
|
|||
HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
|
||||
USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_GAMING),
|
||||
.driver_data = recvr_type_gaming_hidpp},
|
||||
{ /* Logitech 27 MHz HID++ 1.0 receiver (0xc517) */
|
||||
HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
|
||||
USB_DEVICE_ID_S510_RECEIVER_2),
|
||||
.driver_data = recvr_type_27mhz},
|
||||
{}
|
||||
};
|
||||
|
||||
|
|
|
@ -432,7 +432,6 @@ static const struct hid_device_id hid_have_special_driver[] = {
|
|||
#if IS_ENABLED(CONFIG_HID_LOGITECH)
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER_2) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RECEIVER) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_DESKTOP) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_EDGE) },
|
||||
|
|
|
@ -382,6 +382,7 @@ struct hid_item {
|
|||
#define HID_GROUP_WACOM 0x0101
|
||||
#define HID_GROUP_LOGITECH_DJ_DEVICE 0x0102
|
||||
#define HID_GROUP_STEAM 0x0103
|
||||
#define HID_GROUP_LOGITECH_27MHZ_DEVICE 0x0104
|
||||
|
||||
/*
|
||||
* HID protocol status
|
||||
|
|
Загрузка…
Ссылка в новой задаче