Skip to content

Instantly share code, notes, and snippets.

@fauxpark
Last active October 21, 2024 11:36
Show Gist options
  • Save fauxpark/010dcf5d6377c3a71ac98ce37414c6c4 to your computer and use it in GitHub Desktop.
Save fauxpark/010dcf5d6377c3a71ac98ce37414c6c4 to your computer and use it in GitHub Desktop.
QMK Apple Fn

QMK Apple Fn Key

This patch adds support for the Apple Fn key, which unlike most keyboards with Fn keys, is actually sent over the wire. It works by repurposing the reserved byte in the keyboard report to represent the KeyboardFn usage of the AppleVendor Top Case usage page. When the Fn key is pressed, the value of this byte becomes 1.

To apply this patch, download the below file, cd to your qmk_firmware repository in your preferred terminal, and run git apply /path/to/applefn.patch. Then, add the QK_APPLE_FN keycode (or AP_FN for short) to your keymap.

There are a couple of caveats to this implementation that are important to be aware of. Firstly, it is not compatible with NKRO, as QMK's NKRO report format has no reserved byte - it is part of the 6KRO report for compatibility with the HID boot protocol. Thus you must set NKRO_ENABLE = no in your keymap's rules.mk. You will also need to redefine the USB Vendor and Product IDs in your keymap's config.h to that of a genuine Apple keyboard* in order for macOS to recognise the Fn key:

#undef VENDOR_ID
#define VENDOR_ID 0x05AC
#undef PRODUCT_ID
#define PRODUCT_ID <pid>

This is the primary reason this patch has not been integrated into upstream QMK - Apple would probably not be too happy about others using their vendor ID, and a feature that relies on the VID/PID pair being set to a specific value is not particularly ideal anyway.

See qmk/qmk_firmware#2179 for a little more info and discussion.

* It appears that the functionality of certain F keys can differ depending on the PID, likely because they have evolved over time on real Apple keyboards.

diff --git a/builddefs/common_features.mk b/builddefs/common_features.mk
index 18f8b0bbfc..4ef3e230e4 100644
--- a/builddefs/common_features.mk
+++ b/builddefs/common_features.mk
@@ -878,6 +878,10 @@ ifeq ($(strip $(JOYSTICK_ENABLE)), yes)
endif
endif
+ifeq ($(strip $(APPLE_FN_ENABLE)), yes)
+ OPT_DEFS += -DAPPLE_FN_ENABLE
+endif
+
USBPD_ENABLE ?= no
VALID_USBPD_DRIVER_TYPES = custom vendor
USBPD_DRIVER ?= vendor
diff --git a/data/constants/keycodes/keycodes_0.0.2_applefn.hjson b/data/constants/keycodes/keycodes_0.0.2_applefn.hjson
new file mode 100644
index 0000000000..1378413a9e
--- /dev/null
+++ b/data/constants/keycodes/keycodes_0.0.2_applefn.hjson
@@ -0,0 +1,11 @@
+{
+ "keycodes": {
+ "0x5300": {
+ "group": "apple_fn",
+ "key": "QK_APPLE_FN",
+ "aliases": [
+ "AP_FN"
+ ]
+ }
+ }
+}
diff --git a/quantum/action.c b/quantum/action.c
index 6368f7398c..d9bd34f681 100644
--- a/quantum/action.c
+++ b/quantum/action.c
@@ -555,6 +555,18 @@ void process_action(keyrecord_t *record, action_t action) {
}
break;
#endif // EXTRAKEY_ENABLE
+#ifdef APPLE_FN_ENABLE
+ /* Apple Fn */
+ case ACT_APPLE_FN:
+ if (event.pressed) {
+ add_apple_fn(keyboard_report);
+ send_keyboard_report();
+ } else {
+ del_apple_fn(keyboard_report);
+ send_keyboard_report();
+ }
+ break;
+#endif
/* Mouse key */
case ACT_MOUSEKEY:
register_mouse(action.key.code, event.pressed);
@@ -1196,6 +1208,9 @@ void debug_action(action_t action) {
case ACT_USAGE:
ac_dprintf("ACT_USAGE");
break;
+ case ACT_APPLE_FN:
+ dprint("ACT_APPLE_FN");
+ break;
case ACT_MOUSEKEY:
ac_dprintf("ACT_MOUSEKEY");
break;
diff --git a/quantum/action_code.h b/quantum/action_code.h
index d9a575b518..f347010c8d 100644
--- a/quantum/action_code.h
+++ b/quantum/action_code.h
@@ -53,7 +53,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
* ACT_SWAP_HANDS(0110):
* 0110|xxxx| keycode Swap hands (keycode on tap, or options)
*
- * 0111|xxxx xxxx xxxx (reserved)
+ * ACT_APPLE_FN(0111):
+ * 0111|0000|0000|0000 Apple Fn
*
* Layer Actions(10xx)
* -------------------
@@ -95,6 +96,8 @@ enum action_kind_id {
ACT_MOUSEKEY = 0b0101,
/* One-hand Support */
ACT_SWAP_HANDS = 0b0110,
+ /* Apple Fn */
+ ACT_APPLE_FN = 0b0111,
/* Layer Actions */
ACT_LAYER = 0b1000,
ACT_LAYER_MODS = 0b1001,
@@ -182,6 +185,7 @@ enum usage_pages {
#define ACTION_USAGE_SYSTEM(id) ACTION(ACT_USAGE, PAGE_SYSTEM << 10 | (id))
#define ACTION_USAGE_CONSUMER(id) ACTION(ACT_USAGE, PAGE_CONSUMER << 10 | (id))
+#define ACTION_APPLE_FN() ACTION(ACT_APPLE_FN, 0)
#define ACTION_MOUSEKEY(key) ACTION(ACT_MOUSEKEY, key)
/** \brief Layer Actions
diff --git a/quantum/keycodes.h b/quantum/keycodes.h
index bbf10da36d..b8e894a399 100644
--- a/quantum/keycodes.h
+++ b/quantum/keycodes.h
@@ -310,6 +310,7 @@ enum qk_keycode_defines {
KC_RIGHT_SHIFT = 0x00E5,
KC_RIGHT_ALT = 0x00E6,
KC_RIGHT_GUI = 0x00E7,
+ QK_APPLE_FN = 0x5300,
QK_SWAP_HANDS_TOGGLE = 0x56F0,
QK_SWAP_HANDS_TAP_TOGGLE = 0x56F1,
QK_SWAP_HANDS_MOMENTARY_ON = 0x56F2,
@@ -938,6 +939,7 @@ enum qk_keycode_defines {
KC_RGUI = KC_RIGHT_GUI,
KC_RCMD = KC_RIGHT_GUI,
KC_RWIN = KC_RIGHT_GUI,
+ AP_FN = QK_APPLE_FN,
SH_TOGG = QK_SWAP_HANDS_TOGGLE,
SH_TT = QK_SWAP_HANDS_TAP_TOGGLE,
SH_MON = QK_SWAP_HANDS_MOMENTARY_ON,
@@ -1406,6 +1408,7 @@ enum qk_keycode_defines {
#define IS_CONSUMER_KEYCODE(code) ((code) >= KC_AUDIO_MUTE && (code) <= KC_LAUNCHPAD)
#define IS_MOUSE_KEYCODE(code) ((code) >= KC_MS_UP && (code) <= KC_MS_ACCEL2)
#define IS_MODIFIER_KEYCODE(code) ((code) >= KC_LEFT_CTRL && (code) <= KC_RIGHT_GUI)
+#define IS_APPLE_FN_KEYCODE(code) ((code) >= QK_APPLE_FN && (code) <= QK_APPLE_FN)
#define IS_SWAP_HANDS_KEYCODE(code) ((code) >= QK_SWAP_HANDS_TOGGLE && (code) <= QK_SWAP_HANDS_ONE_SHOT)
#define IS_MAGIC_KEYCODE(code) ((code) >= QK_MAGIC_SWAP_CONTROL_CAPS_LOCK && (code) <= QK_MAGIC_TOGGLE_ESCAPE_CAPS_LOCK)
#define IS_MIDI_KEYCODE(code) ((code) >= QK_MIDI_ON && (code) <= QK_MIDI_PITCH_BEND_UP)
diff --git a/quantum/keymap_common.c b/quantum/keymap_common.c
index 9a67fad278..36a0b309be 100644
--- a/quantum/keymap_common.c
+++ b/quantum/keymap_common.c
@@ -70,6 +70,11 @@ action_t action_for_keycode(uint16_t keycode) {
case KC_AUDIO_MUTE ... KC_LAUNCHPAD:
action.code = ACTION_USAGE_CONSUMER(KEYCODE2CONSUMER(keycode));
break;
+#endif
+#ifdef APPLE_FN_ENABLE
+ case QK_APPLE_FN:
+ action.code = ACTION_APPLE_FN();
+ break;
#endif
case KC_MS_UP ... KC_MS_ACCEL2:
action.code = ACTION_MOUSEKEY(keycode);
diff --git a/tmk_core/protocol/report.c b/tmk_core/protocol/report.c
index 1ba3be4604..b53d3f687b 100644
--- a/tmk_core/protocol/report.c
+++ b/tmk_core/protocol/report.c
@@ -299,3 +299,13 @@ __attribute__((weak)) bool has_mouse_report_changed(report_mouse_t* new_report,
return changed;
}
#endif
+
+#ifdef APPLE_FN_ENABLE
+void add_apple_fn(report_keyboard_t* keyboard_report) {
+ keyboard_report->reserved = 1;
+}
+
+void del_apple_fn(report_keyboard_t* keyboard_report) {
+ keyboard_report->reserved = 0;
+}
+#endif
diff --git a/tmk_core/protocol/report.h b/tmk_core/protocol/report.h
index 9d415a3bfd..8c65b40386 100644
--- a/tmk_core/protocol/report.h
+++ b/tmk_core/protocol/report.h
@@ -348,6 +348,11 @@ void clear_keys_from_report(report_keyboard_t* keyboard_report);
bool has_mouse_report_changed(report_mouse_t* new_report, report_mouse_t* old_report);
#endif
+#ifdef APPLE_FN_ENABLE
+void add_apple_fn(report_keyboard_t* keyboard_report);
+void del_apple_fn(report_keyboard_t* keyboard_report);
+#endif
+
#ifdef __cplusplus
}
#endif
diff --git a/tmk_core/protocol/usb_descriptor.c b/tmk_core/protocol/usb_descriptor.c
index e215c90900..e38c0d37f7 100644
--- a/tmk_core/protocol/usb_descriptor.c
+++ b/tmk_core/protocol/usb_descriptor.c
@@ -75,10 +75,22 @@ const USB_Descriptor_HIDReport_Datatype_t PROGMEM KeyboardReport[] = {
HID_RI_REPORT_COUNT(8, 0x08),
HID_RI_REPORT_SIZE(8, 0x01),
HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
+
+#ifdef APPLE_FN_ENABLE
+ HID_RI_USAGE_PAGE(8, 0xFF), // AppleVendor Top Case
+ HID_RI_USAGE(8, 0x03), // KeyboardFn
+ HID_RI_LOGICAL_MINIMUM(8, 0x00),
+ HID_RI_LOGICAL_MAXIMUM(8, 0x01),
+ HID_RI_REPORT_COUNT(8, 0x01),
+ HID_RI_REPORT_SIZE(8, 0x08),
+ HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
+#else
// Reserved (1 byte)
HID_RI_REPORT_COUNT(8, 0x01),
HID_RI_REPORT_SIZE(8, 0x08),
HID_RI_INPUT(8, HID_IOF_CONSTANT),
+#endif
+
// Keycodes (6 bytes)
HID_RI_USAGE_PAGE(8, 0x07), // Keyboard/Keypad
HID_RI_USAGE_MINIMUM(8, 0x00),
diff --git a/tmk_core/protocol/vusb/vusb.c b/tmk_core/protocol/vusb/vusb.c
index d74f375f66..2ade1350ad 100644
--- a/tmk_core/protocol/vusb/vusb.c
+++ b/tmk_core/protocol/vusb/vusb.c
@@ -417,10 +417,22 @@ const PROGMEM uchar keyboard_hid_report[] = {
0x95, 0x08, // Report Count (8)
0x75, 0x01, // Report Size (1)
0x81, 0x02, // Input (Data, Variable, Absolute)
+
+#ifdef APPLE_FN_ENABLE
+ 0x05, 0xFF, // Usage Page (AppleVendor Top Case)
+ 0x09, 0x03, // Usage (KeyboardFn)
+ 0x15, 0x00, // Logical Minimum (0)
+ 0x25, 0x01, // Logical Maximum (1)
+ 0x95, 0x01, // Report Count (1)
+ 0x75, 0x08, // Report Size (8)
+ 0x81, 0x02, // Input (Data, Variable, Absolute)
+#else
// Reserved (1 byte)
0x95, 0x01, // Report Count (1)
0x75, 0x08, // Report Size (8)
0x81, 0x03, // Input (Constant)
+#endif
+
// Keycodes (6 bytes)
0x05, 0x07, // Usage Page (Keyboard/Keypad)
0x19, 0x00, // Usage Minimum (0)
@georgeguimaraes
Copy link

FYI:

I was intrigued by how my Keychron K2's Fn key acts exactly like my Macbook's Fn key (including changing the Touch Bar when I press Fn) and also act like a custom Fn keyboard (to change RGB lights, factory reset, and so on).

Well, Keychron is actually using Apple's vid 0x05AC:

CleanShot 2021-04-26 at 14 51 31

@jc-k91
Copy link

jc-k91 commented Jun 5, 2021

UPDATE 3: Finally had the time to take another look. KC_APFN works perfectly now after disabling NKRO. I'm stupid lol.

UPDATE 2: Looks like this patch added the Apple media key functionality, but the KC_APFN key doesn't do anything for me. Double checked the code I copied to manually patch, and I'm still playing around with different configurations. I'll post another update if anything changes.

UPDATE: I solved this by manually copying the added code over, and removing the deleted lines. For me, I did need to change my VID/PID. Using a GMMK Pro for everyone's reference. Thanks!

ORIGINAL:
Hmm I placed the applefn.patch file in my qmk_firmware directory, and ran git apply applefn.patch, but I'm getting this error:

error: patch failed: common_features.mk:551
error: common_features.mk: patch does not apply
error: patch failed: tmk_core/common/action.c:823
error: tmk_core/common/action.c: patch does not apply

Any ideas on how to address this error?

@chrismanderson
Copy link

Anyone know that the product ID for the Magic Keyboard with Touch ID? I'm looking to use the spotlight/dictate/do not disturb keys. I tried the product id in this gist and while the FN functions, it's acting like a previous magic keyboard and not treating the spotlight/f4 as spotlight.

@fauxpark
Copy link
Author

My suspicion is that it doesn't have a USB PID, it's a wireless keyboard after all.

You can find a list of all the Apple PIDs that Linux knows about here: https://elixir.bootlin.com/linux/latest/source/drivers/hid/hid-ids.h#L93

@chrismanderson
Copy link

I actually tracked down one of the new Magic Keyboards - plugged it into a Mac and turned off Bluetooth on the Mac. It displayed in System information with the vendor id 0x05ac and the product id 0x029c.

I tried that PID in QMK - while the FN 'functioned' in that it was recognized as the Apple-specific FN key, the function row would only trigger F1,F2, etc and not brightness.

When you mention that list of Apple PIDs in that Linux link - does the PID need to be in there as well for this 'hack' to function? I switched back and forth between 0x024f and 0x029c and the former worked every time (though without the updated layout of course) and the latter had a completely non-functioning media row. So odd - but if there's a relationship between that list you linked maybe that's the explanation.

@fauxpark
Copy link
Author

fauxpark commented Sep 27, 2021

while the FN 'functioned' in that it was recognized as the Apple-specific FN key, the function row would only trigger F1,F2, etc and not brightness.

That seems to line up with what this video has to say about the keyboard, from 1:25 to 2:28. I think this is because macOS maps the function keys based on the PID and, presumably, the hardware - hence these new keyboards are only officially compatible with M1 Macs.

When you mention that list of Apple PIDs in that Linux link - does the PID need to be in there as well for this 'hack' to function?

Only if you're using the board on Linux, of course. I just linked that to provide a pool of potentially viable PIDs.

It might be interesting to see what enumeration looks like in Wireshark, maybe there is some difference in the HID report descriptors (obviously ignoring the Touch ID stuff).

@daaaaaaaaaniel
Copy link

I don't understand how this patch works, but I'm trying my best to install it. I downloaded the file applefn.patch and placed it in ~/qmk_firmware/ and then ran the command git apply applefn.patch. But it returns error: corrupt patch at line 235. Whats going on?

@fauxpark
Copy link
Author

fauxpark commented Mar 1, 2022

The patch is out of date; not surprising as we just completed another round of breaking changes. I'll update it in a bit.

@alvaro-prieto
Copy link

Wow! That is really good news @fauxpark !! I use very old version of QMK mainly to keep on using your patch. That would be lovely

@daaaaaaaaaniel
Copy link

@fauxpark, it seems like you updated the patch, but when I run it, I get an error: error: corrupt patch at line 237. Is this an error on my part or is there a problem with the patch?

@fauxpark
Copy link
Author

fauxpark commented Mar 8, 2022

Add an empty line to the end of the file. I've updated to fix it.

@lawkai
Copy link

lawkai commented Mar 17, 2022

I can't get this working with MacOS Monterey on a 2021 MBP.

Checked Karabiner Event viewer, it is reporting the following which looks correct:

type:down            HID usage: 255,3     name:{"apple_vendor_top_case_key_code":"keyboard_fn"}        misc:flags fn
type:up              HID usage: 255,3     name:{"apple_vendor_top_case_key_code":"keyboard_fn"}        misc:

I tried the same keyboard on another Mac with an older MacOS (BigSur), the key works perfectly.

So not sure if Apple has blocked this somehow... or whether there is a bug in MacOS Monterey.

@lawkai
Copy link

lawkai commented Mar 18, 2022

Got this working now after changing Vendor ID and PID.

@marceliwac
Copy link

marceliwac commented Apr 8, 2022

I'm not sure if this is just me being oblivious to the qmk build process, or the lack of documentation in this snippet... To make this work, after applying the patch and updating the vendor and product IDs, I had to set the APPLE_FN_ENABLE to yes and NKRO_ENABLE to no (later of which was mentioned above by @jc-k91 )in my keyboard's rules.mk for it to work.

For anyone else who comes across this issue later on, here's a process I followed, from the very start, to enable Apple Fn key functionality.

  1. Fork the qmk/qmk_firmware repository. This is not strictly necessary, but I found it to be a good way to save my keymaps and the changed configuration afterwards.

  2. Clone your fork locally, download and apply the patch, commit and push changes:

git clone <github_username>/qmk_firmware

cd qmk_firmware

git apply <path_to_patch>/applefn.patch.txt

git commit -am "Applied Apple Fn patch."

git push  <github_username>/qmk_firmware
  1. Install the qmk and use your fork of the firmware, where the patch is applied. I followed the process in the tutorial, specifying my fork of the firmware, like so:
brew install qmk/qmk/qmk

qmk setup <github_username>/qmk_firmware
  1. Create new keymap for your keyboard.
qmk new-keymap -kb <keyboard_model> -km <keymap_name>
  1. Enable the Apple Fn key functionality, and disable NKRO for your keymap.
  • In directory **keyboards/<keyboard_name>/keymaps/<keymap_name> **, open and edit rules.mk, changing the following line:
   NKRO_ENABLE = yes               # Enable N-Key Rollover

to:

   NKRO_ENABLE = no                # Enable N-Key Rollover
   APPLE_FN_ENABLE = yes           # Enable Apple Fn key functionality
  1. Update the keymap, adding the KC_APFN key code in your keymap.c where you want it.

  2. Update the Product ID (PID) and Vendor ID (VID), to a pair that matches Apple-compatible keyboards. The list can be found here. Find a pair that works for you; I tried VID: 0x05AC, PID: 0x0267, as defined here which worked on my planck/rev6_drop.

  • In directory keyboards/<keyboard_name>/keymaps/<keymap_name>, open and edit config.h to update the vendor and product ids:
   define VENDOR_ID       <vendor_id>
   define PRODUCT_ID      <product_id>
  1. Enable bootloader on your keyboard (i.e. reset key if present), use tutorial if needed.

  2. Flash the new keymap to your keyboard.

qmk flash -kb <keyboard_model> -km <keymap_name>

Hope this helps!

@fauxpark
Copy link
Author

fauxpark commented Apr 8, 2022

It's kind of assumed you've already gone through the newbs guide and know how to edit keymaps and use the QMK CLI. I don't think this is the place to reiterate all of that.

You also should never commit to your master branch, as it makes updating from upstream rather painful due to how we manage our git and PR history. If you must commit the patch, switch to a new branch first.

@marceliwac
Copy link

Thanks for the feedback, I think the comment about commiting to master is a valid point! As for re-iterating the newbs guide, I think given the confusion expressed in several comments on this thread and the likelihood of less experienced users looking for a solution to this issue (or simply just trying to add the fn-key functionality without making major changes to the other parts of firmware), I thought a brief walkthrough could be helpful.

@archite
Copy link

archite commented Apr 9, 2022

@fauxpark I would argue that providing the steps to newbs here isn't the worst thing in the world. There are probably a good deal of newbs looking for this support who have limited QMK experience. If I had a complaint, I'd probably point out that the code blocks are badly shown and should include something like this first:

#undef VENDOR_ID
#define VENDOR_ID      <vendor_id>
#undef PRODUCT_ID
#define PRODUCT_ID     <product_id>

By the way, @fauxpark , thanks for taking this patch on and keeping it updated. I intend no disrespect. I just like when people like @marceliwac enjoy something so much like your patch that they spend time making it easier for others to do the same.

@SebSemmi
Copy link

SebSemmi commented Apr 9, 2022

I actually tracked down one of the new Magic Keyboards - plugged it into a Mac and turned off Bluetooth on the Mac. It displayed in System information with the vendor id 0x05ac and the product id 0x029c.

I tried that PID in QMK - while the FN 'functioned' in that it was recognized as the Apple-specific FN key, the function row would only trigger F1,F2, etc and not brightness.

When you mention that list of Apple PIDs in that Linux link - does the PID need to be in there as well for this 'hack' to function? I switched back and forth between 0x024f and 0x029c and the former worked every time (though without the updated layout of course) and the latter had a completely non-functioning media row. So odd - but if there's a relationship between that list you linked maybe that's the explanation.

I try to accomplish the same thing. The product id for the newer Magic Keyboard without Touch ID with the Spotlight/Siri Media keys is 0x029c. But I also have the same problem as you. Did you found a solution?

@chrismanderson
Copy link

I try to accomplish the same thing. The product id for the newer Magic Keyboard without Touch ID with the Spotlight/Siri Media keys is 0x029c. But I also have the same problem as you. Did you found a solution?

I did not and gave up on it unfortunately.

@EthanG45
Copy link

EthanG45 commented Apr 30, 2022

For anyone that has been using this on their keyboard, does it act like the globe key for you? I'm currently struggling to understand if there's a way to properly setup the globe key with QMK. Other manufactures have definitely spoofed the globe key to show up in macOS, my nuphy air75 does at least.

What is confusing to me is that macOS seems to interpret any keyboards sending the old fn key as globe key anyways. This holds true when I use the built-in macOS modifier switch setting to change caps lock on my keychron q1 to send fn. In this case the fn key sent is treated like the globe key. But, when I use the KC_APPLE_FN defined here, it isn't quite treated as the default fn that can be interpreted as globe in macOS.

It'd also be nice to directly interpret the fn key here as globe if possible. I'm trying to dig around to see if this can be done.

Edit: I had my PID and VID flipped lol. fn is now properly interpreted and treated as globe as well. Still the question stands that it'd be interesting to directly implement the new globe key.

@arkku
Copy link

arkku commented Jul 27, 2022

Just in case anyone has the same use case as me: I wanted to make a "virtual Apple Fn" key where the Fn momentary enables a layer (like MO(x)) where I can configure more extensive Fn combos than Apple has done, but also registers as the Fn key on its own (but not in combination with mappings in the momentary layer). So, I added some stuff on top of this patch, here: https://gist.github.com/arkku/95e661db1377342a7ce570a8d5bc9850

Basically the idea is that on compact keyboards without function keys, I want to press Fn-1 for F1, etc., and I need the layer to accomplish this, but I also want to be able to hold down Apple Fn and use the mouse to select text from Terminal when programs in the terminal are grabbing the mouse input. (I have not figured out any other way to do this, except with the Apple Fn key.) Double-tap Fn to speak also works with this hack.

(Oh, and of course the Fn + key combos defined in the layer also work on non-Apple systems, which will ignore the Apple Fn key.)

@S0ulf3re
Copy link

So, I have the Keychron K8 Pro, and the source code was recently released https://github.com/Keychron/qmk_firmware/tree/bluetooth_playground/keyboards/keychron/k8_pro. But when I try to run git apply in the root folder, I get this message:

error: patch failed: tmk_core/protocol/report.c:241
error: tmk_core/protocol/report.c: patch does not apply

Specifically line 241, which seems to be part of a function involving:

void add_key_bit(report_keyboard_t* keyboard_report, uint8_t code) {
    if ((code >> 3) < KEYBOARD_REPORT_BITS) {
        keyboard_report->nkro.bits[code >> 3] |= 1 << (code & 7);
    } else {
        dprintf("add_key_bit: can't add: %02X\n", code);
    }
}

After double checking and making sure that NKRO_ENABLE was equal to "no", I tried again and got the same results. What should I do?

@arkku
Copy link

arkku commented Aug 10, 2022

@S0ulf3re Try my patch from the link in the post directly above yours, I tried applying it on the Keychron firmware and it did succeed… (But FWIW I did not try the patch from this gist.)

@jhorology
Copy link

I implemented a apple_fn key as part of extra keys to support NKRO.
Here is the patch. Simply use as follows in keymap.c:

enum {
#ifdef VIA_ENABLE
  APPLE_FN = USER00
#else
  APPLE_FN = SAFE_RANGE
#endif
};

bool process_record_user(uint16_t keycode, keyrecord_t *record) {
  switch (keycode) {
    case APPLE_FN:
      host_apple_send(record->event.pressed ? 1 : 0);
      return false;
  }
  return true;
}

@ngcaobaolong
Copy link

I implemented a apple_fn key as part of extra keys to support NKRO. Here is the patch. Simply use as follows in keymap.c:

enum {
#ifdef VIA_ENABLE
  APPLE_FN = USER00
#else
  APPLE_FN = SAFE_RANGE
#endif
};

bool process_record_user(uint16_t keycode, keyrecord_t *record) {
  switch (keycode) {
    case APPLE_FN:
      host_apple_send(record->event.pressed ? 1 : 0);
      return false;
  }
  return true;
}

havent tried it yet, just looking around to see if someone ever find the solution to NKRO problem and very happy to see your comment.

@nitsujri
Copy link

nitsujri commented Dec 5, 2022

@fauxpark thanks so much for this patch! Looks like there were some big breaking changes in quantum/ recently.

So much so that I can't figure out how to apply this patch manually even. Possible to get help with this?

@nitsujri
Copy link

nitsujri commented Dec 9, 2022

@fauxpark omg you're amazing! Thanks for updating this!!!

@chrismanderson
Copy link

@jhorology Do you still have the patch to enable NKRO? Your link no longer works, thanks!

@marceliwac
Copy link

marceliwac commented Feb 23, 2023

It's probably worth mentioning that QMK has moved from defining VENDOR_ID and PRODUCT_ID explicitly to an info.json file now and deprecated the previous behaviour. Skipping the step where you define VENDOR_ID and PRODUCT_ID and updating keyboards/<keyboard>/info.json works fine.

Here's an excerpt from my working version (planck/rev6_drop):

  // ...
  "usb": {
    "vid": "0x05AC",
    "pid": "0x0267",
    "device_version": "0.0.6"
  },
  // ...

@fauxpark
Copy link
Author

That's not necessary, you can still override the keyboard-level VID/PID with the defines in your keymap-level config.h (in fact this is what you are meant to do anyway; you shouldn't modify keyboard-level code).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment