[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