The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/acpi_support/acpi_asus_wmi.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Copyright (c) 2012 Alexander Motin <mav@FreeBSD.org>
    3  * All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following disclaimer.
   10  * 2. Redistributions in binary form must reproduce the above copyright
   11  *    notice, this list of conditions and the following disclaimer in the
   12  *    documentation and/or other materials provided with the distribution.
   13  *
   14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   24  * SUCH DAMAGE.
   25  */
   26 
   27 #include <sys/cdefs.h>
   28 __FBSDID("$FreeBSD$");
   29 
   30 #include "opt_acpi.h"
   31 #include <sys/param.h>
   32 #include <sys/conf.h>
   33 #include <sys/uio.h>
   34 #include <sys/proc.h>
   35 #include <sys/kernel.h>
   36 #include <sys/bus.h>
   37 #include <sys/sbuf.h>
   38 #include <sys/module.h>
   39 #include <sys/sysctl.h>
   40 
   41 #include <contrib/dev/acpica/include/acpi.h>
   42 #include <contrib/dev/acpica/include/accommon.h>
   43 #include <dev/acpica/acpivar.h>
   44 #include "acpi_wmi_if.h"
   45 
   46 #define _COMPONENT      ACPI_OEM
   47 ACPI_MODULE_NAME("ASUS-WMI")
   48 
   49 #define ACPI_ASUS_WMI_MGMT_GUID         "97845ED0-4E6D-11DE-8A39-0800200C9A66"
   50 #define ACPI_ASUS_WMI_EVENT_GUID        "0B3CBB35-E3C2-45ED-91C2-4C5A6D195D1C"
   51 #define ACPI_EEEPC_WMI_EVENT_GUID       "ABBC0F72-8EA1-11D1-00A0-C90629100000"
   52 
   53 /* WMI Methods */
   54 #define ASUS_WMI_METHODID_SPEC          0x43455053
   55 #define ASUS_WMI_METHODID_SFUN          0x4E554653
   56 #define ASUS_WMI_METHODID_DSTS          0x53544344
   57 #define ASUS_WMI_METHODID_DSTS2         0x53545344
   58 #define ASUS_WMI_METHODID_DEVS          0x53564544
   59 #define ASUS_WMI_METHODID_INIT          0x54494E49
   60 #define ASUS_WMI_METHODID_HKEY          0x59454B48
   61 
   62 #define ASUS_WMI_UNSUPPORTED_METHOD     0xFFFFFFFE
   63 
   64 /* Wireless */
   65 #define ASUS_WMI_DEVID_HW_SWITCH        0x00010001
   66 #define ASUS_WMI_DEVID_WIRELESS_LED     0x00010002
   67 #define ASUS_WMI_DEVID_CWAP             0x00010003
   68 #define ASUS_WMI_DEVID_WLAN             0x00010011
   69 #define ASUS_WMI_DEVID_BLUETOOTH        0x00010013
   70 #define ASUS_WMI_DEVID_GPS              0x00010015
   71 #define ASUS_WMI_DEVID_WIMAX            0x00010017
   72 #define ASUS_WMI_DEVID_WWAN3G           0x00010019
   73 #define ASUS_WMI_DEVID_UWB              0x00010021
   74 
   75 /* LEDs */
   76 #define ASUS_WMI_DEVID_LED1             0x00020011
   77 #define ASUS_WMI_DEVID_LED2             0x00020012
   78 #define ASUS_WMI_DEVID_LED3             0x00020013
   79 #define ASUS_WMI_DEVID_LED4             0x00020014
   80 #define ASUS_WMI_DEVID_LED5             0x00020015
   81 #define ASUS_WMI_DEVID_LED6             0x00020016
   82 
   83 /* Backlight and Brightness */
   84 #define ASUS_WMI_DEVID_BACKLIGHT        0x00050011
   85 #define ASUS_WMI_DEVID_BRIGHTNESS       0x00050012
   86 #define ASUS_WMI_DEVID_KBD_BACKLIGHT    0x00050021
   87 #define ASUS_WMI_DEVID_LIGHT_SENSOR     0x00050022
   88 
   89 /* Misc */
   90 #define ASUS_WMI_DEVID_CAMERA           0x00060013
   91 #define ASUS_WMI_DEVID_CARDREADER       0x00080013
   92 #define ASUS_WMI_DEVID_TOUCHPAD         0x00100011
   93 #define ASUS_WMI_DEVID_TOUCHPAD_LED     0x00100012
   94 #define ASUS_WMI_DEVID_THERMAL_CTRL     0x00110011
   95 #define ASUS_WMI_DEVID_FAN_CTRL         0x00110012
   96 #define ASUS_WMI_DEVID_PROCESSOR_STATE  0x00120012
   97 
   98 /* DSTS masks */
   99 #define ASUS_WMI_DSTS_STATUS_BIT        0x00000001
  100 #define ASUS_WMI_DSTS_UNKNOWN_BIT       0x00000002
  101 #define ASUS_WMI_DSTS_PRESENCE_BIT      0x00010000
  102 #define ASUS_WMI_DSTS_USER_BIT          0x00020000
  103 #define ASUS_WMI_DSTS_BIOS_BIT          0x00040000
  104 #define ASUS_WMI_DSTS_BRIGHTNESS_MASK   0x000000FF
  105 #define ASUS_WMI_DSTS_MAX_BRIGTH_MASK   0x0000FF00
  106 
  107 struct acpi_asus_wmi_softc {
  108         device_t        dev;
  109         device_t        wmi_dev;
  110         const char      *notify_guid;
  111         struct sysctl_ctx_list  *sysctl_ctx;
  112         struct sysctl_oid       *sysctl_tree;
  113         int             dsts_id;
  114         int             handle_keys;
  115 };
  116 
  117 static struct {
  118         char    *name;
  119         int     dev_id;
  120         char    *description;
  121         int     flag_rdonly;
  122 } acpi_asus_wmi_sysctls[] = {
  123         {
  124                 .name           = "hw_switch",
  125                 .dev_id         = ASUS_WMI_DEVID_HW_SWITCH,
  126                 .description    = "hw_switch",
  127         },
  128         {
  129                 .name           = "wireless_led",
  130                 .dev_id         = ASUS_WMI_DEVID_WIRELESS_LED,
  131                 .description    = "Wireless LED control",
  132         },
  133         {
  134                 .name           = "cwap",
  135                 .dev_id         = ASUS_WMI_DEVID_CWAP,
  136                 .description    = "Alt+F2 function",
  137         },
  138         {
  139                 .name           = "wlan",
  140                 .dev_id         = ASUS_WMI_DEVID_WLAN,
  141                 .description    = "WLAN power control",
  142         },
  143         {
  144                 .name           = "bluetooth",
  145                 .dev_id         = ASUS_WMI_DEVID_BLUETOOTH,
  146                 .description    = "Bluetooth power control",
  147         },
  148         {
  149                 .name           = "gps",
  150                 .dev_id         = ASUS_WMI_DEVID_GPS,
  151                 .description    = "GPS power control",
  152         },
  153         {
  154                 .name           = "wimax",
  155                 .dev_id         = ASUS_WMI_DEVID_WIMAX,
  156                 .description    = "WiMAX power control",
  157         },
  158         {
  159                 .name           = "wwan3g",
  160                 .dev_id         = ASUS_WMI_DEVID_WWAN3G,
  161                 .description    = "WWAN-3G power control",
  162         },
  163         {
  164                 .name           = "uwb",
  165                 .dev_id         = ASUS_WMI_DEVID_UWB,
  166                 .description    = "UWB power control",
  167         },
  168         {
  169                 .name           = "led1",
  170                 .dev_id         = ASUS_WMI_DEVID_LED1,
  171                 .description    = "LED1 control",
  172         },
  173         {
  174                 .name           = "led2",
  175                 .dev_id         = ASUS_WMI_DEVID_LED2,
  176                 .description    = "LED2 control",
  177         },
  178         {
  179                 .name           = "led3",
  180                 .dev_id         = ASUS_WMI_DEVID_LED3,
  181                 .description    = "LED3 control",
  182         },
  183         {
  184                 .name           = "led4",
  185                 .dev_id         = ASUS_WMI_DEVID_LED4,
  186                 .description    = "LED4 control",
  187         },
  188         {
  189                 .name           = "led5",
  190                 .dev_id         = ASUS_WMI_DEVID_LED5,
  191                 .description    = "LED5 control",
  192         },
  193         {
  194                 .name           = "led6",
  195                 .dev_id         = ASUS_WMI_DEVID_LED6,
  196                 .description    = "LED6 control",
  197         },
  198         {
  199                 .name           = "backlight",
  200                 .dev_id         = ASUS_WMI_DEVID_BACKLIGHT,
  201                 .description    = "LCD backlight on/off control",
  202         },
  203         {
  204                 .name           = "brightness",
  205                 .dev_id         = ASUS_WMI_DEVID_BRIGHTNESS,
  206                 .description    = "LCD backlight brightness control",
  207         },
  208         {
  209                 .name           = "kbd_backlight",
  210                 .dev_id         = ASUS_WMI_DEVID_KBD_BACKLIGHT,
  211                 .description    = "Keyboard backlight brightness control",
  212         },
  213         {
  214                 .name           = "light_sensor",
  215                 .dev_id         = ASUS_WMI_DEVID_LIGHT_SENSOR,
  216                 .description    = "Ambient light sensor",
  217         },
  218         {
  219                 .name           = "camera",
  220                 .dev_id         = ASUS_WMI_DEVID_CAMERA,
  221                 .description    = "Camera power control",
  222         },
  223         {
  224                 .name           = "cardreader",
  225                 .dev_id         = ASUS_WMI_DEVID_CARDREADER,
  226                 .description    = "Cardreader power control",
  227         },
  228         {
  229                 .name           = "touchpad",
  230                 .dev_id         = ASUS_WMI_DEVID_TOUCHPAD,
  231                 .description    = "Touchpad control",
  232         },
  233         {
  234                 .name           = "touchpad_led",
  235                 .dev_id         = ASUS_WMI_DEVID_TOUCHPAD_LED,
  236                 .description    = "Touchpad LED control",
  237         },
  238         {
  239                 .name           = "themperature",
  240                 .dev_id         = ASUS_WMI_DEVID_THERMAL_CTRL,
  241                 .description    = "Temperature (C)",
  242                 .flag_rdonly    = 1
  243         },
  244         {
  245                 .name           = "fan_speed",
  246                 .dev_id         = ASUS_WMI_DEVID_FAN_CTRL,
  247                 .description    = "Fan speed (0-3)",
  248                 .flag_rdonly    = 1
  249         },
  250         {
  251                 .name           = "processor_state",
  252                 .dev_id         = ASUS_WMI_DEVID_PROCESSOR_STATE,
  253                 .flag_rdonly    = 1
  254         },
  255         { NULL, 0, NULL, 0 }
  256 };
  257 
  258 ACPI_SERIAL_DECL(asus_wmi, "ASUS WMI device");
  259 
  260 static void     acpi_asus_wmi_identify(driver_t *driver, device_t parent);
  261 static int      acpi_asus_wmi_probe(device_t dev);
  262 static int      acpi_asus_wmi_attach(device_t dev);
  263 static int      acpi_asus_wmi_detach(device_t dev);
  264 
  265 static int      acpi_asus_wmi_sysctl(SYSCTL_HANDLER_ARGS);
  266 static int      acpi_asus_wmi_sysctl_set(struct acpi_asus_wmi_softc *sc, int dev_id,
  267                     int arg, int oldarg);
  268 static int      acpi_asus_wmi_sysctl_get(struct acpi_asus_wmi_softc *sc, int dev_id);
  269 static int      acpi_asus_wmi_evaluate_method(device_t wmi_dev, int method,
  270                     UINT32 arg0, UINT32 arg1, UINT32 *retval);
  271 static int      acpi_wpi_asus_get_devstate(struct acpi_asus_wmi_softc *sc,
  272                     UINT32 dev_id, UINT32 *retval);
  273 static int      acpi_wpi_asus_set_devstate(struct acpi_asus_wmi_softc *sc,
  274                     UINT32 dev_id, UINT32 ctrl_param, UINT32 *retval);
  275 static void     acpi_asus_wmi_notify(ACPI_HANDLE h, UINT32 notify, void *context);
  276 
  277 static device_method_t acpi_asus_wmi_methods[] = {
  278         DEVMETHOD(device_identify, acpi_asus_wmi_identify),
  279         DEVMETHOD(device_probe, acpi_asus_wmi_probe),
  280         DEVMETHOD(device_attach, acpi_asus_wmi_attach),
  281         DEVMETHOD(device_detach, acpi_asus_wmi_detach),
  282 
  283         DEVMETHOD_END
  284 };
  285 
  286 static driver_t acpi_asus_wmi_driver = {
  287         "acpi_asus_wmi",
  288         acpi_asus_wmi_methods,
  289         sizeof(struct acpi_asus_wmi_softc),
  290 };
  291 
  292 DRIVER_MODULE(acpi_asus_wmi, acpi_wmi, acpi_asus_wmi_driver, 0, 0);
  293 MODULE_DEPEND(acpi_asus_wmi, acpi_wmi, 1, 1, 1);
  294 MODULE_DEPEND(acpi_asus_wmi, acpi, 1, 1, 1);
  295 
  296 static void
  297 acpi_asus_wmi_identify(driver_t *driver, device_t parent)
  298 {
  299 
  300         /* Don't do anything if driver is disabled. */
  301         if (acpi_disabled("asus_wmi"))
  302                 return;
  303 
  304         /* Add only a single device instance. */
  305         if (device_find_child(parent, "acpi_asus_wmi", -1) != NULL)
  306                 return;
  307 
  308         /* Check management GUID to see whether system is compatible. */
  309         if (!ACPI_WMI_PROVIDES_GUID_STRING(parent,
  310             ACPI_ASUS_WMI_MGMT_GUID))
  311                 return;
  312 
  313         if (BUS_ADD_CHILD(parent, 0, "acpi_asus_wmi", -1) == NULL)
  314                 device_printf(parent, "add acpi_asus_wmi child failed\n");
  315 }
  316 
  317 static int
  318 acpi_asus_wmi_probe(device_t dev)
  319 {
  320 
  321         if (!ACPI_WMI_PROVIDES_GUID_STRING(device_get_parent(dev),
  322             ACPI_ASUS_WMI_MGMT_GUID))
  323                 return (EINVAL);
  324         device_set_desc(dev, "ASUS WMI device");
  325         return (0);
  326 }
  327 
  328 static int
  329 acpi_asus_wmi_attach(device_t dev)
  330 {
  331         struct acpi_asus_wmi_softc      *sc;
  332         UINT32                  val;
  333         int                     dev_id, i;
  334 
  335         ACPI_FUNCTION_TRACE((char *)(uintptr_t) __func__);
  336 
  337         sc = device_get_softc(dev);
  338         sc->dev = dev;
  339         sc->wmi_dev = device_get_parent(dev);
  340         sc->handle_keys = 1;
  341 
  342         /* Check management GUID. */
  343         if (!ACPI_WMI_PROVIDES_GUID_STRING(sc->wmi_dev,
  344             ACPI_ASUS_WMI_MGMT_GUID)) {
  345                 device_printf(dev,
  346                     "WMI device does not provide the ASUS management GUID\n");
  347                 return (EINVAL);
  348         }
  349 
  350         /* Find proper DSTS method. */
  351         sc->dsts_id = ASUS_WMI_METHODID_DSTS;
  352 next:
  353         for (i = 0; acpi_asus_wmi_sysctls[i].name != NULL; ++i) {
  354                 dev_id = acpi_asus_wmi_sysctls[i].dev_id;
  355                 if (acpi_wpi_asus_get_devstate(sc, dev_id, &val))
  356                         continue;
  357                 break;
  358         }
  359         if (acpi_asus_wmi_sysctls[i].name == NULL) {
  360                 if (sc->dsts_id == ASUS_WMI_METHODID_DSTS) {
  361                         sc->dsts_id = ASUS_WMI_METHODID_DSTS2;
  362                         goto next;
  363                 } else {
  364                         device_printf(dev, "Can not detect DSTS method ID\n");
  365                         return (EINVAL);
  366                 }
  367         }
  368 
  369         /* Find proper and attach to notufy GUID. */
  370         if (ACPI_WMI_PROVIDES_GUID_STRING(sc->wmi_dev,
  371             ACPI_ASUS_WMI_EVENT_GUID))
  372                 sc->notify_guid = ACPI_ASUS_WMI_EVENT_GUID;
  373         else if (ACPI_WMI_PROVIDES_GUID_STRING(sc->wmi_dev,
  374             ACPI_EEEPC_WMI_EVENT_GUID))
  375                 sc->notify_guid = ACPI_EEEPC_WMI_EVENT_GUID;
  376         else
  377                 sc->notify_guid = NULL;
  378         if (sc->notify_guid != NULL) {
  379                 if (ACPI_WMI_INSTALL_EVENT_HANDLER(sc->wmi_dev,
  380                     sc->notify_guid, acpi_asus_wmi_notify, dev))
  381                         sc->notify_guid = NULL;
  382         }
  383         if (sc->notify_guid == NULL)
  384                 device_printf(dev, "Could not install event handler!\n");
  385 
  386         /* Initialize. */
  387         if (!acpi_asus_wmi_evaluate_method(sc->wmi_dev,
  388             ASUS_WMI_METHODID_INIT, 0, 0, &val) && bootverbose)
  389                 device_printf(dev, "Initialization: %#x\n", val);
  390         if (!acpi_asus_wmi_evaluate_method(sc->wmi_dev,
  391             ASUS_WMI_METHODID_SPEC, 0, 0x9, &val) && bootverbose)
  392                 device_printf(dev, "WMI BIOS version: %d.%d\n",
  393                     val >> 16, val & 0xFF);
  394         if (!acpi_asus_wmi_evaluate_method(sc->wmi_dev,
  395             ASUS_WMI_METHODID_SFUN, 0, 0, &val) && bootverbose)
  396                 device_printf(dev, "SFUN value: %#x\n", val);
  397 
  398         ACPI_SERIAL_BEGIN(asus_wmi);
  399 
  400         sc->sysctl_ctx = device_get_sysctl_ctx(dev);
  401         sc->sysctl_tree = device_get_sysctl_tree(dev);
  402         SYSCTL_ADD_INT(sc->sysctl_ctx,
  403             SYSCTL_CHILDREN(sc->sysctl_tree), OID_AUTO,
  404             "handle_keys", CTLFLAG_RW, &sc->handle_keys,
  405             0, "Handle some hardware keys inside the driver");
  406         for (i = 0; acpi_asus_wmi_sysctls[i].name != NULL; ++i) {
  407                 dev_id = acpi_asus_wmi_sysctls[i].dev_id;
  408                 if (acpi_wpi_asus_get_devstate(sc, dev_id, &val))
  409                         continue;
  410                 switch (dev_id) {
  411                 case ASUS_WMI_DEVID_THERMAL_CTRL:
  412                 case ASUS_WMI_DEVID_PROCESSOR_STATE:
  413                 case ASUS_WMI_DEVID_FAN_CTRL:
  414                 case ASUS_WMI_DEVID_BRIGHTNESS:
  415                         if (val == 0)
  416                                 continue;
  417                         break;
  418                 default:
  419                         if ((val & ASUS_WMI_DSTS_PRESENCE_BIT) == 0)
  420                                 continue;
  421                         break;
  422                 }
  423 
  424                 if (acpi_asus_wmi_sysctls[i].flag_rdonly != 0) {
  425                         SYSCTL_ADD_PROC(sc->sysctl_ctx,
  426                             SYSCTL_CHILDREN(sc->sysctl_tree), OID_AUTO,
  427                             acpi_asus_wmi_sysctls[i].name,
  428                             CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE,
  429                             sc, i, acpi_asus_wmi_sysctl, "I",
  430                             acpi_asus_wmi_sysctls[i].description);
  431                 } else {
  432                         SYSCTL_ADD_PROC(sc->sysctl_ctx,
  433                             SYSCTL_CHILDREN(sc->sysctl_tree), OID_AUTO,
  434                             acpi_asus_wmi_sysctls[i].name,
  435                             CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE,
  436                             sc, i, acpi_asus_wmi_sysctl, "I",
  437                             acpi_asus_wmi_sysctls[i].description);
  438                 }
  439         }
  440         ACPI_SERIAL_END(asus_wmi);
  441 
  442         return (0);
  443 }
  444 
  445 static int
  446 acpi_asus_wmi_detach(device_t dev)
  447 {
  448         struct acpi_asus_wmi_softc *sc = device_get_softc(dev);
  449 
  450         ACPI_FUNCTION_TRACE((char *)(uintptr_t) __func__);
  451 
  452         if (sc->notify_guid)
  453                 ACPI_WMI_REMOVE_EVENT_HANDLER(dev, sc->notify_guid);
  454 
  455         return (0);
  456 }
  457 
  458 static int
  459 acpi_asus_wmi_sysctl(SYSCTL_HANDLER_ARGS)
  460 {
  461         struct acpi_asus_wmi_softc      *sc;
  462         int                     arg;
  463         int                     oldarg;
  464         int                     error = 0;
  465         int                     function;
  466         int                     dev_id;
  467 
  468         ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
  469 
  470         sc = (struct acpi_asus_wmi_softc *)oidp->oid_arg1;
  471         function = oidp->oid_arg2;
  472         dev_id = acpi_asus_wmi_sysctls[function].dev_id;
  473 
  474         ACPI_SERIAL_BEGIN(asus_wmi);
  475         arg = acpi_asus_wmi_sysctl_get(sc, dev_id);
  476         oldarg = arg;
  477         error = sysctl_handle_int(oidp, &arg, 0, req);
  478         if (!error && req->newptr != NULL)
  479                 error = acpi_asus_wmi_sysctl_set(sc, dev_id, arg, oldarg);
  480         ACPI_SERIAL_END(asus_wmi);
  481 
  482         return (error);
  483 }
  484 
  485 static int
  486 acpi_asus_wmi_sysctl_get(struct acpi_asus_wmi_softc *sc, int dev_id)
  487 {
  488         UINT32  val = 0;
  489 
  490         ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
  491         ACPI_SERIAL_ASSERT(asus_wmi);
  492 
  493         acpi_wpi_asus_get_devstate(sc, dev_id, &val);
  494 
  495         switch(dev_id) {
  496         case ASUS_WMI_DEVID_THERMAL_CTRL:
  497                 val = (val - 2731 + 5) / 10;
  498                 break;
  499         case ASUS_WMI_DEVID_PROCESSOR_STATE:
  500         case ASUS_WMI_DEVID_FAN_CTRL:
  501                 break;
  502         case ASUS_WMI_DEVID_BRIGHTNESS:
  503                 val &= ASUS_WMI_DSTS_BRIGHTNESS_MASK;
  504                 break;
  505         case ASUS_WMI_DEVID_KBD_BACKLIGHT:
  506                 val &= 0x7;
  507                 break;
  508         default:
  509                 if (val & ASUS_WMI_DSTS_UNKNOWN_BIT)
  510                         val = -1;
  511                 else
  512                         val = !!(val & ASUS_WMI_DSTS_STATUS_BIT);
  513                 break;
  514         }
  515 
  516         return (val);
  517 }
  518 
  519 static int
  520 acpi_asus_wmi_sysctl_set(struct acpi_asus_wmi_softc *sc, int dev_id, int arg, int oldarg)
  521 {
  522         ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
  523         ACPI_SERIAL_ASSERT(asus_wmi);
  524 
  525         switch(dev_id) {
  526         case ASUS_WMI_DEVID_KBD_BACKLIGHT:
  527                 arg = min(0x7, arg);
  528                 if (arg != 0)
  529                         arg |= 0x80;
  530                 break;
  531         }
  532 
  533         acpi_wpi_asus_set_devstate(sc, dev_id, arg, NULL);
  534 
  535         return (0);
  536 }
  537 
  538 static __inline void
  539 acpi_asus_wmi_free_buffer(ACPI_BUFFER* buf) {
  540         if (buf && buf->Pointer) {
  541                 AcpiOsFree(buf->Pointer);
  542         }
  543 }
  544 
  545 static void
  546 acpi_asus_wmi_notify(ACPI_HANDLE h, UINT32 notify, void *context)
  547 {
  548         device_t dev = context;
  549         ACPI_FUNCTION_TRACE_U32((char *)(uintptr_t)__func__, notify);
  550         UINT32 val;
  551         int code = 0;
  552 
  553         struct acpi_asus_wmi_softc *sc = device_get_softc(dev);
  554         ACPI_BUFFER response = { ACPI_ALLOCATE_BUFFER, NULL };
  555         ACPI_OBJECT *obj;
  556         ACPI_WMI_GET_EVENT_DATA(sc->wmi_dev, notify, &response);
  557         obj = (ACPI_OBJECT*) response.Pointer;
  558         if (obj && obj->Type == ACPI_TYPE_INTEGER) {
  559                 code = obj->Integer.Value;
  560                 acpi_UserNotify("ASUS", ACPI_ROOT_OBJECT,
  561                     code);
  562         }
  563         if (code && sc->handle_keys) {
  564                 /* Keyboard backlight control. */
  565                 if (code == 0xc4 || code == 0xc5) {
  566                         acpi_wpi_asus_get_devstate(sc,
  567                             ASUS_WMI_DEVID_KBD_BACKLIGHT, &val);
  568                         val &= 0x7;
  569                         if (code == 0xc4) {
  570                                 if (val < 0x7)
  571                                         val++;
  572                         } else if (val > 0)
  573                                 val--;
  574                         if (val != 0)
  575                                 val |= 0x80;
  576                         acpi_wpi_asus_set_devstate(sc,
  577                             ASUS_WMI_DEVID_KBD_BACKLIGHT, val, NULL);
  578                 }
  579                 /* Touchpad control. */
  580                 if (code == 0x6b) {
  581                         acpi_wpi_asus_get_devstate(sc,
  582                             ASUS_WMI_DEVID_TOUCHPAD, &val);
  583                         val = !(val & 1);
  584                         acpi_wpi_asus_set_devstate(sc,
  585                             ASUS_WMI_DEVID_TOUCHPAD, val, NULL);
  586                 }
  587         }
  588         acpi_asus_wmi_free_buffer(&response);
  589 }
  590 
  591 static int
  592 acpi_asus_wmi_evaluate_method(device_t wmi_dev, int method,
  593     UINT32 arg0, UINT32 arg1, UINT32 *retval)
  594 {
  595         UINT32          params[2] = { arg0, arg1 };
  596         UINT32          result;
  597         ACPI_OBJECT     *obj;
  598         ACPI_BUFFER     in = { sizeof(params), &params };
  599         ACPI_BUFFER     out = { ACPI_ALLOCATE_BUFFER, NULL };
  600 
  601         if (ACPI_FAILURE(ACPI_WMI_EVALUATE_CALL(wmi_dev,
  602             ACPI_ASUS_WMI_MGMT_GUID, 1, method, &in, &out))) {
  603                 acpi_asus_wmi_free_buffer(&out);
  604                 return (-EINVAL);
  605         }
  606         obj = out.Pointer;
  607         if (obj && obj->Type == ACPI_TYPE_INTEGER)
  608                 result = (UINT32) obj->Integer.Value;
  609         else
  610                 result = 0;
  611         acpi_asus_wmi_free_buffer(&out);
  612         if (retval)
  613                 *retval = result;
  614         return (result == ASUS_WMI_UNSUPPORTED_METHOD ? -ENODEV : 0);
  615 }
  616 
  617 static int
  618 acpi_wpi_asus_get_devstate(struct acpi_asus_wmi_softc *sc,
  619     UINT32 dev_id, UINT32 *retval)
  620 {
  621 
  622         return (acpi_asus_wmi_evaluate_method(sc->wmi_dev,
  623             sc->dsts_id, dev_id, 0, retval));
  624 }
  625 
  626 static int
  627 acpi_wpi_asus_set_devstate(struct acpi_asus_wmi_softc *sc,
  628     UINT32 dev_id, UINT32 ctrl_param, UINT32 *retval)
  629 {
  630 
  631         return (acpi_asus_wmi_evaluate_method(sc->wmi_dev,
  632             ASUS_WMI_METHODID_DEVS, dev_id, ctrl_param, retval));
  633 }

Cache object: e79f54c2823b72d28780a76ef8f8d70b


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.