19a8b554fSPhilip Paeps /*- 29a8b554fSPhilip Paeps * Copyright (c) 2002 Sean Bullington <seanATstalker.org> 3b9abb62dSPhilip Paeps * 2003-2006 Anish Mistry <amistry@am-productions.biz> 49a8b554fSPhilip Paeps * 2004 Mark Santcroos <marks@ripe.net> 59a8b554fSPhilip Paeps * All Rights Reserved. 69a8b554fSPhilip Paeps * 79a8b554fSPhilip Paeps * Redistribution and use in source and binary forms, with or without 89a8b554fSPhilip Paeps * modification, are permitted provided that the following conditions 99a8b554fSPhilip Paeps * are met: 109a8b554fSPhilip Paeps * 1. Redistributions of source code must retain the above copyright 119a8b554fSPhilip Paeps * notice, this list of conditions and the following disclaimer. 129a8b554fSPhilip Paeps * 2. Redistributions in binary form must reproduce the above copyright 139a8b554fSPhilip Paeps * notice, this list of conditions and the following disclaimer in the 149a8b554fSPhilip Paeps * documentation and/or other materials provided with the distribution. 159a8b554fSPhilip Paeps * 169a8b554fSPhilip Paeps * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 179a8b554fSPhilip Paeps * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 189a8b554fSPhilip Paeps * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 199a8b554fSPhilip Paeps * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 209a8b554fSPhilip Paeps * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 219a8b554fSPhilip Paeps * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 229a8b554fSPhilip Paeps * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 239a8b554fSPhilip Paeps * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 249a8b554fSPhilip Paeps * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 259a8b554fSPhilip Paeps * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 269a8b554fSPhilip Paeps * SUCH DAMAGE. 279a8b554fSPhilip Paeps * 289a8b554fSPhilip Paeps */ 299a8b554fSPhilip Paeps 309a8b554fSPhilip Paeps #include <sys/cdefs.h> 319a8b554fSPhilip Paeps __FBSDID("$FreeBSD$"); 329a8b554fSPhilip Paeps 339a8b554fSPhilip Paeps #include "opt_acpi.h" 349a8b554fSPhilip Paeps #include <sys/param.h> 359a8b554fSPhilip Paeps #include <sys/kernel.h> 369a8b554fSPhilip Paeps #include <sys/bus.h> 379a8b554fSPhilip Paeps #include <sys/module.h> 389a8b554fSPhilip Paeps #include <sys/sysctl.h> 399a8b554fSPhilip Paeps 402a191126SDavid E. O'Brien #include <contrib/dev/acpica/acpi.h> 419a8b554fSPhilip Paeps #include <dev/acpica/acpivar.h> 429a8b554fSPhilip Paeps 439a8b554fSPhilip Paeps /* Hooks for the ACPI CA debugging infrastructure */ 449a8b554fSPhilip Paeps #define _COMPONENT ACPI_OEM 459a8b554fSPhilip Paeps ACPI_MODULE_NAME("Fujitsu") 469a8b554fSPhilip Paeps 47b9abb62dSPhilip Paeps /* Change and update bits for the hotkeys */ 489a8b554fSPhilip Paeps #define VOLUME_MUTE_BIT 0x40000000 499a8b554fSPhilip Paeps 509a8b554fSPhilip Paeps /* Values of settings */ 519a8b554fSPhilip Paeps #define GENERAL_SETTING_BITS 0x0fffffff 529a8b554fSPhilip Paeps #define MOUSE_SETTING_BITS GENERAL_SETTING_BITS 539a8b554fSPhilip Paeps #define VOLUME_SETTING_BITS GENERAL_SETTING_BITS 549a8b554fSPhilip Paeps #define BRIGHTNESS_SETTING_BITS GENERAL_SETTING_BITS 559a8b554fSPhilip Paeps 569a8b554fSPhilip Paeps /* Possible state changes */ 57b9abb62dSPhilip Paeps /* 58b9abb62dSPhilip Paeps * These are NOT arbitrary values. They are the 59b9abb62dSPhilip Paeps * GHKS return value from the device that says which 60b9abb62dSPhilip Paeps * hotkey is active. They should match up with a bit 61b9abb62dSPhilip Paeps * from the GSIF bitmask. 62b9abb62dSPhilip Paeps */ 63b9abb62dSPhilip Paeps #define BRIGHT_CHANGED 0x01 64b9abb62dSPhilip Paeps #define VOLUME_CHANGED 0x04 65b9abb62dSPhilip Paeps #define MOUSE_CHANGED 0x08 66b9abb62dSPhilip Paeps /* 67b9abb62dSPhilip Paeps * It is unknown which hotkey this bit is supposed to indicate, but 68b9abb62dSPhilip Paeps * according to values from GSIF this is a valid flag. 69b9abb62dSPhilip Paeps */ 70b9abb62dSPhilip Paeps #define UNKNOWN_CHANGED 0x10 719a8b554fSPhilip Paeps 729a8b554fSPhilip Paeps /* sysctl values */ 739a8b554fSPhilip Paeps #define FN_MUTE 0 749a8b554fSPhilip Paeps #define FN_POINTER_ENABLE 1 759a8b554fSPhilip Paeps #define FN_LCD_BRIGHTNESS 2 769a8b554fSPhilip Paeps #define FN_VOLUME 3 779a8b554fSPhilip Paeps 789a8b554fSPhilip Paeps /* Methods */ 799a8b554fSPhilip Paeps #define METHOD_GBLL 1 809a8b554fSPhilip Paeps #define METHOD_GMOU 2 819a8b554fSPhilip Paeps #define METHOD_GVOL 3 829a8b554fSPhilip Paeps #define METHOD_MUTE 4 83b9abb62dSPhilip Paeps #define METHOD_RBLL 5 84b9abb62dSPhilip Paeps #define METHOD_RVOL 6 85b9abb62dSPhilip Paeps #define METHOD_GSIF 7 86b9abb62dSPhilip Paeps #define METHOD_GHKS 8 879a8b554fSPhilip Paeps 889a8b554fSPhilip Paeps /* Notify event */ 899a8b554fSPhilip Paeps #define ACPI_NOTIFY_STATUS_CHANGED 0x80 909a8b554fSPhilip Paeps 919a8b554fSPhilip Paeps /* 929a8b554fSPhilip Paeps * Holds a control method name and its associated integer value. 939a8b554fSPhilip Paeps * Only used for no-argument control methods which return a value. 949a8b554fSPhilip Paeps */ 959a8b554fSPhilip Paeps struct int_nameval { 969a8b554fSPhilip Paeps char *name; 979a8b554fSPhilip Paeps int value; 98b9abb62dSPhilip Paeps int exists; 999a8b554fSPhilip Paeps }; 1009a8b554fSPhilip Paeps 1019a8b554fSPhilip Paeps /* 1029a8b554fSPhilip Paeps * Driver extension for the FUJITSU ACPI driver. 1039a8b554fSPhilip Paeps */ 1049a8b554fSPhilip Paeps struct acpi_fujitsu_softc { 1059a8b554fSPhilip Paeps device_t dev; 1069a8b554fSPhilip Paeps ACPI_HANDLE handle; 1079a8b554fSPhilip Paeps 1089a8b554fSPhilip Paeps /* Control methods */ 1099a8b554fSPhilip Paeps struct int_nameval _sta, /* unused */ 1109a8b554fSPhilip Paeps gbll, /* brightness */ 111b9abb62dSPhilip Paeps ghks, /* hotkey selector */ 112b9abb62dSPhilip Paeps gbuf, /* unused (buffer?) */ 1139a8b554fSPhilip Paeps gmou, /* mouse */ 114b9abb62dSPhilip Paeps gsif, /* function key bitmask */ 1159a8b554fSPhilip Paeps gvol, /* volume */ 116b9abb62dSPhilip Paeps rbll, /* number of brightness levels (radix) */ 117b9abb62dSPhilip Paeps rvol; /* number of volume levels (radix) */ 1189a8b554fSPhilip Paeps 1199a8b554fSPhilip Paeps /* State variables */ 1209a8b554fSPhilip Paeps uint8_t bIsMuted; /* Is volume muted */ 1219a8b554fSPhilip Paeps uint8_t bIntPtrEnabled; /* Is internal ptr enabled */ 1229a8b554fSPhilip Paeps uint32_t lastValChanged; /* The last value updated */ 1239a8b554fSPhilip Paeps 1249a8b554fSPhilip Paeps /* sysctl tree */ 1259a8b554fSPhilip Paeps struct sysctl_ctx_list sysctl_ctx; 1269a8b554fSPhilip Paeps struct sysctl_oid *sysctl_tree; 1279a8b554fSPhilip Paeps }; 1289a8b554fSPhilip Paeps 1299a8b554fSPhilip Paeps /* Driver entry point forward declarations. */ 1309a8b554fSPhilip Paeps static int acpi_fujitsu_probe(device_t dev); 1319a8b554fSPhilip Paeps static int acpi_fujitsu_attach(device_t dev); 1329a8b554fSPhilip Paeps static int acpi_fujitsu_detach(device_t dev); 1339a8b554fSPhilip Paeps static int acpi_fujitsu_suspend(device_t dev); 1349a8b554fSPhilip Paeps static int acpi_fujitsu_resume(device_t dev); 1359a8b554fSPhilip Paeps 1369a8b554fSPhilip Paeps static void acpi_fujitsu_notify_status_changed(void *arg); 1379a8b554fSPhilip Paeps static void acpi_fujitsu_notify_handler(ACPI_HANDLE h, uint32_t notify, void *context); 1389a8b554fSPhilip Paeps static int acpi_fujitsu_sysctl(SYSCTL_HANDLER_ARGS); 1399a8b554fSPhilip Paeps 1409a8b554fSPhilip Paeps /* Utility function declarations */ 1419a8b554fSPhilip Paeps static uint8_t acpi_fujitsu_update(struct acpi_fujitsu_softc *sc); 1429a8b554fSPhilip Paeps static uint8_t acpi_fujitsu_init(struct acpi_fujitsu_softc *sc); 143b9abb62dSPhilip Paeps static uint8_t acpi_fujitsu_check_hardware(struct acpi_fujitsu_softc *sc); 1449a8b554fSPhilip Paeps 1459a8b554fSPhilip Paeps /* Driver/Module specific structure definitions. */ 1469a8b554fSPhilip Paeps static device_method_t acpi_fujitsu_methods[] = { 1479a8b554fSPhilip Paeps /* Device interface */ 1489a8b554fSPhilip Paeps DEVMETHOD(device_probe, acpi_fujitsu_probe), 1499a8b554fSPhilip Paeps DEVMETHOD(device_attach, acpi_fujitsu_attach), 1509a8b554fSPhilip Paeps DEVMETHOD(device_detach, acpi_fujitsu_detach), 1519a8b554fSPhilip Paeps DEVMETHOD(device_suspend, acpi_fujitsu_suspend), 1529a8b554fSPhilip Paeps DEVMETHOD(device_resume, acpi_fujitsu_resume), 1539a8b554fSPhilip Paeps {0, 0} 1549a8b554fSPhilip Paeps }; 1559a8b554fSPhilip Paeps 1569a8b554fSPhilip Paeps static driver_t acpi_fujitsu_driver = { 1579a8b554fSPhilip Paeps "acpi_fujitsu", 1589a8b554fSPhilip Paeps acpi_fujitsu_methods, 1599a8b554fSPhilip Paeps sizeof(struct acpi_fujitsu_softc), 1609a8b554fSPhilip Paeps }; 1619a8b554fSPhilip Paeps 162b9abb62dSPhilip Paeps /* Prototype for function hotkeys for getting/setting a value. */ 1639a8b554fSPhilip Paeps static int acpi_fujitsu_method_get(struct acpi_fujitsu_softc *sc, int method); 1649a8b554fSPhilip Paeps static int acpi_fujitsu_method_set(struct acpi_fujitsu_softc *sc, int method, int value); 1659a8b554fSPhilip Paeps 1669a8b554fSPhilip Paeps static char *fujitsu_ids[] = { "FUJ02B1", NULL }; 1679a8b554fSPhilip Paeps 168b9abb62dSPhilip Paeps ACPI_SERIAL_DECL(fujitsu, "Fujitsu Function Hotkeys"); 1699a8b554fSPhilip Paeps 1709a8b554fSPhilip Paeps /* sysctl names and function calls */ 1719a8b554fSPhilip Paeps static struct { 1729a8b554fSPhilip Paeps char *name; 1739a8b554fSPhilip Paeps int method; 1749a8b554fSPhilip Paeps char *description; 1759a8b554fSPhilip Paeps } sysctl_table[] = { 1769a8b554fSPhilip Paeps { 1779a8b554fSPhilip Paeps .name = "mute", 1789a8b554fSPhilip Paeps .method = METHOD_MUTE, 1799a8b554fSPhilip Paeps .description = "Speakers/headphones mute status" 1809a8b554fSPhilip Paeps }, 1819a8b554fSPhilip Paeps { 1829a8b554fSPhilip Paeps .name = "pointer_enable", 1839a8b554fSPhilip Paeps .method = METHOD_GMOU, 1849a8b554fSPhilip Paeps .description = "Enable and disable the internal pointer" 1859a8b554fSPhilip Paeps }, 1869a8b554fSPhilip Paeps { 1879a8b554fSPhilip Paeps .name = "lcd_brightness", 1889a8b554fSPhilip Paeps .method = METHOD_GBLL, 1899a8b554fSPhilip Paeps .description = "Brightness level of the LCD panel" 1909a8b554fSPhilip Paeps }, 1919a8b554fSPhilip Paeps { 1929a8b554fSPhilip Paeps .name = "volume", 1939a8b554fSPhilip Paeps .method = METHOD_GVOL, 1949a8b554fSPhilip Paeps .description = "Speakers/headphones volume level" 1959a8b554fSPhilip Paeps }, 196b9abb62dSPhilip Paeps { 197b9abb62dSPhilip Paeps .name = "volume_radix", 198b9abb62dSPhilip Paeps .method = METHOD_RVOL, 199b9abb62dSPhilip Paeps .description = "Number of volume level steps" 200b9abb62dSPhilip Paeps }, 201b9abb62dSPhilip Paeps { 202b9abb62dSPhilip Paeps .name = "lcd_brightness_radix", 203b9abb62dSPhilip Paeps .method = METHOD_RBLL, 204b9abb62dSPhilip Paeps .description = "Number of brightness level steps" 205b9abb62dSPhilip Paeps }, 2069a8b554fSPhilip Paeps 2079a8b554fSPhilip Paeps { NULL, 0, NULL } 2089a8b554fSPhilip Paeps }; 2099a8b554fSPhilip Paeps 2109a8b554fSPhilip Paeps static devclass_t acpi_fujitsu_devclass; 2119a8b554fSPhilip Paeps DRIVER_MODULE(acpi_fujitsu, acpi, acpi_fujitsu_driver, 2129a8b554fSPhilip Paeps acpi_fujitsu_devclass, 0, 0); 2139a8b554fSPhilip Paeps MODULE_DEPEND(acpi_fujitsu, acpi, 1, 1, 1); 2149a8b554fSPhilip Paeps MODULE_VERSION(acpi_fujitsu, 1); 2159a8b554fSPhilip Paeps 2169a8b554fSPhilip Paeps static int 2179a8b554fSPhilip Paeps acpi_fujitsu_probe(device_t dev) 2189a8b554fSPhilip Paeps { 219b9abb62dSPhilip Paeps char *name; 220b9abb62dSPhilip Paeps char buffer[64]; 2219a8b554fSPhilip Paeps 222b9abb62dSPhilip Paeps name = ACPI_ID_PROBE(device_get_parent(dev), dev, fujitsu_ids); 223b9abb62dSPhilip Paeps if (acpi_disabled("fujitsu") || name == NULL || 224b9abb62dSPhilip Paeps device_get_unit(dev) > 1) 2259a8b554fSPhilip Paeps return (ENXIO); 2269a8b554fSPhilip Paeps 227b9abb62dSPhilip Paeps sprintf(buffer, "Fujitsu Function Hotkeys %s", name); 228b9abb62dSPhilip Paeps device_set_desc_copy(dev, buffer); 2299a8b554fSPhilip Paeps 2309a8b554fSPhilip Paeps return (0); 2319a8b554fSPhilip Paeps } 2329a8b554fSPhilip Paeps 2339a8b554fSPhilip Paeps static int 2349a8b554fSPhilip Paeps acpi_fujitsu_attach(device_t dev) 2359a8b554fSPhilip Paeps { 2369a8b554fSPhilip Paeps struct acpi_fujitsu_softc *sc; 2379a8b554fSPhilip Paeps 2389a8b554fSPhilip Paeps ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); 2399a8b554fSPhilip Paeps 2409a8b554fSPhilip Paeps sc = device_get_softc(dev); 2419a8b554fSPhilip Paeps sc->dev = dev; 2429a8b554fSPhilip Paeps sc->handle = acpi_get_handle(dev); 2439a8b554fSPhilip Paeps 2449a8b554fSPhilip Paeps /* Install notification handler */ 2459a8b554fSPhilip Paeps AcpiInstallNotifyHandler(sc->handle, ACPI_DEVICE_NOTIFY, 2469a8b554fSPhilip Paeps acpi_fujitsu_notify_handler, sc); 2479a8b554fSPhilip Paeps 248b9abb62dSPhilip Paeps /* Snag our default values for the hotkys / hotkey states. */ 249b308de8bSPhilip Paeps ACPI_SERIAL_BEGIN(fujitsu); 250b308de8bSPhilip Paeps if (!acpi_fujitsu_init(sc)) 251b9abb62dSPhilip Paeps device_printf(dev, "Couldn't initialize hotkey states!\n"); 252b308de8bSPhilip Paeps ACPI_SERIAL_END(fujitsu); 2539a8b554fSPhilip Paeps 2549a8b554fSPhilip Paeps return (0); 2559a8b554fSPhilip Paeps } 2569a8b554fSPhilip Paeps 2579a8b554fSPhilip Paeps /* 2589a8b554fSPhilip Paeps * Called when the system is being suspended, simply 2599a8b554fSPhilip Paeps * set an event to be signalled when we wake up. 2609a8b554fSPhilip Paeps */ 2619a8b554fSPhilip Paeps static int 2629a8b554fSPhilip Paeps acpi_fujitsu_suspend(device_t dev) 2639a8b554fSPhilip Paeps { 2649a8b554fSPhilip Paeps 2659a8b554fSPhilip Paeps return (0); 2669a8b554fSPhilip Paeps } 2679a8b554fSPhilip Paeps 2689a8b554fSPhilip Paeps static int 2699a8b554fSPhilip Paeps acpi_fujitsu_resume(device_t dev) 2709a8b554fSPhilip Paeps { 2719a8b554fSPhilip Paeps struct acpi_fujitsu_softc *sc; 2729a8b554fSPhilip Paeps ACPI_STATUS status; 2739a8b554fSPhilip Paeps 2749a8b554fSPhilip Paeps sc = device_get_softc(dev); 2759a8b554fSPhilip Paeps 2769a8b554fSPhilip Paeps /* 2779a8b554fSPhilip Paeps * The pointer needs to be re-enabled for 2789a8b554fSPhilip Paeps * some revisions of the P series (2120). 2799a8b554fSPhilip Paeps */ 2809a8b554fSPhilip Paeps ACPI_SERIAL_BEGIN(fujitsu); 2819a8b554fSPhilip Paeps 282b9abb62dSPhilip Paeps if(sc->gmou.exists) { 2839a8b554fSPhilip Paeps status = acpi_SetInteger(sc->handle, "SMOU", 1); 2849a8b554fSPhilip Paeps if (ACPI_FAILURE(status)) 2859a8b554fSPhilip Paeps device_printf(sc->dev, "Couldn't enable pointer\n"); 286b9abb62dSPhilip Paeps } 2879a8b554fSPhilip Paeps ACPI_SERIAL_END(fujitsu); 2889a8b554fSPhilip Paeps 2899a8b554fSPhilip Paeps return (0); 2909a8b554fSPhilip Paeps } 2919a8b554fSPhilip Paeps 2929a8b554fSPhilip Paeps static void 2939a8b554fSPhilip Paeps acpi_fujitsu_notify_status_changed(void *arg) 2949a8b554fSPhilip Paeps { 2959a8b554fSPhilip Paeps struct acpi_fujitsu_softc *sc; 2969a8b554fSPhilip Paeps 2979a8b554fSPhilip Paeps ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); 2989a8b554fSPhilip Paeps 2999a8b554fSPhilip Paeps sc = (struct acpi_fujitsu_softc *)arg; 3009a8b554fSPhilip Paeps 3019a8b554fSPhilip Paeps /* 3029a8b554fSPhilip Paeps * Since our notify function is called, we know something has 3039a8b554fSPhilip Paeps * happened. So the only reason for acpi_fujitsu_update to fail 3049a8b554fSPhilip Paeps * is if we can't find what has changed or an error occurs. 3059a8b554fSPhilip Paeps */ 3069a8b554fSPhilip Paeps ACPI_SERIAL_BEGIN(fujitsu); 3079a8b554fSPhilip Paeps acpi_fujitsu_update(sc); 3089a8b554fSPhilip Paeps ACPI_SERIAL_END(fujitsu); 3099a8b554fSPhilip Paeps } 3109a8b554fSPhilip Paeps 3119a8b554fSPhilip Paeps 3129a8b554fSPhilip Paeps static void 3139a8b554fSPhilip Paeps acpi_fujitsu_notify_handler(ACPI_HANDLE h, uint32_t notify, void *context) 3149a8b554fSPhilip Paeps { 3159a8b554fSPhilip Paeps struct acpi_fujitsu_softc *sc; 3169a8b554fSPhilip Paeps 3179a8b554fSPhilip Paeps ACPI_FUNCTION_TRACE_U32((char *)(uintptr_t)__func__, notify); 3189a8b554fSPhilip Paeps 3199a8b554fSPhilip Paeps sc = (struct acpi_fujitsu_softc *)context; 3209a8b554fSPhilip Paeps 3219a8b554fSPhilip Paeps switch (notify) { 3229a8b554fSPhilip Paeps case ACPI_NOTIFY_STATUS_CHANGED: 3232be4e471SJung-uk Kim AcpiOsExecute(OSL_NOTIFY_HANDLER, 3249a8b554fSPhilip Paeps acpi_fujitsu_notify_status_changed, sc); 3259a8b554fSPhilip Paeps break; 3269a8b554fSPhilip Paeps default: 3279a8b554fSPhilip Paeps /* unknown notification value */ 3289a8b554fSPhilip Paeps break; 3299a8b554fSPhilip Paeps } 3309a8b554fSPhilip Paeps } 3319a8b554fSPhilip Paeps 3329a8b554fSPhilip Paeps static int 3339a8b554fSPhilip Paeps acpi_fujitsu_detach(device_t dev) 3349a8b554fSPhilip Paeps { 3359a8b554fSPhilip Paeps struct acpi_fujitsu_softc *sc; 3369a8b554fSPhilip Paeps 3379a8b554fSPhilip Paeps sc = device_get_softc(dev); 3389a8b554fSPhilip Paeps AcpiRemoveNotifyHandler(sc->handle, ACPI_DEVICE_NOTIFY, 3399a8b554fSPhilip Paeps acpi_fujitsu_notify_handler); 3409a8b554fSPhilip Paeps 3419a8b554fSPhilip Paeps sysctl_ctx_free(&sc->sysctl_ctx); 3429a8b554fSPhilip Paeps 3439a8b554fSPhilip Paeps return (0); 3449a8b554fSPhilip Paeps } 3459a8b554fSPhilip Paeps 3469a8b554fSPhilip Paeps /* 3479a8b554fSPhilip Paeps * Initializes the names of the ACPI control methods and grabs 348b9abb62dSPhilip Paeps * the current state of all of the ACPI hotkeys into the softc. 3499a8b554fSPhilip Paeps */ 3509a8b554fSPhilip Paeps static uint8_t 3519a8b554fSPhilip Paeps acpi_fujitsu_init(struct acpi_fujitsu_softc *sc) 3529a8b554fSPhilip Paeps { 3539a8b554fSPhilip Paeps struct acpi_softc *acpi_sc; 354b9abb62dSPhilip Paeps int i, exists; 3559a8b554fSPhilip Paeps 3569a8b554fSPhilip Paeps ACPI_SERIAL_ASSERT(fujitsu); 3579a8b554fSPhilip Paeps 3589a8b554fSPhilip Paeps /* Setup all of the names for each control method */ 3599a8b554fSPhilip Paeps sc->_sta.name = "_STA"; 3609a8b554fSPhilip Paeps sc->gbll.name = "GBLL"; 3619a8b554fSPhilip Paeps sc->ghks.name = "GHKS"; 3629a8b554fSPhilip Paeps sc->gmou.name = "GMOU"; 3639a8b554fSPhilip Paeps sc->gsif.name = "GSIF"; 3649a8b554fSPhilip Paeps sc->gvol.name = "GVOL"; 365b9abb62dSPhilip Paeps sc->ghks.name = "GHKS"; 366b9abb62dSPhilip Paeps sc->gsif.name = "GSIF"; 3679a8b554fSPhilip Paeps sc->rbll.name = "RBLL"; 3689a8b554fSPhilip Paeps sc->rvol.name = "RVOL"; 3699a8b554fSPhilip Paeps 370b9abb62dSPhilip Paeps /* Determine what hardware functionality is available */ 371b9abb62dSPhilip Paeps acpi_fujitsu_check_hardware(sc); 372b9abb62dSPhilip Paeps 3739a8b554fSPhilip Paeps /* Build the sysctl tree */ 3749a8b554fSPhilip Paeps acpi_sc = acpi_device_get_parent_softc(sc->dev); 3759a8b554fSPhilip Paeps sysctl_ctx_init(&sc->sysctl_ctx); 3769a8b554fSPhilip Paeps sc->sysctl_tree = SYSCTL_ADD_NODE(&sc->sysctl_ctx, 3779a8b554fSPhilip Paeps SYSCTL_CHILDREN(acpi_sc->acpi_sysctl_tree), 3789a8b554fSPhilip Paeps OID_AUTO, "fujitsu", CTLFLAG_RD, 0, ""); 3799a8b554fSPhilip Paeps 3809a8b554fSPhilip Paeps for (i = 0; sysctl_table[i].name != NULL; i++) { 381b9abb62dSPhilip Paeps exists = 0; 382b9abb62dSPhilip Paeps switch(sysctl_table[i].method) { 383b9abb62dSPhilip Paeps case METHOD_GMOU: 384b9abb62dSPhilip Paeps exists = sc->gmou.exists; 385b9abb62dSPhilip Paeps break; 386b9abb62dSPhilip Paeps case METHOD_GBLL: 387b9abb62dSPhilip Paeps exists = sc->gbll.exists; 388b9abb62dSPhilip Paeps break; 389b9abb62dSPhilip Paeps case METHOD_GVOL: 390b9abb62dSPhilip Paeps case METHOD_MUTE: 391b9abb62dSPhilip Paeps exists = sc->gvol.exists; 392b9abb62dSPhilip Paeps break; 393b9abb62dSPhilip Paeps case METHOD_RVOL: 394b9abb62dSPhilip Paeps exists = sc->rvol.exists; 395b9abb62dSPhilip Paeps break; 396b9abb62dSPhilip Paeps case METHOD_RBLL: 397b9abb62dSPhilip Paeps exists = sc->rbll.exists; 398b9abb62dSPhilip Paeps break; 399b9abb62dSPhilip Paeps default: 400b9abb62dSPhilip Paeps /* Allow by default */ 401b9abb62dSPhilip Paeps exists = 1; 402b9abb62dSPhilip Paeps break; 403b9abb62dSPhilip Paeps } 404b9abb62dSPhilip Paeps if(!exists) 405b9abb62dSPhilip Paeps continue; 4069a8b554fSPhilip Paeps SYSCTL_ADD_PROC(&sc->sysctl_ctx, 4079a8b554fSPhilip Paeps SYSCTL_CHILDREN(sc->sysctl_tree), OID_AUTO, 4089a8b554fSPhilip Paeps sysctl_table[i].name, 4099a8b554fSPhilip Paeps CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_ANYBODY, 4109a8b554fSPhilip Paeps sc, i, acpi_fujitsu_sysctl, "I", 4119a8b554fSPhilip Paeps sysctl_table[i].description); 4129a8b554fSPhilip Paeps } 4139a8b554fSPhilip Paeps 414b9abb62dSPhilip Paeps 415b9abb62dSPhilip Paeps /* Set the hotkeys to their initial states */ 4169a8b554fSPhilip Paeps if (!acpi_fujitsu_update(sc)) { 417b9abb62dSPhilip Paeps device_printf(sc->dev, "Couldn't init hotkey states\n"); 4189a8b554fSPhilip Paeps return (FALSE); 4199a8b554fSPhilip Paeps } 4209a8b554fSPhilip Paeps 4219a8b554fSPhilip Paeps return (TRUE); 4229a8b554fSPhilip Paeps } 4239a8b554fSPhilip Paeps 4249a8b554fSPhilip Paeps static int 4259a8b554fSPhilip Paeps acpi_fujitsu_sysctl(SYSCTL_HANDLER_ARGS) 4269a8b554fSPhilip Paeps { 4279a8b554fSPhilip Paeps struct acpi_fujitsu_softc *sc; 4289a8b554fSPhilip Paeps int method; 4299a8b554fSPhilip Paeps int arg; 4309a8b554fSPhilip Paeps int function_num, error = 0; 4319a8b554fSPhilip Paeps 4329a8b554fSPhilip Paeps sc = (struct acpi_fujitsu_softc *)oidp->oid_arg1; 4339a8b554fSPhilip Paeps function_num = oidp->oid_arg2; 4349a8b554fSPhilip Paeps method = sysctl_table[function_num].method; 4359a8b554fSPhilip Paeps 4369a8b554fSPhilip Paeps ACPI_SERIAL_BEGIN(fujitsu); 4379a8b554fSPhilip Paeps 4389a8b554fSPhilip Paeps /* Get the current value */ 4399a8b554fSPhilip Paeps arg = acpi_fujitsu_method_get(sc, method); 4409a8b554fSPhilip Paeps error = sysctl_handle_int(oidp, &arg, 0, req); 4419a8b554fSPhilip Paeps 4429a8b554fSPhilip Paeps if (error != 0 || req->newptr == NULL) 4439a8b554fSPhilip Paeps goto out; 4449a8b554fSPhilip Paeps 4459a8b554fSPhilip Paeps /* Update the value */ 4469a8b554fSPhilip Paeps error = acpi_fujitsu_method_set(sc, method, arg); 4479a8b554fSPhilip Paeps 4489a8b554fSPhilip Paeps out: 4499a8b554fSPhilip Paeps ACPI_SERIAL_END(fujitsu); 4509a8b554fSPhilip Paeps return (error); 4519a8b554fSPhilip Paeps } 4529a8b554fSPhilip Paeps 4539a8b554fSPhilip Paeps static int 4549a8b554fSPhilip Paeps acpi_fujitsu_method_get(struct acpi_fujitsu_softc *sc, int method) 4559a8b554fSPhilip Paeps { 4569a8b554fSPhilip Paeps struct int_nameval nv; 4579a8b554fSPhilip Paeps ACPI_STATUS status; 4589a8b554fSPhilip Paeps 4599a8b554fSPhilip Paeps ACPI_SERIAL_ASSERT(fujitsu); 4609a8b554fSPhilip Paeps 4619a8b554fSPhilip Paeps switch (method) { 4629a8b554fSPhilip Paeps case METHOD_GBLL: 4639a8b554fSPhilip Paeps nv = sc->gbll; 4649a8b554fSPhilip Paeps break; 4659a8b554fSPhilip Paeps case METHOD_GMOU: 4669a8b554fSPhilip Paeps nv = sc->gmou; 4679a8b554fSPhilip Paeps break; 4689a8b554fSPhilip Paeps case METHOD_GVOL: 4699a8b554fSPhilip Paeps case METHOD_MUTE: 4709a8b554fSPhilip Paeps nv = sc->gvol; 4719a8b554fSPhilip Paeps break; 472b9abb62dSPhilip Paeps case METHOD_GHKS: 473b9abb62dSPhilip Paeps nv = sc->ghks; 474b9abb62dSPhilip Paeps break; 475b9abb62dSPhilip Paeps case METHOD_GSIF: 476b9abb62dSPhilip Paeps nv = sc->gsif; 477b9abb62dSPhilip Paeps break; 478b9abb62dSPhilip Paeps case METHOD_RBLL: 479b9abb62dSPhilip Paeps nv = sc->rbll; 480b9abb62dSPhilip Paeps break; 481b9abb62dSPhilip Paeps case METHOD_RVOL: 482b9abb62dSPhilip Paeps nv = sc->rvol; 483b9abb62dSPhilip Paeps break; 4849a8b554fSPhilip Paeps default: 4859a8b554fSPhilip Paeps return (FALSE); 4869a8b554fSPhilip Paeps } 4879a8b554fSPhilip Paeps 488b9abb62dSPhilip Paeps if(!nv.exists) 489b9abb62dSPhilip Paeps return (EINVAL); 490b9abb62dSPhilip Paeps 4919a8b554fSPhilip Paeps status = acpi_GetInteger(sc->handle, nv.name, &nv.value); 4929a8b554fSPhilip Paeps if (ACPI_FAILURE(status)) { 493b9abb62dSPhilip Paeps device_printf(sc->dev, "Couldn't query method (%s)\n", nv.name); 4949a8b554fSPhilip Paeps return (FALSE); 4959a8b554fSPhilip Paeps } 4969a8b554fSPhilip Paeps 4979a8b554fSPhilip Paeps if (method == METHOD_MUTE) { 4989a8b554fSPhilip Paeps sc->bIsMuted = (uint8_t)((nv.value & VOLUME_MUTE_BIT) != 0); 4999a8b554fSPhilip Paeps return (sc->bIsMuted); 5009a8b554fSPhilip Paeps } 5019a8b554fSPhilip Paeps 5029a8b554fSPhilip Paeps nv.value &= GENERAL_SETTING_BITS; 5039a8b554fSPhilip Paeps return (nv.value); 5049a8b554fSPhilip Paeps } 5059a8b554fSPhilip Paeps 5069a8b554fSPhilip Paeps static int 5079a8b554fSPhilip Paeps acpi_fujitsu_method_set(struct acpi_fujitsu_softc *sc, int method, int value) 5089a8b554fSPhilip Paeps { 5099a8b554fSPhilip Paeps struct int_nameval nv; 5109a8b554fSPhilip Paeps ACPI_STATUS status; 5119a8b554fSPhilip Paeps char *control; 5129a8b554fSPhilip Paeps int changed; 5139a8b554fSPhilip Paeps 5149a8b554fSPhilip Paeps ACPI_SERIAL_ASSERT(fujitsu); 5159a8b554fSPhilip Paeps 5169a8b554fSPhilip Paeps switch (method) { 5179a8b554fSPhilip Paeps case METHOD_GBLL: 5189a8b554fSPhilip Paeps changed = BRIGHT_CHANGED; 5199a8b554fSPhilip Paeps control = "SBLL"; 5209a8b554fSPhilip Paeps nv = sc->gbll; 5219a8b554fSPhilip Paeps break; 5229a8b554fSPhilip Paeps case METHOD_GMOU: 5239a8b554fSPhilip Paeps changed = MOUSE_CHANGED; 5249a8b554fSPhilip Paeps control = "SMOU"; 5259a8b554fSPhilip Paeps nv = sc->gmou; 5269a8b554fSPhilip Paeps break; 5279a8b554fSPhilip Paeps case METHOD_GVOL: 5289a8b554fSPhilip Paeps case METHOD_MUTE: 5299a8b554fSPhilip Paeps changed = VOLUME_CHANGED; 5309a8b554fSPhilip Paeps control = "SVOL"; 5319a8b554fSPhilip Paeps nv = sc->gvol; 5329a8b554fSPhilip Paeps break; 5339a8b554fSPhilip Paeps default: 5349a8b554fSPhilip Paeps return (EINVAL); 5359a8b554fSPhilip Paeps } 5369a8b554fSPhilip Paeps 537b9abb62dSPhilip Paeps if(!nv.exists) 538b9abb62dSPhilip Paeps return (EINVAL); 539b9abb62dSPhilip Paeps 5409a8b554fSPhilip Paeps if (method == METHOD_MUTE) { 5419a8b554fSPhilip Paeps if (value == 1) 5429a8b554fSPhilip Paeps value = nv.value | VOLUME_MUTE_BIT; 5439a8b554fSPhilip Paeps else if (value == 0) 5449a8b554fSPhilip Paeps value = nv.value & ~VOLUME_MUTE_BIT; 5459a8b554fSPhilip Paeps else 5469a8b554fSPhilip Paeps return (EINVAL); 5479a8b554fSPhilip Paeps } 5489a8b554fSPhilip Paeps 5499a8b554fSPhilip Paeps status = acpi_SetInteger(sc->handle, control, value); 5509a8b554fSPhilip Paeps if (ACPI_FAILURE(status)) { 5519a8b554fSPhilip Paeps device_printf(sc->dev, "Couldn't update %s\n", control); 552b9abb62dSPhilip Paeps return (FALSE); 5539a8b554fSPhilip Paeps } 5549a8b554fSPhilip Paeps 5559a8b554fSPhilip Paeps sc->lastValChanged = changed; 5569a8b554fSPhilip Paeps return (0); 5579a8b554fSPhilip Paeps } 5589a8b554fSPhilip Paeps 5599a8b554fSPhilip Paeps /* 560b9abb62dSPhilip Paeps * Query the get methods to determine what functionality is available 561b9abb62dSPhilip Paeps * from the hardware function hotkeys. 562b9abb62dSPhilip Paeps */ 563b9abb62dSPhilip Paeps static uint8_t 564b9abb62dSPhilip Paeps acpi_fujitsu_check_hardware(struct acpi_fujitsu_softc *sc) 565b9abb62dSPhilip Paeps { 566b9abb62dSPhilip Paeps int val; 567b9abb62dSPhilip Paeps struct acpi_softc *acpi_sc; 568b9abb62dSPhilip Paeps 569b9abb62dSPhilip Paeps acpi_sc = acpi_device_get_parent_softc(sc->dev); 570b9abb62dSPhilip Paeps 571b9abb62dSPhilip Paeps ACPI_SERIAL_ASSERT(fujitsu); 572b9abb62dSPhilip Paeps /* save the hotkey bitmask */ 573b9abb62dSPhilip Paeps if (ACPI_FAILURE(acpi_GetInteger(sc->handle, 574b9abb62dSPhilip Paeps sc->gsif.name, &(sc->gsif.value)))) { 575b9abb62dSPhilip Paeps sc->gsif.exists = 0; 576b9abb62dSPhilip Paeps device_printf(sc->dev, "Couldn't query bitmask value\n"); 577b9abb62dSPhilip Paeps } else { 578b9abb62dSPhilip Paeps sc->gsif.exists = 1; 579b9abb62dSPhilip Paeps } 580b9abb62dSPhilip Paeps 581b9abb62dSPhilip Paeps /* System Volume Level */ 582b9abb62dSPhilip Paeps if (ACPI_FAILURE(acpi_GetInteger(sc->handle, 583b9abb62dSPhilip Paeps sc->gvol.name, &val))) { 584b9abb62dSPhilip Paeps sc->gvol.exists = 0; 585b9abb62dSPhilip Paeps } else { 586b9abb62dSPhilip Paeps sc->gvol.exists = 1; 587b9abb62dSPhilip Paeps } 588b9abb62dSPhilip Paeps 589b9abb62dSPhilip Paeps if (ACPI_FAILURE(acpi_GetInteger(sc->handle, 590b9abb62dSPhilip Paeps sc->gbll.name, &val))) { 591b9abb62dSPhilip Paeps sc->gbll.exists = 0; 592b9abb62dSPhilip Paeps } else { 593b9abb62dSPhilip Paeps sc->gbll.exists = 1; 594b9abb62dSPhilip Paeps } 595b9abb62dSPhilip Paeps 596b9abb62dSPhilip Paeps if (ACPI_FAILURE(acpi_GetInteger(sc->handle, 597b9abb62dSPhilip Paeps sc->ghks.name, &val))) { 598b9abb62dSPhilip Paeps sc->ghks.exists = 0; 599b9abb62dSPhilip Paeps } else { 600b9abb62dSPhilip Paeps sc->ghks.exists = 1; 601b9abb62dSPhilip Paeps } 602b9abb62dSPhilip Paeps 603b9abb62dSPhilip Paeps if (ACPI_FAILURE(acpi_GetInteger(sc->handle, 604b9abb62dSPhilip Paeps sc->gmou.name, &val))) { 605b9abb62dSPhilip Paeps sc->gmou.exists = 0; 606b9abb62dSPhilip Paeps } else { 607b9abb62dSPhilip Paeps sc->gmou.exists = 1; 608b9abb62dSPhilip Paeps } 609b9abb62dSPhilip Paeps 610b9abb62dSPhilip Paeps if (ACPI_FAILURE(acpi_GetInteger(sc->handle, 611b9abb62dSPhilip Paeps sc->rbll.name, &val))) { 612b9abb62dSPhilip Paeps sc->rbll.exists = 0; 613b9abb62dSPhilip Paeps } else { 614b9abb62dSPhilip Paeps sc->rbll.exists = 1; 615b9abb62dSPhilip Paeps } 616b9abb62dSPhilip Paeps 617b9abb62dSPhilip Paeps if (ACPI_FAILURE(acpi_GetInteger(sc->handle, 618b9abb62dSPhilip Paeps sc->rvol.name, &val))) { 619b9abb62dSPhilip Paeps sc->rvol.exists = 0; 620b9abb62dSPhilip Paeps } else { 621b9abb62dSPhilip Paeps sc->rvol.exists = 1; 622b9abb62dSPhilip Paeps } 623b9abb62dSPhilip Paeps 624b9abb62dSPhilip Paeps return (TRUE); 625b9abb62dSPhilip Paeps } 626b9abb62dSPhilip Paeps 627b9abb62dSPhilip Paeps /* 6289a8b554fSPhilip Paeps * Query each of the ACPI control methods that contain information we're 6299a8b554fSPhilip Paeps * interested in. We check the return values from the control methods and 6309a8b554fSPhilip Paeps * adjust any state variables if they should be adjusted. 6319a8b554fSPhilip Paeps */ 6329a8b554fSPhilip Paeps static uint8_t 6339a8b554fSPhilip Paeps acpi_fujitsu_update(struct acpi_fujitsu_softc *sc) 6349a8b554fSPhilip Paeps { 635b9abb62dSPhilip Paeps int changed; 6369a8b554fSPhilip Paeps struct acpi_softc *acpi_sc; 6379a8b554fSPhilip Paeps 6389a8b554fSPhilip Paeps acpi_sc = acpi_device_get_parent_softc(sc->dev); 6399a8b554fSPhilip Paeps 6409a8b554fSPhilip Paeps ACPI_SERIAL_ASSERT(fujitsu); 641b9abb62dSPhilip Paeps if(sc->gsif.exists) 642b9abb62dSPhilip Paeps changed = sc->gsif.value & acpi_fujitsu_method_get(sc,METHOD_GHKS); 643b9abb62dSPhilip Paeps else 644b9abb62dSPhilip Paeps changed = 0; 6459a8b554fSPhilip Paeps 6469a8b554fSPhilip Paeps /* System Volume Level */ 647b9abb62dSPhilip Paeps if(sc->gvol.exists) { 6489a8b554fSPhilip Paeps if (ACPI_FAILURE(acpi_GetInteger(sc->handle, 6499a8b554fSPhilip Paeps sc->gvol.name, &(sc->gvol.value)))) { 6509a8b554fSPhilip Paeps device_printf(sc->dev, "Couldn't query volume level\n"); 6519a8b554fSPhilip Paeps return (FALSE); 6529a8b554fSPhilip Paeps } 6539a8b554fSPhilip Paeps 654b9abb62dSPhilip Paeps if (changed & VOLUME_CHANGED) { 6559a8b554fSPhilip Paeps sc->bIsMuted = 6569a8b554fSPhilip Paeps (uint8_t)((sc->gvol.value & VOLUME_MUTE_BIT) != 0); 6579a8b554fSPhilip Paeps 6589a8b554fSPhilip Paeps /* Clear the modification bit */ 6599a8b554fSPhilip Paeps sc->gvol.value &= VOLUME_SETTING_BITS; 6609a8b554fSPhilip Paeps 6619a8b554fSPhilip Paeps if (sc->bIsMuted) { 6629a8b554fSPhilip Paeps acpi_UserNotify("FUJITSU", sc->handle, FN_MUTE); 6639a8b554fSPhilip Paeps ACPI_VPRINT(sc->dev, acpi_sc, "Volume is now mute\n"); 6649a8b554fSPhilip Paeps } else 6659a8b554fSPhilip Paeps ACPI_VPRINT(sc->dev, acpi_sc, "Volume is now %d\n", 6669a8b554fSPhilip Paeps sc->gvol.value); 6679a8b554fSPhilip Paeps 6689a8b554fSPhilip Paeps acpi_UserNotify("FUJITSU", sc->handle, FN_VOLUME); 669b9abb62dSPhilip Paeps } 6709a8b554fSPhilip Paeps } 6719a8b554fSPhilip Paeps 6729a8b554fSPhilip Paeps /* Internal mouse pointer (eraserhead) */ 673b9abb62dSPhilip Paeps if(sc->gmou.exists) { 6749a8b554fSPhilip Paeps if (ACPI_FAILURE(acpi_GetInteger(sc->handle, 6759a8b554fSPhilip Paeps sc->gmou.name, &(sc->gmou.value)))) { 6769a8b554fSPhilip Paeps device_printf(sc->dev, "Couldn't query pointer state\n"); 6779a8b554fSPhilip Paeps return (FALSE); 6789a8b554fSPhilip Paeps } 6799a8b554fSPhilip Paeps 680b9abb62dSPhilip Paeps if (changed & MOUSE_CHANGED) { 6819a8b554fSPhilip Paeps sc->bIntPtrEnabled = (uint8_t)(sc->gmou.value & 0x1); 6829a8b554fSPhilip Paeps 6839a8b554fSPhilip Paeps /* Clear the modification bit */ 6849a8b554fSPhilip Paeps sc->gmou.value &= MOUSE_SETTING_BITS; 6859a8b554fSPhilip Paeps 6869a8b554fSPhilip Paeps acpi_UserNotify("FUJITSU", sc->handle, FN_POINTER_ENABLE); 6879a8b554fSPhilip Paeps 6889a8b554fSPhilip Paeps ACPI_VPRINT(sc->dev, acpi_sc, "Internal pointer is now %s\n", 6899a8b554fSPhilip Paeps (sc->bIntPtrEnabled) ? "enabled" : "disabled"); 690b9abb62dSPhilip Paeps } 6919a8b554fSPhilip Paeps } 6929a8b554fSPhilip Paeps 6939a8b554fSPhilip Paeps /* Screen Brightness Level */ 694b9abb62dSPhilip Paeps if(sc->gbll.exists) { 6959a8b554fSPhilip Paeps if (ACPI_FAILURE(acpi_GetInteger(sc->handle, 6969a8b554fSPhilip Paeps sc->gbll.name, &(sc->gbll.value)))) { 6979a8b554fSPhilip Paeps device_printf(sc->dev, "Couldn't query brightness level\n"); 6989a8b554fSPhilip Paeps return (FALSE); 6999a8b554fSPhilip Paeps } 7009a8b554fSPhilip Paeps 701b9abb62dSPhilip Paeps if (changed & BRIGHT_CHANGED) { 7029a8b554fSPhilip Paeps /* No state to record here. */ 7039a8b554fSPhilip Paeps 7049a8b554fSPhilip Paeps /* Clear the modification bit */ 7059a8b554fSPhilip Paeps sc->gbll.value &= BRIGHTNESS_SETTING_BITS; 7069a8b554fSPhilip Paeps 7079a8b554fSPhilip Paeps acpi_UserNotify("FUJITSU", sc->handle, FN_LCD_BRIGHTNESS); 7089a8b554fSPhilip Paeps 7099a8b554fSPhilip Paeps ACPI_VPRINT(sc->dev, acpi_sc, "Brightness level is now %d\n", 7109a8b554fSPhilip Paeps sc->gbll.value); 711b9abb62dSPhilip Paeps } 7129a8b554fSPhilip Paeps } 7139a8b554fSPhilip Paeps 714b9abb62dSPhilip Paeps sc->lastValChanged = changed; 7159a8b554fSPhilip Paeps return (TRUE); 7169a8b554fSPhilip Paeps } 717