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.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) 2004, 2005 Philip Paeps <philip@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: releng/8.4/sys/dev/acpi_support/acpi_asus.c 193530 2009-06-05 18:44:36Z jkim $");
   29 
   30 /*
   31  * Driver for extra ACPI-controlled gadgets (hotkeys, leds, etc) found on
   32  * recent Asus (and Medion) laptops.  Inspired by the acpi4asus project which
   33  * implements these features in the Linux kernel.
   34  *
   35  *   <http://sourceforge.net/projects/acpi4asus/>
   36  *
   37  * Currently should support most features, but could use some more testing.
   38  * Particularly the display-switching stuff is a bit hairy.  If you have an
   39  * Asus laptop which doesn't appear to be supported, or strange things happen
   40  * when using this driver, please report to <acpi@FreeBSD.org>.
   41  */
   42 
   43 #include "opt_acpi.h"
   44 #include <sys/param.h>
   45 #include <sys/kernel.h>
   46 #include <sys/module.h>
   47 #include <sys/bus.h>
   48 #include <sys/sbuf.h>
   49 
   50 #include <contrib/dev/acpica/include/acpi.h>
   51 #include <contrib/dev/acpica/include/accommon.h>
   52 
   53 #include <dev/acpica/acpivar.h>
   54 #include <dev/led/led.h>
   55 
   56 /* Methods */
   57 #define ACPI_ASUS_METHOD_BRN    1
   58 #define ACPI_ASUS_METHOD_DISP   2
   59 #define ACPI_ASUS_METHOD_LCD    3
   60 #define ACPI_ASUS_METHOD_CAMERA 4
   61 #define ACPI_ASUS_METHOD_CARDRD 5
   62 #define ACPI_ASUS_METHOD_WLAN   6
   63 
   64 #define _COMPONENT      ACPI_OEM
   65 ACPI_MODULE_NAME("ASUS")
   66 
   67 struct acpi_asus_model {
   68         char    *name;
   69 
   70         char    *bled_set;
   71         char    *dled_set;
   72         char    *gled_set;
   73         char    *mled_set;
   74         char    *tled_set;
   75         char    *wled_set;
   76 
   77         char    *brn_get;
   78         char    *brn_set;
   79         char    *brn_up;
   80         char    *brn_dn;
   81 
   82         char    *lcd_get;
   83         char    *lcd_set;
   84 
   85         char    *disp_get;
   86         char    *disp_set;
   87 
   88         char    *cam_get;
   89         char    *cam_set;
   90 
   91         char    *crd_get;
   92         char    *crd_set;
   93 
   94         char    *wlan_get;
   95         char    *wlan_set;
   96 
   97         void    (*n_func)(ACPI_HANDLE, UINT32, void *);
   98 
   99         char    *lcdd;
  100         void    (*lcdd_n_func)(ACPI_HANDLE, UINT32, void *);
  101 };
  102 
  103 struct acpi_asus_led {
  104         struct acpi_asus_softc *sc;
  105         struct cdev     *cdev;
  106         int             busy;
  107         int             state;
  108         enum {
  109                 ACPI_ASUS_LED_BLED,
  110                 ACPI_ASUS_LED_DLED,
  111                 ACPI_ASUS_LED_GLED,
  112                 ACPI_ASUS_LED_MLED,
  113                 ACPI_ASUS_LED_TLED,
  114                 ACPI_ASUS_LED_WLED,
  115         } type;
  116 };
  117 
  118 struct acpi_asus_softc {
  119         device_t                dev;
  120         ACPI_HANDLE             handle;
  121         ACPI_HANDLE             lcdd_handle;
  122 
  123         struct acpi_asus_model  *model;
  124         struct sysctl_ctx_list  sysctl_ctx;
  125         struct sysctl_oid       *sysctl_tree;
  126 
  127         struct acpi_asus_led    s_bled;
  128         struct acpi_asus_led    s_dled;
  129         struct acpi_asus_led    s_gled;
  130         struct acpi_asus_led    s_mled;
  131         struct acpi_asus_led    s_tled;
  132         struct acpi_asus_led    s_wled;
  133 
  134         int                     s_brn;
  135         int                     s_disp;
  136         int                     s_lcd;
  137         int                     s_cam;
  138         int                     s_crd;
  139         int                     s_wlan;
  140 };
  141 
  142 static void     acpi_asus_lcdd_notify(ACPI_HANDLE h, UINT32 notify,
  143     void *context);
  144 
  145 /*
  146  * We can identify Asus laptops from the string they return
  147  * as a result of calling the ATK0100 'INIT' method.
  148  */
  149 static struct acpi_asus_model acpi_asus_models[] = {
  150         {
  151                 .name           = "xxN",
  152                 .mled_set       = "MLED",
  153                 .wled_set       = "WLED",
  154                 .lcd_get        = "\\BKLT",
  155                 .lcd_set        = "\\_SB.PCI0.SBRG.EC0._Q10",
  156                 .brn_get        = "GPLV",
  157                 .brn_set        = "SPLV",
  158                 .disp_get       = "\\ADVG",
  159                 .disp_set       = "SDSP"
  160         },
  161         {
  162                 .name           = "A1x",
  163                 .mled_set       = "MLED",
  164                 .lcd_get        = "\\BKLI",
  165                 .lcd_set        = "\\_SB.PCI0.ISA.EC0._Q10",
  166                 .brn_up         = "\\_SB.PCI0.ISA.EC0._Q0E",
  167                 .brn_dn         = "\\_SB.PCI0.ISA.EC0._Q0F"
  168         },
  169         {
  170                 .name           = "A2x",
  171                 .mled_set       = "MLED",
  172                 .wled_set       = "WLED",
  173                 .lcd_get        = "\\BAOF",
  174                 .lcd_set        = "\\Q10",
  175                 .brn_get        = "GPLV",
  176                 .brn_set        = "SPLV",
  177                 .disp_get       = "\\INFB",
  178                 .disp_set       = "SDSP"
  179         },
  180         {
  181                 .name           = "A3E",
  182                 .mled_set       = "MLED",
  183                 .wled_set       = "WLED",
  184                 .lcd_get        = "\\_SB.PCI0.SBRG.EC0.RPIN(0x67)",
  185                 .lcd_set        = "\\_SB.PCI0.SBRG.EC0._Q10",
  186                 .brn_get        = "GPLV",
  187                 .brn_set        = "SPLV",
  188                 .disp_get       = "\\_SB.PCI0.P0P2.VGA.GETD",
  189                 .disp_set       = "SDSP"
  190         },
  191         {
  192                 .name           = "A3F",
  193                 .mled_set       = "MLED",
  194                 .wled_set       = "WLED",
  195                 .bled_set       = "BLED",
  196                 .lcd_get        = "\\_SB.PCI0.SBRG.EC0.RPIN(0x11)",
  197                 .lcd_set        = "\\_SB.PCI0.SBRG.EC0._Q10",
  198                 .brn_get        = "GPLV",
  199                 .brn_set        = "SPLV",
  200                 .disp_get       = "\\SSTE",
  201                 .disp_set       = "SDSP"
  202         },
  203         {
  204                 .name           = "A3N",
  205                 .mled_set       = "MLED",
  206                 .bled_set       = "BLED",
  207                 .wled_set       = "WLED",
  208                 .lcd_get        = "\\BKLT",
  209                 .lcd_set        = "\\_SB.PCI0.SBRG.EC0._Q10",
  210                 .brn_get        = "GPLV",
  211                 .brn_set        = "SPLV",
  212                 .disp_get       = "\\_SB.PCI0.P0P3.VGA.GETD",
  213                 .disp_set       = "SDSP"
  214         },
  215         {
  216                 .name           = "A4D",
  217                 .mled_set       = "MLED",
  218                 .brn_up         = "\\_SB_.PCI0.SBRG.EC0._Q0E",
  219                 .brn_dn         = "\\_SB_.PCI0.SBRG.EC0._Q0F",
  220                 .brn_get        = "GPLV",
  221                 .brn_set        = "SPLV",
  222 #ifdef notyet
  223                 .disp_get       = "\\_SB_.PCI0.SBRG.EC0._Q10",
  224                 .disp_set       = "\\_SB_.PCI0.SBRG.EC0._Q11"
  225 #endif
  226         },
  227         {
  228                 .name           = "A6V",
  229                 .bled_set       = "BLED",
  230                 .mled_set       = "MLED",
  231                 .wled_set       = "WLED",
  232                 .lcd_get        = NULL,
  233                 .lcd_set        = "\\_SB.PCI0.SBRG.EC0._Q10",
  234                 .brn_get        = "GPLV",
  235                 .brn_set        = "SPLV",
  236                 .disp_get       = "\\_SB.PCI0.P0P3.VGA.GETD",
  237                 .disp_set       = "SDSP"
  238         },
  239         {
  240                 .name           = "A8SR",
  241                 .bled_set       = "BLED",
  242                 .mled_set       = "MLED",
  243                 .wled_set       = "WLED",
  244                 .lcd_get        = NULL,
  245                 .lcd_set        = "\\_SB.PCI0.SBRG.EC0._Q10",
  246                 .brn_get        = "GPLV",
  247                 .brn_set        = "SPLV",
  248                 .disp_get       = "\\_SB.PCI0.P0P1.VGA.GETD",
  249                 .disp_set       = "SDSP",
  250                 .lcdd           = "\\_SB.PCI0.P0P1.VGA.LCDD",
  251                 .lcdd_n_func    = acpi_asus_lcdd_notify
  252         },
  253         {
  254                 .name           = "D1x",
  255                 .mled_set       = "MLED",
  256                 .lcd_get        = "\\GP11",
  257                 .lcd_set        = "\\Q0D",
  258                 .brn_up         = "\\Q0C",
  259                 .brn_dn         = "\\Q0B",
  260                 .disp_get       = "\\INFB",
  261                 .disp_set       = "SDSP"
  262         },
  263         {
  264                 .name           = "G2K",
  265                 .bled_set       = "BLED",
  266                 .dled_set       = "DLED",
  267                 .gled_set       = "GLED",
  268                 .mled_set       = "MLED",
  269                 .tled_set       = "TLED",
  270                 .wled_set       = "WLED",
  271                 .brn_get        = "GPLV",
  272                 .brn_set        = "SPLV",
  273                 .lcd_get        = "\\_SB.PCI0.SBRG.EC0.RPIN",
  274                 .lcd_set        = "\\_SB.PCI0.SBRG.EC0._Q10",
  275                 .disp_get       = "\\_SB.PCI0.PCE2.VGA.GETD",
  276                 .disp_set       = "SDSP",
  277         },
  278         {
  279                 .name           = "L2D",
  280                 .mled_set       = "MLED",
  281                 .wled_set       = "WLED",
  282                 .brn_up         = "\\Q0E",
  283                 .brn_dn         = "\\Q0F",
  284                 .lcd_get        = "\\SGP0",
  285                 .lcd_set        = "\\Q10"
  286         },
  287         {
  288                 .name           = "L3C",
  289                 .mled_set       = "MLED",
  290                 .wled_set       = "WLED",
  291                 .brn_get        = "GPLV",
  292                 .brn_set        = "SPLV",
  293                 .lcd_get        = "\\GL32",
  294                 .lcd_set        = "\\_SB.PCI0.PX40.ECD0._Q10"
  295         },
  296         {
  297                 .name           = "L3D",
  298                 .mled_set       = "MLED",
  299                 .wled_set       = "WLED",
  300                 .brn_get        = "GPLV",
  301                 .brn_set        = "SPLV",
  302                 .lcd_get        = "\\BKLG",
  303                 .lcd_set        = "\\Q10"
  304         },
  305         {
  306                 .name           = "L3H",
  307                 .mled_set       = "MLED",
  308                 .wled_set       = "WLED",
  309                 .brn_get        = "GPLV",
  310                 .brn_set        = "SPLV",
  311                 .lcd_get        = "\\_SB.PCI0.PM.PBC",
  312                 .lcd_set        = "EHK",
  313                 .disp_get       = "\\_SB.INFB",
  314                 .disp_set       = "SDSP"
  315         },
  316         {
  317                 .name           = "L4R",
  318                 .mled_set       = "MLED",
  319                 .wled_set       = "WLED",
  320                 .brn_get        = "GPLV",
  321                 .brn_set        = "SPLV",
  322                 .lcd_get        = "\\_SB.PCI0.SBSM.SEO4",
  323                 .lcd_set        = "\\_SB.PCI0.SBRG.EC0._Q10",
  324                 .disp_get       = "\\_SB.PCI0.P0P1.VGA.GETD",
  325                 .disp_set       = "SDSP"
  326         },
  327         {
  328                 .name           = "L5x",
  329                 .mled_set       = "MLED",
  330                 .tled_set       = "TLED",
  331                 .lcd_get        = "\\BAOF",
  332                 .lcd_set        = "\\Q0D",
  333                 .brn_get        = "GPLV",
  334                 .brn_set        = "SPLV",
  335                 .disp_get       = "\\INFB",
  336                 .disp_set       = "SDSP"
  337         },
  338         {
  339                 .name           = "L8L"
  340                 /* Only has hotkeys, apparently */
  341         },
  342         {
  343                 .name           = "M1A",
  344                 .mled_set       = "MLED",
  345                 .brn_up         = "\\_SB.PCI0.PX40.EC0.Q0E",
  346                 .brn_dn         = "\\_SB.PCI0.PX40.EC0.Q0F",
  347                 .lcd_get        = "\\PNOF",
  348                 .lcd_set        = "\\_SB.PCI0.PX40.EC0.Q10"
  349         },
  350         {
  351                 .name           = "M2E",
  352                 .mled_set       = "MLED",
  353                 .wled_set       = "WLED",
  354                 .brn_get        = "GPLV",
  355                 .brn_set        = "SPLV",
  356                 .lcd_get        = "\\GP06",
  357                 .lcd_set        = "\\Q10"
  358         },
  359         {
  360                 .name           = "M6N",
  361                 .mled_set       = "MLED",
  362                 .wled_set       = "WLED",
  363                 .lcd_set        = "\\_SB.PCI0.SBRG.EC0._Q10",
  364                 .lcd_get        = "\\_SB.BKLT",
  365                 .brn_set        = "SPLV",
  366                 .brn_get        = "GPLV",
  367                 .disp_set       = "SDSP",
  368                 .disp_get       = "\\SSTE"
  369         },
  370         {
  371                 .name           = "M6R",
  372                 .mled_set       = "MLED",
  373                 .wled_set       = "WLED",
  374                 .brn_get        = "GPLV",
  375                 .brn_set        = "SPLV",
  376                 .lcd_get        = "\\_SB.PCI0.SBSM.SEO4",
  377                 .lcd_set        = "\\_SB.PCI0.SBRG.EC0._Q10",
  378                 .disp_get       = "\\SSTE",
  379                 .disp_set       = "SDSP"
  380         },
  381         {
  382                 .name           = "S1x",
  383                 .mled_set       = "MLED",
  384                 .wled_set       = "WLED",
  385                 .lcd_get        = "\\PNOF",
  386                 .lcd_set        = "\\_SB.PCI0.PX40.Q10",
  387                 .brn_get        = "GPLV",
  388                 .brn_set        = "SPLV"
  389         },
  390         {
  391                 .name           = "S2x",
  392                 .mled_set       = "MLED",
  393                 .lcd_get        = "\\BKLI",
  394                 .lcd_set        = "\\_SB.PCI0.ISA.EC0._Q10",
  395                 .brn_up         = "\\_SB.PCI0.ISA.EC0._Q0B",
  396                 .brn_dn         = "\\_SB.PCI0.ISA.EC0._Q0A"
  397         },
  398         {
  399                 .name           = "V6V",
  400                 .bled_set       = "BLED",
  401                 .tled_set       = "TLED",
  402                 .wled_set       = "WLED",
  403                 .lcd_get        = "\\BKLT",
  404                 .lcd_set        = "\\_SB.PCI0.SBRG.EC0._Q10",
  405                 .brn_get        = "GPLV",
  406                 .brn_set        = "SPLV",
  407                 .disp_get       = "\\_SB.PCI0.P0P1.VGA.GETD",
  408                 .disp_set       = "SDSP"
  409         },
  410         {
  411                 .name           = "W5A",
  412                 .bled_set       = "BLED",
  413                 .lcd_get        = "\\BKLT",
  414                 .lcd_set        = "\\_SB.PCI0.SBRG.EC0._Q10",
  415                 .brn_get        = "GPLV",
  416                 .brn_set        = "SPLV",
  417                 .disp_get       = "\\_SB.PCI0.P0P2.VGA.GETD",
  418                 .disp_set       = "SDSP"
  419         },
  420 
  421         { .name = NULL }
  422 };
  423 
  424 /*
  425  * Samsung P30/P35 laptops have an Asus ATK0100 gadget interface,
  426  * but they can't be probed quite the same way as Asus laptops.
  427  */
  428 static struct acpi_asus_model acpi_samsung_models[] = {
  429         {
  430                 .name           = "P30",
  431                 .wled_set       = "WLED",
  432                 .brn_up         = "\\_SB.PCI0.LPCB.EC0._Q68",
  433                 .brn_dn         = "\\_SB.PCI0.LPCB.EC0._Q69",
  434                 .lcd_get        = "\\BKLT",
  435                 .lcd_set        = "\\_SB.PCI0.LPCB.EC0._Q0E"
  436         },
  437 
  438         { .name = NULL }
  439 };
  440 
  441 static void     acpi_asus_eeepc_notify(ACPI_HANDLE h, UINT32 notify, void *context);
  442 
  443 /*
  444  * EeePC have an Asus ASUS010 gadget interface,
  445  * but they can't be probed quite the same way as Asus laptops.
  446  */
  447 static struct acpi_asus_model acpi_eeepc_models[] = {
  448         {
  449                 .name           = "EEE",
  450                 .brn_get        = "\\_SB.ATKD.PBLG",
  451                 .brn_set        = "\\_SB.ATKD.PBLS",
  452                 .cam_get        = "\\_SB.ATKD.CAMG",
  453                 .cam_set        = "\\_SB.ATKD.CAMS",
  454                 .crd_set        = "\\_SB.ATKD.CRDS",
  455                 .crd_get        = "\\_SB.ATKD.CRDG",
  456                 .wlan_get       = "\\_SB.ATKD.WLDG",
  457                 .wlan_set       = "\\_SB.ATKD.WLDS",
  458                 .n_func         = acpi_asus_eeepc_notify
  459         },
  460 
  461         { .name = NULL }
  462 };
  463 
  464 static struct {
  465         char    *name;
  466         char    *description;
  467         int     method;
  468         int     flags;
  469 } acpi_asus_sysctls[] = {
  470         {
  471                 .name           = "lcd_backlight",
  472                 .method         = ACPI_ASUS_METHOD_LCD,
  473                 .description    = "state of the lcd backlight",
  474                 .flags          = CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_ANYBODY
  475         },
  476         {
  477                 .name           = "lcd_brightness",
  478                 .method         = ACPI_ASUS_METHOD_BRN,
  479                 .description    = "brightness of the lcd panel",
  480                 .flags          = CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_ANYBODY
  481         },
  482         {
  483                 .name           = "video_output",
  484                 .method         = ACPI_ASUS_METHOD_DISP,
  485                 .description    = "display output state",
  486                 .flags          = CTLTYPE_INT | CTLFLAG_RW
  487         },
  488         {
  489                 .name           = "camera",
  490                 .method         = ACPI_ASUS_METHOD_CAMERA,
  491                 .description    = "internal camera state",  
  492                 .flags          = CTLTYPE_INT | CTLFLAG_RW
  493         },
  494         {
  495                 .name           = "cardreader",
  496                 .method         = ACPI_ASUS_METHOD_CARDRD,
  497                 .description    = "internal card reader state",
  498                 .flags          = CTLTYPE_INT | CTLFLAG_RW
  499         },
  500         {
  501                 .name           = "wlan",
  502                 .method         = ACPI_ASUS_METHOD_WLAN,
  503                 .description    = "wireless lan state",
  504                 .flags          = CTLTYPE_INT | CTLFLAG_RW
  505         },
  506 
  507         { .name = NULL }
  508 };
  509 
  510 ACPI_SERIAL_DECL(asus, "ACPI ASUS extras");
  511 
  512 /* Function prototypes */
  513 static int      acpi_asus_probe(device_t dev);
  514 static int      acpi_asus_attach(device_t dev);
  515 static int      acpi_asus_detach(device_t dev);
  516 
  517 static void     acpi_asus_led(struct acpi_asus_led *led, int state);
  518 static void     acpi_asus_led_task(struct acpi_asus_led *led, int pending __unused);
  519 
  520 static int      acpi_asus_sysctl(SYSCTL_HANDLER_ARGS);
  521 static int      acpi_asus_sysctl_init(struct acpi_asus_softc *sc, int method);
  522 static int      acpi_asus_sysctl_get(struct acpi_asus_softc *sc, int method);
  523 static int      acpi_asus_sysctl_set(struct acpi_asus_softc *sc, int method, int val);
  524 
  525 static void     acpi_asus_notify(ACPI_HANDLE h, UINT32 notify, void *context);
  526 
  527 static device_method_t acpi_asus_methods[] = {
  528         DEVMETHOD(device_probe,  acpi_asus_probe),
  529         DEVMETHOD(device_attach, acpi_asus_attach),
  530         DEVMETHOD(device_detach, acpi_asus_detach),
  531 
  532         { 0, 0 }
  533 };
  534 
  535 static driver_t acpi_asus_driver = {
  536         "acpi_asus",
  537         acpi_asus_methods,
  538         sizeof(struct acpi_asus_softc)
  539 };
  540 
  541 static devclass_t acpi_asus_devclass;
  542 
  543 DRIVER_MODULE(acpi_asus, acpi, acpi_asus_driver, acpi_asus_devclass, 0, 0);
  544 MODULE_DEPEND(acpi_asus, acpi, 1, 1, 1);
  545 
  546 static int
  547 acpi_asus_probe(device_t dev)
  548 {
  549         struct acpi_asus_model  *model;
  550         struct acpi_asus_softc  *sc;
  551         struct sbuf             *sb;
  552         ACPI_BUFFER             Buf;
  553         ACPI_OBJECT             Arg, *Obj;
  554         ACPI_OBJECT_LIST        Args;
  555         static char             *asus_ids[] = { "ATK0100", "ASUS010", NULL };
  556         char *rstr;
  557 
  558         ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
  559 
  560         if (acpi_disabled("asus"))
  561                 return (ENXIO);
  562         rstr = ACPI_ID_PROBE(device_get_parent(dev), dev, asus_ids);
  563         if (rstr == NULL) {
  564                 return (ENXIO);
  565         }
  566 
  567         sc = device_get_softc(dev);
  568         sc->dev = dev;
  569         sc->handle = acpi_get_handle(dev);
  570 
  571         Arg.Type = ACPI_TYPE_INTEGER;
  572         Arg.Integer.Value = 0;
  573 
  574         Args.Count = 1;
  575         Args.Pointer = &Arg;
  576 
  577         Buf.Pointer = NULL;
  578         Buf.Length = ACPI_ALLOCATE_BUFFER;
  579 
  580         AcpiEvaluateObject(sc->handle, "INIT", &Args, &Buf);
  581         Obj = Buf.Pointer;
  582 
  583         /*
  584          * The Samsung P30 returns a null-pointer from INIT, we
  585          * can identify it from the 'ODEM' string in the DSDT.
  586          */
  587         if (Obj->String.Pointer == NULL) {
  588                 ACPI_STATUS             status;
  589                 ACPI_TABLE_HEADER       th;
  590 
  591                 status = AcpiGetTableHeader(ACPI_SIG_DSDT, 0, &th);
  592                 if (ACPI_FAILURE(status)) {
  593                         device_printf(dev, "Unsupported (Samsung?) laptop\n");
  594                         AcpiOsFree(Buf.Pointer);
  595                         return (ENXIO);
  596                 }
  597 
  598                 if (strncmp("ODEM", th.OemTableId, 4) == 0) {
  599                         sc->model = &acpi_samsung_models[0];
  600                         device_set_desc(dev, "Samsung P30 Laptop Extras");
  601                         AcpiOsFree(Buf.Pointer);
  602                         return (0);
  603                 }
  604 
  605                 /* EeePC */
  606                 if (strncmp("ASUS010", rstr, 7) == 0) {
  607                         sc->model = &acpi_eeepc_models[0];
  608                         device_set_desc(dev, "ASUS EeePC");
  609                         AcpiOsFree(Buf.Pointer);
  610                         return (0);
  611                 }
  612         }
  613 
  614         sb = sbuf_new_auto();
  615         if (sb == NULL)
  616                 return (ENOMEM);
  617 
  618         /*
  619          * Asus laptops are simply identified by name, easy!
  620          */
  621         for (model = acpi_asus_models; model->name != NULL; model++) {
  622                 if (strncmp(Obj->String.Pointer, model->name, 3) == 0) {
  623 
  624 good:
  625                         sbuf_printf(sb, "Asus %s Laptop Extras",
  626                             Obj->String.Pointer);
  627                         sbuf_finish(sb);
  628 
  629                         sc->model = model;
  630                         device_set_desc_copy(dev, sbuf_data(sb));
  631 
  632                         sbuf_delete(sb);
  633                         AcpiOsFree(Buf.Pointer);
  634                         return (0);
  635                 }
  636                 
  637                 /*
  638                  * Some models look exactly the same as other models, but have
  639                  * their own ids.  If we spot these, set them up with the same
  640                  * details as the models they're like, possibly dealing with
  641                  * small differences.
  642                  *
  643                  * XXX: there must be a prettier way to do this!
  644                  */
  645                 else if (strncmp(model->name, "xxN", 3) == 0 &&
  646                     (strncmp(Obj->String.Pointer, "M3N", 3) == 0 ||
  647                      strncmp(Obj->String.Pointer, "S1N", 3) == 0))
  648                         goto good;
  649                 else if (strncmp(model->name, "A1x", 3) == 0 &&
  650                     strncmp(Obj->String.Pointer, "A1", 2) == 0)
  651                         goto good;
  652                 else if (strncmp(model->name, "A2x", 3) == 0 &&
  653                     strncmp(Obj->String.Pointer, "A2", 2) == 0)
  654                         goto good;
  655                 else if (strncmp(model->name, "A3F", 3) == 0 &&
  656                     strncmp(Obj->String.Pointer, "A6F", 3) == 0)
  657                         goto good;
  658                 else if (strncmp(model->name, "D1x", 3) == 0 &&
  659                     strncmp(Obj->String.Pointer, "D1", 2) == 0)
  660                         goto good;
  661                 else if (strncmp(model->name, "L3H", 3) == 0 &&
  662                     strncmp(Obj->String.Pointer, "L2E", 3) == 0)
  663                         goto good;
  664                 else if (strncmp(model->name, "L5x", 3) == 0 &&
  665                     strncmp(Obj->String.Pointer, "L5", 2) == 0)
  666                         goto good;
  667                 else if (strncmp(model->name, "M2E", 3) == 0 &&
  668                     (strncmp(Obj->String.Pointer, "M2", 2) == 0 ||
  669                      strncmp(Obj->String.Pointer, "L4E", 3) == 0))
  670                         goto good;
  671                 else if (strncmp(model->name, "S1x", 3) == 0 &&
  672                     (strncmp(Obj->String.Pointer, "L8", 2) == 0 ||
  673                      strncmp(Obj->String.Pointer, "S1", 2) == 0))
  674                         goto good;
  675                 else if (strncmp(model->name, "S2x", 3) == 0 &&
  676                     (strncmp(Obj->String.Pointer, "J1", 2) == 0 ||
  677                      strncmp(Obj->String.Pointer, "S2", 2) == 0))
  678                         goto good;
  679 
  680                 /* L2B is like L3C but has no lcd_get method */
  681                 else if (strncmp(model->name, "L3C", 3) == 0 &&
  682                     strncmp(Obj->String.Pointer, "L2B", 3) == 0) {
  683                         model->lcd_get = NULL;
  684                         goto good;
  685                 }
  686 
  687                 /* A3G is like M6R but with a different lcd_get method */
  688                 else if (strncmp(model->name, "M6R", 3) == 0 &&
  689                     strncmp(Obj->String.Pointer, "A3G", 3) == 0) {
  690                         model->lcd_get = "\\BLFG";
  691                         goto good;
  692                 }
  693 
  694                 /* M2N and W1N are like xxN with added WLED */
  695                 else if (strncmp(model->name, "xxN", 3) == 0 &&
  696                     (strncmp(Obj->String.Pointer, "M2N", 3) == 0 ||
  697                      strncmp(Obj->String.Pointer, "W1N", 3) == 0)) {
  698                         model->wled_set = "WLED";
  699                         goto good;
  700                 }
  701 
  702                 /* M5N and S5N are like xxN without MLED */
  703                 else if (strncmp(model->name, "xxN", 3) == 0 &&
  704                     (strncmp(Obj->String.Pointer, "M5N", 3) == 0 ||
  705                      strncmp(Obj->String.Pointer, "S5N", 3) == 0)) {
  706                         model->mled_set = NULL;
  707                         goto good;
  708                 }
  709         }
  710 
  711         sbuf_printf(sb, "Unsupported Asus laptop: %s\n", Obj->String.Pointer);
  712         sbuf_finish(sb);
  713 
  714         device_printf(dev, sbuf_data(sb));
  715 
  716         sbuf_delete(sb);
  717         AcpiOsFree(Buf.Pointer);
  718 
  719         return (ENXIO);
  720 }
  721 
  722 static int
  723 acpi_asus_attach(device_t dev)
  724 {
  725         struct acpi_asus_softc  *sc;
  726         struct acpi_softc       *acpi_sc;
  727 
  728         ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
  729 
  730         sc = device_get_softc(dev);
  731         acpi_sc = acpi_device_get_parent_softc(dev);
  732 
  733         /* Build sysctl tree */
  734         sysctl_ctx_init(&sc->sysctl_ctx);
  735         sc->sysctl_tree = SYSCTL_ADD_NODE(&sc->sysctl_ctx,
  736             SYSCTL_CHILDREN(acpi_sc->acpi_sysctl_tree),
  737             OID_AUTO, "asus", CTLFLAG_RD, 0, "");
  738 
  739         /* Hook up nodes */
  740         for (int i = 0; acpi_asus_sysctls[i].name != NULL; i++) {
  741                 if (!acpi_asus_sysctl_init(sc, acpi_asus_sysctls[i].method))
  742                         continue;
  743 
  744                 SYSCTL_ADD_PROC(&sc->sysctl_ctx,
  745                     SYSCTL_CHILDREN(sc->sysctl_tree), OID_AUTO,
  746                     acpi_asus_sysctls[i].name,
  747                     acpi_asus_sysctls[i].flags,
  748                     sc, i, acpi_asus_sysctl, "I",
  749                     acpi_asus_sysctls[i].description);
  750         }
  751 
  752         /* Attach leds */
  753         if (sc->model->bled_set) {
  754                 sc->s_bled.busy = 0;
  755                 sc->s_bled.sc = sc;
  756                 sc->s_bled.type = ACPI_ASUS_LED_BLED;
  757                 sc->s_bled.cdev =
  758                     led_create_state((led_t *)acpi_asus_led, &sc->s_bled,
  759                         "bled", 1);
  760         }
  761 
  762         if (sc->model->dled_set) {
  763                 sc->s_dled.busy = 0;
  764                 sc->s_dled.sc = sc;
  765                 sc->s_dled.type = ACPI_ASUS_LED_DLED;
  766                 sc->s_dled.cdev =
  767                     led_create((led_t *)acpi_asus_led, &sc->s_dled, "dled");
  768         }
  769 
  770         if (sc->model->gled_set) {
  771                 sc->s_gled.busy = 0;
  772                 sc->s_gled.sc = sc;
  773                 sc->s_gled.type = ACPI_ASUS_LED_GLED;
  774                 sc->s_gled.cdev =
  775                     led_create((led_t *)acpi_asus_led, &sc->s_gled, "gled");
  776         }
  777 
  778         if (sc->model->mled_set) {
  779                 sc->s_mled.busy = 0;
  780                 sc->s_mled.sc = sc;
  781                 sc->s_mled.type = ACPI_ASUS_LED_MLED;
  782                 sc->s_mled.cdev =
  783                     led_create((led_t *)acpi_asus_led, &sc->s_mled, "mled");
  784         }
  785 
  786         if (sc->model->tled_set) {
  787                 sc->s_tled.busy = 0;
  788                 sc->s_tled.sc = sc;
  789                 sc->s_tled.type = ACPI_ASUS_LED_TLED;
  790                 sc->s_tled.cdev =
  791                     led_create_state((led_t *)acpi_asus_led, &sc->s_tled,
  792                         "tled", 1);
  793         }
  794 
  795         if (sc->model->wled_set) {
  796                 sc->s_wled.busy = 0;
  797                 sc->s_wled.sc = sc;
  798                 sc->s_wled.type = ACPI_ASUS_LED_WLED;
  799                 sc->s_wled.cdev =
  800                     led_create_state((led_t *)acpi_asus_led, &sc->s_wled,
  801                         "wled", 1);
  802         }
  803 
  804         /* Activate hotkeys */
  805         AcpiEvaluateObject(sc->handle, "BSTS", NULL, NULL);
  806 
  807         /* Handle notifies */
  808         if (sc->model->n_func == NULL)
  809                 sc->model->n_func = acpi_asus_notify;
  810 
  811         AcpiInstallNotifyHandler(sc->handle, ACPI_SYSTEM_NOTIFY,
  812             sc->model->n_func, dev);
  813 
  814         /* Find and hook the 'LCDD' object */
  815         if (sc->model->lcdd != NULL && sc->model->lcdd_n_func != NULL) {
  816                 ACPI_STATUS res;
  817 
  818                 sc->lcdd_handle = NULL;
  819                 res = AcpiGetHandle((sc->model->lcdd[0] == '\\' ?
  820                     NULL : sc->handle), sc->model->lcdd, &(sc->lcdd_handle));
  821                 if (ACPI_SUCCESS(res)) {
  822                         AcpiInstallNotifyHandler((sc->lcdd_handle),
  823                             ACPI_DEVICE_NOTIFY, sc->model->lcdd_n_func, dev);
  824                 } else {
  825                         printf("%s: unable to find LCD device '%s'\n",
  826                             __func__, sc->model->lcdd);
  827                 }
  828         }
  829 
  830         return (0);
  831 }
  832 
  833 static int
  834 acpi_asus_detach(device_t dev)
  835 {
  836         struct acpi_asus_softc  *sc;
  837 
  838         ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
  839 
  840         sc = device_get_softc(dev);
  841 
  842         /* Turn the lights off */
  843         if (sc->model->bled_set)
  844                 led_destroy(sc->s_bled.cdev);
  845 
  846         if (sc->model->dled_set)
  847                 led_destroy(sc->s_dled.cdev);
  848 
  849         if (sc->model->gled_set)
  850                 led_destroy(sc->s_gled.cdev);
  851 
  852         if (sc->model->mled_set)
  853                 led_destroy(sc->s_mled.cdev);
  854 
  855         if (sc->model->tled_set)
  856                 led_destroy(sc->s_tled.cdev);
  857 
  858         if (sc->model->wled_set)
  859                 led_destroy(sc->s_wled.cdev);
  860 
  861         /* Remove notify handler */
  862         AcpiRemoveNotifyHandler(sc->handle, ACPI_SYSTEM_NOTIFY,
  863             acpi_asus_notify);
  864         
  865         if (sc->lcdd_handle) {
  866                 KASSERT(sc->model->lcdd_n_func != NULL,
  867                     ("model->lcdd_n_func is NULL, but lcdd_handle is non-zero"));
  868                 AcpiRemoveNotifyHandler((sc->lcdd_handle),
  869                     ACPI_DEVICE_NOTIFY, sc->model->lcdd_n_func);
  870         }
  871 
  872         /* Free sysctl tree */
  873         sysctl_ctx_free(&sc->sysctl_ctx);
  874 
  875         return (0);
  876 }
  877 
  878 static void
  879 acpi_asus_led_task(struct acpi_asus_led *led, int pending __unused)
  880 {
  881         struct acpi_asus_softc  *sc;
  882         char                    *method;
  883         int                     state;
  884         
  885         ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
  886 
  887         sc = led->sc;
  888 
  889         switch (led->type) {
  890         case ACPI_ASUS_LED_BLED:
  891                 method = sc->model->bled_set;
  892                 state = led->state;
  893                 break;
  894         case ACPI_ASUS_LED_DLED:
  895                 method = sc->model->dled_set;
  896                 state = led->state;
  897                 break;
  898         case ACPI_ASUS_LED_GLED:
  899                 method = sc->model->gled_set;
  900                 state = led->state + 1; /* 1: off, 2: on */
  901                 break;
  902         case ACPI_ASUS_LED_MLED:
  903                 method = sc->model->mled_set;
  904                 state = !led->state;    /* inverted */
  905                 break;
  906         case ACPI_ASUS_LED_TLED:
  907                 method = sc->model->tled_set;
  908                 state = led->state;
  909                 break;
  910         case ACPI_ASUS_LED_WLED:
  911                 method = sc->model->wled_set;
  912                 state = led->state;
  913                 break;
  914         default:
  915                 printf("acpi_asus_led: invalid LED type %d\n",
  916                     (int)led->type);
  917                 return;
  918         }
  919 
  920         acpi_SetInteger(sc->handle, method, state);
  921         led->busy = 0;
  922 }
  923         
  924 static void
  925 acpi_asus_led(struct acpi_asus_led *led, int state)
  926 {
  927 
  928         ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
  929 
  930         if (led->busy)
  931                 return;
  932 
  933         led->busy = 1;
  934         led->state = state;
  935 
  936         AcpiOsExecute(OSL_NOTIFY_HANDLER, (void *)acpi_asus_led_task, led);
  937 }
  938 
  939 static int
  940 acpi_asus_sysctl(SYSCTL_HANDLER_ARGS)
  941 {
  942         struct acpi_asus_softc  *sc;
  943         int                     arg;
  944         int                     error = 0;
  945         int                     function;
  946         int                     method;
  947         
  948         ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
  949 
  950         sc = (struct acpi_asus_softc *)oidp->oid_arg1;
  951         function = oidp->oid_arg2;
  952         method = acpi_asus_sysctls[function].method;
  953 
  954         ACPI_SERIAL_BEGIN(asus);
  955         arg = acpi_asus_sysctl_get(sc, method);
  956         error = sysctl_handle_int(oidp, &arg, 0, req);
  957 
  958         /* Sanity check */
  959         if (error != 0 || req->newptr == NULL)
  960                 goto out;
  961 
  962         /* Update */
  963         error = acpi_asus_sysctl_set(sc, method, arg);
  964 
  965 out:
  966         ACPI_SERIAL_END(asus);
  967         return (error);
  968 }
  969 
  970 static int
  971 acpi_asus_sysctl_get(struct acpi_asus_softc *sc, int method)
  972 {
  973         int val = 0;
  974 
  975         ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
  976         ACPI_SERIAL_ASSERT(asus);
  977 
  978         switch (method) {
  979         case ACPI_ASUS_METHOD_BRN:
  980                 val = sc->s_brn;
  981                 break;
  982         case ACPI_ASUS_METHOD_DISP:
  983                 val = sc->s_disp;
  984                 break;
  985         case ACPI_ASUS_METHOD_LCD:
  986                 val = sc->s_lcd;
  987                 break;
  988         case ACPI_ASUS_METHOD_CAMERA:
  989                 val = sc->s_cam;
  990                 break;
  991         case ACPI_ASUS_METHOD_CARDRD:
  992                 val = sc->s_crd;
  993                 break;
  994         case ACPI_ASUS_METHOD_WLAN:
  995                 val = sc->s_wlan;
  996                 break;
  997         }
  998 
  999         return (val);
 1000 }
 1001 
 1002 static int
 1003 acpi_asus_sysctl_set(struct acpi_asus_softc *sc, int method, int arg)
 1004 {
 1005         ACPI_STATUS             status = AE_OK;
 1006         ACPI_OBJECT_LIST        acpiargs;
 1007         ACPI_OBJECT             acpiarg[1];
 1008 
 1009         ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
 1010         ACPI_SERIAL_ASSERT(asus);
 1011 
 1012         acpiargs.Count = 1;
 1013         acpiargs.Pointer = acpiarg;
 1014         acpiarg[0].Type = ACPI_TYPE_INTEGER;
 1015         acpiarg[0].Integer.Value = arg;
 1016 
 1017         switch (method) {
 1018         case ACPI_ASUS_METHOD_BRN:
 1019                 if (arg < 0 || arg > 15)
 1020                         return (EINVAL);
 1021 
 1022                 if (sc->model->brn_set)
 1023                         status = acpi_SetInteger(sc->handle,
 1024                             sc->model->brn_set, arg);
 1025                 else {
 1026                         while (arg != 0) {
 1027                                 status = AcpiEvaluateObject(sc->handle,
 1028                                     (arg > 0) ?  sc->model->brn_up :
 1029                                     sc->model->brn_dn, NULL, NULL);
 1030                                 (arg > 0) ? arg-- : arg++;
 1031                         }
 1032                 }
 1033 
 1034                 if (ACPI_SUCCESS(status))
 1035                         sc->s_brn = arg;
 1036 
 1037                 break;
 1038         case ACPI_ASUS_METHOD_DISP:
 1039                 if (arg < 0 || arg > 7)
 1040                         return (EINVAL);
 1041 
 1042                 status = acpi_SetInteger(sc->handle,
 1043                     sc->model->disp_set, arg);
 1044 
 1045                 if (ACPI_SUCCESS(status))
 1046                         sc->s_disp = arg;
 1047 
 1048                 break;
 1049         case ACPI_ASUS_METHOD_LCD:
 1050                 if (arg < 0 || arg > 1)
 1051                         return (EINVAL);
 1052 
 1053                 if (strncmp(sc->model->name, "L3H", 3) != 0)
 1054                         status = AcpiEvaluateObject(sc->handle,
 1055                             sc->model->lcd_set, NULL, NULL);
 1056                 else
 1057                         status = acpi_SetInteger(sc->handle,
 1058                             sc->model->lcd_set, 0x7);
 1059 
 1060                 if (ACPI_SUCCESS(status))
 1061                         sc->s_lcd = arg;
 1062 
 1063                 break;
 1064         case ACPI_ASUS_METHOD_CAMERA:
 1065                 if (arg < 0 || arg > 1)
 1066                         return (EINVAL);
 1067 
 1068                 status = AcpiEvaluateObject(sc->handle,
 1069                     sc->model->cam_set, &acpiargs, NULL);
 1070 
 1071                 if (ACPI_SUCCESS(status))
 1072                         sc->s_cam = arg;
 1073                 break;
 1074         case ACPI_ASUS_METHOD_CARDRD:
 1075                 if (arg < 0 || arg > 1)
 1076                         return (EINVAL);
 1077 
 1078                 status = AcpiEvaluateObject(sc->handle,
 1079                     sc->model->crd_set, &acpiargs, NULL);
 1080 
 1081                 if (ACPI_SUCCESS(status))
 1082                         sc->s_crd = arg;
 1083                 break;
 1084         case ACPI_ASUS_METHOD_WLAN:
 1085                 if (arg < 0 || arg > 1)
 1086                         return (EINVAL);
 1087 
 1088                 status = AcpiEvaluateObject(sc->handle,
 1089                     sc->model->wlan_set, &acpiargs, NULL);
 1090 
 1091                 if (ACPI_SUCCESS(status))
 1092                         sc->s_wlan = arg;
 1093                 break;
 1094         }
 1095 
 1096         return (0);
 1097 }
 1098 
 1099 static int
 1100 acpi_asus_sysctl_init(struct acpi_asus_softc *sc, int method)
 1101 {
 1102         ACPI_STATUS     status;
 1103 
 1104         switch (method) {
 1105         case ACPI_ASUS_METHOD_BRN:
 1106                 if (sc->model->brn_get) {
 1107                         /* GPLV/SPLV models */
 1108                         status = acpi_GetInteger(sc->handle,
 1109                             sc->model->brn_get, &sc->s_brn);
 1110                         if (ACPI_SUCCESS(status))
 1111                                 return (TRUE);
 1112                 } else if (sc->model->brn_up) {
 1113                         /* Relative models */
 1114                         status = AcpiEvaluateObject(sc->handle,
 1115                             sc->model->brn_up, NULL, NULL);
 1116                         if (ACPI_FAILURE(status))
 1117                                 return (FALSE);
 1118 
 1119                         status = AcpiEvaluateObject(sc->handle,
 1120                             sc->model->brn_dn, NULL, NULL);
 1121                         if (ACPI_FAILURE(status))
 1122                                 return (FALSE);
 1123 
 1124                         return (TRUE);
 1125                 }
 1126                 return (FALSE);
 1127         case ACPI_ASUS_METHOD_DISP:
 1128                 if (sc->model->disp_get) {
 1129                         status = acpi_GetInteger(sc->handle,
 1130                             sc->model->disp_get, &sc->s_disp);
 1131                         if (ACPI_SUCCESS(status))
 1132                                 return (TRUE);
 1133                 }
 1134                 return (FALSE);
 1135         case ACPI_ASUS_METHOD_LCD:
 1136                 if (sc->model->lcd_get) {
 1137                         if (strncmp(sc->model->name, "G2K", 3) == 0) {
 1138                                 ACPI_BUFFER             Buf;
 1139                                 ACPI_OBJECT             Arg, Obj;
 1140                                 ACPI_OBJECT_LIST        Args;
 1141 
 1142                                 Arg.Type = ACPI_TYPE_INTEGER;
 1143                                 Arg.Integer.Value = 0x11;
 1144                                 Args.Count = 1;
 1145                                 Args.Pointer = &Arg;
 1146                                 Buf.Length = sizeof(Obj);
 1147                                 Buf.Pointer = &Obj;
 1148 
 1149                                 status = AcpiEvaluateObject(sc->handle,
 1150                                     sc->model->lcd_get, &Args, &Buf);
 1151                                 if (ACPI_SUCCESS(status) &&
 1152                                     Obj.Type == ACPI_TYPE_INTEGER) {
 1153                                         sc->s_lcd = Obj.Integer.Value;
 1154                                         return (TRUE);
 1155                                 }
 1156                         } else if (strncmp(sc->model->name, "L3H", 3) == 0) {
 1157                                 ACPI_BUFFER             Buf;
 1158                                 ACPI_OBJECT             Arg[2], Obj;
 1159                                 ACPI_OBJECT_LIST        Args;
 1160 
 1161                                 /* L3H is a bit special */
 1162                                 Arg[0].Type = ACPI_TYPE_INTEGER;
 1163                                 Arg[0].Integer.Value = 0x02;
 1164                                 Arg[1].Type = ACPI_TYPE_INTEGER;
 1165                                 Arg[1].Integer.Value = 0x03;
 1166 
 1167                                 Args.Count = 2;
 1168                                 Args.Pointer = Arg;
 1169 
 1170                                 Buf.Length = sizeof(Obj);
 1171                                 Buf.Pointer = &Obj;
 1172 
 1173                                 status = AcpiEvaluateObject(sc->handle,
 1174                                     sc->model->lcd_get, &Args, &Buf);
 1175                                 if (ACPI_SUCCESS(status) &&
 1176                                     Obj.Type == ACPI_TYPE_INTEGER) {
 1177                                         sc->s_lcd = Obj.Integer.Value >> 8;
 1178                                         return (TRUE);
 1179                                 }
 1180                         } else {
 1181                                 status = acpi_GetInteger(sc->handle,
 1182                                     sc->model->lcd_get, &sc->s_lcd);
 1183                                 if (ACPI_SUCCESS(status))
 1184                                         return (TRUE);
 1185                         }
 1186                 }
 1187                 return (FALSE);
 1188         case ACPI_ASUS_METHOD_CAMERA:
 1189                 if (sc->model->cam_get) {
 1190                         status = acpi_GetInteger(sc->handle,
 1191                             sc->model->cam_get, &sc->s_cam);
 1192                         if (ACPI_SUCCESS(status))
 1193                                 return (TRUE);
 1194                 }
 1195                 return (FALSE);
 1196         case ACPI_ASUS_METHOD_CARDRD:
 1197                 if (sc->model->crd_get) {
 1198                         status = acpi_GetInteger(sc->handle,
 1199                             sc->model->crd_get, &sc->s_crd);
 1200                         if (ACPI_SUCCESS(status))
 1201                                 return (TRUE);
 1202                 }
 1203                 return (FALSE);
 1204         case ACPI_ASUS_METHOD_WLAN:
 1205                 if (sc->model->wlan_get) {
 1206                         status = acpi_GetInteger(sc->handle,
 1207                             sc->model->wlan_get, &sc->s_wlan);
 1208                         if (ACPI_SUCCESS(status))
 1209                                 return (TRUE);
 1210                 }
 1211                 return (FALSE);
 1212         }
 1213         return (FALSE);
 1214 }
 1215 
 1216 static void
 1217 acpi_asus_notify(ACPI_HANDLE h, UINT32 notify, void *context)
 1218 {
 1219         struct acpi_asus_softc  *sc;
 1220         struct acpi_softc       *acpi_sc;
 1221 
 1222         ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
 1223 
 1224         sc = device_get_softc((device_t)context);
 1225         acpi_sc = acpi_device_get_parent_softc(sc->dev);
 1226 
 1227         ACPI_SERIAL_BEGIN(asus);
 1228         if ((notify & ~0x10) <= 15) {
 1229                 sc->s_brn = notify & ~0x10;
 1230                 ACPI_VPRINT(sc->dev, acpi_sc, "Brightness increased\n");
 1231         } else if ((notify & ~0x20) <= 15) {
 1232                 sc->s_brn = notify & ~0x20;
 1233                 ACPI_VPRINT(sc->dev, acpi_sc, "Brightness decreased\n");
 1234         } else if (notify == 0x33) {
 1235                 sc->s_lcd = 1;
 1236                 ACPI_VPRINT(sc->dev, acpi_sc, "LCD turned on\n");
 1237         } else if (notify == 0x34) {
 1238                 sc->s_lcd = 0;
 1239                 ACPI_VPRINT(sc->dev, acpi_sc, "LCD turned off\n");
 1240         } else if (notify == 0x86) {
 1241                 acpi_asus_sysctl_set(sc, ACPI_ASUS_METHOD_BRN, sc->s_brn-1);
 1242                 ACPI_VPRINT(sc->dev, acpi_sc, "Brightness decreased\n");
 1243         } else if (notify == 0x87) {
 1244                 acpi_asus_sysctl_set(sc, ACPI_ASUS_METHOD_BRN, sc->s_brn+1);
 1245                 ACPI_VPRINT(sc->dev, acpi_sc, "Brightness increased\n");
 1246         } else {
 1247                 /* Notify devd(8) */
 1248                 acpi_UserNotify("ASUS", h, notify);
 1249         }
 1250         ACPI_SERIAL_END(asus);
 1251 }
 1252 
 1253 static void
 1254 acpi_asus_lcdd_notify(ACPI_HANDLE h, UINT32 notify, void *context)
 1255 {
 1256         struct acpi_asus_softc  *sc;
 1257         struct acpi_softc       *acpi_sc;
 1258 
 1259         ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
 1260 
 1261         sc = device_get_softc((device_t)context);
 1262         acpi_sc = acpi_device_get_parent_softc(sc->dev);
 1263 
 1264         ACPI_SERIAL_BEGIN(asus);
 1265         switch (notify) {
 1266         case 0x87:
 1267                 acpi_asus_sysctl_set(sc, ACPI_ASUS_METHOD_BRN, sc->s_brn-1);
 1268                 ACPI_VPRINT(sc->dev, acpi_sc, "Brightness decreased\n");
 1269                 break;
 1270         case 0x86:
 1271                 acpi_asus_sysctl_set(sc, ACPI_ASUS_METHOD_BRN, sc->s_brn+1);
 1272                 ACPI_VPRINT(sc->dev, acpi_sc, "Brightness increased\n");
 1273                 break;
 1274         }
 1275         ACPI_SERIAL_END(asus);
 1276 }
 1277 
 1278 static void
 1279 acpi_asus_eeepc_notify(ACPI_HANDLE h, UINT32 notify, void *context)
 1280 {
 1281         struct acpi_asus_softc  *sc;
 1282         struct acpi_softc       *acpi_sc;
 1283 
 1284         ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
 1285 
 1286         sc = device_get_softc((device_t)context);
 1287         acpi_sc = acpi_device_get_parent_softc(sc->dev);
 1288 
 1289         ACPI_SERIAL_BEGIN(asus);
 1290         if ((notify & ~0x20) <= 15) {
 1291                 sc->s_brn = notify & ~0x20;
 1292                 ACPI_VPRINT(sc->dev, acpi_sc,
 1293                     "Brightness increased/decreased\n");
 1294         } else {
 1295                 /* Notify devd(8) */
 1296                 acpi_UserNotify("ASUS-Eee", h, notify);
 1297         }
 1298         ACPI_SERIAL_END(asus);
 1299 }

Cache object: da38529f966640a508e2db202f4eacf9


[ 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.