diff --git a/etc/devd/Makefile b/etc/devd/Makefile index 8d7246abba35..433436b0890c 100644 --- a/etc/devd/Makefile +++ b/etc/devd/Makefile @@ -1,6 +1,14 @@ # $FreeBSD$ -FILES= asus.conf uath.conf usb.conf +FILES= uath.conf usb.conf + +.if ${MACHINE} == "powerpc" +FILES+= apple.conf +.endif + +.if ${MACHINE} == "amd64" || ${MACHINE} == "i386" +FILES+= asus.conf +.endif NO_OBJ= FILESDIR= /etc/devd diff --git a/etc/devd/apple.conf b/etc/devd/apple.conf new file mode 100644 index 000000000000..a57a8e06a640 --- /dev/null +++ b/etc/devd/apple.conf @@ -0,0 +1,46 @@ +# $FreeBSD$ +# +# PowerPC Apple specific devd events + +# Keyboard power key +notify 0 { + match "system" "PMU"; + match "subsystem" "Button"; + match "notify" "0x0"; + action "shutdown -p now"; +}; + + +# The next blocks enable volume hotkeys that can be found on Apple laptops +notify 0 { + match "system" "PMU"; + match "subsystem" "keys"; + match "type" "mute"; + action "mixer 0"; +}; + +notify 0 { + match "system" "PMU"; + match "subsystem" "keys"; + match "type" "volume"; + match "notify" "down"; + action "mixer vol -10"; +}; + +notify 0 { + match "system" "PMU"; + match "subsystem" "keys"; + match "type" "volume"; + match "notify" "up"; + action "mixer vol +10"; +}; + +# Eject key +notify 0 { + match "system" "PMU"; + match "subsystem" "keys"; + match "type" "eject"; + action "camcontrol eject cd0"; +}; + + diff --git a/share/man/man4/man4.powerpc/Makefile b/share/man/man4/man4.powerpc/Makefile index 57196a3b92b1..09d8b70eb1f2 100644 --- a/share/man/man4/man4.powerpc/Makefile +++ b/share/man/man4/man4.powerpc/Makefile @@ -2,6 +2,7 @@ MAN= adb.4 \ akbd.4 \ + abtn.4 \ ams.4 \ bm.4 \ cuda.4 \ diff --git a/share/man/man4/man4.powerpc/abtn.4 b/share/man/man4/man4.powerpc/abtn.4 new file mode 100644 index 000000000000..8aab9a7040f3 --- /dev/null +++ b/share/man/man4/man4.powerpc/abtn.4 @@ -0,0 +1,115 @@ +.\"- +.\" Copyright (c) 2011 Justin Hibbits +.\" Copyright (c) 2009 Nathan Whitehorn +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +.\" WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +.\" DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, +.\" INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +.\" (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +.\" SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +.\" STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +.\" ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +.\" POSSIBILITY OF SUCH DAMAGE. +.\" +.\" $FreeBSD$ +.\" +.Dd October 16, 2011 +.Dt ABTN 4 +.Os +.Sh NAME +.Nm abtn +.Nd ADB Keyboard Special Keys Driver +.Sh SYNOPSIS +To compile this driver into the kernel, +place the following lines in your +kernel configuration file: +.Bd -ragged -offset indent +.Cd "device adb" +.Ed +.Sh DESCRIPTION +The +.Nm +driver provides support for the extended Fn keys on Apple notebooks with an ADB +interface. +.Sh HARDWARE +The +.Nm +driver supports extended keyboard keys (special F-keys) on the following devices: +.Pp +.Bl -bullet -compact +.It +Apple iBook Keyboard +.It +Apple PowerBook Keyboard +.El +.Sh EVENTS +The +.Nm +driver sends events to +.Xr devd 8 +for the following events under the +.Cd PMU +system, and +.Cd keys +subsystem: +.Pp +.Bl -bullet -compact +.It +.Cd brightness +- Generates +.Cd up +and +.Cd down +notify types matching the pressed key. +.It +.Cd mute +.It +.Cd volume +- Generates +.Cd up +and +.Cd down +notify types matching the pressed key. +.It +.Cd eject +.El +.Pp +Examples are included in /etc/devd/apple.conf. +.Sh SEE ALSO +.Xr adb 4 , +.Xr akbd 4 , +.Xr cuda 4 , +.Xr pmu 4, +.Xr devd 8 +.Sh HISTORY +The +.Nm +device driver first appeared in +.Nx 5.0 +and was ported to +.Fx 10.0 . +.Sh AUTHORS +.An -nosplit +The +.Nm +driver was written by +.An Tsubai Masanari +for +.Nx +and ported to +.Fx +by +.An Justin Hibbits . diff --git a/share/man/man4/man4.powerpc/akbd.4 b/share/man/man4/man4.powerpc/akbd.4 index aea2fa01f504..d4f3aa167059 100644 --- a/share/man/man4/man4.powerpc/akbd.4 +++ b/share/man/man4/man4.powerpc/akbd.4 @@ -58,7 +58,36 @@ Apple iBook Keyboard .It Apple PowerBook Keyboard .El +.Sh EVENTS +The +.Nm +driver sends events to +.Xr devd 8 +for the following events under the +.Cd PMU +system: +.Pp +.Bl -bullet -compact +.It +Power button - +.Cd "Button" +subsystem, +.Cd "pressed" +type. +.El +.Sh SYSCTL VARIABLES +The +.Nm +driver supports the following sysctl variable for configuring the Fn keys: +.Bl -tag -width indent +.It Va dev.akbd.%d.fn_keys_function_as_primary +Set the Fn keys to be their F-key type as default. A value of 0 causes the +F-keys keys to work as special keys by default ( +.Xr abtn 4 ) +and a value of 1 sets them to behave as F-keys by default. +.El .Sh SEE ALSO +.Xr abtn 4 , .Xr adb 4 , .Xr cuda 4 , .Xr pmu 4 diff --git a/sys/conf/files.powerpc b/sys/conf/files.powerpc index 031a1848f800..2760edf14112 100644 --- a/sys/conf/files.powerpc +++ b/sys/conf/files.powerpc @@ -22,6 +22,7 @@ dev/adb/adb_kbd.c optional adb dev/adb/adb_mouse.c optional adb dev/adb/adb_hb_if.m optional adb dev/adb/adb_if.m optional adb +dev/adb/adb_buttons.c optional adb dev/agp/agp_apple.c optional agp powermac dev/cfi/cfi_bus_fdt.c optional cfi fdt dev/fb/fb.c optional sc diff --git a/sys/dev/adb/adb_buttons.c b/sys/dev/adb/adb_buttons.c new file mode 100644 index 000000000000..92cdda169bae --- /dev/null +++ b/sys/dev/adb/adb_buttons.c @@ -0,0 +1,165 @@ +/*- + * Copyright (c) 2011, Justin Hibbits. + * Copyright (c) 2002, Miodrag Vallat. + * Copyright (C) 1999 Tsubai Masanari. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * OpenBSD: abtn.c,v 1.12 2009/01/10 18:00:59 robert Exp + * NetBSD: abtn.c,v 1.1 1999/07/12 17:48:26 tsubai Exp + * + * $FreeBSD$ + */ + +#include +#include +#include +#include +#include + +#include + +#include +#include + +#include + +#define ABTN_HANDLER_ID 31 + +struct abtn_softc { + device_t sc_dev; + + int handler_id; +}; + +static int abtn_probe(device_t dev); +static int abtn_attach(device_t dev); +static u_int abtn_receive_packet(device_t dev, u_char status, + u_char command, u_char reg, int len, u_char *data); + +static device_method_t abtn_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, abtn_probe), + DEVMETHOD(device_attach, abtn_attach), + DEVMETHOD(device_shutdown, bus_generic_shutdown), + DEVMETHOD(device_suspend, bus_generic_suspend), + DEVMETHOD(device_resume, bus_generic_resume), + + /* ADB interface */ + DEVMETHOD(adb_receive_packet, abtn_receive_packet), + + { 0, 0 } +}; + +static driver_t abtn_driver = { + "abtn", + abtn_methods, + sizeof(struct abtn_softc), +}; + +static devclass_t abtn_devclass; + +DRIVER_MODULE(abtn, adb, abtn_driver, abtn_devclass, 0, 0); + +static int +abtn_probe(device_t dev) +{ + uint8_t type; + + type = adb_get_device_type(dev); + + if (type != ADB_DEVICE_MISC) + return (ENXIO); + + device_set_desc(dev, "ADB Brightness/Volume/Eject Buttons"); + return (0); +} + +static int +abtn_attach(device_t dev) +{ + struct abtn_softc *sc; + + sc = device_get_softc(dev); + sc->sc_dev = dev; + + sc->handler_id = adb_get_device_handler(dev); + + return 0; +} + +static u_int +abtn_receive_packet(device_t dev, u_char status, + u_char command, u_char reg, int len, u_char *data) +{ + u_int cmd; + + cmd = data[0]; + + switch (cmd) { + case 0x0a: /* decrease brightness */ + if (devctl_process_running()) + devctl_notify("PMU", "keys", "brightness", + "notify=down"); + break; + + case 0x09: /* increase brightness */ + if (devctl_process_running()) + devctl_notify("PMU", "keys", "brightness", "notify=up"); + break; + + case 0x08: /* mute */ + case 0x01: /* mute, AV hardware */ + if (devctl_process_running()) + devctl_notify("PMU", "keys", "mute", NULL); + break; + case 0x07: /* decrease volume */ + case 0x02: /* decrease volume, AV hardware */ + if (devctl_process_running()) + devctl_notify("PMU", "keys", "volume", "notify=down"); + break; + case 0x06: /* increase volume */ + case 0x03: /* increase volume, AV hardware */ + if (devctl_process_running()) + devctl_notify("PMU", "keys", "volume", "notify=up"); + break; + case 0x0c: /* mirror display key */ + /* Need callback to do something with this */ + break; + case 0x0b: /* eject tray */ + if (devctl_process_running()) + devctl_notify("PMU", "keys", "eject", NULL); + case 0x7f: /* numlock */ + /* Need callback to do something with this */ + break; + + default: +#ifdef DEBUG + if ((cmd & ~0x7f) == 0) + device_printf(dev, "unknown ADB button 0x%x\n", cmd); +#endif + break; + } + return 0; +} + diff --git a/sys/dev/adb/adb_kbd.c b/sys/dev/adb/adb_kbd.c index e66b5b21608d..e69c4db47dcb 100644 --- a/sys/dev/adb/adb_kbd.c +++ b/sys/dev/adb/adb_kbd.c @@ -35,12 +35,15 @@ #include #include #include +#include #include #include "opt_kbd.h" #include #include +#include +#include #include #include @@ -55,6 +58,7 @@ static int adb_kbd_probe(device_t dev); static int adb_kbd_attach(device_t dev); static int adb_kbd_detach(device_t dev); static void akbd_repeat(void *xsc); +static int adb_fn_keys(SYSCTL_HANDLER_ARGS); static u_int adb_kbd_receive_packet(device_t dev, u_char status, u_char command, u_char reg, int len, u_char *data); @@ -282,6 +286,8 @@ adb_kbd_attach(device_t dev) { struct adb_kbd_softc *sc; keyboard_switch_t *sw; + uint32_t fkeys; + phandle_t handle; sw = kbd_get_switch(KBD_DRIVER_NAME); if (sw == NULL) { @@ -333,6 +339,40 @@ adb_kbd_attach(device_t dev) adb_set_autopoll(dev,1); + handle = OF_finddevice("mac-io/via-pmu/adb/keyboard"); + if (handle != -1 && OF_getprop(handle, "AAPL,has-embedded-fn-keys", + &fkeys, sizeof(fkeys)) != -1) { + static const char *key_names[] = {"F1", "F2", "F3", "F4", "F5", + "F6", "F7", "F8", "F9", "F10", "F11", "F12"}; + struct sysctl_ctx_list *ctx; + struct sysctl_oid *tree; + int i; + + if (bootverbose) + device_printf(dev, "Keyboard has embedded Fn keys\n"); + + for (i = 0; i < 12; i++) { + uint32_t keyval; + char buf[3]; + if (OF_getprop(handle, key_names[i], &keyval, + sizeof(keyval)) < 0) + continue; + buf[0] = 1; + buf[1] = i+1; + buf[2] = keyval; + adb_write_register(dev, 0, 3, buf); + } + adb_write_register(dev, 1, 2, &(uint16_t){0}); + + ctx = device_get_sysctl_ctx(dev); + tree = device_get_sysctl_tree(dev); + + SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, + "fn_keys_function_as_primary", CTLTYPE_INT | CTLFLAG_RW, sc, + 0, adb_fn_keys, "I", + "Set the Fn keys to be their F-key type as default"); + } + return (0); } @@ -383,6 +423,13 @@ adb_kbd_receive_packet(device_t dev, u_char status, return (0); mtx_lock(&sc->sc_mutex); + /* 0x7f is always the power button */ + if (data[0] == 0x7f && devctl_process_running()) { + devctl_notify("PMU", "Button", "pressed", NULL); + return (0); + } else if (data[0] == 0xff) { + return (0); /* Ignore power button release. */ + } if ((data[0] & 0x7f) == 57 && sc->buffers < 7) { /* Fake the down/up cycle for caps lock */ sc->buffer[sc->buffers++] = data[0] & 0x7f; @@ -390,7 +437,6 @@ adb_kbd_receive_packet(device_t dev, u_char status, } else { sc->buffer[sc->buffers++] = data[0]; } - if (sc->buffer[sc->buffers-1] < 0xff) sc->last_press = sc->buffer[sc->buffers-1]; @@ -814,5 +860,29 @@ akbd_modevent(module_t mod, int type, void *data) return (0); } +static int +adb_fn_keys(SYSCTL_HANDLER_ARGS) +{ + struct adb_kbd_softc *sc = arg1; + int error; + uint16_t is_fn_enabled; + unsigned int is_fn_enabled_sysctl; + + adb_read_register(sc->sc_dev, 1, &is_fn_enabled); + is_fn_enabled &= 1; + is_fn_enabled_sysctl = is_fn_enabled; + error = sysctl_handle_int(oidp, &is_fn_enabled_sysctl, 0, req); + + if (error || !req->newptr) + return (error); + + is_fn_enabled = is_fn_enabled_sysctl; + if (is_fn_enabled != 1 && is_fn_enabled != 0) + return (EINVAL); + + adb_write_register(sc->sc_dev, 1, 2, &is_fn_enabled); + return (0); +} + DEV_MODULE(akbd, akbd_modevent, NULL);