You've already forked linux-t2-patches
mirror of
https://github.com/t2linux/linux-t2-patches.git
synced 2026-04-30 13:52:11 -07:00
Add the new touch bar driver
This commit is contained in:
@@ -0,0 +1,115 @@
|
|||||||
|
From 75ca57b64ce6846622d8aefac5a76fc638a2123d Mon Sep 17 00:00:00 2001
|
||||||
|
From: Kerem Karabay <kekrby@gmail.com>
|
||||||
|
Date: Sun, 5 Mar 2023 19:12:53 +0300
|
||||||
|
Subject: [PATCH 01/12] HID: core: add helper for finding a field with a
|
||||||
|
certain usage
|
||||||
|
|
||||||
|
This helper will allow HID drivers to easily determine if they should
|
||||||
|
bind to a hid_device by checking for the prescence of a certain field
|
||||||
|
when its ID is not enough, which can be the case on USB devices with
|
||||||
|
multiple interfaces and/or configurations.
|
||||||
|
|
||||||
|
Signed-off-by: Kerem Karabay <kekrby@gmail.com>
|
||||||
|
---
|
||||||
|
drivers/hid/hid-core.c | 25 +++++++++++++++++++++++++
|
||||||
|
drivers/hid/hid-google-hammer.c | 27 ++-------------------------
|
||||||
|
include/linux/hid.h | 2 ++
|
||||||
|
3 files changed, 29 insertions(+), 25 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
|
||||||
|
index 8992e3c1e..6395bdc2e 100644
|
||||||
|
--- a/drivers/hid/hid-core.c
|
||||||
|
+++ b/drivers/hid/hid-core.c
|
||||||
|
@@ -1906,6 +1906,31 @@ int hid_set_field(struct hid_field *field, unsigned offset, __s32 value)
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(hid_set_field);
|
||||||
|
|
||||||
|
+struct hid_field *hid_find_field(struct hid_device *hdev, unsigned int report_type,
|
||||||
|
+ unsigned int application, unsigned int usage)
|
||||||
|
+{
|
||||||
|
+ struct list_head *report_list = &hdev->report_enum[report_type].report_list;
|
||||||
|
+ struct hid_report *report;
|
||||||
|
+ int i, j;
|
||||||
|
+
|
||||||
|
+ list_for_each_entry(report, report_list, list) {
|
||||||
|
+ if (report->application != application)
|
||||||
|
+ continue;
|
||||||
|
+
|
||||||
|
+ for (i = 0; i < report->maxfield; i++) {
|
||||||
|
+ struct hid_field *field = report->field[i];
|
||||||
|
+
|
||||||
|
+ for (j = 0; j < field->maxusage; j++) {
|
||||||
|
+ if (field->usage[j].hid == usage)
|
||||||
|
+ return field;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return NULL;
|
||||||
|
+}
|
||||||
|
+EXPORT_SYMBOL_GPL(hid_find_field);
|
||||||
|
+
|
||||||
|
static struct hid_report *hid_get_report(struct hid_report_enum *report_enum,
|
||||||
|
const u8 *data)
|
||||||
|
{
|
||||||
|
diff --git a/drivers/hid/hid-google-hammer.c b/drivers/hid/hid-google-hammer.c
|
||||||
|
index c6bdb9c4e..fba3652aa 100644
|
||||||
|
--- a/drivers/hid/hid-google-hammer.c
|
||||||
|
+++ b/drivers/hid/hid-google-hammer.c
|
||||||
|
@@ -419,38 +419,15 @@ static int hammer_event(struct hid_device *hid, struct hid_field *field,
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
-static bool hammer_has_usage(struct hid_device *hdev, unsigned int report_type,
|
||||||
|
- unsigned application, unsigned usage)
|
||||||
|
-{
|
||||||
|
- struct hid_report_enum *re = &hdev->report_enum[report_type];
|
||||||
|
- struct hid_report *report;
|
||||||
|
- int i, j;
|
||||||
|
-
|
||||||
|
- list_for_each_entry(report, &re->report_list, list) {
|
||||||
|
- if (report->application != application)
|
||||||
|
- continue;
|
||||||
|
-
|
||||||
|
- for (i = 0; i < report->maxfield; i++) {
|
||||||
|
- struct hid_field *field = report->field[i];
|
||||||
|
-
|
||||||
|
- for (j = 0; j < field->maxusage; j++)
|
||||||
|
- if (field->usage[j].hid == usage)
|
||||||
|
- return true;
|
||||||
|
- }
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- return false;
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
static bool hammer_has_folded_event(struct hid_device *hdev)
|
||||||
|
{
|
||||||
|
- return hammer_has_usage(hdev, HID_INPUT_REPORT,
|
||||||
|
+ return !!hid_find_field(hdev, HID_INPUT_REPORT,
|
||||||
|
HID_GD_KEYBOARD, HID_USAGE_KBD_FOLDED);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool hammer_has_backlight_control(struct hid_device *hdev)
|
||||||
|
{
|
||||||
|
- return hammer_has_usage(hdev, HID_OUTPUT_REPORT,
|
||||||
|
+ return !!hid_find_field(hdev, HID_OUTPUT_REPORT,
|
||||||
|
HID_GD_KEYBOARD, HID_AD_BRIGHTNESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
diff --git a/include/linux/hid.h b/include/linux/hid.h
|
||||||
|
index 39e21e381..9520fdfdd 100644
|
||||||
|
--- a/include/linux/hid.h
|
||||||
|
+++ b/include/linux/hid.h
|
||||||
|
@@ -913,6 +913,8 @@ extern void hidinput_report_event(struct hid_device *hid, struct hid_report *rep
|
||||||
|
extern int hidinput_connect(struct hid_device *hid, unsigned int force);
|
||||||
|
extern void hidinput_disconnect(struct hid_device *);
|
||||||
|
|
||||||
|
+struct hid_field *hid_find_field(struct hid_device *hdev, unsigned int report_type,
|
||||||
|
+ unsigned int application, unsigned int usage);
|
||||||
|
int hid_set_field(struct hid_field *, unsigned, __s32);
|
||||||
|
int hid_input_report(struct hid_device *hid, enum hid_report_type type, u8 *data, u32 size,
|
||||||
|
int interrupt);
|
||||||
|
--
|
||||||
|
2.42.0
|
||||||
|
|
||||||
@@ -0,0 +1,299 @@
|
|||||||
|
From 05cd738ce1c0e1a930a1dab02528fd9f1c702c38 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Kerem Karabay <kekrby@gmail.com>
|
||||||
|
Date: Sun, 5 Mar 2023 18:52:43 +0300
|
||||||
|
Subject: [PATCH 02/12] HID: hid-appletb-bl: add driver for the backlight of
|
||||||
|
Apple Touch Bars
|
||||||
|
MIME-Version: 1.0
|
||||||
|
Content-Type: text/plain; charset=UTF-8
|
||||||
|
Content-Transfer-Encoding: 8bit
|
||||||
|
|
||||||
|
This commit adds a driver for the backlight of Apple Touch Bars on x86
|
||||||
|
Macs. Note that currently only T2 Macs are supported.
|
||||||
|
|
||||||
|
This driver is based on previous work done by Ronald Tschalär
|
||||||
|
<ronald@innovation.ch>.
|
||||||
|
|
||||||
|
Signed-off-by: Kerem Karabay <kekrby@gmail.com>
|
||||||
|
---
|
||||||
|
MAINTAINERS | 6 ++
|
||||||
|
drivers/hid/Kconfig | 10 ++
|
||||||
|
drivers/hid/Makefile | 1 +
|
||||||
|
drivers/hid/hid-appletb-bl.c | 193 +++++++++++++++++++++++++++++++++++
|
||||||
|
drivers/hid/hid-quirks.c | 4 +-
|
||||||
|
5 files changed, 213 insertions(+), 1 deletion(-)
|
||||||
|
create mode 100644 drivers/hid/hid-appletb-bl.c
|
||||||
|
|
||||||
|
diff --git a/MAINTAINERS b/MAINTAINERS
|
||||||
|
index 4cc6bf79f..519b3b736 100644
|
||||||
|
--- a/MAINTAINERS
|
||||||
|
+++ b/MAINTAINERS
|
||||||
|
@@ -9157,6 +9157,12 @@ F: include/linux/pm.h
|
||||||
|
F: include/linux/suspend.h
|
||||||
|
F: kernel/power/
|
||||||
|
|
||||||
|
+HID APPLE TOUCH BAR DRIVERS
|
||||||
|
+M: Kerem Karabay <kekrby@gmail.com>
|
||||||
|
+L: linux-input@vger.kernel.org
|
||||||
|
+S: Maintained
|
||||||
|
+F: drivers/hid/hid-appletb-*
|
||||||
|
+
|
||||||
|
HID CORE LAYER
|
||||||
|
M: Jiri Kosina <jikos@kernel.org>
|
||||||
|
M: Benjamin Tissoires <benjamin.tissoires@redhat.com>
|
||||||
|
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
|
||||||
|
index e11c1c803..cf19a3b33 100644
|
||||||
|
--- a/drivers/hid/Kconfig
|
||||||
|
+++ b/drivers/hid/Kconfig
|
||||||
|
@@ -148,6 +148,16 @@ config HID_APPLEIR
|
||||||
|
|
||||||
|
Say Y here if you want support for Apple infrared remote control.
|
||||||
|
|
||||||
|
+config HID_APPLETB_BL
|
||||||
|
+ tristate "Apple Touch Bar Backlight"
|
||||||
|
+ depends on BACKLIGHT_CLASS_DEVICE
|
||||||
|
+ help
|
||||||
|
+ Say Y here if you want support for the backlight of Touch Bars on x86
|
||||||
|
+ MacBook Pros.
|
||||||
|
+
|
||||||
|
+ To compile this driver as a module, choose M here: the
|
||||||
|
+ module will be called hid-appletb-bl.
|
||||||
|
+
|
||||||
|
config HID_ASUS
|
||||||
|
tristate "Asus"
|
||||||
|
depends on USB_HID
|
||||||
|
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
|
||||||
|
index 7a9e16015..bc86e38b2 100644
|
||||||
|
--- a/drivers/hid/Makefile
|
||||||
|
+++ b/drivers/hid/Makefile
|
||||||
|
@@ -29,6 +29,7 @@ obj-$(CONFIG_HID_ALPS) += hid-alps.o
|
||||||
|
obj-$(CONFIG_HID_ACRUX) += hid-axff.o
|
||||||
|
obj-$(CONFIG_HID_APPLE) += hid-apple.o
|
||||||
|
obj-$(CONFIG_HID_APPLEIR) += hid-appleir.o
|
||||||
|
+obj-$(CONFIG_HID_APPLETB_BL) += hid-appletb-bl.o
|
||||||
|
obj-$(CONFIG_HID_CREATIVE_SB0540) += hid-creative-sb0540.o
|
||||||
|
obj-$(CONFIG_HID_ASUS) += hid-asus.o
|
||||||
|
obj-$(CONFIG_HID_AUREAL) += hid-aureal.o
|
||||||
|
diff --git a/drivers/hid/hid-appletb-bl.c b/drivers/hid/hid-appletb-bl.c
|
||||||
|
new file mode 100644
|
||||||
|
index 000000000..0c5e4b776
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/drivers/hid/hid-appletb-bl.c
|
||||||
|
@@ -0,0 +1,193 @@
|
||||||
|
+// SPDX-License-Identifier: GPL-2.0
|
||||||
|
+/*
|
||||||
|
+ * Apple Touch Bar Backlight Driver
|
||||||
|
+ *
|
||||||
|
+ * Copyright (c) 2017-2018 Ronald Tschalär
|
||||||
|
+ * Copyright (c) 2022-2023 Kerem Karabay <kekrby@gmail.com>
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||||
|
+
|
||||||
|
+#include <linux/hid.h>
|
||||||
|
+#include <linux/backlight.h>
|
||||||
|
+
|
||||||
|
+#include "hid-ids.h"
|
||||||
|
+
|
||||||
|
+#define APPLETB_BL_ON 1
|
||||||
|
+#define APPLETB_BL_DIM 3
|
||||||
|
+#define APPLETB_BL_OFF 4
|
||||||
|
+
|
||||||
|
+#define HID_UP_APPLEVENDOR_TB_BL 0xff120000
|
||||||
|
+
|
||||||
|
+#define HID_VD_APPLE_TB_BRIGHTNESS 0xff120001
|
||||||
|
+#define HID_USAGE_AUX1 0xff120020
|
||||||
|
+#define HID_USAGE_BRIGHTNESS 0xff120021
|
||||||
|
+
|
||||||
|
+struct appletb_bl {
|
||||||
|
+ struct hid_field *aux1_field, *brightness_field;
|
||||||
|
+ struct backlight_device *bdev;
|
||||||
|
+
|
||||||
|
+ bool full_on;
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+const u8 appletb_bl_brightness_map[] = {
|
||||||
|
+ APPLETB_BL_OFF,
|
||||||
|
+ APPLETB_BL_DIM,
|
||||||
|
+ APPLETB_BL_ON
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+static int appletb_bl_set_brightness(struct appletb_bl *bl, u8 brightness)
|
||||||
|
+{
|
||||||
|
+ struct hid_report *report = bl->brightness_field->report;
|
||||||
|
+ struct hid_device *hdev = report->device;
|
||||||
|
+ int ret;
|
||||||
|
+
|
||||||
|
+ ret = hid_set_field(bl->aux1_field, 0, 1);
|
||||||
|
+ if (ret) {
|
||||||
|
+ hid_err(hdev, "Failed to set auxiliary field (%pe)\n", ERR_PTR(ret));
|
||||||
|
+ return ret;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ ret = hid_set_field(bl->brightness_field, 0, brightness);
|
||||||
|
+ if (ret) {
|
||||||
|
+ hid_err(hdev, "Failed to set brightness field (%pe)\n", ERR_PTR(ret));
|
||||||
|
+ return ret;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (!bl->full_on) {
|
||||||
|
+ ret = hid_hw_power(hdev, PM_HINT_FULLON);
|
||||||
|
+ if (ret < 0) {
|
||||||
|
+ hid_err(hdev, "Device didn't power on (%pe)\n", ERR_PTR(ret));
|
||||||
|
+ return ret;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ bl->full_on = true;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ hid_hw_request(hdev, report, HID_REQ_SET_REPORT);
|
||||||
|
+
|
||||||
|
+ if (brightness == APPLETB_BL_OFF) {
|
||||||
|
+ hid_hw_power(hdev, PM_HINT_NORMAL);
|
||||||
|
+ bl->full_on = false;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int appletb_bl_update_status(struct backlight_device *bdev)
|
||||||
|
+{
|
||||||
|
+ struct appletb_bl *bl = bl_get_data(bdev);
|
||||||
|
+ u16 brightness;
|
||||||
|
+
|
||||||
|
+ if (bdev->props.state & BL_CORE_SUSPENDED)
|
||||||
|
+ brightness = 0;
|
||||||
|
+ else
|
||||||
|
+ brightness = backlight_get_brightness(bdev);
|
||||||
|
+
|
||||||
|
+ return appletb_bl_set_brightness(bl, appletb_bl_brightness_map[brightness]);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static const struct backlight_ops appletb_bl_backlight_ops = {
|
||||||
|
+ .options = BL_CORE_SUSPENDRESUME,
|
||||||
|
+ .update_status = appletb_bl_update_status,
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+static int appletb_bl_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
||||||
|
+{
|
||||||
|
+ struct hid_field *aux1_field, *brightness_field;
|
||||||
|
+ struct backlight_properties bl_props = { 0 };
|
||||||
|
+ struct device *dev = &hdev->dev;
|
||||||
|
+ struct appletb_bl *bl;
|
||||||
|
+ int ret;
|
||||||
|
+
|
||||||
|
+ ret = hid_parse(hdev);
|
||||||
|
+ if (ret)
|
||||||
|
+ return dev_err_probe(dev, ret, "HID parse failed\n");
|
||||||
|
+
|
||||||
|
+ aux1_field = hid_find_field(hdev, HID_FEATURE_REPORT,
|
||||||
|
+ HID_VD_APPLE_TB_BRIGHTNESS, HID_USAGE_AUX1);
|
||||||
|
+
|
||||||
|
+ brightness_field = hid_find_field(hdev, HID_FEATURE_REPORT,
|
||||||
|
+ HID_VD_APPLE_TB_BRIGHTNESS, HID_USAGE_BRIGHTNESS);
|
||||||
|
+
|
||||||
|
+ if (!aux1_field || !brightness_field)
|
||||||
|
+ return -ENODEV;
|
||||||
|
+
|
||||||
|
+ if (aux1_field->report != brightness_field->report)
|
||||||
|
+ return dev_err_probe(dev, -ENODEV, "Encountered unexpected report structure\n");
|
||||||
|
+
|
||||||
|
+ bl = devm_kzalloc(dev, sizeof(*bl), GFP_KERNEL);
|
||||||
|
+ if (!bl)
|
||||||
|
+ return -ENOMEM;
|
||||||
|
+
|
||||||
|
+ ret = hid_hw_start(hdev, HID_CONNECT_DRIVER);
|
||||||
|
+ if (ret)
|
||||||
|
+ return dev_err_probe(dev, ret, "HID hardware start failed\n");
|
||||||
|
+
|
||||||
|
+ ret = hid_hw_open(hdev);
|
||||||
|
+ if (ret) {
|
||||||
|
+ dev_err_probe(dev, ret, "HID hardware open failed\n");
|
||||||
|
+ goto stop_hw;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ bl->aux1_field = aux1_field;
|
||||||
|
+ bl->brightness_field = brightness_field;
|
||||||
|
+
|
||||||
|
+ ret = appletb_bl_set_brightness(bl, APPLETB_BL_OFF);
|
||||||
|
+ if (ret) {
|
||||||
|
+ dev_err_probe(dev, ret, "Failed to set touch bar brightness to off\n");
|
||||||
|
+ goto close_hw;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ bl_props.type = BACKLIGHT_RAW;
|
||||||
|
+ bl_props.max_brightness = ARRAY_SIZE(appletb_bl_brightness_map) - 1;
|
||||||
|
+
|
||||||
|
+ bl->bdev = devm_backlight_device_register(dev, "appletb_backlight", dev, bl,
|
||||||
|
+ &appletb_bl_backlight_ops, &bl_props);
|
||||||
|
+ if (IS_ERR(bl->bdev)) {
|
||||||
|
+ ret = PTR_ERR(bl->bdev);
|
||||||
|
+ dev_err_probe(dev, ret, "Failed to register backlight device\n");
|
||||||
|
+ goto close_hw;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ hid_set_drvdata(hdev, bl);
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+
|
||||||
|
+close_hw:
|
||||||
|
+ hid_hw_close(hdev);
|
||||||
|
+stop_hw:
|
||||||
|
+ hid_hw_stop(hdev);
|
||||||
|
+
|
||||||
|
+ return ret;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void appletb_bl_remove(struct hid_device *hdev)
|
||||||
|
+{
|
||||||
|
+ struct appletb_bl *bl = hid_get_drvdata(hdev);
|
||||||
|
+
|
||||||
|
+ appletb_bl_set_brightness(bl, APPLETB_BL_OFF);
|
||||||
|
+
|
||||||
|
+ hid_hw_close(hdev);
|
||||||
|
+ hid_hw_stop(hdev);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static const struct hid_device_id appletb_bl_hid_ids[] = {
|
||||||
|
+ /* MacBook Pro's 2018, 2019, with T2 chip: iBridge DFR Brightness */
|
||||||
|
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_TOUCHBAR_BACKLIGHT) },
|
||||||
|
+ { }
|
||||||
|
+};
|
||||||
|
+MODULE_DEVICE_TABLE(hid, appletb_bl_hid_ids);
|
||||||
|
+
|
||||||
|
+static struct hid_driver appletb_bl_hid_driver = {
|
||||||
|
+ .name = "hid-appletb-bl",
|
||||||
|
+ .id_table = appletb_bl_hid_ids,
|
||||||
|
+ .probe = appletb_bl_probe,
|
||||||
|
+ .remove = appletb_bl_remove,
|
||||||
|
+};
|
||||||
|
+module_hid_driver(appletb_bl_hid_driver);
|
||||||
|
+
|
||||||
|
+MODULE_AUTHOR("Ronald Tschalär");
|
||||||
|
+MODULE_AUTHOR("Kerem Karabay <kekrby@gmail.com>");
|
||||||
|
+MODULE_DESCRIPTION("MacBookPro Touch Bar Backlight Driver");
|
||||||
|
+MODULE_LICENSE("GPL");
|
||||||
|
diff --git a/drivers/hid/hid-quirks.c b/drivers/hid/hid-quirks.c
|
||||||
|
index 3983b4f28..82e7a80c9 100644
|
||||||
|
--- a/drivers/hid/hid-quirks.c
|
||||||
|
+++ b/drivers/hid/hid-quirks.c
|
||||||
|
@@ -325,7 +325,6 @@ static const struct hid_device_id hid_have_special_driver[] = {
|
||||||
|
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) },
|
||||||
|
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_2021) },
|
||||||
|
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_FINGERPRINT_2021) },
|
||||||
|
- { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_TOUCHBAR_BACKLIGHT) },
|
||||||
|
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_TOUCHBAR_DISPLAY) },
|
||||||
|
#endif
|
||||||
|
#if IS_ENABLED(CONFIG_HID_APPLEIR)
|
||||||
|
@@ -335,6 +334,9 @@ static const struct hid_device_id hid_have_special_driver[] = {
|
||||||
|
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL4) },
|
||||||
|
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL5) },
|
||||||
|
#endif
|
||||||
|
+#if IS_ENABLED(CONFIG_HID_APPLETB_BL)
|
||||||
|
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_TOUCHBAR_BACKLIGHT) },
|
||||||
|
+#endif
|
||||||
|
#if IS_ENABLED(CONFIG_HID_ASUS)
|
||||||
|
{ HID_I2C_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_I2C_KEYBOARD) },
|
||||||
|
{ HID_I2C_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_I2C_TOUCHPAD) },
|
||||||
|
--
|
||||||
|
2.42.0
|
||||||
|
|
||||||
@@ -0,0 +1,404 @@
|
|||||||
|
From 514b4f088b7ed916c634ca6f61de72c5f86268dd Mon Sep 17 00:00:00 2001
|
||||||
|
From: Kerem Karabay <kekrby@gmail.com>
|
||||||
|
Date: Sun, 5 Mar 2023 18:17:23 +0300
|
||||||
|
Subject: [PATCH 03/12] HID: hid-appletb-kbd: add driver for the keyboard mode
|
||||||
|
of Apple Touch Bars
|
||||||
|
MIME-Version: 1.0
|
||||||
|
Content-Type: text/plain; charset=UTF-8
|
||||||
|
Content-Transfer-Encoding: 8bit
|
||||||
|
|
||||||
|
The Touch Bars found on x86 Macs support two USB configurations: one
|
||||||
|
where the device presents itself as a HID keyboard and can display
|
||||||
|
predefined sets of keys, and one where the operating system has full
|
||||||
|
control over what is displayed. This commit adds a driver for the
|
||||||
|
display functionality of the first configuration.
|
||||||
|
|
||||||
|
Note that currently only T2 Macs are supported.
|
||||||
|
|
||||||
|
This driver is based on previous work done by Ronald Tschalär
|
||||||
|
<ronald@innovation.ch>.
|
||||||
|
|
||||||
|
Signed-off-by: Kerem Karabay <kekrby@gmail.com>
|
||||||
|
---
|
||||||
|
.../ABI/testing/sysfs-driver-hid-appletb-kbd | 13 +
|
||||||
|
drivers/hid/Kconfig | 11 +
|
||||||
|
drivers/hid/Makefile | 1 +
|
||||||
|
drivers/hid/hid-appletb-kbd.c | 289 ++++++++++++++++++
|
||||||
|
drivers/hid/hid-quirks.c | 4 +-
|
||||||
|
5 files changed, 317 insertions(+), 1 deletion(-)
|
||||||
|
create mode 100644 Documentation/ABI/testing/sysfs-driver-hid-appletb-kbd
|
||||||
|
create mode 100644 drivers/hid/hid-appletb-kbd.c
|
||||||
|
|
||||||
|
diff --git a/Documentation/ABI/testing/sysfs-driver-hid-appletb-kbd b/Documentation/ABI/testing/sysfs-driver-hid-appletb-kbd
|
||||||
|
new file mode 100644
|
||||||
|
index 000000000..2a19584d0
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/Documentation/ABI/testing/sysfs-driver-hid-appletb-kbd
|
||||||
|
@@ -0,0 +1,13 @@
|
||||||
|
+What: /sys/bus/hid/drivers/hid-appletb-kbd/<dev>/mode
|
||||||
|
+Date: September, 2023
|
||||||
|
+KernelVersion: 6.5
|
||||||
|
+Contact: linux-input@vger.kernel.org
|
||||||
|
+Description:
|
||||||
|
+ The set of keys displayed on the Touch Bar.
|
||||||
|
+ Valid values are:
|
||||||
|
+ == =================
|
||||||
|
+ 0 Escape key only
|
||||||
|
+ 1 Function keys
|
||||||
|
+ 2 Media/brightness keys
|
||||||
|
+ 3 None
|
||||||
|
+ == =================
|
||||||
|
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
|
||||||
|
index cf19a3b33..852de13aa 100644
|
||||||
|
--- a/drivers/hid/Kconfig
|
||||||
|
+++ b/drivers/hid/Kconfig
|
||||||
|
@@ -158,6 +158,17 @@ config HID_APPLETB_BL
|
||||||
|
To compile this driver as a module, choose M here: the
|
||||||
|
module will be called hid-appletb-bl.
|
||||||
|
|
||||||
|
+config HID_APPLETB_KBD
|
||||||
|
+ tristate "Apple Touch Bar Keyboard Mode"
|
||||||
|
+ depends on USB_HID
|
||||||
|
+ help
|
||||||
|
+ Say Y here if you want support for the keyboard mode (escape,
|
||||||
|
+ function, media and brightness keys) of Touch Bars on x86 MacBook
|
||||||
|
+ Pros.
|
||||||
|
+
|
||||||
|
+ To compile this driver as a module, choose M here: the
|
||||||
|
+ module will be called hid-appletb-kbd.
|
||||||
|
+
|
||||||
|
config HID_ASUS
|
||||||
|
tristate "Asus"
|
||||||
|
depends on USB_HID
|
||||||
|
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
|
||||||
|
index bc86e38b2..5b60015fd 100644
|
||||||
|
--- a/drivers/hid/Makefile
|
||||||
|
+++ b/drivers/hid/Makefile
|
||||||
|
@@ -30,6 +30,7 @@ obj-$(CONFIG_HID_ACRUX) += hid-axff.o
|
||||||
|
obj-$(CONFIG_HID_APPLE) += hid-apple.o
|
||||||
|
obj-$(CONFIG_HID_APPLEIR) += hid-appleir.o
|
||||||
|
obj-$(CONFIG_HID_APPLETB_BL) += hid-appletb-bl.o
|
||||||
|
+obj-$(CONFIG_HID_APPLETB_KBD) += hid-appletb-kbd.o
|
||||||
|
obj-$(CONFIG_HID_CREATIVE_SB0540) += hid-creative-sb0540.o
|
||||||
|
obj-$(CONFIG_HID_ASUS) += hid-asus.o
|
||||||
|
obj-$(CONFIG_HID_AUREAL) += hid-aureal.o
|
||||||
|
diff --git a/drivers/hid/hid-appletb-kbd.c b/drivers/hid/hid-appletb-kbd.c
|
||||||
|
new file mode 100644
|
||||||
|
index 000000000..bc004c408
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/drivers/hid/hid-appletb-kbd.c
|
||||||
|
@@ -0,0 +1,289 @@
|
||||||
|
+// SPDX-License-Identifier: GPL-2.0
|
||||||
|
+/*
|
||||||
|
+ * Apple Touch Bar Keyboard Mode Driver
|
||||||
|
+ *
|
||||||
|
+ * Copyright (c) 2017-2018 Ronald Tschalär
|
||||||
|
+ * Copyright (c) 2022-2023 Kerem Karabay <kekrby@gmail.com>
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||||
|
+
|
||||||
|
+#include <linux/hid.h>
|
||||||
|
+#include <linux/usb.h>
|
||||||
|
+#include <linux/input.h>
|
||||||
|
+#include <linux/sysfs.h>
|
||||||
|
+#include <linux/bitops.h>
|
||||||
|
+#include <linux/module.h>
|
||||||
|
+#include <linux/string.h>
|
||||||
|
+#include <linux/input/sparse-keymap.h>
|
||||||
|
+
|
||||||
|
+#include "hid-ids.h"
|
||||||
|
+
|
||||||
|
+#define APPLETB_KBD_MODE_ESC 0
|
||||||
|
+#define APPLETB_KBD_MODE_FN 1
|
||||||
|
+#define APPLETB_KBD_MODE_SPCL 2
|
||||||
|
+#define APPLETB_KBD_MODE_OFF 3
|
||||||
|
+#define APPLETB_KBD_MODE_MAX APPLETB_KBD_MODE_OFF
|
||||||
|
+
|
||||||
|
+#define HID_USAGE_MODE 0x00ff0004
|
||||||
|
+
|
||||||
|
+struct appletb_kbd {
|
||||||
|
+ struct hid_field *mode_field;
|
||||||
|
+
|
||||||
|
+ u8 saved_mode;
|
||||||
|
+ u8 current_mode;
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+static const struct key_entry appletb_kbd_keymap[] = {
|
||||||
|
+ { KE_KEY, KEY_ESC, { KEY_ESC } },
|
||||||
|
+ { KE_KEY, KEY_F1, { KEY_BRIGHTNESSDOWN } },
|
||||||
|
+ { KE_KEY, KEY_F2, { KEY_BRIGHTNESSUP } },
|
||||||
|
+ { KE_KEY, KEY_F3, { KEY_RESERVED } },
|
||||||
|
+ { KE_KEY, KEY_F4, { KEY_RESERVED } },
|
||||||
|
+ { KE_KEY, KEY_F5, { KEY_KBDILLUMDOWN } },
|
||||||
|
+ { KE_KEY, KEY_F6, { KEY_KBDILLUMUP } },
|
||||||
|
+ { KE_KEY, KEY_F7, { KEY_PREVIOUSSONG } },
|
||||||
|
+ { KE_KEY, KEY_F8, { KEY_PLAYPAUSE } },
|
||||||
|
+ { KE_KEY, KEY_F9, { KEY_NEXTSONG } },
|
||||||
|
+ { KE_KEY, KEY_F10, { KEY_MUTE } },
|
||||||
|
+ { KE_KEY, KEY_F11, { KEY_VOLUMEDOWN } },
|
||||||
|
+ { KE_KEY, KEY_F12, { KEY_VOLUMEUP } },
|
||||||
|
+ { KE_END, 0 }
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+static int appletb_kbd_set_mode(struct appletb_kbd *kbd, u8 mode)
|
||||||
|
+{
|
||||||
|
+ struct hid_report *report = kbd->mode_field->report;
|
||||||
|
+ struct hid_device *hdev = report->device;
|
||||||
|
+ int ret;
|
||||||
|
+
|
||||||
|
+ ret = hid_hw_power(hdev, PM_HINT_FULLON);
|
||||||
|
+ if (ret) {
|
||||||
|
+ hid_err(hdev, "Device didn't resume (%pe)\n", ERR_PTR(ret));
|
||||||
|
+ return ret;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ ret = hid_set_field(kbd->mode_field, 0, mode);
|
||||||
|
+ if (ret) {
|
||||||
|
+ hid_err(hdev, "Failed to set mode field to %u (%pe)\n", mode, ERR_PTR(ret));
|
||||||
|
+ goto power_normal;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ hid_hw_request(hdev, report, HID_REQ_SET_REPORT);
|
||||||
|
+
|
||||||
|
+ kbd->current_mode = mode;
|
||||||
|
+
|
||||||
|
+power_normal:
|
||||||
|
+ hid_hw_power(hdev, PM_HINT_NORMAL);
|
||||||
|
+
|
||||||
|
+ return ret;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static ssize_t mode_show(struct device *dev,
|
||||||
|
+ struct device_attribute *attr, char *buf)
|
||||||
|
+{
|
||||||
|
+ struct appletb_kbd *kbd = dev_get_drvdata(dev);
|
||||||
|
+
|
||||||
|
+ return sysfs_emit(buf, "%d\n", kbd->current_mode);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static ssize_t mode_store(struct device *dev,
|
||||||
|
+ struct device_attribute *attr,
|
||||||
|
+ const char *buf, size_t size)
|
||||||
|
+{
|
||||||
|
+ struct appletb_kbd *kbd = dev_get_drvdata(dev);
|
||||||
|
+ u8 mode;
|
||||||
|
+ int ret;
|
||||||
|
+
|
||||||
|
+ ret = kstrtou8(buf, 0, &mode);
|
||||||
|
+ if (ret)
|
||||||
|
+ return ret;
|
||||||
|
+
|
||||||
|
+ if (mode > APPLETB_KBD_MODE_MAX)
|
||||||
|
+ return -EINVAL;
|
||||||
|
+
|
||||||
|
+ ret = appletb_kbd_set_mode(kbd, mode);
|
||||||
|
+
|
||||||
|
+ return ret < 0 ? ret : size;
|
||||||
|
+}
|
||||||
|
+static DEVICE_ATTR_RW(mode);
|
||||||
|
+
|
||||||
|
+struct attribute *appletb_kbd_attrs[] = {
|
||||||
|
+ &dev_attr_mode.attr,
|
||||||
|
+ NULL
|
||||||
|
+};
|
||||||
|
+ATTRIBUTE_GROUPS(appletb_kbd);
|
||||||
|
+
|
||||||
|
+static int appletb_tb_key_to_slot(unsigned int code)
|
||||||
|
+{
|
||||||
|
+ switch (code) {
|
||||||
|
+ case KEY_ESC:
|
||||||
|
+ return 0;
|
||||||
|
+ case KEY_F1 ... KEY_F10:
|
||||||
|
+ return code - KEY_F1 + 1;
|
||||||
|
+ case KEY_F11 ... KEY_F12:
|
||||||
|
+ return code - KEY_F11 + 11;
|
||||||
|
+
|
||||||
|
+ default:
|
||||||
|
+ return -EINVAL;
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int appletb_kbd_hid_event(struct hid_device *hdev, struct hid_field *field,
|
||||||
|
+ struct hid_usage *usage, __s32 value)
|
||||||
|
+{
|
||||||
|
+ struct appletb_kbd *kbd = hid_get_drvdata(hdev);
|
||||||
|
+ struct key_entry *translation;
|
||||||
|
+ struct input_dev *input;
|
||||||
|
+ int slot;
|
||||||
|
+
|
||||||
|
+ if ((usage->hid & HID_USAGE_PAGE) != HID_UP_KEYBOARD || usage->type != EV_KEY)
|
||||||
|
+ return 0;
|
||||||
|
+
|
||||||
|
+ input = field->hidinput->input;
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ * Skip non-touch-bar keys.
|
||||||
|
+ *
|
||||||
|
+ * Either the touch bar itself or usbhid generate a slew of key-down
|
||||||
|
+ * events for all the meta keys. None of which we're at all interested
|
||||||
|
+ * in.
|
||||||
|
+ */
|
||||||
|
+ slot = appletb_tb_key_to_slot(usage->code);
|
||||||
|
+ if (slot < 0)
|
||||||
|
+ return 0;
|
||||||
|
+
|
||||||
|
+ translation = sparse_keymap_entry_from_scancode(input, usage->code);
|
||||||
|
+
|
||||||
|
+ if (translation && kbd->current_mode == APPLETB_KBD_MODE_SPCL) {
|
||||||
|
+ input_event(input, usage->type, translation->keycode, value);
|
||||||
|
+
|
||||||
|
+ return 1;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return kbd->current_mode == APPLETB_KBD_MODE_OFF;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int appletb_kbd_input_configured(struct hid_device *hdev, struct hid_input *hidinput)
|
||||||
|
+{
|
||||||
|
+ struct input_dev *input = hidinput->input;
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ * Clear various input capabilities that are blindly set by the hid
|
||||||
|
+ * driver (usbkbd.c)
|
||||||
|
+ */
|
||||||
|
+ memset(input->evbit, 0, sizeof(input->evbit));
|
||||||
|
+ memset(input->keybit, 0, sizeof(input->keybit));
|
||||||
|
+ memset(input->ledbit, 0, sizeof(input->ledbit));
|
||||||
|
+
|
||||||
|
+ __set_bit(EV_REP, input->evbit);
|
||||||
|
+
|
||||||
|
+ return sparse_keymap_setup(input, appletb_kbd_keymap, NULL);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int appletb_kbd_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
||||||
|
+{
|
||||||
|
+ struct appletb_kbd *kbd;
|
||||||
|
+ struct device *dev = &hdev->dev;
|
||||||
|
+ struct hid_field *mode_field;
|
||||||
|
+ int ret;
|
||||||
|
+
|
||||||
|
+ ret = hid_parse(hdev);
|
||||||
|
+ if (ret)
|
||||||
|
+ return dev_err_probe(dev, ret, "HID parse failed\n");
|
||||||
|
+
|
||||||
|
+ mode_field = hid_find_field(hdev, HID_OUTPUT_REPORT,
|
||||||
|
+ HID_GD_KEYBOARD, HID_USAGE_MODE);
|
||||||
|
+ if (!mode_field)
|
||||||
|
+ return -ENODEV;
|
||||||
|
+
|
||||||
|
+ kbd = devm_kzalloc(dev, sizeof(*kbd), GFP_KERNEL);
|
||||||
|
+ if (!kbd)
|
||||||
|
+ return -ENOMEM;
|
||||||
|
+
|
||||||
|
+ kbd->mode_field = mode_field;
|
||||||
|
+
|
||||||
|
+ ret = hid_hw_start(hdev, HID_CONNECT_HIDINPUT);
|
||||||
|
+ if (ret)
|
||||||
|
+ return dev_err_probe(dev, ret, "HID hw start failed\n");
|
||||||
|
+
|
||||||
|
+ ret = hid_hw_open(hdev);
|
||||||
|
+ if (ret) {
|
||||||
|
+ dev_err_probe(dev, ret, "HID hw open failed\n");
|
||||||
|
+ goto stop_hw;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ ret = appletb_kbd_set_mode(kbd, APPLETB_KBD_MODE_OFF);
|
||||||
|
+ if (ret) {
|
||||||
|
+ dev_err_probe(dev, ret, "Failed to set touchbar mode\n");
|
||||||
|
+ goto close_hw;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ hid_set_drvdata(hdev, kbd);
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+
|
||||||
|
+close_hw:
|
||||||
|
+ hid_hw_close(hdev);
|
||||||
|
+stop_hw:
|
||||||
|
+ hid_hw_stop(hdev);
|
||||||
|
+ return ret;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void appletb_kbd_remove(struct hid_device *hdev)
|
||||||
|
+{
|
||||||
|
+ struct appletb_kbd *kbd = hid_get_drvdata(hdev);
|
||||||
|
+
|
||||||
|
+ appletb_kbd_set_mode(kbd, APPLETB_KBD_MODE_OFF);
|
||||||
|
+
|
||||||
|
+ hid_hw_close(hdev);
|
||||||
|
+ hid_hw_stop(hdev);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+#ifdef CONFIG_PM
|
||||||
|
+static int appletb_kbd_suspend(struct hid_device *hdev, pm_message_t msg)
|
||||||
|
+{
|
||||||
|
+ struct appletb_kbd *kbd = hid_get_drvdata(hdev);
|
||||||
|
+
|
||||||
|
+ kbd->saved_mode = kbd->current_mode;
|
||||||
|
+ appletb_kbd_set_mode(kbd, APPLETB_KBD_MODE_OFF);
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int appletb_kbd_reset_resume(struct hid_device *hdev)
|
||||||
|
+{
|
||||||
|
+ struct appletb_kbd *kbd = hid_get_drvdata(hdev);
|
||||||
|
+
|
||||||
|
+ appletb_kbd_set_mode(kbd, kbd->saved_mode);
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
+static const struct hid_device_id appletb_kbd_hid_ids[] = {
|
||||||
|
+ /* MacBook Pro's 2018, 2019, with T2 chip: iBridge Display */
|
||||||
|
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_TOUCHBAR_DISPLAY) },
|
||||||
|
+ { }
|
||||||
|
+};
|
||||||
|
+MODULE_DEVICE_TABLE(hid, appletb_kbd_hid_ids);
|
||||||
|
+
|
||||||
|
+static struct hid_driver appletb_kbd_hid_driver = {
|
||||||
|
+ .name = "hid-appletb-kbd",
|
||||||
|
+ .id_table = appletb_kbd_hid_ids,
|
||||||
|
+ .probe = appletb_kbd_probe,
|
||||||
|
+ .remove = appletb_kbd_remove,
|
||||||
|
+ .event = appletb_kbd_hid_event,
|
||||||
|
+ .input_configured = appletb_kbd_input_configured,
|
||||||
|
+#ifdef CONFIG_PM
|
||||||
|
+ .suspend = appletb_kbd_suspend,
|
||||||
|
+ .reset_resume = appletb_kbd_reset_resume,
|
||||||
|
+#endif
|
||||||
|
+ .driver.dev_groups = appletb_kbd_groups,
|
||||||
|
+};
|
||||||
|
+module_hid_driver(appletb_kbd_hid_driver);
|
||||||
|
+
|
||||||
|
+MODULE_AUTHOR("Ronald Tschalär");
|
||||||
|
+MODULE_AUTHOR("Kerem Karabay <kekrby@gmail.com>");
|
||||||
|
+MODULE_DESCRIPTION("MacBookPro Touch Bar Keyboard Mode Driver");
|
||||||
|
+MODULE_LICENSE("GPL");
|
||||||
|
diff --git a/drivers/hid/hid-quirks.c b/drivers/hid/hid-quirks.c
|
||||||
|
index 82e7a80c9..82be9dfaf 100644
|
||||||
|
--- a/drivers/hid/hid-quirks.c
|
||||||
|
+++ b/drivers/hid/hid-quirks.c
|
||||||
|
@@ -325,7 +325,6 @@ static const struct hid_device_id hid_have_special_driver[] = {
|
||||||
|
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) },
|
||||||
|
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_2021) },
|
||||||
|
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_FINGERPRINT_2021) },
|
||||||
|
- { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_TOUCHBAR_DISPLAY) },
|
||||||
|
#endif
|
||||||
|
#if IS_ENABLED(CONFIG_HID_APPLEIR)
|
||||||
|
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL) },
|
||||||
|
@@ -337,6 +336,9 @@ static const struct hid_device_id hid_have_special_driver[] = {
|
||||||
|
#if IS_ENABLED(CONFIG_HID_APPLETB_BL)
|
||||||
|
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_TOUCHBAR_BACKLIGHT) },
|
||||||
|
#endif
|
||||||
|
+#if IS_ENABLED(CONFIG_HID_APPLETB_KBD)
|
||||||
|
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_TOUCHBAR_DISPLAY) },
|
||||||
|
+#endif
|
||||||
|
#if IS_ENABLED(CONFIG_HID_ASUS)
|
||||||
|
{ HID_I2C_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_I2C_KEYBOARD) },
|
||||||
|
{ HID_I2C_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_I2C_TOUCHPAD) },
|
||||||
|
--
|
||||||
|
2.42.0
|
||||||
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,40 @@
|
|||||||
|
From 2f9be28549307b4ac51e8d66bf3b8d5e0621466d Mon Sep 17 00:00:00 2001
|
||||||
|
From: Kerem Karabay <kekrby@gmail.com>
|
||||||
|
Date: Wed, 19 Jul 2023 19:37:14 +0300
|
||||||
|
Subject: [PATCH 04/12] HID: multitouch: support getting the contact ID from
|
||||||
|
HID_DG_TRANSDUCER_INDEX fields
|
||||||
|
|
||||||
|
This is needed to support Apple Touch Bars, where the contact ID is
|
||||||
|
contained in fields with the HID_DG_TRANSDUCER_INDEX usage.
|
||||||
|
|
||||||
|
Signed-off-by: Kerem Karabay <kekrby@gmail.com>
|
||||||
|
---
|
||||||
|
drivers/hid/hid-multitouch.c | 5 ++++-
|
||||||
|
1 file changed, 4 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
|
||||||
|
index e31be0cb8..902a59928 100644
|
||||||
|
--- a/drivers/hid/hid-multitouch.c
|
||||||
|
+++ b/drivers/hid/hid-multitouch.c
|
||||||
|
@@ -636,7 +636,9 @@ static struct mt_report_data *mt_allocate_report_data(struct mt_device *td,
|
||||||
|
|
||||||
|
if (field->logical == HID_DG_FINGER || td->hdev->group != HID_GROUP_MULTITOUCH_WIN_8) {
|
||||||
|
for (n = 0; n < field->report_count; n++) {
|
||||||
|
- if (field->usage[n].hid == HID_DG_CONTACTID) {
|
||||||
|
+ unsigned int hid = field->usage[n].hid;
|
||||||
|
+
|
||||||
|
+ if (hid == HID_DG_CONTACTID || hid == HID_DG_TRANSDUCER_INDEX) {
|
||||||
|
rdata->is_mt_collection = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
@@ -815,6 +817,7 @@ static int mt_touch_input_mapping(struct hid_device *hdev, struct hid_input *hi,
|
||||||
|
MT_STORE_FIELD(tip_state);
|
||||||
|
return 1;
|
||||||
|
case HID_DG_CONTACTID:
|
||||||
|
+ case HID_DG_TRANSDUCER_INDEX:
|
||||||
|
MT_STORE_FIELD(contactid);
|
||||||
|
app->touches_by_report++;
|
||||||
|
return 1;
|
||||||
|
--
|
||||||
|
2.42.0
|
||||||
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,58 @@
|
|||||||
|
From 6162d328fe7b2cf5a3ee8c29bdb229e9528c7a6c Mon Sep 17 00:00:00 2001
|
||||||
|
From: Kerem Karabay <kekrby@gmail.com>
|
||||||
|
Date: Wed, 19 Jul 2023 19:44:10 +0300
|
||||||
|
Subject: [PATCH 05/12] HID: multitouch: support getting the tip state from
|
||||||
|
HID_DG_TOUCH fields
|
||||||
|
|
||||||
|
This is necessary on Apple Touch Bars, where the tip state is contained
|
||||||
|
in fields with the HID_DG_TOUCH usage. This feature is gated by a quirk
|
||||||
|
in order to prevent breaking other devices, see commit c2ef8f21ea8f
|
||||||
|
("HID: multitouch: add support for trackpads").
|
||||||
|
|
||||||
|
Signed-off-by: Kerem Karabay <kekrby@gmail.com>
|
||||||
|
---
|
||||||
|
drivers/hid/hid-multitouch.c | 14 ++++++++++----
|
||||||
|
1 file changed, 10 insertions(+), 4 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
|
||||||
|
index 902a59928..dd5509eeb 100644
|
||||||
|
--- a/drivers/hid/hid-multitouch.c
|
||||||
|
+++ b/drivers/hid/hid-multitouch.c
|
||||||
|
@@ -72,6 +72,7 @@ MODULE_LICENSE("GPL");
|
||||||
|
#define MT_QUIRK_FORCE_MULTI_INPUT BIT(20)
|
||||||
|
#define MT_QUIRK_DISABLE_WAKEUP BIT(21)
|
||||||
|
#define MT_QUIRK_ORIENTATION_INVERT BIT(22)
|
||||||
|
+#define MT_QUIRK_TOUCH_IS_TIPSTATE BIT(23)
|
||||||
|
|
||||||
|
#define MT_INPUTMODE_TOUCHSCREEN 0x02
|
||||||
|
#define MT_INPUTMODE_TOUCHPAD 0x03
|
||||||
|
@@ -810,6 +811,15 @@ static int mt_touch_input_mapping(struct hid_device *hdev, struct hid_input *hi,
|
||||||
|
|
||||||
|
MT_STORE_FIELD(confidence_state);
|
||||||
|
return 1;
|
||||||
|
+ case HID_DG_TOUCH:
|
||||||
|
+ /*
|
||||||
|
+ * Legacy devices use TIPSWITCH and not TOUCH.
|
||||||
|
+ * Let's just ignore this field unless the quirk is set.
|
||||||
|
+ */
|
||||||
|
+ if (!(cls->quirks & MT_QUIRK_TOUCH_IS_TIPSTATE))
|
||||||
|
+ return -1;
|
||||||
|
+
|
||||||
|
+ fallthrough;
|
||||||
|
case HID_DG_TIPSWITCH:
|
||||||
|
if (field->application != HID_GD_SYSTEM_MULTIAXIS)
|
||||||
|
input_set_capability(hi->input,
|
||||||
|
@@ -873,10 +883,6 @@ static int mt_touch_input_mapping(struct hid_device *hdev, struct hid_input *hi,
|
||||||
|
case HID_DG_CONTACTMAX:
|
||||||
|
/* contact max are global to the report */
|
||||||
|
return -1;
|
||||||
|
- case HID_DG_TOUCH:
|
||||||
|
- /* Legacy devices use TIPSWITCH and not TOUCH.
|
||||||
|
- * Let's just ignore this field. */
|
||||||
|
- return -1;
|
||||||
|
}
|
||||||
|
/* let hid-input decide for the others */
|
||||||
|
return 0;
|
||||||
|
--
|
||||||
|
2.42.0
|
||||||
|
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
From e923c6e1a5a508e341851ae020cdb3e7333ccd18 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Kerem Karabay <kekrby@gmail.com>
|
||||||
|
Date: Wed, 19 Jul 2023 19:26:57 +0300
|
||||||
|
Subject: [PATCH 06/12] HID: multitouch: take cls->maxcontacts into account for
|
||||||
|
devices without a HID_DG_CONTACTMAX field too
|
||||||
|
|
||||||
|
This is needed for Apple Touch Bars, where no HID_DG_CONTACTMAX field is
|
||||||
|
present and the maximum contact count is greater than the default.
|
||||||
|
|
||||||
|
Signed-off-by: Kerem Karabay <kekrby@gmail.com>
|
||||||
|
---
|
||||||
|
drivers/hid/hid-multitouch.c | 7 ++++---
|
||||||
|
1 file changed, 4 insertions(+), 3 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
|
||||||
|
index dd5509eeb..624c1d3cc 100644
|
||||||
|
--- a/drivers/hid/hid-multitouch.c
|
||||||
|
+++ b/drivers/hid/hid-multitouch.c
|
||||||
|
@@ -491,9 +491,6 @@ static void mt_feature_mapping(struct hid_device *hdev,
|
||||||
|
if (!td->maxcontacts &&
|
||||||
|
field->logical_maximum <= MT_MAX_MAXCONTACT)
|
||||||
|
td->maxcontacts = field->logical_maximum;
|
||||||
|
- if (td->mtclass.maxcontacts)
|
||||||
|
- /* check if the maxcontacts is given by the class */
|
||||||
|
- td->maxcontacts = td->mtclass.maxcontacts;
|
||||||
|
|
||||||
|
break;
|
||||||
|
case HID_DG_BUTTONTYPE:
|
||||||
|
@@ -1310,6 +1307,10 @@ static int mt_touch_input_configured(struct hid_device *hdev,
|
||||||
|
struct input_dev *input = hi->input;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
+ /* check if the maxcontacts is given by the class */
|
||||||
|
+ if (cls->maxcontacts)
|
||||||
|
+ td->maxcontacts = cls->maxcontacts;
|
||||||
|
+
|
||||||
|
if (!td->maxcontacts)
|
||||||
|
td->maxcontacts = MT_DEFAULT_MAXCONTACT;
|
||||||
|
|
||||||
|
--
|
||||||
|
2.42.0
|
||||||
|
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
From b9f7232d2696b91ae98fadd7b14c531aa8edceb5 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Kerem Karabay <kekrby@gmail.com>
|
||||||
|
Date: Wed, 19 Jul 2023 19:39:53 +0300
|
||||||
|
Subject: [PATCH 07/12] HID: multitouch: allow specifying if a device is direct
|
||||||
|
in a class
|
||||||
|
|
||||||
|
Currently the driver determines the device type based on the
|
||||||
|
application, but this value is not reliable on Apple Touch Bars, where
|
||||||
|
the application is HID_DG_TOUCHPAD even though the devices are direct,
|
||||||
|
so allow setting it in classes.
|
||||||
|
|
||||||
|
Signed-off-by: Kerem Karabay <kekrby@gmail.com>
|
||||||
|
---
|
||||||
|
drivers/hid/hid-multitouch.c | 8 ++++++--
|
||||||
|
1 file changed, 6 insertions(+), 2 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
|
||||||
|
index 624c1d3cc..f98fb36ff 100644
|
||||||
|
--- a/drivers/hid/hid-multitouch.c
|
||||||
|
+++ b/drivers/hid/hid-multitouch.c
|
||||||
|
@@ -147,6 +147,7 @@ struct mt_class {
|
||||||
|
__s32 sn_height; /* Signal/noise ratio for height events */
|
||||||
|
__s32 sn_pressure; /* Signal/noise ratio for pressure events */
|
||||||
|
__u8 maxcontacts;
|
||||||
|
+ bool is_direct; /* true for touchscreens */
|
||||||
|
bool is_indirect; /* true for touchpads */
|
||||||
|
bool export_all_inputs; /* do not ignore mouse, keyboards, etc... */
|
||||||
|
};
|
||||||
|
@@ -564,13 +565,13 @@ static struct mt_application *mt_allocate_application(struct mt_device *td,
|
||||||
|
mt_application->application = application;
|
||||||
|
INIT_LIST_HEAD(&mt_application->mt_usages);
|
||||||
|
|
||||||
|
- if (application == HID_DG_TOUCHSCREEN)
|
||||||
|
+ if (application == HID_DG_TOUCHSCREEN && !td->mtclass.is_indirect)
|
||||||
|
mt_application->mt_flags |= INPUT_MT_DIRECT;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Model touchscreens providing buttons as touchpads.
|
||||||
|
*/
|
||||||
|
- if (application == HID_DG_TOUCHPAD) {
|
||||||
|
+ if (application == HID_DG_TOUCHPAD && !td->mtclass.is_direct) {
|
||||||
|
mt_application->mt_flags |= INPUT_MT_POINTER;
|
||||||
|
td->inputmode_value = MT_INPUTMODE_TOUCHPAD;
|
||||||
|
}
|
||||||
|
@@ -1318,6 +1319,9 @@ static int mt_touch_input_configured(struct hid_device *hdev,
|
||||||
|
if (td->serial_maybe)
|
||||||
|
mt_post_parse_default_settings(td, app);
|
||||||
|
|
||||||
|
+ if (cls->is_direct)
|
||||||
|
+ app->mt_flags |= INPUT_MT_DIRECT;
|
||||||
|
+
|
||||||
|
if (cls->is_indirect)
|
||||||
|
app->mt_flags |= INPUT_MT_POINTER;
|
||||||
|
|
||||||
|
--
|
||||||
|
2.42.0
|
||||||
|
|
||||||
@@ -0,0 +1,94 @@
|
|||||||
|
From a74de0b6f2e1b79d54e84dbeab1b310232275d6c Mon Sep 17 00:00:00 2001
|
||||||
|
From: Kerem Karabay <kekrby@gmail.com>
|
||||||
|
Date: Wed, 19 Jul 2023 19:46:02 +0300
|
||||||
|
Subject: [PATCH 08/12] HID: multitouch: add device ID for Apple Touch Bars
|
||||||
|
|
||||||
|
Note that this is device ID is for T2 Macs. Testing on T1 Macs would be
|
||||||
|
appreciated.
|
||||||
|
|
||||||
|
Signed-off-by: Kerem Karabay <kekrby@gmail.com>
|
||||||
|
---
|
||||||
|
drivers/hid/Kconfig | 1 +
|
||||||
|
drivers/hid/hid-multitouch.c | 26 ++++++++++++++++++++++----
|
||||||
|
2 files changed, 23 insertions(+), 4 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
|
||||||
|
index 852de13aa..4e238df87 100644
|
||||||
|
--- a/drivers/hid/Kconfig
|
||||||
|
+++ b/drivers/hid/Kconfig
|
||||||
|
@@ -737,6 +737,7 @@ config HID_MULTITOUCH
|
||||||
|
Say Y here if you have one of the following devices:
|
||||||
|
- 3M PCT touch screens
|
||||||
|
- ActionStar dual touch panels
|
||||||
|
+ - Touch Bars on x86 MacBook Pros
|
||||||
|
- Atmel panels
|
||||||
|
- Cando dual touch panels
|
||||||
|
- Chunghwa panels
|
||||||
|
diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
|
||||||
|
index f98fb36ff..f881b19db 100644
|
||||||
|
--- a/drivers/hid/hid-multitouch.c
|
||||||
|
+++ b/drivers/hid/hid-multitouch.c
|
||||||
|
@@ -215,6 +215,7 @@ static void mt_post_parse(struct mt_device *td, struct mt_application *app);
|
||||||
|
#define MT_CLS_GOOGLE 0x0111
|
||||||
|
#define MT_CLS_RAZER_BLADE_STEALTH 0x0112
|
||||||
|
#define MT_CLS_SMART_TECH 0x0113
|
||||||
|
+#define MT_CLS_APPLE_TOUCHBAR 0x0114
|
||||||
|
|
||||||
|
#define MT_DEFAULT_MAXCONTACT 10
|
||||||
|
#define MT_MAX_MAXCONTACT 250
|
||||||
|
@@ -399,6 +400,13 @@ static const struct mt_class mt_classes[] = {
|
||||||
|
MT_QUIRK_CONTACT_CNT_ACCURATE |
|
||||||
|
MT_QUIRK_SEPARATE_APP_REPORT,
|
||||||
|
},
|
||||||
|
+ { .name = MT_CLS_APPLE_TOUCHBAR,
|
||||||
|
+ .quirks = MT_QUIRK_HOVERING |
|
||||||
|
+ MT_QUIRK_TOUCH_IS_TIPSTATE |
|
||||||
|
+ MT_QUIRK_SLOT_IS_CONTACTID_MINUS_ONE,
|
||||||
|
+ .is_direct = true,
|
||||||
|
+ .maxcontacts = 11,
|
||||||
|
+ },
|
||||||
|
{ }
|
||||||
|
};
|
||||||
|
|
||||||
|
@@ -1755,6 +1763,15 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+ ret = hid_parse(hdev);
|
||||||
|
+ if (ret != 0)
|
||||||
|
+ return ret;
|
||||||
|
+
|
||||||
|
+ if (mtclass->name == MT_CLS_APPLE_TOUCHBAR &&
|
||||||
|
+ !hid_find_field(hdev, HID_INPUT_REPORT,
|
||||||
|
+ HID_DG_TOUCHPAD, HID_DG_TRANSDUCER_INDEX))
|
||||||
|
+ return -ENODEV;
|
||||||
|
+
|
||||||
|
td = devm_kzalloc(&hdev->dev, sizeof(struct mt_device), GFP_KERNEL);
|
||||||
|
if (!td) {
|
||||||
|
dev_err(&hdev->dev, "cannot allocate multitouch data\n");
|
||||||
|
@@ -1802,10 +1819,6 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
||||||
|
|
||||||
|
timer_setup(&td->release_timer, mt_expired_timeout, 0);
|
||||||
|
|
||||||
|
- ret = hid_parse(hdev);
|
||||||
|
- if (ret != 0)
|
||||||
|
- return ret;
|
||||||
|
-
|
||||||
|
if (mtclass->quirks & MT_QUIRK_FIX_CONST_CONTACT_ID)
|
||||||
|
mt_fix_const_fields(hdev, HID_DG_CONTACTID);
|
||||||
|
|
||||||
|
@@ -2240,6 +2253,11 @@ static const struct hid_device_id mt_devices[] = {
|
||||||
|
MT_USB_DEVICE(USB_VENDOR_ID_XIROKU,
|
||||||
|
USB_DEVICE_ID_XIROKU_CSR2) },
|
||||||
|
|
||||||
|
+ /* Apple Touch Bars */
|
||||||
|
+ { .driver_data = MT_CLS_APPLE_TOUCHBAR,
|
||||||
|
+ HID_USB_DEVICE(USB_VENDOR_ID_APPLE,
|
||||||
|
+ USB_DEVICE_ID_APPLE_TOUCHBAR_DISPLAY) },
|
||||||
|
+
|
||||||
|
/* Google MT devices */
|
||||||
|
{ .driver_data = MT_CLS_GOOGLE,
|
||||||
|
HID_DEVICE(HID_BUS_ANY, HID_GROUP_ANY, USB_VENDOR_ID_GOOGLE,
|
||||||
|
--
|
||||||
|
2.42.0
|
||||||
|
|
||||||
@@ -0,0 +1,197 @@
|
|||||||
|
From f6ab7e4580962c9d82e7dc40dd074d47b2bce034 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Hector Martin <marcan@marcan.st>
|
||||||
|
Date: Tue, 1 Feb 2022 00:40:51 +0900
|
||||||
|
Subject: [PATCH 09/12] lib/vsprintf: Add support for generic FOURCCs by
|
||||||
|
extending %p4cc
|
||||||
|
|
||||||
|
%p4cc is designed for DRM/V4L2 FOURCCs with their specific quirks, but
|
||||||
|
it's useful to be able to print generic 4-character codes formatted as
|
||||||
|
an integer. Extend it to add format specifiers for printing generic
|
||||||
|
32-bit FOURCCs with various endian semantics:
|
||||||
|
|
||||||
|
%p4ch Host-endian
|
||||||
|
%p4cl Little-endian
|
||||||
|
%p4cb Big-endian
|
||||||
|
%p4cr Reverse-endian
|
||||||
|
|
||||||
|
The endianness determines how bytes are interpreted as a u32, and the
|
||||||
|
FOURCC is then always printed MSByte-first (this is the opposite of
|
||||||
|
V4L/DRM FOURCCs). This covers most practical cases, e.g. %p4cr would
|
||||||
|
allow printing LSByte-first FOURCCs stored in host endian order
|
||||||
|
(other than the hex form being in character order, not the integer
|
||||||
|
value).
|
||||||
|
|
||||||
|
Signed-off-by: Hector Martin <marcan@marcan.st>
|
||||||
|
Signed-off-by: Kerem Karabay <kekrby@gmail.com>
|
||||||
|
---
|
||||||
|
Documentation/core-api/printk-formats.rst | 32 ++++++++++++++++++++
|
||||||
|
lib/test_printf.c | 20 +++++++++----
|
||||||
|
lib/vsprintf.c | 36 +++++++++++++++++++----
|
||||||
|
scripts/checkpatch.pl | 2 +-
|
||||||
|
4 files changed, 77 insertions(+), 13 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/Documentation/core-api/printk-formats.rst b/Documentation/core-api/printk-formats.rst
|
||||||
|
index dfe7e75a7..0ccef63e6 100644
|
||||||
|
--- a/Documentation/core-api/printk-formats.rst
|
||||||
|
+++ b/Documentation/core-api/printk-formats.rst
|
||||||
|
@@ -631,6 +631,38 @@ Examples::
|
||||||
|
%p4cc Y10 little-endian (0x20303159)
|
||||||
|
%p4cc NV12 big-endian (0xb231564e)
|
||||||
|
|
||||||
|
+Generic FourCC code
|
||||||
|
+-------------------
|
||||||
|
+
|
||||||
|
+::
|
||||||
|
+ %p4c[hnbl] gP00 (0x67503030)
|
||||||
|
+
|
||||||
|
+Print a generic FourCC code, as both ASCII characters and its numerical
|
||||||
|
+value as hexadecimal.
|
||||||
|
+
|
||||||
|
+The additional ``h``, ``r``, ``b``, and ``l`` specifiers are used to specify
|
||||||
|
+host, reversed, big or little endian order data respectively. Host endian
|
||||||
|
+order means the data is interpreted as a 32-bit integer and the most
|
||||||
|
+significant byte is printed first; that is, the character code as printed
|
||||||
|
+matches the byte order stored in memory on big-endian systems, and is reversed
|
||||||
|
+on little-endian systems.
|
||||||
|
+
|
||||||
|
+Passed by reference.
|
||||||
|
+
|
||||||
|
+Examples for a little-endian machine, given &(u32)0x67503030::
|
||||||
|
+
|
||||||
|
+ %p4ch gP00 (0x67503030)
|
||||||
|
+ %p4cl gP00 (0x67503030)
|
||||||
|
+ %p4cb 00Pg (0x30305067)
|
||||||
|
+ %p4cr 00Pg (0x30305067)
|
||||||
|
+
|
||||||
|
+Examples for a big-endian machine, given &(u32)0x67503030::
|
||||||
|
+
|
||||||
|
+ %p4ch gP00 (0x67503030)
|
||||||
|
+ %p4cl 00Pg (0x30305067)
|
||||||
|
+ %p4cb gP00 (0x67503030)
|
||||||
|
+ %p4cr 00Pg (0x30305067)
|
||||||
|
+
|
||||||
|
Rust
|
||||||
|
----
|
||||||
|
|
||||||
|
diff --git a/lib/test_printf.c b/lib/test_printf.c
|
||||||
|
index 7677ebccf..2355be36f 100644
|
||||||
|
--- a/lib/test_printf.c
|
||||||
|
+++ b/lib/test_printf.c
|
||||||
|
@@ -746,18 +746,26 @@ static void __init fwnode_pointer(void)
|
||||||
|
static void __init fourcc_pointer(void)
|
||||||
|
{
|
||||||
|
struct {
|
||||||
|
+ char type;
|
||||||
|
u32 code;
|
||||||
|
char *str;
|
||||||
|
} const try[] = {
|
||||||
|
- { 0x3231564e, "NV12 little-endian (0x3231564e)", },
|
||||||
|
- { 0xb231564e, "NV12 big-endian (0xb231564e)", },
|
||||||
|
- { 0x10111213, ".... little-endian (0x10111213)", },
|
||||||
|
- { 0x20303159, "Y10 little-endian (0x20303159)", },
|
||||||
|
+ { 'c', 0x3231564e, "NV12 little-endian (0x3231564e)", },
|
||||||
|
+ { 'c', 0xb231564e, "NV12 big-endian (0xb231564e)", },
|
||||||
|
+ { 'c', 0x10111213, ".... little-endian (0x10111213)", },
|
||||||
|
+ { 'c', 0x20303159, "Y10 little-endian (0x20303159)", },
|
||||||
|
+ { 'h', 0x67503030, "gP00 (0x67503030)", },
|
||||||
|
+ { 'r', 0x30305067, "gP00 (0x67503030)", },
|
||||||
|
+ { 'l', cpu_to_le32(0x67503030), "gP00 (0x67503030)", },
|
||||||
|
+ { 'b', cpu_to_be32(0x67503030), "gP00 (0x67503030)", },
|
||||||
|
};
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
- for (i = 0; i < ARRAY_SIZE(try); i++)
|
||||||
|
- test(try[i].str, "%p4cc", &try[i].code);
|
||||||
|
+ for (i = 0; i < ARRAY_SIZE(try); i++) {
|
||||||
|
+ char fmt[] = { '%', 'p', '4', 'c', try[i].type, '\0' };
|
||||||
|
+
|
||||||
|
+ test(try[i].str, fmt, &try[i].code);
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __init
|
||||||
|
diff --git a/lib/vsprintf.c b/lib/vsprintf.c
|
||||||
|
index 40f560959..bd9af783c 100644
|
||||||
|
--- a/lib/vsprintf.c
|
||||||
|
+++ b/lib/vsprintf.c
|
||||||
|
@@ -1758,27 +1758,50 @@ char *fourcc_string(char *buf, char *end, const u32 *fourcc,
|
||||||
|
char output[sizeof("0123 little-endian (0x01234567)")];
|
||||||
|
char *p = output;
|
||||||
|
unsigned int i;
|
||||||
|
+ bool pix_fmt = false;
|
||||||
|
u32 orig, val;
|
||||||
|
|
||||||
|
- if (fmt[1] != 'c' || fmt[2] != 'c')
|
||||||
|
+ if (fmt[1] != 'c')
|
||||||
|
return error_string(buf, end, "(%p4?)", spec);
|
||||||
|
|
||||||
|
if (check_pointer(&buf, end, fourcc, spec))
|
||||||
|
return buf;
|
||||||
|
|
||||||
|
orig = get_unaligned(fourcc);
|
||||||
|
- val = orig & ~BIT(31);
|
||||||
|
+ switch (fmt[2]) {
|
||||||
|
+ case 'h':
|
||||||
|
+ val = orig;
|
||||||
|
+ break;
|
||||||
|
+ case 'r':
|
||||||
|
+ val = orig = swab32(orig);
|
||||||
|
+ break;
|
||||||
|
+ case 'l':
|
||||||
|
+ val = orig = le32_to_cpu(orig);
|
||||||
|
+ break;
|
||||||
|
+ case 'b':
|
||||||
|
+ val = orig = be32_to_cpu(orig);
|
||||||
|
+ break;
|
||||||
|
+ case 'c':
|
||||||
|
+ /* Pixel formats are printed LSB-first */
|
||||||
|
+ val = swab32(orig & ~BIT(31));
|
||||||
|
+ pix_fmt = true;
|
||||||
|
+ break;
|
||||||
|
+ default:
|
||||||
|
+ return error_string(buf, end, "(%p4?)", spec);
|
||||||
|
+ }
|
||||||
|
|
||||||
|
for (i = 0; i < sizeof(u32); i++) {
|
||||||
|
- unsigned char c = val >> (i * 8);
|
||||||
|
+ unsigned char c = val >> ((3 - i) * 8);
|
||||||
|
|
||||||
|
/* Print non-control ASCII characters as-is, dot otherwise */
|
||||||
|
*p++ = isascii(c) && isprint(c) ? c : '.';
|
||||||
|
}
|
||||||
|
|
||||||
|
- *p++ = ' ';
|
||||||
|
- strcpy(p, orig & BIT(31) ? "big-endian" : "little-endian");
|
||||||
|
- p += strlen(p);
|
||||||
|
+ if (pix_fmt) {
|
||||||
|
+ *p++ = ' ';
|
||||||
|
+ strcpy(p, orig & BIT(31) ? "big-endian" : "little-endian");
|
||||||
|
+ p += strlen(p);
|
||||||
|
+ }
|
||||||
|
|
||||||
|
*p++ = ' ';
|
||||||
|
*p++ = '(';
|
||||||
|
@@ -2348,6 +2371,7 @@ char *rust_fmt_argument(char *buf, char *end, void *ptr);
|
||||||
|
* read the documentation (path below) first.
|
||||||
|
* - 'NF' For a netdev_features_t
|
||||||
|
* - '4cc' V4L2 or DRM FourCC code, with endianness and raw numerical value.
|
||||||
|
+ * - '4c[hlbr]' Generic FourCC code.
|
||||||
|
* - 'h[CDN]' For a variable-length buffer, it prints it as a hex string with
|
||||||
|
* a certain separator (' ' by default):
|
||||||
|
* C colon
|
||||||
|
diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
|
||||||
|
index 880fde13d..f080e33a4 100755
|
||||||
|
--- a/scripts/checkpatch.pl
|
||||||
|
+++ b/scripts/checkpatch.pl
|
||||||
|
@@ -6906,7 +6906,7 @@ sub process {
|
||||||
|
($extension eq "f" &&
|
||||||
|
defined $qualifier && $qualifier !~ /^w/) ||
|
||||||
|
($extension eq "4" &&
|
||||||
|
- defined $qualifier && $qualifier !~ /^cc/)) {
|
||||||
|
+ defined $qualifier && $qualifier !~ /^c[chlbr]/)) {
|
||||||
|
$bad_specifier = $specifier;
|
||||||
|
last;
|
||||||
|
}
|
||||||
|
--
|
||||||
|
2.42.0
|
||||||
|
|
||||||
@@ -0,0 +1,94 @@
|
|||||||
|
From f893444f7c842f97f3707897ba29f2c8dd77c8df Mon Sep 17 00:00:00 2001
|
||||||
|
From: Kerem Karabay <kekrby@gmail.com>
|
||||||
|
Date: Mon, 7 Aug 2023 20:29:27 +0300
|
||||||
|
Subject: [PATCH 10/12] USB: core: add 'shutdown' callback to usb_driver
|
||||||
|
|
||||||
|
This simplifies running code on shutdown for USB drivers.
|
||||||
|
|
||||||
|
Signed-off-by: Kerem Karabay <kekrby@gmail.com>
|
||||||
|
---
|
||||||
|
drivers/usb/core/driver.c | 14 ++++++++++++++
|
||||||
|
drivers/usb/storage/uas.c | 5 ++---
|
||||||
|
include/linux/usb.h | 3 +++
|
||||||
|
3 files changed, 19 insertions(+), 3 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
|
||||||
|
index f58a0299f..dc0f86376 100644
|
||||||
|
--- a/drivers/usb/core/driver.c
|
||||||
|
+++ b/drivers/usb/core/driver.c
|
||||||
|
@@ -514,6 +514,19 @@ static int usb_unbind_interface(struct device *dev)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
+static void usb_shutdown_interface(struct device *dev)
|
||||||
|
+{
|
||||||
|
+ struct usb_interface *intf = to_usb_interface(dev);
|
||||||
|
+ struct usb_driver *driver;
|
||||||
|
+
|
||||||
|
+ if (!dev->driver)
|
||||||
|
+ return;
|
||||||
|
+
|
||||||
|
+ driver = to_usb_driver(dev->driver);
|
||||||
|
+ if (driver->shutdown)
|
||||||
|
+ driver->shutdown(intf);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
/**
|
||||||
|
* usb_driver_claim_interface - bind a driver to an interface
|
||||||
|
* @driver: the driver to be bound
|
||||||
|
@@ -1053,6 +1066,7 @@ int usb_register_driver(struct usb_driver *new_driver, struct module *owner,
|
||||||
|
new_driver->drvwrap.driver.bus = &usb_bus_type;
|
||||||
|
new_driver->drvwrap.driver.probe = usb_probe_interface;
|
||||||
|
new_driver->drvwrap.driver.remove = usb_unbind_interface;
|
||||||
|
+ new_driver->drvwrap.driver.shutdown = usb_shutdown_interface;
|
||||||
|
new_driver->drvwrap.driver.owner = owner;
|
||||||
|
new_driver->drvwrap.driver.mod_name = mod_name;
|
||||||
|
new_driver->drvwrap.driver.dev_groups = new_driver->dev_groups;
|
||||||
|
diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c
|
||||||
|
index 2583ee981..591fa0379 100644
|
||||||
|
--- a/drivers/usb/storage/uas.c
|
||||||
|
+++ b/drivers/usb/storage/uas.c
|
||||||
|
@@ -1221,9 +1221,8 @@ static void uas_disconnect(struct usb_interface *intf)
|
||||||
|
* hang on reboot when the device is still in uas mode. Note the reset is
|
||||||
|
* necessary as some devices won't revert to usb-storage mode without it.
|
||||||
|
*/
|
||||||
|
-static void uas_shutdown(struct device *dev)
|
||||||
|
+static void uas_shutdown(struct usb_interface *intf)
|
||||||
|
{
|
||||||
|
- struct usb_interface *intf = to_usb_interface(dev);
|
||||||
|
struct usb_device *udev = interface_to_usbdev(intf);
|
||||||
|
struct Scsi_Host *shost = usb_get_intfdata(intf);
|
||||||
|
struct uas_dev_info *devinfo = (struct uas_dev_info *)shost->hostdata;
|
||||||
|
@@ -1246,7 +1245,7 @@ static struct usb_driver uas_driver = {
|
||||||
|
.suspend = uas_suspend,
|
||||||
|
.resume = uas_resume,
|
||||||
|
.reset_resume = uas_reset_resume,
|
||||||
|
- .drvwrap.driver.shutdown = uas_shutdown,
|
||||||
|
+ .shutdown = uas_shutdown,
|
||||||
|
.id_table = uas_usb_ids,
|
||||||
|
};
|
||||||
|
|
||||||
|
diff --git a/include/linux/usb.h b/include/linux/usb.h
|
||||||
|
index 25f8e62a3..5f3ae2186 100644
|
||||||
|
--- a/include/linux/usb.h
|
||||||
|
+++ b/include/linux/usb.h
|
||||||
|
@@ -1194,6 +1194,7 @@ struct usbdrv_wrap {
|
||||||
|
* post_reset method is called.
|
||||||
|
* @post_reset: Called by usb_reset_device() after the device
|
||||||
|
* has been reset
|
||||||
|
+ * @shutdown: Called at shut-down time to quiesce the device.
|
||||||
|
* @id_table: USB drivers use ID table to support hotplugging.
|
||||||
|
* Export this with MODULE_DEVICE_TABLE(usb,...). This must be set
|
||||||
|
* or your driver's probe function will never get called.
|
||||||
|
@@ -1245,6 +1246,8 @@ struct usb_driver {
|
||||||
|
int (*pre_reset)(struct usb_interface *intf);
|
||||||
|
int (*post_reset)(struct usb_interface *intf);
|
||||||
|
|
||||||
|
+ void (*shutdown)(struct usb_interface *intf);
|
||||||
|
+
|
||||||
|
const struct usb_device_id *id_table;
|
||||||
|
const struct attribute_group **dev_groups;
|
||||||
|
|
||||||
|
--
|
||||||
|
2.42.0
|
||||||
|
|
||||||
@@ -0,0 +1,232 @@
|
|||||||
|
From 337d6f6e34daaa786a0fb70d0dbd553288cd5ecd Mon Sep 17 00:00:00 2001
|
||||||
|
From: Kerem Karabay <kekrby@gmail.com>
|
||||||
|
Date: Fri, 4 Aug 2023 17:49:25 +0300
|
||||||
|
Subject: [PATCH 11/12] drm/format-helper: add helper for BGR888 to XRGB8888
|
||||||
|
conversion
|
||||||
|
|
||||||
|
Add XRGB8888 emulation helper for devices that only support BGR888.
|
||||||
|
|
||||||
|
Signed-off-by: Kerem Karabay <kekrby@gmail.com>
|
||||||
|
---
|
||||||
|
drivers/gpu/drm/drm_format_helper.c | 53 ++++++++++++++
|
||||||
|
.../gpu/drm/tests/drm_format_helper_test.c | 69 +++++++++++++++++++
|
||||||
|
include/drm/drm_format_helper.h | 3 +
|
||||||
|
3 files changed, 125 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/drivers/gpu/drm/drm_format_helper.c b/drivers/gpu/drm/drm_format_helper.c
|
||||||
|
index f93a4efce..5508fbde1 100644
|
||||||
|
--- a/drivers/gpu/drm/drm_format_helper.c
|
||||||
|
+++ b/drivers/gpu/drm/drm_format_helper.c
|
||||||
|
@@ -601,6 +601,56 @@ void drm_fb_xrgb8888_to_rgb888(struct iosys_map *dst, const unsigned int *dst_pi
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(drm_fb_xrgb8888_to_rgb888);
|
||||||
|
|
||||||
|
+static void drm_fb_xrgb8888_to_bgr888_line(void *dbuf, const void *sbuf, unsigned int pixels)
|
||||||
|
+{
|
||||||
|
+ u8 *dbuf8 = dbuf;
|
||||||
|
+ const __le32 *sbuf32 = sbuf;
|
||||||
|
+ unsigned int x;
|
||||||
|
+ u32 pix;
|
||||||
|
+
|
||||||
|
+ for (x = 0; x < pixels; x++) {
|
||||||
|
+ pix = le32_to_cpu(sbuf32[x]);
|
||||||
|
+ /* write red-green-blue to output in little endianness */
|
||||||
|
+ *dbuf8++ = (pix & 0x00FF0000) >> 16;
|
||||||
|
+ *dbuf8++ = (pix & 0x0000FF00) >> 8;
|
||||||
|
+ *dbuf8++ = (pix & 0x000000FF) >> 0;
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/**
|
||||||
|
+ * drm_fb_xrgb8888_to_bgr888 - Convert XRGB8888 to BGR888 clip buffer
|
||||||
|
+ * @dst: Array of BGR888 destination buffers
|
||||||
|
+ * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines
|
||||||
|
+ * within @dst; can be NULL if scanlines are stored next to each other.
|
||||||
|
+ * @src: Array of XRGB8888 source buffers
|
||||||
|
+ * @fb: DRM framebuffer
|
||||||
|
+ * @clip: Clip rectangle area to copy
|
||||||
|
+ *
|
||||||
|
+ * This function copies parts of a framebuffer to display memory and converts the
|
||||||
|
+ * color format during the process. Destination and framebuffer formats must match. The
|
||||||
|
+ * parameters @dst, @dst_pitch and @src refer to arrays. Each array must have at
|
||||||
|
+ * least as many entries as there are planes in @fb's format. Each entry stores the
|
||||||
|
+ * value for the format's respective color plane at the same index.
|
||||||
|
+ *
|
||||||
|
+ * This function does not apply clipping on @dst (i.e. the destination is at the
|
||||||
|
+ * top-left corner).
|
||||||
|
+ *
|
||||||
|
+ * Drivers can use this function for BGR888 devices that don't natively
|
||||||
|
+ * support XRGB8888.
|
||||||
|
+ */
|
||||||
|
+void drm_fb_xrgb8888_to_bgr888(struct iosys_map *dst, const unsigned int *dst_pitch,
|
||||||
|
+ const struct iosys_map *src, const struct drm_framebuffer *fb,
|
||||||
|
+ const struct drm_rect *clip)
|
||||||
|
+{
|
||||||
|
+ static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = {
|
||||||
|
+ 3,
|
||||||
|
+ };
|
||||||
|
+
|
||||||
|
+ drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false,
|
||||||
|
+ drm_fb_xrgb8888_to_bgr888_line);
|
||||||
|
+}
|
||||||
|
+EXPORT_SYMBOL(drm_fb_xrgb8888_to_bgr888);
|
||||||
|
+
|
||||||
|
static void drm_fb_xrgb8888_to_argb8888_line(void *dbuf, const void *sbuf, unsigned int pixels)
|
||||||
|
{
|
||||||
|
__le32 *dbuf32 = dbuf;
|
||||||
|
@@ -925,6 +975,9 @@ int drm_fb_blit(struct iosys_map *dst, const unsigned int *dst_pitch, uint32_t d
|
||||||
|
} else if (dst_format == DRM_FORMAT_RGB888) {
|
||||||
|
drm_fb_xrgb8888_to_rgb888(dst, dst_pitch, src, fb, clip);
|
||||||
|
return 0;
|
||||||
|
+ } else if (dst_format == DRM_FORMAT_BGR888) {
|
||||||
|
+ drm_fb_xrgb8888_to_bgr888(dst, dst_pitch, src, fb, clip);
|
||||||
|
+ return 0;
|
||||||
|
} else if (dst_format == DRM_FORMAT_ARGB8888) {
|
||||||
|
drm_fb_xrgb8888_to_argb8888(dst, dst_pitch, src, fb, clip);
|
||||||
|
return 0;
|
||||||
|
diff --git a/drivers/gpu/drm/tests/drm_format_helper_test.c b/drivers/gpu/drm/tests/drm_format_helper_test.c
|
||||||
|
index 474bb7a1c..dff7fabd9 100644
|
||||||
|
--- a/drivers/gpu/drm/tests/drm_format_helper_test.c
|
||||||
|
+++ b/drivers/gpu/drm/tests/drm_format_helper_test.c
|
||||||
|
@@ -52,6 +52,11 @@ struct convert_to_rgb888_result {
|
||||||
|
const u8 expected[TEST_BUF_SIZE];
|
||||||
|
};
|
||||||
|
|
||||||
|
+struct convert_to_bgr888_result {
|
||||||
|
+ unsigned int dst_pitch;
|
||||||
|
+ const u8 expected[TEST_BUF_SIZE];
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
struct convert_to_argb8888_result {
|
||||||
|
unsigned int dst_pitch;
|
||||||
|
const u32 expected[TEST_BUF_SIZE];
|
||||||
|
@@ -84,6 +89,7 @@ struct convert_xrgb8888_case {
|
||||||
|
struct convert_to_argb1555_result argb1555_result;
|
||||||
|
struct convert_to_rgba5551_result rgba5551_result;
|
||||||
|
struct convert_to_rgb888_result rgb888_result;
|
||||||
|
+ struct convert_to_bgr888_result bgr888_result;
|
||||||
|
struct convert_to_argb8888_result argb8888_result;
|
||||||
|
struct convert_to_xrgb2101010_result xrgb2101010_result;
|
||||||
|
struct convert_to_argb2101010_result argb2101010_result;
|
||||||
|
@@ -125,6 +131,10 @@ static struct convert_xrgb8888_case convert_xrgb8888_cases[] = {
|
||||||
|
.dst_pitch = 0,
|
||||||
|
.expected = { 0x00, 0x00, 0xFF },
|
||||||
|
},
|
||||||
|
+ .bgr888_result = {
|
||||||
|
+ .dst_pitch = 0,
|
||||||
|
+ .expected = { 0xFF, 0x00, 0x00 },
|
||||||
|
+ },
|
||||||
|
.argb8888_result = {
|
||||||
|
.dst_pitch = 0,
|
||||||
|
.expected = { 0xFFFF0000 },
|
||||||
|
@@ -179,6 +189,10 @@ static struct convert_xrgb8888_case convert_xrgb8888_cases[] = {
|
||||||
|
.dst_pitch = 0,
|
||||||
|
.expected = { 0x00, 0x00, 0xFF },
|
||||||
|
},
|
||||||
|
+ .bgr888_result = {
|
||||||
|
+ .dst_pitch = 0,
|
||||||
|
+ .expected = { 0xFF, 0x00, 0x00 },
|
||||||
|
+ },
|
||||||
|
.argb8888_result = {
|
||||||
|
.dst_pitch = 0,
|
||||||
|
.expected = { 0xFFFF0000 },
|
||||||
|
@@ -280,6 +294,15 @@ static struct convert_xrgb8888_case convert_xrgb8888_cases[] = {
|
||||||
|
0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
+ .bgr888_result = {
|
||||||
|
+ .dst_pitch = 0,
|
||||||
|
+ .expected = {
|
||||||
|
+ 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00,
|
||||||
|
+ 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00,
|
||||||
|
+ 0x00, 0x00, 0xFF, 0xFF, 0x00, 0xFF,
|
||||||
|
+ 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF,
|
||||||
|
+ },
|
||||||
|
+ },
|
||||||
|
.argb8888_result = {
|
||||||
|
.dst_pitch = 0,
|
||||||
|
.expected = {
|
||||||
|
@@ -391,6 +414,17 @@ static struct convert_xrgb8888_case convert_xrgb8888_cases[] = {
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
+ .bgr888_result = {
|
||||||
|
+ .dst_pitch = 15,
|
||||||
|
+ .expected = {
|
||||||
|
+ 0x0E, 0x44, 0x9C, 0x11, 0x4D, 0x05, 0xA8, 0xF3, 0x03,
|
||||||
|
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
+ 0x6C, 0xF0, 0x73, 0x0E, 0x44, 0x9C, 0x11, 0x4D, 0x05,
|
||||||
|
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
+ 0xA8, 0x03, 0x03, 0x6C, 0xF0, 0x73, 0x0E, 0x44, 0x9C,
|
||||||
|
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
+ },
|
||||||
|
+ },
|
||||||
|
.argb8888_result = {
|
||||||
|
.dst_pitch = 20,
|
||||||
|
.expected = {
|
||||||
|
@@ -727,6 +761,40 @@ static void drm_test_fb_xrgb8888_to_rgb888(struct kunit *test)
|
||||||
|
KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
+static void drm_test_fb_xrgb8888_to_bgr888(struct kunit *test)
|
||||||
|
+{
|
||||||
|
+ const struct convert_xrgb8888_case *params = test->param_value;
|
||||||
|
+ const struct convert_to_bgr888_result *result = ¶ms->bgr888_result;
|
||||||
|
+ size_t dst_size;
|
||||||
|
+ u8 *buf = NULL;
|
||||||
|
+ __le32 *xrgb8888 = NULL;
|
||||||
|
+ struct iosys_map dst, src;
|
||||||
|
+
|
||||||
|
+ struct drm_framebuffer fb = {
|
||||||
|
+ .format = drm_format_info(DRM_FORMAT_XRGB8888),
|
||||||
|
+ .pitches = { params->pitch, 0, 0 },
|
||||||
|
+ };
|
||||||
|
+
|
||||||
|
+ dst_size = conversion_buf_size(DRM_FORMAT_BGR888, result->dst_pitch,
|
||||||
|
+ ¶ms->clip);
|
||||||
|
+ KUNIT_ASSERT_GT(test, dst_size, 0);
|
||||||
|
+
|
||||||
|
+ buf = kunit_kzalloc(test, dst_size, GFP_KERNEL);
|
||||||
|
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, buf);
|
||||||
|
+ iosys_map_set_vaddr(&dst, buf);
|
||||||
|
+
|
||||||
|
+ xrgb8888 = cpubuf_to_le32(test, params->xrgb8888, TEST_BUF_SIZE);
|
||||||
|
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, xrgb8888);
|
||||||
|
+ iosys_map_set_vaddr(&src, xrgb8888);
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ * BGR888 expected results are already in little-endian
|
||||||
|
+ * order, so there's no need to convert the test output.
|
||||||
|
+ */
|
||||||
|
+ drm_fb_xrgb8888_to_bgr888(&dst, &result->dst_pitch, &src, &fb, ¶ms->clip);
|
||||||
|
+ KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static void drm_test_fb_xrgb8888_to_argb8888(struct kunit *test)
|
||||||
|
{
|
||||||
|
const struct convert_xrgb8888_case *params = test->param_value;
|
||||||
|
@@ -858,6 +926,7 @@ static struct kunit_case drm_format_helper_test_cases[] = {
|
||||||
|
KUNIT_CASE_PARAM(drm_test_fb_xrgb8888_to_argb1555, convert_xrgb8888_gen_params),
|
||||||
|
KUNIT_CASE_PARAM(drm_test_fb_xrgb8888_to_rgba5551, convert_xrgb8888_gen_params),
|
||||||
|
KUNIT_CASE_PARAM(drm_test_fb_xrgb8888_to_rgb888, convert_xrgb8888_gen_params),
|
||||||
|
+ KUNIT_CASE_PARAM(drm_test_fb_xrgb8888_to_bgr888, convert_xrgb8888_gen_params),
|
||||||
|
KUNIT_CASE_PARAM(drm_test_fb_xrgb8888_to_argb8888, convert_xrgb8888_gen_params),
|
||||||
|
KUNIT_CASE_PARAM(drm_test_fb_xrgb8888_to_xrgb2101010, convert_xrgb8888_gen_params),
|
||||||
|
KUNIT_CASE_PARAM(drm_test_fb_xrgb8888_to_argb2101010, convert_xrgb8888_gen_params),
|
||||||
|
diff --git a/include/drm/drm_format_helper.h b/include/drm/drm_format_helper.h
|
||||||
|
index 291deb094..7fc553318 100644
|
||||||
|
--- a/include/drm/drm_format_helper.h
|
||||||
|
+++ b/include/drm/drm_format_helper.h
|
||||||
|
@@ -42,6 +42,9 @@ void drm_fb_xrgb8888_to_rgba5551(struct iosys_map *dst, const unsigned int *dst_
|
||||||
|
void drm_fb_xrgb8888_to_rgb888(struct iosys_map *dst, const unsigned int *dst_pitch,
|
||||||
|
const struct iosys_map *src, const struct drm_framebuffer *fb,
|
||||||
|
const struct drm_rect *clip);
|
||||||
|
+void drm_fb_xrgb8888_to_bgr888(struct iosys_map *dst, const unsigned int *dst_pitch,
|
||||||
|
+ const struct iosys_map *src, const struct drm_framebuffer *fb,
|
||||||
|
+ const struct drm_rect *clip);
|
||||||
|
void drm_fb_xrgb8888_to_argb8888(struct iosys_map *dst, const unsigned int *dst_pitch,
|
||||||
|
const struct iosys_map *src, const struct drm_framebuffer *fb,
|
||||||
|
const struct drm_rect *clip);
|
||||||
|
--
|
||||||
|
2.42.0
|
||||||
|
|
||||||
File diff suppressed because it is too large
Load Diff
+19
-19
@@ -24,12 +24,12 @@ Reviewed-by: Thomas Weißschuh <linux@weissschuh.net>
|
|||||||
create mode 100644 drivers/hid/hid-apple-magic-backlight.c
|
create mode 100644 drivers/hid/hid-apple-magic-backlight.c
|
||||||
|
|
||||||
diff --git a/MAINTAINERS b/MAINTAINERS
|
diff --git a/MAINTAINERS b/MAINTAINERS
|
||||||
index 6a47510d1592..b93c68158be3 100644
|
index dfc63d257..9148bda0a 100644
|
||||||
--- a/MAINTAINERS
|
--- a/MAINTAINERS
|
||||||
+++ b/MAINTAINERS
|
+++ b/MAINTAINERS
|
||||||
@@ -9201,6 +9201,12 @@ F: include/linux/pm.h
|
@@ -9169,6 +9169,12 @@ L: linux-input@vger.kernel.org
|
||||||
F: include/linux/suspend.h
|
S: Maintained
|
||||||
F: kernel/power/
|
F: drivers/hid/hid-appletb-*
|
||||||
|
|
||||||
+HID APPLE MAGIC BACKLIGHT DRIVER
|
+HID APPLE MAGIC BACKLIGHT DRIVER
|
||||||
+M: Orlando Chamberlain <orlandoch.dev@gmail.com>
|
+M: Orlando Chamberlain <orlandoch.dev@gmail.com>
|
||||||
@@ -41,12 +41,12 @@ index 6a47510d1592..b93c68158be3 100644
|
|||||||
M: Jiri Kosina <jikos@kernel.org>
|
M: Jiri Kosina <jikos@kernel.org>
|
||||||
M: Benjamin Tissoires <benjamin.tissoires@redhat.com>
|
M: Benjamin Tissoires <benjamin.tissoires@redhat.com>
|
||||||
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
|
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
|
||||||
index e2a5d30c8895..fe489632bfd9 100644
|
index 4e238df87..83fbab6d4 100644
|
||||||
--- a/drivers/hid/Kconfig
|
--- a/drivers/hid/Kconfig
|
||||||
+++ b/drivers/hid/Kconfig
|
+++ b/drivers/hid/Kconfig
|
||||||
@@ -130,6 +130,19 @@ config HID_APPLE
|
@@ -169,6 +169,19 @@ config HID_APPLETB_KBD
|
||||||
Say Y here if you want support for keyboards of Apple iBooks, PowerBooks,
|
To compile this driver as a module, choose M here: the
|
||||||
MacBooks, MacBook Pros and Apple Aluminum.
|
module will be called hid-appletb-kbd.
|
||||||
|
|
||||||
+config HID_APPLE_MAGIC_BACKLIGHT
|
+config HID_APPLE_MAGIC_BACKLIGHT
|
||||||
+ tristate "Apple Magic Keyboard Backlight"
|
+ tristate "Apple Magic Keyboard Backlight"
|
||||||
@@ -61,24 +61,24 @@ index e2a5d30c8895..fe489632bfd9 100644
|
|||||||
+ To compile this driver as a module, choose M here: the
|
+ To compile this driver as a module, choose M here: the
|
||||||
+ module will be called hid-apple-magic-backlight.
|
+ module will be called hid-apple-magic-backlight.
|
||||||
+
|
+
|
||||||
config HID_APPLEIR
|
config HID_ASUS
|
||||||
tristate "Apple infrared receiver"
|
tristate "Asus"
|
||||||
depends on (USB_HID)
|
depends on USB_HID
|
||||||
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
|
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
|
||||||
index e8014c1a2f8b..dc8df002bc86 100644
|
index 5b60015fd..581f5e720 100644
|
||||||
--- a/drivers/hid/Makefile
|
--- a/drivers/hid/Makefile
|
||||||
+++ b/drivers/hid/Makefile
|
+++ b/drivers/hid/Makefile
|
||||||
@@ -26,6 +26,7 @@ obj-$(CONFIG_HID_ACCUTOUCH) += hid-accutouch.o
|
@@ -31,6 +31,7 @@ obj-$(CONFIG_HID_APPLE) += hid-apple.o
|
||||||
obj-$(CONFIG_HID_ALPS) += hid-alps.o
|
|
||||||
obj-$(CONFIG_HID_ACRUX) += hid-axff.o
|
|
||||||
obj-$(CONFIG_HID_APPLE) += hid-apple.o
|
|
||||||
+obj-$(CONFIG_HID_APPLE_MAGIC_BACKLIGHT) += hid-apple-magic-backlight.o
|
|
||||||
obj-$(CONFIG_HID_APPLEIR) += hid-appleir.o
|
obj-$(CONFIG_HID_APPLEIR) += hid-appleir.o
|
||||||
|
obj-$(CONFIG_HID_APPLETB_BL) += hid-appletb-bl.o
|
||||||
|
obj-$(CONFIG_HID_APPLETB_KBD) += hid-appletb-kbd.o
|
||||||
|
+obj-$(CONFIG_HID_APPLE_MAGIC_BACKLIGHT) += hid-apple-magic-backlight.o
|
||||||
obj-$(CONFIG_HID_CREATIVE_SB0540) += hid-creative-sb0540.o
|
obj-$(CONFIG_HID_CREATIVE_SB0540) += hid-creative-sb0540.o
|
||||||
obj-$(CONFIG_HID_ASUS) += hid-asus.o
|
obj-$(CONFIG_HID_ASUS) += hid-asus.o
|
||||||
|
obj-$(CONFIG_HID_AUREAL) += hid-aureal.o
|
||||||
diff --git a/drivers/hid/hid-apple-magic-backlight.c b/drivers/hid/hid-apple-magic-backlight.c
|
diff --git a/drivers/hid/hid-apple-magic-backlight.c b/drivers/hid/hid-apple-magic-backlight.c
|
||||||
new file mode 100644
|
new file mode 100644
|
||||||
index 000000000000..f0fc02ff3b2d
|
index 000000000..f0fc02ff3
|
||||||
--- /dev/null
|
--- /dev/null
|
||||||
+++ b/drivers/hid/hid-apple-magic-backlight.c
|
+++ b/drivers/hid/hid-apple-magic-backlight.c
|
||||||
@@ -0,0 +1,120 @@
|
@@ -0,0 +1,120 @@
|
||||||
@@ -203,5 +203,5 @@ index 000000000000..f0fc02ff3b2d
|
|||||||
+MODULE_AUTHOR("Orlando Chamberlain <orlandoch.dev@gmail.com>");
|
+MODULE_AUTHOR("Orlando Chamberlain <orlandoch.dev@gmail.com>");
|
||||||
+MODULE_LICENSE("GPL");
|
+MODULE_LICENSE("GPL");
|
||||||
--
|
--
|
||||||
2.39.1
|
2.39.2
|
||||||
|
|
||||||
Reference in New Issue
Block a user