Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions drivers/hid/hid-ids.h
Original file line number Diff line number Diff line change
Expand Up @@ -509,6 +509,7 @@
#define I2C_DEVICE_ID_GOODIX_01E8 0x01e8
#define I2C_DEVICE_ID_GOODIX_01E9 0x01e9
#define I2C_DEVICE_ID_GOODIX_01F0 0x01f0
#define I2C_DEVICE_ID_GOODIX_0D42 0x0d42

#define USB_VENDOR_ID_GOODTOUCH 0x1aad
#define USB_DEVICE_ID_GOODTOUCH_000f 0x000f
Expand Down
190 changes: 110 additions & 80 deletions drivers/hid/i2c-hid/i2c-hid-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
#define I2C_HID_QUIRK_BAD_INPUT_SIZE BIT(3)
#define I2C_HID_QUIRK_NO_WAKEUP_AFTER_RESET BIT(4)
#define I2C_HID_QUIRK_NO_SLEEP_ON_SUSPEND BIT(5)
#define I2C_HID_QUIRK_DELAY_WAKEUP_AFTER_RESUME BIT(6)

/* Command opcodes */
#define I2C_HID_OPCODE_RESET 0x01
Expand Down Expand Up @@ -105,6 +106,7 @@ struct i2c_hid {

wait_queue_head_t wait; /* For waiting the interrupt */

struct mutex cmd_lock; /* protects cmdbuf and rawbuf */
struct mutex reset_lock;

struct i2chid_ops *ops;
Expand Down Expand Up @@ -139,6 +141,8 @@ static const struct i2c_hid_quirks {
{ USB_VENDOR_ID_ELAN, HID_ANY_ID,
I2C_HID_QUIRK_NO_WAKEUP_AFTER_RESET |
I2C_HID_QUIRK_BOGUS_IRQ },
{ I2C_VENDOR_ID_GOODIX, I2C_DEVICE_ID_GOODIX_0D42,
I2C_HID_QUIRK_DELAY_WAKEUP_AFTER_RESUME },
{ 0, 0 }
};

Expand All @@ -163,6 +167,24 @@ static u32 i2c_hid_lookup_quirk(const u16 idVendor, const u16 idProduct)
return quirks;
}

static int i2c_hid_probe_address(struct i2c_hid *ihid)
{
int ret;

/*
* Some STM-based devices need 400µs after a rising clock edge to wake
* from deep sleep, in which case the first read will fail. Try after a
* short sleep to see if the device came alive on the bus. Certain
* Weida Tech devices also need this.
*/
ret = i2c_smbus_read_byte(ihid->client);
if (ret < 0) {
usleep_range(400, 500);
ret = i2c_smbus_read_byte(ihid->client);
}
return ret < 0 ? ret : 0;
}

static int i2c_hid_xfer(struct i2c_hid *ihid,
u8 *send_buf, int send_len, u8 *recv_buf, int recv_len)
{
Expand Down Expand Up @@ -202,6 +224,8 @@ static int i2c_hid_xfer(struct i2c_hid *ihid,
static int i2c_hid_read_register(struct i2c_hid *ihid, __le16 reg,
void *buf, size_t len)
{
guard(mutex)(&ihid->cmd_lock);

*(__le16 *)ihid->cmdbuf = reg;

return i2c_hid_xfer(ihid, ihid->cmdbuf, sizeof(__le16), buf, len);
Expand Down Expand Up @@ -234,6 +258,8 @@ static int i2c_hid_get_report(struct i2c_hid *ihid,

i2c_hid_dbg(ihid, "%s\n", __func__);

guard(mutex)(&ihid->cmd_lock);

/* Command register goes first */
*(__le16 *)ihid->cmdbuf = ihid->hdesc.wCommandRegister;
length += sizeof(__le16);
Expand Down Expand Up @@ -324,6 +350,8 @@ static int i2c_hid_set_or_send_report(struct i2c_hid *ihid,
if (!do_set && le16_to_cpu(ihid->hdesc.wMaxOutputLength) == 0)
return -ENOSYS;

guard(mutex)(&ihid->cmd_lock);

if (do_set) {
/* Command register goes first */
*(__le16 *)ihid->cmdbuf = ihid->hdesc.wCommandRegister;
Expand Down Expand Up @@ -366,6 +394,8 @@ static int i2c_hid_set_power_command(struct i2c_hid *ihid, int power_state)
{
size_t length;

guard(mutex)(&ihid->cmd_lock);

/* SET_POWER uses command register */
*(__le16 *)ihid->cmdbuf = ihid->hdesc.wCommandRegister;
length = sizeof(__le16);
Expand All @@ -385,25 +415,22 @@ static int i2c_hid_set_power(struct i2c_hid *ihid, int power_state)
i2c_hid_dbg(ihid, "%s\n", __func__);

/*
* Some devices require to send a command to wakeup before power on.
* The call will get a return value (EREMOTEIO) but device will be
* triggered and activated. After that, it goes like a normal device.
* Some STM-based devices need 400µs after a rising clock edge to wake
* from deep sleep, in which case the first request will fail due to
* the address not being acknowledged. Try after a short sleep to see
* if the device came alive on the bus. Certain Weida Tech devices also
* need this.
*/
if (power_state == I2C_HID_PWR_ON) {
ret = i2c_hid_set_power_command(ihid, power_state);
if (ret && power_state == I2C_HID_PWR_ON) {
usleep_range(400, 500);
ret = i2c_hid_set_power_command(ihid, I2C_HID_PWR_ON);

/* Device was already activated */
if (!ret)
goto set_pwr_exit;
}

ret = i2c_hid_set_power_command(ihid, power_state);
if (ret)
dev_err(&ihid->client->dev,
"failed to change power setting.\n");

set_pwr_exit:

/*
* The HID over I2C specification states that if a DEVICE needs time
* after the PWR_ON request, it should utilise CLOCK stretching.
Expand All @@ -419,78 +446,71 @@ static int i2c_hid_set_power(struct i2c_hid *ihid, int power_state)
return ret;
}

static int i2c_hid_execute_reset(struct i2c_hid *ihid)
static int i2c_hid_start_hwreset(struct i2c_hid *ihid)
{
size_t length = 0;
int ret;

i2c_hid_dbg(ihid, "resetting...\n");
i2c_hid_dbg(ihid, "%s\n", __func__);

/* Prepare reset command. Command register goes first. */
*(__le16 *)ihid->cmdbuf = ihid->hdesc.wCommandRegister;
length += sizeof(__le16);
/* Next is RESET command itself */
length += i2c_hid_encode_command(ihid->cmdbuf + length,
I2C_HID_OPCODE_RESET, 0, 0);
/*
* This prevents sending feature reports while the device is
* being reset. Otherwise we may lose the reset complete
* interrupt.
*/
lockdep_assert_held(&ihid->reset_lock);

set_bit(I2C_HID_RESET_PENDING, &ihid->flags);
ret = i2c_hid_set_power(ihid, I2C_HID_PWR_ON);
if (ret)
return ret;

ret = i2c_hid_xfer(ihid, ihid->cmdbuf, length, NULL, 0);
if (ret) {
dev_err(&ihid->client->dev, "failed to reset device.\n");
goto out;
}
scoped_guard(mutex, &ihid->cmd_lock) {
/* Prepare reset command. Command register goes first. */
*(__le16 *)ihid->cmdbuf = ihid->hdesc.wCommandRegister;
length += sizeof(__le16);
/* Next is RESET command itself */
length += i2c_hid_encode_command(ihid->cmdbuf + length,
I2C_HID_OPCODE_RESET, 0, 0);

if (ihid->quirks & I2C_HID_QUIRK_NO_IRQ_AFTER_RESET) {
msleep(100);
goto out;
}
set_bit(I2C_HID_RESET_PENDING, &ihid->flags);

i2c_hid_dbg(ihid, "%s: waiting...\n", __func__);
if (!wait_event_timeout(ihid->wait,
!test_bit(I2C_HID_RESET_PENDING, &ihid->flags),
msecs_to_jiffies(5000))) {
ret = -ENODATA;
goto out;
ret = i2c_hid_xfer(ihid, ihid->cmdbuf, length, NULL, 0);
if (ret) {
dev_err(&ihid->client->dev,
"failed to reset device: %d\n", ret);
break;
}

return 0;
}
i2c_hid_dbg(ihid, "%s: finished.\n", __func__);

out:
/* Clean up if sending reset command failed */
clear_bit(I2C_HID_RESET_PENDING, &ihid->flags);
i2c_hid_set_power(ihid, I2C_HID_PWR_SLEEP);
return ret;
}

static int i2c_hid_hwreset(struct i2c_hid *ihid)
static int i2c_hid_finish_hwreset(struct i2c_hid *ihid)
{
int ret;

i2c_hid_dbg(ihid, "%s\n", __func__);

/*
* This prevents sending feature reports while the device is
* being reset. Otherwise we may lose the reset complete
* interrupt.
*/
mutex_lock(&ihid->reset_lock);
int ret = 0;

ret = i2c_hid_set_power(ihid, I2C_HID_PWR_ON);
if (ret)
goto out_unlock;
i2c_hid_dbg(ihid, "%s: waiting...\n", __func__);

ret = i2c_hid_execute_reset(ihid);
if (ret) {
dev_err(&ihid->client->dev,
"failed to reset device: %d\n", ret);
i2c_hid_set_power(ihid, I2C_HID_PWR_SLEEP);
goto out_unlock;
if (ihid->quirks & I2C_HID_QUIRK_NO_IRQ_AFTER_RESET) {
msleep(100);
clear_bit(I2C_HID_RESET_PENDING, &ihid->flags);
} else if (!wait_event_timeout(ihid->wait,
!test_bit(I2C_HID_RESET_PENDING, &ihid->flags),
msecs_to_jiffies(1000))) {
dev_warn(&ihid->client->dev, "device did not ack reset within 1000 ms\n");
clear_bit(I2C_HID_RESET_PENDING, &ihid->flags);
}
i2c_hid_dbg(ihid, "%s: finished.\n", __func__);

/* At least some SIS devices need this after reset */
if (!(ihid->quirks & I2C_HID_QUIRK_NO_WAKEUP_AFTER_RESET))
ret = i2c_hid_set_power(ihid, I2C_HID_PWR_ON);

out_unlock:
mutex_unlock(&ihid->reset_lock);
return ret;
}

Expand Down Expand Up @@ -719,11 +739,10 @@ static int i2c_hid_parse(struct hid_device *hid)
struct i2c_client *client = hid->driver_data;
struct i2c_hid *ihid = i2c_get_clientdata(client);
struct i2c_hid_desc *hdesc = &ihid->hdesc;
char *rdesc = NULL, *use_override = NULL;
unsigned int rsize;
char *rdesc;
int ret;
int tries = 3;
char *use_override;

i2c_hid_dbg(ihid, "entering %s\n", __func__);

Expand All @@ -733,11 +752,15 @@ static int i2c_hid_parse(struct hid_device *hid)
return -EINVAL;
}

mutex_lock(&ihid->reset_lock);
do {
ret = i2c_hid_hwreset(ihid);
if (ret)
ret = i2c_hid_start_hwreset(ihid);
if (ret == 0)
ret = i2c_hid_finish_hwreset(ihid);
else
msleep(1000);
} while (tries-- > 0 && ret);
mutex_unlock(&ihid->reset_lock);

if (ret)
return ret;
Expand All @@ -750,11 +773,8 @@ static int i2c_hid_parse(struct hid_device *hid)
i2c_hid_dbg(ihid, "Using a HID report descriptor override\n");
} else {
rdesc = kzalloc(rsize, GFP_KERNEL);

if (!rdesc) {
dbg_hid("couldn't allocate rdesc memory\n");
if (!rdesc)
return -ENOMEM;
}

i2c_hid_dbg(ihid, "asking HID report descriptor\n");

Expand All @@ -763,23 +783,21 @@ static int i2c_hid_parse(struct hid_device *hid)
rdesc, rsize);
if (ret) {
hid_err(hid, "reading report descriptor failed\n");
kfree(rdesc);
return -EIO;
goto out;
}
}

i2c_hid_dbg(ihid, "Report Descriptor: %*ph\n", rsize, rdesc);

ret = hid_parse_report(hid, rdesc, rsize);
if (ret)
dbg_hid("parsing report descriptor failed\n");

out:
if (!use_override)
kfree(rdesc);

if (ret) {
dbg_hid("parsing report descriptor failed\n");
return ret;
}

return 0;
return ret;
}

static int i2c_hid_start(struct hid_device *hid)
Expand Down Expand Up @@ -970,6 +988,13 @@ static int i2c_hid_core_resume(struct i2c_hid *ihid)

enable_irq(client->irq);

/* On Goodix 27c6:0d42 wait extra time before device wakeup.
* It's not clear why but if we send wakeup too early, the device will
* never trigger input interrupts.
*/
if (ihid->quirks & I2C_HID_QUIRK_DELAY_WAKEUP_AFTER_RESUME)
msleep(1500);

/* Instead of resetting device, simply powers the device on. This
* solves "incomplete reports" on Raydium devices 2386:3118 and
* 2386:4B33 and fixes various SIS touchscreens no longer sending
Expand All @@ -978,10 +1003,15 @@ static int i2c_hid_core_resume(struct i2c_hid *ihid)
* However some ALPS touchpads generate IRQ storm without reset, so
* let's still reset them here.
*/
if (ihid->quirks & I2C_HID_QUIRK_RESET_ON_RESUME)
ret = i2c_hid_hwreset(ihid);
else
if (ihid->quirks & I2C_HID_QUIRK_RESET_ON_RESUME) {
mutex_lock(&ihid->reset_lock);
ret = i2c_hid_start_hwreset(ihid);
if (ret == 0)
ret = i2c_hid_finish_hwreset(ihid);
mutex_unlock(&ihid->reset_lock);
} else {
ret = i2c_hid_set_power(ihid, I2C_HID_PWR_ON);
}

if (ret)
return ret;
Expand All @@ -998,8 +1028,7 @@ static int __i2c_hid_core_probe(struct i2c_hid *ihid)
struct hid_device *hid = ihid->hid;
int ret;

/* Make sure there is something at this address */
ret = i2c_smbus_read_byte(client);
ret = i2c_hid_probe_address(ihid);
if (ret < 0) {
i2c_hid_dbg(ihid, "nothing at this address: %d\n", ret);
return -ENXIO;
Expand Down Expand Up @@ -1196,6 +1225,7 @@ int i2c_hid_core_probe(struct i2c_client *client, struct i2chid_ops *ops,
ihid->is_panel_follower = drm_is_panel_follower(&client->dev);

init_waitqueue_head(&ihid->wait);
mutex_init(&ihid->cmd_lock);
mutex_init(&ihid->reset_lock);
INIT_WORK(&ihid->panel_follower_prepare_work, ihid_core_panel_prepare_work);

Expand Down
Loading