[PATCH evdev 3/4] Add a property to toggle fnmode on Apple keyboards

Jeremy Huddleston jeremyhu at apple.com
Wed May 18 07:45:06 PDT 2011


Hey Peter,

I'm guessing that proxying this property in the driver will make it easier for generalized preference panes to be created based on Xinput.  I seem to recall filing a bug somewhere a couple years ago about the lack of GUI surrounding this option in Gnome's preferences, so this gets a big:

Acked-by: Jeremy Huddleston <jeremyhu at apple.com>
Reviewed-by: Jeremy Huddleston <jeremyhu at apple.com>

--Jeremy

On May 17, 2011, at 22:00, Peter Hutterer wrote:

> On Apple keyboards, the multimedia function keys are overlaid with the F
> keys. F1 is also BrightnessDown, F10 is Mute, etc. The kernel provides a
> tweak to enable/disable this.
> 
> /sys/module/hid_apple/parameters/fnmode
>    0 .. keyboard sends Fx keys
>    1 .. keyboard sends multimedia keys
> 
> Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
> ---
> include/evdev-properties.h |    3 +
> src/Makefile.am            |    3 +-
> src/apple.c                |  168 ++++++++++++++++++++++++++++++++++++++++++++
> src/evdev.c                |    1 +
> src/evdev.h                |    1 +
> 5 files changed, 175 insertions(+), 1 deletions(-)
> create mode 100644 src/apple.c
> 
> diff --git a/include/evdev-properties.h b/include/evdev-properties.h
> index 16f2af7..8887cd1 100644
> --- a/include/evdev-properties.h
> +++ b/include/evdev-properties.h
> @@ -75,4 +75,7 @@
> /* CARD32 */
> #define EVDEV_PROP_THIRDBUTTON_THRESHOLD "Evdev Third Button Emulation Threshold"
> 
> +/* BOOL, 1 value, true → send function keys, false → send multimedia keys */
> +#define EVDEV_PROP_APPLE_FNMODE "Evdev Apple Function Keys"
> +
> #endif
> diff --git a/src/Makefile.am b/src/Makefile.am
> index d1efe53..b3a5671 100644
> --- a/src/Makefile.am
> +++ b/src/Makefile.am
> @@ -37,5 +37,6 @@ AM_CPPFLAGS =-I$(top_srcdir)/include
>                                emuMB.c \
>                                emuThird.c \
>                                emuWheel.c \
> -                               draglock.c
> +                               draglock.c \
> +                               apple.c
> 
> diff --git a/src/apple.c b/src/apple.c
> new file mode 100644
> index 0000000..1a82e2a
> --- /dev/null
> +++ b/src/apple.c
> @@ -0,0 +1,168 @@
> +/*
> + * Copyright © 2011 Red Hat, Inc.
> + *
> + * Permission to use, copy, modify, distribute, and sell this software
> + * and its documentation for any purpose is hereby granted without
> + * fee, provided that the above copyright notice appear in all copies
> + * and that both that copyright notice and this permission notice
> + * appear in supporting documentation, and that the name of Red Hat
> + * not be used in advertising or publicity pertaining to distribution
> + * of the software without specific, written prior permission.  Red
> + * Hat makes no representations about the suitability of this software
> + * for any purpose.  It is provided "as is" without express or implied
> + * warranty.
> + *
> + * THE AUTHORS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
> + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
> + * NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
> + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
> + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
> + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
> + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> + *
> + * Authors:
> + *	Peter Hutterer (peter.hutterer at redhat.com)
> + */
> +
> +#ifdef HAVE_CONFIG_H
> +#include "config.h"
> +#endif
> +
> +#include <evdev.h>
> +#include <evdev-properties.h>
> +#include <errno.h>
> +#include <sys/types.h>
> +#include <sys/stat.h>
> +#include <fcntl.h>
> +#include <unistd.h>
> +
> +#include <exevents.h>
> +#include <xf86.h>
> +#include <xf86Xinput.h>
> +#include <X11/Xatom.h>
> +
> +/* Apple-specific controls.
> + *
> + * On Apple keyboards, the multimedia function keys are overlaid with the F
> + * keys. F1 is also BrightnessDown, F10 is Mute, etc. The kernel provides a
> + * tweak to enable/disable this.
> + *
> + * /sys/module/hid_apple/parameters/fnmode
> + *     0 .. keyboard sends Fx keys
> + *     1 .. keyboard sends multimedia keys
> + */
> +
> +#define FNMODE_PATH "/sys/module/hid_apple/parameters/fnmode"
> +#define APPLE_VENDOR 0x5ac
> +#define APPLE_KEYBOARD 0x220
> +
> +static Atom prop_fnmode;
> +static Bool fnmode_readonly; /* set if we can only read fnmode */
> +
> +
> +/**
> + * @retval 0 fnmode is set to function keys
> + * @retval 1 fnmode is set to multimedia keys
> + * @retval -1 Error, see errno
> + */
> +static int
> +get_fnmode(void)
> +{
> +    int fd;
> +    char retvalue;
> +
> +    fd = open(FNMODE_PATH, O_RDWR);
> +    if (fd < 0)
> +    {
> +        if (errno == EACCES)
> +        {
> +            fnmode_readonly = TRUE;
> +            fd = open(FNMODE_PATH, O_RDONLY);
> +        }
> +    }
> +
> +    if (fd < 0)
> +        return -1;
> +
> +    if (read(fd, &retvalue, 1) != 1)
> +        return -1;
> +
> +    close(fd);
> +
> +    if (retvalue != '0' && retvalue != '1')
> +    {
> +        xf86Msg(X_ERROR, "Invalid fnmode value: %c\n", retvalue);
> +        errno = EINVAL;
> +        return -1;
> +    }
> +
> +    return retvalue == '1';
> +}
> +
> +/**
> + * @param fnmode 0 for function keys,  1 for multimedia keys
> + * @return 0 on success, -1 otherwise (check errno)
> + */
> +static int
> +set_fnmode(Bool fnmode)
> +{
> +    int fd;
> +    char mode;
> +
> +    fd = open(FNMODE_PATH, O_WRONLY);
> +    if (fd < 0)
> +        return -1;
> +
> +    mode = fnmode ? '1' : '0';
> +
> +    if (write(fd, &mode, 1) != 1)
> +        return -1;
> +
> +    close(fd);
> +
> +    return 0;
> +}
> +
> +static int
> +EvdevAppleSetProperty(DeviceIntPtr dev, Atom atom,
> +                      XIPropertyValuePtr val, BOOL checkonly)
> +{
> +    if (atom == prop_fnmode)
> +    {
> +        if (val->format != 8 || val->type != XA_INTEGER)
> +            return BadMatch;
> +
> +        if (fnmode_readonly)
> +            return BadAccess;
> +
> +        if (!checkonly)
> +            set_fnmode(*(CARD8*)val->data);
> +    }
> +
> +    return Success;
> +}
> +
> +void
> +EvdevAppleInitProperty(DeviceIntPtr dev)
> +{
> +    InputInfoPtr pInfo  = dev->public.devicePrivate;
> +    EvdevPtr     pEvdev = pInfo->private;
> +    char fnmode;
> +
> +    if (pEvdev->id_vendor != APPLE_VENDOR ||
> +        pEvdev->id_product != APPLE_KEYBOARD)
> +        return;
> +
> +    fnmode = get_fnmode();
> +    if (fnmode == -1)
> +    {
> +        xf86IDrvMsg(pInfo, X_ERROR, "Failed to get fnmode (%s)\n", strerror(errno));
> +        return;
> +    }
> +
> +    prop_fnmode = MakeAtom(EVDEV_PROP_APPLE_FNMODE, strlen(EVDEV_PROP_APPLE_FNMODE), TRUE);
> +    XIChangeDeviceProperty(dev, prop_fnmode, XA_INTEGER, 8,
> +                           PropModeReplace, 1, &fnmode, FALSE);
> +    XISetDevicePropertyDeletable(dev, prop_fnmode, FALSE);
> +    XIRegisterPropertyHandler(dev, EvdevAppleSetProperty, NULL, NULL);
> +}
> diff --git a/src/evdev.c b/src/evdev.c
> index d93adb4..38868c4 100644
> --- a/src/evdev.c
> +++ b/src/evdev.c
> @@ -1359,6 +1359,7 @@ EvdevInit(DeviceIntPtr device)
>     Evdev3BEmuInitProperty(device);
>     EvdevWheelEmuInitProperty(device);
>     EvdevDragLockInitProperty(device);
> +    EvdevAppleInitProperty(device);
> 
>     return Success;
> }
> diff --git a/src/evdev.h b/src/evdev.h
> index 1741e59..6434c3f 100644
> --- a/src/evdev.h
> +++ b/src/evdev.h
> @@ -243,4 +243,5 @@ void EvdevMBEmuInitProperty(DeviceIntPtr);
> void Evdev3BEmuInitProperty(DeviceIntPtr);
> void EvdevWheelEmuInitProperty(DeviceIntPtr);
> void EvdevDragLockInitProperty(DeviceIntPtr);
> +void EvdevAppleInitProperty(DeviceIntPtr);
> #endif
> -- 
> 1.7.4.4
> 
> _______________________________________________
> xorg-devel at lists.x.org: X.Org development
> Archives: http://lists.x.org/archives/xorg-devel
> Info: http://lists.x.org/mailman/listinfo/xorg-devel



More information about the xorg-devel mailing list