Commit db8d3a21 authored by Michael Zaidman's avatar Michael Zaidman Committed by Jiri Kosina

HID: ft260: fix device removal due to USB disconnect

This commit fixes a functional regression introduced by the commit 82f09a63
("HID: ft260: improve error handling of ft260_hid_feature_report_get()")
when upon USB disconnect, the FTDI FT260 i2c device is still available within
the /dev folder.

In my company's product, where the host USB to FT260 USB connection is
hard-wired in the PCB, the issue is not reproducible. To reproduce it, I used
the VirtualBox Ubuntu 20.04 VM and the UMFT260EV1A development module for the
FTDI FT260 chip:

Plug the UMFT260EV1A module into a USB port and attach it to VM.

The VM shows 2 i2c devices under the /dev:
    michael@michael-VirtualBox:~$ ls /dev/i2c-*
    /dev/i2c-0  /dev/i2c-1

The i2c-0 is not related to the FTDI FT260:
    michael@michael-VirtualBox:~$ cat /sys/bus/i2c/devices/i2c-0/name
    SMBus PIIX4 adapter at 4100

The i2c-1 is created by hid-ft260.ko:
    michael@michael-VirtualBox:~$ cat /sys/bus/i2c/devices/i2c-1/name
    FT260 usb-i2c bridge on hidraw1

Now, detach the FTDI FT260 USB device from VM. We expect the /dev/i2c-1
to disappear, but it's still here:
    michael@michael-VirtualBox:~$ ls /dev/i2c-*
    /dev/i2c-0  /dev/i2c-1

And the kernel log shows:
    [  +0.001202] usb 2-2: USB disconnect, device number 3
    [  +0.000109] ft260 0003:0403:6030.0002: failed to retrieve system status
    [  +0.000316] ft260 0003:0403:6030.0003: failed to retrieve system status

It happens because the commit 82f09a63 changed the ft260_get_system_config()
return logic. This caused the ft260_is_interface_enabled() to exit with error
upon the FT260 device USB disconnect, which in turn, aborted the ft260_remove()
before deleting the FT260 i2c device and cleaning its sysfs stuff.

This commit restores the FT260 USB removal functionality and improves the
ft260_is_interface_enabled() code to handle correctly all chip modes defined
by the device interface configuration pins DCNF0 and DCNF1.
Signed-off-by: default avatarMichael Zaidman <michael.zaidman@gmail.com>
Acked-by: default avatarAaron Jones (FTDI-UK) <aaron.jones@ftdichip.com>
Signed-off-by: default avatarJiri Kosina <jkosina@suse.cz>
parent 7cc8524f
......@@ -742,7 +742,7 @@ static int ft260_is_interface_enabled(struct hid_device *hdev)
int ret;
ret = ft260_get_system_config(hdev, &cfg);
if (ret)
if (ret < 0)
return ret;
ft260_dbg("interface: 0x%02x\n", interface);
......@@ -754,23 +754,16 @@ static int ft260_is_interface_enabled(struct hid_device *hdev)
switch (cfg.chip_mode) {
case FT260_MODE_ALL:
case FT260_MODE_BOTH:
if (interface == 1) {
if (interface == 1)
hid_info(hdev, "uart interface is not supported\n");
return 0;
}
ret = 1;
else
ret = 1;
break;
case FT260_MODE_UART:
if (interface == 0) {
hid_info(hdev, "uart is unsupported on interface 0\n");
ret = 0;
}
hid_info(hdev, "uart interface is not supported\n");
break;
case FT260_MODE_I2C:
if (interface == 1) {
hid_info(hdev, "i2c is unsupported on interface 1\n");
ret = 0;
}
ret = 1;
break;
}
return ret;
......@@ -1004,11 +997,9 @@ static int ft260_probe(struct hid_device *hdev, const struct hid_device_id *id)
static void ft260_remove(struct hid_device *hdev)
{
int ret;
struct ft260_device *dev = hid_get_drvdata(hdev);
ret = ft260_is_interface_enabled(hdev);
if (ret <= 0)
if (!dev)
return;
sysfs_remove_group(&hdev->dev.kobj, &ft260_attr_group);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment