|
diff --git a/builddefs/common_features.mk b/builddefs/common_features.mk |
|
index d9130b5338..3a80ec71bc 100644 |
|
--- a/builddefs/common_features.mk |
|
+++ b/builddefs/common_features.mk |
|
@@ -851,6 +851,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.1_basic.hjson b/data/constants/keycodes/keycodes_0.0.1_basic.hjson |
|
index 7141d553b0..c21f4483db 100644 |
|
--- a/data/constants/keycodes/keycodes_0.0.1_basic.hjson |
|
+++ b/data/constants/keycodes/keycodes_0.0.1_basic.hjson |
|
@@ -1286,6 +1286,14 @@ |
|
"KC_ASST" |
|
] |
|
}, |
|
+ "0x00C1": { |
|
+ "group": "media", |
|
+ "key": "KC_APPLE_FN", |
|
+ "label": "Apple Fn", |
|
+ "aliases": [ |
|
+ "KC_APFN" |
|
+ ] |
|
+ }, |
|
|
|
"0x00CD": { |
|
"group": "mouse", |
|
diff --git a/quantum/action.c b/quantum/action.c |
|
index abf9834d2f..edb000974c 100644 |
|
--- a/quantum/action.c |
|
+++ b/quantum/action.c |
|
@@ -534,6 +534,16 @@ void process_action(keyrecord_t *record, action_t action) { |
|
break; |
|
} |
|
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 |
|
/* Mouse key */ |
|
case ACT_MOUSEKEY: |
|
@@ -919,6 +929,12 @@ __attribute__((weak)) void register_code(uint8_t code) { |
|
host_consumer_send(KEYCODE2CONSUMER(code)); |
|
#endif |
|
|
|
+#ifdef APPLE_FN_ENABLE |
|
+ } else if IS_APPLE_FN (code) { |
|
+ add_key(code); |
|
+ send_keyboard_report(); |
|
+#endif |
|
+ |
|
} else if IS_MOUSEKEY (code) { |
|
register_mouse(code, true); |
|
} |
|
@@ -976,6 +992,12 @@ __attribute__((weak)) void unregister_code(uint8_t code) { |
|
host_consumer_send(0); |
|
#endif |
|
|
|
+#ifdef APPLE_FN_ENABLE |
|
+ } else if IS_APPLE_FN (code) { |
|
+ del_key(code); |
|
+ send_keyboard_report(); |
|
+#endif |
|
+ |
|
} else if IS_MOUSEKEY (code) { |
|
register_mouse(code, false); |
|
} |
|
@@ -1173,6 +1195,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/quantum/action_code.h b/quantum/action_code.h |
|
index 58d929016d..3a1b7b1545 100644 |
|
--- a/quantum/action_code.h |
|
+++ b/quantum/action_code.h |
|
@@ -51,7 +51,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) |
|
* ------------------- |
|
@@ -93,6 +94,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, |
|
@@ -202,6 +205,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/keycode.h b/quantum/keycode.h |
|
index 45736e92f1..dea665d7c8 100644 |
|
--- a/quantum/keycode.h |
|
+++ b/quantum/keycode.h |
|
@@ -32,6 +32,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
|
|
#define IS_SYSTEM(code) IS_SYSTEM_KEYCODE(code) |
|
#define IS_CONSUMER(code) IS_MEDIA_KEYCODE(code) |
|
+#define IS_APPLE_FN(code) (KC_APFN == (code)) |
|
|
|
#define IS_MOUSEKEY(code) IS_MOUSE_KEYCODE(code) |
|
#define IS_MOUSEKEY_MOVE(code) (KC_MS_UP <= (code) && (code) <= KC_MS_RIGHT) |
|
diff --git a/quantum/keycodes.h b/quantum/keycodes.h |
|
index c013858e78..46745477c9 100644 |
|
--- a/quantum/keycodes.h |
|
+++ b/quantum/keycodes.h |
|
@@ -277,6 +277,7 @@ enum qk_keycode_defines { |
|
KC_BRIGHTNESS_DOWN = 0x00BE, |
|
KC_CONTROL_PANEL = 0x00BF, |
|
KC_ASSISTANT = 0x00C0, |
|
+ KC_APPLE_FN = 0x00C1, |
|
KC_MS_UP = 0x00CD, |
|
KC_MS_DOWN = 0x00CE, |
|
KC_MS_LEFT = 0x00CF, |
|
@@ -829,6 +830,7 @@ enum qk_keycode_defines { |
|
KC_BRID = KC_BRIGHTNESS_DOWN, |
|
KC_CPNL = KC_CONTROL_PANEL, |
|
KC_ASST = KC_ASSISTANT, |
|
+ KC_APFN = KC_APPLE_FN, |
|
KC_MS_U = KC_MS_UP, |
|
KC_MS_D = KC_MS_DOWN, |
|
KC_MS_L = KC_MS_LEFT, |
|
diff --git a/quantum/keymap_common.c b/quantum/keymap_common.c |
|
index c4336440f9..01d93cfcc3 100644 |
|
--- a/quantum/keymap_common.c |
|
+++ b/quantum/keymap_common.c |
|
@@ -64,6 +64,11 @@ action_t action_for_keycode(uint16_t keycode) { |
|
case KC_AUDIO_MUTE ... KC_ASSISTANT: |
|
action.code = ACTION_USAGE_CONSUMER(KEYCODE2CONSUMER(keycode)); |
|
break; |
|
+#endif |
|
+#ifdef APPLE_FN_ENABLE |
|
+ case KC_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 5755098c60..6498f46750 100644 |
|
--- a/tmk_core/protocol/report.c |
|
+++ b/tmk_core/protocol/report.c |
|
@@ -241,6 +241,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); |
|
@@ -255,6 +261,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 99c52952a0..84a6c4134d 100644 |
|
--- a/tmk_core/protocol/usb_descriptor.c |
|
+++ b/tmk_core/protocol/usb_descriptor.c |
|
@@ -74,10 +74,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 2d17761978..91dcf6d407 100644 |
|
--- a/tmk_core/protocol/vusb/vusb.c |
|
+++ b/tmk_core/protocol/vusb/vusb.c |
|
@@ -413,10 +413,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) |
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 id0x029c
.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
and0x029c
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.