[RAMEN9610-21858]HID: hid-input: clear unmapped usages
[GitHub/LineageOS/android_kernel_motorola_exynos9610.git] / drivers / hid / hid-input.c
index 199f6a01fc629ead34108da7ddc895269ed0820a..68811f41f2f21ca24134fe82294f65152d63edc0 100644 (file)
@@ -94,6 +94,8 @@ static bool match_index(struct hid_usage *usage,
 typedef bool (*hid_usage_cmp_t)(struct hid_usage *usage,
                                unsigned int cur_idx, unsigned int val);
 
+extern bool lcd_is_on;
+
 static struct hid_usage *hidinput_find_key(struct hid_device *hid,
                                           hid_usage_cmp_t match,
                                           unsigned int value,
@@ -325,6 +327,9 @@ static const struct hid_device_id hid_battery_quirks[] = {
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ELECOM,
                USB_DEVICE_ID_ELECOM_BM084),
          HID_BATTERY_QUIRK_IGNORE },
+       { HID_USB_DEVICE(USB_VENDOR_ID_SYMBOL,
+               USB_DEVICE_ID_SYMBOL_SCANNER_3),
+         HID_BATTERY_QUIRK_IGNORE },
        {}
 };
 
@@ -387,7 +392,8 @@ static int hidinput_get_battery_property(struct power_supply *psy,
                break;
 
        case POWER_SUPPLY_PROP_CAPACITY:
-               if (dev->battery_report_type == HID_FEATURE_REPORT) {
+               if (dev->battery_status != HID_BATTERY_REPORTED &&
+                   !dev->battery_avoid_query) {
                        value = hidinput_query_battery_capacity(dev);
                        if (value < 0)
                                return value;
@@ -403,17 +409,17 @@ static int hidinput_get_battery_property(struct power_supply *psy,
                break;
 
        case POWER_SUPPLY_PROP_STATUS:
-               if (!dev->battery_reported &&
-                   dev->battery_report_type == HID_FEATURE_REPORT) {
+               if (dev->battery_status != HID_BATTERY_REPORTED &&
+                   !dev->battery_avoid_query) {
                        value = hidinput_query_battery_capacity(dev);
                        if (value < 0)
                                return value;
 
                        dev->battery_capacity = value;
-                       dev->battery_reported = true;
+                       dev->battery_status = HID_BATTERY_QUERIED;
                }
 
-               if (!dev->battery_reported)
+               if (dev->battery_status == HID_BATTERY_UNKNOWN)
                        val->intval = POWER_SUPPLY_STATUS_UNKNOWN;
                else if (dev->battery_capacity == 100)
                        val->intval = POWER_SUPPLY_STATUS_FULL;
@@ -486,6 +492,14 @@ static int hidinput_setup_battery(struct hid_device *dev, unsigned report_type,
        dev->battery_report_type = report_type;
        dev->battery_report_id = field->report->id;
 
+       /*
+        * Stylus is normally not connected to the device and thus we
+        * can't query the device and get meaningful battery strength.
+        * We have to wait for the device to report it on its own.
+        */
+       dev->battery_avoid_query = report_type == HID_INPUT_REPORT &&
+                                  field->physical == HID_DG_STYLUS;
+
        dev->battery = power_supply_register(&dev->dev, psy_desc, &psy_cfg);
        if (IS_ERR(dev->battery)) {
                error = PTR_ERR(dev->battery);
@@ -530,9 +544,10 @@ static void hidinput_update_battery(struct hid_device *dev, int value)
 
        capacity = hidinput_scale_battery_capacity(dev, value);
 
-       if (!dev->battery_reported || capacity != dev->battery_capacity) {
+       if (dev->battery_status != HID_BATTERY_REPORTED ||
+           capacity != dev->battery_capacity) {
                dev->battery_capacity = capacity;
-               dev->battery_reported = true;
+               dev->battery_status = HID_BATTERY_REPORTED;
                power_supply_changed(dev->battery);
        }
 }
@@ -1085,9 +1100,15 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
        }
 
 mapped:
-       if (device->driver->input_mapped && device->driver->input_mapped(device,
-                               hidinput, field, usage, &bit, &max) < 0)
-               goto ignore;
+       if (device->driver->input_mapped &&
+           device->driver->input_mapped(device, hidinput, field, usage,
+                                        &bit, &max) < 0) {
+               /*
+                * The driver indicated that no further generic handling
+                * of the usage is desired.
+                */
+               return;
+       }
 
        set_bit(usage->type, input->evbit);
 
@@ -1145,9 +1166,11 @@ mapped:
                set_bit(MSC_SCAN, input->mscbit);
        }
 
-ignore:
        return;
 
+ignore:
+       usage->type = 0;
+       usage->code = 0;
 }
 
 void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct hid_usage *usage, __s32 value)
@@ -1359,7 +1382,8 @@ static void hidinput_led_worker(struct work_struct *work)
                                              led_work);
        struct hid_field *field;
        struct hid_report *report;
-       int len, ret;
+       int ret;
+       u32 len;
        __u8 *buf;
 
        field = hidinput_get_led_field(hid);
@@ -1391,6 +1415,11 @@ static void hidinput_led_worker(struct work_struct *work)
        if (!buf)
                return;
 
+       if (!lcd_is_on) {
+               kfree(buf);
+               return;
+       }
+
        hid_output_report(report, buf);
        /* synchronous output report */
        ret = hid_hw_output_report(hid, buf, len);