HID: wacom: Correct behavior when processing some confidence == false touches
[platform/kernel/linux-rpi.git] / drivers / hid / hid-logitech-hidpp.c
index a209d51..7bf12ca 100644 (file)
@@ -1835,15 +1835,14 @@ static int hidpp_battery_get_property(struct power_supply *psy,
 /* -------------------------------------------------------------------------- */
 #define HIDPP_PAGE_WIRELESS_DEVICE_STATUS                      0x1d4b
 
-static int hidpp_set_wireless_feature_index(struct hidpp_device *hidpp)
+static int hidpp_get_wireless_feature_index(struct hidpp_device *hidpp, u8 *feature_index)
 {
        u8 feature_type;
        int ret;
 
        ret = hidpp_root_get_feature(hidpp,
                                     HIDPP_PAGE_WIRELESS_DEVICE_STATUS,
-                                    &hidpp->wireless_feature_index,
-                                    &feature_type);
+                                    feature_index, &feature_type);
 
        return ret;
 }
@@ -4249,6 +4248,13 @@ static void hidpp_connect_event(struct hidpp_device *hidpp)
                }
        }
 
+       if (hidpp->protocol_major >= 2) {
+               u8 feature_index;
+
+               if (!hidpp_get_wireless_feature_index(hidpp, &feature_index))
+                       hidpp->wireless_feature_index = feature_index;
+       }
+
        if (hidpp->name == hdev->name && hidpp->protocol_major >= 2) {
                name = hidpp_get_device_name(hidpp);
                if (name) {
@@ -4394,7 +4400,6 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id)
        bool connected;
        unsigned int connect_mask = HID_CONNECT_DEFAULT;
        struct hidpp_ff_private_data data;
-       bool will_restart = false;
 
        /* report_fixup needs drvdata to be set before we call hid_parse */
        hidpp = devm_kzalloc(&hdev->dev, sizeof(*hidpp), GFP_KERNEL);
@@ -4445,10 +4450,6 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id)
                        return ret;
        }
 
-       if (hidpp->quirks & HIDPP_QUIRK_DELAYED_INIT ||
-           hidpp->quirks & HIDPP_QUIRK_UNIFYING)
-               will_restart = true;
-
        INIT_WORK(&hidpp->work, delayed_work_cb);
        mutex_init(&hidpp->send_mutex);
        init_waitqueue_head(&hidpp->wait);
@@ -4460,10 +4461,12 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id)
                         hdev->name);
 
        /*
-        * Plain USB connections need to actually call start and open
-        * on the transport driver to allow incoming data.
+        * First call hid_hw_start(hdev, 0) to allow IO without connecting any
+        * hid subdrivers (hid-input, hidraw). This allows retrieving the dev's
+        * name and serial number and store these in hdev->name and hdev->uniq,
+        * before the hid-input and hidraw drivers expose these to userspace.
         */
-       ret = hid_hw_start(hdev, will_restart ? 0 : connect_mask);
+       ret = hid_hw_start(hdev, 0);
        if (ret) {
                hid_err(hdev, "hw start failed\n");
                goto hid_hw_start_fail;
@@ -4496,15 +4499,6 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id)
                hidpp_overwrite_name(hdev);
        }
 
-       if (connected && hidpp->protocol_major >= 2) {
-               ret = hidpp_set_wireless_feature_index(hidpp);
-               if (ret == -ENOENT)
-                       hidpp->wireless_feature_index = 0;
-               else if (ret)
-                       goto hid_hw_init_fail;
-               ret = 0;
-       }
-
        if (connected && (hidpp->quirks & HIDPP_QUIRK_CLASS_WTP)) {
                ret = wtp_get_config(hidpp);
                if (ret)
@@ -4518,21 +4512,14 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id)
        schedule_work(&hidpp->work);
        flush_work(&hidpp->work);
 
-       if (will_restart) {
-               /* Reset the HID node state */
-               hid_device_io_stop(hdev);
-               hid_hw_close(hdev);
-               hid_hw_stop(hdev);
-
-               if (hidpp->quirks & HIDPP_QUIRK_DELAYED_INIT)
-                       connect_mask &= ~HID_CONNECT_HIDINPUT;
+       if (hidpp->quirks & HIDPP_QUIRK_DELAYED_INIT)
+               connect_mask &= ~HID_CONNECT_HIDINPUT;
 
-               /* Now export the actual inputs and hidraw nodes to the world */
-               ret = hid_hw_start(hdev, connect_mask);
-               if (ret) {
-                       hid_err(hdev, "%s:hid_hw_start returned error\n", __func__);
-                       goto hid_hw_start_fail;
-               }
+       /* Now export the actual inputs and hidraw nodes to the world */
+       ret = hid_connect(hdev, connect_mask);
+       if (ret) {
+               hid_err(hdev, "%s:hid_connect returned error %d\n", __func__, ret);
+               goto hid_hw_init_fail;
        }
 
        if (hidpp->quirks & HIDPP_QUIRK_CLASS_G920) {
@@ -4543,6 +4530,11 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id)
                                 ret);
        }
 
+       /*
+        * This relies on logi_dj_ll_close() being a no-op so that DJ connection
+        * events will still be received.
+        */
+       hid_hw_close(hdev);
        return ret;
 
 hid_hw_init_fail: