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