Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8c4de9bc authored by Jiri Kosina's avatar Jiri Kosina
Browse files

Merge branches 'for-4.3/chicony', 'for-4.3/cp2112', 'for-4.3/i2c-hid',...

Merge branches 'for-4.3/chicony', 'for-4.3/cp2112', 'for-4.3/i2c-hid', 'for-4.3/lenovo', 'for-4.3/logitech', 'for-4.3/multitouch', 'for-4.3/picolcd', 'for-4.3/rmi', 'for-4.3/sensor-hub', 'for-4.3/sony' and 'for-4.3/wacom' into for-linus
Loading
+19 −0
Original line number Diff line number Diff line
@@ -77,3 +77,22 @@ Description:
		The format is also scrambled, like in the USB mode, and it can
		be summarized by converting 76543210 into GECA6420.
					    HGFEDCBA      HFDB7531

What:		/sys/bus/hid/devices/<bus>:<vid>:<pid>.<n>/wacom_remote/unpair_remote
Date:		July 2015
Contact:	linux-input@vger.kernel.org
Description:
		Writing the character sequence '*' followed by a newline to
		this file will delete all of the current pairings on the
		device. Other character sequences are reserved. This file is
		write only.

What:		/sys/bus/hid/devices/<bus>:<vid>:<pid>.<n>/wacom_remote/<serial_number>/remote_mode
Date:		July 2015
Contact:	linux-input@vger.kernel.org
Description:
		Reading from this file reports the mode status of the
		remote as indicated by the LED lights on the device. If no
		reports have been received from the paired device, reading
		from this file will report '-1'. The mode is read-only
		and cannot be set through the driver.
+1 −0
Original line number Diff line number Diff line
@@ -486,6 +486,7 @@ config HID_MULTITOUCH
	  - Atmel panels
	  - Cando dual touch panels
	  - Chunghwa panels
	  - CJTouch panels
	  - CVTouch panels
	  - Cypress TrueTouch panels
	  - Elan Microelectronics touch panels
+26 −0
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@
#include <linux/input.h>
#include <linux/hid.h>
#include <linux/module.h>
#include <linux/usb.h>

#include "hid-ids.h"

@@ -57,10 +58,34 @@ static int ch_input_mapping(struct hid_device *hdev, struct hid_input *hi,
	return 1;
}

static __u8 *ch_switch12_report_fixup(struct hid_device *hdev, __u8 *rdesc,
		unsigned int *rsize)
{
	struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
	
	if (intf->cur_altsetting->desc.bInterfaceNumber == 1) {
		/* Change usage maximum and logical maximum from 0x7fff to
		 * 0x2fff, so they don't exceed HID_MAX_USAGES */
		switch (hdev->product) {
		case USB_DEVICE_ID_CHICONY_ACER_SWITCH12:
			if (*rsize >= 128 && rdesc[64] == 0xff && rdesc[65] == 0x7f
					&& rdesc[69] == 0xff && rdesc[70] == 0x7f) {
				hid_info(hdev, "Fixing up report descriptor\n");
				rdesc[65] = rdesc[70] = 0x2f;
			}
			break;
		}

	}
	return rdesc;
}


static const struct hid_device_id ch_devices[] = {
	{ HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_TACTICAL_PAD) },
	{ HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_WIRELESS2) },
	{ HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_AK1D) },
	{ HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_ACER_SWITCH12) },
	{ }
};
MODULE_DEVICE_TABLE(hid, ch_devices);
@@ -68,6 +93,7 @@ MODULE_DEVICE_TABLE(hid, ch_devices);
static struct hid_driver ch_driver = {
	.name = "chicony",
	.id_table = ch_devices,
	.report_fixup = ch_switch12_report_fixup,
	.input_mapping = ch_input_mapping,
};
module_hid_driver(ch_driver);
+1 −0
Original line number Diff line number Diff line
@@ -1826,6 +1826,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
	{ HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_WIRELESS) },
	{ HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_WIRELESS2) },
	{ HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_AK1D) },
	{ HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_ACER_SWITCH12) },
	{ HID_USB_DEVICE(USB_VENDOR_ID_CREATIVELABS, USB_DEVICE_ID_PRODIKEYS_PCMIDI) },
	{ HID_USB_DEVICE(USB_VENDOR_ID_CYGNAL, USB_DEVICE_ID_CYGNAL_CP2112) },
	{ HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_1) },
+80 −27
Original line number Diff line number Diff line
@@ -156,6 +156,7 @@ struct cp2112_device {
	wait_queue_head_t wait;
	u8 read_data[61];
	u8 read_length;
	u8 hwversion;
	int xfer_status;
	atomic_t read_avail;
	atomic_t xfer_avail;
@@ -446,6 +447,24 @@ static int cp2112_i2c_write_req(void *buf, u8 slave_address, u8 *data,
	return data_length + 3;
}

static int cp2112_i2c_write_read_req(void *buf, u8 slave_address,
				     u8 *addr, int addr_length,
				     int read_length)
{
	struct cp2112_write_read_req_report *report = buf;

	if (read_length < 1 || read_length > 512 ||
	    addr_length > sizeof(report->target_address))
		return -EINVAL;

	report->report = CP2112_DATA_WRITE_READ_REQUEST;
	report->slave_address = slave_address << 1;
	report->length = cpu_to_be16(read_length);
	report->target_address_length = addr_length;
	memcpy(report->target_address, addr, addr_length);
	return addr_length + 5;
}

static int cp2112_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
			   int num)
{
@@ -453,26 +472,46 @@ static int cp2112_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
	struct hid_device *hdev = dev->hdev;
	u8 buf[64];
	ssize_t count;
	ssize_t read_length = 0;
	u8 *read_buf = NULL;
	unsigned int retries;
	int ret;

	hid_dbg(hdev, "I2C %d messages\n", num);

	if (num != 1) {
	if (num == 1) {
		if (msgs->flags & I2C_M_RD) {
			hid_dbg(hdev, "I2C read %#04x len %d\n",
				msgs->addr, msgs->len);
			read_length = msgs->len;
			read_buf = msgs->buf;
			count = cp2112_read_req(buf, msgs->addr, msgs->len);
		} else {
			hid_dbg(hdev, "I2C write %#04x len %d\n",
				msgs->addr, msgs->len);
			count = cp2112_i2c_write_req(buf, msgs->addr,
						     msgs->buf, msgs->len);
		}
		if (count < 0)
			return count;
	} else if (dev->hwversion > 1 &&  /* no repeated start in rev 1 */
		   num == 2 &&
		   msgs[0].addr == msgs[1].addr &&
		   !(msgs[0].flags & I2C_M_RD) && (msgs[1].flags & I2C_M_RD)) {
		hid_dbg(hdev, "I2C write-read %#04x wlen %d rlen %d\n",
			msgs[0].addr, msgs[0].len, msgs[1].len);
		read_length = msgs[1].len;
		read_buf = msgs[1].buf;
		count = cp2112_i2c_write_read_req(buf, msgs[0].addr,
				msgs[0].buf, msgs[0].len, msgs[1].len);
		if (count < 0)
			return count;
	} else {
		hid_err(hdev,
			"Multi-message I2C transactions not supported\n");
		return -EOPNOTSUPP;
	}

	if (msgs->flags & I2C_M_RD)
		count = cp2112_read_req(buf, msgs->addr, msgs->len);
	else
		count = cp2112_i2c_write_req(buf, msgs->addr, msgs->buf,
					     msgs->len);

	if (count < 0)
		return count;

	ret = hid_hw_power(hdev, PM_HINT_FULLON);
	if (ret < 0) {
		hid_err(hdev, "power management error: %d\n", ret);
@@ -508,21 +547,34 @@ static int cp2112_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
		goto power_normal;
	}

	if (!(msgs->flags & I2C_M_RD))
		goto finish;

	ret = cp2112_read(dev, msgs->buf, msgs->len);
	for (count = 0; count < read_length;) {
		ret = cp2112_read(dev, read_buf + count, read_length - count);
		if (ret < 0)
			goto power_normal;
	if (ret != msgs->len) {
		hid_warn(hdev, "short read: %d < %d\n", ret, msgs->len);
		if (ret == 0) {
			hid_err(hdev, "read returned 0\n");
			ret = -EIO;
			goto power_normal;
		}
		count += ret;
		if (count > read_length) {
			/*
			 * The hardware returned too much data.
			 * This is mostly harmless because cp2112_read()
			 * has a limit check so didn't overrun our
			 * buffer.  Nevertheless, we return an error
			 * because something is seriously wrong and
			 * it shouldn't go unnoticed.
			 */
			hid_err(hdev, "long read: %d > %zd\n",
				ret, read_length - count + ret);
			ret = -EIO;
			goto power_normal;
		}
	}

finish:
	/* return the number of transferred messages */
	ret = 1;
	ret = num;

power_normal:
	hid_hw_power(hdev, PM_HINT_NORMAL);
@@ -537,7 +589,7 @@ static int cp2112_xfer(struct i2c_adapter *adap, u16 addr,
	struct cp2112_device *dev = (struct cp2112_device *)adap->algo_data;
	struct hid_device *hdev = dev->hdev;
	u8 buf[64];
	__be16 word;
	__le16 word;
	ssize_t count;
	size_t read_length = 0;
	unsigned int retries;
@@ -554,7 +606,7 @@ static int cp2112_xfer(struct i2c_adapter *adap, u16 addr,
		if (I2C_SMBUS_READ == read_write)
			count = cp2112_read_req(buf, addr, read_length);
		else
			count = cp2112_write_req(buf, addr, data->byte, NULL,
			count = cp2112_write_req(buf, addr, command, NULL,
						 0);
		break;
	case I2C_SMBUS_BYTE_DATA:
@@ -569,7 +621,7 @@ static int cp2112_xfer(struct i2c_adapter *adap, u16 addr,
		break;
	case I2C_SMBUS_WORD_DATA:
		read_length = 2;
		word = cpu_to_be16(data->word);
		word = cpu_to_le16(data->word);

		if (I2C_SMBUS_READ == read_write)
			count = cp2112_write_read_req(buf, addr, read_length,
@@ -582,7 +634,7 @@ static int cp2112_xfer(struct i2c_adapter *adap, u16 addr,
		size = I2C_SMBUS_WORD_DATA;
		read_write = I2C_SMBUS_READ;
		read_length = 2;
		word = cpu_to_be16(data->word);
		word = cpu_to_le16(data->word);

		count = cp2112_write_read_req(buf, addr, read_length, command,
					      (u8 *)&word, 2);
@@ -675,7 +727,7 @@ static int cp2112_xfer(struct i2c_adapter *adap, u16 addr,
		data->byte = buf[0];
		break;
	case I2C_SMBUS_WORD_DATA:
		data->word = be16_to_cpup((__be16 *)buf);
		data->word = le16_to_cpup((__le16 *)buf);
		break;
	case I2C_SMBUS_BLOCK_DATA:
		if (read_length > I2C_SMBUS_BLOCK_MAX) {
@@ -1030,6 +1082,7 @@ static int cp2112_probe(struct hid_device *hdev, const struct hid_device_id *id)
	dev->adap.dev.parent	= &hdev->dev;
	snprintf(dev->adap.name, sizeof(dev->adap.name),
		 "CP2112 SMBus Bridge on hiddev%d", hdev->minor);
	dev->hwversion = buf[2];
	init_waitqueue_head(&dev->wait);

	hid_device_io_start(hdev);
Loading