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$");
   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        = "GBTL",
  274                 .lcd_set        = "SBTL",
  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         { .name = NULL }
  421 };
  422 
  423 /*
  424  * Samsung P30/P35 laptops have an Asus ATK0100 gadget interface,
  425  * but they can't be probed quite the same way as Asus laptops.
  426  */
  427 static struct acpi_asus_model acpi_samsung_models[] = {
  428         {
  429                 .name           = "P30",
  430                 .wled_set       = "WLED",
  431                 .brn_up         = "\\_SB.PCI0.LPCB.EC0._Q68",
  432                 .brn_dn         = "\\_SB.PCI0.LPCB.EC0._Q69",
  433                 .lcd_get        = "\\BKLT",
  434                 .lcd_set        = "\\_SB.PCI0.LPCB.EC0._Q0E"
  435         },
  436         { .name = NULL }
  437 };
  438 
  439 static void     acpi_asus_eeepc_notify(ACPI_HANDLE h, UINT32 notify, void *context);
  440 
  441 /*
  442  * EeePC have an Asus ASUS010 gadget interface,
  443  * but they can't be probed quite the same way as Asus laptops.
  444  */
  445 static struct acpi_asus_model acpi_eeepc_models[] = {
  446         {
  447                 .name           = "EEE",
  448                 .brn_get        = "\\_SB.ATKD.PBLG",
  449                 .brn_set        = "\\_SB.ATKD.PBLS",
  450                 .cam_get        = "\\_SB.ATKD.CAMG",
  451                 .cam_set        = "\\_SB.ATKD.CAMS",
  452                 .crd_set        = "\\_SB.ATKD.CRDS",
  453                 .crd_get        = "\\_SB.ATKD.CRDG",
  454                 .wlan_get       = "\\_SB.ATKD.WLDG",
  455                 .wlan_set       = "\\_SB.ATKD.WLDS",
  456                 .n_func         = acpi_asus_eeepc_notify
  457         },
  458         { .name = NULL }
  459 };
  460 
  461 static struct {
  462         char    *name;
  463         char    *description;
  464         int     method;
  465         int     flag_anybody;
  466 } acpi_asus_sysctls[] = {
  467         {
  468                 .name           = "lcd_backlight",
  469                 .method         = ACPI_ASUS_METHOD_LCD,
  470                 .description    = "state of the lcd backlight",
  471                 .flag_anybody   = 1
  472         },
  473         {
  474                 .name           = "lcd_brightness",
  475                 .method         = ACPI_ASUS_METHOD_BRN,
  476                 .description    = "brightness of the lcd panel",
  477                 .flag_anybody   = 1
  478         },
  479         {
  480                 .name           = "video_output",
  481                 .method         = ACPI_ASUS_METHOD_DISP,
  482                 .description    = "display output state",
  483         },
  484         {
  485                 .name           = "camera",
  486                 .method         = ACPI_ASUS_METHOD_CAMERA,
  487                 .description    = "internal camera state",  
  488         },
  489         {
  490                 .name           = "cardreader",
  491                 .method         = ACPI_ASUS_METHOD_CARDRD,
  492                 .description    = "internal card reader state",
  493         },
  494         {
  495                 .name           = "wlan",
  496                 .method         = ACPI_ASUS_METHOD_WLAN,
  497                 .description    = "wireless lan state",
  498         },
  499         { .name = NULL }
  500 };
  501 
  502 ACPI_SERIAL_DECL(asus, "ACPI ASUS extras");
  503 
  504 /* Function prototypes */
  505 static int      acpi_asus_probe(device_t dev);
  506 static int      acpi_asus_attach(device_t dev);
  507 static int      acpi_asus_detach(device_t dev);
  508 
  509 static void     acpi_asus_led(struct acpi_asus_led *led, int state);
  510 static void     acpi_asus_led_task(struct acpi_asus_led *led, int pending __unused);
  511 
  512 static int      acpi_asus_sysctl(SYSCTL_HANDLER_ARGS);
  513 static int      acpi_asus_sysctl_init(struct acpi_asus_softc *sc, int method);
  514 static int      acpi_asus_sysctl_get(struct acpi_asus_softc *sc, int method);
  515 static int      acpi_asus_sysctl_set(struct acpi_asus_softc *sc, int method, int val);
  516 
  517 static void     acpi_asus_notify(ACPI_HANDLE h, UINT32 notify, void *context);
  518 
  519 static device_method_t acpi_asus_methods[] = {
  520         DEVMETHOD(device_probe,  acpi_asus_probe),
  521         DEVMETHOD(device_attach, acpi_asus_attach),
  522         DEVMETHOD(device_detach, acpi_asus_detach),
  523         { 0, 0 }
  524 };
  525 
  526 static driver_t acpi_asus_driver = {
  527         "acpi_asus",
  528         acpi_asus_methods,
  529         sizeof(struct acpi_asus_softc)
  530 };
  531 
  532 DRIVER_MODULE(acpi_asus, acpi, acpi_asus_driver, 0, 0);
  533 MODULE_DEPEND(acpi_asus, acpi, 1, 1, 1);
  534 
  535 static int
  536 acpi_asus_probe(device_t dev)
  537 {
  538         struct acpi_asus_model  *model;
  539         struct acpi_asus_softc  *sc;
  540         struct sbuf             *sb;
  541         ACPI_BUFFER             Buf;
  542         ACPI_OBJECT             Arg, *Obj;
  543         ACPI_OBJECT_LIST        Args;
  544         static char             *asus_ids[] = { "ATK0100", "ASUS010", NULL };
  545         int rv;
  546         char *rstr;
  547 
  548         ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
  549 
  550         if (acpi_disabled("asus"))
  551                 return (ENXIO);
  552         rv = ACPI_ID_PROBE(device_get_parent(dev), dev, asus_ids, &rstr);
  553         if (rv > 0) {
  554                 return (rv);
  555         }
  556 
  557         sc = device_get_softc(dev);
  558         sc->dev = dev;
  559         sc->handle = acpi_get_handle(dev);
  560 
  561         Arg.Type = ACPI_TYPE_INTEGER;
  562         Arg.Integer.Value = 0;
  563 
  564         Args.Count = 1;
  565         Args.Pointer = &Arg;
  566 
  567         Buf.Pointer = NULL;
  568         Buf.Length = ACPI_ALLOCATE_BUFFER;
  569 
  570         AcpiEvaluateObject(sc->handle, "INIT", &Args, &Buf);
  571         Obj = Buf.Pointer;
  572 
  573         /*
  574          * The Samsung P30 returns a null-pointer from INIT, we
  575          * can identify it from the 'ODEM' string in the DSDT.
  576          */
  577         if (Obj->String.Pointer == NULL) {
  578                 ACPI_STATUS             status;
  579                 ACPI_TABLE_HEADER       th;
  580 
  581                 status = AcpiGetTableHeader(ACPI_SIG_DSDT, 0, &th);
  582                 if (ACPI_FAILURE(status)) {
  583                         device_printf(dev, "Unsupported (Samsung?) laptop\n");
  584                         AcpiOsFree(Buf.Pointer);
  585                         return (ENXIO);
  586                 }
  587 
  588                 if (strncmp("ODEM", th.OemTableId, 4) == 0) {
  589                         sc->model = &acpi_samsung_models[0];
  590                         device_set_desc(dev, "Samsung P30 Laptop Extras");
  591                         AcpiOsFree(Buf.Pointer);
  592                         return (rv);
  593                 }
  594 
  595                 /* EeePC */
  596                 if (strncmp("ASUS010", rstr, 7) == 0) {
  597                         sc->model = &acpi_eeepc_models[0];
  598                         device_set_desc(dev, "ASUS EeePC");
  599                         AcpiOsFree(Buf.Pointer);
  600                         return (rv);
  601                 }
  602         }
  603 
  604         sb = sbuf_new_auto();
  605         if (sb == NULL)
  606                 return (ENOMEM);
  607 
  608         /*
  609          * Asus laptops are simply identified by name, easy!
  610          */
  611         for (model = acpi_asus_models; model->name != NULL; model++) {
  612                 if (strncmp(Obj->String.Pointer, model->name, 3) == 0) {
  613 good:
  614                         sbuf_printf(sb, "Asus %s Laptop Extras",
  615                             Obj->String.Pointer);
  616                         sbuf_finish(sb);
  617 
  618                         sc->model = model;
  619                         device_set_desc_copy(dev, sbuf_data(sb));
  620 
  621                         sbuf_delete(sb);
  622                         AcpiOsFree(Buf.Pointer);
  623                         return (rv);
  624                 }
  625                 
  626                 /*
  627                  * Some models look exactly the same as other models, but have
  628                  * their own ids.  If we spot these, set them up with the same
  629                  * details as the models they're like, possibly dealing with
  630                  * small differences.
  631                  *
  632                  * XXX: there must be a prettier way to do this!
  633                  */
  634                 else if (strncmp(model->name, "xxN", 3) == 0 &&
  635                     (strncmp(Obj->String.Pointer, "M3N", 3) == 0 ||
  636                      strncmp(Obj->String.Pointer, "S1N", 3) == 0))
  637                         goto good;
  638                 else if (strncmp(model->name, "A1x", 3) == 0 &&
  639                     strncmp(Obj->String.Pointer, "A1", 2) == 0)
  640                         goto good;
  641                 else if (strncmp(model->name, "A2x", 3) == 0 &&
  642                     strncmp(Obj->String.Pointer, "A2", 2) == 0)
  643                         goto good;
  644                 else if (strncmp(model->name, "A3F", 3) == 0 &&
  645                     strncmp(Obj->String.Pointer, "A6F", 3) == 0)
  646                         goto good;
  647                 else if (strncmp(model->name, "D1x", 3) == 0 &&
  648                     strncmp(Obj->String.Pointer, "D1", 2) == 0)
  649                         goto good;
  650                 else if (strncmp(model->name, "L3H", 3) == 0 &&
  651                     strncmp(Obj->String.Pointer, "L2E", 3) == 0)
  652                         goto good;
  653                 else if (strncmp(model->name, "L5x", 3) == 0 &&
  654                     strncmp(Obj->String.Pointer, "L5", 2) == 0)
  655                         goto good;
  656                 else if (strncmp(model->name, "M2E", 3) == 0 &&
  657                     (strncmp(Obj->String.Pointer, "M2", 2) == 0 ||
  658                      strncmp(Obj->String.Pointer, "L4E", 3) == 0))
  659                         goto good;
  660                 else if (strncmp(model->name, "S1x", 3) == 0 &&
  661                     (strncmp(Obj->String.Pointer, "L8", 2) == 0 ||
  662                      strncmp(Obj->String.Pointer, "S1", 2) == 0))
  663                         goto good;
  664                 else if (strncmp(model->name, "S2x", 3) == 0 &&
  665                     (strncmp(Obj->String.Pointer, "J1", 2) == 0 ||
  666                      strncmp(Obj->String.Pointer, "S2", 2) == 0))
  667                         goto good;
  668 
  669                 /* L2B is like L3C but has no lcd_get method */
  670                 else if (strncmp(model->name, "L3C", 3) == 0 &&
  671                     strncmp(Obj->String.Pointer, "L2B", 3) == 0) {
  672                         model->lcd_get = NULL;
  673                         goto good;
  674                 }
  675 
  676                 /* A3G is like M6R but with a different lcd_get method */
  677                 else if (strncmp(model->name, "M6R", 3) == 0 &&
  678                     strncmp(Obj->String.Pointer, "A3G", 3) == 0) {
  679                         model->lcd_get = "\\BLFG";
  680                         goto good;
  681                 }
  682 
  683                 /* M2N and W1N are like xxN with added WLED */
  684                 else if (strncmp(model->name, "xxN", 3) == 0 &&
  685                     (strncmp(Obj->String.Pointer, "M2N", 3) == 0 ||
  686                      strncmp(Obj->String.Pointer, "W1N", 3) == 0)) {
  687                         model->wled_set = "WLED";
  688                         goto good;
  689                 }
  690 
  691                 /* M5N and S5N are like xxN without MLED */
  692                 else if (strncmp(model->name, "xxN", 3) == 0 &&
  693                     (strncmp(Obj->String.Pointer, "M5N", 3) == 0 ||
  694                      strncmp(Obj->String.Pointer, "S5N", 3) == 0)) {
  695                         model->mled_set = NULL;
  696                         goto good;
  697                 }
  698         }
  699 
  700         sbuf_printf(sb, "Unsupported Asus laptop: %s\n", Obj->String.Pointer);
  701         sbuf_finish(sb);
  702 
  703         device_printf(dev, "%s", sbuf_data(sb));
  704 
  705         sbuf_delete(sb);
  706         AcpiOsFree(Buf.Pointer);
  707 
  708         return (ENXIO);
  709 }
  710 
  711 static int
  712 acpi_asus_attach(device_t dev)
  713 {
  714         struct acpi_asus_softc  *sc;
  715         struct acpi_softc       *acpi_sc;
  716 
  717         ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
  718 
  719         sc = device_get_softc(dev);
  720         acpi_sc = acpi_device_get_parent_softc(dev);
  721 
  722         /* Build sysctl tree */
  723         sysctl_ctx_init(&sc->sysctl_ctx);
  724         sc->sysctl_tree = SYSCTL_ADD_NODE(&sc->sysctl_ctx,
  725             SYSCTL_CHILDREN(acpi_sc->acpi_sysctl_tree),
  726             OID_AUTO, "asus", CTLFLAG_RD | CTLFLAG_MPSAFE, 0, "");
  727 
  728         /* Hook up nodes */
  729         for (int i = 0; acpi_asus_sysctls[i].name != NULL; i++) {
  730                 if (!acpi_asus_sysctl_init(sc, acpi_asus_sysctls[i].method))
  731                         continue;
  732 
  733                 if (acpi_asus_sysctls[i].flag_anybody != 0) {
  734                         SYSCTL_ADD_PROC(&sc->sysctl_ctx,
  735                             SYSCTL_CHILDREN(sc->sysctl_tree), OID_AUTO,
  736                             acpi_asus_sysctls[i].name,
  737                             CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_ANYBODY |
  738                             CTLFLAG_MPSAFE, sc, i, acpi_asus_sysctl, "I",
  739                             acpi_asus_sysctls[i].description);
  740                 } else {
  741                         SYSCTL_ADD_PROC(&sc->sysctl_ctx,
  742                             SYSCTL_CHILDREN(sc->sysctl_tree), OID_AUTO,
  743                             acpi_asus_sysctls[i].name,
  744                             CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE,
  745                             sc, i, acpi_asus_sysctl, "I",
  746                             acpi_asus_sysctls[i].description);
  747                 }
  748         }
  749 
  750         /* Attach leds */
  751         if (sc->model->bled_set) {
  752                 sc->s_bled.busy = 0;
  753                 sc->s_bled.sc = sc;
  754                 sc->s_bled.type = ACPI_ASUS_LED_BLED;
  755                 sc->s_bled.cdev =
  756                     led_create_state((led_t *)acpi_asus_led, &sc->s_bled,
  757                         "bled", 1);
  758         }
  759 
  760         if (sc->model->dled_set) {
  761                 sc->s_dled.busy = 0;
  762                 sc->s_dled.sc = sc;
  763                 sc->s_dled.type = ACPI_ASUS_LED_DLED;
  764                 sc->s_dled.cdev =
  765                     led_create((led_t *)acpi_asus_led, &sc->s_dled, "dled");
  766         }
  767 
  768         if (sc->model->gled_set) {
  769                 sc->s_gled.busy = 0;
  770                 sc->s_gled.sc = sc;
  771                 sc->s_gled.type = ACPI_ASUS_LED_GLED;
  772                 sc->s_gled.cdev =
  773                     led_create((led_t *)acpi_asus_led, &sc->s_gled, "gled");
  774         }
  775 
  776         if (sc->model->mled_set) {
  777                 sc->s_mled.busy = 0;
  778                 sc->s_mled.sc = sc;
  779                 sc->s_mled.type = ACPI_ASUS_LED_MLED;
  780                 sc->s_mled.cdev =
  781                     led_create((led_t *)acpi_asus_led, &sc->s_mled, "mled");
  782         }
  783 
  784         if (sc->model->tled_set) {
  785                 sc->s_tled.busy = 0;
  786                 sc->s_tled.sc = sc;
  787                 sc->s_tled.type = ACPI_ASUS_LED_TLED;
  788                 sc->s_tled.cdev =
  789                     led_create_state((led_t *)acpi_asus_led, &sc->s_tled,
  790                         "tled", 1);
  791         }
  792 
  793         if (sc->model->wled_set) {
  794                 sc->s_wled.busy = 0;
  795                 sc->s_wled.sc = sc;
  796                 sc->s_wled.type = ACPI_ASUS_LED_WLED;
  797                 sc->s_wled.cdev =
  798                     led_create_state((led_t *)acpi_asus_led, &sc->s_wled,
  799                         "wled", 1);
  800         }
  801 
  802         /* Activate hotkeys */
  803         AcpiEvaluateObject(sc->handle, "BSTS", NULL, NULL);
  804 
  805         /* Handle notifies */
  806         if (sc->model->n_func == NULL)
  807                 sc->model->n_func = acpi_asus_notify;
  808 
  809         AcpiInstallNotifyHandler(sc->handle, ACPI_SYSTEM_NOTIFY,
  810             sc->model->n_func, dev);
  811 
  812         /* Find and hook the 'LCDD' object */
  813         if (sc->model->lcdd != NULL && sc->model->lcdd_n_func != NULL) {
  814                 ACPI_STATUS res;
  815 
  816                 sc->lcdd_handle = NULL;
  817                 res = AcpiGetHandle((sc->model->lcdd[0] == '\\' ?
  818                     NULL : sc->handle), sc->model->lcdd, &(sc->lcdd_handle));
  819                 if (ACPI_SUCCESS(res)) {
  820                         AcpiInstallNotifyHandler((sc->lcdd_handle),
  821                             ACPI_DEVICE_NOTIFY, sc->model->lcdd_n_func, dev);
  822                 } else {
  823                         printf("%s: unable to find LCD device '%s'\n",
  824                             __func__, sc->model->lcdd);
  825                 }
  826         }
  827 
  828         return (0);
  829 }
  830 
  831 static int
  832 acpi_asus_detach(device_t dev)
  833 {
  834         struct acpi_asus_softc  *sc;
  835 
  836         ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
  837 
  838         sc = device_get_softc(dev);
  839 
  840         /* Turn the lights off */
  841         if (sc->model->bled_set)
  842                 led_destroy(sc->s_bled.cdev);
  843 
  844         if (sc->model->dled_set)
  845                 led_destroy(sc->s_dled.cdev);
  846 
  847         if (sc->model->gled_set)
  848                 led_destroy(sc->s_gled.cdev);
  849 
  850         if (sc->model->mled_set)
  851                 led_destroy(sc->s_mled.cdev);
  852 
  853         if (sc->model->tled_set)
  854                 led_destroy(sc->s_tled.cdev);
  855 
  856         if (sc->model->wled_set)
  857                 led_destroy(sc->s_wled.cdev);
  858 
  859         /* Remove notify handler */
  860         AcpiRemoveNotifyHandler(sc->handle, ACPI_SYSTEM_NOTIFY,
  861             acpi_asus_notify);
  862 
  863         if (sc->lcdd_handle) {
  864                 KASSERT(sc->model->lcdd_n_func != NULL,
  865                     ("model->lcdd_n_func is NULL, but lcdd_handle is non-zero"));
  866                 AcpiRemoveNotifyHandler((sc->lcdd_handle),
  867                     ACPI_DEVICE_NOTIFY, sc->model->lcdd_n_func);
  868         }
  869 
  870         /* Free sysctl tree */
  871         sysctl_ctx_free(&sc->sysctl_ctx);
  872 
  873         return (0);
  874 }
  875 
  876 static void
  877 acpi_asus_led_task(struct acpi_asus_led *led, int pending __unused)
  878 {
  879         struct acpi_asus_softc  *sc;
  880         char                    *method;
  881         int                     state;
  882 
  883         ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
  884 
  885         sc = led->sc;
  886 
  887         switch (led->type) {
  888         case ACPI_ASUS_LED_BLED:
  889                 method = sc->model->bled_set;
  890                 state = led->state;
  891                 break;
  892         case ACPI_ASUS_LED_DLED:
  893                 method = sc->model->dled_set;
  894                 state = led->state;
  895                 break;
  896         case ACPI_ASUS_LED_GLED:
  897                 method = sc->model->gled_set;
  898                 state = led->state + 1; /* 1: off, 2: on */
  899                 break;
  900         case ACPI_ASUS_LED_MLED:
  901                 method = sc->model->mled_set;
  902                 state = !led->state;    /* inverted */
  903                 break;
  904         case ACPI_ASUS_LED_TLED:
  905                 method = sc->model->tled_set;
  906                 state = led->state;
  907                 break;
  908         case ACPI_ASUS_LED_WLED:
  909                 method = sc->model->wled_set;
  910                 state = led->state;
  911                 break;
  912         default:
  913                 printf("acpi_asus_led: invalid LED type %d\n",
  914                     (int)led->type);
  915                 return;
  916         }
  917 
  918         acpi_SetInteger(sc->handle, method, state);
  919         led->busy = 0;
  920 }
  921 
  922 static void
  923 acpi_asus_led(struct acpi_asus_led *led, int state)
  924 {
  925 
  926         ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
  927 
  928         if (led->busy)
  929                 return;
  930 
  931         led->busy = 1;
  932         led->state = state;
  933 
  934         AcpiOsExecute(OSL_NOTIFY_HANDLER, (void *)acpi_asus_led_task, led);
  935 }
  936 
  937 static int
  938 acpi_asus_sysctl(SYSCTL_HANDLER_ARGS)
  939 {
  940         struct acpi_asus_softc  *sc;
  941         int                     arg;
  942         int                     error = 0;
  943         int                     function;
  944         int                     method;
  945 
  946         ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
  947 
  948         sc = (struct acpi_asus_softc *)oidp->oid_arg1;
  949         function = oidp->oid_arg2;
  950         method = acpi_asus_sysctls[function].method;
  951 
  952         ACPI_SERIAL_BEGIN(asus);
  953         arg = acpi_asus_sysctl_get(sc, method);
  954         error = sysctl_handle_int(oidp, &arg, 0, req);
  955 
  956         /* Sanity check */
  957         if (error != 0 || req->newptr == NULL)
  958                 goto out;
  959 
  960         /* Update */
  961         error = acpi_asus_sysctl_set(sc, method, arg);
  962 
  963 out:
  964         ACPI_SERIAL_END(asus);
  965         return (error);
  966 }
  967 
  968 static int
  969 acpi_asus_sysctl_get(struct acpi_asus_softc *sc, int method)
  970 {
  971         int val = 0;
  972 
  973         ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
  974         ACPI_SERIAL_ASSERT(asus);
  975 
  976         switch (method) {
  977         case ACPI_ASUS_METHOD_BRN:
  978                 val = sc->s_brn;
  979                 break;
  980         case ACPI_ASUS_METHOD_DISP:
  981                 val = sc->s_disp;
  982                 break;
  983         case ACPI_ASUS_METHOD_LCD:
  984                 val = sc->s_lcd;
  985                 break;
  986         case ACPI_ASUS_METHOD_CAMERA:
  987                 val = sc->s_cam;
  988                 break;
  989         case ACPI_ASUS_METHOD_CARDRD:
  990                 val = sc->s_crd;
  991                 break;
  992         case ACPI_ASUS_METHOD_WLAN:
  993                 val = sc->s_wlan;
  994                 break;
  995         }
  996 
  997         return (val);
  998 }
  999 
 1000 static int
 1001 acpi_asus_sysctl_set(struct acpi_asus_softc *sc, int method, int arg)
 1002 {
 1003         ACPI_STATUS             status = AE_OK;
 1004         ACPI_OBJECT_LIST        acpiargs;
 1005         ACPI_OBJECT             acpiarg[1];
 1006 
 1007         ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
 1008         ACPI_SERIAL_ASSERT(asus);
 1009 
 1010         acpiargs.Count = 1;
 1011         acpiargs.Pointer = acpiarg;
 1012         acpiarg[0].Type = ACPI_TYPE_INTEGER;
 1013         acpiarg[0].Integer.Value = arg;
 1014 
 1015         switch (method) {
 1016         case ACPI_ASUS_METHOD_BRN:
 1017                 if (arg < 0 || arg > 15)
 1018                         return (EINVAL);
 1019 
 1020                 if (sc->model->brn_set)
 1021                         status = acpi_SetInteger(sc->handle,
 1022                             sc->model->brn_set, arg);
 1023                 else {
 1024                         while (arg != 0) {
 1025                                 status = AcpiEvaluateObject(sc->handle,
 1026                                     (arg > 0) ?  sc->model->brn_up :
 1027                                     sc->model->brn_dn, NULL, NULL);
 1028                                 (arg > 0) ? arg-- : arg++;
 1029                         }
 1030                 }
 1031 
 1032                 if (ACPI_SUCCESS(status))
 1033                         sc->s_brn = arg;
 1034 
 1035                 break;
 1036         case ACPI_ASUS_METHOD_DISP:
 1037                 if (arg < 0 || arg > 7)
 1038                         return (EINVAL);
 1039 
 1040                 status = acpi_SetInteger(sc->handle,
 1041                     sc->model->disp_set, arg);
 1042 
 1043                 if (ACPI_SUCCESS(status))
 1044                         sc->s_disp = arg;
 1045 
 1046                 break;
 1047         case ACPI_ASUS_METHOD_LCD:
 1048                 if (arg < 0 || arg > 1)
 1049                         return (EINVAL);
 1050 
 1051                 if (strncmp(sc->model->name, "L3H", 3) != 0)
 1052                         status = AcpiEvaluateObject(sc->handle,
 1053                             sc->model->lcd_set, NULL, NULL);
 1054                 else
 1055                         status = acpi_SetInteger(sc->handle,
 1056                             sc->model->lcd_set, 0x7);
 1057 
 1058                 if (ACPI_SUCCESS(status))
 1059                         sc->s_lcd = arg;
 1060 
 1061                 break;
 1062         case ACPI_ASUS_METHOD_CAMERA:
 1063                 if (arg < 0 || arg > 1)
 1064                         return (EINVAL);
 1065 
 1066                 status = AcpiEvaluateObject(sc->handle,
 1067                     sc->model->cam_set, &acpiargs, NULL);
 1068 
 1069                 if (ACPI_SUCCESS(status))
 1070                         sc->s_cam = arg;
 1071                 break;
 1072         case ACPI_ASUS_METHOD_CARDRD:
 1073                 if (arg < 0 || arg > 1)
 1074                         return (EINVAL);
 1075 
 1076                 status = AcpiEvaluateObject(sc->handle,
 1077                     sc->model->crd_set, &acpiargs, NULL);
 1078 
 1079                 if (ACPI_SUCCESS(status))
 1080                         sc->s_crd = arg;
 1081                 break;
 1082         case ACPI_ASUS_METHOD_WLAN:
 1083                 if (arg < 0 || arg > 1)
 1084                         return (EINVAL);
 1085 
 1086                 status = AcpiEvaluateObject(sc->handle,
 1087                     sc->model->wlan_set, &acpiargs, NULL);
 1088 
 1089                 if (ACPI_SUCCESS(status))
 1090                         sc->s_wlan = arg;
 1091                 break;
 1092         }
 1093 
 1094         return (0);
 1095 }
 1096 
 1097 static int
 1098 acpi_asus_sysctl_init(struct acpi_asus_softc *sc, int method)
 1099 {
 1100         ACPI_STATUS     status;
 1101 
 1102         switch (method) {
 1103         case ACPI_ASUS_METHOD_BRN:
 1104                 if (sc->model->brn_get) {
 1105                         /* GPLV/SPLV models */
 1106                         status = acpi_GetInteger(sc->handle,
 1107                             sc->model->brn_get, &sc->s_brn);
 1108                         if (ACPI_SUCCESS(status))
 1109                                 return (TRUE);
 1110                 } else if (sc->model->brn_up) {
 1111                         /* Relative models */
 1112                         status = AcpiEvaluateObject(sc->handle,
 1113                             sc->model->brn_up, NULL, NULL);
 1114                         if (ACPI_FAILURE(status))
 1115                                 return (FALSE);
 1116 
 1117                         status = AcpiEvaluateObject(sc->handle,
 1118                             sc->model->brn_dn, NULL, NULL);
 1119                         if (ACPI_FAILURE(status))
 1120                                 return (FALSE);
 1121 
 1122                         return (TRUE);
 1123                 }
 1124                 return (FALSE);
 1125         case ACPI_ASUS_METHOD_DISP:
 1126                 if (sc->model->disp_get) {
 1127                         status = acpi_GetInteger(sc->handle,
 1128                             sc->model->disp_get, &sc->s_disp);
 1129                         if (ACPI_SUCCESS(status))
 1130                                 return (TRUE);
 1131                 }
 1132                 return (FALSE);
 1133         case ACPI_ASUS_METHOD_LCD:
 1134                 if (sc->model->lcd_get) {
 1135                         if (strncmp(sc->model->name, "L3H", 3) == 0) {
 1136                                 ACPI_BUFFER             Buf;
 1137                                 ACPI_OBJECT             Arg[2], Obj;
 1138                                 ACPI_OBJECT_LIST        Args;
 1139 
 1140                                 /* L3H is a bit special */
 1141                                 Arg[0].Type = ACPI_TYPE_INTEGER;
 1142                                 Arg[0].Integer.Value = 0x02;
 1143                                 Arg[1].Type = ACPI_TYPE_INTEGER;
 1144                                 Arg[1].Integer.Value = 0x03;
 1145 
 1146                                 Args.Count = 2;
 1147                                 Args.Pointer = Arg;
 1148 
 1149                                 Buf.Length = sizeof(Obj);
 1150                                 Buf.Pointer = &Obj;
 1151 
 1152                                 status = AcpiEvaluateObject(sc->handle,
 1153                                     sc->model->lcd_get, &Args, &Buf);
 1154                                 if (ACPI_SUCCESS(status) &&
 1155                                     Obj.Type == ACPI_TYPE_INTEGER) {
 1156                                         sc->s_lcd = Obj.Integer.Value >> 8;
 1157                                         return (TRUE);
 1158                                 }
 1159                         } else {
 1160                                 status = acpi_GetInteger(sc->handle,
 1161                                     sc->model->lcd_get, &sc->s_lcd);
 1162                                 if (ACPI_SUCCESS(status))
 1163                                         return (TRUE);
 1164                         }
 1165                 }
 1166                 return (FALSE);
 1167         case ACPI_ASUS_METHOD_CAMERA:
 1168                 if (sc->model->cam_get) {
 1169                         status = acpi_GetInteger(sc->handle,
 1170                             sc->model->cam_get, &sc->s_cam);
 1171                         if (ACPI_SUCCESS(status))
 1172                                 return (TRUE);
 1173                 }
 1174                 return (FALSE);
 1175         case ACPI_ASUS_METHOD_CARDRD:
 1176                 if (sc->model->crd_get) {
 1177                         status = acpi_GetInteger(sc->handle,
 1178                             sc->model->crd_get, &sc->s_crd);
 1179                         if (ACPI_SUCCESS(status))
 1180                                 return (TRUE);
 1181                 }
 1182                 return (FALSE);
 1183         case ACPI_ASUS_METHOD_WLAN:
 1184                 if (sc->model->wlan_get) {
 1185                         status = acpi_GetInteger(sc->handle,
 1186                             sc->model->wlan_get, &sc->s_wlan);
 1187                         if (ACPI_SUCCESS(status))
 1188                                 return (TRUE);
 1189                 }
 1190                 return (FALSE);
 1191         }
 1192         return (FALSE);
 1193 }
 1194 
 1195 static void
 1196 acpi_asus_notify(ACPI_HANDLE h, UINT32 notify, void *context)
 1197 {
 1198         struct acpi_asus_softc  *sc;
 1199         struct acpi_softc       *acpi_sc;
 1200 
 1201         ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
 1202 
 1203         sc = device_get_softc((device_t)context);
 1204         acpi_sc = acpi_device_get_parent_softc(sc->dev);
 1205 
 1206         ACPI_SERIAL_BEGIN(asus);
 1207         if ((notify & ~0x10) <= 15) {
 1208                 sc->s_brn = notify & ~0x10;
 1209                 ACPI_VPRINT(sc->dev, acpi_sc, "Brightness increased\n");
 1210         } else if ((notify & ~0x20) <= 15) {
 1211                 sc->s_brn = notify & ~0x20;
 1212                 ACPI_VPRINT(sc->dev, acpi_sc, "Brightness decreased\n");
 1213         } else if (notify == 0x33) {
 1214                 sc->s_lcd = 1;
 1215                 ACPI_VPRINT(sc->dev, acpi_sc, "LCD turned on\n");
 1216         } else if (notify == 0x34) {
 1217                 sc->s_lcd = 0;
 1218                 ACPI_VPRINT(sc->dev, acpi_sc, "LCD turned off\n");
 1219         } else if (notify == 0x86) {
 1220                 acpi_asus_sysctl_set(sc, ACPI_ASUS_METHOD_BRN, sc->s_brn-1);
 1221                 ACPI_VPRINT(sc->dev, acpi_sc, "Brightness decreased\n");
 1222         } else if (notify == 0x87) {
 1223                 acpi_asus_sysctl_set(sc, ACPI_ASUS_METHOD_BRN, sc->s_brn+1);
 1224                 ACPI_VPRINT(sc->dev, acpi_sc, "Brightness increased\n");
 1225         } else {
 1226                 /* Notify devd(8) */
 1227                 acpi_UserNotify("ASUS", h, notify);
 1228         }
 1229         ACPI_SERIAL_END(asus);
 1230 }
 1231 
 1232 static void
 1233 acpi_asus_lcdd_notify(ACPI_HANDLE h, UINT32 notify, void *context)
 1234 {
 1235         struct acpi_asus_softc  *sc;
 1236         struct acpi_softc       *acpi_sc;
 1237 
 1238         ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
 1239 
 1240         sc = device_get_softc((device_t)context);
 1241         acpi_sc = acpi_device_get_parent_softc(sc->dev);
 1242 
 1243         ACPI_SERIAL_BEGIN(asus);
 1244         switch (notify) {
 1245         case 0x87:
 1246                 acpi_asus_sysctl_set(sc, ACPI_ASUS_METHOD_BRN, sc->s_brn-1);
 1247                 ACPI_VPRINT(sc->dev, acpi_sc, "Brightness decreased\n");
 1248                 break;
 1249         case 0x86:
 1250                 acpi_asus_sysctl_set(sc, ACPI_ASUS_METHOD_BRN, sc->s_brn+1);
 1251                 ACPI_VPRINT(sc->dev, acpi_sc, "Brightness increased\n");
 1252                 break;
 1253         }
 1254         ACPI_SERIAL_END(asus);
 1255 }
 1256 
 1257 static void
 1258 acpi_asus_eeepc_notify(ACPI_HANDLE h, UINT32 notify, void *context)
 1259 {
 1260         struct acpi_asus_softc  *sc;
 1261         struct acpi_softc       *acpi_sc;
 1262 
 1263         ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
 1264 
 1265         sc = device_get_softc((device_t)context);
 1266         acpi_sc = acpi_device_get_parent_softc(sc->dev);
 1267 
 1268         ACPI_SERIAL_BEGIN(asus);
 1269         if ((notify & ~0x20) <= 15) {
 1270                 sc->s_brn = notify & ~0x20;
 1271                 ACPI_VPRINT(sc->dev, acpi_sc,
 1272                     "Brightness increased/decreased\n");
 1273         } else {
 1274                 /* Notify devd(8) */
 1275                 acpi_UserNotify("ASUS-Eee", h, notify);
 1276         }
 1277         ACPI_SERIAL_END(asus);
 1278 }

Cache object: db362b4a9cab9daf0458b02d55d33630


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