]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blobdiff - drivers/hid/hid-input.c
HID: Add quirk for HP X1200 PIXART OEM mouse
[mirror_ubuntu-bionic-kernel.git] / drivers / hid / hid-input.c
index 04d01b57d94c8280d2d6a63ef863136165555c11..4435512b8707bd5948ad688045631bda55638771 100644 (file)
@@ -325,6 +325,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 +390,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 +407,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 +490,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 +542,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);
        }
 }
@@ -664,6 +677,14 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
                        break;
                }
 
+               if ((usage->hid & 0xf0) == 0xb0) {      /* SC - Display */
+                       switch (usage->hid & 0xf) {
+                       case 0x05: map_key_clear(KEY_SWITCHVIDEOMODE); break;
+                       default: goto ignore;
+                       }
+                       break;
+               }
+
                /*
                 * Some lazy vendors declare 255 usages for System Control,
                 * leading to the creation of ABS_X|Y axis and too many others.
@@ -882,6 +903,10 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
                case 0x074: map_key_clear(KEY_BRIGHTNESS_MAX);          break;
                case 0x075: map_key_clear(KEY_BRIGHTNESS_AUTO);         break;
 
+               case 0x079: map_key_clear(KEY_KBDILLUMUP);      break;
+               case 0x07a: map_key_clear(KEY_KBDILLUMDOWN);    break;
+               case 0x07c: map_key_clear(KEY_KBDILLUMTOGGLE);  break;
+
                case 0x082: map_key_clear(KEY_VIDEO_NEXT);      break;
                case 0x083: map_key_clear(KEY_LAST);            break;
                case 0x084: map_key_clear(KEY_ENTER);           break;
@@ -969,6 +994,7 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
                case 0x1b8: map_key_clear(KEY_VIDEO);           break;
                case 0x1bc: map_key_clear(KEY_MESSENGER);       break;
                case 0x1bd: map_key_clear(KEY_INFO);            break;
+               case 0x1cb: map_key_clear(KEY_ASSISTANT);       break;
                case 0x201: map_key_clear(KEY_NEW);             break;
                case 0x202: map_key_clear(KEY_OPEN);            break;
                case 0x203: map_key_clear(KEY_CLOSE);           break;
@@ -1012,6 +1038,8 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
                case 0x2cb: map_key_clear(KEY_KBDINPUTASSIST_ACCEPT);   break;
                case 0x2cc: map_key_clear(KEY_KBDINPUTASSIST_CANCEL);   break;
 
+               case 0x29f: map_key_clear(KEY_SCALE);           break;
+
                default: map_key_clear(KEY_UNKNOWN);
                }
                break;
@@ -1368,7 +1396,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);