[PATCH] HID: mcp2221: fix probing of the I2C bus added by hid_mcp2221

From: Sven Zühlsdorf
Date: Tue Dec 13 2022 - 09:05:16 EST


From: Karl Georg Esser <kgesser@xxxxxxxx>
Date: Fri, 9 Dec 2022 16:17:59 +0100
Subject: [PATCH] HID: mcp2221: fix probing of the I2C bus added by hid_mcp2221

As soon as the I2C driver part will be enabled in mcp2221_probe(), the
first HID reports might be exchanged with the chip due to other drivers
probing for their devices on the just added I2C bus. HID I/O has to be
enabled explicitly during mcp2221_probe() to receive response reports.
In addition, the I2C bus' adapdata has to be set before any use of the bus,
otherwise mcp_{i2c,smbus}_xfer will attempt to dereference a NULL pointer.

Fixes: 67a95c21463d ("HID: mcp2221: add usb to i2c-smbus host bridge")
Signed-off-by: Karl Georg Esser <kgesser@xxxxxxxx>
Signed-off-by: Sven Zühlsdorf <sven.zuehlsdorf@xxxxxxxx>
---
drivers/hid/hid-mcp2221.c | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/drivers/hid/hid-mcp2221.c b/drivers/hid/hid-mcp2221.c
index 5886543b17f3..35b7d6939b38 100644
--- a/drivers/hid/hid-mcp2221.c
+++ b/drivers/hid/hid-mcp2221.c
@@ -324,6 +324,9 @@ static int mcp_i2c_xfer(struct i2c_adapter *adapter,
int ret;
struct mcp2221 *mcp = i2c_get_adapdata(adapter);

+ if(!mcp)
+ return -ECONNREFUSED;
+
hid_hw_power(mcp->hdev, PM_HINT_FULLON);

mutex_lock(&mcp->lock);
@@ -433,6 +436,9 @@ static int mcp_smbus_xfer(struct i2c_adapter *adapter, u16 addr,
int ret;
struct mcp2221 *mcp = i2c_get_adapdata(adapter);

+ if(!mcp)
+ return -ECONNREFUSED;
+
hid_hw_power(mcp->hdev, PM_HINT_FULLON);

mutex_lock(&mcp->lock);
@@ -1148,12 +1154,14 @@ static int mcp2221_probe(struct hid_device *hdev,
"MCP2221 usb-i2c bridge on hidraw%d",
((struct hidraw *)hdev->hidraw)->minor);

+ i2c_set_adapdata(&mcp->adapter, mcp);
+ hid_device_io_start(hdev);
+
ret = devm_i2c_add_adapter(&hdev->dev, &mcp->adapter);
if (ret) {
hid_err(hdev, "can't add usb-i2c adapter: %d\n", ret);
return ret;
}
- i2c_set_adapdata(&mcp->adapter, mcp);

#if IS_REACHABLE(CONFIG_GPIOLIB)
/* Setup GPIO chip */
--
2.38.1