diff --git a/README.md b/README.md index 5db73e6..1f3f6b1 100644 --- a/README.md +++ b/README.md @@ -22,11 +22,10 @@ Travis kernel publish status - : - 5.2 kernel - random kernel panics - - -> Tested on: Macbook Pro 13" 2019 i5 TouchBar Z0WQ000AR +> Tested on: Macbook Pro 15,2 13" 2019 i5 TouchBar Z0WQ000AR MV972ZE/A/R1 #### Not working -- Keyboard backlight - Microphone - Dynamic audio outputs change (on connecting/disconnecting headphones jack) - Suspend/Resume (sleep mode) @@ -83,7 +82,8 @@ and the .txt to something like /lib/firmware/brcm/brcmfmac4364-pcie.Apple Inc.-M ### Github - GitHub issue (RE history): -- VHCI+Sound driver (Apple T2) +- VHCI+Sound driver (Apple T2): +- hid-apple keyboard backlight patch: - TouchBar driver: - Kernel patches (all are mentioned in github issue above): - ArchLinux kernel patches: diff --git a/patches/hid-apple-mod.patch b/patches/hid-apple-mod.patch index 85f185c..f74bc53 100644 --- a/patches/hid-apple-mod.patch +++ b/patches/hid-apple-mod.patch @@ -5,7 +5,23 @@ diff --git a/drivers/hid/hid-apple.c b/drivers/hid/hid-apple.c index 1cb4199..3f30d04 100644 --- a/drivers/hid/hid-apple.c +++ b/drivers/hid/hid-apple.c -@@ -54,6 +54,17 @@ MODULE_PARM_DESC(swap_opt_cmd, "Swap the Option (\"Alt\") and Command (\"Flag\") +@@ -6,6 +6,7 @@ + * Copyright (c) 2005 Michael Haboustak for Concept2, Inc + * Copyright (c) 2006-2007 Jiri Kosina + * Copyright (c) 2008 Jiri Slaby ++ * Copyright (c) 2019 Paul Pawlowski + */ + + /* +@@ -33,6 +34,7 @@ + #define APPLE_INVERT_HWHEEL 0x0040 + #define APPLE_IGNORE_HIDINPUT 0x0080 + #define APPLE_NUMLOCK_EMULATION 0x0100 ++#define APPLE_BACKLIGHT_CTL 0x0200 + + #define APPLE_FLAG_FKEY 0x01 + +@@ -54,11 +56,31 @@ "(For people who want to keep Windows PC keyboard muscle memory. " "[0] = as-is, Mac layout. 1 = swapped, Windows layout.)"); @@ -19,11 +35,25 @@ index 1cb4199..3f30d04 100644 +module_param(rightalt_as_rightctrl, uint, 0644); +MODULE_PARM_DESC(rightalt_as_rightctrl, "Use the right Alt key as a right Ctrl key. " + "[0] = as-is, Mac layout. 1 = Right Alt is right Ctrl"); ++ ++struct apple_sc_backlight; + struct apple_sc { unsigned long quirks; unsigned int fn_on; -@@ -166,6 +177,16 @@ static const struct apple_key_translation swapped_option_cmd_keys[] = { + DECLARE_BITMAP(pressed_fn, KEY_CNT); + DECLARE_BITMAP(pressed_numlock, KEY_CNT); ++ struct apple_sc_backlight *backlight; ++}; ++ ++struct apple_sc_backlight { ++ struct led_classdev cdev; ++ struct hid_device *hdev; ++ unsigned short backlight_off, backlight_on_min, backlight_on_max; + }; + + struct apple_key_translation { +@@ -166,6 +188,16 @@ { } }; @@ -40,7 +70,7 @@ index 1cb4199..3f30d04 100644 static const struct apple_key_translation *apple_find_translation( const struct apple_key_translation *table, u16 from) { -@@ -185,9 +206,11 @@ static int hidinput_apple_event(struct hid_device *hid, struct input_dev *input, +@@ -185,9 +217,11 @@ struct apple_sc *asc = hid_get_drvdata(hid); const struct apple_key_translation *trans, *table; @@ -54,7 +84,7 @@ index 1cb4199..3f30d04 100644 return 1; } -@@ -266,6 +289,22 @@ static int hidinput_apple_event(struct hid_device *hid, struct input_dev *input, +@@ -266,6 +300,22 @@ } } @@ -77,7 +107,7 @@ index 1cb4199..3f30d04 100644 return 0; } -@@ -329,6 +368,17 @@ static void apple_setup_input(struct input_dev *input) +@@ -329,6 +379,17 @@ for (trans = apple_iso_keyboard; trans->from; trans++) set_bit(trans->to, input->keybit); @@ -95,14 +125,133 @@ index 1cb4199..3f30d04 100644 } static int apple_input_mapping(struct hid_device *hdev, struct hid_input *hi, -@@ -557,6 +607,10 @@ static const struct hid_device_id apple_devices[] = { +@@ -366,6 +427,11 @@ + return 0; + } + ++static int apple_init_backlight(struct hid_device *hdev); ++static int apple_set_backlight(struct hid_device *hdev, u16 value, u16 rate); ++static int apple_led_set_backlight(struct led_classdev *led_cdev, ++ enum led_brightness brightness); ++ + static int apple_probe(struct hid_device *hdev, + const struct hid_device_id *id) + { +@@ -401,9 +467,106 @@ + return ret; + } + ++ if (quirks & APPLE_BACKLIGHT_CTL) ++ apple_init_backlight(hdev); ++ + return 0; + } + ++struct apple_backlight_config_report { ++ u8 report_id; ++ u8 version; ++ u16 backlight_off, backlight_on_min, backlight_on_max; ++}; ++struct apple_backlight_set_report { ++ u8 report_id; ++ u8 version; ++ u16 backlight; ++ u16 rate; ++}; ++ ++static bool apple_check_backlight_support(struct hid_device *hdev) ++{ ++ int i; ++ unsigned hid; ++ struct hid_report *report; ++ ++ list_for_each_entry(report, &hdev->report_enum[HID_INPUT_REPORT].report_list, list) { ++ for (i = 0; i < report->maxfield; i++) { ++ hid = report->field[i]->usage->hid; ++ if ((hid & HID_USAGE_PAGE) == HID_UP_MSVENDOR && (hid & HID_USAGE) == 0xf) ++ return true; ++ } ++ } ++ return false; ++} ++ ++static int apple_init_backlight(struct hid_device *hdev) ++{ ++ int ret; ++ struct apple_sc *asc = hid_get_drvdata(hdev); ++ struct apple_backlight_config_report *rep; ++ ++ if (!apple_check_backlight_support(hdev)) ++ return -EINVAL; ++ ++ rep = kmalloc(0x200, GFP_KERNEL); ++ ret = hid_hw_raw_request(hdev, 0xBFu, (u8 *) rep, sizeof(*rep), HID_FEATURE_REPORT, HID_REQ_GET_REPORT); ++ if (ret < 0) { ++ hid_err(hdev, "backlight request failed\n"); ++ return ret; ++ } ++ if (ret < 8 || rep->version != 1) { ++ hid_err(hdev, "backlight config struct: bad version %i\n", rep->version); ++ kfree(rep); ++ return -EINVAL; ++ } ++ ++ hid_dbg(hdev, "backlight config: off=%u, on_min=%u, on_max=%u\n", ++ rep->backlight_off, rep->backlight_on_min, rep->backlight_on_max); ++ ++ asc->backlight = devm_kzalloc(&hdev->dev, sizeof(*asc->backlight), GFP_KERNEL); ++ if (!asc->backlight) { ++ kfree(rep); ++ return -ENOMEM; ++ } ++ ++ asc->backlight->hdev = hdev; ++ asc->backlight->cdev.name = "apple::kbd_backlight"; ++ asc->backlight->cdev.max_brightness = rep->backlight_on_max; ++ asc->backlight->cdev.brightness_set_blocking = apple_led_set_backlight; ++ kfree(rep); ++ ++ apple_set_backlight(hdev, 0, 0); ++ ++ return devm_led_classdev_register(&hdev->dev, &asc->backlight->cdev); ++} ++ ++static int apple_set_backlight(struct hid_device *hdev, u16 value, u16 rate) ++{ ++ int ret; ++ struct apple_backlight_set_report *rep; ++ ++ rep = kmalloc(sizeof(*rep), GFP_KERNEL); ++ rep->report_id = 0xB0; ++ rep->version = 1; ++ rep->backlight = value; ++ rep->rate = rate; ++ ++ ret = hid_hw_raw_request(hdev, 0xB0u, (u8 *) rep, sizeof(*rep), HID_OUTPUT_REPORT, HID_REQ_SET_REPORT); ++ kfree(rep); ++ if (ret) ++ return ret; ++ return 0; ++} ++ ++static int apple_led_set_backlight(struct led_classdev *led_cdev, ++ enum led_brightness brightness) ++{ ++ struct apple_sc_backlight *backlight = container_of(led_cdev, struct apple_sc_backlight, cdev); ++ return apple_set_backlight(backlight->hdev, brightness, 0); ++} ++ + static const struct hid_device_id apple_devices[] = { + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MIGHTYMOUSE), + .driver_data = APPLE_MIGHTYMOUSE | APPLE_INVERT_HWHEEL }, +@@ -557,6 +720,10 @@ .driver_data = APPLE_HAS_FN }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING9_JIS), .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MBA8_1), -+ .driver_data = APPLE_HAS_FN }, ++ .driver_data = APPLE_HAS_FN | APPLE_BACKLIGHT_CTL }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MBP15_X), -+ .driver_data = APPLE_HAS_FN }, ++ .driver_data = APPLE_HAS_FN | APPLE_BACKLIGHT_CTL }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI), .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO),