Commit 2043f9a3 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'for-linus-2022121301' of git://git.kernel.org/pub/scm/linux/kernel/git/hid/hid

Pull HID updates from Jiri Kosina:

 - iio support for the MCP2221 HID driver (Matt Ranostay)

 - support for more than one hinge sensor in hid-sensor-custom (Yauhen
   Kharuzhy)

 - PS DualShock 4 controller support (Roderick Colenbrander)

 - XP-PEN Deco LW support (José Expósito)

 - other assorted code cleanups and device ID/quirk addtions

* tag 'for-linus-2022121301' of git://git.kernel.org/pub/scm/linux/kernel/git/hid/hid: (51 commits)
  HID: logitech HID++: Send SwID in GetProtocolVersion
  HID: hid-elan: use default remove for hid device
  HID: hid-alps: use default remove for hid device
  HID: hid-sensor-custom: set fixed size for custom attributes
  HID: i2c: let RMI devices decide what constitutes wakeup event
  HID: playstation: fix DualShock4 bluetooth CRC endian issue.
  HID: playstation: fix DualShock4 bluetooth memory corruption bug.
  HID: apple: Swap Control and Command keys on Apple keyboards
  HID: intel-ish-hid: ishtp: remove variable rb_count
  HID: uclogic: Standardize test name prefix
  HID: hid-sensor-custom: Allow more than one hinge angle sensor
  HID: ft260: fix 'cast to restricted' kernel CI bot warnings
  HID: ft260: missed NACK from busy device
  HID: ft260: fix a NULL pointer dereference in ft260_i2c_write
  HID: ft260: wake up device from power saving mode
  HID: ft260: missed NACK from big i2c read
  HID: ft260: remove SMBus Quick command support
  HID: ft260: skip unexpected HID input reports
  HID: ft260: do not populate /dev/hidraw device
  HID: ft260: improve i2c large reads performance
  ...
parents 86a0b425 f722052c
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -1252,7 +1252,8 @@ config HID_ALPS
config HID_MCP2221
	tristate "Microchip MCP2221 HID USB-to-I2C/SMbus host support"
	depends on USB_HID && I2C
	depends on GPIOLIB
	imply GPIOLIB
	imply IIO
	help
	Provides I2C and SMBUS host adapter functionality over USB-HID
	through MCP2221 device.
+0 −6
Original line number Diff line number Diff line
@@ -820,11 +820,6 @@ static int alps_probe(struct hid_device *hdev, const struct hid_device_id *id)
	return 0;
}

static void alps_remove(struct hid_device *hdev)
{
	hid_hw_stop(hdev);
}

static const struct hid_device_id alps_id[] = {
	{ HID_DEVICE(HID_BUS_ANY, HID_GROUP_ANY,
		USB_VENDOR_ID_ALPS_JP, HID_DEVICE_ID_ALPS_U1_DUAL) },
@@ -842,7 +837,6 @@ static struct hid_driver alps_driver = {
	.name = "hid-alps",
	.id_table		= alps_id,
	.probe			= alps_probe,
	.remove			= alps_remove,
	.raw_event		= alps_raw_event,
	.input_mapping		= alps_input_mapping,
	.input_configured	= alps_input_configured,
+74 −67
Original line number Diff line number Diff line
@@ -59,6 +59,12 @@ MODULE_PARM_DESC(swap_opt_cmd, "Swap the Option (\"Alt\") and Command (\"Flag\")
		"(For people who want to keep Windows PC keyboard muscle memory. "
		"[0] = as-is, Mac layout. 1 = swapped, Windows layout.)");

static unsigned int swap_ctrl_cmd;
module_param(swap_ctrl_cmd, uint, 0644);
MODULE_PARM_DESC(swap_ctrl_cmd, "Swap the Control (\"Ctrl\") and Command (\"Flag\") keys. "
		"(For people who are used to Mac shortcuts involving Command instead of Control. "
		"[0] = No change. 1 = Swapped.)");

static unsigned int swap_fn_leftctrl;
module_param(swap_fn_leftctrl, uint, 0644);
MODULE_PARM_DESC(swap_fn_leftctrl, "Swap the Fn and left Control keys. "
@@ -312,8 +318,17 @@ static const struct apple_key_translation swapped_option_cmd_keys[] = {
	{ }
};

static const struct apple_key_translation swapped_ctrl_cmd_keys[] = {
	{ KEY_LEFTCTRL,	KEY_LEFTMETA },
	{ KEY_LEFTMETA,	KEY_LEFTCTRL },
	{ KEY_RIGHTCTRL, KEY_RIGHTMETA },
	{ KEY_RIGHTMETA, KEY_RIGHTCTRL },
	{ }
};

static const struct apple_key_translation swapped_fn_leftctrl_keys[] = {
	{ KEY_FN, KEY_LEFTCTRL },
	{ KEY_LEFTCTRL, KEY_FN },
	{ }
};

@@ -375,24 +390,47 @@ static int hidinput_apple_event(struct hid_device *hid, struct input_dev *input,
	struct apple_sc *asc = hid_get_drvdata(hid);
	const struct apple_key_translation *trans, *table;
	bool do_translate;
	u16 code = 0;
	u16 code = usage->code;
	unsigned int real_fnmode;

	u16 fn_keycode = (swap_fn_leftctrl) ? (KEY_LEFTCTRL) : (KEY_FN);

	if (usage->code == fn_keycode) {
		asc->fn_on = !!value;
		input_event_with_scancode(input, usage->type, KEY_FN,
				usage->hid, value);
		return 1;
	}

	if (fnmode == 3) {
		real_fnmode = (asc->quirks & APPLE_IS_NON_APPLE) ? 2 : 1;
	} else {
		real_fnmode = fnmode;
	}

	if (swap_fn_leftctrl) {
		trans = apple_find_translation(swapped_fn_leftctrl_keys, code);

		if (trans)
			code = trans->to;
	}

	if (iso_layout > 0 || (iso_layout < 0 && (asc->quirks & APPLE_ISO_TILDE_QUIRK) &&
			hid->country == HID_COUNTRY_INTERNATIONAL_ISO)) {
		trans = apple_find_translation(apple_iso_keyboard, code);

		if (trans)
			code = trans->to;
	}

	if (swap_opt_cmd) {
		trans = apple_find_translation(swapped_option_cmd_keys, code);

		if (trans)
			code = trans->to;
	}

	if (swap_ctrl_cmd) {
		trans = apple_find_translation(swapped_ctrl_cmd_keys, code);

		if (trans)
			code = trans->to;
	}

	if (code == KEY_FN)
		asc->fn_on = !!value;

	if (real_fnmode) {
		if (hid->product == USB_DEVICE_ID_APPLE_ALU_WIRELESS_ANSI ||
		    hid->product == USB_DEVICE_ID_APPLE_ALU_WIRELESS_ISO ||
@@ -430,15 +468,18 @@ static int hidinput_apple_event(struct hid_device *hid, struct input_dev *input,
		else
			table = apple_fn_keys;

		trans = apple_find_translation (table, usage->code);
		trans = apple_find_translation(table, code);

		if (trans) {
			if (test_bit(trans->from, input->key))
			bool from_is_set = test_bit(trans->from, input->key);
			bool to_is_set = test_bit(trans->to, input->key);

			if (from_is_set)
				code = trans->from;
			else if (test_bit(trans->to, input->key))
			else if (to_is_set)
				code = trans->to;

			if (!code) {
			if (!(from_is_set || to_is_set)) {
				if (trans->flags & APPLE_FLAG_FKEY) {
					switch (real_fnmode) {
					case 1:
@@ -455,63 +496,32 @@ static int hidinput_apple_event(struct hid_device *hid, struct input_dev *input,
					do_translate = asc->fn_on;
				}

				code = do_translate ? trans->to : trans->from;
				if (do_translate)
					code = trans->to;
			}

			input_event_with_scancode(input, usage->type, code,
					usage->hid, value);
			return 1;
		}

		if (asc->quirks & APPLE_NUMLOCK_EMULATION &&
				(test_bit(usage->code, asc->pressed_numlock) ||
				(test_bit(code, asc->pressed_numlock) ||
				test_bit(LED_NUML, input->led))) {
			trans = apple_find_translation(powerbook_numlock_keys,
					usage->code);
			trans = apple_find_translation(powerbook_numlock_keys, code);

			if (trans) {
				if (value)
					set_bit(usage->code,
							asc->pressed_numlock);
					set_bit(code, asc->pressed_numlock);
				else
					clear_bit(usage->code,
							asc->pressed_numlock);
					clear_bit(code, asc->pressed_numlock);

				input_event_with_scancode(input, usage->type,
						trans->to, usage->hid, value);
				code = trans->to;
			}

			return 1;
		}
	}

	if (iso_layout > 0 || (iso_layout < 0 && (asc->quirks & APPLE_ISO_TILDE_QUIRK) &&
			hid->country == HID_COUNTRY_INTERNATIONAL_ISO)) {
		trans = apple_find_translation(apple_iso_keyboard, usage->code);
		if (trans) {
			input_event_with_scancode(input, usage->type,
					trans->to, usage->hid, value);
			return 1;
		}
	}
	if (usage->code != code) {
		input_event_with_scancode(input, usage->type, code, usage->hid, value);

	if (swap_opt_cmd) {
		trans = apple_find_translation(swapped_option_cmd_keys, usage->code);
		if (trans) {
			input_event_with_scancode(input, usage->type,
					trans->to, usage->hid, value);
		return 1;
	}
	}

	if (swap_fn_leftctrl) {
		trans = apple_find_translation(swapped_fn_leftctrl_keys, usage->code);
		if (trans) {
			input_event_with_scancode(input, usage->type,
					trans->to, usage->hid, value);
			return 1;
		}
	}

	return 0;
}
@@ -640,9 +650,6 @@ static void apple_setup_input(struct input_dev *input)
	apple_setup_key_translation(input, apple2021_fn_keys);
	apple_setup_key_translation(input, macbookpro_no_esc_fn_keys);
	apple_setup_key_translation(input, macbookpro_dedicated_esc_fn_keys);

	if (swap_fn_leftctrl)
		apple_setup_key_translation(input, swapped_fn_leftctrl_keys);
}

static int apple_input_mapping(struct hid_device *hdev, struct hid_input *hi,
@@ -1011,21 +1018,21 @@ static const struct hid_device_id apple_devices[] = {
	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING9_JIS),
		.driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS },
	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J140K),
		.driver_data = APPLE_HAS_FN | APPLE_BACKLIGHT_CTL },
		.driver_data = APPLE_HAS_FN | APPLE_BACKLIGHT_CTL | APPLE_ISO_TILDE_QUIRK },
	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J132),
		.driver_data = APPLE_HAS_FN | APPLE_BACKLIGHT_CTL },
		.driver_data = APPLE_HAS_FN | APPLE_BACKLIGHT_CTL | APPLE_ISO_TILDE_QUIRK },
	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J680),
		.driver_data = APPLE_HAS_FN | APPLE_BACKLIGHT_CTL },
		.driver_data = APPLE_HAS_FN | APPLE_BACKLIGHT_CTL | APPLE_ISO_TILDE_QUIRK },
	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J213),
		.driver_data = APPLE_HAS_FN | APPLE_BACKLIGHT_CTL },
		.driver_data = APPLE_HAS_FN | APPLE_BACKLIGHT_CTL | APPLE_ISO_TILDE_QUIRK },
	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J214K),
		.driver_data = APPLE_HAS_FN },
		.driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK },
	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J223),
		.driver_data = APPLE_HAS_FN },
		.driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK },
	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J230K),
		.driver_data = APPLE_HAS_FN },
		.driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK },
	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J152F),
		.driver_data = APPLE_HAS_FN },
		.driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK },
	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI),
		.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO),
+0 −6
Original line number Diff line number Diff line
@@ -507,11 +507,6 @@ static int elan_probe(struct hid_device *hdev, const struct hid_device_id *id)
	return ret;
}

static void elan_remove(struct hid_device *hdev)
{
	hid_hw_stop(hdev);
}

static const struct hid_device_id elan_devices[] = {
	{ HID_USB_DEVICE(USB_VENDOR_ID_ELAN, USB_DEVICE_ID_HP_X2),
	  .driver_data = ELAN_HAS_LED },
@@ -529,7 +524,6 @@ static struct hid_driver elan_driver = {
	.input_configured = elan_input_configured,
	.raw_event = elan_raw_event,
	.probe = elan_probe,
	.remove = elan_remove,
};

module_hid_driver(elan_driver);
+191 −134
Original line number Diff line number Diff line
@@ -30,12 +30,21 @@ MODULE_PARM_DESC(debug, "Toggle FT260 debugging messages");

#define FT260_REPORT_MAX_LENGTH (64)
#define FT260_I2C_DATA_REPORT_ID(len) (FT260_I2C_REPORT_MIN + (len - 1) / 4)

#define FT260_WAKEUP_NEEDED_AFTER_MS (4800) /* 5s minus 200ms margin */

/*
 * The input report format assigns 62 bytes for the data payload, but ft260
 * returns 60 and 2 in two separate transactions. To minimize transfer time
 * in reading chunks mode, set the maximum read payload length to 60 bytes.
 * The ft260 input report format defines 62 bytes for the data payload, but
 * when requested 62 bytes, the controller returns 60 and 2 in separate input
 * reports. To achieve better performance with the multi-report read data
 * transfers, we set the maximum read payload length to a multiple of 60.
 * With a 100 kHz I2C clock, one 240 bytes read takes about 1/27 second,
 * which is excessive; On the other hand, some higher layer drivers like at24
 * or optoe limit the i2c reads to 128 bytes. To not block other drivers out
 * of I2C for potentially troublesome amounts of time, we select the maximum
 * read payload length to be 180 bytes.
*/
#define FT260_RD_DATA_MAX (60)
#define FT260_RD_DATA_MAX (180)
#define FT260_WR_DATA_MAX (60)

/*
@@ -230,6 +239,7 @@ struct ft260_device {
	struct completion wait;
	struct mutex lock;
	u8 write_buf[FT260_REPORT_MAX_LENGTH];
	unsigned long need_wakeup_at;
	u8 *read_buf;
	u16 read_idx;
	u16 read_len;
@@ -293,12 +303,26 @@ static int ft260_i2c_reset(struct hid_device *hdev)
	return ret;
}

static int ft260_xfer_status(struct ft260_device *dev)
static int ft260_xfer_status(struct ft260_device *dev, u8 bus_busy)
{
	struct hid_device *hdev = dev->hdev;
	struct ft260_get_i2c_status_report report;
	int ret;

	if (time_is_before_jiffies(dev->need_wakeup_at)) {
		ret = ft260_hid_feature_report_get(hdev, FT260_I2C_STATUS,
						(u8 *)&report, sizeof(report));
		if (unlikely(ret < 0)) {
			hid_err(hdev, "failed to retrieve status: %d, no wakeup\n",
				ret);
		} else {
			dev->need_wakeup_at = jiffies +
				msecs_to_jiffies(FT260_WAKEUP_NEEDED_AFTER_MS);
			ft260_dbg("bus_status %#02x, wakeup\n",
				  report.bus_status);
		}
	}

	ret = ft260_hid_feature_report_get(hdev, FT260_I2C_STATUS,
					   (u8 *)&report, sizeof(report));
	if (unlikely(ret < 0)) {
@@ -310,30 +334,20 @@ static int ft260_xfer_status(struct ft260_device *dev)
	ft260_dbg("bus_status %#02x, clock %u\n", report.bus_status,
		  dev->clock);

	if (report.bus_status & FT260_I2C_STATUS_CTRL_BUSY)
	if (report.bus_status & (FT260_I2C_STATUS_CTRL_BUSY | bus_busy))
		return -EAGAIN;

	if (report.bus_status & FT260_I2C_STATUS_BUS_BUSY)
		return -EBUSY;

	if (report.bus_status & FT260_I2C_STATUS_ERROR)
	/*
	 * The error condition (bit 1) is a status bit reflecting any
	 * error conditions. When any of the bits 2, 3, or 4 are raised
	 * to 1, bit 1 is also set to 1.
	 */
	if (report.bus_status & FT260_I2C_STATUS_ERROR) {
		hid_err(hdev, "i2c bus error: %#02x\n", report.bus_status);
		return -EIO;
	}

	ret = -EIO;

	if (report.bus_status & FT260_I2C_STATUS_ADDR_NO_ACK)
		ft260_dbg("unacknowledged address\n");

	if (report.bus_status & FT260_I2C_STATUS_DATA_NO_ACK)
		ft260_dbg("unacknowledged data\n");

	if (report.bus_status & FT260_I2C_STATUS_ARBITR_LOST)
		ft260_dbg("arbitration loss\n");

	if (report.bus_status & FT260_I2C_STATUS_CTRL_IDLE)
		ret = 0;

	return ret;
	return 0;
}

static int ft260_hid_output_report(struct hid_device *hdev, u8 *data,
@@ -355,8 +369,11 @@ static int ft260_hid_output_report(struct hid_device *hdev, u8 *data,
static int ft260_hid_output_report_check_status(struct ft260_device *dev,
						u8 *data, int len)
{
	int ret, usec, try = 3;
	u8 bus_busy;
	int ret, usec, try = 100;
	struct hid_device *hdev = dev->hdev;
	struct ft260_i2c_write_request_report *rep =
		(struct ft260_i2c_write_request_report *)data;

	ret = ft260_hid_output_report(hdev, data, len);
	if (ret < 0) {
@@ -366,17 +383,31 @@ static int ft260_hid_output_report_check_status(struct ft260_device *dev,
		return ret;
	}

	/* transfer time = 1 / clock(KHz) * 10 bits * bytes */
	usec = 10000 / dev->clock * len;
	/* transfer time = 1 / clock(KHz) * 9 bits * bytes */
	usec = len * 9000 / dev->clock;
	if (usec > 2000) {
		usec -= 1500;
		usleep_range(usec, usec + 100);
		ft260_dbg("wait %d usec, len %d\n", usec, len);
	}

	/*
	 * Do not check the busy bit for combined transactions
	 * since the controller keeps the bus busy between writing
	 * and reading IOs to ensure an atomic operation.
	 */
	if (rep->flag == FT260_FLAG_START)
		bus_busy = 0;
	else
		bus_busy = FT260_I2C_STATUS_BUS_BUSY;

	do {
		ret = ft260_xfer_status(dev);
		ret = ft260_xfer_status(dev, bus_busy);
		if (ret != -EAGAIN)
			break;
	} while (--try);

	if (ret == 0 || ret == -EBUSY)
	if (ret == 0)
		return 0;

	ft260_i2c_reset(hdev);
@@ -384,41 +415,49 @@ static int ft260_hid_output_report_check_status(struct ft260_device *dev,
}

static int ft260_i2c_write(struct ft260_device *dev, u8 addr, u8 *data,
			   int data_len, u8 flag)
			   int len, u8 flag)
{
	int len, ret, idx = 0;
	int ret, wr_len, idx = 0;
	struct hid_device *hdev = dev->hdev;
	struct ft260_i2c_write_request_report *rep =
		(struct ft260_i2c_write_request_report *)dev->write_buf;

	if (len < 1)
		return -EINVAL;

	rep->flag = FT260_FLAG_START;

	do {
		if (data_len <= FT260_WR_DATA_MAX)
			len = data_len;
		else
			len = FT260_WR_DATA_MAX;
		if (len <= FT260_WR_DATA_MAX) {
			wr_len = len;
			if (flag == FT260_FLAG_START_STOP)
				rep->flag |= FT260_FLAG_STOP;
		} else {
			wr_len = FT260_WR_DATA_MAX;
		}

		rep->report = FT260_I2C_DATA_REPORT_ID(len);
		rep->report = FT260_I2C_DATA_REPORT_ID(wr_len);
		rep->address = addr;
		rep->length = len;
		rep->flag = flag;
		rep->length = wr_len;

		memcpy(rep->data, &data[idx], len);
		memcpy(rep->data, &data[idx], wr_len);

		ft260_dbg("rep %#02x addr %#02x off %d len %d d[0] %#02x\n",
			  rep->report, addr, idx, len, data[0]);
		ft260_dbg("rep %#02x addr %#02x off %d len %d wlen %d flag %#x d[0] %#02x\n",
			  rep->report, addr, idx, len, wr_len,
			  rep->flag, data[0]);

		ret = ft260_hid_output_report_check_status(dev, (u8 *)rep,
							   len + 4);
							   wr_len + 4);
		if (ret < 0) {
			hid_err(hdev, "%s: failed to start transfer, ret %d\n",
				__func__, ret);
			hid_err(hdev, "%s: failed with %d\n", __func__, ret);
			return ret;
		}

		data_len -= len;
		idx += len;
		len -= wr_len;
		idx += wr_len;
		rep->flag = 0;

	} while (data_len > 0);
	} while (len > 0);

	return 0;
}
@@ -457,49 +496,74 @@ static int ft260_smbus_write(struct ft260_device *dev, u8 addr, u8 cmd,
static int ft260_i2c_read(struct ft260_device *dev, u8 addr, u8 *data,
			  u16 len, u8 flag)
{
	u16 rd_len;
	u16 rd_data_max = 60;
	int timeout, ret = 0;
	struct ft260_i2c_read_request_report rep;
	struct hid_device *hdev = dev->hdev;
	int timeout;
	int ret;
	u8 bus_busy = 0;

	if (len > FT260_RD_DATA_MAX) {
		hid_err(hdev, "%s: unsupported rd len: %d\n", __func__, len);
		return -EINVAL;
	if ((flag & FT260_FLAG_START_REPEATED) == FT260_FLAG_START_REPEATED)
		flag = FT260_FLAG_START_REPEATED;
	else
		flag = FT260_FLAG_START;
	do {
		if (len <= rd_data_max) {
			rd_len = len;
			flag |= FT260_FLAG_STOP;
		} else {
			rd_len = rd_data_max;
		}

	dev->read_idx = 0;
	dev->read_buf = data;
	dev->read_len = len;
		rd_data_max = FT260_RD_DATA_MAX;

		rep.report = FT260_I2C_READ_REQ;
	rep.length = cpu_to_le16(len);
		rep.length = cpu_to_le16(rd_len);
		rep.address = addr;
		rep.flag = flag;

	ft260_dbg("rep %#02x addr %#02x len %d\n", rep.report, rep.address,
		  rep.length);
		ft260_dbg("rep %#02x addr %#02x len %d rlen %d flag %#x\n",
			  rep.report, rep.address, len, rd_len, flag);

		reinit_completion(&dev->wait);

		dev->read_idx = 0;
		dev->read_buf = data;
		dev->read_len = rd_len;

		ret = ft260_hid_output_report(hdev, (u8 *)&rep, sizeof(rep));
		if (ret < 0) {
		hid_err(hdev, "%s: failed to start transaction, ret %d\n",
			__func__, ret);
		return ret;
			hid_err(hdev, "%s: failed with %d\n", __func__, ret);
			goto ft260_i2c_read_exit;
		}

		timeout = msecs_to_jiffies(5000);
		if (!wait_for_completion_timeout(&dev->wait, timeout)) {
			ret = -ETIMEDOUT;
			ft260_i2c_reset(hdev);
		return -ETIMEDOUT;
			goto ft260_i2c_read_exit;
		}

	ret = ft260_xfer_status(dev);
	if (ret == 0)
		return 0;
		dev->read_buf = NULL;

		if (flag & FT260_FLAG_STOP)
			bus_busy = FT260_I2C_STATUS_BUS_BUSY;

		ret = ft260_xfer_status(dev, bus_busy);
		if (ret < 0) {
			ret = -EIO;
			ft260_i2c_reset(hdev);
	return -EIO;
			goto ft260_i2c_read_exit;
		}

		len -= rd_len;
		data += rd_len;
		flag = 0;

	} while (len > 0);

ft260_i2c_read_exit:
	dev->read_buf = NULL;
	return ret;
}

/*
@@ -510,46 +574,38 @@ static int ft260_i2c_read(struct ft260_device *dev, u8 addr, u8 *data,
 */
static int ft260_i2c_write_read(struct ft260_device *dev, struct i2c_msg *msgs)
{
	int len, ret;
	u16 left_len = msgs[1].len;
	u8 *read_buf = msgs[1].buf;
	int ret;
	int wr_len = msgs[0].len;
	int rd_len = msgs[1].len;
	struct hid_device *hdev = dev->hdev;
	u8 addr = msgs[0].addr;
	u16 read_off = 0;
	struct hid_device *hdev = dev->hdev;

	if (msgs[0].len > 2) {
		hid_err(hdev, "%s: unsupported wr len: %d\n", __func__,
			msgs[0].len);
	if (wr_len > 2) {
		hid_err(hdev, "%s: invalid wr_len: %d\n", __func__, wr_len);
		return -EOPNOTSUPP;
	}

	memcpy(&read_off, msgs[0].buf, msgs[0].len);

	do {
		if (left_len <= FT260_RD_DATA_MAX)
			len = left_len;
	if (ft260_debug) {
		if (wr_len == 2)
			read_off = be16_to_cpu(*(__be16 *)msgs[0].buf);
		else
			len = FT260_RD_DATA_MAX;
			read_off = *msgs[0].buf;

		ft260_dbg("read_off %#x left_len %d len %d\n", read_off,
			  left_len, len);
		pr_info("%s: off %#x rlen %d wlen %d\n", __func__,
			read_off, rd_len, wr_len);
	}

		ret = ft260_i2c_write(dev, addr, (u8 *)&read_off, msgs[0].len,
	ret = ft260_i2c_write(dev, addr, msgs[0].buf, wr_len,
			      FT260_FLAG_START);
	if (ret < 0)
		return ret;

		ret = ft260_i2c_read(dev, addr, read_buf, len,
				     FT260_FLAG_START_STOP);
	ret = ft260_i2c_read(dev, addr, msgs[1].buf, rd_len,
			     FT260_FLAG_START_STOP_REPEATED);
	if (ret < 0)
		return ret;

		left_len -= len;
		read_buf += len;
		read_off += len;

	} while (left_len > 0);

	return 0;
}

@@ -613,14 +669,6 @@ static int ft260_smbus_xfer(struct i2c_adapter *adapter, u16 addr, u16 flags,
	}

	switch (size) {
	case I2C_SMBUS_QUICK:
		if (read_write == I2C_SMBUS_READ)
			ret = ft260_i2c_read(dev, addr, &data->byte, 0,
					     FT260_FLAG_START_STOP);
		else
			ret = ft260_smbus_write(dev, addr, cmd, NULL, 0,
						FT260_FLAG_START_STOP);
		break;
	case I2C_SMBUS_BYTE:
		if (read_write == I2C_SMBUS_READ)
			ret = ft260_i2c_read(dev, addr, &data->byte, 1,
@@ -703,7 +751,7 @@ static int ft260_smbus_xfer(struct i2c_adapter *adapter, u16 addr, u16 flags,

static u32 ft260_functionality(struct i2c_adapter *adap)
{
	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_BYTE | I2C_FUNC_SMBUS_QUICK |
	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_BYTE |
	       I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
	       I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_SMBUS_I2C_BLOCK;
}
@@ -782,7 +830,7 @@ static int ft260_byte_show(struct hid_device *hdev, int id, u8 *cfg, int len,
}

static int ft260_word_show(struct hid_device *hdev, int id, u8 *cfg, int len,
			   u16 *field, u8 *buf)
			   __le16 *field, u8 *buf)
{
	int ret;

@@ -811,9 +859,9 @@ static int ft260_word_show(struct hid_device *hdev, int id, u8 *cfg, int len,

#define FT260_I2CST_ATTR_SHOW(name)					       \
		FT260_ATTR_SHOW(name, ft260_get_i2c_status_report,	       \
				FT260_I2C_STATUS, u16, ft260_word_show)
				FT260_I2C_STATUS, __le16, ft260_word_show)

#define FT260_ATTR_STORE(name, reptype, id, req, type, func)		       \
#define FT260_ATTR_STORE(name, reptype, id, req, type, ctype, func)	       \
	static ssize_t name##_store(struct device *kdev,		       \
				    struct device_attribute *attr,	       \
				    const char *buf, size_t count)	       \
@@ -823,7 +871,7 @@ static int ft260_word_show(struct hid_device *hdev, int id, u8 *cfg, int len,
		type name;						       \
		int ret;						       \
									       \
		if (!func(buf, 10, &name)) {				       \
		if (!func(buf, 10, (ctype *)&name)) {			       \
			rep.name = name;				       \
			rep.report = id;				       \
			rep.request = req;				       \
@@ -839,11 +887,11 @@ static int ft260_word_show(struct hid_device *hdev, int id, u8 *cfg, int len,

#define FT260_BYTE_ATTR_STORE(name, reptype, req)			       \
		FT260_ATTR_STORE(name, reptype, FT260_SYSTEM_SETTINGS, req,    \
				 u8, kstrtou8)
				 u8, u8, kstrtou8)

#define FT260_WORD_ATTR_STORE(name, reptype, req)			       \
		FT260_ATTR_STORE(name, reptype, FT260_SYSTEM_SETTINGS, req,    \
				 u16, kstrtou16)
				 __le16, u16, kstrtou16)

FT260_SSTAT_ATTR_SHOW(chip_mode);
static DEVICE_ATTR_RO(chip_mode);
@@ -928,7 +976,7 @@ static int ft260_probe(struct hid_device *hdev, const struct hid_device_id *id)
		return ret;
	}

	ret = hid_hw_start(hdev, HID_CONNECT_HIDRAW);
	ret = hid_hw_start(hdev, 0);
	if (ret) {
		hid_err(hdev, "failed to start HID HW\n");
		return ret;
@@ -955,6 +1003,10 @@ static int ft260_probe(struct hid_device *hdev, const struct hid_device_id *id)
	if (ret <= 0)
		goto err_hid_close;

	hid_info(hdev, "USB HID v%x.%02x Device [%s] on %s\n",
		hdev->version >> 8, hdev->version & 0xff, hdev->name,
		hdev->phys);

	hid_set_drvdata(hdev, dev);
	dev->hdev = hdev;
	dev->adap.owner = THIS_MODULE;
@@ -963,13 +1015,12 @@ static int ft260_probe(struct hid_device *hdev, const struct hid_device_id *id)
	dev->adap.quirks = &ft260_i2c_quirks;
	dev->adap.dev.parent = &hdev->dev;
	snprintf(dev->adap.name, sizeof(dev->adap.name),
		 "FT260 usb-i2c bridge on hidraw%d",
		 ((struct hidraw *)hdev->hidraw)->minor);
		 "FT260 usb-i2c bridge");

	mutex_init(&dev->lock);
	init_completion(&dev->wait);

	ret = ft260_xfer_status(dev);
	ret = ft260_xfer_status(dev, FT260_I2C_STATUS_BUS_BUSY);
	if (ret)
		ft260_i2c_reset(hdev);

@@ -1022,6 +1073,13 @@ static int ft260_raw_event(struct hid_device *hdev, struct hid_report *report,
		ft260_dbg("i2c resp: rep %#02x len %d\n", xfer->report,
			  xfer->length);

		if ((dev->read_buf == NULL) ||
		    (xfer->length > dev->read_len - dev->read_idx)) {
			hid_err(hdev, "unexpected report %#02x, length %d\n",
				xfer->report, xfer->length);
			return -1;
		}

		memcpy(&dev->read_buf[dev->read_idx], &xfer->data,
		       xfer->length);
		dev->read_idx += xfer->length;
@@ -1030,10 +1088,9 @@ static int ft260_raw_event(struct hid_device *hdev, struct hid_report *report,
			complete(&dev->wait);

	} else {
		hid_err(hdev, "unknown report: %#02x\n", xfer->report);
		return 0;
		hid_err(hdev, "unhandled report %#02x\n", xfer->report);
	}
	return 1;
	return 0;
}

static struct hid_driver ft260_driver = {
Loading