Skip to content

Commit

Permalink
feat: add split keyboard functionality
Browse files Browse the repository at this point in the history
TODO: add tests, fix bugs, etc.
  • Loading branch information
headblockhead committed Nov 3, 2024
1 parent b225f99 commit 55f3092
Show file tree
Hide file tree
Showing 8 changed files with 81 additions and 7 deletions.
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ add_library(squirrel STATIC
src/squirrel_consumer.c
src/squirrel_init.c
src/squirrel_keymap.c
src/squirrel_split.c
)

target_include_directories(squirrel PRIVATE include)
Expand Down
5 changes: 4 additions & 1 deletion include/squirrel_consumer.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,8 @@ void consumer_activate_consumer_code(uint16_t consumer_code);
void consumer_deactivate_consumer_code(uint16_t consumer_code);
// consumer_get_consumer_code returns the currently active consumer code.
uint16_t consumer_get_consumer_code();

// consumer_get_local_consumer_code returns the currently active consumer code
// without considering any remote boards. This is only useful in split
// keyboards.
uint16_t consumer_get_local_consumer_code();
#endif
5 changes: 2 additions & 3 deletions include/squirrel_init.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
#ifndef SQUIRREL_INIT_H
#define SQUIRREL_INIT_H
#pragma once

enum squirrel_error
squirrel_init(void); // Initialize the keyboard with the total number of keys.
#endif
8 changes: 8 additions & 0 deletions include/squirrel_keyboard.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,20 @@ void keyboard_deactivate_keycode(uint8_t keycode);
// keycodes. 6 is the maximum number of keycodes that can be sent over USB HID.
// If there are no keycodes, the function will return false.
bool keyboard_get_keycodes(uint8_t (*active_keycodes)[6]);
// keyboard_get_local_keycodes populates the provided array with the first 6
// active keycodes without considering the input of other connected boards. This
// is only useful for split keyboards.
void keyboard_get_local_keycodes(uint8_t (*active_keycodes)[6]);

// keyboard_activate_modifier marks the provided modifier as active.
void keyboard_activate_modifier(uint8_t modifier);
// keyboard_deactivate_modifier marks the provided modifier as inactive.
void keyboard_deactivate_modifier(uint8_t modifier);
// keyboard_get_modifiers returns a bitfield of active modifiers.
uint8_t keyboard_get_modifiers();
// keyboard_get_local_modifiers returns a bitfield of active modifiers without
// considering the input of other connected boards. This is only useful for
// split keyboards.
uint8_t keyboard_get_local_modifiers();

#endif
11 changes: 11 additions & 0 deletions include/squirrel_split.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#pragma once

#include <stdint.h>

// get_packet takes a pointer to a 9-byte array and fills it with the data for
// the packet to be sent.
void get_packet(uint8_t (*packet)[9]);

extern uint8_t remote_keycodes[6];
extern uint8_t remote_modifiers;
extern uint16_t remote_consumer_code;
9 changes: 8 additions & 1 deletion src/squirrel_consumer.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "squirrel_consumer.h"
#include "squirrel_split.h"
#include <stdint.h>

uint16_t consumer_code = 0;
Expand All @@ -9,4 +10,10 @@ void consumer_deactivate_consumer_code(uint16_t code) {
consumer_code = 0;
}
}
uint16_t consumer_get_consumer_code() { return consumer_code; }
uint16_t consumer_get_consumer_code() {
if (consumer_code != 0) {
return consumer_code;
}
return remote_consumer_code;
}
uint16_t consumer_get_local_consumer_code() { return consumer_code; }
22 changes: 20 additions & 2 deletions src/squirrel_keyboard.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#include "squirrel_keyboard.h"
#include "squirrel_split.h"
#include <stdbool.h>
#include <stdint.h>
#include <string.h>

bool keyboard_keycodes[256] = {false};
uint8_t keyboard_modifiers = 0;
Expand All @@ -12,9 +14,10 @@ void keyboard_deactivate_keycode(uint8_t keycode) {
keyboard_keycodes[keycode] = false;
}
bool keyboard_get_keycodes(uint8_t (*active_keycodes)[6]) {
memset(*active_keycodes, 0, 6);
uint8_t active_keycodes_index = 0;
for (int i = 0; (i <= 0xFF) && active_keycodes_index < 6; i++) {
if (!keyboard_keycodes[i]) {
if (!keyboard_keycodes[i] && !remote_keycodes[i]) {
continue;
}
(*active_keycodes)[active_keycodes_index] = i;
Expand All @@ -23,10 +26,25 @@ bool keyboard_get_keycodes(uint8_t (*active_keycodes)[6]) {
return active_keycodes_index != 0;
}

void keyboard_get_local_keycodes(uint8_t (*active_keycodes)[6]) {
memset(*active_keycodes, 0, 6);
uint8_t active_keycodes_index = 0;
for (int i = 0; (i <= 0xFF) && active_keycodes_index < 6; i++) {
if (!keyboard_keycodes[i]) {
continue;
}
(*active_keycodes)[active_keycodes_index] = i;
active_keycodes_index++;
}
}

void keyboard_activate_modifier(uint8_t modifier) {
keyboard_modifiers |= modifier;
}
void keyboard_deactivate_modifier(uint8_t modifier) {
keyboard_modifiers &= ~modifier;
}
uint8_t keyboard_get_modifiers() { return keyboard_modifiers; }
uint8_t keyboard_get_modifiers() {
return keyboard_modifiers | remote_modifiers;
}
uint8_t keyboard_get_local_modifiers() { return keyboard_modifiers; }
27 changes: 27 additions & 0 deletions src/squirrel_split.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#include "squirrel_split.h"
#include "squirrel.h"
#include "squirrel_consumer.h"
#include "squirrel_keyboard.h"
#include <stdint.h>
#include <string.h>

void get_packet(uint8_t (*packet)[9]) {
memset(*packet, 0, 9);
uint8_t local_keycodes[6] = {0};
keyboard_get_local_keycodes(&local_keycodes);
memcpy(packet, local_keycodes, 6); // 0th to 5th byte
(*packet)[6] = keyboard_get_local_modifiers(); // 6th byte
uint16_t consumer = consumer_get_local_consumer_code();
(*packet)[7] = consumer & 0xFF; // 7th byte
(*packet)[8] = consumer >> 8; // 8th byte
}

uint8_t remote_keycodes[6] = {0};
uint8_t remote_modifiers = 0;
uint16_t remote_consumer_code = 0;

void process_packet(uint8_t (*packet)[9]) {
memcpy(remote_keycodes, *packet, 6); // 0th to 5th byte
remote_modifiers = (*packet)[6]; // 6th byte
remote_consumer_code = (*packet)[7] | ((*packet)[8] << 8); // 7th and 8th byte
}

0 comments on commit 55f3092

Please sign in to comment.