Commit a8da334c authored by Benjamin Tissoires's avatar Benjamin Tissoires
Browse files

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
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -867,6 +867,7 @@
#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_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_SPACETRAVELLER	0xc623
#define USB_DEVICE_ID_SPACENAVIGATOR	0xc626
+12 −4
Original line number Diff line number Diff line
@@ -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.
		 */
		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,
	buf[5] = 0x09;
	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,
			HID_REQ_SET_REPORT);

@@ -1692,11 +1695,12 @@ static int logi_dj_raw_event(struct hid_device *hdev,
		}
		/*
		 * 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 &&
		    size <= 8) {
			u8 mouse_report[9];
		    size <= 13){
			u8 mouse_report[14];

			/* Prepend report id */
			mouse_report[0] = REPORT_TYPE_MOUSE;
@@ -1980,6 +1984,10 @@ static const struct hid_device_id logi_dj_receivers[] = {
	  HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
		USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_LIGHTSPEED_1_1),
	 .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) */
	  HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER),
+80 −41
Original line number Diff line number Diff line
@@ -228,7 +228,7 @@ struct hidpp_device {
#define HIDPP20_ERROR_INVALID_ARGS		0x02
#define HIDPP20_ERROR_OUT_OF_RANGE		0x03
#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_FUNCTION_ID	0x07
#define HIDPP20_ERROR_BUSY			0x08
@@ -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
 * in case of a failure.
 * - If ' something else' is positive, that means that an error has been raised
 *   by the protocol itself.
 * - If ' something else' is negative, that means that we had a classic error
 *   (-ENOMEM, -EPIPE, etc...)
 * Effectively send the message to the device, waiting for its answer.
 *
 * Must be called with hidpp->send_mutex locked
 *
 * Same return protocol than hidpp_send_message_sync():
 * - 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 *response)
{
	int ret = -1;
	int max_retries = 3;
	int ret;

	mutex_lock(&hidpp->send_mutex);
	__must_hold(&hidpp->send_mutex);

	hidpp->send_receive_buf = response;
	hidpp->answer_available = false;
@@ -300,47 +301,74 @@ static int hidpp_send_message_sync(struct hidpp_device *hidpp,
	 */
	*response = *message;

	for (; max_retries != 0 && ret; max_retries--) {
	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));
			break;
		return ret;
	}

	if (!wait_event_timeout(hidpp->wait, hidpp->answer_available,
				5*HZ)) {
		dbg_hid("%s:timeout waiting for response\n", __func__);
		memset(response, 0, sizeof(struct hidpp_report));
			ret = -ETIMEDOUT;
			break;
		return -ETIMEDOUT;
	}

	if (response->report_id == REPORT_ID_HIDPP_SHORT &&
	    response->rap.sub_id == HIDPP_ERROR) {
		ret = response->rap.params[1];
		dbg_hid("%s:got hidpp error %02X\n", __func__, ret);
			break;
		return ret;
	}

	if ((response->report_id == REPORT_ID_HIDPP_LONG ||
	     response->report_id == REPORT_ID_HIDPP_VERY_LONG) &&
	    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);
		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;

		dbg_hid("%s:got busy hidpp 2.0 error %02X, retrying\n", __func__, ret);
	} while (--max_retries);

	mutex_unlock(&hidpp->send_mutex);
	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,
	u8 feat_index, u8 funcindex_clientid, u8 *params, int param_count,
	struct hidpp_report *response)
@@ -373,6 +401,13 @@ static int hidpp_send_fap_command_sync(struct hidpp_device *hidpp,
	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,
	u8 report_id, u8 sub_id, u8 reg_address, u8 *params, int param_count,
	struct hidpp_report *response)
@@ -4620,6 +4655,8 @@ static const struct hid_device_id hidpp_devices[] = {
		.driver_data = HIDPP_QUIRK_CLASS_G920 | HIDPP_QUIRK_FORCE_OUTPUT_REPORTS },
	{ /* Logitech G Pro Gaming Mouse over USB */
	  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 */
	  HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 0x0a87),
@@ -4647,6 +4684,8 @@ static const struct hid_device_id hidpp_devices[] = {
	  HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb02a) },
	{ /* MX Master 3 mouse over Bluetooth */
	  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 */
	  HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb034) },
	{}