From patchwork Thu Jun 13 03:04:07 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ayman Bagabas X-Patchwork-Id: 10993035 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 3C97C924 for ; Thu, 13 Jun 2019 16:53:56 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 2B237204FD for ; Thu, 13 Jun 2019 16:53:56 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 1FCB222BF1; Thu, 13 Jun 2019 16:53:56 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FROM,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 3C527204FD for ; Thu, 13 Jun 2019 16:53:55 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730078AbfFMQx1 (ORCPT ); Thu, 13 Jun 2019 12:53:27 -0400 Received: from mail-yb1-f193.google.com ([209.85.219.193]:37531 "EHLO mail-yb1-f193.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730088AbfFMDEy (ORCPT ); Wed, 12 Jun 2019 23:04:54 -0400 Received: by mail-yb1-f193.google.com with SMTP id v144so1427117ybb.4; Wed, 12 Jun 2019 20:04:54 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=FQGdGVqH87IxKss+usNHBBm91lSItbEHwj8H2DZqtLQ=; b=WuRi0QWjmPYvi1NZtojCFs0j2Q/X/BIqMrkcLJQbEam8hfJinvDQCz0FzPsyrYO6c+ CHCeZc9SKy+Xs9Vamk48kFLFFYC4pjH6PXXeW0mHftWb/oaixklI33XPU8Q9pv6x3qAF S0Uazu5xluV7BokTnWnYEo9mCrFQC8YN48HPfIdeRNxSjEvlT4DW4NywXgmeL8rnXF4m yumT2/LW3SLOaoSh3G2MSzp9OnzJiM0ThHgXsSAIO49SiDk7RPRpU6qAcZ1oFQLL/BRb /pj7moQQsRdW+s9DMj8udf3uOFYMOw6bsLKfBzh2MbIY4NAryM0CKxHJXJHoJK3yEAm0 qoyQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=FQGdGVqH87IxKss+usNHBBm91lSItbEHwj8H2DZqtLQ=; b=WYN+IPb8cQ6+qlq1ESrU8FBcOyj/buV1PH117NGxCHUSTa9+u9+04keaLjAMrTXh90 jNaBi6KoULRA4ySS9xM0E1bPfsBceDSRGHSoumFEMj/RWUqlZcgWKh5eYsB5P6zeknMA L2GCyHiJvW9RSOw0Trc3kmpRaZHHbnJ7H8TlDv0lAzCGBrx4U040gM4s6Jw7pjpOImwC tKqbHtZsTQxUScG8frHXkI8umLpQ3zlikM/z/9tBuj/VY/ZUkaEKDMcadjKlLET3DtOW KCYe2akFpl4jEVX7pC3yl1fCcf/+k2pbx4et3z1Zo22IrmrTNbJbawxdk0AMTg3D0E5L aHqw== X-Gm-Message-State: APjAAAU4EYdWfB/Q+AD3UfZWDw27v9iw+CoNLQpDfvm3Z+4KUWZ111VJ 0FT/wujvLgtJ9TsL9oMCJw== X-Google-Smtp-Source: APXvYqyxJXtaSbCarpiOjzshTb6+iivjhkZmcUg2zHLlBqrUVJePpMmDQr07r/tccqCZ3m5+B19RZA== X-Received: by 2002:a25:9789:: with SMTP id i9mr31421315ybo.73.1560395093560; Wed, 12 Jun 2019 20:04:53 -0700 (PDT) Received: from 960.localdomain ([71.46.56.3]) by smtp.gmail.com with ESMTPSA id j184sm424831ywf.8.2019.06.12.20.04.52 (version=TLS1_3 cipher=AEAD-AES256-GCM-SHA384 bits=256/256); Wed, 12 Jun 2019 20:04:53 -0700 (PDT) From: Ayman Bagabas To: Darren Hart , Andy Shevchenko , platform-driver-x86@vger.kernel.org, linux-kernel@vger.kernel.org Cc: ayman.bagabas@gmail.com Subject: [PATCH v2 1/8] platform/x86: huawei-wmi: move to platform driver Date: Wed, 12 Jun 2019 23:04:07 -0400 Message-Id: <20190613030416.25807-2-ayman.bagabas@gmail.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190613030416.25807-1-ayman.bagabas@gmail.com> References: <20190613030416.25807-1-ayman.bagabas@gmail.com> MIME-Version: 1.0 Sender: platform-driver-x86-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: platform-driver-x86@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP This move is necessary because the driver is no longer only a hotkeys driver and platform_driver offers easier future extensibility. Along with that, some renames have been made to identify the WMI device in ASL code. AMW0 -> HWMI which is the UID of this WMI device found on supported laptops. WMI0 is the device name and has no UID, therefore, left as it is. Signed-off-by: Ayman Bagabas --- drivers/platform/x86/huawei-wmi.c | 231 ++++++++++++++++++++---------- 1 file changed, 154 insertions(+), 77 deletions(-) diff --git a/drivers/platform/x86/huawei-wmi.c b/drivers/platform/x86/huawei-wmi.c index 52fcac5b393a..4a9e14d3b705 100644 --- a/drivers/platform/x86/huawei-wmi.c +++ b/drivers/platform/x86/huawei-wmi.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 /* - * Huawei WMI hotkeys + * Huawei WMI laptop extras driver * * Copyright (C) 2018 Ayman Bagabas */ @@ -10,23 +10,27 @@ #include #include #include +#include #include /* * Huawei WMI GUIDs */ -#define WMI0_EVENT_GUID "59142400-C6A3-40fa-BADB-8A2652834100" -#define AMW0_EVENT_GUID "ABBC0F5C-8EA1-11D1-A000-C90629100000" +#define HWMI_EVENT_GUID "ABBC0F5C-8EA1-11D1-A000-C90629100000" +/* Legacy GUIDs */ #define WMI0_EXPENSIVE_GUID "39142400-C6A3-40fa-BADB-8A2652834100" +#define WMI0_EVENT_GUID "59142400-C6A3-40fa-BADB-8A2652834100" -struct huawei_wmi_priv { - struct input_dev *idev; + +struct huawei_wmi { struct led_classdev cdev; - acpi_handle handle; - char *acpi_method; + struct input_dev *idev[2]; + struct platform_device *pdev; }; +struct platform_device *huawei_wmi_pdev; + static const struct key_entry huawei_wmi_keymap[] = { { KE_KEY, 0x281, { KEY_BRIGHTNESSDOWN } }, { KE_KEY, 0x282, { KEY_BRIGHTNESSUP } }, @@ -37,17 +41,20 @@ static const struct key_entry huawei_wmi_keymap[] = { { KE_KEY, 0x289, { KEY_WLAN } }, // Huawei |M| key { KE_KEY, 0x28a, { KEY_CONFIG } }, - // Keyboard backlight + // Keyboard backlit { KE_IGNORE, 0x293, { KEY_KBDILLUMTOGGLE } }, { KE_IGNORE, 0x294, { KEY_KBDILLUMUP } }, { KE_IGNORE, 0x295, { KEY_KBDILLUMUP } }, { KE_END, 0 } }; +/* LEDs */ + static int huawei_wmi_micmute_led_set(struct led_classdev *led_cdev, enum led_brightness brightness) { - struct huawei_wmi_priv *priv = dev_get_drvdata(led_cdev->dev->parent); + char *acpi_method; + acpi_handle handle; acpi_status status; union acpi_object args[3]; struct acpi_object_list arg_list = { @@ -55,55 +62,54 @@ static int huawei_wmi_micmute_led_set(struct led_classdev *led_cdev, .count = ARRAY_SIZE(args), }; + handle = ec_get_handle(); + if (!handle) { + dev_err(led_cdev->dev->parent, "Failed to get EC handle\n"); + return -ENODEV; + } + args[0].type = args[1].type = args[2].type = ACPI_TYPE_INTEGER; args[1].integer.value = 0x04; - if (strcmp(priv->acpi_method, "SPIN") == 0) { + if (acpi_has_method(handle, "SPIN")) { + acpi_method = "SPIN"; args[0].integer.value = 0; args[2].integer.value = brightness ? 1 : 0; - } else if (strcmp(priv->acpi_method, "WPIN") == 0) { + } else if (acpi_has_method(handle, "WPIN")) { + acpi_method = "WPIN"; args[0].integer.value = 1; args[2].integer.value = brightness ? 0 : 1; } else { - return -EINVAL; + return -ENODEV; } - status = acpi_evaluate_object(priv->handle, priv->acpi_method, &arg_list, NULL); - if (ACPI_FAILURE(status)) - return -ENXIO; + status = acpi_evaluate_object(handle, acpi_method, &arg_list, NULL); + if (ACPI_FAILURE(status)) { + return -ENODEV; + } return 0; } -static int huawei_wmi_leds_setup(struct wmi_device *wdev) +static int huawei_wmi_leds_setup(struct device *dev) { - struct huawei_wmi_priv *priv = dev_get_drvdata(&wdev->dev); + struct huawei_wmi *huawei = dev_get_drvdata(dev); - priv->handle = ec_get_handle(); - if (!priv->handle) - return 0; + huawei->cdev.name = "platform::micmute"; + huawei->cdev.max_brightness = 1; + huawei->cdev.brightness_set_blocking = huawei_wmi_micmute_led_set; + huawei->cdev.default_trigger = "audio-micmute"; + huawei->cdev.brightness = ledtrig_audio_get(LED_AUDIO_MICMUTE); + huawei->cdev.dev = dev->parent; + huawei->cdev.flags = LED_CORE_SUSPENDRESUME; - if (acpi_has_method(priv->handle, "SPIN")) - priv->acpi_method = "SPIN"; - else if (acpi_has_method(priv->handle, "WPIN")) - priv->acpi_method = "WPIN"; - else - return 0; - - priv->cdev.name = "platform::micmute"; - priv->cdev.max_brightness = 1; - priv->cdev.brightness_set_blocking = huawei_wmi_micmute_led_set; - priv->cdev.default_trigger = "audio-micmute"; - priv->cdev.brightness = ledtrig_audio_get(LED_AUDIO_MICMUTE); - priv->cdev.dev = &wdev->dev; - priv->cdev.flags = LED_CORE_SUSPENDRESUME; - - return devm_led_classdev_register(&wdev->dev, &priv->cdev); + return devm_led_classdev_register(dev, &huawei->cdev); } -static void huawei_wmi_process_key(struct wmi_device *wdev, int code) +/* Input */ + +static void huawei_wmi_process_key(struct input_dev *idev, int code) { - struct huawei_wmi_priv *priv = dev_get_drvdata(&wdev->dev); const struct key_entry *key; /* @@ -117,8 +123,10 @@ static void huawei_wmi_process_key(struct wmi_device *wdev, int code) acpi_status status; status = wmi_query_block(WMI0_EXPENSIVE_GUID, 0, &response); - if (ACPI_FAILURE(status)) + if (ACPI_FAILURE(status)) { + dev_err(&idev->dev, "Failed to query wmi block\n"); return; + } obj = (union acpi_object *)response.pointer; if (obj && obj->type == ACPI_TYPE_INTEGER) @@ -127,81 +135,150 @@ static void huawei_wmi_process_key(struct wmi_device *wdev, int code) kfree(response.pointer); } - key = sparse_keymap_entry_from_scancode(priv->idev, code); + key = sparse_keymap_entry_from_scancode(idev, code); if (!key) { - dev_info(&wdev->dev, "Unknown key pressed, code: 0x%04x\n", code); + dev_info(&idev->dev, "Unknown key pressed, code: 0x%04x\n", code); return; } - sparse_keymap_report_entry(priv->idev, key, 1, true); + sparse_keymap_report_entry(idev, key, 1, true); } -static void huawei_wmi_notify(struct wmi_device *wdev, - union acpi_object *obj) +static void huawei_wmi_input_notify(u32 value, void *context) { - if (obj->type == ACPI_TYPE_INTEGER) - huawei_wmi_process_key(wdev, obj->integer.value); + struct input_dev *idev = (struct input_dev *)context; + struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL }; + union acpi_object *obj; + acpi_status status; + + status = wmi_get_event_data(value, &response); + if (ACPI_FAILURE(status)) { + dev_err(&idev->dev, "Unable to get event data\n"); + return; + } + + obj = (union acpi_object *)response.pointer; + if (obj && obj->type == ACPI_TYPE_INTEGER) + huawei_wmi_process_key(idev, obj->integer.value); else - dev_info(&wdev->dev, "Bad response type %d\n", obj->type); + dev_err(&idev->dev, "Bad response type\n"); + + kfree(response.pointer); } -static int huawei_wmi_input_setup(struct wmi_device *wdev) +static int huawei_wmi_input_setup(struct platform_device *pdev, + struct input_dev **idev) { - struct huawei_wmi_priv *priv = dev_get_drvdata(&wdev->dev); int err; - priv->idev = devm_input_allocate_device(&wdev->dev); - if (!priv->idev) + *idev = devm_input_allocate_device(&pdev->dev); + if (!*idev) return -ENOMEM; - priv->idev->name = "Huawei WMI hotkeys"; - priv->idev->phys = "wmi/input0"; - priv->idev->id.bustype = BUS_HOST; - priv->idev->dev.parent = &wdev->dev; + (*idev)->name = "Huawei WMI hotkeys"; + (*idev)->phys = "wmi/input0"; + (*idev)->id.bustype = BUS_HOST; + (*idev)->dev.parent = &pdev->dev; - err = sparse_keymap_setup(priv->idev, huawei_wmi_keymap, NULL); + err = sparse_keymap_setup(*idev, huawei_wmi_keymap, NULL); if (err) return err; - return input_register_device(priv->idev); + return input_register_device(*idev); } -static int huawei_wmi_probe(struct wmi_device *wdev) +/* Huawei driver */ + +static int huawei_wmi_probe(struct platform_device *pdev) { - struct huawei_wmi_priv *priv; + struct huawei_wmi *huawei; int err; - priv = devm_kzalloc(&wdev->dev, sizeof(struct huawei_wmi_priv), GFP_KERNEL); - if (!priv) + huawei = devm_kzalloc(&pdev->dev, sizeof(struct huawei_wmi), GFP_KERNEL); + if (!huawei) return -ENOMEM; - dev_set_drvdata(&wdev->dev, priv); + huawei->pdev = pdev; + dev_set_drvdata(&pdev->dev, huawei); + + if (wmi_has_guid(WMI0_EVENT_GUID)) { + err = huawei_wmi_input_setup(pdev, &huawei->idev[0]); + if (err) + dev_err(&pdev->dev, "Failed to setup input device\n"); + err = wmi_install_notify_handler(WMI0_EVENT_GUID, + huawei_wmi_input_notify, huawei->idev[0]); + if (err) + dev_err(&pdev->dev, "Failed to install notify handler\n"); + } - err = huawei_wmi_input_setup(wdev); - if (err) - return err; + if (wmi_has_guid(HWMI_EVENT_GUID)) { + err = huawei_wmi_input_setup(pdev, &huawei->idev[1]); + if (err) + dev_err(&pdev->dev, "Failed to setup input device\n"); + err = wmi_install_notify_handler(HWMI_EVENT_GUID, + huawei_wmi_input_notify, huawei->idev[1]); + if (err) + dev_err(&pdev->dev, "Failed to install notify handler\n"); + } - return huawei_wmi_leds_setup(wdev); + if (wmi_has_guid(HWMI_METHOD_GUID)) { + err = huawei_wmi_leds_setup(&pdev->dev); + if (err) + dev_err(&pdev->dev, "Failed to setup leds\n"); + } + return 0; } -static const struct wmi_device_id huawei_wmi_id_table[] = { - { .guid_string = WMI0_EVENT_GUID }, - { .guid_string = AMW0_EVENT_GUID }, - { } -}; +static int huawei_wmi_remove(struct platform_device *pdev) +{ + if (wmi_has_guid(WMI0_EVENT_GUID)) + wmi_remove_notify_handler(WMI0_EVENT_GUID); -static struct wmi_driver huawei_wmi_driver = { + if (wmi_has_guid(HWMI_EVENT_GUID)) + wmi_remove_notify_handler(HWMI_EVENT_GUID); + + return 0; +} + +static struct platform_driver huawei_wmi_driver = { .driver = { .name = "huawei-wmi", }, - .id_table = huawei_wmi_id_table, .probe = huawei_wmi_probe, - .notify = huawei_wmi_notify, + .remove = huawei_wmi_remove, }; -module_wmi_driver(huawei_wmi_driver); +static __init int huawei_wmi_init(void) +{ + int err; + + err = platform_driver_register(&huawei_wmi_driver); + if (err) { + pr_err("Failed to register platform driver\n"); + return err; + } + + huawei_wmi_pdev = platform_device_register_simple("huawei-wmi", -1, NULL, 0); + if (IS_ERR(huawei_wmi_pdev)) { + pr_err("Failed to register platform device\n"); + platform_driver_unregister(&huawei_wmi_driver); + return PTR_ERR(huawei_wmi_pdev); + } + + return 0; +} + +static __exit void huawei_wmi_exit(void) +{ + platform_device_unregister(huawei_wmi_pdev); + platform_driver_unregister(&huawei_wmi_driver); +} + +module_init(huawei_wmi_init); +module_exit(huawei_wmi_exit); -MODULE_DEVICE_TABLE(wmi, huawei_wmi_id_table); +MODULE_ALIAS("wmi:"WMI0_EVENT_GUID); +MODULE_ALIAS("wmi:"HWMI_EVENT_GUID); MODULE_AUTHOR("Ayman Bagabas "); -MODULE_DESCRIPTION("Huawei WMI hotkeys"); +MODULE_DESCRIPTION("Huawei WMI laptop extras driver"); MODULE_LICENSE("GPL v2"); From patchwork Thu Jun 13 03:04:09 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ayman Bagabas X-Patchwork-Id: 10993029 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id E2338924 for ; Thu, 13 Jun 2019 16:53:29 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id D0418204FD for ; Thu, 13 Jun 2019 16:53:29 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id C4AB721FAC; Thu, 13 Jun 2019 16:53:29 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FROM,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 9D0E122A68 for ; Thu, 13 Jun 2019 16:53:28 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2404049AbfFMQx2 (ORCPT ); Thu, 13 Jun 2019 12:53:28 -0400 Received: from mail-yb1-f196.google.com ([209.85.219.196]:46648 "EHLO mail-yb1-f196.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730091AbfFMDE5 (ORCPT ); Wed, 12 Jun 2019 23:04:57 -0400 Received: by mail-yb1-f196.google.com with SMTP id p8so7189182ybo.13; Wed, 12 Jun 2019 20:04:56 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=Ki2D2489PS85Mw+OS3eiSgqoQG8BdIGhGbAH8PhBaTk=; b=WgEVGNyOzjz+qKInfXs9knL0X9RGoA4LC/YeP2WzGI2Ib0nrvhh63OlpPORlxnh1GB W7oH0YpL67lrV0LKWhJHWDg80dXjgj0nwqh4YQKhKauUTcYm1DX+VJoYm2uJNLZdiEeP tJIjSbU6lb+F/cA6GPQDXgLpwa3DSX8ITd/4m7lnrBudBlBAyEg0VHPx0S7RKn5JVoql cQxYiG7ZCRZzuYutXn9xLMYYv7OjV0vbOyV1dc59/JgBXZGXY/uLOZVGptD3TLB16/Ge p8qpm30sK4BW3QTT3/DePhmuGJLgZ3sBHzg6NuXVPw8KhK6ShTBd3m5GzYElPl7TL7jY VIbw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=Ki2D2489PS85Mw+OS3eiSgqoQG8BdIGhGbAH8PhBaTk=; b=ltuCoxpKrm0MmXrroWQitUhHD9hl+8KEtrp/qSf+InO3LEZqZfpO55MVCO2AZdFjMX PcIjERDk/2SCLu60Fc7yeSHdDZI70czeALReYUJku9sw8DOGZ2Cz8uxtO96IXd40BlMK Px2HVGHMAP57GOG2D5LmxxtxDO4EVuLt9aBhBOsA15UX0/g10C8io+5u9598zHuovHzs 2bz+jtex7g6xM6wH01+VWtLnSwo4IecorsgxNPfBTcJYddITnkCRGmQ/Qr34SdVhWruA RkwUOGzWkzGcA4mVcQnoGqBxw/e6T2HYjsrUHx0/qA7k4fUxi6gBFaHuuLqy2/OnyDCV qQkg== X-Gm-Message-State: APjAAAVdpQgXnewjozLoGm1o07tn5W8aGwM3aQbvtBM1CPPH0P3KlF3r PQIMLlT5Z1L39IDim5qV+w== X-Google-Smtp-Source: APXvYqz7xuFPoZJ4rT70/zjIe43JLm8aduIypeLy3RbluurBb9OLlVitn12gnM54R6xndHOB96YvtA== X-Received: by 2002:a25:83c7:: with SMTP id v7mr40085247ybm.345.1560395096377; Wed, 12 Jun 2019 20:04:56 -0700 (PDT) Received: from 960.localdomain ([71.46.56.3]) by smtp.gmail.com with ESMTPSA id j184sm424831ywf.8.2019.06.12.20.04.55 (version=TLS1_3 cipher=AEAD-AES256-GCM-SHA384 bits=256/256); Wed, 12 Jun 2019 20:04:55 -0700 (PDT) From: Ayman Bagabas To: Darren Hart , Andy Shevchenko , platform-driver-x86@vger.kernel.org, linux-kernel@vger.kernel.org Cc: ayman.bagabas@gmail.com Subject: [PATCH v2 2/8] platform/x86: huawei-wmi: implement WMI management interface Date: Wed, 12 Jun 2019 23:04:09 -0400 Message-Id: <20190613030416.25807-4-ayman.bagabas@gmail.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190613030416.25807-1-ayman.bagabas@gmail.com> References: <20190613030416.25807-1-ayman.bagabas@gmail.com> MIME-Version: 1.0 Sender: platform-driver-x86-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: platform-driver-x86@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP The patch introduces a WMI BIOS interface that can control various device features like micmute LED, battery charging thresholds, and fn-lock. This interface, with device UID of HWMI, is found on recent and old models including MateBook X released in 2017. This model is kind of "special" since it has two WMI interfaces, this interface and what we call it the "legacy" interface. Due to lack of hardware and testers, this "legacy" interface is not "fully" implemented yet. This "legacy" interface supports setting the micmute LED for MateBook X (2017). This device, HWMI, has only one method that takes a 64 bit argument and returns a package with two elements, the first is 4 bytes and the second is 256 bytes. The first 4 bytes are always skipped since they return zero all the time. MateBook X (2017) is a bit different where it takes 64 bit argument but returns one 260 byte buffer (265+4). Right now, this interface doesn't offer any usability for MateBook X (2017) except for fn-lock and debugfs. Signed-off-by: Ayman Bagabas --- drivers/platform/x86/huawei-wmi.c | 127 ++++++++++++++++++++++++++++++ 1 file changed, 127 insertions(+) diff --git a/drivers/platform/x86/huawei-wmi.c b/drivers/platform/x86/huawei-wmi.c index 4a9e14d3b705..37b09d497f5e 100644 --- a/drivers/platform/x86/huawei-wmi.c +++ b/drivers/platform/x86/huawei-wmi.c @@ -10,22 +10,35 @@ #include #include #include +#include #include #include /* * Huawei WMI GUIDs */ +#define HWMI_METHOD_GUID "ABBC0F5B-8EA1-11D1-A000-C90629100000" #define HWMI_EVENT_GUID "ABBC0F5C-8EA1-11D1-A000-C90629100000" /* Legacy GUIDs */ #define WMI0_EXPENSIVE_GUID "39142400-C6A3-40fa-BADB-8A2652834100" #define WMI0_EVENT_GUID "59142400-C6A3-40fa-BADB-8A2652834100" +/* HWMI_commands */ + +enum { + BATTERY_THRESH_GET = 0x00001103, /* \GBTT */ + BATTERY_THRESH_SET = 0x00001003, /* \SBTT */ + FAN_SPEED_GET = 0x00000802, /* \GFNS */ + FN_LOCK_GET = 0x00000604, /* \GFRS */ + FN_LOCK_SET = 0x00000704, /* \SFRS */ + MICMUTE_LED_SET = 0x00000b04, /* \SMLS */ +}; struct huawei_wmi { struct led_classdev cdev; struct input_dev *idev[2]; + struct mutex wmi_lock; struct platform_device *pdev; }; @@ -48,6 +61,118 @@ static const struct key_entry huawei_wmi_keymap[] = { { KE_END, 0 } }; +/* Utils */ + +static int huawei_wmi_call(struct device *dev, struct acpi_buffer *in, + struct acpi_buffer *out) +{ + struct huawei_wmi *huawei = dev_get_drvdata(dev); + acpi_status status; + + mutex_lock(&huawei->wmi_lock); + status = wmi_evaluate_method(HWMI_METHOD_GUID, 0, 1, in, out); + mutex_unlock(&huawei->wmi_lock); + if (ACPI_FAILURE(status)) { + dev_err(dev, "Failed to evaluate wmi method\n"); + return -ENODEV; + } + + return 0; +} + +/* HWMI takes a 64 bit input and returns either a package with 2 buffers, one of + * 4 bytes and the other of 256 bytes, or one buffer of size 0x104 (260) bytes. + * The first 4 bytes are ignored, we ignore the first 4 bytes buffer if we got a + * package, or skip the first 4 if a buffer of 0x104 is used. The first byte of + * the remaining 0x100 sized buffer has the return status of every call. In case + * the return status is non-zero, we return -ENODEV but still copy the returned + * buffer to the given buffer parameter (buf). + */ +static int huawei_wmi_cmd(struct device *dev, u64 arg, u8 *buf, size_t buflen) +{ + struct acpi_buffer out = { ACPI_ALLOCATE_BUFFER, NULL }; + struct acpi_buffer in; + union acpi_object *obj; + size_t len; + int err, i; + + in.length = sizeof(u64); + in.pointer = &arg; + + /* Some models require calling HWMI twice to execute a command. We evaluate + * HWMI and if we get a non-zero return status we evaluate it again. + */ + for (i = 0; i < 2; i++) { + err = huawei_wmi_call(dev, &in, &out); + if (err) { + goto fail_cmd; + } + + obj = out.pointer; + if (!obj) { + err = -EIO; + goto fail_cmd; + } + + switch (obj->type) { + /* Models that implement both "legacy" and HWMI tend to return a 0x104 + * sized buffer instead of a package of 0x4 and 0x100 buffers. + */ + case ACPI_TYPE_BUFFER: + if (obj->buffer.length == 0x104) { + // Skip the first 4 bytes. + obj->buffer.pointer += 4; + len = 0x100; + } else { + dev_err(dev, "Bad buffer length, got %d\n", obj->buffer.length); + err = -EIO; + goto fail_cmd; + } + + break; + /* HWMI returns a package with 2 buffer elements, one of 4 bytes and the + * other is 256 bytes. + */ + case ACPI_TYPE_PACKAGE: + if (obj->package.count != 2) { + dev_err(dev, "Bad package count, got %d\n", obj->package.count); + err = -EIO; + goto fail_cmd; + } + + obj = &obj->package.elements[1]; + if (obj->type != ACPI_TYPE_BUFFER) { + dev_err(dev, "Bad package element type, got %d\n", obj->type); + err = -EIO; + goto fail_cmd; + } + len = obj->buffer.length; + + break; + /* Shouldn't get here! */ + default: + dev_err(dev, "Unexpected obj type, got: %d\n", obj->type); + err = -EIO; + goto fail_cmd; + } + + if (!*obj->buffer.pointer) { + break; + } + } + + err = (*obj->buffer.pointer) ? -ENODEV : 0; + + if (buf) { + len = min(buflen, len); + memcpy(buf, obj->buffer.pointer, len); + } + +fail_cmd: + kfree(out.pointer); + return err; +} + /* LEDs */ static int huawei_wmi_micmute_led_set(struct led_classdev *led_cdev, @@ -222,6 +347,7 @@ static int huawei_wmi_probe(struct platform_device *pdev) } if (wmi_has_guid(HWMI_METHOD_GUID)) { + mutex_init(&huawei->wmi_lock); err = huawei_wmi_leds_setup(&pdev->dev); if (err) dev_err(&pdev->dev, "Failed to setup leds\n"); @@ -279,6 +405,7 @@ module_exit(huawei_wmi_exit); MODULE_ALIAS("wmi:"WMI0_EVENT_GUID); MODULE_ALIAS("wmi:"HWMI_EVENT_GUID); +MODULE_ALIAS("wmi:"HWMI_METHOD_GUID); MODULE_AUTHOR("Ayman Bagabas "); MODULE_DESCRIPTION("Huawei WMI laptop extras driver"); MODULE_LICENSE("GPL v2"); From patchwork Thu Jun 13 03:04:10 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ayman Bagabas X-Patchwork-Id: 10993037 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id A1A2518A6 for ; Thu, 13 Jun 2019 16:53:56 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 90914204FD for ; Thu, 13 Jun 2019 16:53:56 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 8522521FAC; Thu, 13 Jun 2019 16:53:56 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FROM,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 060F122ADC for ; Thu, 13 Jun 2019 16:53:56 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2392977AbfFMQx1 (ORCPT ); Thu, 13 Jun 2019 12:53:27 -0400 Received: from mail-yb1-f195.google.com ([209.85.219.195]:35296 "EHLO mail-yb1-f195.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730092AbfFMDE7 (ORCPT ); Wed, 12 Jun 2019 23:04:59 -0400 Received: by mail-yb1-f195.google.com with SMTP id v17so7209823ybm.2; Wed, 12 Jun 2019 20:04:58 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=bKWy+MYAC9Qnk4R94EFOwHl0lKGQuAZ2oqXPCo3dOhw=; b=JTpvtPBkRmGtQnud9fO2fYZJevc3HJLX591AVdzUF4SmiS18T8U/m2k9xky5KPUMYT 3xkW9Ykht4kyduPLAN3/qjvuFHcjess1RPLgG8AgdLKLOls8tFlg93kBPwAWayogWELt zmsxO/ixd/zeHTcgxad4aRdvBT3ipPCggmAZShGhhIo5MRh3kTgmM+gBqjS31AGp0x1w f0sYCrm9yzJ5BHfHbSAJ/YUj72Oi8FZRsfsM6wgFVg60qepxJeqPzQMqKOSUX6dQnmTZ o73SaB7mY8WidO2ntPdA4EtXwkq8LsXpW1mjUiZ55YuTcXh6F8t4Ob6eFUrM0wd5YWIw Edng== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=bKWy+MYAC9Qnk4R94EFOwHl0lKGQuAZ2oqXPCo3dOhw=; b=qBttOupWfLu0C2oVmF4HVi6khNlBQm7gl9c51y0y/IGLdt+cIu7mNz5SFBDN46RVmD N+2+T5JS7p11PSb1hobktFHpJwhmvOnau8qeeeLWSn2nEYrLWiaUnMy4zJHz/Dx8zt9J JAlSY1NWeyxdR/f4pTdj6KvIcHKR9074X+xH5pd4+yLQJcONmukjPxn9/JVtOgj8mw/1 pRdIc4dETSP/9DBLDvn/cz1kYb0XaTyp3OJpIHQa9s3J8wOsmHo5UOG7EIPHjfd+Ff10 pboHKHaUp7L1CQejUEOIz6cVGHM2fscp+HfncZcz1kFWB5T1mGzetQIWpkaiy5kkEly8 apJQ== X-Gm-Message-State: APjAAAVrM1Bo04MoeUbesnwJq3qPNnQF3IH73RC4J5QKgxU/eFPys8DH gl4UJr9agDfEy6O0T89PTQ== X-Google-Smtp-Source: APXvYqz7Iw97WcJzg59QpO1fIdasPdVT8+xM6RNGzAz94X5hYmGBPkrdg3oga1rcJqorZbflskpnEg== X-Received: by 2002:a5b:801:: with SMTP id x1mr38471062ybp.95.1560395097834; Wed, 12 Jun 2019 20:04:57 -0700 (PDT) Received: from 960.localdomain ([71.46.56.3]) by smtp.gmail.com with ESMTPSA id j184sm424831ywf.8.2019.06.12.20.04.57 (version=TLS1_3 cipher=AEAD-AES256-GCM-SHA384 bits=256/256); Wed, 12 Jun 2019 20:04:57 -0700 (PDT) From: Ayman Bagabas To: Darren Hart , Andy Shevchenko , platform-driver-x86@vger.kernel.org, linux-kernel@vger.kernel.org Cc: ayman.bagabas@gmail.com Subject: [PATCH v2 3/8] platform/x86: huawei-wmi: use quirks and module parameters Date: Wed, 12 Jun 2019 23:04:10 -0400 Message-Id: <20190613030416.25807-5-ayman.bagabas@gmail.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190613030416.25807-1-ayman.bagabas@gmail.com> References: <20190613030416.25807-1-ayman.bagabas@gmail.com> MIME-Version: 1.0 Sender: platform-driver-x86-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: platform-driver-x86@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP The patch introduces two parameters to force reporting brightness keys and sleeping after setting battery thresholds value. These parameters are implemented as quirks along with `ec_micmute` quirk which controls the micmute LED through ACPI EC interface. All newer models that "fully" implement the new interface report brightness key events twice, once through WMI and once through acpi-video. Older models, such as `MateBook X`, don't report brightness events using WMI. This is implemented as a quirk and can be forced using module parameters. Some models don't allow setting thresholds to (0, 100), due to bad ASL code, which indicates reset values, instead, it only turns off battery charging protection. This would return the currently set values even though battery protection is off which doesn't make sense. A sane value like (0, 100) indicates no charging protection, but since it's not possible to set such values, (0, 0) is set before turning protection off with (0, 100). This requires a delay after setting (0, 0) and after (0, 100) so that these values make their way to EC memory. Method (SBTT, 1, NotSerialized) { Name (BUFF, Buffer (0x0100){}) Local0 = Arg0 CreateByteField (Arg0, 0x02, STCP) CreateByteField (Arg0, 0x03, SOCP) CreateByteField (BUFF, Zero, STAT) If (((STCP == Zero) && (SOCP == 0x64))) { \_SB.PCI0.LPCB.EC0.ECXT (0xC7, Zero, Zero, Zero, Zero, Zero) } Else { \_SB.PCI0.LPCB.EC0.ECXT (0xC7, One, STCP, SOCP, Zero, Zero) } // ^ ^ ^ // | | | STAT = Zero // on low high Return (BUFF) /* \SBTT.BUFF */ // bit thresh thresh } ASL code taken from MateBook X Pro (MACH-WX9) showing how it turns off protection without changing values. Signed-off-by: Ayman Bagabas --- drivers/platform/x86/huawei-wmi.c | 71 +++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) diff --git a/drivers/platform/x86/huawei-wmi.c b/drivers/platform/x86/huawei-wmi.c index 37b09d497f5e..647c5a6c8ab3 100644 --- a/drivers/platform/x86/huawei-wmi.c +++ b/drivers/platform/x86/huawei-wmi.c @@ -6,6 +6,7 @@ */ #include +#include #include #include #include @@ -35,6 +36,14 @@ enum { MICMUTE_LED_SET = 0x00000b04, /* \SMLS */ }; +struct quirk_entry { + bool battery_sleep; + bool ec_micmute; + bool report_brightness; +}; + +static struct quirk_entry *quirks; + struct huawei_wmi { struct led_classdev cdev; struct input_dev *idev[2]; @@ -61,6 +70,58 @@ static const struct key_entry huawei_wmi_keymap[] = { { KE_END, 0 } }; +static bool battery_sleep; +static bool report_brightness; + +module_param(battery_sleep, bool, 0444); +MODULE_PARM_DESC(battery_sleep, + "Delay after setting battery charging thresholds."); +module_param(report_brightness, bool, 0444); +MODULE_PARM_DESC(report_brightness, + "Report brightness key events."); + +/* Quirks */ + +static int __init dmi_matched(const struct dmi_system_id *dmi) +{ + quirks = dmi->driver_data; + return 1; +} + +static struct quirk_entry quirk_unknown = { +}; + +static struct quirk_entry quirk_battery_sleep = { + .battery_sleep = true, +}; + +static struct quirk_entry quirk_matebook_x = { + .ec_micmute = true, + .report_brightness = true, +}; + +static const struct dmi_system_id huawei_quirks[] = { + { + .callback = dmi_matched, + .ident = "Huawei MACH-WX9", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "HUAWEI"), + DMI_MATCH(DMI_PRODUCT_NAME, "MACH-WX9"), + }, + .driver_data = &quirk_battery_sleep + }, + { + .callback = dmi_matched, + .ident = "Huawei MateBook X", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "HUAWEI"), + DMI_MATCH(DMI_PRODUCT_NAME, "HUAWEI MateBook X") + }, + .driver_data = &quirk_matebook_x + }, + { } +}; + /* Utils */ static int huawei_wmi_call(struct device *dev, struct acpi_buffer *in, @@ -266,6 +327,11 @@ static void huawei_wmi_process_key(struct input_dev *idev, int code) return; } + if (quirks && !quirks->report_brightness && + (key->sw.code == KEY_BRIGHTNESSDOWN || + key->sw.code == KEY_BRIGHTNESSUP)) + return; + sparse_keymap_report_entry(idev, key, 1, true); } @@ -378,6 +444,11 @@ static __init int huawei_wmi_init(void) { int err; + quirks = &quirk_unknown; + dmi_check_system(huawei_quirks); + quirks->battery_sleep |= battery_sleep; + quirks->report_brightness |= report_brightness; + err = platform_driver_register(&huawei_wmi_driver); if (err) { pr_err("Failed to register platform driver\n"); From patchwork Thu Jun 13 03:04:11 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ayman Bagabas X-Patchwork-Id: 10993023 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id EB10F924 for ; Thu, 13 Jun 2019 16:53:17 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id D81A421FAC for ; Thu, 13 Jun 2019 16:53:17 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id CA5B422ADC; Thu, 13 Jun 2019 16:53:17 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FROM,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 62D3E21FAC for ; Thu, 13 Jun 2019 16:53:17 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730106AbfFMQxR (ORCPT ); Thu, 13 Jun 2019 12:53:17 -0400 Received: from mail-yw1-f68.google.com ([209.85.161.68]:34400 "EHLO mail-yw1-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730095AbfFMDFA (ORCPT ); Wed, 12 Jun 2019 23:05:00 -0400 Received: by mail-yw1-f68.google.com with SMTP id a11so1589189ywc.1; Wed, 12 Jun 2019 20:04:59 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=4S5lqn5I3zXmixd7LhbTzQ90QBdVDOadcoSgSK1gCOU=; b=KrUI5Tu6zNMBrq05zotXrdh9heUiqi7xbScH8EwQOyONcKXTp+CvKgkRTWE9zi6lMT HMLoFTwcZ7c+TNNMB5soGWw7BFAfNpkhSALhb3mm342GBFL/CxEDkSM7Fsu5fAUcIXSy l1cj2//rqY43Alm0AGi8cRXB32HsXsnp3zTgSTPoXkHlpmRju0Rdxxt501uDvGPOZk4V f2gY0tdJxiOwEPeWShAVOFyxDBwoyGOC9xProejMYqscuTJYMxjg36z708/lHQA6z/Ho z2y3tw/7KjJZCGOY54vPJOz5U667wbE1OgG2iktoXPxHQ+OQB/EDzyzBhhRjUHGaLylO D92g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=4S5lqn5I3zXmixd7LhbTzQ90QBdVDOadcoSgSK1gCOU=; b=W1P/eHwxYnDnoIfcdN2zh+zjH/AQm4qFvN18dOlTaWXsy8DhC13T/NVDMRXUlgBFEj t5mS86T38VUOzMeM7iLH/rvFtB7u4JQdKnN0so1b2+wbnVrDY5vC9ctA5kFK156iXr0D Vpm+mprbjXAJAImXyXf5AtIcFTVriuq38y2dTvPEMrKvmHkHU5zVRc2vylGdRo6o14p7 OBTXAxNEeKMG/OkDwShR3E5yyIzOGOdRWKY4ej4lcvAiEI4gbJQN+AULNhPNoIel21oQ zJaxTZRGlZNjEzePovPfiKwdB4FIQc8OwAhv2+rm1/ZSaa8F5/rKjwsg8WL69E+93zZE 20yQ== X-Gm-Message-State: APjAAAX/bsQG5CB8BoBUJvyCly8X1u0KWcXAVId597CWbeAUVH1rn5iU TLJRCMDQkqyC3XR06hJ8Bm0YcEiIDw== X-Google-Smtp-Source: APXvYqylhQw4ltDpktiVjx6zWXMhigkwD7C2gG3zsJn/8dmWhxog4MIBDsp1oOp0vLh0T00iuPwzGQ== X-Received: by 2002:a81:3358:: with SMTP id z85mr46704537ywz.251.1560395099163; Wed, 12 Jun 2019 20:04:59 -0700 (PDT) Received: from 960.localdomain ([71.46.56.3]) by smtp.gmail.com with ESMTPSA id j184sm424831ywf.8.2019.06.12.20.04.58 (version=TLS1_3 cipher=AEAD-AES256-GCM-SHA384 bits=256/256); Wed, 12 Jun 2019 20:04:58 -0700 (PDT) From: Ayman Bagabas To: Darren Hart , Andy Shevchenko , platform-driver-x86@vger.kernel.org, linux-kernel@vger.kernel.org Cc: ayman.bagabas@gmail.com Subject: [PATCH v2 4/8] platform/x86: huawei-wmi: control micmute LED through WMI interface Date: Wed, 12 Jun 2019 23:04:11 -0400 Message-Id: <20190613030416.25807-6-ayman.bagabas@gmail.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190613030416.25807-1-ayman.bagabas@gmail.com> References: <20190613030416.25807-1-ayman.bagabas@gmail.com> MIME-Version: 1.0 Sender: platform-driver-x86-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: platform-driver-x86@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Using HWMI interface, micmute LED can be controlled on supported models. `MateBook X` from 2017, doesn't provide controlling the micmute LED through this interface instead it uses another "legacy" interface that is not "fully" implemented yet. Currently, this "legacy" interface is used for hotkeys on this specific model. A quirk is set to use ACPI method to control micmute LED on MateBook X (2017). Signed-off-by: Ayman Bagabas --- drivers/platform/x86/huawei-wmi.c | 74 ++++++++++++++++++------------- 1 file changed, 42 insertions(+), 32 deletions(-) diff --git a/drivers/platform/x86/huawei-wmi.c b/drivers/platform/x86/huawei-wmi.c index 647c5a6c8ab3..358d9d168300 100644 --- a/drivers/platform/x86/huawei-wmi.c +++ b/drivers/platform/x86/huawei-wmi.c @@ -239,42 +239,52 @@ static int huawei_wmi_cmd(struct device *dev, u64 arg, u8 *buf, size_t buflen) static int huawei_wmi_micmute_led_set(struct led_classdev *led_cdev, enum led_brightness brightness) { - char *acpi_method; - acpi_handle handle; - acpi_status status; - union acpi_object args[3]; - struct acpi_object_list arg_list = { - .pointer = args, - .count = ARRAY_SIZE(args), - }; - - handle = ec_get_handle(); - if (!handle) { - dev_err(led_cdev->dev->parent, "Failed to get EC handle\n"); - return -ENODEV; - } + /* This is a workaround until the "legacy" interface is implemented. */ + if (quirks && quirks->ec_micmute) { + char *acpi_method; + acpi_handle handle; + acpi_status status; + union acpi_object args[3]; + struct acpi_object_list arg_list = { + .pointer = args, + .count = ARRAY_SIZE(args), + }; + + handle = ec_get_handle(); + if (!handle) { + dev_err(led_cdev->dev->parent, "Failed to get EC handle\n"); + return -ENODEV; + } - args[0].type = args[1].type = args[2].type = ACPI_TYPE_INTEGER; - args[1].integer.value = 0x04; - - if (acpi_has_method(handle, "SPIN")) { - acpi_method = "SPIN"; - args[0].integer.value = 0; - args[2].integer.value = brightness ? 1 : 0; - } else if (acpi_has_method(handle, "WPIN")) { - acpi_method = "WPIN"; - args[0].integer.value = 1; - args[2].integer.value = brightness ? 0 : 1; + args[0].type = args[1].type = args[2].type = ACPI_TYPE_INTEGER; + args[1].integer.value = 0x04; + + if (acpi_has_method(handle, "SPIN")) { + acpi_method = "SPIN"; + args[0].integer.value = 0; + args[2].integer.value = brightness ? 1 : 0; + } else if (acpi_has_method(handle, "WPIN")) { + acpi_method = "WPIN"; + args[0].integer.value = 1; + args[2].integer.value = brightness ? 0 : 1; + } else { + return -ENODEV; + } + + status = acpi_evaluate_object(handle, acpi_method, &arg_list, NULL); + if (ACPI_FAILURE(status)) { + return -ENODEV; + } + + return 0; } else { - return -ENODEV; - } + u8 arg[8]; - status = acpi_evaluate_object(handle, acpi_method, &arg_list, NULL); - if (ACPI_FAILURE(status)) { - return -ENODEV; - } + *(u64 *)arg = MICMUTE_LED_SET; + arg[2] = brightness; - return 0; + return huawei_wmi_cmd(led_cdev->dev->parent, *(u64 *)arg, NULL, NULL); + } } static int huawei_wmi_leds_setup(struct device *dev) From patchwork Thu Jun 13 03:04:12 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ayman Bagabas X-Patchwork-Id: 10993025 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 7589814DB for ; Thu, 13 Jun 2019 16:53:18 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 65CEA204FD for ; Thu, 13 Jun 2019 16:53:18 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 596CE22A68; Thu, 13 Jun 2019 16:53:18 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FROM,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 42526204FD for ; Thu, 13 Jun 2019 16:53:17 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1725852AbfFMQxQ (ORCPT ); Thu, 13 Jun 2019 12:53:16 -0400 Received: from mail-yw1-f67.google.com ([209.85.161.67]:35343 "EHLO mail-yw1-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730096AbfFMDFB (ORCPT ); Wed, 12 Jun 2019 23:05:01 -0400 Received: by mail-yw1-f67.google.com with SMTP id k128so7722218ywf.2; Wed, 12 Jun 2019 20:05:00 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=maWSYYRrvybYLk/ZwWvDJFQUXbxnczUBvQ66MuAR1dc=; b=VHXWTh2mZ0oAsXy17t6u1QflJMPukrCoBzvL9WuTHC8D+AHupnXjAB/LeT3RpTZ3sC iOOEwf8Xi3ADTgIWVAQ+8Gg9wrhOeWRCnJS/JaTUIDbTpkNwVAmrU2hj8hYHGistWht3 er3TxXYJgi5K32kJbaKxmqYfiK2487FfbqBsYm8esStBaNxAyQbemBSdYVFQmRuleyoO QEVFbQ6U5vtVmQsM6MqUSUFvnJRybJ9bHy8kr77e7w5q2l7maA6lpYR4XjzxFfsMqOeu Ie9LqaGuRQTVk7DYW5FbLovrMyQ0ijYjhmXY104yCkm9bpePQevfjtMW19yH7HTBbkaP LPeQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=maWSYYRrvybYLk/ZwWvDJFQUXbxnczUBvQ66MuAR1dc=; b=T/piU1+rcSNXmHeQOGuadLDC6xQFpY9Sinhqalj9OnnRFI+LITHzoVM6NCObwBzF2N m+q6BOT3cBKLTslEXzR7W1KhDsZZcFtHKM7wss1ixI/4d2atnJBTxL94L8a0K8d9q70m jyHgJgkgjvxBNt3QKzAhuUlImLXw2iqvdNB+HHRqxyvMD2ECIxT4nskh7kaxe9gRZfLo V3mK8WbIz1j7E14L5k9M0NOYx+cEk5MFK0zSI1rS6nr8B0z1DpQzS4rKjADsyc/WvyeS NiIxiSGwRs7PH3fGr16oWbkTqTb3gkYQXeUcPbl23wJ+cmHY305ttftZ91oL5g5RTZpG 4LSA== X-Gm-Message-State: APjAAAWK56vdmr3U9I0YQ4TDnE5xMgyj+shpx/F2W4Qg3+WqbRQ99wOs kHEdJV7paB3BISxVELW2mg== X-Google-Smtp-Source: APXvYqwalc9ioEK569U58MgtvdylDr75TJ1pfhNP9M1+ymoS432VWYMQYU2WFK7KGp9WIIZ1vRywXQ== X-Received: by 2002:a81:4786:: with SMTP id u128mr46699794ywa.43.1560395100453; Wed, 12 Jun 2019 20:05:00 -0700 (PDT) Received: from 960.localdomain ([71.46.56.3]) by smtp.gmail.com with ESMTPSA id j184sm424831ywf.8.2019.06.12.20.04.59 (version=TLS1_3 cipher=AEAD-AES256-GCM-SHA384 bits=256/256); Wed, 12 Jun 2019 20:05:00 -0700 (PDT) From: Ayman Bagabas To: Darren Hart , Andy Shevchenko , platform-driver-x86@vger.kernel.org, linux-kernel@vger.kernel.org Cc: ayman.bagabas@gmail.com Subject: [PATCH v2 5/8] platform/x86: huawei-wmi: add battery charging protection support Date: Wed, 12 Jun 2019 23:04:12 -0400 Message-Id: <20190613030416.25807-7-ayman.bagabas@gmail.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190613030416.25807-1-ayman.bagabas@gmail.com> References: <20190613030416.25807-1-ayman.bagabas@gmail.com> MIME-Version: 1.0 Sender: platform-driver-x86-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: platform-driver-x86@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Some models that implement the new WMI management interface can control battery charging thresholds where it limits charging the battery once it reaches certain thresholds. This feature is not present in MateBook X (2017). Signed-off-by: Ayman Bagabas --- drivers/platform/x86/huawei-wmi.c | 56 +++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/drivers/platform/x86/huawei-wmi.c b/drivers/platform/x86/huawei-wmi.c index 358d9d168300..06d83e613504 100644 --- a/drivers/platform/x86/huawei-wmi.c +++ b/drivers/platform/x86/huawei-wmi.c @@ -6,6 +6,7 @@ */ #include +#include #include #include #include @@ -48,6 +49,7 @@ struct huawei_wmi { struct led_classdev cdev; struct input_dev *idev[2]; struct mutex wmi_lock; + struct mutex battery_lock; struct platform_device *pdev; }; @@ -302,6 +304,59 @@ static int huawei_wmi_leds_setup(struct device *dev) return devm_led_classdev_register(dev, &huawei->cdev); } +/* Battery protection */ + +static int huawei_wmi_battery_get(struct device *dev, int *low, int *high) +{ + struct huawei_wmi *huawei = dev_get_drvdata(dev); + u8 ret[0x100]; + int err, i; + + mutex_lock(&huawei->battery_lock); + err = huawei_wmi_cmd(dev, BATTERY_THRESH_GET, ret, 0x100); + mutex_unlock(&huawei->battery_lock); + if (err) { + return err; + } + + /* Find the last two non-zero values. Return status is ignored. */ + i = 0x100; + do { + *low = ret[i-1]; + *high = ret[i]; + } while (i > 2 && !ret[i--]); + + return 0; +} + +static int huawei_wmi_battery_set(struct device *dev, int low, int high) +{ + struct huawei_wmi *huawei = dev_get_drvdata(dev); + u8 arg[8]; + int err; + + *(u64 *)arg = BATTERY_THRESH_SET; + arg[2] = low; + arg[3] = high; + + /* This is an edge case were some models turn battery protection + * off without changing their thresholds values. We clear the + * values before turning off protection. Sometimes we need a sleep delay to + * make sure these values make their way to EC memory. + */ + if (low == 0 && high == 100) { + huawei_wmi_battery_set(dev, 0, 0); + } + + mutex_lock(&huawei->battery_lock); + err = huawei_wmi_cmd(dev, *(u64 *)arg, NULL, NULL); + if (quirks && quirks->battery_sleep) + msleep(1000); + mutex_unlock(&huawei->battery_lock); + + return err; +} + /* Input */ static void huawei_wmi_process_key(struct input_dev *idev, int code) @@ -424,6 +479,7 @@ static int huawei_wmi_probe(struct platform_device *pdev) if (wmi_has_guid(HWMI_METHOD_GUID)) { mutex_init(&huawei->wmi_lock); + mutex_init(&huawei->battery_lock); err = huawei_wmi_leds_setup(&pdev->dev); if (err) dev_err(&pdev->dev, "Failed to setup leds\n"); From patchwork Thu Jun 13 03:04:13 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ayman Bagabas X-Patchwork-Id: 10993021 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 36E8B924 for ; Thu, 13 Jun 2019 16:53:12 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 2586F204FD for ; Thu, 13 Jun 2019 16:53:12 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 1A04B22A68; Thu, 13 Jun 2019 16:53:12 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FROM,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id B187F204FD for ; Thu, 13 Jun 2019 16:53:11 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730117AbfFMQws (ORCPT ); Thu, 13 Jun 2019 12:52:48 -0400 Received: from mail-yb1-f194.google.com ([209.85.219.194]:37537 "EHLO mail-yb1-f194.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730098AbfFMDFC (ORCPT ); Wed, 12 Jun 2019 23:05:02 -0400 Received: by mail-yb1-f194.google.com with SMTP id v144so1427249ybb.4; Wed, 12 Jun 2019 20:05:02 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=wWWBa0nTBIfYqSobNC1C7xjNtAsVYb7zyqkZL1BlQZY=; b=pq06vN7Ms6UkApZ0vO7TyshYj05cnnMm445rxsQlPQH0AuaDb0hdXCmpASyDEt77x2 W6xZ6qgII7nhqXXMJlINNaNqOZrrylfoFJDfjsDR6ITbLRaUltHUU9dm8tTR91+jO3vm YRpVelRi+uHB5LzOs3X4O+IFT/UKw8i8hSbWFOeI+dcq4IVPsX2gHkQ8uF8o1T+jQuqq 7B8UNFlVy9ArWLOCbvSc+tQCth9kFBZVZko3IfvoqGPeFqcU/cJ4gralqp5MK+0AiErM IPgqqJ07NPkC4eFwlEIoU7SweSZMXGgYpStlm0KpjlWVsc4SgsKiWph7HCYf1o+xhuVn L5lA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=wWWBa0nTBIfYqSobNC1C7xjNtAsVYb7zyqkZL1BlQZY=; b=mQOladKUYXFP6cmLFaE6yJP/d7uF5I85O2v2Rj4vnr/k+9H5NFO6uNqEInv0pAcsMu Qp2tFAgWVJ7Pe8XYMgkpq5CMDEi6FpK8HdXexdE+/4pRILd9pKN+ZY6pDYb+71L+v0SI uKAsjzJWeQ3H1rpS8NtPmBAlZegys8psQYSGy+n5fnldqu8KONAgJTXoc2nOCfwUWtIc xim4+AqY63YDvZ9guAKGvPh89N54aDmRjlGiDiuQ8f3qXb6wiSi1h3DdODxBE3yFAhyV 7ragQCN2kcxMqQz4DNp3883RAvq6ztWGPHxjxkz+WF8SgRUhFxA44Fu5SEMKQoASzxOj 0bag== X-Gm-Message-State: APjAAAWnWACJwcI2YHzkhKRKhvafhMgC6qWj/63UcgoBAK5vWaSR0WMa hbDDT9D9Rrsmq16mmWQAkD4rxusVTA== X-Google-Smtp-Source: APXvYqyNuXd2BE5Co4jcJjOydd8vpZMOsSp5ubsDeM1jILgi58Mwh4DV3zMnQzpjmzJXC4Hu34k/5w== X-Received: by 2002:a25:4115:: with SMTP id o21mr40435969yba.162.1560395101673; Wed, 12 Jun 2019 20:05:01 -0700 (PDT) Received: from 960.localdomain ([71.46.56.3]) by smtp.gmail.com with ESMTPSA id j184sm424831ywf.8.2019.06.12.20.05.01 (version=TLS1_3 cipher=AEAD-AES256-GCM-SHA384 bits=256/256); Wed, 12 Jun 2019 20:05:01 -0700 (PDT) From: Ayman Bagabas To: Darren Hart , Andy Shevchenko , platform-driver-x86@vger.kernel.org, linux-kernel@vger.kernel.org Cc: ayman.bagabas@gmail.com Subject: [PATCH v2 6/8] platform/x86: huawei-wmi: add fn-lock support Date: Wed, 12 Jun 2019 23:04:13 -0400 Message-Id: <20190613030416.25807-8-ayman.bagabas@gmail.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190613030416.25807-1-ayman.bagabas@gmail.com> References: <20190613030416.25807-1-ayman.bagabas@gmail.com> MIME-Version: 1.0 Sender: platform-driver-x86-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: platform-driver-x86@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP The behavior of hotkeys is not the same among all models. Some models require fn-lock to do things like `Ctrl-Ins` or `Alt-PrtSc`. By default, hotkeys behave as special keys (media keys, Ins, etc), but if a modifier is used (ctrl, alt, shift) these keys behave as F1-F12 keys. If the Fn key is toggled on, the hotkeys with or without a modifier, behave as F1-F12 keys. This makes it impossible to use a modifier and `PrtSc` or `Ins`. Now, some models fix this by excluding `PrtSc` and `Ins` keys from being treated as F11 and F12 keys with the use of a modifier. However, some models do not, and fixes this by the so called fn-lock. Fn-lock inverts the behavior of the top row from special keys to F1-F12 keys. So a modifier and a special key would be possible which make things like `Alt-Ins` possible. Now, with fn-lock we would have 4 modes: * Fn-key off & fn-lock off - hotkeys treated as special keys using a modifier gives F1-F12 keys. * Fn-key on & fn-lock off - hotkeys treated as F1-F12 keys and using a modifier gives F1-F12. * Fn-key off & fn-lock on - hotkeys are treated as F1-F12 keys and using a modifier gives special keys. * Fn-key on & fn-lock on - hotkeys are treated as special keys and using a modifier gives special keys. Signed-off-by: Ayman Bagabas --- drivers/platform/x86/huawei-wmi.c | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/drivers/platform/x86/huawei-wmi.c b/drivers/platform/x86/huawei-wmi.c index 06d83e613504..aac9b80f9976 100644 --- a/drivers/platform/x86/huawei-wmi.c +++ b/drivers/platform/x86/huawei-wmi.c @@ -357,6 +357,37 @@ static int huawei_wmi_battery_set(struct device *dev, int low, int high) return err; } +/* Fn lock */ + +static int huawei_wmi_fn_lock_get(struct device *dev, int *on) +{ + u8 ret[0x100] = { 0 }; + int err, i; + + err = huawei_wmi_cmd(dev, FN_LOCK_GET, ret, 0x100); + if (err) { + return err; + } + + /* Find the first non-zero value. Return status is ignored. */ + i = 1; + do { + *on = ret[i] - 1; // -1 undefined, 0 off, 1 on. + } while (i < 0x100 && !ret[i++]); + + return 0; +} + +static int huawei_wmi_fn_lock_set(struct device *dev, int on) +{ + u8 arg[8]; + + *(u64 *)arg = FN_LOCK_SET; + arg[2] = on + 1; // 0 undefined, 1 off, 2 on. + + return huawei_wmi_cmd(dev, *(u64 *)arg, NULL, NULL); +} + /* Input */ static void huawei_wmi_process_key(struct input_dev *idev, int code) From patchwork Thu Jun 13 03:04:14 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ayman Bagabas X-Patchwork-Id: 10993017 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 42BBF13AD for ; Thu, 13 Jun 2019 16:53:10 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 3218A204FD for ; Thu, 13 Jun 2019 16:53:10 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 2576922A68; Thu, 13 Jun 2019 16:53:10 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FROM,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id AA0DC204FD for ; Thu, 13 Jun 2019 16:53:09 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1725837AbfFMQws (ORCPT ); Thu, 13 Jun 2019 12:52:48 -0400 Received: from mail-yw1-f68.google.com ([209.85.161.68]:41296 "EHLO mail-yw1-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730100AbfFMDFD (ORCPT ); Wed, 12 Jun 2019 23:05:03 -0400 Received: by mail-yw1-f68.google.com with SMTP id y185so7714322ywy.8; Wed, 12 Jun 2019 20:05:03 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=myoxJzu/9GGD8CDA7Jss3DQ4pwILeQvRbCANtsG19pw=; b=YiFpGG5M4wKy3HRF/pP5FMtdCciPX4Trjz4ief8Xx5F3YkrXZsv/L9ctZSNUQ/To/m auB54GSjyhGZ9k41VPJ1Nm9jExldGaxu7UH3mYpGutyIr2Z2eASpFnWEfQyCdr+1tndx pOdoel4EnqFJoQaTZ1toTOJsInMUN1fTrCqBiMBErUas3hrPX3D+jWwl67W2r5ZEt4/z 71og30607ygiI2uBOEZmOwK7ubFYmIsrLEHhYeVP7DD4E528IjqQc/mreAM956FGvu/6 Gss6JGyRZEhsrnsZKA+OHJ/QwAAE/oGCME63FRaw0mk97Zq7ZO6uFHxaQcX2G6Ds3zGj A+0Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=myoxJzu/9GGD8CDA7Jss3DQ4pwILeQvRbCANtsG19pw=; b=EBMkL9+sDW6B5FNHnvlSnDOvDZ5kvQsBTqeCvpII4X1/DvmkETZOvrxMA6n5YVtMqd j54Vj9XcwmjXQ7kB+HdTSsyDnAFSKAH8cOHvwK+C/aFmtLpn8PulAzmsFRpo7XruT4Wu FhPw78M4QpC56YxLCXGm8g9EhbHke2G3vALFIq9/3e6mqY5xIJMFYZW6rcOE3SY43707 EjcmxYVaR2iOb7KluUq5jz7NYgMgaGj4wsrtg7k7NltfoiDTDXmZ7+GZ08ggv7Oad1g3 c+3KKQ/8eHkx/0Lft4gssad3nkwB5ITxaRs9NjAXLF4ehcd/wVhCsCnNnUTUHZnwyZbC bU4g== X-Gm-Message-State: APjAAAWTgNE9E2DG++sTsD145wUkRY0PTJSUvzKak+4zgd80WkaMJ89b BQEif3mTsOu1BMwcwWJMpg== X-Google-Smtp-Source: APXvYqwMfUTh7v1bSfm2TC7qB5zZG+zAFVgIk0L2up9GYpWETsqpYMvG6u6+R0GIT4VLe+Ko9kda9Q== X-Received: by 2002:a0d:d806:: with SMTP id a6mr45667997ywe.420.1560395102980; Wed, 12 Jun 2019 20:05:02 -0700 (PDT) Received: from 960.localdomain ([71.46.56.3]) by smtp.gmail.com with ESMTPSA id j184sm424831ywf.8.2019.06.12.20.05.02 (version=TLS1_3 cipher=AEAD-AES256-GCM-SHA384 bits=256/256); Wed, 12 Jun 2019 20:05:02 -0700 (PDT) From: Ayman Bagabas To: Darren Hart , Andy Shevchenko , platform-driver-x86@vger.kernel.org, linux-kernel@vger.kernel.org Cc: ayman.bagabas@gmail.com Subject: [PATCH v2 7/8] platform/x86: huawei-wmi: add sysfs interface support Date: Wed, 12 Jun 2019 23:04:14 -0400 Message-Id: <20190613030416.25807-9-ayman.bagabas@gmail.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190613030416.25807-1-ayman.bagabas@gmail.com> References: <20190613030416.25807-1-ayman.bagabas@gmail.com> MIME-Version: 1.0 Sender: platform-driver-x86-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: platform-driver-x86@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Battery charging thresholds and fn-lock are implemented as sysfs attributes. Both have R/W permissions and set with root permission. Although using Huawei Management Software in Windows gives access to these features without admin privileges, user could use something like a udev rule to change writing permissions of these attributes. Signed-off-by: Ayman Bagabas --- drivers/platform/x86/huawei-wmi.c | 87 +++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) diff --git a/drivers/platform/x86/huawei-wmi.c b/drivers/platform/x86/huawei-wmi.c index aac9b80f9976..cc6745ff1bad 100644 --- a/drivers/platform/x86/huawei-wmi.c +++ b/drivers/platform/x86/huawei-wmi.c @@ -14,6 +14,7 @@ #include #include #include +#include #include /* @@ -388,6 +389,80 @@ static int huawei_wmi_fn_lock_set(struct device *dev, int on) return huawei_wmi_cmd(dev, *(u64 *)arg, NULL, NULL); } +/* sysfs */ + +static ssize_t charge_thresholds_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + int err, low, high; + + err = huawei_wmi_battery_get(dev, &low, &high); + if (err) + return err; + + return sprintf(buf, "%d %d\n", low, high); +} + +static ssize_t charge_thresholds_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size) +{ + int low, high, err; + + if (sscanf(buf, "%d %d", &low, &high) != 2 || + low < 0 || high > 100 || + low > high) + return -EINVAL; + + err = huawei_wmi_battery_set(dev, low, high); + if (err) + return err; + + return size; +} + +static ssize_t fn_lock_state_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + int err, on; + + err = huawei_wmi_fn_lock_get(dev, &on); + if (err) + return err; + + return sprintf(buf, "%d\n", on); +} + +static ssize_t fn_lock_state_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size) +{ + int on, err; + + if (kstrtoint(buf, 10, &on) || + on < 0 || on > 1) + return -EINVAL; + + err = huawei_wmi_fn_lock_set(dev, on); + if (err) + return err; + + return size; +} + +static DEVICE_ATTR_RW(charge_thresholds); +static DEVICE_ATTR_RW(fn_lock_state); + +static struct attribute *huawei_wmi_attrs[] = { + &dev_attr_charge_thresholds.attr, + &dev_attr_fn_lock_state.attr, + NULL +}; + +ATTRIBUTE_GROUPS(huawei_wmi); + /* Input */ static void huawei_wmi_process_key(struct input_dev *idev, int code) @@ -509,8 +584,16 @@ static int huawei_wmi_probe(struct platform_device *pdev) } if (wmi_has_guid(HWMI_METHOD_GUID)) { + mutex_init(&huawei->wmi_lock); mutex_init(&huawei->battery_lock); + + err = sysfs_create_group(&pdev->dev.kobj, &huawei_wmi_group); + if (err) { + dev_err(&pdev->dev, "Failed to create sysfs interface\n"); + return err; + } + err = huawei_wmi_leds_setup(&pdev->dev); if (err) dev_err(&pdev->dev, "Failed to setup leds\n"); @@ -526,6 +609,10 @@ static int huawei_wmi_remove(struct platform_device *pdev) if (wmi_has_guid(HWMI_EVENT_GUID)) wmi_remove_notify_handler(HWMI_EVENT_GUID); + if (wmi_has_guid(HWMI_METHOD_GUID)) { + sysfs_remove_group(&pdev->dev.kobj, &huawei_wmi_group); + } + return 0; } From patchwork Thu Jun 13 03:04:15 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ayman Bagabas X-Patchwork-Id: 10993019 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 76C9413AD for ; Thu, 13 Jun 2019 16:53:11 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 65556204FD for ; Thu, 13 Jun 2019 16:53:11 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 5931A22A68; Thu, 13 Jun 2019 16:53:11 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FROM,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id DA4BB204FD for ; Thu, 13 Jun 2019 16:53:10 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730105AbfFMQws (ORCPT ); Thu, 13 Jun 2019 12:52:48 -0400 Received: from mail-yb1-f193.google.com ([209.85.219.193]:46651 "EHLO mail-yb1-f193.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730101AbfFMDFF (ORCPT ); Wed, 12 Jun 2019 23:05:05 -0400 Received: by mail-yb1-f193.google.com with SMTP id p8so7189267ybo.13; Wed, 12 Jun 2019 20:05:04 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=avxwadTNE1a71wDomhQ/ZZmaD0txhopJrsKMB0EV4wo=; b=E1AzkrzQ5MTzeWt0LWAN5qdswY5GbDun/Q8rZsfTeQ7WY8CGbJ5Xkx3W8elwusUpTE OU+IffJv3JmhVhL6MQzVLP8FxTZAIXr/QQyz28jcgIgbxotGSESWKshcUlxORGFyfWrV dUXxg8PdAQ1o4QGXhzFN4cvPpRI/u+6nP4w4IEe8ZbDKI2L596x2qzaN/V+rLj/tOyxs IQFeXmLTnTGiL7TvFanIyKHCttX4wP5l0Lh7i/AcI9jj1Xjx8/fSWEkuU+fsq5F4koac gsrJnDBAQYNR07cXZDFRthxJeiXyekeFfcB9yuwY/7BfmFcwhW/H55MvU8Dpy7+5OBRh KlqQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=avxwadTNE1a71wDomhQ/ZZmaD0txhopJrsKMB0EV4wo=; b=KOoQPYMyQSqPLsX6JQSSQtGQx3FeD1L84Sw03eC1g5Xmd+FlV/plBwR6a6FH6jIu1W WbYpmh6P7iixN5ZQpPiNzQk0ZZudj+npeJHCg8snRP+xQVFWJ3p2FafCVv8UXnYc59YR ogJrAoiNxCJd0Oo8CKSe/c5q2EbhoLJ2mApkCyNvThtbrR4qUrNaEQJGz+YOH4h1/ySa 6r517ZxrYk8mrIrsdxSsCbdGHF08iAN6p9cZUd5kVh/lDgK/OFuWsl3tl1HdZfzj/5/S jskj6qmgRK8JbAqrmT8UoCqE0aXHuVLOUTA1jps2IsfrsvHQt/BbNgOw6Y/vvuVJFy9n CEFQ== X-Gm-Message-State: APjAAAVFVfSlvh9b9MjSQDhMPmriAY9zZOPzvkKnR4dCRaguh1Yj6urt wgJXM9hOHnikXSFirCGhOBsRc9aJWQ== X-Google-Smtp-Source: APXvYqzNbq/DIp83v1nhwYJtQdaQss3Kk2KAfqHa2OG+ZxBlzUrkSMVEicDr+fufaPMXukd5YLwPnQ== X-Received: by 2002:a25:d9cc:: with SMTP id q195mr42965806ybg.390.1560395104284; Wed, 12 Jun 2019 20:05:04 -0700 (PDT) Received: from 960.localdomain ([71.46.56.3]) by smtp.gmail.com with ESMTPSA id j184sm424831ywf.8.2019.06.12.20.05.03 (version=TLS1_3 cipher=AEAD-AES256-GCM-SHA384 bits=256/256); Wed, 12 Jun 2019 20:05:03 -0700 (PDT) From: Ayman Bagabas To: Darren Hart , Andy Shevchenko , platform-driver-x86@vger.kernel.org, linux-kernel@vger.kernel.org Cc: ayman.bagabas@gmail.com Subject: [PATCH v2 8/8] platform/x86: huawei-wmi: add debugfs files support Date: Wed, 12 Jun 2019 23:04:15 -0400 Message-Id: <20190613030416.25807-10-ayman.bagabas@gmail.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190613030416.25807-1-ayman.bagabas@gmail.com> References: <20190613030416.25807-1-ayman.bagabas@gmail.com> MIME-Version: 1.0 Sender: platform-driver-x86-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: platform-driver-x86@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP A debugfs interface that creates two attributes `arg` and `call` to set an argument to be called by the WMI device and show the results returned. This argument is a 64 bit long which complies the properties of the HWMI interface. Signed-off-by: Ayman Bagabas --- drivers/platform/x86/huawei-wmi.c | 117 ++++++++++++++++++++++++++++++ 1 file changed, 117 insertions(+) diff --git a/drivers/platform/x86/huawei-wmi.c b/drivers/platform/x86/huawei-wmi.c index cc6745ff1bad..a74ddd9adb47 100644 --- a/drivers/platform/x86/huawei-wmi.c +++ b/drivers/platform/x86/huawei-wmi.c @@ -6,6 +6,7 @@ */ #include +#include #include #include #include @@ -46,8 +47,14 @@ struct quirk_entry { static struct quirk_entry *quirks; +struct huawei_wmi_debug { + struct dentry *root; + u64 arg; +}; + struct huawei_wmi { struct led_classdev cdev; + struct huawei_wmi_debug debug; struct input_dev *idev[2]; struct mutex wmi_lock; struct mutex battery_lock; @@ -463,6 +470,110 @@ static struct attribute *huawei_wmi_attrs[] = { ATTRIBUTE_GROUPS(huawei_wmi); +/* debugfs */ + +static void huawei_wmi_debugfs_call_dump(struct seq_file *m, void *data, + union acpi_object *obj) +{ + struct huawei_wmi *huawei = m->private; + int i; + + switch (obj->type) { + case ACPI_TYPE_INTEGER: + seq_printf(m, "0x%llx", obj->integer.value); + break; + case ACPI_TYPE_STRING: + seq_printf(m, "\"%*s\"", obj->string.length, obj->string.pointer); + break; + case ACPI_TYPE_BUFFER: + seq_printf(m, "{"); + for (i = 0; i < obj->buffer.length; i++) { + seq_printf(m, "0x%02x", obj->buffer.pointer[i]); + if (i < obj->buffer.length - 1) + seq_printf(m, ","); + } + seq_printf(m, "}"); + break; + case ACPI_TYPE_PACKAGE: + seq_printf(m, "["); + for (i = 0; i < obj->package.count; i++) { + huawei_wmi_debugfs_call_dump(m, huawei, &obj->package.elements[i]); + if (i < obj->package.count - 1) + seq_printf(m, ","); + } + seq_printf(m, "]"); + break; + default: + dev_err(&huawei->pdev->dev, "Unexpected obj type, got %d\n", obj->type); + return; + } +} + +static int huawei_wmi_debugfs_call_show(struct seq_file *m, void *data) +{ + struct huawei_wmi *huawei = m->private; + struct acpi_buffer out = { ACPI_ALLOCATE_BUFFER, NULL }; + struct acpi_buffer in; + union acpi_object *obj; + int err; + + in.length = sizeof(u64); + in.pointer = &huawei->debug.arg; + + err = huawei_wmi_call(&huawei->pdev->dev, &in, &out); + if (err) + return err; + + obj = out.pointer; + if (!obj) { + err = -EIO; + goto fail_debugfs_call; + } + + huawei_wmi_debugfs_call_dump(m, huawei, obj); + +fail_debugfs_call: + kfree(out.pointer); + return err; +} + +DEFINE_SHOW_ATTRIBUTE(huawei_wmi_debugfs_call); + +static void huawei_wmi_debugfs_exit(struct device *dev) +{ + struct huawei_wmi *huawei = dev_get_drvdata(dev); + + debugfs_remove_recursive(huawei->debug.root); +} + +static int huawei_wmi_debugfs_init(struct device *dev) +{ + struct huawei_wmi *huawei = dev_get_drvdata(dev); + struct dentry *dent; + + huawei->debug.root = debugfs_create_dir("huawei-wmi", NULL); + if (!huawei->debug.root) { + dev_err(dev, "Failed to create debugfs directory\n"); + goto fail_debugfs; + } + + dent = debugfs_create_x64("arg", S_IRUGO | S_IWUSR, huawei->debug.root, + &huawei->debug.arg); + if (!dent) + goto fail_debugfs; + + dent = debugfs_create_file("call", S_IFREG | S_IRUSR, + huawei->debug.root, huawei, &huawei_wmi_debugfs_call_fops); + if (!dent) + goto fail_debugfs; + + return 0; + +fail_debugfs: + huawei_wmi_debugfs_exit(dev); + return -ENOMEM; +} + /* Input */ static void huawei_wmi_process_key(struct input_dev *idev, int code) @@ -597,7 +708,12 @@ static int huawei_wmi_probe(struct platform_device *pdev) err = huawei_wmi_leds_setup(&pdev->dev); if (err) dev_err(&pdev->dev, "Failed to setup leds\n"); + + err = huawei_wmi_debugfs_init(&pdev->dev); + if (err) + dev_err(&pdev->dev, "Failed to setup debugfs\n"); } + return 0; } @@ -610,6 +726,7 @@ static int huawei_wmi_remove(struct platform_device *pdev) wmi_remove_notify_handler(HWMI_EVENT_GUID); if (wmi_has_guid(HWMI_METHOD_GUID)) { + huawei_wmi_debugfs_exit(&pdev->dev); sysfs_remove_group(&pdev->dev.kobj, &huawei_wmi_group); }