]> git.proxmox.com Git - mirror_ubuntu-hirsute-kernel.git/blobdiff - drivers/hid/hid-microsoft.c
HID: microsoft: Convert private data to be a proper struct
[mirror_ubuntu-hirsute-kernel.git] / drivers / hid / hid-microsoft.c
index 96e7d3231d2fbacf7f92f11915a9a4ef000a0920..1cbeeeabd2dd493032e2d7b745aea70b49c4b4ee 100644 (file)
 
 #include "hid-ids.h"
 
-#define MS_HIDINPUT            0x01
-#define MS_ERGONOMY            0x02
-#define MS_PRESENTER           0x04
-#define MS_RDESC               0x08
-#define MS_NOGET               0x10
-#define MS_DUPLICATE_USAGES    0x20
+#define MS_HIDINPUT            BIT(0)
+#define MS_ERGONOMY            BIT(1)
+#define MS_PRESENTER           BIT(2)
+#define MS_RDESC               BIT(3)
+#define MS_NOGET               BIT(4)
+#define MS_DUPLICATE_USAGES    BIT(5)
+#define MS_SURFACE_DIAL                BIT(6)
+
+struct ms_data {
+       unsigned long quirks;
+};
 
 static __u8 *ms_report_fixup(struct hid_device *hdev, __u8 *rdesc,
                unsigned int *rsize)
 {
-       unsigned long quirks = (unsigned long)hid_get_drvdata(hdev);
+       struct ms_data *ms = hid_get_drvdata(hdev);
+       unsigned long quirks = ms->quirks;
 
        /*
         * Microsoft Wireless Desktop Receiver (Model 1028) has
@@ -130,11 +136,36 @@ static int ms_presenter_8k_quirk(struct hid_input *hi, struct hid_usage *usage,
        return 1;
 }
 
+static int ms_surface_dial_quirk(struct hid_input *hi, struct hid_field *field,
+               struct hid_usage *usage, unsigned long **bit, int *max)
+{
+       switch (usage->hid & HID_USAGE_PAGE) {
+       case 0xff070000:
+               /* fall-through */
+       case HID_UP_DIGITIZER:
+               /* ignore those axis */
+               return -1;
+       case HID_UP_GENDESK:
+               switch (usage->hid) {
+               case HID_GD_X:
+                       /* fall-through */
+               case HID_GD_Y:
+                       /* fall-through */
+               case HID_GD_RFKILL_BTN:
+                       /* ignore those axis */
+                       return -1;
+               }
+       }
+
+       return 0;
+}
+
 static int ms_input_mapping(struct hid_device *hdev, struct hid_input *hi,
                struct hid_field *field, struct hid_usage *usage,
                unsigned long **bit, int *max)
 {
-       unsigned long quirks = (unsigned long)hid_get_drvdata(hdev);
+       struct ms_data *ms = hid_get_drvdata(hdev);
+       unsigned long quirks = ms->quirks;
 
        if (quirks & MS_ERGONOMY) {
                int ret = ms_ergonomy_kb_quirk(hi, usage, bit, max);
@@ -146,6 +177,13 @@ static int ms_input_mapping(struct hid_device *hdev, struct hid_input *hi,
                        ms_presenter_8k_quirk(hi, usage, bit, max))
                return 1;
 
+       if (quirks & MS_SURFACE_DIAL) {
+               int ret = ms_surface_dial_quirk(hi, field, usage, bit, max);
+
+               if (ret)
+                       return ret;
+       }
+
        return 0;
 }
 
@@ -153,7 +191,8 @@ static int ms_input_mapped(struct hid_device *hdev, struct hid_input *hi,
                struct hid_field *field, struct hid_usage *usage,
                unsigned long **bit, int *max)
 {
-       unsigned long quirks = (unsigned long)hid_get_drvdata(hdev);
+       struct ms_data *ms = hid_get_drvdata(hdev);
+       unsigned long quirks = ms->quirks;
 
        if (quirks & MS_DUPLICATE_USAGES)
                clear_bit(usage->code, *bit);
@@ -164,7 +203,8 @@ static int ms_input_mapped(struct hid_device *hdev, struct hid_input *hi,
 static int ms_event(struct hid_device *hdev, struct hid_field *field,
                struct hid_usage *usage, __s32 value)
 {
-       unsigned long quirks = (unsigned long)hid_get_drvdata(hdev);
+       struct ms_data *ms = hid_get_drvdata(hdev);
+       unsigned long quirks = ms->quirks;
        struct input_dev *input;
 
        if (!(hdev->claimed & HID_CLAIMED_INPUT) || !field->hidinput ||
@@ -222,13 +262,23 @@ static int ms_event(struct hid_device *hdev, struct hid_field *field,
 static int ms_probe(struct hid_device *hdev, const struct hid_device_id *id)
 {
        unsigned long quirks = id->driver_data;
+       struct ms_data *ms;
        int ret;
 
-       hid_set_drvdata(hdev, (void *)quirks);
+       ms = devm_kzalloc(&hdev->dev, sizeof(*ms), GFP_KERNEL);
+       if (ms == NULL)
+               return -ENOMEM;
+
+       ms->quirks = quirks;
+
+       hid_set_drvdata(hdev, ms);
 
        if (quirks & MS_NOGET)
                hdev->quirks |= HID_QUIRK_NOGET;
 
+       if (quirks & MS_SURFACE_DIAL)
+               hdev->quirks |= HID_QUIRK_INPUT_PER_APP;
+
        ret = hid_parse(hdev);
        if (ret) {
                hid_err(hdev, "parse failed\n");
@@ -281,6 +331,8 @@ static const struct hid_device_id ms_devices[] = {
 
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_BT),
                .driver_data = MS_PRESENTER },
+       { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, 0x091B),
+               .driver_data = MS_SURFACE_DIAL },
        { }
 };
 MODULE_DEVICE_TABLE(hid, ms_devices);