History log of /linux-master/drivers/hid/hid-mcp2221.c
Revision Date Author Comments
# 3cba9cfc 02-Apr-2024 Abdelrahman Morsy <abdelrahmanhesham94@gmail.com>

HID: mcp-2221: cancel delayed_work only when CONFIG_IIO is enabled

If the device is unplugged and CONFIG_IIO is not supported, this will
result in a warning message at kernel/workqueue.

Only cancel delayed work in mcp2221_remove(), when CONFIG_IIO is enabled.

Signed-off-by: Abdelrahman Morsy <abdelrahmanhesham94@gmail.com>
Signed-off-by: Jiri Kosina <jkosina@suse.com>


# 26824686 24-Oct-2023 Hamish Martin <hamish.martin@alliedtelesis.co.nz>

HID: mcp2221: Handle reads greater than 60 bytes

When a user requests more than 60 bytes of data the MCP2221 must chunk
the data in chunks up to 60 bytes long (see command/response code 0x40
in the datasheet).
In order to signal that the device has more data the (undocumented) byte
at byte index 2 of the Get I2C Data response uses the value 0x54. This
contrasts with the case for the final data chunk where the value
returned is 0x55 (MCP2221_I2C_READ_COMPL). The fact that 0x55 was not
returned in the response was interpreted by the driver as a failure
meaning that all reads of more than 60 bytes would fail.

Add support for reads that are split over multiple chunks by looking for
the response code indicating that more data is expected and continuing
the read as the code intended. Some timing delays are required to ensure
the chip has time to refill its FIFO as data is read in from the I2C
bus. This timing has been tested in my system when configured for bus
speeds of 50KHz, 100KHz, and 400KHz and operates well.

Signed-off-by: Hamish Martin <hamish.martin@alliedtelesis.co.nz>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>


# 02a46753 24-Oct-2023 Hamish Martin <hamish.martin@alliedtelesis.co.nz>

HID: mcp2221: Don't set bus speed on every transfer

Since the initial commit of this driver the I2C bus speed has been
reconfigured for every single transfer. This is despite the fact that we
never change the speed and it is never "lost" by the chip.
Upon investigation we find that what was really happening was that the
setting of the bus speed had the side effect of cancelling a previous
failed command if there was one, thereby freeing the bus. This is the
part that was actually required to keep the bus operational in the face
of failed commands.

Instead of always setting the speed, we now correctly cancel any failed
commands as they are detected. This means we can just set the bus speed
at probe time and remove the previous speed sets on each transfer.
This has the effect of improving performance and reducing the number of
commands required to complete transfers.

Signed-off-by: Hamish Martin <hamish.martin@alliedtelesis.co.nz>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>


# d9786159 24-Oct-2023 Hamish Martin <hamish.martin@alliedtelesis.co.nz>

HID: mcp2221: Set ACPI companion

In scenarios where an I2C device tree is defined in ACPI and exists off
the MCP2221 I2C bus, the devices could not be instantiated.
Mark the USB port that the MCP2221 is connected to as its ACPI companion
so that the USB device can be bound to the ACPI tree when enumerated.
With this change the downstream I2C tree devices can be instantiated on
ACPI systems.

Signed-off-by: Hamish Martin <hamish.martin@alliedtelesis.co.nz>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>


# 73ce9f1f 24-Oct-2023 Hamish Martin <hamish.martin@alliedtelesis.co.nz>

HID: mcp2221: Allow IO to start during probe

During the probe we add an I2C adapter and as soon as we add that adapter
it may be used for a transfer (e.g via the code in i2cdetect()).
Those transfers are not able to complete and time out. This is because the
HID raw_event callback (mcp2221_raw_event) will not be invoked until the
HID device's 'driver_input_lock' is marked up at the completion of the
probe in hid_device_probe(). This starves the driver of the responses it
is waiting for.
In order to allow the I2C transfers to complete while we are still in the
probe, start the IO once we have completed init of the HID device.

This issue seems to have been seen before and a patch was submitted but
it seems it was never accepted. See:
https://lore.kernel.org/all/20221103222714.21566-3-Enrik.Berkhan@inka.de/

Signed-off-by: Hamish Martin <hamish.martin@alliedtelesis.co.nz>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>


# f2d4a583 24-Oct-2023 Hamish Martin <hamish.martin@alliedtelesis.co.nz>

HID: mcp2221: Set driver data before I2C adapter add

The process of adding an I2C adapter can invoke I2C accesses on that new
adapter (see i2c_detect()).

Ensure we have set the adapter's driver data to avoid null pointer
dereferences in the xfer functions during the adapter add.

This has been noted in the past and the same fix proposed but not
completed. See:
https://lore.kernel.org/lkml/ef597e73-ed71-168e-52af-0d19b03734ac@vigem.de/

Signed-off-by: Hamish Martin <hamish.martin@alliedtelesis.co.nz>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>


# ca6961d8 04-Apr-2023 Louis Morhet <lmorhet@kalrayinc.com>

HID: mcp2221: fix get and get_direction for gpio

The mcp2221_raw_event retrieves the value and direction of gpio on the
same command, by setting the value on mcp->status and the direction on
mcp->gpio_dir; and the offset at which they are read is based on
mcp->gp_idx, set by the gpiochip callbacks.

However, the individual gpiochip calls set the index to look for
directly on the field they want to track. This create a "double offset"
in the final read in the response report.

Align the behaviour of mcp2221_raw_event and
mcp_gpio_get/mcp_gpio_get_direction by putting gp_idx on those calls to
the base offset of the gpio status struct.

Signed-off-by: Louis Morhet <lmorhet@kalrayinc.com>
Link: https://lore.kernel.org/r/dd0b23800a79d2a464e1e9ed429b018b69fd5df2.1680602387.git.lmorhet@kalrayinc.com
Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>


# e36c31f8 04-Apr-2023 Louis Morhet <lmorhet@kalrayinc.com>

HID: mcp2221: fix report layout for gpio get

The documentation of the component (section 3.1.12 GET GPIO VALUES)
describes the hid report structure with two fields per gpio:
its value, followed by its direction.

However, the driver describes it with a wrong order:
direction followed by value.

Fix the structure representing the report answered by the chip to the
GET GPIO VALUES command.

Fixes commit 567b8e9fed8a ("HID: mcp2221: Fix GPIO output handling")

Signed-off-by: Louis Morhet <lmorhet@kalrayinc.com>
Link: https://lore.kernel.org/r/945967fbab56d53f9630ad3844b64734f8c3107e.1680602387.git.lmorhet@kalrayinc.com
Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>


# 47e91fdf 16-Feb-2023 Benjamin Tissoires <benjamin.tissoires@redhat.com>

HID: mcp-2221: prevent UAF in delayed work

If the device is plugged/unplugged without giving time for mcp_init_work()
to complete, we might kick in the devm free code path and thus have
unavailable struct mcp_2221 while in delayed work.

Canceling the delayed_work item is enough to solve the issue, because
cancel_delayed_work_sync will prevent the work item to requeue itself.

Fixes: 960f9df7c620 ("HID: mcp2221: add ADC/DAC support via iio subsystem")
CC: stable@vger.kernel.org
Acked-by: Jiri Kosina <jkosina@suse.cz>
Link: https://lore.kernel.org/r/20230215-wip-mcp2221-v2-1-109f71fd036e@redhat.com
Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>


# 67c90d14 03-Nov-2022 Enrik Berkhan <Enrik.Berkhan@inka.de>

HID: mcp2221: don't connect hidraw

The MCP2221 driver should not connect to the hidraw userspace interface,
as it needs exclusive access to the chip.

If you want to use /dev/hidrawX with the MCP2221, you need to avoid
binding this driver to the device and use the hid generic driver instead
(e.g. using udev rules).

Cc: stable@vger.kernel.org
Reported-by: Sven Zühlsdorf <sven.zuehlsdorf@vigem.de>
Signed-off-by: Enrik Berkhan <Enrik.Berkhan@inka.de>
Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
Link: https://lore.kernel.org/r/20221103222714.21566-2-Enrik.Berkhan@inka.de


# 3d74c9ec 20-Oct-2022 Matt Ranostay <matt.ranostay@konsulko.com>

HID: mcp2221: correct undefined references when CONFIG_GPIOLIB isn't defined

Singular #ifdef IS_REACHABLE(CONFIG_GPIOLIB) weren't covering all the
gpiolib functions that were being referenced.

Update the code regions that are commented out when CONFIG_GPIOLIB isn't
enabled to avoid errors.

Fixes: 960f9df7c620 ("HID: mcp2221: add ADC/DAC support via iio subsystem")
Signed-off-by: Matt Ranostay <matt.ranostay@konsulko.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>


# e91fc483 20-Oct-2022 Matt Ranostay <matt.ranostay@konsulko.com>

HID: mcp2221: fix 'cast to restricted __le16' sparse warnings

Use (__force __le16) cast for adc_values le16_to_cpu conversion to correct following sparse
warnings:

drivers/hid/hid-mcp2221.c:950:32: sparse: sparse: cast to restricted __le16

Reported-by: kernel test robot <lkp@intel.com>
Fixes: 960f9df7c620 ("HID: mcp2221: add ADC/DAC support via iio subsystem")
Signed-off-by: Matt Ranostay <matt.ranostay@konsulko.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>


# daf405c8 20-Oct-2022 Jiri Kosina <jkosina@suse.cz>

HID: mcp2221: fix usage of tmp variable in mcp2221_raw_event()

In mcp2221_raw_event(), 'tmp' is used only conditionally. Move
the declaration into the conditional block in order to prevent
unused variable warning.

Reported-by: kernel test robot <lkp@intel.com>
Fixes: 960f9df7c620 ("HID: mcp2221: add ADC/DAC support via iio subsystem")
Signed-off-by: Jiri Kosina <jkosina@suse.cz>


# 960f9df7 30-Sep-2022 Matt Ranostay <matt.ranostay@konsulko.com>

HID: mcp2221: add ADC/DAC support via iio subsystem

Add support for 3x 10-bit ADC and 1x DAC channels registered via the iio
subsystem.

To prevent breakage and unexpected dependencies this support only is
only built if CONFIG_IIO is enabled, and is only weakly referenced by
'imply IIO' within the respective Kconfig.

Additionally the iio device only gets registered if at least one channel
is enabled in the power-on configuration read from SRAM.

Signed-off-by: Matt Ranostay <matt.ranostay@konsulko.com>
Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>


# ea418b35 30-Sep-2022 Matt Ranostay <matt.ranostay@konsulko.com>

HID: mcp2221: change 'select GPIOLIB' to imply

To avoid recursive dependencies on GPIOLIB when 'imply IIO' is requested
with other drivers we should switch GPIOLIB to an imply.

This isn't the most ideal solution but avoids modifiying the Kconfig for
other drivers, and only requires a singular IS_REACHABLE(CONFIG_GPIOLIB)
check.

Signed-off-by: Matt Ranostay <matt.ranostay@konsulko.com>
Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>


# deb3b88b 30-Sep-2022 Matt Ranostay <matt.ranostay@konsulko.com>

HID: mcp2221: switch i2c registration to devm functions

Switch from i2c_add_adapter() to resource managed devm_i2c_add_adapter()
for matching rest of driver initialization, and more concise code.

Signed-off-by: Matt Ranostay <matt.ranostay@konsulko.com>
Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>


# 62ac2473 20-Jun-2022 Harshit Mogalapalli <harshit.m.mogalapalli@oracle.com>

HID: mcp2221: prevent a buffer overflow in mcp_smbus_write()

Smatch Warning:
drivers/hid/hid-mcp2221.c:388 mcp_smbus_write() error: __memcpy()
'&mcp->txbuf[5]' too small (59 vs 255)
drivers/hid/hid-mcp2221.c:388 mcp_smbus_write() error: __memcpy() 'buf'
too small (34 vs 255)

The 'len' variable can take a value between 0-255 as it can come from
data->block[0] and it is user data. So add an bound check to prevent a
buffer overflow in memcpy().

Fixes: 67a95c21463d ("HID: mcp2221: add usb to i2c-smbus host bridge")
Signed-off-by: Harshit Mogalapalli <harshit.m.mogalapalli@oracle.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>


# 567b8e9f 04-Nov-2020 Lars Povlsen <lars.povlsen@microchip.com>

HID: mcp2221: Fix GPIO output handling

The mcp2221 driver GPIO output handling has has several issues.

* A wrong value is used for the GPIO direction.

* Wrong offsets are calculated for some GPIO set value/set direction
operations, when offset is larger than 0.

This has been fixed by introducing proper manifest constants for the
direction encoding, and using 'offsetof' when calculating GPIO
register offsets.

The updated driver has been tested with the Sparx5 pcb134/pcb135
board, which has the mcp2221 device with several (output) GPIO's.

Fixes: 328de1c519c5c092 ("HID: mcp2221: add GPIO functionality support")
Reviewed-by: Rishi Gupta <gupt21@gmail.com>
Signed-off-by: Lars Povlsen <lars.povlsen@microchip.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>


# b266eacf 13-Jul-2020 Alexander A. Klimov <grandmaster@al2klimov.de>

HID: mcp2221: Replace HTTP links with HTTPS ones

Rationale:
Reduces attack surface on kernel devs opening the links for MITM
as HTTPS traffic is much harder to manipulate.

Deterministic algorithm:
For each file:
If not .svg:
For each line:
If doesn't contain `\bxmlns\b`:
For each link, `\bhttp://[^# \t\r\n]*(?:\w|/)`:
If neither `\bgnu\.org/license`, nor `\bmozilla\.org/MPL\b`:
If both the HTTP and HTTPS versions
return 200 OK and serve the same content:
Replace HTTP with HTTPS.

Signed-off-by: Alexander A. Klimov <grandmaster@al2klimov.de>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>


# 328de1c5 14-Apr-2020 Rishi Gupta <gupt21@gmail.com>

HID: mcp2221: add GPIO functionality support

MCP2221 has 4 pins that can be used as GPIO or configured
for alternate functionality such as clock generation and
IRQ detection. This patch adds support for GPIO functionality.

To set direction of a pin or to toggle its state after it
has been configured as GPIO, driver sends command to mcp2221
and parses response received from mcp2221. Based on this
response either 0 or appropriate error code is returned to
GPIO framework.

To get the direction or current state of a pin, driver
sends command and read response from the device. Based on
the response received from device direction or value
is sent to the GPIO framework.

Command from driver to mcp2221 device are output report.
Response received from mcp2221 is input report.

Datasheet (page 45-48) contains details about how to decode
the response received from device:
http://ww1.microchip.com/downloads/en/DeviceDoc/20005565B.pdf

Signed-off-by: Rishi Gupta <gupt21@gmail.com>
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>


# 67a95c21 27-Jan-2020 Rishi Gupta <gupt21@gmail.com>

HID: mcp2221: add usb to i2c-smbus host bridge

MCP2221 is a USB HID to I2C/SMbus host bridge device. This
commit implements i2c and smbus host adapter support. 7-bit
address and i2c multi-message transaction is also supported.

Signed-off-by: Rishi Gupta <gupt21@gmail.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>