diff --git a/common_features.mk b/common_features.mk
index 8ac53ec45a5f..558a32b33fb0 100644
--- a/common_features.mk
+++ b/common_features.mk
@@ -592,3 +592,7 @@ endif
ifeq ($(strip $(JOYSTICK_ENABLE)), digital)
OPT_DEFS += -DDIGITAL_JOYSTICK_ENABLE
endif
+
+ifeq ($(strip $(APPLE_FN_ENABLE)), yes)
+ OPT_DEFS += -DAPPLE_FN_ENABLE
+endif
diff --git a/quantum/keymap_common.c b/quantum/keymap_common.c
index 570d4798debe..d58ed66ed46a 100644
--- a/quantum/keymap_common.c
+++ b/quantum/keymap_common.c
@@ -68,6 +68,11 @@ action_t action_for_key(uint8_t layer, keypos_t key) {
action.code = ACTION_USAGE_CONSUMER(KEYCODE2CONSUMER(keycode));
break;
#endif
+#ifdef APPLE_FN_ENABLE
+ case KC_APPLE_FN:
+ action.code = ACTION_APPLE_FN();
+ break;
+#endif
#ifdef MOUSEKEY_ENABLE
case KC_MS_UP ... KC_MS_ACCEL2:
action.code = ACTION_MOUSEKEY(keycode);
diff --git a/tmk_core/common/action.c b/tmk_core/common/action.c
index a7432bae599a..ecb8634fe7fe 100644
--- a/tmk_core/common/action.c
+++ b/tmk_core/common/action.c
@@ -419,6 +419,16 @@ void process_action(keyrecord_t *record, action_t action) {
}
break;
#endif
+#ifdef APPLE_FN_ENABLE
+ /* Apple Fn */
+ case ACT_APPLE_FN:
+ if (event.pressed) {
+ register_code(KC_APPLE_FN);
+ } else {
+ unregister_code(KC_APPLE_FN);
+ }
+ break;
+#endif
#ifdef MOUSEKEY_ENABLE
/* Mouse key */
case ACT_MOUSEKEY:
@@ -863,6 +873,12 @@ void register_code(uint8_t code) {
else if
IS_CONSUMER(code) { host_consumer_send(KEYCODE2CONSUMER(code)); }
#endif
+#ifdef APPLE_FN_ENABLE
+ else if IS_APPLE_FN(code) {
+ add_key(code);
+ send_keyboard_report();
+ }
+#endif
#ifdef MOUSEKEY_ENABLE
else if
IS_MOUSEKEY(code) {
@@ -927,6 +943,12 @@ void unregister_code(uint8_t code) {
IS_SYSTEM(code) { host_system_send(0); }
else if
IS_CONSUMER(code) { host_consumer_send(0); }
+#ifdef APPLE_FN_ENABLE
+ else if IS_APPLE_FN(code) {
+ del_key(code);
+ send_keyboard_report();
+ }
+#endif
#ifdef MOUSEKEY_ENABLE
else if
IS_MOUSEKEY(code) {
@@ -1110,6 +1132,9 @@ void debug_action(action_t action) {
case ACT_USAGE:
dprint("ACT_USAGE");
break;
+ case ACT_APPLE_FN:
+ dprint("ACT_APPLE_FN");
+ break;
case ACT_MOUSEKEY:
dprint("ACT_MOUSEKEY");
break;
diff --git a/tmk_core/common/action_code.h b/tmk_core/common/action_code.h
index eb18c36ae809..f6ffc0d68a1b 100644
--- a/tmk_core/common/action_code.h
+++ b/tmk_core/common/action_code.h
@@ -51,7 +51,8 @@ along with this program. If not, see .
* 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)
* -------------------
@@ -106,6 +107,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,
@@ -216,6 +219,7 @@ enum mods_codes {
enum usage_pages { PAGE_SYSTEM, PAGE_CONSUMER };
#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/tmk_core/common/keycode.h b/tmk_core/common/keycode.h
index d35e44d8dc24..26eb55f52f7a 100644
--- a/tmk_core/common/keycode.h
+++ b/tmk_core/common/keycode.h
@@ -34,6 +34,7 @@ along with this program. If not, see .
#define IS_SPECIAL(code) ((0xA5 <= (code) && (code) <= 0xDF) || (0xE8 <= (code) && (code) <= 0xFF))
#define IS_SYSTEM(code) (KC_PWR <= (code) && (code) <= KC_WAKE)
#define IS_CONSUMER(code) (KC_MUTE <= (code) && (code) <= KC_BRID)
+#define IS_APPLE_FN(code) (KC_APFN == (code))
#define IS_FN(code) (KC_FN0 <= (code) && (code) <= KC_FN31)
@@ -191,6 +192,9 @@ along with this program. If not, see .
#define KC_BRIU KC_BRIGHTNESS_UP
#define KC_BRID KC_BRIGHTNESS_DOWN
+/* Apple Fn */
+#define KC_APFN KC_APPLE_FN
+
/* System Specific */
#define KC_BRMU KC_PAUSE
#define KC_BRMD KC_SCROLLLOCK
@@ -484,6 +488,9 @@ enum internal_special_keycodes {
KC_BRIGHTNESS_UP,
KC_BRIGHTNESS_DOWN,
+ /* Apple Fn */
+ KC_APPLE_FN,
+
/* Fn keys */
KC_FN0 = 0xC0,
KC_FN1,
diff --git a/tmk_core/common/report.c b/tmk_core/common/report.c
index 1bcb6f2adb94..3d41bf186246 100644
--- a/tmk_core/common/report.c
+++ b/tmk_core/common/report.c
@@ -231,6 +231,12 @@ void del_key_bit(report_keyboard_t* keyboard_report, uint8_t code) {
* FIXME: Needs doc
*/
void add_key_to_report(report_keyboard_t* keyboard_report, uint8_t key) {
+#ifdef APPLE_FN_ENABLE
+ if IS_APPLE_FN(key) {
+ keyboard_report->reserved = 1;
+ return;
+ }
+#endif
#ifdef NKRO_ENABLE
if (keyboard_protocol && keymap_config.nkro) {
add_key_bit(keyboard_report, key);
@@ -245,6 +251,12 @@ void add_key_to_report(report_keyboard_t* keyboard_report, uint8_t key) {
* FIXME: Needs doc
*/
void del_key_from_report(report_keyboard_t* keyboard_report, uint8_t key) {
+#ifdef APPLE_FN_ENABLE
+ if IS_APPLE_FN(key) {
+ keyboard_report->reserved = 0;
+ return;
+ }
+#endif
#ifdef NKRO_ENABLE
if (keyboard_protocol && keymap_config.nkro) {
del_key_bit(keyboard_report, key);
diff --git a/tmk_core/protocol/usb_descriptor.c b/tmk_core/protocol/usb_descriptor.c
index 7ea4b2e37c4b..efc8f994cc7d 100644
--- a/tmk_core/protocol/usb_descriptor.c
+++ b/tmk_core/protocol/usb_descriptor.c
@@ -71,10 +71,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 a422903ccf2e..042aaef1865a 100644
--- a/tmk_core/protocol/vusb/vusb.c
+++ b/tmk_core/protocol/vusb/vusb.c
@@ -401,10 +401,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)