]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
HID: apple: Add support for magic keyboard backlight on T2 Macs
authorOrlando Chamberlain <orlandoch.dev@gmail.com>
Wed, 3 Jul 2024 17:54:11 +0000 (17:54 +0000)
committerBenjamin Tissoires <bentiss@kernel.org>
Thu, 4 Jul 2024 07:47:33 +0000 (09:47 +0200)
Unlike T2 Macs with Butterfly keyboard, who have their keyboard backlight
on the USB device the T2 Macs with Magic keyboard have their backlight on
the Touchbar backlight device (05ac:8102).

Support for Butterfly keyboards has already been added in
commit 9018eacbe623 ("HID: apple: Add support for keyboard backlight on
certain T2 Macs.") This patch adds support for the Magic keyboards.

Signed-off-by: Orlando Chamberlain <orlandoch.dev@gmail.com>
Co-developed-by: Aditya Garg <gargaditya08@live.com>
Signed-off-by: Aditya Garg <gargaditya08@live.com>
Link: https://patch.msgid.link/E1D444EA-7FD0-42DA-B198-50B0F03298FB@live.com
Signed-off-by: Benjamin Tissoires <bentiss@kernel.org>
drivers/hid/hid-apple.c

index bd022e0043569cc84c5323a53749e06f122dbcbe..6dedb84d7cc397107ae52f288db797b009bf6ee1 100644 (file)
@@ -8,6 +8,8 @@
  *  Copyright (c) 2006-2007 Jiri Kosina
  *  Copyright (c) 2008 Jiri Slaby <jirislaby@gmail.com>
  *  Copyright (c) 2019 Paul Pawlowski <paul@mrarm.io>
+ *  Copyright (c) 2023 Orlando Chamberlain <orlandoch.dev@gmail.com>
+ *  Copyright (c) 2024 Aditya Garg <gargaditya08@live.com>
  */
 
 /*
@@ -23,6 +25,7 @@
 #include <linux/timer.h>
 #include <linux/string.h>
 #include <linux/leds.h>
+#include <dt-bindings/leds/common.h>
 
 #include "hid-ids.h"
 
 #define APPLE_RDESC_BATTERY    BIT(9)
 #define APPLE_BACKLIGHT_CTL    BIT(10)
 #define APPLE_IS_NON_APPLE     BIT(11)
+#define APPLE_MAGIC_BACKLIGHT  BIT(12)
 
 #define APPLE_FLAG_FKEY                0x01
 
 #define HID_COUNTRY_INTERNATIONAL_ISO  13
 #define APPLE_BATTERY_TIMEOUT_MS       60000
 
+#define HID_USAGE_MAGIC_BL                     0xff00000f
+#define APPLE_MAGIC_REPORT_ID_POWER            3
+#define APPLE_MAGIC_REPORT_ID_BRIGHTNESS       1
+
 static unsigned int fnmode = 3;
 module_param(fnmode, uint, 0644);
 MODULE_PARM_DESC(fnmode, "Mode of fn key on Apple keyboards (0 = disabled, "
@@ -81,6 +89,12 @@ struct apple_sc_backlight {
        struct hid_device *hdev;
 };
 
+struct apple_magic_backlight {
+       struct led_classdev cdev;
+       struct hid_report *brightness;
+       struct hid_report *power;
+};
+
 struct apple_sc {
        struct hid_device *hdev;
        unsigned long quirks;
@@ -822,6 +836,66 @@ cleanup_and_exit:
        return ret;
 }
 
+static void apple_magic_backlight_report_set(struct hid_report *rep, s32 value, u8 rate)
+{
+       rep->field[0]->value[0] = value;
+       rep->field[1]->value[0] = 0x5e; /* Mimic Windows */
+       rep->field[1]->value[0] |= rate << 8;
+
+       hid_hw_request(rep->device, rep, HID_REQ_SET_REPORT);
+}
+
+static void apple_magic_backlight_set(struct apple_magic_backlight *backlight,
+                                    int brightness, char rate)
+{
+       apple_magic_backlight_report_set(backlight->power, brightness ? 1 : 0, rate);
+       if (brightness)
+               apple_magic_backlight_report_set(backlight->brightness, brightness, rate);
+}
+
+static int apple_magic_backlight_led_set(struct led_classdev *led_cdev,
+                                        enum led_brightness brightness)
+{
+       struct apple_magic_backlight *backlight = container_of(led_cdev,
+                       struct apple_magic_backlight, cdev);
+
+       apple_magic_backlight_set(backlight, brightness, 1);
+       return 0;
+}
+
+static int apple_magic_backlight_init(struct hid_device *hdev)
+{
+       struct apple_magic_backlight *backlight;
+       struct hid_report_enum *report_enum;
+
+       /*
+        * Ensure this usb endpoint is for the keyboard backlight, not touchbar
+        * backlight.
+        */
+       if (hdev->collection[0].usage != HID_USAGE_MAGIC_BL)
+               return -ENODEV;
+
+       backlight = devm_kzalloc(&hdev->dev, sizeof(*backlight), GFP_KERNEL);
+       if (!backlight)
+               return -ENOMEM;
+
+       report_enum = &hdev->report_enum[HID_FEATURE_REPORT];
+       backlight->brightness = report_enum->report_id_hash[APPLE_MAGIC_REPORT_ID_BRIGHTNESS];
+       backlight->power = report_enum->report_id_hash[APPLE_MAGIC_REPORT_ID_POWER];
+
+       if (!backlight->brightness || !backlight->power)
+               return -ENODEV;
+
+       backlight->cdev.name = ":white:" LED_FUNCTION_KBD_BACKLIGHT;
+       backlight->cdev.max_brightness = backlight->brightness->field[0]->logical_maximum;
+       backlight->cdev.brightness_set_blocking = apple_magic_backlight_led_set;
+
+       apple_magic_backlight_set(backlight, 0, 0);
+
+       return devm_led_classdev_register(&hdev->dev, &backlight->cdev);
+
+}
+
 static int apple_probe(struct hid_device *hdev,
                const struct hid_device_id *id)
 {
@@ -860,7 +934,18 @@ static int apple_probe(struct hid_device *hdev,
        if (quirks & APPLE_BACKLIGHT_CTL)
                apple_backlight_init(hdev);
 
+       if (quirks & APPLE_MAGIC_BACKLIGHT) {
+               ret = apple_magic_backlight_init(hdev);
+               if (ret)
+                       goto out_err;
+       }
+
        return 0;
+
+out_err:
+       del_timer_sync(&asc->battery_timer);
+       hid_hw_stop(hdev);
+       return ret;
 }
 
 static void apple_remove(struct hid_device *hdev)
@@ -1073,6 +1158,8 @@ static const struct hid_device_id apple_devices[] = {
                .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK | APPLE_RDESC_BATTERY },
        { HID_BLUETOOTH_DEVICE(BT_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_NUMPAD_2021),
                .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_TOUCHBAR_BACKLIGHT),
+               .driver_data = APPLE_MAGIC_BACKLIGHT },
 
        { }
 };