1 /*- 2 * Copyright (c) 2002 Sean Bullington <seanATstalker.org> 3 * 2003-2006 Anish Mistry <amistry@am-productions.biz> 4 * 2004 Mark Santcroos <marks@ripe.net> 5 * All Rights Reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 * 28 */ 29 30 #include <sys/cdefs.h> 31 __FBSDID("$FreeBSD$"); 32 33 #include "opt_acpi.h" 34 #include <sys/param.h> 35 #include <sys/kernel.h> 36 #include <sys/bus.h> 37 #include <sys/module.h> 38 #include <sys/sysctl.h> 39 40 #include <contrib/dev/acpica/include/acpi.h> 41 #include <contrib/dev/acpica/include/accommon.h> 42 43 #include <dev/acpica/acpivar.h> 44 45 /* Hooks for the ACPI CA debugging infrastructure */ 46 #define _COMPONENT ACPI_OEM 47 ACPI_MODULE_NAME("Fujitsu") 48 49 /* Change and update bits for the hotkeys */ 50 #define VOLUME_MUTE_BIT 0x40000000 51 52 /* Values of settings */ 53 #define GENERAL_SETTING_BITS 0x0fffffff 54 #define MOUSE_SETTING_BITS GENERAL_SETTING_BITS 55 #define VOLUME_SETTING_BITS GENERAL_SETTING_BITS 56 #define BRIGHTNESS_SETTING_BITS GENERAL_SETTING_BITS 57 58 /* Possible state changes */ 59 /* 60 * These are NOT arbitrary values. They are the 61 * GHKS return value from the device that says which 62 * hotkey is active. They should match up with a bit 63 * from the GSIF bitmask. 64 */ 65 #define BRIGHT_CHANGED 0x01 66 #define VOLUME_CHANGED 0x04 67 #define MOUSE_CHANGED 0x08 68 /* 69 * It is unknown which hotkey this bit is supposed to indicate, but 70 * according to values from GSIF this is a valid flag. 71 */ 72 #define UNKNOWN_CHANGED 0x10 73 74 /* sysctl values */ 75 #define FN_MUTE 0 76 #define FN_POINTER_ENABLE 1 77 #define FN_LCD_BRIGHTNESS 2 78 #define FN_VOLUME 3 79 80 /* Methods */ 81 #define METHOD_GBLL 1 82 #define METHOD_GMOU 2 83 #define METHOD_GVOL 3 84 #define METHOD_MUTE 4 85 #define METHOD_RBLL 5 86 #define METHOD_RVOL 6 87 #define METHOD_GSIF 7 88 #define METHOD_GHKS 8 89 90 /* Notify event */ 91 #define ACPI_NOTIFY_STATUS_CHANGED 0x80 92 93 /* 94 * Holds a control method name and its associated integer value. 95 * Only used for no-argument control methods which return a value. 96 */ 97 struct int_nameval { 98 char *name; 99 int value; 100 int exists; 101 }; 102 103 /* 104 * Driver extension for the FUJITSU ACPI driver. 105 */ 106 struct acpi_fujitsu_softc { 107 device_t dev; 108 ACPI_HANDLE handle; 109 110 /* Control methods */ 111 struct int_nameval _sta, /* unused */ 112 gbll, /* brightness */ 113 ghks, /* hotkey selector */ 114 gbuf, /* unused (buffer?) */ 115 gmou, /* mouse */ 116 gsif, /* function key bitmask */ 117 gvol, /* volume */ 118 rbll, /* number of brightness levels (radix) */ 119 rvol; /* number of volume levels (radix) */ 120 121 /* State variables */ 122 uint8_t bIsMuted; /* Is volume muted */ 123 uint8_t bIntPtrEnabled; /* Is internal ptr enabled */ 124 uint32_t lastValChanged; /* The last value updated */ 125 126 /* sysctl tree */ 127 struct sysctl_ctx_list sysctl_ctx; 128 struct sysctl_oid *sysctl_tree; 129 }; 130 131 /* Driver entry point forward declarations. */ 132 static int acpi_fujitsu_probe(device_t dev); 133 static int acpi_fujitsu_attach(device_t dev); 134 static int acpi_fujitsu_detach(device_t dev); 135 static int acpi_fujitsu_suspend(device_t dev); 136 static int acpi_fujitsu_resume(device_t dev); 137 138 static void acpi_fujitsu_notify_status_changed(void *arg); 139 static void acpi_fujitsu_notify_handler(ACPI_HANDLE h, uint32_t notify, void *context); 140 static int acpi_fujitsu_sysctl(SYSCTL_HANDLER_ARGS); 141 142 /* Utility function declarations */ 143 static uint8_t acpi_fujitsu_update(struct acpi_fujitsu_softc *sc); 144 static uint8_t acpi_fujitsu_init(struct acpi_fujitsu_softc *sc); 145 static uint8_t acpi_fujitsu_check_hardware(struct acpi_fujitsu_softc *sc); 146 147 /* Driver/Module specific structure definitions. */ 148 static device_method_t acpi_fujitsu_methods[] = { 149 /* Device interface */ 150 DEVMETHOD(device_probe, acpi_fujitsu_probe), 151 DEVMETHOD(device_attach, acpi_fujitsu_attach), 152 DEVMETHOD(device_detach, acpi_fujitsu_detach), 153 DEVMETHOD(device_suspend, acpi_fujitsu_suspend), 154 DEVMETHOD(device_resume, acpi_fujitsu_resume), 155 {0, 0} 156 }; 157 158 static driver_t acpi_fujitsu_driver = { 159 "acpi_fujitsu", 160 acpi_fujitsu_methods, 161 sizeof(struct acpi_fujitsu_softc), 162 }; 163 164 /* Prototype for function hotkeys for getting/setting a value. */ 165 static int acpi_fujitsu_method_get(struct acpi_fujitsu_softc *sc, int method); 166 static int acpi_fujitsu_method_set(struct acpi_fujitsu_softc *sc, int method, int value); 167 168 static char *fujitsu_ids[] = { "FUJ02B1", NULL }; 169 170 ACPI_SERIAL_DECL(fujitsu, "Fujitsu Function Hotkeys"); 171 172 /* sysctl names and function calls */ 173 static struct { 174 char *name; 175 int method; 176 char *description; 177 } sysctl_table[] = { 178 { 179 .name = "mute", 180 .method = METHOD_MUTE, 181 .description = "Speakers/headphones mute status" 182 }, 183 { 184 .name = "pointer_enable", 185 .method = METHOD_GMOU, 186 .description = "Enable and disable the internal pointer" 187 }, 188 { 189 .name = "lcd_brightness", 190 .method = METHOD_GBLL, 191 .description = "Brightness level of the LCD panel" 192 }, 193 { 194 .name = "volume", 195 .method = METHOD_GVOL, 196 .description = "Speakers/headphones volume level" 197 }, 198 { 199 .name = "volume_radix", 200 .method = METHOD_RVOL, 201 .description = "Number of volume level steps" 202 }, 203 { 204 .name = "lcd_brightness_radix", 205 .method = METHOD_RBLL, 206 .description = "Number of brightness level steps" 207 }, 208 209 { NULL, 0, NULL } 210 }; 211 212 static devclass_t acpi_fujitsu_devclass; 213 DRIVER_MODULE(acpi_fujitsu, acpi, acpi_fujitsu_driver, 214 acpi_fujitsu_devclass, 0, 0); 215 MODULE_DEPEND(acpi_fujitsu, acpi, 1, 1, 1); 216 MODULE_VERSION(acpi_fujitsu, 1); 217 218 static int 219 acpi_fujitsu_probe(device_t dev) 220 { 221 char *name; 222 char buffer[64]; 223 224 name = ACPI_ID_PROBE(device_get_parent(dev), dev, fujitsu_ids); 225 if (acpi_disabled("fujitsu") || name == NULL || 226 device_get_unit(dev) > 1) 227 return (ENXIO); 228 229 sprintf(buffer, "Fujitsu Function Hotkeys %s", name); 230 device_set_desc_copy(dev, buffer); 231 232 return (0); 233 } 234 235 static int 236 acpi_fujitsu_attach(device_t dev) 237 { 238 struct acpi_fujitsu_softc *sc; 239 240 ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); 241 242 sc = device_get_softc(dev); 243 sc->dev = dev; 244 sc->handle = acpi_get_handle(dev); 245 246 /* Install notification handler */ 247 AcpiInstallNotifyHandler(sc->handle, ACPI_DEVICE_NOTIFY, 248 acpi_fujitsu_notify_handler, sc); 249 250 /* Snag our default values for the hotkeys / hotkey states. */ 251 ACPI_SERIAL_BEGIN(fujitsu); 252 if (!acpi_fujitsu_init(sc)) 253 device_printf(dev, "Couldn't initialize hotkey states!\n"); 254 ACPI_SERIAL_END(fujitsu); 255 256 return (0); 257 } 258 259 /* 260 * Called when the system is being suspended, simply 261 * set an event to be signalled when we wake up. 262 */ 263 static int 264 acpi_fujitsu_suspend(device_t dev) 265 { 266 267 return (0); 268 } 269 270 static int 271 acpi_fujitsu_resume(device_t dev) 272 { 273 struct acpi_fujitsu_softc *sc; 274 ACPI_STATUS status; 275 276 sc = device_get_softc(dev); 277 278 /* 279 * The pointer needs to be re-enabled for 280 * some revisions of the P series (2120). 281 */ 282 ACPI_SERIAL_BEGIN(fujitsu); 283 284 if(sc->gmou.exists) { 285 status = acpi_SetInteger(sc->handle, "SMOU", 1); 286 if (ACPI_FAILURE(status)) 287 device_printf(sc->dev, "Couldn't enable pointer\n"); 288 } 289 ACPI_SERIAL_END(fujitsu); 290 291 return (0); 292 } 293 294 static void 295 acpi_fujitsu_notify_status_changed(void *arg) 296 { 297 struct acpi_fujitsu_softc *sc; 298 299 ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); 300 301 sc = (struct acpi_fujitsu_softc *)arg; 302 303 /* 304 * Since our notify function is called, we know something has 305 * happened. So the only reason for acpi_fujitsu_update to fail 306 * is if we can't find what has changed or an error occurs. 307 */ 308 ACPI_SERIAL_BEGIN(fujitsu); 309 acpi_fujitsu_update(sc); 310 ACPI_SERIAL_END(fujitsu); 311 } 312 313 314 static void 315 acpi_fujitsu_notify_handler(ACPI_HANDLE h, uint32_t notify, void *context) 316 { 317 struct acpi_fujitsu_softc *sc; 318 319 ACPI_FUNCTION_TRACE_U32((char *)(uintptr_t)__func__, notify); 320 321 sc = (struct acpi_fujitsu_softc *)context; 322 323 switch (notify) { 324 case ACPI_NOTIFY_STATUS_CHANGED: 325 AcpiOsExecute(OSL_NOTIFY_HANDLER, 326 acpi_fujitsu_notify_status_changed, sc); 327 break; 328 default: 329 /* unknown notification value */ 330 break; 331 } 332 } 333 334 static int 335 acpi_fujitsu_detach(device_t dev) 336 { 337 struct acpi_fujitsu_softc *sc; 338 339 sc = device_get_softc(dev); 340 AcpiRemoveNotifyHandler(sc->handle, ACPI_DEVICE_NOTIFY, 341 acpi_fujitsu_notify_handler); 342 343 sysctl_ctx_free(&sc->sysctl_ctx); 344 345 return (0); 346 } 347 348 /* 349 * Initializes the names of the ACPI control methods and grabs 350 * the current state of all of the ACPI hotkeys into the softc. 351 */ 352 static uint8_t 353 acpi_fujitsu_init(struct acpi_fujitsu_softc *sc) 354 { 355 struct acpi_softc *acpi_sc; 356 int i, exists; 357 358 ACPI_SERIAL_ASSERT(fujitsu); 359 360 /* Setup all of the names for each control method */ 361 sc->_sta.name = "_STA"; 362 sc->gbll.name = "GBLL"; 363 sc->ghks.name = "GHKS"; 364 sc->gmou.name = "GMOU"; 365 sc->gsif.name = "GSIF"; 366 sc->gvol.name = "GVOL"; 367 sc->ghks.name = "GHKS"; 368 sc->gsif.name = "GSIF"; 369 sc->rbll.name = "RBLL"; 370 sc->rvol.name = "RVOL"; 371 372 /* Determine what hardware functionality is available */ 373 acpi_fujitsu_check_hardware(sc); 374 375 /* Build the sysctl tree */ 376 acpi_sc = acpi_device_get_parent_softc(sc->dev); 377 sysctl_ctx_init(&sc->sysctl_ctx); 378 sc->sysctl_tree = SYSCTL_ADD_NODE(&sc->sysctl_ctx, 379 SYSCTL_CHILDREN(acpi_sc->acpi_sysctl_tree), 380 OID_AUTO, "fujitsu", CTLFLAG_RD, 0, ""); 381 382 for (i = 0; sysctl_table[i].name != NULL; i++) { 383 exists = 0; 384 switch(sysctl_table[i].method) { 385 case METHOD_GMOU: 386 exists = sc->gmou.exists; 387 break; 388 case METHOD_GBLL: 389 exists = sc->gbll.exists; 390 break; 391 case METHOD_GVOL: 392 case METHOD_MUTE: 393 exists = sc->gvol.exists; 394 break; 395 case METHOD_RVOL: 396 exists = sc->rvol.exists; 397 break; 398 case METHOD_RBLL: 399 exists = sc->rbll.exists; 400 break; 401 default: 402 /* Allow by default */ 403 exists = 1; 404 break; 405 } 406 if(!exists) 407 continue; 408 SYSCTL_ADD_PROC(&sc->sysctl_ctx, 409 SYSCTL_CHILDREN(sc->sysctl_tree), OID_AUTO, 410 sysctl_table[i].name, 411 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_ANYBODY, 412 sc, i, acpi_fujitsu_sysctl, "I", 413 sysctl_table[i].description); 414 } 415 416 417 /* Set the hotkeys to their initial states */ 418 if (!acpi_fujitsu_update(sc)) { 419 device_printf(sc->dev, "Couldn't init hotkey states\n"); 420 return (FALSE); 421 } 422 423 return (TRUE); 424 } 425 426 static int 427 acpi_fujitsu_sysctl(SYSCTL_HANDLER_ARGS) 428 { 429 struct acpi_fujitsu_softc *sc; 430 int method; 431 int arg; 432 int function_num, error = 0; 433 434 sc = (struct acpi_fujitsu_softc *)oidp->oid_arg1; 435 function_num = oidp->oid_arg2; 436 method = sysctl_table[function_num].method; 437 438 ACPI_SERIAL_BEGIN(fujitsu); 439 440 /* Get the current value */ 441 arg = acpi_fujitsu_method_get(sc, method); 442 error = sysctl_handle_int(oidp, &arg, 0, req); 443 444 if (error != 0 || req->newptr == NULL) 445 goto out; 446 447 /* Update the value */ 448 error = acpi_fujitsu_method_set(sc, method, arg); 449 450 out: 451 ACPI_SERIAL_END(fujitsu); 452 return (error); 453 } 454 455 static int 456 acpi_fujitsu_method_get(struct acpi_fujitsu_softc *sc, int method) 457 { 458 struct int_nameval nv; 459 ACPI_STATUS status; 460 461 ACPI_SERIAL_ASSERT(fujitsu); 462 463 switch (method) { 464 case METHOD_GBLL: 465 nv = sc->gbll; 466 break; 467 case METHOD_GMOU: 468 nv = sc->gmou; 469 break; 470 case METHOD_GVOL: 471 case METHOD_MUTE: 472 nv = sc->gvol; 473 break; 474 case METHOD_GHKS: 475 nv = sc->ghks; 476 break; 477 case METHOD_GSIF: 478 nv = sc->gsif; 479 break; 480 case METHOD_RBLL: 481 nv = sc->rbll; 482 break; 483 case METHOD_RVOL: 484 nv = sc->rvol; 485 break; 486 default: 487 return (FALSE); 488 } 489 490 if(!nv.exists) 491 return (EINVAL); 492 493 status = acpi_GetInteger(sc->handle, nv.name, &nv.value); 494 if (ACPI_FAILURE(status)) { 495 device_printf(sc->dev, "Couldn't query method (%s)\n", nv.name); 496 return (FALSE); 497 } 498 499 if (method == METHOD_MUTE) { 500 sc->bIsMuted = (uint8_t)((nv.value & VOLUME_MUTE_BIT) != 0); 501 return (sc->bIsMuted); 502 } 503 504 nv.value &= GENERAL_SETTING_BITS; 505 return (nv.value); 506 } 507 508 static int 509 acpi_fujitsu_method_set(struct acpi_fujitsu_softc *sc, int method, int value) 510 { 511 struct int_nameval nv; 512 ACPI_STATUS status; 513 char *control; 514 int changed; 515 516 ACPI_SERIAL_ASSERT(fujitsu); 517 518 switch (method) { 519 case METHOD_GBLL: 520 changed = BRIGHT_CHANGED; 521 control = "SBLL"; 522 nv = sc->gbll; 523 break; 524 case METHOD_GMOU: 525 changed = MOUSE_CHANGED; 526 control = "SMOU"; 527 nv = sc->gmou; 528 break; 529 case METHOD_GVOL: 530 case METHOD_MUTE: 531 changed = VOLUME_CHANGED; 532 control = "SVOL"; 533 nv = sc->gvol; 534 break; 535 default: 536 return (EINVAL); 537 } 538 539 if(!nv.exists) 540 return (EINVAL); 541 542 if (method == METHOD_MUTE) { 543 if (value == 1) 544 value = nv.value | VOLUME_MUTE_BIT; 545 else if (value == 0) 546 value = nv.value & ~VOLUME_MUTE_BIT; 547 else 548 return (EINVAL); 549 } 550 551 status = acpi_SetInteger(sc->handle, control, value); 552 if (ACPI_FAILURE(status)) { 553 device_printf(sc->dev, "Couldn't update %s\n", control); 554 return (FALSE); 555 } 556 557 sc->lastValChanged = changed; 558 return (0); 559 } 560 561 /* 562 * Query the get methods to determine what functionality is available 563 * from the hardware function hotkeys. 564 */ 565 static uint8_t 566 acpi_fujitsu_check_hardware(struct acpi_fujitsu_softc *sc) 567 { 568 int val; 569 struct acpi_softc *acpi_sc; 570 571 acpi_sc = acpi_device_get_parent_softc(sc->dev); 572 573 ACPI_SERIAL_ASSERT(fujitsu); 574 /* save the hotkey bitmask */ 575 if (ACPI_FAILURE(acpi_GetInteger(sc->handle, 576 sc->gsif.name, &(sc->gsif.value)))) { 577 sc->gsif.exists = 0; 578 device_printf(sc->dev, "Couldn't query bitmask value\n"); 579 } else { 580 sc->gsif.exists = 1; 581 } 582 583 /* System Volume Level */ 584 if (ACPI_FAILURE(acpi_GetInteger(sc->handle, 585 sc->gvol.name, &val))) { 586 sc->gvol.exists = 0; 587 } else { 588 sc->gvol.exists = 1; 589 } 590 591 if (ACPI_FAILURE(acpi_GetInteger(sc->handle, 592 sc->gbll.name, &val))) { 593 sc->gbll.exists = 0; 594 } else { 595 sc->gbll.exists = 1; 596 } 597 598 if (ACPI_FAILURE(acpi_GetInteger(sc->handle, 599 sc->ghks.name, &val))) { 600 sc->ghks.exists = 0; 601 } else { 602 sc->ghks.exists = 1; 603 } 604 605 if (ACPI_FAILURE(acpi_GetInteger(sc->handle, 606 sc->gmou.name, &val))) { 607 sc->gmou.exists = 0; 608 } else { 609 sc->gmou.exists = 1; 610 } 611 612 if (ACPI_FAILURE(acpi_GetInteger(sc->handle, 613 sc->rbll.name, &val))) { 614 sc->rbll.exists = 0; 615 } else { 616 sc->rbll.exists = 1; 617 } 618 619 if (ACPI_FAILURE(acpi_GetInteger(sc->handle, 620 sc->rvol.name, &val))) { 621 sc->rvol.exists = 0; 622 } else { 623 sc->rvol.exists = 1; 624 } 625 626 return (TRUE); 627 } 628 629 /* 630 * Query each of the ACPI control methods that contain information we're 631 * interested in. We check the return values from the control methods and 632 * adjust any state variables if they should be adjusted. 633 */ 634 static uint8_t 635 acpi_fujitsu_update(struct acpi_fujitsu_softc *sc) 636 { 637 int changed; 638 struct acpi_softc *acpi_sc; 639 640 acpi_sc = acpi_device_get_parent_softc(sc->dev); 641 642 ACPI_SERIAL_ASSERT(fujitsu); 643 if(sc->gsif.exists) 644 changed = sc->gsif.value & acpi_fujitsu_method_get(sc,METHOD_GHKS); 645 else 646 changed = 0; 647 648 /* System Volume Level */ 649 if(sc->gvol.exists) { 650 if (ACPI_FAILURE(acpi_GetInteger(sc->handle, 651 sc->gvol.name, &(sc->gvol.value)))) { 652 device_printf(sc->dev, "Couldn't query volume level\n"); 653 return (FALSE); 654 } 655 656 if (changed & VOLUME_CHANGED) { 657 sc->bIsMuted = 658 (uint8_t)((sc->gvol.value & VOLUME_MUTE_BIT) != 0); 659 660 /* Clear the modification bit */ 661 sc->gvol.value &= VOLUME_SETTING_BITS; 662 663 if (sc->bIsMuted) { 664 acpi_UserNotify("FUJITSU", sc->handle, FN_MUTE); 665 ACPI_VPRINT(sc->dev, acpi_sc, "Volume is now mute\n"); 666 } else 667 ACPI_VPRINT(sc->dev, acpi_sc, "Volume is now %d\n", 668 sc->gvol.value); 669 670 acpi_UserNotify("FUJITSU", sc->handle, FN_VOLUME); 671 } 672 } 673 674 /* Internal mouse pointer (eraserhead) */ 675 if(sc->gmou.exists) { 676 if (ACPI_FAILURE(acpi_GetInteger(sc->handle, 677 sc->gmou.name, &(sc->gmou.value)))) { 678 device_printf(sc->dev, "Couldn't query pointer state\n"); 679 return (FALSE); 680 } 681 682 if (changed & MOUSE_CHANGED) { 683 sc->bIntPtrEnabled = (uint8_t)(sc->gmou.value & 0x1); 684 685 /* Clear the modification bit */ 686 sc->gmou.value &= MOUSE_SETTING_BITS; 687 688 acpi_UserNotify("FUJITSU", sc->handle, FN_POINTER_ENABLE); 689 690 ACPI_VPRINT(sc->dev, acpi_sc, "Internal pointer is now %s\n", 691 (sc->bIntPtrEnabled) ? "enabled" : "disabled"); 692 } 693 } 694 695 /* Screen Brightness Level */ 696 if(sc->gbll.exists) { 697 if (ACPI_FAILURE(acpi_GetInteger(sc->handle, 698 sc->gbll.name, &(sc->gbll.value)))) { 699 device_printf(sc->dev, "Couldn't query brightness level\n"); 700 return (FALSE); 701 } 702 703 if (changed & BRIGHT_CHANGED) { 704 /* No state to record here. */ 705 706 /* Clear the modification bit */ 707 sc->gbll.value &= BRIGHTNESS_SETTING_BITS; 708 709 acpi_UserNotify("FUJITSU", sc->handle, FN_LCD_BRIGHTNESS); 710 711 ACPI_VPRINT(sc->dev, acpi_sc, "Brightness level is now %d\n", 712 sc->gbll.value); 713 } 714 } 715 716 sc->lastValChanged = changed; 717 return (TRUE); 718 } 719