Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input

Pull input updates from Dmitry Torokhov:

 - a new driver for SparkFun Qwiic Joystick

 - pm8941-pwrkey driver now supports PMK8350

 - a bunch of assorted driver fixes

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input: (44 commits)
  Input: joydev - prevent use of not validated data in JSIOCSBTNMAP ioctl
  Input: hideep - fix the uninitialized use in hideep_nvm_unlock()
  Input: trackpoint - use kobj_to_dev()
  Input: atkbd - use kobj_to_dev()
  Input: tsc200x-core - use kobj_to_dev()
  Input: ims-pcu - use kobj_to_dev()
  Input: cros_ec_keyb - use kobj_to_dev() API
  dt-bindings: input: touchscreen: st1232: Convert to json-schema
  Input: i8042 - fix typos in comments
  Input: add SparkFun Qwiic Joystick driver
  dt-bindings: Add vendor prefix and bindings for Qwiic Joystick
  Input: cy8ctmg110_ts - switch to using gpiod API
  Input: cy8ctmg110_ts - switch to using managed resources
  Input: cy8ctmg110_ts - use endian helpers when converting data on wire
  Input: cy8ctmg110_ts - let I2C core configure wake interrupt
  Input: cy8ctmg110_ts - do not hardcode as wakeup source
  Input: cy8ctmg110_ts - do not hard code interrupt trigger
  Input: cy8ctmg110_ts - rely on platform code to supply interrupt
  Input: resistive-adc-touch - fix uninitialized variable 'press'
  Input: pm8941-pwrkey - add support for PMK8350 PON_HLOS PMIC peripheral
  ...
This commit is contained in:
Linus Torvalds
2021-07-05 11:42:45 -07:00
39 changed files with 834 additions and 392 deletions

View File

@@ -7,9 +7,6 @@
* Input driver event debug module - dumps all events into syslog
*/
/*
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/slab.h>

View File

@@ -499,7 +499,7 @@ static int joydev_handle_JSIOCSBTNMAP(struct joydev *joydev,
memcpy(joydev->keypam, keypam, len);
for (i = 0; i < joydev->nkey; i++)
joydev->keymap[keypam[i] - BTN_MISC] = i;
joydev->keymap[joydev->keypam[i] - BTN_MISC] = i;
out:
kfree(keypam);

View File

@@ -372,6 +372,15 @@ config JOYSTICK_PXRC
To compile this driver as a module, choose M here: the
module will be called pxrc.
config JOYSTICK_QWIIC
tristate "SparkFun Qwiic Joystick"
depends on I2C
help
Say Y here if you want to use the SparkFun Qwiic Joystick.
To compile this driver as a module, choose M here: the
module will be called qwiic-joystick.
config JOYSTICK_FSIA6B
tristate "FlySky FS-iA6B RC Receiver"
select SERIO

View File

@@ -27,6 +27,7 @@ obj-$(CONFIG_JOYSTICK_MAPLE) += maplecontrol.o
obj-$(CONFIG_JOYSTICK_N64) += n64joy.o
obj-$(CONFIG_JOYSTICK_PSXPAD_SPI) += psxpad-spi.o
obj-$(CONFIG_JOYSTICK_PXRC) += pxrc.o
obj-$(CONFIG_JOYSTICK_QWIIC) += qwiic-joystick.o
obj-$(CONFIG_JOYSTICK_SIDEWINDER) += sidewinder.o
obj-$(CONFIG_JOYSTICK_SPACEBALL) += spaceball.o
obj-$(CONFIG_JOYSTICK_SPACEORB) += spaceorb.o

View File

@@ -0,0 +1,146 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2021 Oleh Kravchenko <oleg@kaa.org.ua>
*
* SparkFun Qwiic Joystick
* Product page:https://www.sparkfun.com/products/15168
* Firmware and hardware sources:https://github.com/sparkfun/Qwiic_Joystick
*/
#include <linux/bits.h>
#include <linux/i2c.h>
#include <linux/input.h>
#include <linux/kernel.h>
#include <linux/module.h>
#define DRV_NAME "qwiic-joystick"
#define QWIIC_JSK_REG_VERS 1
#define QWIIC_JSK_REG_DATA 3
#define QWIIC_JSK_MAX_AXIS GENMASK(9, 0)
#define QWIIC_JSK_FUZZ 2
#define QWIIC_JSK_FLAT 2
#define QWIIC_JSK_POLL_INTERVAL 16
#define QWIIC_JSK_POLL_MIN 8
#define QWIIC_JSK_POLL_MAX 32
struct qwiic_jsk {
char phys[32];
struct input_dev *dev;
struct i2c_client *client;
};
struct qwiic_ver {
u8 major;
u8 minor;
};
struct qwiic_data {
__be16 x;
__be16 y;
u8 thumb;
};
static void qwiic_poll(struct input_dev *input)
{
struct qwiic_jsk *priv = input_get_drvdata(input);
struct qwiic_data data;
int err;
err = i2c_smbus_read_i2c_block_data(priv->client, QWIIC_JSK_REG_DATA,
sizeof(data), (u8 *)&data);
if (err != sizeof(data))
return;
input_report_abs(input, ABS_X, be16_to_cpu(data.x) >> 6);
input_report_abs(input, ABS_Y, be16_to_cpu(data.y) >> 6);
input_report_key(input, BTN_THUMBL, !data.thumb);
input_sync(input);
}
static int qwiic_probe(struct i2c_client *client)
{
struct qwiic_jsk *priv;
struct qwiic_ver vers;
int err;
err = i2c_smbus_read_i2c_block_data(client, QWIIC_JSK_REG_VERS,
sizeof(vers), (u8 *)&vers);
if (err < 0)
return err;
if (err != sizeof(vers))
return -EIO;
dev_dbg(&client->dev, "SparkFun Qwiic Joystick, FW: %u.%u\n",
vers.major, vers.minor);
priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
priv->client = client;
snprintf(priv->phys, sizeof(priv->phys),
"i2c/%s", dev_name(&client->dev));
i2c_set_clientdata(client, priv);
priv->dev = devm_input_allocate_device(&client->dev);
if (!priv->dev)
return -ENOMEM;
priv->dev->id.bustype = BUS_I2C;
priv->dev->name = "SparkFun Qwiic Joystick";
priv->dev->phys = priv->phys;
input_set_drvdata(priv->dev, priv);
input_set_abs_params(priv->dev, ABS_X, 0, QWIIC_JSK_MAX_AXIS,
QWIIC_JSK_FUZZ, QWIIC_JSK_FLAT);
input_set_abs_params(priv->dev, ABS_Y, 0, QWIIC_JSK_MAX_AXIS,
QWIIC_JSK_FUZZ, QWIIC_JSK_FLAT);
input_set_capability(priv->dev, EV_KEY, BTN_THUMBL);
err = input_setup_polling(priv->dev, qwiic_poll);
if (err) {
dev_err(&client->dev, "failed to set up polling: %d\n", err);
return err;
}
input_set_poll_interval(priv->dev, QWIIC_JSK_POLL_INTERVAL);
input_set_min_poll_interval(priv->dev, QWIIC_JSK_POLL_MIN);
input_set_max_poll_interval(priv->dev, QWIIC_JSK_POLL_MAX);
err = input_register_device(priv->dev);
if (err) {
dev_err(&client->dev, "failed to register joystick: %d\n", err);
return err;
}
return 0;
}
#ifdef CONFIG_OF
static const struct of_device_id of_qwiic_match[] = {
{ .compatible = "sparkfun,qwiic-joystick", },
{ },
};
MODULE_DEVICE_TABLE(of, of_qwiic_match);
#endif /* CONFIG_OF */
static const struct i2c_device_id qwiic_id_table[] = {
{ KBUILD_MODNAME, 0 },
{ },
};
MODULE_DEVICE_TABLE(i2c, qwiic_id_table);
static struct i2c_driver qwiic_driver = {
.driver = {
.name = DRV_NAME,
.of_match_table = of_match_ptr(of_qwiic_match),
},
.id_table = qwiic_id_table,
.probe_new = qwiic_probe,
};
module_i2c_driver(qwiic_driver);
MODULE_AUTHOR("Oleh Kravchenko <oleg@kaa.org.ua>");
MODULE_DESCRIPTION("SparkFun Qwiic Joystick driver");
MODULE_LICENSE("GPL v2");

View File

@@ -79,6 +79,7 @@
#define MAP_DPAD_TO_BUTTONS (1 << 0)
#define MAP_TRIGGERS_TO_BUTTONS (1 << 1)
#define MAP_STICKS_TO_NULL (1 << 2)
#define MAP_SELECT_BUTTON (1 << 3)
#define DANCEPAD_MAP_CONFIG (MAP_DPAD_TO_BUTTONS | \
MAP_TRIGGERS_TO_BUTTONS | MAP_STICKS_TO_NULL)
@@ -130,6 +131,7 @@ static const struct xpad_device {
{ 0x045e, 0x02e3, "Microsoft X-Box One Elite pad", 0, XTYPE_XBOXONE },
{ 0x045e, 0x02ea, "Microsoft X-Box One S pad", 0, XTYPE_XBOXONE },
{ 0x045e, 0x0719, "Xbox 360 Wireless Receiver", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360W },
{ 0x045e, 0x0b12, "Microsoft Xbox One X pad", MAP_SELECT_BUTTON, XTYPE_XBOXONE },
{ 0x046d, 0xc21d, "Logitech Gamepad F310", 0, XTYPE_XBOX360 },
{ 0x046d, 0xc21e, "Logitech Gamepad F510", 0, XTYPE_XBOX360 },
{ 0x046d, 0xc21f, "Logitech Gamepad F710", 0, XTYPE_XBOX360 },
@@ -864,6 +866,8 @@ static void xpadone_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char
/* menu/view buttons */
input_report_key(dev, BTN_START, data[4] & 0x04);
input_report_key(dev, BTN_SELECT, data[4] & 0x08);
if (xpad->mapping & MAP_SELECT_BUTTON)
input_report_key(dev, KEY_RECORD, data[22] & 0x01);
/* buttons A,B,X,Y */
input_report_key(dev, BTN_A, data[4] & 0x10);
@@ -1674,6 +1678,8 @@ static int xpad_init_input(struct usb_xpad *xpad)
xpad->xtype == XTYPE_XBOXONE) {
for (i = 0; xpad360_btn[i] >= 0; i++)
input_set_capability(input_dev, EV_KEY, xpad360_btn[i]);
if (xpad->mapping & MAP_SELECT_BUTTON)
input_set_capability(input_dev, EV_KEY, KEY_RECORD);
} else {
for (i = 0; xpad_btn[i] >= 0; i++)
input_set_capability(input_dev, EV_KEY, xpad_btn[i]);

View File

@@ -324,7 +324,7 @@ static ssize_t atkbd_show_function_row_physmap(struct atkbd *atkbd, char *buf)
static umode_t atkbd_attr_is_visible(struct kobject *kobj,
struct attribute *attr, int i)
{
struct device *dev = container_of(kobj, struct device, kobj);
struct device *dev = kobj_to_dev(kobj);
struct serio *serio = to_serio_port(dev);
struct atkbd *atkbd = serio_get_drvdata(serio);

View File

@@ -644,7 +644,7 @@ static umode_t cros_ec_keyb_attr_is_visible(struct kobject *kobj,
struct attribute *attr,
int n)
{
struct device *dev = container_of(kobj, struct device, kobj);
struct device *dev = kobj_to_dev(kobj);
struct cros_ec_keyb *ckdev = dev_get_drvdata(dev);
if (attr == &dev_attr_function_row_physmap.attr &&

View File

@@ -512,6 +512,7 @@ static int hil_dev_connect(struct serio *serio, struct serio_driver *drv)
HIL_IDD_NUM_AXES_PER_SET(*idd)) {
printk(KERN_INFO PREFIX
"combo devices are not supported.\n");
error = -EINVAL;
goto bail1;
}

View File

@@ -647,8 +647,8 @@ static int __ims_pcu_execute_command(struct ims_pcu *pcu,
#define IMS_PCU_BL_DATA_OFFSET 3
static int __ims_pcu_execute_bl_command(struct ims_pcu *pcu,
u8 command, const void *data, size_t len,
u8 expected_response, int response_time)
u8 command, const void *data, size_t len,
u8 expected_response, int response_time)
{
int error;
@@ -1228,7 +1228,7 @@ static struct attribute *ims_pcu_attrs[] = {
static umode_t ims_pcu_is_attr_visible(struct kobject *kobj,
struct attribute *attr, int n)
{
struct device *dev = container_of(kobj, struct device, kobj);
struct device *dev = kobj_to_dev(kobj);
struct usb_interface *intf = to_usb_interface(dev);
struct ims_pcu *pcu = usb_get_intfdata(intf);
umode_t mode = attr->mode;

View File

@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
* Copyright (c) 2010-2011, 2020-2021, The Linux Foundation. All rights reserved.
* Copyright (c) 2014, Sony Mobile Communications Inc.
*/
@@ -22,6 +22,8 @@
#define PON_RT_STS 0x10
#define PON_KPDPWR_N_SET BIT(0)
#define PON_RESIN_N_SET BIT(1)
#define PON_GEN3_RESIN_N_SET BIT(6)
#define PON_GEN3_KPDPWR_N_SET BIT(7)
#define PON_PS_HOLD_RST_CTL 0x5a
#define PON_PS_HOLD_RST_CTL2 0x5b
@@ -38,8 +40,12 @@
#define PON_DBC_DELAY_MASK 0x7
struct pm8941_data {
unsigned int pull_up_bit;
unsigned int status_bit;
unsigned int pull_up_bit;
unsigned int status_bit;
bool supports_ps_hold_poff_config;
bool supports_debounce_config;
const char *name;
const char *phys;
};
struct pm8941_pwrkey {
@@ -231,34 +237,40 @@ static int pm8941_pwrkey_probe(struct platform_device *pdev)
input_set_capability(pwrkey->input, EV_KEY, pwrkey->code);
pwrkey->input->name = "pm8941_pwrkey";
pwrkey->input->phys = "pm8941_pwrkey/input0";
pwrkey->input->name = pwrkey->data->name;
pwrkey->input->phys = pwrkey->data->phys;
req_delay = (req_delay << 6) / USEC_PER_SEC;
req_delay = ilog2(req_delay);
if (pwrkey->data->supports_debounce_config) {
req_delay = (req_delay << 6) / USEC_PER_SEC;
req_delay = ilog2(req_delay);
error = regmap_update_bits(pwrkey->regmap,
pwrkey->baseaddr + PON_DBC_CTL,
PON_DBC_DELAY_MASK,
req_delay);
if (error) {
dev_err(&pdev->dev, "failed to set debounce: %d\n", error);
return error;
error = regmap_update_bits(pwrkey->regmap,
pwrkey->baseaddr + PON_DBC_CTL,
PON_DBC_DELAY_MASK,
req_delay);
if (error) {
dev_err(&pdev->dev, "failed to set debounce: %d\n",
error);
return error;
}
}
error = regmap_update_bits(pwrkey->regmap,
pwrkey->baseaddr + PON_PULL_CTL,
pwrkey->data->pull_up_bit,
pull_up ? pwrkey->data->pull_up_bit : 0);
if (error) {
dev_err(&pdev->dev, "failed to set pull: %d\n", error);
return error;
if (pwrkey->data->pull_up_bit) {
error = regmap_update_bits(pwrkey->regmap,
pwrkey->baseaddr + PON_PULL_CTL,
pwrkey->data->pull_up_bit,
pull_up ? pwrkey->data->pull_up_bit :
0);
if (error) {
dev_err(&pdev->dev, "failed to set pull: %d\n", error);
return error;
}
}
error = devm_request_threaded_irq(&pdev->dev, pwrkey->irq,
NULL, pm8941_pwrkey_irq,
IRQF_ONESHOT,
"pm8941_pwrkey", pwrkey);
pwrkey->data->name, pwrkey);
if (error) {
dev_err(&pdev->dev, "failed requesting IRQ: %d\n", error);
return error;
@@ -271,12 +283,14 @@ static int pm8941_pwrkey_probe(struct platform_device *pdev)
return error;
}
pwrkey->reboot_notifier.notifier_call = pm8941_reboot_notify,
error = register_reboot_notifier(&pwrkey->reboot_notifier);
if (error) {
dev_err(&pdev->dev, "failed to register reboot notifier: %d\n",
error);
return error;
if (pwrkey->data->supports_ps_hold_poff_config) {
pwrkey->reboot_notifier.notifier_call = pm8941_reboot_notify,
error = register_reboot_notifier(&pwrkey->reboot_notifier);
if (error) {
dev_err(&pdev->dev, "failed to register reboot notifier: %d\n",
error);
return error;
}
}
platform_set_drvdata(pdev, pwrkey);
@@ -289,7 +303,8 @@ static int pm8941_pwrkey_remove(struct platform_device *pdev)
{
struct pm8941_pwrkey *pwrkey = platform_get_drvdata(pdev);
unregister_reboot_notifier(&pwrkey->reboot_notifier);
if (pwrkey->data->supports_ps_hold_poff_config)
unregister_reboot_notifier(&pwrkey->reboot_notifier);
return 0;
}
@@ -297,16 +312,42 @@ static int pm8941_pwrkey_remove(struct platform_device *pdev)
static const struct pm8941_data pwrkey_data = {
.pull_up_bit = PON_KPDPWR_PULL_UP,
.status_bit = PON_KPDPWR_N_SET,
.name = "pm8941_pwrkey",
.phys = "pm8941_pwrkey/input0",
.supports_ps_hold_poff_config = true,
.supports_debounce_config = true,
};
static const struct pm8941_data resin_data = {
.pull_up_bit = PON_RESIN_PULL_UP,
.status_bit = PON_RESIN_N_SET,
.name = "pm8941_resin",
.phys = "pm8941_resin/input0",
.supports_ps_hold_poff_config = true,
.supports_debounce_config = true,
};
static const struct pm8941_data pon_gen3_pwrkey_data = {
.status_bit = PON_GEN3_KPDPWR_N_SET,
.name = "pmic_pwrkey",
.phys = "pmic_pwrkey/input0",
.supports_ps_hold_poff_config = false,
.supports_debounce_config = false,
};
static const struct pm8941_data pon_gen3_resin_data = {
.status_bit = PON_GEN3_RESIN_N_SET,
.name = "pmic_resin",
.phys = "pmic_resin/input0",
.supports_ps_hold_poff_config = false,
.supports_debounce_config = false,
};
static const struct of_device_id pm8941_pwr_key_id_table[] = {
{ .compatible = "qcom,pm8941-pwrkey", .data = &pwrkey_data },
{ .compatible = "qcom,pm8941-resin", .data = &resin_data },
{ .compatible = "qcom,pmk8350-pwrkey", .data = &pon_gen3_pwrkey_data },
{ .compatible = "qcom,pmk8350-resin", .data = &pon_gen3_resin_data },
{ }
};
MODULE_DEVICE_TABLE(of, pm8941_pwr_key_id_table);

View File

@@ -214,7 +214,7 @@ static bool trackpoint_is_attr_available(struct psmouse *psmouse,
static umode_t trackpoint_is_attr_visible(struct kobject *kobj,
struct attribute *attr, int n)
{
struct device *dev = container_of(kobj, struct device, kobj);
struct device *dev = kobj_to_dev(kobj);
struct serio *serio = to_serio_port(dev);
struct psmouse *psmouse = serio_get_drvdata(serio);

View File

@@ -139,7 +139,7 @@ static DEFINE_SPINLOCK(i8042_lock);
/*
* Writers to AUX and KBD ports as well as users issuing i8042_command
* directly should acquire i8042_mutex (by means of calling
* i8042_lock_chip() and i8042_unlock_ship() helpers) to ensure that
* i8042_lock_chip() and i8042_unlock_chip() helpers) to ensure that
* they do not disturb each other (unfortunately in many i8042
* implementations write to one of the ports will immediately abort
* command that is being processed by another port).
@@ -979,7 +979,7 @@ static int i8042_controller_selftest(void)
}
/*
* i8042_controller init initializes the i8042 controller, and,
* i8042_controller_init initializes the i8042 controller, and,
* most importantly, sets it into non-xlated mode if that's
* desired.
*/

View File

@@ -7,15 +7,14 @@
* Some cleanups by Alan Cox <alan@linux.intel.com>
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/input.h>
#include <linux/slab.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/i2c.h>
#include <linux/gpio.h>
#include <linux/input/cy8ctmg110_pdata.h>
#include <linux/input.h>
#include <linux/interrupt.h>
#include <linux/gpio/consumer.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <asm/byteorder.h>
#define CY8CTMG110_DRIVER_NAME "cy8ctmg110"
@@ -45,18 +44,18 @@ struct cy8ctmg110 {
struct input_dev *input;
char phys[32];
struct i2c_client *client;
int reset_pin;
int irq_pin;
struct gpio_desc *reset_gpio;
};
/*
* cy8ctmg110_power is the routine that is called when touch hardware
* will powered off or on.
* is being powered off or on. When powering on this routine de-asserts
* the RESET line, when powering off reset line is asserted.
*/
static void cy8ctmg110_power(struct cy8ctmg110 *ts, bool poweron)
{
if (ts->reset_pin)
gpio_direction_output(ts->reset_pin, 1 - poweron);
if (ts->reset_gpio)
gpiod_set_value_cansleep(ts->reset_gpio, !poweron);
}
static int cy8ctmg110_write_regs(struct cy8ctmg110 *tsc, unsigned char reg,
@@ -112,7 +111,6 @@ static int cy8ctmg110_touch_pos(struct cy8ctmg110 *tsc)
{
struct input_dev *input = tsc->input;
unsigned char reg_p[CY8CTMG110_REG_MAX];
int x, y;
memset(reg_p, 0, CY8CTMG110_REG_MAX);
@@ -120,16 +118,15 @@ static int cy8ctmg110_touch_pos(struct cy8ctmg110 *tsc)
if (cy8ctmg110_read_regs(tsc, reg_p, 9, CY8CTMG110_TOUCH_X1) != 0)
return -EIO;
y = reg_p[2] << 8 | reg_p[3];
x = reg_p[0] << 8 | reg_p[1];
/* Number of touch */
if (reg_p[8] == 0) {
input_report_key(input, BTN_TOUCH, 0);
} else {
input_report_key(input, BTN_TOUCH, 1);
input_report_abs(input, ABS_X, x);
input_report_abs(input, ABS_Y, y);
input_report_abs(input, ABS_X,
be16_to_cpup((__be16 *)(reg_p + 0)));
input_report_abs(input, ABS_Y,
be16_to_cpup((__be16 *)(reg_p + 2)));
}
input_sync(input);
@@ -163,35 +160,35 @@ static irqreturn_t cy8ctmg110_irq_thread(int irq, void *dev_id)
return IRQ_HANDLED;
}
static void cy8ctmg110_shut_off(void *_ts)
{
struct cy8ctmg110 *ts = _ts;
cy8ctmg110_set_sleepmode(ts, true);
cy8ctmg110_power(ts, false);
}
static int cy8ctmg110_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
const struct cy8ctmg110_pdata *pdata = dev_get_platdata(&client->dev);
struct cy8ctmg110 *ts;
struct input_dev *input_dev;
int err;
/* No pdata no way forward */
if (pdata == NULL) {
dev_err(&client->dev, "no pdata\n");
return -ENODEV;
}
if (!i2c_check_functionality(client->adapter,
I2C_FUNC_SMBUS_READ_WORD_DATA))
return -EIO;
ts = kzalloc(sizeof(struct cy8ctmg110), GFP_KERNEL);
input_dev = input_allocate_device();
if (!ts || !input_dev) {
err = -ENOMEM;
goto err_free_mem;
}
ts = devm_kzalloc(&client->dev, sizeof(*ts), GFP_KERNEL);
if (!ts)
return -ENOMEM;
input_dev = devm_input_allocate_device(&client->dev);
if (!input_dev)
return -ENOMEM;
ts->client = client;
ts->input = input_dev;
ts->reset_pin = pdata->reset_pin;
ts->irq_pin = pdata->irq_pin;
snprintf(ts->phys, sizeof(ts->phys),
"%s/input0", dev_name(&client->dev));
@@ -199,84 +196,46 @@ static int cy8ctmg110_probe(struct i2c_client *client,
input_dev->name = CY8CTMG110_DRIVER_NAME " Touchscreen";
input_dev->phys = ts->phys;
input_dev->id.bustype = BUS_I2C;
input_dev->dev.parent = &client->dev;
input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
input_set_capability(input_dev, EV_KEY, BTN_TOUCH);
input_set_abs_params(input_dev, ABS_X,
CY8CTMG110_X_MIN, CY8CTMG110_X_MAX, 4, 0);
input_set_abs_params(input_dev, ABS_Y,
CY8CTMG110_Y_MIN, CY8CTMG110_Y_MAX, 4, 0);
if (ts->reset_pin) {
err = gpio_request(ts->reset_pin, NULL);
if (err) {
dev_err(&client->dev,
"Unable to request GPIO pin %d.\n",
ts->reset_pin);
goto err_free_mem;
}
/* Request and assert reset line */
ts->reset_gpio = devm_gpiod_get_optional(&client->dev, NULL,
GPIOD_OUT_HIGH);
if (IS_ERR(ts->reset_gpio)) {
err = PTR_ERR(ts->reset_gpio);
dev_err(&client->dev,
"Unable to request reset GPIO: %d\n", err);
return err;
}
cy8ctmg110_power(ts, true);
cy8ctmg110_set_sleepmode(ts, false);
err = gpio_request(ts->irq_pin, "touch_irq_key");
if (err < 0) {
dev_err(&client->dev,
"Failed to request GPIO %d, error %d\n",
ts->irq_pin, err);
goto err_shutoff_device;
}
err = devm_add_action_or_reset(&client->dev, cy8ctmg110_shut_off, ts);
if (err)
return err;
err = gpio_direction_input(ts->irq_pin);
if (err < 0) {
dev_err(&client->dev,
"Failed to configure input direction for GPIO %d, error %d\n",
ts->irq_pin, err);
goto err_free_irq_gpio;
}
client->irq = gpio_to_irq(ts->irq_pin);
if (client->irq < 0) {
err = client->irq;
dev_err(&client->dev,
"Unable to get irq number for GPIO %d, error %d\n",
ts->irq_pin, err);
goto err_free_irq_gpio;
}
err = request_threaded_irq(client->irq, NULL, cy8ctmg110_irq_thread,
IRQF_TRIGGER_RISING | IRQF_ONESHOT,
"touch_reset_key", ts);
if (err < 0) {
err = devm_request_threaded_irq(&client->dev, client->irq,
NULL, cy8ctmg110_irq_thread,
IRQF_ONESHOT, "touch_reset_key", ts);
if (err) {
dev_err(&client->dev,
"irq %d busy? error %d\n", client->irq, err);
goto err_free_irq_gpio;
return err;
}
err = input_register_device(input_dev);
if (err)
goto err_free_irq;
return err;
i2c_set_clientdata(client, ts);
device_init_wakeup(&client->dev, 1);
return 0;
err_free_irq:
free_irq(client->irq, ts);
err_free_irq_gpio:
gpio_free(ts->irq_pin);
err_shutoff_device:
cy8ctmg110_set_sleepmode(ts, true);
cy8ctmg110_power(ts, false);
if (ts->reset_pin)
gpio_free(ts->reset_pin);
err_free_mem:
input_free_device(input_dev);
kfree(ts);
return err;
return 0;
}
static int __maybe_unused cy8ctmg110_suspend(struct device *dev)
@@ -284,12 +243,11 @@ static int __maybe_unused cy8ctmg110_suspend(struct device *dev)
struct i2c_client *client = to_i2c_client(dev);
struct cy8ctmg110 *ts = i2c_get_clientdata(client);
if (device_may_wakeup(&client->dev))
enable_irq_wake(client->irq);
else {
if (!device_may_wakeup(&client->dev)) {
cy8ctmg110_set_sleepmode(ts, true);
cy8ctmg110_power(ts, false);
}
return 0;
}
@@ -298,34 +256,16 @@ static int __maybe_unused cy8ctmg110_resume(struct device *dev)
struct i2c_client *client = to_i2c_client(dev);
struct cy8ctmg110 *ts = i2c_get_clientdata(client);
if (device_may_wakeup(&client->dev))
disable_irq_wake(client->irq);
else {
if (!device_may_wakeup(&client->dev)) {
cy8ctmg110_power(ts, true);
cy8ctmg110_set_sleepmode(ts, false);
}
return 0;
}
static SIMPLE_DEV_PM_OPS(cy8ctmg110_pm, cy8ctmg110_suspend, cy8ctmg110_resume);
static int cy8ctmg110_remove(struct i2c_client *client)
{
struct cy8ctmg110 *ts = i2c_get_clientdata(client);
cy8ctmg110_set_sleepmode(ts, true);
cy8ctmg110_power(ts, false);
free_irq(client->irq, ts);
input_unregister_device(ts->input);
gpio_free(ts->irq_pin);
if (ts->reset_pin)
gpio_free(ts->reset_pin);
kfree(ts);
return 0;
}
static const struct i2c_device_id cy8ctmg110_idtable[] = {
{ CY8CTMG110_DRIVER_NAME, 1 },
{ }
@@ -340,7 +280,6 @@ static struct i2c_driver cy8ctmg110_driver = {
},
.id_table = cy8ctmg110_idtable,
.probe = cy8ctmg110_probe,
.remove = cy8ctmg110_remove,
};
module_i2c_driver(cy8ctmg110_driver);

View File

@@ -22,6 +22,7 @@
#include <linux/slab.h>
#include <linux/property.h>
#include <linux/gpio/consumer.h>
#include <linux/regulator/consumer.h>
#include "cyttsp_core.h"
@@ -45,8 +46,15 @@
#define CY_MAXZ 255
#define CY_DELAY_DFLT 20 /* ms */
#define CY_DELAY_MAX 500
#define CY_ACT_DIST_DFLT 0xF8
/* Active distance in pixels for a gesture to be reported */
#define CY_ACT_DIST_DFLT 0xF8 /* pixels */
#define CY_ACT_DIST_MASK 0x0F
/* Active Power state scanning/processing refresh interval */
#define CY_ACT_INTRVL_DFLT 0x00 /* ms */
/* Low Power state scanning/processing refresh interval */
#define CY_LP_INTRVL_DFLT 0x0A /* ms */
/* touch timeout for the Active power */
#define CY_TCH_TMOUT_DFLT 0xFF /* ms */
#define CY_HNDSHK_BIT 0x80
/* device mode bits */
#define CY_OPERATE_MODE 0x00
@@ -608,6 +616,14 @@ static int cyttsp_parse_properties(struct cyttsp *ts)
return 0;
}
static void cyttsp_disable_regulators(void *_ts)
{
struct cyttsp *ts = _ts;
regulator_bulk_disable(ARRAY_SIZE(ts->regulators),
ts->regulators);
}
struct cyttsp *cyttsp_probe(const struct cyttsp_bus_ops *bus_ops,
struct device *dev, int irq, size_t xfer_buf_size)
{
@@ -628,6 +644,32 @@ struct cyttsp *cyttsp_probe(const struct cyttsp_bus_ops *bus_ops,
ts->bus_ops = bus_ops;
ts->irq = irq;
/*
* VCPIN is the analog voltage supply
* VDD is the digital voltage supply
*/
ts->regulators[0].supply = "vcpin";
ts->regulators[1].supply = "vdd";
error = devm_regulator_bulk_get(dev, ARRAY_SIZE(ts->regulators),
ts->regulators);
if (error) {
dev_err(dev, "Failed to get regulators: %d\n", error);
return ERR_PTR(error);
}
error = regulator_bulk_enable(ARRAY_SIZE(ts->regulators),
ts->regulators);
if (error) {
dev_err(dev, "Cannot enable regulators: %d\n", error);
return ERR_PTR(error);
}
error = devm_add_action_or_reset(dev, cyttsp_disable_regulators, ts);
if (error) {
dev_err(dev, "failed to install chip disable handler\n");
return ERR_PTR(error);
}
ts->reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
if (IS_ERR(ts->reset_gpio)) {
error = PTR_ERR(ts->reset_gpio);
@@ -664,8 +706,7 @@ struct cyttsp *cyttsp_probe(const struct cyttsp_bus_ops *bus_ops,
}
error = devm_request_threaded_irq(dev, ts->irq, NULL, cyttsp_irq,
IRQF_TRIGGER_FALLING | IRQF_ONESHOT |
IRQF_NO_AUTOEN,
IRQF_ONESHOT | IRQF_NO_AUTOEN,
"cyttsp", ts);
if (error) {
dev_err(ts->dev, "failed to request IRQ %d, err: %d\n",

View File

@@ -22,7 +22,7 @@
#include <linux/module.h>
#include <linux/types.h>
#include <linux/device.h>
#include <linux/input/cyttsp.h>
#include <linux/regulator/consumer.h>
#define CY_NUM_RETRY 16 /* max number of retries for read ops */
@@ -122,6 +122,7 @@ struct cyttsp {
enum cyttsp_state state;
bool suspended;
struct regulator_bulk_data regulators[2];
struct gpio_desc *reset_gpio;
bool use_hndshk;
u8 act_dist;

View File

@@ -18,6 +18,8 @@
#include <linux/i2c.h>
#include <linux/input.h>
#define CY_I2C_NAME "cyttsp-i2c"
#define CY_I2C_DATA_SIZE 128
static const struct cyttsp_bus_ops cyttsp_i2c_bus_ops = {
@@ -52,10 +54,18 @@ static const struct i2c_device_id cyttsp_i2c_id[] = {
};
MODULE_DEVICE_TABLE(i2c, cyttsp_i2c_id);
static const struct of_device_id cyttsp_of_i2c_match[] = {
{ .compatible = "cypress,cy8ctma340", },
{ .compatible = "cypress,cy8ctst341", },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, cyttsp_of_i2c_match);
static struct i2c_driver cyttsp_i2c_driver = {
.driver = {
.name = CY_I2C_NAME,
.pm = &cyttsp_pm_ops,
.of_match_table = cyttsp_of_i2c_match,
},
.probe = cyttsp_i2c_probe,
.id_table = cyttsp_i2c_id,

View File

@@ -20,6 +20,8 @@
#include <linux/input.h>
#include <linux/spi/spi.h>
#define CY_SPI_NAME "cyttsp-spi"
#define CY_SPI_WR_OP 0x00 /* r/~w */
#define CY_SPI_RD_OP 0x01
#define CY_SPI_CMD_BYTES 4
@@ -160,10 +162,18 @@ static int cyttsp_spi_probe(struct spi_device *spi)
return 0;
}
static const struct of_device_id cyttsp_of_spi_match[] = {
{ .compatible = "cypress,cy8ctma340", },
{ .compatible = "cypress,cy8ctst341", },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, cyttsp_of_spi_match);
static struct spi_driver cyttsp_spi_driver = {
.driver = {
.name = CY_SPI_NAME,
.pm = &cyttsp_pm_ops,
.of_match_table = cyttsp_of_spi_match,
},
.probe = cyttsp_spi_probe,
};

View File

@@ -104,6 +104,7 @@ struct edt_ft5x06_ts_data {
u16 num_x;
u16 num_y;
struct regulator *vcc;
struct regulator *iovcc;
struct gpio_desc *reset_gpio;
struct gpio_desc *wake_gpio;
@@ -1062,11 +1063,12 @@ static void edt_ft5x06_ts_set_regs(struct edt_ft5x06_ts_data *tsdata)
}
}
static void edt_ft5x06_disable_regulator(void *arg)
static void edt_ft5x06_disable_regulators(void *arg)
{
struct edt_ft5x06_ts_data *data = arg;
regulator_disable(data->vcc);
regulator_disable(data->iovcc);
}
static int edt_ft5x06_ts_probe(struct i2c_client *client,
@@ -1107,14 +1109,33 @@ static int edt_ft5x06_ts_probe(struct i2c_client *client,
return error;
}
tsdata->iovcc = devm_regulator_get(&client->dev, "iovcc");
if (IS_ERR(tsdata->iovcc)) {
error = PTR_ERR(tsdata->iovcc);
if (error != -EPROBE_DEFER)
dev_err(&client->dev,
"failed to request iovcc regulator: %d\n", error);
return error;
}
error = regulator_enable(tsdata->iovcc);
if (error < 0) {
dev_err(&client->dev, "failed to enable iovcc: %d\n", error);
return error;
}
/* Delay enabling VCC for > 10us (T_ivd) after IOVCC */
usleep_range(10, 100);
error = regulator_enable(tsdata->vcc);
if (error < 0) {
dev_err(&client->dev, "failed to enable vcc: %d\n", error);
regulator_disable(tsdata->iovcc);
return error;
}
error = devm_add_action_or_reset(&client->dev,
edt_ft5x06_disable_regulator,
edt_ft5x06_disable_regulators,
tsdata);
if (error)
return error;
@@ -1289,6 +1310,9 @@ static int __maybe_unused edt_ft5x06_ts_suspend(struct device *dev)
ret = regulator_disable(tsdata->vcc);
if (ret)
dev_warn(dev, "Failed to disable vcc\n");
ret = regulator_disable(tsdata->iovcc);
if (ret)
dev_warn(dev, "Failed to disable iovcc\n");
return 0;
}
@@ -1319,9 +1343,19 @@ static int __maybe_unused edt_ft5x06_ts_resume(struct device *dev)
gpiod_set_value_cansleep(reset_gpio, 1);
usleep_range(5000, 6000);
ret = regulator_enable(tsdata->iovcc);
if (ret) {
dev_err(dev, "Failed to enable iovcc\n");
return ret;
}
/* Delay enabling VCC for > 10us (T_ivd) after IOVCC */
usleep_range(10, 100);
ret = regulator_enable(tsdata->vcc);
if (ret) {
dev_err(dev, "Failed to enable vcc\n");
regulator_disable(tsdata->iovcc);
return ret;
}

View File

@@ -1369,8 +1369,7 @@ static bool elants_acpi_is_hid_device(struct device *dev)
}
#endif
static int elants_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *id)
static int elants_i2c_probe(struct i2c_client *client)
{
union i2c_smbus_data dummy;
struct elants_data *ts;
@@ -1396,7 +1395,7 @@ static int elants_i2c_probe(struct i2c_client *client,
init_completion(&ts->cmd_done);
ts->client = client;
ts->chip_id = (enum elants_chip_id)id->driver_data;
ts->chip_id = (enum elants_chip_id)(uintptr_t)device_get_match_data(&client->dev);
i2c_set_clientdata(client, ts);
ts->vcc33 = devm_regulator_get(&client->dev, "vcc33");
@@ -1636,15 +1635,15 @@ MODULE_DEVICE_TABLE(acpi, elants_acpi_id);
#ifdef CONFIG_OF
static const struct of_device_id elants_of_match[] = {
{ .compatible = "elan,ekth3500" },
{ .compatible = "elan,ektf3624" },
{ .compatible = "elan,ekth3500", .data = (void *)EKTH3500 },
{ .compatible = "elan,ektf3624", .data = (void *)EKTF3624 },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, elants_of_match);
#endif
static struct i2c_driver elants_i2c_driver = {
.probe = elants_i2c_probe,
.probe_new = elants_i2c_probe,
.id_table = elants_i2c_id,
.driver = {
.name = DEVICE_NAME,

View File

@@ -361,13 +361,16 @@ static int hideep_enter_pgm(struct hideep_ts *ts)
return -EIO;
}
static void hideep_nvm_unlock(struct hideep_ts *ts)
static int hideep_nvm_unlock(struct hideep_ts *ts)
{
u32 unmask_code;
int error;
hideep_pgm_w_reg(ts, HIDEEP_FLASH_CFG, HIDEEP_NVM_SFR_RPAGE);
hideep_pgm_r_reg(ts, 0x0000000C, &unmask_code);
error = hideep_pgm_r_reg(ts, 0x0000000C, &unmask_code);
hideep_pgm_w_reg(ts, HIDEEP_FLASH_CFG, HIDEEP_NVM_DEFAULT_PAGE);
if (error)
return error;
/* make it unprotected code */
unmask_code &= ~HIDEEP_PROT_MODE;
@@ -384,6 +387,8 @@ static void hideep_nvm_unlock(struct hideep_ts *ts)
NVM_W_SFR(HIDEEP_NVM_MASK_OFS, ts->nvm_mask);
SET_FLASH_HWCONTROL();
hideep_pgm_w_reg(ts, HIDEEP_FLASH_CFG, HIDEEP_NVM_DEFAULT_PAGE);
return 0;
}
static int hideep_check_status(struct hideep_ts *ts)
@@ -462,7 +467,9 @@ static int hideep_program_nvm(struct hideep_ts *ts,
u32 addr = 0;
int error;
hideep_nvm_unlock(ts);
error = hideep_nvm_unlock(ts);
if (error)
return error;
while (ucode_len > 0) {
xfer_len = min_t(size_t, ucode_len, HIDEEP_NVM_PAGE_SIZE);

View File

@@ -13,44 +13,78 @@
#include <linux/input/touchscreen.h>
#include <linux/iio/consumer.h>
#include <linux/iio/iio.h>
#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/property.h>
#define DRIVER_NAME "resistive-adc-touch"
#define GRTS_DEFAULT_PRESSURE_MIN 50000
#define GRTS_DEFAULT_PRESSURE_MAX 65535
#define GRTS_MAX_POS_MASK GENMASK(11, 0)
#define GRTS_MAX_CHANNELS 4
enum grts_ch_type {
GRTS_CH_X,
GRTS_CH_Y,
GRTS_CH_PRESSURE,
GRTS_CH_Z1,
GRTS_CH_Z2,
GRTS_CH_MAX = GRTS_CH_Z2 + 1
};
/**
* struct grts_state - generic resistive touch screen information struct
* @x_plate_ohms: resistance of the X plate
* @pressure_min: number representing the minimum for the pressure
* @pressure: are we getting pressure info or not
* @iio_chans: list of channels acquired
* @iio_cb: iio_callback buffer for the data
* @input: the input device structure that we register
* @prop: touchscreen properties struct
* @ch_map: map of channels that are defined for the touchscreen
*/
struct grts_state {
u32 x_plate_ohms;
u32 pressure_min;
bool pressure;
struct iio_channel *iio_chans;
struct iio_cb_buffer *iio_cb;
struct input_dev *input;
struct touchscreen_properties prop;
u8 ch_map[GRTS_CH_MAX];
};
static int grts_cb(const void *data, void *private)
{
const u16 *touch_info = data;
struct grts_state *st = private;
unsigned int x, y, press = 0x0;
unsigned int x, y, press = 0;
/* channel data coming in buffer in the order below */
x = touch_info[0];
y = touch_info[1];
if (st->pressure)
press = touch_info[2];
x = touch_info[st->ch_map[GRTS_CH_X]];
y = touch_info[st->ch_map[GRTS_CH_Y]];
if (st->ch_map[GRTS_CH_PRESSURE] < GRTS_MAX_CHANNELS) {
press = touch_info[st->ch_map[GRTS_CH_PRESSURE]];
} else if (st->ch_map[GRTS_CH_Z1] < GRTS_MAX_CHANNELS) {
unsigned int z1 = touch_info[st->ch_map[GRTS_CH_Z1]];
unsigned int z2 = touch_info[st->ch_map[GRTS_CH_Z2]];
unsigned int Rt;
Rt = z2;
Rt -= z1;
Rt *= st->x_plate_ohms;
Rt = DIV_ROUND_CLOSEST(Rt, 16);
Rt *= x;
Rt /= z1;
Rt = DIV_ROUND_CLOSEST(Rt, 256);
/*
* On increased pressure the resistance (Rt) is decreasing
* so, convert values to make it looks as real pressure.
*/
if (Rt < GRTS_DEFAULT_PRESSURE_MAX)
press = GRTS_DEFAULT_PRESSURE_MAX - Rt;
}
if ((!x && !y) || (st->pressure && (press < st->pressure_min))) {
/* report end of touch */
@@ -94,12 +128,77 @@ static void grts_disable(void *data)
iio_channel_release_all_cb(data);
}
static int grts_map_channel(struct grts_state *st, struct device *dev,
enum grts_ch_type type, const char *name,
bool optional)
{
int idx;
idx = device_property_match_string(dev, "io-channel-names", name);
if (idx < 0) {
if (!optional)
return idx;
idx = GRTS_MAX_CHANNELS;
} else if (idx >= GRTS_MAX_CHANNELS) {
return -EOVERFLOW;
}
st->ch_map[type] = idx;
return 0;
}
static int grts_get_properties(struct grts_state *st, struct device *dev)
{
int error;
error = grts_map_channel(st, dev, GRTS_CH_X, "x", false);
if (error)
return error;
error = grts_map_channel(st, dev, GRTS_CH_Y, "y", false);
if (error)
return error;
/* pressure is optional */
error = grts_map_channel(st, dev, GRTS_CH_PRESSURE, "pressure", true);
if (error)
return error;
if (st->ch_map[GRTS_CH_PRESSURE] < GRTS_MAX_CHANNELS) {
st->pressure = true;
return 0;
}
/* if no pressure is defined, try optional z1 + z2 */
error = grts_map_channel(st, dev, GRTS_CH_Z1, "z1", true);
if (error)
return error;
if (st->ch_map[GRTS_CH_Z1] >= GRTS_MAX_CHANNELS)
return 0;
/* if z1 is provided z2 is not optional */
error = grts_map_channel(st, dev, GRTS_CH_Z2, "z2", true);
if (error)
return error;
error = device_property_read_u32(dev,
"touchscreen-x-plate-ohms",
&st->x_plate_ohms);
if (error) {
dev_err(dev, "can't get touchscreen-x-plate-ohms property\n");
return error;
}
st->pressure = true;
return 0;
}
static int grts_probe(struct platform_device *pdev)
{
struct grts_state *st;
struct input_dev *input;
struct device *dev = &pdev->dev;
struct iio_channel *chan;
int error;
st = devm_kzalloc(dev, sizeof(struct grts_state), GFP_KERNEL);
@@ -115,12 +214,13 @@ static int grts_probe(struct platform_device *pdev)
return error;
}
chan = &st->iio_chans[0];
st->pressure = false;
while (chan && chan->indio_dev) {
if (!strcmp(chan->channel->datasheet_name, "pressure"))
st->pressure = true;
chan++;
if (!device_property_present(dev, "io-channel-names"))
return -ENODEV;
error = grts_get_properties(st, dev);
if (error) {
dev_err(dev, "Failed to parse properties\n");
return error;
}
if (st->pressure) {
@@ -148,7 +248,7 @@ static int grts_probe(struct platform_device *pdev)
input_set_abs_params(input, ABS_Y, 0, GRTS_MAX_POS_MASK - 1, 0, 0);
if (st->pressure)
input_set_abs_params(input, ABS_PRESSURE, st->pressure_min,
0xffff, 0, 0);
GRTS_DEFAULT_PRESSURE_MAX, 0, 0);
input_set_capability(input, EV_KEY, BTN_TOUCH);
@@ -193,7 +293,7 @@ static struct platform_driver grts_driver = {
.probe = grts_probe,
.driver = {
.name = DRIVER_NAME,
.of_match_table = of_match_ptr(grts_of_match),
.of_match_table = grts_of_match,
},
};

View File

@@ -338,7 +338,7 @@ static struct attribute *tsc200x_attrs[] = {
static umode_t tsc200x_attr_is_visible(struct kobject *kobj,
struct attribute *attr, int n)
{
struct device *dev = container_of(kobj, struct device, kobj);
struct device *dev = kobj_to_dev(kobj);
struct tsc200x *ts = dev_get_drvdata(dev);
umode_t mode = attr->mode;

View File

@@ -251,7 +251,7 @@ static int e2i_init(struct usbtouch_usb *usbtouch)
int ret;
struct usb_device *udev = interface_to_usbdev(usbtouch->interface);
ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
0x01, 0x02, 0x0000, 0x0081,
NULL, 0, USB_CTRL_SET_TIMEOUT);
@@ -531,7 +531,7 @@ static int mtouch_init(struct usbtouch_usb *usbtouch)
if (ret)
return ret;
ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
MTOUCHUSB_RESET,
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
1, 0, NULL, 0, USB_CTRL_SET_TIMEOUT);
@@ -543,7 +543,7 @@ static int mtouch_init(struct usbtouch_usb *usbtouch)
msleep(150);
for (i = 0; i < 3; i++) {
ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
MTOUCHUSB_ASYNC_REPORT,
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
1, 1, NULL, 0, USB_CTRL_SET_TIMEOUT);
@@ -722,7 +722,7 @@ static int dmc_tsc10_init(struct usbtouch_usb *usbtouch)
}
/* start sending data */
ret = usb_control_msg(dev, usb_rcvctrlpipe (dev, 0),
ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
TSC10_CMD_DATA1,
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
0, 0, NULL, 0, USB_CTRL_SET_TIMEOUT);