Commit a8da334c authored by Benjamin Tissoires's avatar Benjamin Tissoires

Merge branch 'for-6.6/logitech' into for-linus

Various new device ID addition and a couple of HID++
fixes to tackle the last few opened bugs (Nikita Zhandarovich
and Benjamin Tissoires)
parents a48e7607 60165ab7
...@@ -867,6 +867,7 @@ ...@@ -867,6 +867,7 @@
#define USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_2 0xc534 #define USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_2 0xc534
#define USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_LIGHTSPEED_1 0xc539 #define USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_LIGHTSPEED_1 0xc539
#define USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_LIGHTSPEED_1_1 0xc53f #define USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_LIGHTSPEED_1_1 0xc53f
#define USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_LIGHTSPEED_1_2 0xc547
#define USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_POWERPLAY 0xc53a #define USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_POWERPLAY 0xc53a
#define USB_DEVICE_ID_SPACETRAVELLER 0xc623 #define USB_DEVICE_ID_SPACETRAVELLER 0xc623
#define USB_DEVICE_ID_SPACENAVIGATOR 0xc626 #define USB_DEVICE_ID_SPACENAVIGATOR 0xc626
......
...@@ -1285,6 +1285,9 @@ static int logi_dj_recv_switch_to_dj_mode(struct dj_receiver_dev *djrcv_dev, ...@@ -1285,6 +1285,9 @@ static int logi_dj_recv_switch_to_dj_mode(struct dj_receiver_dev *djrcv_dev,
* 50 msec should gives enough time to the receiver to be ready. * 50 msec should gives enough time to the receiver to be ready.
*/ */
msleep(50); msleep(50);
if (retval)
return retval;
} }
/* /*
...@@ -1306,7 +1309,7 @@ static int logi_dj_recv_switch_to_dj_mode(struct dj_receiver_dev *djrcv_dev, ...@@ -1306,7 +1309,7 @@ static int logi_dj_recv_switch_to_dj_mode(struct dj_receiver_dev *djrcv_dev,
buf[5] = 0x09; buf[5] = 0x09;
buf[6] = 0x00; buf[6] = 0x00;
hid_hw_raw_request(hdev, REPORT_ID_HIDPP_SHORT, buf, retval = hid_hw_raw_request(hdev, REPORT_ID_HIDPP_SHORT, buf,
HIDPP_REPORT_SHORT_LENGTH, HID_OUTPUT_REPORT, HIDPP_REPORT_SHORT_LENGTH, HID_OUTPUT_REPORT,
HID_REQ_SET_REPORT); HID_REQ_SET_REPORT);
...@@ -1692,11 +1695,12 @@ static int logi_dj_raw_event(struct hid_device *hdev, ...@@ -1692,11 +1695,12 @@ static int logi_dj_raw_event(struct hid_device *hdev,
} }
/* /*
* Mouse-only receivers send unnumbered mouse data. The 27 MHz * Mouse-only receivers send unnumbered mouse data. The 27 MHz
* receiver uses 6 byte packets, the nano receiver 8 bytes. * receiver uses 6 byte packets, the nano receiver 8 bytes,
* the lightspeed receiver (Pro X Superlight) 13 bytes.
*/ */
if (djrcv_dev->unnumbered_application == HID_GD_MOUSE && if (djrcv_dev->unnumbered_application == HID_GD_MOUSE &&
size <= 8) { size <= 13){
u8 mouse_report[9]; u8 mouse_report[14];
/* Prepend report id */ /* Prepend report id */
mouse_report[0] = REPORT_TYPE_MOUSE; mouse_report[0] = REPORT_TYPE_MOUSE;
...@@ -1980,6 +1984,10 @@ static const struct hid_device_id logi_dj_receivers[] = { ...@@ -1980,6 +1984,10 @@ static const struct hid_device_id logi_dj_receivers[] = {
HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_LIGHTSPEED_1_1), USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_LIGHTSPEED_1_1),
.driver_data = recvr_type_gaming_hidpp}, .driver_data = recvr_type_gaming_hidpp},
{ /* Logitech lightspeed receiver (0xc547) */
HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_LIGHTSPEED_1_2),
.driver_data = recvr_type_gaming_hidpp},
{ /* Logitech 27 MHz HID++ 1.0 receiver (0xc513) */ { /* Logitech 27 MHz HID++ 1.0 receiver (0xc513) */
HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER), HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER),
......
...@@ -228,7 +228,7 @@ struct hidpp_device { ...@@ -228,7 +228,7 @@ struct hidpp_device {
#define HIDPP20_ERROR_INVALID_ARGS 0x02 #define HIDPP20_ERROR_INVALID_ARGS 0x02
#define HIDPP20_ERROR_OUT_OF_RANGE 0x03 #define HIDPP20_ERROR_OUT_OF_RANGE 0x03
#define HIDPP20_ERROR_HW_ERROR 0x04 #define HIDPP20_ERROR_HW_ERROR 0x04
#define HIDPP20_ERROR_LOGITECH_INTERNAL 0x05 #define HIDPP20_ERROR_NOT_ALLOWED 0x05
#define HIDPP20_ERROR_INVALID_FEATURE_INDEX 0x06 #define HIDPP20_ERROR_INVALID_FEATURE_INDEX 0x06
#define HIDPP20_ERROR_INVALID_FUNCTION_ID 0x07 #define HIDPP20_ERROR_INVALID_FUNCTION_ID 0x07
#define HIDPP20_ERROR_BUSY 0x08 #define HIDPP20_ERROR_BUSY 0x08
...@@ -275,21 +275,22 @@ static int __hidpp_send_report(struct hid_device *hdev, ...@@ -275,21 +275,22 @@ static int __hidpp_send_report(struct hid_device *hdev,
} }
/* /*
* hidpp_send_message_sync() returns 0 in case of success, and something else * Effectively send the message to the device, waiting for its answer.
* in case of a failure. *
* - If ' something else' is positive, that means that an error has been raised * Must be called with hidpp->send_mutex locked
* by the protocol itself. *
* - If ' something else' is negative, that means that we had a classic error * Same return protocol than hidpp_send_message_sync():
* (-ENOMEM, -EPIPE, etc...) * - success on 0
* - negative error means transport error
* - positive value means protocol error
*/ */
static int hidpp_send_message_sync(struct hidpp_device *hidpp, static int __do_hidpp_send_message_sync(struct hidpp_device *hidpp,
struct hidpp_report *message, struct hidpp_report *message,
struct hidpp_report *response) struct hidpp_report *response)
{ {
int ret = -1; int ret;
int max_retries = 3;
mutex_lock(&hidpp->send_mutex); __must_hold(&hidpp->send_mutex);
hidpp->send_receive_buf = response; hidpp->send_receive_buf = response;
hidpp->answer_available = false; hidpp->answer_available = false;
...@@ -300,47 +301,74 @@ static int hidpp_send_message_sync(struct hidpp_device *hidpp, ...@@ -300,47 +301,74 @@ static int hidpp_send_message_sync(struct hidpp_device *hidpp,
*/ */
*response = *message; *response = *message;
for (; max_retries != 0 && ret; max_retries--) { ret = __hidpp_send_report(hidpp->hid_dev, message);
ret = __hidpp_send_report(hidpp->hid_dev, message); if (ret) {
dbg_hid("__hidpp_send_report returned err: %d\n", ret);
memset(response, 0, sizeof(struct hidpp_report));
return ret;
}
if (ret) { if (!wait_event_timeout(hidpp->wait, hidpp->answer_available,
dbg_hid("__hidpp_send_report returned err: %d\n", ret); 5*HZ)) {
memset(response, 0, sizeof(struct hidpp_report)); dbg_hid("%s:timeout waiting for response\n", __func__);
break; memset(response, 0, sizeof(struct hidpp_report));
} return -ETIMEDOUT;
}
if (!wait_event_timeout(hidpp->wait, hidpp->answer_available, if (response->report_id == REPORT_ID_HIDPP_SHORT &&
5*HZ)) { response->rap.sub_id == HIDPP_ERROR) {
dbg_hid("%s:timeout waiting for response\n", __func__); ret = response->rap.params[1];
memset(response, 0, sizeof(struct hidpp_report)); dbg_hid("%s:got hidpp error %02X\n", __func__, ret);
ret = -ETIMEDOUT; return ret;
break; }
}
if (response->report_id == REPORT_ID_HIDPP_SHORT && if ((response->report_id == REPORT_ID_HIDPP_LONG ||
response->rap.sub_id == HIDPP_ERROR) { response->report_id == REPORT_ID_HIDPP_VERY_LONG) &&
ret = response->rap.params[1]; response->fap.feature_index == HIDPP20_ERROR) {
dbg_hid("%s:got hidpp error %02X\n", __func__, ret); ret = response->fap.params[1];
dbg_hid("%s:got hidpp 2.0 error %02X\n", __func__, ret);
return ret;
}
return 0;
}
/*
* hidpp_send_message_sync() returns 0 in case of success, and something else
* in case of a failure.
*
* See __do_hidpp_send_message_sync() for a detailed explanation of the returned
* value.
*/
static int hidpp_send_message_sync(struct hidpp_device *hidpp,
struct hidpp_report *message,
struct hidpp_report *response)
{
int ret;
int max_retries = 3;
mutex_lock(&hidpp->send_mutex);
do {
ret = __do_hidpp_send_message_sync(hidpp, message, response);
if (ret != HIDPP20_ERROR_BUSY)
break; break;
}
if ((response->report_id == REPORT_ID_HIDPP_LONG || dbg_hid("%s:got busy hidpp 2.0 error %02X, retrying\n", __func__, ret);
response->report_id == REPORT_ID_HIDPP_VERY_LONG) && } while (--max_retries);
response->fap.feature_index == HIDPP20_ERROR) {
ret = response->fap.params[1];
if (ret != HIDPP20_ERROR_BUSY) {
dbg_hid("%s:got hidpp 2.0 error %02X\n", __func__, ret);
break;
}
dbg_hid("%s:got busy hidpp 2.0 error %02X, retrying\n", __func__, ret);
}
}
mutex_unlock(&hidpp->send_mutex); mutex_unlock(&hidpp->send_mutex);
return ret; return ret;
} }
/*
* hidpp_send_fap_command_sync() returns 0 in case of success, and something else
* in case of a failure.
*
* See __do_hidpp_send_message_sync() for a detailed explanation of the returned
* value.
*/
static int hidpp_send_fap_command_sync(struct hidpp_device *hidpp, static int hidpp_send_fap_command_sync(struct hidpp_device *hidpp,
u8 feat_index, u8 funcindex_clientid, u8 *params, int param_count, u8 feat_index, u8 funcindex_clientid, u8 *params, int param_count,
struct hidpp_report *response) struct hidpp_report *response)
...@@ -373,6 +401,13 @@ static int hidpp_send_fap_command_sync(struct hidpp_device *hidpp, ...@@ -373,6 +401,13 @@ static int hidpp_send_fap_command_sync(struct hidpp_device *hidpp,
return ret; return ret;
} }
/*
* hidpp_send_rap_command_sync() returns 0 in case of success, and something else
* in case of a failure.
*
* See __do_hidpp_send_message_sync() for a detailed explanation of the returned
* value.
*/
static int hidpp_send_rap_command_sync(struct hidpp_device *hidpp_dev, static int hidpp_send_rap_command_sync(struct hidpp_device *hidpp_dev,
u8 report_id, u8 sub_id, u8 reg_address, u8 *params, int param_count, u8 report_id, u8 sub_id, u8 reg_address, u8 *params, int param_count,
struct hidpp_report *response) struct hidpp_report *response)
...@@ -4620,6 +4655,8 @@ static const struct hid_device_id hidpp_devices[] = { ...@@ -4620,6 +4655,8 @@ static const struct hid_device_id hidpp_devices[] = {
.driver_data = HIDPP_QUIRK_CLASS_G920 | HIDPP_QUIRK_FORCE_OUTPUT_REPORTS }, .driver_data = HIDPP_QUIRK_CLASS_G920 | HIDPP_QUIRK_FORCE_OUTPUT_REPORTS },
{ /* Logitech G Pro Gaming Mouse over USB */ { /* Logitech G Pro Gaming Mouse over USB */
HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 0xC088) }, HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 0xC088) },
{ /* Logitech G Pro X Superlight Gaming Mouse over USB */
HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 0xC094) },
{ /* G935 Gaming Headset */ { /* G935 Gaming Headset */
HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 0x0a87), HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 0x0a87),
...@@ -4647,6 +4684,8 @@ static const struct hid_device_id hidpp_devices[] = { ...@@ -4647,6 +4684,8 @@ static const struct hid_device_id hidpp_devices[] = {
HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb02a) }, HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb02a) },
{ /* MX Master 3 mouse over Bluetooth */ { /* MX Master 3 mouse over Bluetooth */
HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb023) }, HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb023) },
{ /* MX Anywhere 3 mouse over Bluetooth */
HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb025) },
{ /* MX Master 3S mouse over Bluetooth */ { /* MX Master 3S mouse over Bluetooth */
HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb034) }, HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb034) },
{} {}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment