All of lore.kernel.org
 help / color / mirror / Atom feed
From: Gavin Li <gavinli@thegavinli.com>
To: Corentin Chary <corentin.chary@gmail.com>
Cc: "platform-driver-x86@vger.kernel.org"
	<platform-driver-x86@vger.kernel.org>,
	Gavin Li <git@thegavinli.com>
Subject: Re: [PATCH] platform: add samsung-wmi driver for newer Samsung laptops
Date: Thu, 16 Apr 2015 03:33:30 -0700	[thread overview]
Message-ID: <CA+GxvY6VvimZO01aybweD5Qv_xcN+wrjoe-E-S1wN-2qC-Moig@mail.gmail.com> (raw)
In-Reply-To: <CA+GxvY4t-DBeaYzzhWqV8OexikkYUdCaCwFc=z_1gjnj5bXUfg@mail.gmail.com>

Actually there is an issue that affects the functionality of the
driver; I will have to work on this a bit more first. Thanks for the
feedback.

Gavin

On Thu, Apr 16, 2015 at 3:30 AM, Gavin Li <gavinli@thegavinli.com> wrote:
> Actually there is an issue that affects the functionality of the driver; I
> will have to work on this a bit more first. Thanks for the feedback.
>
> Gavin
>
> On Thu, Apr 16, 2015 at 12:04 AM, Corentin Chary <corentin.chary@gmail.com>
> wrote:
>>
>> On Tue, Apr 7, 2015 at 6:53 PM,  <gavinli@thegavinli.com> wrote:
>> > From: Gavin Li <git@thegavinli.com>
>> >
>> > This driver adds support for coarse (on or off) fan control and
>> > the keyboard backlight on newer Samsung laptops.
>> > ---
>> >  drivers/platform/x86/Kconfig       |  10 ++
>> >  drivers/platform/x86/Makefile      |   1 +
>> >  drivers/platform/x86/samsung-wmi.c | 221
>> > +++++++++++++++++++++++++++++++++++++
>> >  3 files changed, 232 insertions(+)
>> >  create mode 100644 drivers/platform/x86/samsung-wmi.c
>> >
>> > diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
>> > index 9752761..96f4620 100644
>> > --- a/drivers/platform/x86/Kconfig
>> > +++ b/drivers/platform/x86/Kconfig
>> > @@ -813,6 +813,16 @@ config SAMSUNG_LAPTOP
>> >           To compile this driver as a module, choose M here: the module
>> >           will be called samsung-laptop.
>> >
>> > +config SAMSUNG_WMI
>> > +       tristate "Samsung WMI driver (for newer Samsung laptops)"
>> > +       depends on ACPI
>> > +       depends on ACPI_WMI
>> > +       select LEDS_CLASS
>> > +       select NEW_LEDS
>> > +         ---help---
>> > +         This driver adds support for coarse (on or off) fan control
>> > +         and the keyboard backlight for newer Samsung laptops.
>> > +
>> >  config MXM_WMI
>> >         tristate "WMI support for MXM Laptop Graphics"
>> >         depends on ACPI_WMI
>> > diff --git a/drivers/platform/x86/Makefile
>> > b/drivers/platform/x86/Makefile
>> > index f82232b..4c65e51 100644
>> > --- a/drivers/platform/x86/Makefile
>> > +++ b/drivers/platform/x86/Makefile
>> > @@ -48,6 +48,7 @@ obj-$(CONFIG_XO1_RFKILL)      += xo1-rfkill.o
>> >  obj-$(CONFIG_XO15_EBOOK)       += xo15-ebook.o
>> >  obj-$(CONFIG_IBM_RTL)          += ibm_rtl.o
>> >  obj-$(CONFIG_SAMSUNG_LAPTOP)   += samsung-laptop.o
>> > +obj-$(CONFIG_SAMSUNG_WMI)      += samsung-wmi.o
>> >  obj-$(CONFIG_MXM_WMI)          += mxm-wmi.o
>> >  obj-$(CONFIG_INTEL_MID_POWER_BUTTON)   += intel_mid_powerbtn.o
>> >  obj-$(CONFIG_INTEL_OAKTRAIL)   += intel_oaktrail.o
>> > diff --git a/drivers/platform/x86/samsung-wmi.c
>> > b/drivers/platform/x86/samsung-wmi.c
>> > new file mode 100644
>> > index 0000000..c93cfe4
>> > --- /dev/null
>> > +++ b/drivers/platform/x86/samsung-wmi.c
>> > @@ -0,0 +1,221 @@
>> > +/*
>> > + *  Samsung WMI driver
>> > + *
>> > + *  Copyright (C) 2015 Gavin Li <git@thegavinli.com>
>> > + *
>> > + *  This program is free software; you can redistribute it and/or
>> > modify
>> > + *  it under the terms of the GNU General Public License as published
>> > by
>> > + *  the Free Software Foundation; either version 2 of the License, or
>> > + *  (at your option) any later version.
>> > + *
>> > + *  This program is distributed in the hope that it will be useful,
>> > + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
>> > + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>> > + *  GNU General Public License for more details.
>> > + *
>> > + *  You should have received a copy of the GNU General Public License
>> > along
>> > + *  with this program; if not, write to the Free Software Foundation,
>> > Inc.,
>> > + *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
>> > + */
>> > +
>> > +#include <linux/init.h>
>> > +#include <linux/module.h>
>> > +#include <linux/acpi.h>
>> > +#include <linux/leds.h>
>> > +#include <linux/platform_device.h>
>> > +
>> > +#define DRIVER_NAME "samsung-wmi"
>> > +#define WMI_GUID "C16C47BA-50E3-444A-AF3A-B1C348380001"
>> > +
>> > +struct samsung_wmi_packet {
>> > +       uint16_t magic;
>> > +       uint16_t opcode;
>> > +       uint8_t reqres;
>> > +       uint8_t data[16];
>> > +} __packed;
>> > +
>> > +static struct platform_device *samsung_wmi_device;
>> > +
>> > +static inline bool string_matches(const char *str, const char *kwd) {
>> > +       size_t len = strlen(kwd);
>> > +       if (strncmp(str, kwd, len) != 0)
>> > +               return false;
>> > +       return str[len] == '\0' || str[len] == '\n';
>> > +}
>> > +
>> > +static int samsung_wmi_method_call(uint16_t opcode, void *data, size_t
>> > len) {
>> > +       struct samsung_wmi_packet inpkt = {
>> > +               .magic = 0x5843,
>>
>> Please use a constant instead of a magic number here.
>>
>> > +               .opcode = opcode,
>> > +       };
>> > +       struct acpi_buffer inbuf = { sizeof(inpkt), &inpkt };
>> > +       struct acpi_buffer outbuf = { ACPI_ALLOCATE_BUFFER, NULL };
>> > +       union acpi_object *outobj;
>> > +       struct samsung_wmi_packet *outpkt;
>> > +       acpi_status st;
>> > +       int ret = -EIO;
>> > +       /********/
>> > +       if (len > 16) {
>>
>> Please use a constant instead of 16 here.
>>
>> > +               ret = -EINVAL;
>> > +               goto err0;
>> > +       }
>> > +       memcpy(inpkt.data, data, len);
>> > +       st = wmi_evaluate_method(WMI_GUID, 1, 0, &inbuf, &outbuf);
>> > +       if (ACPI_FAILURE(st)) {
>> > +               dev_err(&samsung_wmi_device->dev, "opcode 0x%x failed:
>> > %s\n",
>> > +                               opcode, acpi_format_exception(st));
>> > +               goto err0;
>> > +       }
>> > +       outobj = outbuf.pointer;
>> > +       if (outobj->type != ACPI_TYPE_BUFFER) {
>> > +               goto err1;
>> > +       }
>> > +       if (outobj->buffer.length < sizeof(outpkt)) {
>> > +               goto err1;
>> > +       }
>> > +       outpkt = (struct samsung_wmi_packet *)outobj->buffer.pointer;
>> > +       memcpy(data, outpkt->data, len);
>> > +       ret = 0;
>> > +err1:
>> > +       kfree(outobj);
>> > +err0:
>> > +       return ret;
>> > +}
>> > +
>> > +static int samsung_wmi_method_call_with_unlock(
>> > +               uint16_t unlock_opcode,
>> > +               uint16_t opcode, void *data, size_t len) {
>> > +       unsigned int unlock_data = 0xAABB;
>>
>> Same
>>
>> > +       int ret;
>> > +       /********/
>> > +       ret = samsung_wmi_method_call(unlock_opcode, &unlock_data,
>> > sizeof(unlock_data));
>> > +       if (ret)
>> > +               goto err0;
>> > +       if (unlock_data != 0xCCDD) {
>> > +               dev_err(&samsung_wmi_device->dev, "incorrect unlock
>> > response!\n");
>> > +               ret = -EIO;
>> > +               goto err0;
>> > +       }
>> > +       ret = samsung_wmi_method_call(opcode, data, len);
>> > +err0:
>> > +       return ret;
>> > +}
>> > +
>> > +static ssize_t samsung_wmi_fan_mode_show(struct device *dev, struct
>> > device_attribute *attr,
>> > +               char *buf) {
>> > +       uint32_t data = 0;
>> > +       if (samsung_wmi_method_call_with_unlock(0x31, 0x31, &data,
>> > sizeof(data)))
>> > +               return -EIO;
>> > +       if (data)
>> > +               strcpy(buf, "[auto off] on\n");
>> > +       else
>> > +               strcpy(buf, "auto off [on]\n");
>> > +       return strlen(buf);
>> > +}
>> > +
>> > +static ssize_t samsung_wmi_fan_mode_store(struct device *dev, struct
>> > device_attribute *attr,
>> > +               const char *buf, size_t count) {
>> > +       uint32_t data;
>> > +       if (string_matches(buf, "auto"))
>> > +               data = 0x810001;
>>
>> Same, and other places
>>
>> > +       else if (string_matches(buf, "on"))
>> > +               data = 0;
>> > +       else if (string_matches(buf, "off"))
>> > +               data = 0x800001;
>> > +       else
>> > +               return -EINVAL;
>> > +       if (samsung_wmi_method_call_with_unlock(0x31, 0x32, &data,
>> > sizeof(data)))
>> > +               return -EIO;
>> > +       else
>> > +               return count;
>> > +}
>> > +
>> > +static void samsung_wmi_kbd_backlight_led_brightness_set(
>> > +               struct led_classdev *cdev, enum led_brightness
>> > brightness) {
>> > +       unsigned int data = brightness;
>>
>> Why sometime uint32_t and sometime unsigned int ?
>>
>> > +       if (data > 4)
>> > +               data = 4;
>> > +       data = (data << 8) | 0x82;
>> > +       /********/
>> > +       samsung_wmi_method_call_with_unlock(0x78, 0x78, &data,
>> > sizeof(data));
>> > +}
>> > +
>> > +static DEVICE_ATTR(fan_mode, S_IRUGO | S_IWUSR,
>> > samsung_wmi_fan_mode_show, samsung_wmi_fan_mode_store);
>> > +
>> > +static struct platform_driver samsung_wmi_driver = {
>> > +       .driver = {
>> > +               .name = DRIVER_NAME,
>> > +               .owner = THIS_MODULE,
>> > +       },
>> > +};
>> > +
>> > +static struct led_classdev samsung_wmi_kbd_backlight_led = {
>> > +       .name = DRIVER_NAME "::kbd_backlight",
>> > +       .max_brightness = 4,
>> > +       .brightness_set = samsung_wmi_kbd_backlight_led_brightness_set,
>> > +};
>> > +
>> > +static int kb_default_brightness = -1;
>> > +module_param(kb_default_brightness, int, S_IRUGO);
>> > +MODULE_PARM_DESC(kb_default_brightness,
>> > +               "Default keyboard backlight brightness right after
>> > initialization");
>> > +
>> > +static int samsung_wmi_init(void) {
>> > +       int ret;
>> > +       // check whether method is present
>> > +       if (!wmi_has_guid(WMI_GUID))
>> > +               return -ENODEV;
>> > +       // we're good to go
>> > +       ret = platform_driver_register(&samsung_wmi_driver);
>> > +       if (ret) {
>> > +               goto err0;
>> > +       }
>> > +       samsung_wmi_device = platform_device_alloc(DRIVER_NAME, -1);
>> > +       if (!samsung_wmi_device) {
>> > +               ret = -ENOMEM;
>> > +               goto err1;
>> > +       }
>> > +       ret = platform_device_add(samsung_wmi_device);
>> > +       if (ret) {
>> > +               goto err2;
>> > +       }
>> > +       ret = device_create_file(&samsung_wmi_device->dev,
>> > &dev_attr_fan_mode);
>> > +       if (ret) {
>> > +               goto err3;
>> > +       }
>> > +       ret = led_classdev_register(&samsung_wmi_device->dev,
>> > +                       &samsung_wmi_kbd_backlight_led);
>> > +       if (ret) {
>> > +               goto err4;
>> > +       }
>> > +       if (kb_default_brightness >= 0) {
>> > +               led_set_brightness(&samsung_wmi_kbd_backlight_led,
>> > kb_default_brightness);
>> > +       }
>> > +       return 0;
>> > +//err5:
>> > +       led_classdev_unregister(&samsung_wmi_kbd_backlight_led);
>> > +err4:
>>
>> Instead of 'errX' please give a name related to what happen after the
>> label (or what failed just before)
>>
>> > +       device_remove_file(&samsung_wmi_device->dev,
>> > &dev_attr_fan_mode);
>> > +err3:
>> > +       platform_device_del(samsung_wmi_device);
>> > +err2:
>> > +       platform_device_put(samsung_wmi_device);
>> > +err1:
>> > +       platform_driver_unregister(&samsung_wmi_driver);
>> > +err0:
>> > +       return ret;
>> > +}
>> > +
>> > +static void samsung_wmi_exit(void) {
>> > +       led_classdev_unregister(&samsung_wmi_kbd_backlight_led);
>> > +       device_remove_file(&samsung_wmi_device->dev,
>> > &dev_attr_fan_mode);
>> > +       platform_device_unregister(samsung_wmi_device);
>> > +       platform_driver_unregister(&samsung_wmi_driver);
>> > +}
>> > +
>> > +MODULE_LICENSE("GPL");
>> > +MODULE_AUTHOR("Gavin Li");
>> > +MODULE_DESCRIPTION("WMI driver for some Samsung laptops.");
>> > +MODULE_ALIAS("wmi:" WMI_GUID);
>> > +module_init(samsung_wmi_init);
>> > +module_exit(samsung_wmi_exit);
>> > --
>> > 2.3.5
>> >
>> > --
>> > To unsubscribe from this list: send the line "unsubscribe
>> > platform-driver-x86" in
>> > the body of a message to majordomo@vger.kernel.org
>> > More majordomo info at  http://vger.kernel.org/majordomo-info.html
>>
>>
>>
>> --
>> Corentin Chary
>> http://xf.iksaif.net
>
>

      parent reply	other threads:[~2015-04-16 10:33 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-04-07 17:53 [PATCH] platform: add samsung-wmi driver for newer Samsung laptops gavinli
2015-04-13  6:01 ` Giedrius Statkevičius
2015-04-13  6:58   ` gavinli
2015-04-13  8:21   ` (unknown), gavinli
2015-04-13  8:21     ` [PATCH] platform: add samsung-wmi driver for newer Samsung laptops gavinli
2015-04-16  7:04 ` Corentin Chary
     [not found]   ` <CA+GxvY4t-DBeaYzzhWqV8OexikkYUdCaCwFc=z_1gjnj5bXUfg@mail.gmail.com>
2015-04-16 10:33     ` Gavin Li [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=CA+GxvY6VvimZO01aybweD5Qv_xcN+wrjoe-E-S1wN-2qC-Moig@mail.gmail.com \
    --to=gavinli@thegavinli.com \
    --cc=corentin.chary@gmail.com \
    --cc=git@thegavinli.com \
    --cc=platform-driver-x86@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.