summaryrefslogtreecommitdiffhomepage
path: root/src/srp/fw-ec
diff options
context:
space:
mode:
Diffstat (limited to 'src/srp/fw-ec')
-rw-r--r--src/srp/fw-ec/1172.pngbin0 -> 17531 bytes
-rw-r--r--src/srp/fw-ec/fn-lock-1.diff.html12
-rw-r--r--src/srp/fw-ec/fn-lock-2.diff.html36
-rw-r--r--src/srp/fw-ec/hybrid.diff.html88
-rw-r--r--src/srp/fw-ec/index.html155
-rw-r--r--src/srp/fw-ec/kbd-sc-cb.c.html7
6 files changed, 298 insertions, 0 deletions
diff --git a/src/srp/fw-ec/1172.png b/src/srp/fw-ec/1172.png
new file mode 100644
index 0000000..14b3be1
--- /dev/null
+++ b/src/srp/fw-ec/1172.png
Binary files differ
diff --git a/src/srp/fw-ec/fn-lock-1.diff.html b/src/srp/fw-ec/fn-lock-1.diff.html
new file mode 100644
index 0000000..fb48204
--- /dev/null
+++ b/src/srp/fw-ec/fn-lock-1.diff.html
@@ -0,0 +1,12 @@
+<code><span class="diff-meta">diff --git a/board/hx20/board.h b/board/hx20/board.h</span></code>
+<code><span class="diff-meta">index 7b4ea288a..cfc6a61a2 100644</span></code>
+<code><span class="diff-meta">--- a/board/hx20/board.h</span></code>
+<code><span class="diff-meta">+++ b/board/hx20/board.h</span></code>
+<code><span class="diff-loc">@@ -218,7 +218,6 @@</span></code>
+<code> #define CONFIG_CMD_LEDTEST</code>
+<code> #define CONFIG_LED_PWM_COUNT 3</code>
+<code> #define CONFIG_LED_PWM_TASK_DISABLED</code>
+<code><span class="diff-del">-#define CONFIG_CAPSLED_SUPPORT</span></code>
+<code></code>
+<code> #ifdef CONFIG_ACCEL_KX022</code>
+<code> #define CONFIG_LID_ANGLE</code>
diff --git a/src/srp/fw-ec/fn-lock-2.diff.html b/src/srp/fw-ec/fn-lock-2.diff.html
new file mode 100644
index 0000000..b3880e0
--- /dev/null
+++ b/src/srp/fw-ec/fn-lock-2.diff.html
@@ -0,0 +1,36 @@
+<code><span class="diff-meta">diff --git a/board/hx20/keyboard_customization.c b/board/hx20/keyboard_customization.c</span></code>
+<code><span class="diff-meta">index 2b91f2e0c..9a5050a0f 100644</span></code>
+<code><span class="diff-meta">--- a/board/hx20/keyboard_customization.c</span></code>
+<code><span class="diff-meta">+++ b/board/hx20/keyboard_customization.c</span></code>
+<code><span class="diff-loc">@@ -249,6 +249,23 @@ int fn_table_set(int8_t pressed, uint32_t fn_bit)</span></code>
+<code> return false;</code>
+<code> }</code>
+<code></code>
+<code><span class="diff-ins">+static void hx20_update_fnkey_led(void) {</span></code>
+<code><span class="diff-ins">+ /* Turn the capslock light into a fn-lock light */</span></code>
+<code><span class="diff-ins">+ gpio_set_level(GPIO_CAP_LED_L, (Fn_key & FN_LOCKED) ? 1 : 0);</span></code>
+<code><span class="diff-ins">+}</span></code>
+<code><span class="diff-ins">+</span></code>
+<code><span class="diff-ins">+/* Set the fn-lock light to the correct setting when the system resumes */</span></code>
+<code><span class="diff-ins">+void hx20_fnkey_resume(void) {</span></code>
+<code><span class="diff-ins">+ hx20_update_fnkey_led();</span></code>
+<code><span class="diff-ins">+}</span></code>
+<code><span class="diff-ins">+DECLARE_HOOK(HOOK_CHIPSET_RESUME, hx20_fnkey_resume, HOOK_PRIO_DEFAULT);</span></code>
+<code><span class="diff-ins">+</span></code>
+<code><span class="diff-ins">+/* Disable the fn-lock light on suspend */</span></code>
+<code><span class="diff-ins">+void hx20_fnkey_suspend(void) {</span></code>
+<code><span class="diff-ins">+ gpio_set_level(GPIO_CAP_LED_L, 0);</span></code>
+<code><span class="diff-ins">+}</span></code>
+<code><span class="diff-ins">+DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, hx20_fnkey_suspend, HOOK_PRIO_DEFAULT);</span></code>
+<code><span class="diff-ins">+</span></code>
+<code> void fnkey_shutdown(void) {</code>
+<code> uint8_t current_kb = 0;</code>
+<code></code>
+<code><span class="diff-loc">@@ -420,6 +437,7 @@ int functional_hotkey(uint16_t *key_code, int8_t pressed)</span></code>
+<code> Fn_key &= ~FN_LOCKED;</code>
+<code> else</code>
+<code> Fn_key |= FN_LOCKED;</code>
+<code><span class="diff-ins">+ hx20_update_fnkey_led();</span></code>
+<code> }</code>
+<code> return EC_ERROR_UNIMPLEMENTED;</code>
+<code> }</code>
diff --git a/src/srp/fw-ec/hybrid.diff.html b/src/srp/fw-ec/hybrid.diff.html
new file mode 100644
index 0000000..a37d3b5
--- /dev/null
+++ b/src/srp/fw-ec/hybrid.diff.html
@@ -0,0 +1,88 @@
+<code><span class="diff-meta">diff --git a/board/hx20/keyboard_customization.c b/board/hx20/keyboard_customization.c</span></code>
+<code><span class="diff-meta">index 9a5050a0f..2756f17ce 100644</span></code>
+<code><span class="diff-meta">--- a/board/hx20/keyboard_customization.c</span></code>
+<code><span class="diff-meta">+++ b/board/hx20/keyboard_customization.c</span></code>
+<code><span class="diff-loc">@@ -22,12 +22,15 @@</span></code>
+<code> #define CPRINTS(format, args...) cprints(CC_KEYBOARD, format, ## args)</code>
+<code> #define CPRINTF(format, args...) cprintf(CC_KEYBOARD, format, ## args)</code>
+<code></code>
+<code><span class="diff-ins">+/* The scancode for the caps-lock key, which is now a hybrid key */</span></code>
+<code><span class="diff-ins">+#define SCANCODE_CTRL_ESC 0x0101</span></code>
+<code><span class="diff-ins">+</span></code>
+<code> uint16_t scancode_set2[KEYBOARD_COLS_MAX][KEYBOARD_ROWS] = {</code>
+<code> {0x0021, 0x007B, 0x0079, 0x0072, 0x007A, 0x0071, 0x0069, 0xe04A},</code>
+<code> {0xe071, 0xe070, 0x007D, 0xe01f, 0x006c, 0xe06c, 0xe07d, 0x0077},</code>
+<code> {0x0015, 0x0070, 0x00ff, 0x000D, 0x000E, 0x0016, 0x0067, 0x001c},</code>
+<code> {0xe011, 0x0011, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000},</code>
+<code><span class="diff-del">- {0xe05a, 0x0029, 0x0024, 0x000c, 0x0058, 0x0026, 0x0004, 0xe07a},</span></code>
+<code><span class="diff-ins">+ {0xe05a, 0x0029, 0x0024, 0x000c, 0x0101, 0x0026, 0x0004, 0xe07a},</span></code>
+<code> {0x0022, 0x001a, 0x0006, 0x0005, 0x001b, 0x001e, 0x001d, 0x0076},</code>
+<code> {0x002A, 0x0032, 0x0034, 0x002c, 0x002e, 0x0025, 0x002d, 0x002b},</code>
+<code> {0x003a, 0x0031, 0x0033, 0x0035, 0x0036, 0x003d, 0x003c, 0x003b},</code>
+<code><span class="diff-loc">@@ -497,6 +500,55 @@ int functional_hotkey(uint16_t *key_code, int8_t pressed)</span></code>
+<code> return EC_SUCCESS;</code>
+<code> }</code>
+<code></code>
+<code><span class="diff-ins">+int try_ctrl_esc(uint16_t *key_code, int8_t pressed) {</span></code>
+<code><span class="diff-ins">+ static enum {</span></code>
+<code><span class="diff-ins">+ NONE,</span></code>
+<code><span class="diff-ins">+ HELD,</span></code>
+<code><span class="diff-ins">+ CTRL</span></code>
+<code><span class="diff-ins">+ } ctrl_esc_state;</span></code>
+<code><span class="diff-ins">+</span></code>
+<code><span class="diff-ins">+ if (*key_code == SCANCODE_CTRL_ESC) {</span></code>
+<code><span class="diff-ins">+ /* If we pressed the caps key, enter the HELD state. Otherwise,</span></code>
+<code><span class="diff-ins">+ * we are either releasing from the HELD state or the CTRL</span></code>
+<code><span class="diff-ins">+ * state. In both cases we should reset the state to NONE, but</span></code>
+<code><span class="diff-ins">+ * when releasing from the HELD state we want to send an ESC and</span></code>
+<code><span class="diff-ins">+ * when releasing from the CTRL state we want to end the CTRL.</span></code>
+<code><span class="diff-ins">+ *</span></code>
+<code><span class="diff-ins">+ * Also important to note is that even before we know if we’re</span></code>
+<code><span class="diff-ins">+ * going to be acting as ESC or CTRL, we need to send a press-</span></code>
+<code><span class="diff-ins">+ * event of the CTRL key because you can chord CTRL with mouse-</span></code>
+<code><span class="diff-ins">+ * clicks too, not just other keys.</span></code>
+<code><span class="diff-ins">+ */</span></code>
+<code><span class="diff-ins">+ if (pressed) {</span></code>
+<code><span class="diff-ins">+ ctrl_esc_state = HELD;</span></code>
+<code><span class="diff-ins">+ simulate_keyboard(SCANCODE_LEFT_CTRL, 1);</span></code>
+<code><span class="diff-ins">+ } else if (ctrl_esc_state == HELD) {</span></code>
+<code><span class="diff-ins">+ ctrl_esc_state = NONE;</span></code>
+<code><span class="diff-ins">+ simulate_keyboard(SCANCODE_LEFT_CTRL, 0);</span></code>
+<code><span class="diff-ins">+ simulate_keyboard(SCANCODE_ESC, 1);</span></code>
+<code><span class="diff-ins">+ simulate_keyboard(SCANCODE_ESC, 0);</span></code>
+<code><span class="diff-ins">+ } else if (ctrl_esc_state == CTRL) {</span></code>
+<code><span class="diff-ins">+ ctrl_esc_state = NONE;</span></code>
+<code><span class="diff-ins">+ simulate_keyboard(SCANCODE_LEFT_CTRL, 0);</span></code>
+<code><span class="diff-ins">+ }</span></code>
+<code><span class="diff-ins">+</span></code>
+<code><span class="diff-ins">+ return EC_ERROR_UNIMPLEMENTED;</span></code>
+<code><span class="diff-ins">+ }</span></code>
+<code><span class="diff-ins">+</span></code>
+<code><span class="diff-ins">+ /* If we get here then we are dealing with a key that isn’t the caps</span></code>
+<code><span class="diff-ins">+ * key. In that case we need to handle all 3 states. If the state is</span></code>
+<code><span class="diff-ins">+ * NONE then we can just exit from this function. If it’s HELD and we</span></code>
+<code><span class="diff-ins">+ * are pressing a key, then that’s a key-chord and we need to start a</span></code>
+<code><span class="diff-ins">+ * CTRL. Finally, if we are in the CTRL state, there is nothing to do.</span></code>
+<code><span class="diff-ins">+ */</span></code>
+<code><span class="diff-ins">+ if (ctrl_esc_state == HELD && pressed) {</span></code>
+<code><span class="diff-ins">+ ctrl_esc_state = CTRL;</span></code>
+<code><span class="diff-ins">+ simulate_keyboard(SCANCODE_LEFT_CTRL, 1);</span></code>
+<code><span class="diff-ins">+ }</span></code>
+<code><span class="diff-ins">+</span></code>
+<code><span class="diff-ins">+ return EC_SUCCESS;</span></code>
+<code><span class="diff-ins">+}</span></code>
+<code><span class="diff-ins">+</span></code>
+<code> enum ec_error_list keyboard_scancode_callback(uint16_t *make_code,</code>
+<code> int8_t pressed)</code>
+<code> {</code>
+<code><span class="diff-loc">@@ -521,6 +573,10 @@ enum ec_error_list keyboard_scancode_callback(uint16_t *make_code,</span></code>
+<code> if (!pos_get_state())</code>
+<code> return EC_SUCCESS;</code>
+<code></code>
+<code><span class="diff-ins">+ r = try_ctrl_esc(make_code, pressed);</span></code>
+<code><span class="diff-ins">+ if (r != EC_SUCCESS)</span></code>
+<code><span class="diff-ins">+ return r;</span></code>
+<code><span class="diff-ins">+</span></code>
+<code> r = hotkey_F1_F12(make_code, Fn_key, pressed);</code>
+<code> if (r != EC_SUCCESS)</code>
+<code> return r;</code>
diff --git a/src/srp/fw-ec/index.html b/src/srp/fw-ec/index.html
index d8a48ba..cdfc8b5 100644
--- a/src/srp/fw-ec/index.html
+++ b/src/srp/fw-ec/index.html
@@ -87,6 +87,161 @@
tuples which is awesome, because it opens the door to
custom <abbr class="rgb">RGB</abbr> effects in the future!
</p>
+
+ <h2>There’s More Than One <abbr class="led">LED</abbr>!?</h2>
+
+ <p>
+ That’s right! The Framework laptop I own (13″; the 16″ releases
+ soon though!) has 3 more <abbr class="led">LED</abbr> lights.
+ One on the left of the chassis, one on right of the chassis, and
+ one on the capslock key. The capslock
+ <abbr class="led">LED</abbr> acts as an indicator of whether or
+ not you’ve got capslock enabled. This is useless to me though,
+ because my custom keyboard layout doesn’t even support capslock
+ (see the next section) — so I patched it to be a function-lock
+ indicator instead!
+ </p>
+
+ <p>
+ Here’s the diff — but do take care if you want to apply similar
+ patches to your laptop! The files I’m editing are under
+ <code>board/hx20</code> since I’m on an 11th Gen Intel
+ <abbr class="cpu">CPU</abbr>. If you have a different
+ <abbr class="cpu">CPU</abbr>, you will probably need to fuck with
+ different code:
+ </p>
+
+ <figure>
+ <figcaption>
+ <code>~/board/hx20/board.h</code>
+ </figcaption>
+ <pre>m4_include(fn-lock-1.diff.html)</pre>
+ </figure>
+
+ <figure>
+ <figcaption>
+ <code>~/board/hx20/keyboard-customization.c</code>
+ </figcaption>
+ <pre>m4_include(fn-lock-2.diff.html)</pre>
+ </figure>
+
+ <p>
+ As you can see, toggling the capslock
+ <abbr class="led">LED</abbr> is as simple as
+ invoking <code>gpio_set_level()</code>. Not only that, but
+ disabling its functionality with the capslock key is as easy as
+ undefining the <code>CONFIG_CAPSLOCK_SUPPORT</code> macro.
+ Figuring out if the function key is locked is also really easy.
+ The <code>Fn_key</code> global variable is a bit-field containing
+ information pertaining to the function key, and we also
+ conveniently already have the <code>FN_LOCKED</code> constant
+ defined that we can bitwise-AND with <code>Fn_key</code> to check
+ the locked state!
+ </p>
+
+ <p>
+ We also setup some hooks with the <code>DECLARE_HOOK()</code>
+ macro. These just ensure that we are behaving properly on system
+ resume and -suspend.
+ </p>
+
+ <h2>The Hybrid Key</h2>
+
+ <p>
+ Wouldn’t it be cool if a physical key could represent two keys at
+ the same time? I thought so too. Like all Emacs users, I suffer
+ from a distinct lack of easily-accessible modifier keys. I need
+ escape because I use Vim bindings; I need left-control because
+ all the Emacs bindings use it; I need super for my
+ window-managers’ bindings; I need left-alt so I can type
+ characters that don’t come on a standard American keyboard (such
+ as <em>ß</em>, <em>€</em>, and <em>é</em>), and now I have a
+ problem. All my modifiers are taken, but Emacs still needs a
+ meta key to work!
+ </p>
+ <figure>
+ <figcaption>
+ <cite>Workflow</cite> by Randall Munroe
+ </figcaption>
+ <img alt="XKCD Comic 1172" src="1172.png">
+ </figure>
+
+ <p>
+ What will I ever do!? Well thanks to Framework making
+ the <abbr class="ec">EC</abbr> open-source, and conveniently
+ giving me a file called <code>keyboard_customization.c</code>,
+ I’m going to take two keys and stick them in one! The basic
+ premise is this: the capslock key is arguably the easiest
+ modifier key to hit, and it’s currently bound to the escape key
+ on my system. This is inefficient though, because nobody makes
+ key-bindings that chord the escape-key with another key; chords
+ are always done with a modifier like control, and Emacs is no
+ different. So my plan was to make it so that the capslock key
+ when used on its own mimics an escape-key, while instead
+ mimicking the left-control-key when used in a chord with another
+ key.
+ </p>
+
+ <p>
+ It took me a little longer this time to figure out how to
+ implement what I wanted since the code isn’t as clear, but it was
+ still a surprisingly easy feature to patch into the
+ <abbr class="ec">EC</abbr>! I basically just updated the
+ scancode table, swapping out the capslock scancode for my own
+ random one that I called <code>SCANCODE_CTRL_ESC</code>. I then
+ created a new function called <code>try_ctrl_esc()</code> which
+ is called in the on-keyup and -down callback function. The
+ <code>try_ctrl_esc()</code> function handles all of the logic as
+ you can see in the following diff; it’s basically just a state
+ machine:
+ </p>
+
+ <aside>
+ <p>
+ If you’re confused by what I mean by a “key-chord”, I am
+ simply referring to pressing multiple keys in conjunction,
+ such as when you press “<kbd>Ctrl + C</kbd>” to copy text.
+ </p>
+ </aside>
+
+ <figure>
+ <figcaption><code>~/board/hx20/keyboard_customization.c</code></figcaption>
+ <pre>m4_include(hybrid.diff.html)</pre>
+ </figure>
+
+ <p>
+ One thing that’s good to take note of is what I return from
+ <code>try_ctrl_esc()</code>. The general pattern for handling a
+ keyup or -down event is to stick the following code into
+ <code>keyboard_scancode_callback()</code>:
+ </p>
+
+ <figure>
+ <figcaption>
+ <code>keyboard_scancode_callback()</code> in
+ <code>~/board/hx20/keyboard_customization.c</code>
+ </figcaption>
+ <pre>m4_include(kbd-sc-cb.c.html)</pre>
+ </figure>
+
+ <p>
+ In <code>my_handler_function()</code> (or whatever you decide to
+ name it), you attempt to handle the event. If you don’t want to
+ handle a particular event and instead want to pass it on to the
+ next handler, you need to return <code>EC_SUCCESS</code>. If you
+ managed to successfully handle the event though, then you need to
+ return an error such as <code>EC_ERROR_UNIMPLEMENTED</code>.
+ It’s pretty stupid and makes very little sense from a naming
+ perspective, but oh well…
+ </p>
+
+ <h2>What’s Next?</h2>
+
+ <p>
+ <abbr class="rgb">RGB</abbr>
+ <abbr class="led">LED</abbr>s
+ maybe.
+ </p>
</main>
<hr>
diff --git a/src/srp/fw-ec/kbd-sc-cb.c.html b/src/srp/fw-ec/kbd-sc-cb.c.html
new file mode 100644
index 0000000..6fffdc5
--- /dev/null
+++ b/src/srp/fw-ec/kbd-sc-cb.c.html
@@ -0,0 +1,7 @@
+<code><span class="c-cmt">/* “make_code” is the scancode. “pressed” is a boolean that is true if this is a</span></code>
+<code><span class="c-cmt"> * keydown event, and false if it’s a keyup.</span></code>
+<code><span class="c-cmt"> */</span></code>
+<code></code>
+<code>r = <span class="c-fn">my_handler_function</span>(make_code, pressed);</code>
+<code><span class="c-kw">if</span> (r != <span class="c-pp">EC_SUCCESS</span>)</code>
+<code> <span class="c-kw">return</span> r;</code>