From nobody Thu Apr 23 05:10:59 2026 X-Original-To: dev-commits-src-all@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4g1PLw6KVtz6bbrd for ; Thu, 23 Apr 2026 05:11:04 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R13" (not verified)) by mx1.freebsd.org (Postfix) with ESMTPS id 4g1PLw2YNSz3Gt0 for ; Thu, 23 Apr 2026 05:11:04 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1776921064; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=EUKDfva3et6Q8amerXYjwdrI6EP7/ihSzq5r9BZXpWA=; b=ORIjJQdMwAfYXMxttWTyIDkLxmom1Zbo1ymwO1M0yyv3SV/r9sAstH0Jf55Gs627T8feMx P2L3ck5OHW0gi906Q5fUUF90eaYl/xi5kpejN/ZXCgb+JrgrEnAHaQkEA3m/kKwTG0GC34 F3uEa2AgAqXQ/VPT/+3+cALxXT70j8D0OGY++VEDIKIMaLLL6tYLp/aYpN4QV28qRSoFTG pGG7FonJiKRW6WD0+flc5iaUGfPpT68/+Vo04Wd+UdfETF6s/YmRh/iUgfdou4bzy0DLy5 vGbG08Ub+aVFxzzNYjcQcTZ2oN0V9C4z/RAMw1nAddTDSRbMCN+jpFFKL1n59g== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1776921064; a=rsa-sha256; cv=none; b=ffbQbbECjVL4KQewFnCfEZNg0nqSXGsguL1hUGjDGE1nCKGRQ73ieJg86Fau+F+83IWiqd DyGO+mUklp3Jn/yxV0bT3U8GzFpIcfngu+0k7mOaaJ26WrBuit6nYBfsbKrwmzFhDFY8zw NSyBdY5RqnLVugzON11NqZ3KA+VaQu7ifleS5o8IoE3Evj3MwEZtZ02aYIO++OVw7it8RR Uuu+lzeYjNSwkC3ggelUk+2cJNH36EHCLUgIAIKn+1qucKyA5OJNKIB6EMWFR7jI/tIm3c N2xh2xfPx2T1a7/J+54XI0XZpcwj5TOrMsbICbknAm9orRprHblT9YMJexJ3Bw== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1776921064; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=EUKDfva3et6Q8amerXYjwdrI6EP7/ihSzq5r9BZXpWA=; b=Gk5wcxhC3Brewv9o7mkJnt4ywXAfRjfsbTfWjhsxiWmThHu9TCLWz8do6dxglEMPg8lKTZ xbhVThNYqZZbJydicveVeE/MOYtlT6RpIm56a0c9sA8zzWJkQ7wX0zfHRZfZAvL1C6OcVi 1S4/1yzB5IbCUvHdxHuyy+3ocKubVIQlmjhcV+SFupoKlwamGN6uEVRQiw0Jt0x7ZY7I3b P69DPzjALdb8UxrHFOnvmDvzbEuiFdD3dyOuph9XuA+B4SKOWALhuDHWtGnJwPH70DDkq9 aqySe1xv26PUj6spSDibD9rS+iIeTbpMRyrkzRmm+W2mu9zznJ4ka/LanPjASw== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4g1PLw1tbDz12vs for ; Thu, 23 Apr 2026 05:11:04 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 44079 by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Thu, 23 Apr 2026 05:10:59 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org Cc: ~Not Toby <0x2b@0xff.art> From: Vladimir Kondratyev Subject: git: c0e26f7b29dd - main - hkbd/ukbd: sysctls to swap macbook kbd modifiers List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-all@freebsd.org Sender: owner-dev-commits-src-all@FreeBSD.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: wulf X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: c0e26f7b29ddd2d081ac113d64807849e87737a2 Auto-Submitted: auto-generated Date: Thu, 23 Apr 2026 05:10:59 +0000 Message-Id: <69e9a9e3.44079.76d25369@gitrepo.freebsd.org> The branch main has been updated by wulf: URL: https://cgit.FreeBSD.org/src/commit/?id=c0e26f7b29ddd2d081ac113d64807849e87737a2 commit c0e26f7b29ddd2d081ac113d64807849e87737a2 Author: ~Not Toby <0x2b@0xff.art> AuthorDate: 2026-04-23 05:10:05 +0000 Commit: Vladimir Kondratyev CommitDate: 2026-04-23 05:10:05 +0000 hkbd/ukbd: sysctls to swap macbook kbd modifiers Many applications, desktop environments, window managers & text editors favor the usage of Alt or Ctrl over Super (Cmd). On a Macbook it is quite annoying that the Super (Cmd) key gets pride of place by the spacebar. The standard MacBook Cmd key location only really makes sense for macOS or maybe in some tiling wm if Mod4/Super is your main modifier. For most mainstream desktops and window managers, having Alt or Ctrl in that location makes much much more sense. This patch adds two sysctls for swapping either Opt(Alt) or Ctrl with Cmd(Super). Linux has similar sysctls to this; allowing a user to make an Apple keyboard more "orthodox"/useful at a level that takes effect independent of typing context - ie) tty, Xorg and/or wayland. Having a sysctl to do these swaps means that a user doesn't have to faff about with both creating a custom vt keymap AND figure out which magic setxkbmap incantation one needs to make one's keyboard behave as desired across environments. Signed-off-by: ~Not Toby <0x2b@0xff.art> Reviewed by: wulf MFC after: 1 week Pull Request: https://github.com/freebsd/freebsd-src/pull/2141 --- share/man/man4/hkbd.4 | 14 +++++++++++++- share/man/man4/ukbd.4 | 14 +++++++++++++- sys/dev/hid/hkbd.c | 38 ++++++++++++++++++++++++++++++++++++++ sys/dev/usb/input/ukbd.c | 38 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 102 insertions(+), 2 deletions(-) diff --git a/share/man/man4/hkbd.4 b/share/man/man4/hkbd.4 index 6e936b198618..4aefad10846c 100644 --- a/share/man/man4/hkbd.4 +++ b/share/man/man4/hkbd.4 @@ -22,7 +22,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd September 12, 2020 +.Dd April 23, 2026 .Dt HKBD 4 .Os .Sh NAME @@ -151,6 +151,18 @@ tunables: Debug output level, where 0 is debugging disabled and larger values increase debug message verbosity. Default is 0. +.It Va hw.hid.hkbd.apple_swap_cmd_opt +Swap the Command & Option keys on Apple keyboards if set to 1. +Default is 0. +.It Va hw.hid.hkbd.apple_swap_cmd_ctl +Swap the Command & Control keys on Apple keyboards if set to 1. +Default is 0. +.It Va hw.hid.hkbd.apple_fn_mode +Direct access to media keys without holding Fn if set to 1. +Default is 0. +.It Va hw.hid.hkbd.no_leds +Disables setting of keyboard LEDs if set to 1. +Default is 0. .El .Sh FILES .Bl -tag -width ".Pa /dev/input/event*" -compact diff --git a/share/man/man4/ukbd.4 b/share/man/man4/ukbd.4 index 14d6cca51e6f..003600aac084 100644 --- a/share/man/man4/ukbd.4 +++ b/share/man/man4/ukbd.4 @@ -22,7 +22,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd April 24, 2018 +.Dd April 23, 2026 .Dt UKBD 4 .Os .Sh NAME @@ -156,6 +156,18 @@ tunables: Debug output level, where 0 is debugging disabled and larger values increase debug message verbosity. Default is 0. +.It Va hw.usb.ukbd.apple_swap_cmd_opt +Swap the Command & Option keys on Apple keyboards if set to 1. +Default is 0. +.It Va hw.usb.ukbd.apple_swap_cmd_ctl +Swap the Command & Control keys on Apple keyboards if set to 1. +Default is 0. +.It Va hw.usb.ukbd.apple_fn_mode +Direct access to media keys without holding Fn if set to 1. +Default is 0. +.It Va hw.usb.ukbd.no_leds +Disables setting of keyboard LEDs if set to 1. +Default is 0. .El .Sh FILES .Bl -tag -width ".Pa /dev/kbd*" -compact diff --git a/sys/dev/hid/hkbd.c b/sys/dev/hid/hkbd.c index c98f4be69169..edfd3f5d4eff 100644 --- a/sys/dev/hid/hkbd.c +++ b/sys/dev/hid/hkbd.c @@ -100,6 +100,8 @@ static int hkbd_debug = 0; #endif static int hkbd_no_leds = 0; static int hkbd_apple_fn_mode = 0; +static int hkbd_apple_swap_cmd_ctl = 0; +static int hkbd_apple_swap_cmd_opt = 0; static SYSCTL_NODE(_hw_hid, OID_AUTO, hkbd, CTLFLAG_RW, 0, "USB keyboard"); #ifdef HID_DEBUG @@ -110,6 +112,10 @@ SYSCTL_INT(_hw_hid_hkbd, OID_AUTO, no_leds, CTLFLAG_RWTUN, &hkbd_no_leds, 0, "Disables setting of keyboard leds"); SYSCTL_INT(_hw_hid_hkbd, OID_AUTO, apple_fn_mode, CTLFLAG_RWTUN, &hkbd_apple_fn_mode, 0, "0 = Fn + F1..12 -> media, 1 = F1..F12 -> media"); +SYSCTL_INT(_hw_hid_hkbd, OID_AUTO, apple_swap_cmd_ctl, CTLFLAG_RWTUN, + &hkbd_apple_swap_cmd_ctl, 0, "Swap Command & Control keys"); +SYSCTL_INT(_hw_hid_hkbd, OID_AUTO, apple_swap_cmd_opt, CTLFLAG_RWTUN, + &hkbd_apple_swap_cmd_opt, 0, "Swap Command & Option keys"); #define INPUT_EPOCH global_epoch_preempt @@ -664,6 +670,30 @@ hkbd_apple_fn_media(uint32_t keycode) } } +static uint32_t +hkbd_apple_doswap_cmd_ctl(uint32_t keycode) +{ + switch (keycode) { + case 0xe3: return 0xe0; /* LCMD -> LCTL */ + case 0xe7: return 0xe4; /* RCMD -> RCTL */ + case 0xe0: return 0xe3; /* LCTL -> LCMD */ + case 0xe4: return 0xe7; /* RCTL -> RCMD */ + default: return keycode; + } +} + +static uint32_t +hkbd_apple_doswap_cmd_opt(uint32_t keycode) +{ + switch (keycode) { + case 0xe3: return 0xe2; /* LCMD -> ROPT */ + case 0xe7: return 0xe6; /* RCMD -> ROPT */ + case 0xe2: return 0xe3; /* LOPT -> LCMD */ + case 0xe6: return 0xe7; /* ROPT -> RCMD */ + default: return keycode; + } +} + static uint32_t hkbd_apple_swap(uint32_t keycode) { @@ -765,6 +795,10 @@ hkbd_intr_callback(void *context, void *data, hid_size_t len) key = hkbd_apple_fn(key); if (apply_apple_fn_media) key = hkbd_apple_fn_media(key); + if (hkbd_apple_swap_cmd_ctl) + key = hkbd_apple_doswap_cmd_ctl(key); + if (hkbd_apple_swap_cmd_opt) + key = hkbd_apple_doswap_cmd_opt(key); if (sc->sc_flags & HKBD_FLAG_APPLE_SWAP) key = hkbd_apple_swap(key); if (key == KEY_NONE || key >= HKBD_NKEYCODE) @@ -780,6 +814,10 @@ hkbd_intr_callback(void *context, void *data, hid_size_t len) key = hkbd_apple_fn(key); if (apply_apple_fn_media) key = hkbd_apple_fn_media(key); + if (hkbd_apple_swap_cmd_ctl) + key = hkbd_apple_doswap_cmd_ctl(key); + if (hkbd_apple_swap_cmd_opt) + key = hkbd_apple_doswap_cmd_opt(key); if (sc->sc_flags & HKBD_FLAG_APPLE_SWAP) key = hkbd_apple_swap(key); if (key == KEY_NONE || key == KEY_ERROR || key >= HKBD_NKEYCODE) diff --git a/sys/dev/usb/input/ukbd.c b/sys/dev/usb/input/ukbd.c index 7a33a9ad2efe..104e51c082c3 100644 --- a/sys/dev/usb/input/ukbd.c +++ b/sys/dev/usb/input/ukbd.c @@ -99,6 +99,8 @@ static int ukbd_debug = 0; static int ukbd_no_leds = 0; static int ukbd_pollrate = 0; static int ukbd_apple_fn_mode = 0; +static int ukbd_apple_swap_cmd_ctl = 0; +static int ukbd_apple_swap_cmd_opt = 0; static SYSCTL_NODE(_hw_usb, OID_AUTO, ukbd, CTLFLAG_RW | CTLFLAG_MPSAFE, 0, "USB keyboard"); @@ -112,6 +114,10 @@ SYSCTL_INT(_hw_usb_ukbd, OID_AUTO, pollrate, CTLFLAG_RWTUN, &ukbd_pollrate, 0, "Force this polling rate, 1-1000Hz"); SYSCTL_INT(_hw_usb_ukbd, OID_AUTO, apple_fn_mode, CTLFLAG_RWTUN, &ukbd_apple_fn_mode, 0, "0 = Fn + F1..12 -> media, 1 = F1..F12 -> media"); +SYSCTL_INT(_hw_usb_ukbd, OID_AUTO, apple_swap_cmd_ctl, CTLFLAG_RWTUN, + &ukbd_apple_swap_cmd_ctl, 0, "Swap Command & Control keys"); +SYSCTL_INT(_hw_usb_ukbd, OID_AUTO, apple_swap_cmd_opt, CTLFLAG_RWTUN, + &ukbd_apple_swap_cmd_opt, 0, "Swap Command & Option keys"); #define UKBD_EMULATE_ATSCANCODE 1 #define UKBD_DRIVER_NAME "ukbd" @@ -720,6 +726,30 @@ ukbd_apple_fn_media(uint32_t keycode) } } +static uint32_t +ukbd_apple_doswap_cmd_ctl(uint32_t keycode) +{ + switch (keycode) { + case 0xe3: return 0xe0; /* LCMD -> LCTL */ + case 0xe7: return 0xe4; /* RCMD -> RCTL */ + case 0xe0: return 0xe3; /* LCTL -> LCMD */ + case 0xe4: return 0xe7; /* RCTL -> RCMD */ + default: return keycode; + } +} + +static uint32_t +ukbd_apple_doswap_cmd_opt(uint32_t keycode) +{ + switch (keycode) { + case 0xe3: return 0xe2; /* LCMD -> ROPT */ + case 0xe7: return 0xe6; /* RCMD -> ROPT */ + case 0xe2: return 0xe3; /* LOPT -> LCMD */ + case 0xe6: return 0xe7; /* ROPT -> RCMD */ + default: return keycode; + } +} + static uint32_t ukbd_apple_swap(uint32_t keycode) { @@ -839,6 +869,10 @@ ukbd_intr_callback(struct usb_xfer *xfer, usb_error_t error) key = ukbd_apple_fn(key); if (apply_apple_fn_media) key = ukbd_apple_fn_media(key); + if (ukbd_apple_swap_cmd_ctl) + key = ukbd_apple_doswap_cmd_ctl(key); + if (ukbd_apple_swap_cmd_opt) + key = ukbd_apple_doswap_cmd_opt(key); if (sc->sc_flags & UKBD_FLAG_APPLE_SWAP) key = ukbd_apple_swap(key); if (key == KEY_NONE || key >= UKBD_NKEYCODE) @@ -853,6 +887,10 @@ ukbd_intr_callback(struct usb_xfer *xfer, usb_error_t error) key = ukbd_apple_fn(key); if (apply_apple_fn_media) key = ukbd_apple_fn_media(key); + if (ukbd_apple_swap_cmd_ctl) + key = ukbd_apple_doswap_cmd_ctl(key); + if (ukbd_apple_swap_cmd_opt) + key = ukbd_apple_doswap_cmd_opt(key); if (sc->sc_flags & UKBD_FLAG_APPLE_SWAP) key = ukbd_apple_swap(key); if (key == KEY_NONE || key == KEY_ERROR || key >= UKBD_NKEYCODE)