diff options
author | philip <philip@FreeBSD.org> | 2005-03-20 23:36:36 +0000 |
---|---|---|
committer | philip <philip@FreeBSD.org> | 2005-03-20 23:36:36 +0000 |
commit | df09d3a7819676e84feebf7b0dfd2d7736450bd6 (patch) | |
tree | 5e7df4e4beba465715e60acf6726c79529674593 /sys | |
parent | 4da02be559060350260670cdba83826a86971ad7 (diff) | |
download | FreeBSD-src-df09d3a7819676e84feebf7b0dfd2d7736450bd6.zip FreeBSD-src-df09d3a7819676e84feebf7b0dfd2d7736450bd6.tar.gz |
Simplify sysctl handling by consolidating various get/set functions into
generic functions, use a table for hooking up sysctls nodes rather than doing
it manually. While here, clean up some style bugs.
Glanced at by: njl
Diffstat (limited to 'sys')
-rw-r--r-- | sys/dev/acpi_support/acpi_asus.c | 373 |
1 files changed, 213 insertions, 160 deletions
diff --git a/sys/dev/acpi_support/acpi_asus.c b/sys/dev/acpi_support/acpi_asus.c index 372a9c3..88e2384 100644 --- a/sys/dev/acpi_support/acpi_asus.c +++ b/sys/dev/acpi_support/acpi_asus.c @@ -51,6 +51,11 @@ __FBSDID("$FreeBSD$"); #include <dev/acpica/acpivar.h> #include <dev/led/led.h> +/* Methods */ +#define ACPI_ASUS_METHOD_BRN 1 +#define ACPI_ASUS_METHOD_DISP 2 +#define ACPI_ASUS_METHOD_LCD 3 + #define _COMPONENT ACPI_OEM ACPI_MODULE_NAME("ASUS") @@ -218,6 +223,30 @@ static struct acpi_asus_model acpi_samsung_models[] = { { .name = NULL } }; +static struct { + char *name; + char *description; + int method; +} acpi_asus_sysctls[] = { + { + .name = "lcd_backlight", + .method = ACPI_ASUS_METHOD_LCD, + .description = "state of the lcd backlight" + }, + { + .name = "lcd_brightness", + .method = ACPI_ASUS_METHOD_BRN, + .description = "brightness of the lcd panel" + }, + { + .name = "video_output", + .method = ACPI_ASUS_METHOD_DISP, + .description = "display output state" + }, + + { .name = NULL } +}; + ACPI_SERIAL_DECL(asus, "ACPI ASUS extras"); /* Function prototypes */ @@ -227,9 +256,10 @@ static int acpi_asus_detach(device_t dev); static void acpi_asus_led(struct acpi_asus_led *led, int state); -static int acpi_asus_sysctl_brn(SYSCTL_HANDLER_ARGS); -static int acpi_asus_sysctl_lcd(SYSCTL_HANDLER_ARGS); -static int acpi_asus_sysctl_disp(SYSCTL_HANDLER_ARGS); +static int acpi_asus_sysctl(SYSCTL_HANDLER_ARGS); +static int acpi_asus_sysctl_init(struct acpi_asus_softc *sc, int method); +static int acpi_asus_sysctl_get(struct acpi_asus_softc *sc, int method); +static int acpi_asus_sysctl_set(struct acpi_asus_softc *sc, int method, int val); static void acpi_asus_notify(ACPI_HANDLE h, UINT32 notify, void *context); @@ -356,6 +386,19 @@ acpi_asus_attach(device_t dev) SYSCTL_CHILDREN(acpi_sc->acpi_sysctl_tree), OID_AUTO, "asus", CTLFLAG_RD, 0, ""); + /* Hook up nodes */ + for (int i = 0; acpi_asus_sysctls[i].name != NULL; i++) { + if (!acpi_asus_sysctl_init(sc, acpi_asus_sysctls[i].method)) + continue; + + SYSCTL_ADD_PROC(&sc->sysctl_ctx, + SYSCTL_CHILDREN(sc->sysctl_tree), OID_AUTO, + acpi_asus_sysctls[i].name, + CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_ANYBODY, + sc, i, acpi_asus_sysctl, "I", + acpi_asus_sysctls[i].description); + } + /* Attach leds */ if (sc->model->mled_set) { sc->s_mled.dev = dev; @@ -378,71 +421,6 @@ acpi_asus_attach(device_t dev) led_create((led_t *)acpi_asus_led, &sc->s_wled, "wled"); } - /* Attach brightness for GPLV/SPLV models */ - if (sc->model->brn_get && ACPI_SUCCESS(acpi_GetInteger(sc->handle, - sc->model->brn_get, &sc->s_brn))) - SYSCTL_ADD_PROC(&sc->sysctl_ctx, - SYSCTL_CHILDREN(sc->sysctl_tree), OID_AUTO, - "lcd_brightness", CTLTYPE_INT | CTLFLAG_RW, sc, 0, - acpi_asus_sysctl_brn, "I", "brightness of the lcd panel"); - - /* Attach brightness for other models */ - if (sc->model->brn_up && - ACPI_SUCCESS(AcpiEvaluateObject(sc->handle, sc->model->brn_up, - NULL, NULL)) && - ACPI_SUCCESS(AcpiEvaluateObject(sc->handle, sc->model->brn_dn, - NULL, NULL))) - SYSCTL_ADD_PROC(&sc->sysctl_ctx, - SYSCTL_CHILDREN(sc->sysctl_tree), OID_AUTO, - "lcd_brightness", CTLTYPE_INT | CTLFLAG_RW, sc, 0, - acpi_asus_sysctl_brn, "I", "brightness of the lcd panel"); - - /* Attach display switching */ - if (sc->model->disp_get && ACPI_SUCCESS(acpi_GetInteger(sc->handle, - sc->model->disp_get, &sc->s_disp))) - SYSCTL_ADD_PROC(&sc->sysctl_ctx, - SYSCTL_CHILDREN(sc->sysctl_tree), OID_AUTO, - "video_output", CTLTYPE_INT | CTLFLAG_RW, sc, 0, - acpi_asus_sysctl_disp, "I", "display output state"); - - /* Attach LCD state, easy for most models... */ - if (sc->model->lcd_get && strncmp(sc->model->name, "L3H", 3) != 0 && - ACPI_SUCCESS(acpi_GetInteger(sc->handle, sc->model->lcd_get, - &sc->s_lcd))) { - SYSCTL_ADD_PROC(&sc->sysctl_ctx, - SYSCTL_CHILDREN(sc->sysctl_tree), OID_AUTO, - "lcd_backlight", CTLTYPE_INT | CTLFLAG_RW, sc, 0, - acpi_asus_sysctl_lcd, "I", "state of the lcd backlight"); - } else if (sc->model->lcd_get) { - ACPI_BUFFER Buf; - ACPI_OBJECT Arg[2], Obj; - ACPI_OBJECT_LIST Args; - - /* ...a nightmare for the L3H */ - Arg[0].Type = ACPI_TYPE_INTEGER; - Arg[0].Integer.Value = 0x02; - Arg[1].Type = ACPI_TYPE_INTEGER; - Arg[1].Integer.Value = 0x03; - - Args.Count = 2; - Args.Pointer = Arg; - - Buf.Length = sizeof(Obj); - Buf.Pointer = &Obj; - - if (ACPI_SUCCESS(AcpiEvaluateObject(sc->handle, - sc->model->lcd_get, &Args, &Buf)) && - Obj.Type == ACPI_TYPE_INTEGER) { - sc->s_lcd = Obj.Integer.Value >> 8; - - SYSCTL_ADD_PROC(&sc->sysctl_ctx, - SYSCTL_CHILDREN(sc->sysctl_tree), OID_AUTO, - "lcd_backlight", CTLTYPE_INT | CTLFLAG_RW, sc, 0, - acpi_asus_sysctl_lcd, "I", - "state of the lcd backlight"); - } - } - /* Activate hotkeys */ AcpiEvaluateObject(sc->handle, "BSTS", NULL, NULL); @@ -493,138 +471,213 @@ acpi_asus_led(struct acpi_asus_led *led, int state) sc = device_get_softc(led->dev); switch (led->type) { - case ACPI_ASUS_LED_MLED: - method = sc->model->mled_set; - - /* Note: inverted */ - state = !state; - break; - case ACPI_ASUS_LED_TLED: - method = sc->model->tled_set; - break; - case ACPI_ASUS_LED_WLED: - method = sc->model->wled_set; - break; - default: - printf("acpi_asus_led: invalid LED type %d\n", - (int)led->type); - return; + case ACPI_ASUS_LED_MLED: + method = sc->model->mled_set; + + /* Note: inverted */ + state = !state; + break; + case ACPI_ASUS_LED_TLED: + method = sc->model->tled_set; + break; + case ACPI_ASUS_LED_WLED: + method = sc->model->wled_set; + break; + default: + printf("acpi_asus_led: invalid LED type %d\n", + (int)led->type); + return; } acpi_SetInteger(sc->handle, method, state); } static int -acpi_asus_sysctl_brn(SYSCTL_HANDLER_ARGS) +acpi_asus_sysctl(SYSCTL_HANDLER_ARGS) { struct acpi_asus_softc *sc; - int brn, err; - + int arg; + int error = 0; + int function; + int method; + ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); sc = (struct acpi_asus_softc *)oidp->oid_arg1; + function = oidp->oid_arg2; + method = acpi_asus_sysctls[function].method; + ACPI_SERIAL_BEGIN(asus); + arg = acpi_asus_sysctl_get(sc, method); + error = sysctl_handle_int(oidp, &arg, 0, req); /* Sanity check */ - brn = sc->s_brn; - err = sysctl_handle_int(oidp, &brn, 0, req); - - if (err != 0 || req->newptr == NULL) + if (error != 0 || req->newptr == NULL) goto out; - if (brn < 0 || brn > 15) { - err = EINVAL; - goto out; - } - - /* Keep track and update */ - sc->s_brn = brn; - - if (sc->model->brn_set) - acpi_SetInteger(sc->handle, sc->model->brn_set, brn); - else { - brn -= sc->s_brn; - - while (brn != 0) { - AcpiEvaluateObject(sc->handle, (brn > 0) ? - sc->model->brn_up : sc->model->brn_dn, - NULL, NULL); - (brn > 0) ? brn-- : brn++; - } - } + /* Update */ + error = acpi_asus_sysctl_set(sc, method, arg); out: ACPI_SERIAL_END(asus); - return (err); + return (error); } static int -acpi_asus_sysctl_lcd(SYSCTL_HANDLER_ARGS) +acpi_asus_sysctl_get(struct acpi_asus_softc *sc, int method) { - struct acpi_asus_softc *sc; - int lcd, err; + int val = 0; ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); - - sc = (struct acpi_asus_softc *)oidp->oid_arg1; - ACPI_SERIAL_BEGIN(asus); - - /* Sanity check */ - lcd = sc->s_lcd; - err = sysctl_handle_int(oidp, &lcd, 0, req); - - if (err != 0 || req->newptr == NULL) - goto out; - - if (lcd < 0 || lcd > 1) { - err = EINVAL; - goto out; + ACPI_SERIAL_ASSERT(asus); + + switch (method) { + case ACPI_ASUS_METHOD_BRN: + val = sc->s_brn; + break; + case ACPI_ASUS_METHOD_DISP: + val = sc->s_disp; + break; + case ACPI_ASUS_METHOD_LCD: + val = sc->s_lcd; + break; } - /* Keep track and update */ - sc->s_lcd = lcd; - - /* Most models just need a lcd_set evaluated, the L3H is trickier */ - if (strncmp(sc->model->name, "L3H", 3) != 0) - AcpiEvaluateObject(sc->handle, sc->model->lcd_set, NULL, NULL); - else - acpi_SetInteger(sc->handle, sc->model->lcd_set, 0x7); - -out: - ACPI_SERIAL_END(asus); - return (err); + return (val); } static int -acpi_asus_sysctl_disp(SYSCTL_HANDLER_ARGS) +acpi_asus_sysctl_set(struct acpi_asus_softc *sc, int method, int arg) { - struct acpi_asus_softc *sc; - int disp, err; + ACPI_STATUS status; ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); + ACPI_SERIAL_ASSERT(asus); + + switch (method) { + case ACPI_ASUS_METHOD_BRN: + if (arg < 0 || arg > 15) + return (EINVAL); + + if (sc->model->brn_set) + status = acpi_SetInteger(sc->handle, + sc->model->brn_set, arg); + else { + while (arg != 0) { + status = AcpiEvaluateObject(sc->handle, + (arg > 0) ? sc->model->brn_up : + sc->model->brn_dn, NULL, NULL); + (arg > 0) ? arg-- : arg++; + } + } - sc = (struct acpi_asus_softc *)oidp->oid_arg1; + if (ACPI_SUCCESS(status)) + sc->s_brn = arg; - /* Sanity check */ - ACPI_SERIAL_BEGIN(asus); - disp = sc->s_disp; - err = sysctl_handle_int(oidp, &disp, 0, req); + break; + case ACPI_ASUS_METHOD_DISP: + if (arg < 0 || arg > 7) + return (EINVAL); - if (err != 0 || req->newptr == NULL) - goto out; + status = acpi_SetInteger(sc->handle, + sc->model->disp_set, arg); - if (disp < 0 || disp > 7) { - err = EINVAL; - goto out; + if (ACPI_SUCCESS(status)) + sc->s_disp = arg; + + break; + case ACPI_ASUS_METHOD_LCD: + if (arg < 0 || arg > 1) + return (EINVAL); + + if (strncmp(sc->model->name, "L3H", 3) != 0) + status = AcpiEvaluateObject(sc->handle, + sc->model->lcd_set, NULL, NULL); + else + status = acpi_SetInteger(sc->handle, + sc->model->lcd_set, 0x7); + + if (ACPI_SUCCESS(status)) + sc->s_lcd = arg; + + break; } - /* Keep track and update */ - sc->s_disp = disp; - acpi_SetInteger(sc->handle, sc->model->disp_set, disp); + return (0); +} -out: - ACPI_SERIAL_END(asus); - return (err); +static int +acpi_asus_sysctl_init(struct acpi_asus_softc *sc, int method) +{ + ACPI_STATUS status; + + switch (method) { + case ACPI_ASUS_METHOD_BRN: + if (sc->model->brn_get) { + /* GPLV/SPLV models */ + status = acpi_GetInteger(sc->handle, + sc->model->brn_get, &sc->s_brn); + if (ACPI_SUCCESS(status)) + return (TRUE); + } else if (sc->model->brn_up) { + /* Relative models */ + status = AcpiEvaluateObject(sc->handle, + sc->model->brn_up, NULL, NULL); + if (ACPI_FAILURE(status)) + return (FALSE); + + status = AcpiEvaluateObject(sc->handle, + sc->model->brn_dn, NULL, NULL); + if (ACPI_FAILURE(status)) + return (FALSE); + + return (TRUE); + } + return (FALSE); + case ACPI_ASUS_METHOD_DISP: + if (sc->model->disp_get) { + status = acpi_GetInteger(sc->handle, + sc->model->disp_get, &sc->s_disp); + if (ACPI_SUCCESS(status)) + return (TRUE); + } + return (FALSE); + case ACPI_ASUS_METHOD_LCD: + if (sc->model->lcd_get && + strncmp(sc->model->name, "L3H", 3) != 0) { + status = acpi_GetInteger(sc->handle, + sc->model->lcd_get, &sc->s_lcd); + if (ACPI_SUCCESS(status)) + return (TRUE); + } + else if (sc->model->lcd_get) { + ACPI_BUFFER Buf; + ACPI_OBJECT Arg[2], Obj; + ACPI_OBJECT_LIST Args; + + /* L3H is a bit special */ + Arg[0].Type = ACPI_TYPE_INTEGER; + Arg[0].Integer.Value = 0x02; + Arg[1].Type = ACPI_TYPE_INTEGER; + Arg[1].Integer.Value = 0x03; + + Args.Count = 2; + Args.Pointer = Arg; + + Buf.Length = sizeof(Obj); + Buf.Pointer = &Obj; + + status = AcpiEvaluateObject(sc->handle, + sc->model->lcd_get, &Args, &Buf); + if (ACPI_SUCCESS(status) && + Obj.Type == ACPI_TYPE_INTEGER) { + sc->s_lcd = Obj.Integer.Value >> 8; + return (TRUE); + } + } + return (FALSE); + } + return (FALSE); } static void |