Skip to content

Commit

Permalink
experimental sun keyboard sniffer (#9)
Browse files Browse the repository at this point in the history
  • Loading branch information
delan committed Nov 29, 2024
1 parent 6411fad commit 25d9def
Show file tree
Hide file tree
Showing 8 changed files with 112 additions and 15 deletions.
1 change: 1 addition & 0 deletions platformio.ini
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ lib_deps =
build_flags =
-DSUNK_ENABLE
-DSUNM_ENABLE
; -DSUNK_SNIFFER_ENABLE ; sun keyboard sniffer
; -DWIPE_SETTINGS ; wipe settings on every boot
-DUSB3SUN_HAL_ARDUINO_PICO
-DUSE_TINYUSB
Expand Down
20 changes: 19 additions & 1 deletion run-build-tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ build() {
export PLATFORMIO_BUILD_FLAGS='
-USUNK_ENABLE
-USUNM_ENABLE
-USUNK_SNIFFER_ENABLE
-UWIPE_SETTINGS
-UDEBUG_TIMINGS
-UUHID_LED_ENABLE
Expand All @@ -27,6 +28,22 @@ build "$@"
export PLATFORMIO_BUILD_FLAGS='
-DSUNK_ENABLE
-DSUNM_ENABLE
-USUNK_SNIFFER_ENABLE
-DWIPE_SETTINGS
-DDEBUG_TIMINGS
-DUHID_LED_ENABLE
-DUHID_LED_TEST
-DWAIT_PIN
-DWAIT_SERIAL
-UBUZZER_VERBOSE
-USUNK_VERBOSE
-USUNM_VERBOSE
-UUHID_VERBOSE
'; build "$@"
export PLATFORMIO_BUILD_FLAGS='
-USUNK_ENABLE
-USUNM_ENABLE
-DSUNK_SNIFFER_ENABLE
-DWIPE_SETTINGS
-DDEBUG_TIMINGS
-DUHID_LED_ENABLE
Expand All @@ -39,10 +56,11 @@ export PLATFORMIO_BUILD_FLAGS='
-UUHID_VERBOSE
'; build "$@"

# build with all flags on.
# build with all flags on, where compatible.
export PLATFORMIO_BUILD_FLAGS='
-DSUNK_ENABLE
-DSUNM_ENABLE
-USUNK_SNIFFER_ENABLE
-DWIPE_SETTINGS
-DDEBUG_TIMINGS
-DUHID_LED_ENABLE
Expand Down
3 changes: 3 additions & 0 deletions run-tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,6 @@ for me in -DSUNM_ENABLE ''; do
.pio/build/linux/program ${1-all}
done
done

PLATFORMIO_BUILD_FLAGS="-DSUNK_SNIFFER_ENABLE" pio run -e linux
.pio/build/linux/program ${1-all}
10 changes: 10 additions & 0 deletions src/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,20 @@
#define POWER_KEY 15 // ...any
// pin 8: +5 Vdc (orange)

// the following should generally be set in platformio.ini only, but remember
// to update compile_commands.json (pio run -t compiledb) when changing these,
// so clangd knows what features are enabled.
// -DSUNK_ENABLE in platformio.ini to enable sun keyboard interface
// -DSUNM_ENABLE in platformio.ini to enable sun mouse interface
// -DSUNK_SNIFFER_ENABLE in platform.ini to enable sun keyboard sniffer
// -DWIPE_SETTINGS in platformio.ini to wipe settings on every boot

#if defined(SUNK_ENABLE) || defined(SUNM_ENABLE)
#ifdef SUNK_SNIFFER_ENABLE
#error SUNK_ENABLE and SUNM_ENABLE are not allowed when SUNK_SNIFFER_ENABLE is set
#endif
#endif

#if defined(DEBUG_LOGGING)
#define Sprint(...) do { pinout.debugPrint(__VA_ARGS__); } while (0)
#define Sprintln(...) do { pinout.debugPrintln(__VA_ARGS__); } while (0)
Expand Down
29 changes: 29 additions & 0 deletions src/hal.cc
Original file line number Diff line number Diff line change
Expand Up @@ -145,9 +145,12 @@ extern "C" {

static Adafruit_SSD1306 display{128, 32, &Wire, /* OLED_RESET */ -1};
static Adafruit_USBH_Host USBHost;
static SerialPIO sunkTxSnifferV1{SerialPIO::NOPIN, SUN_KTX_V1};
static SerialPIO sunkTxSnifferV2{SerialPIO::NOPIN, SUN_KTX_V2};
static struct {
size_t version = 1;
HardwareSerial *sunk = &SUNK_UART_V1;
HardwareSerial *sunkTxSniffer = &sunkTxSnifferV1;
HardwareSerial *sunm = &SUNM_UART_V1;
Adafruit_USBD_CDC *debugCdc = nullptr;
SerialUART *debugUart = nullptr;
Expand All @@ -170,6 +173,7 @@ size_t usb3sun_pinout_version(void) {
void usb3sun_pinout_v2(void) {
pinout.version = 2;
pinout.sunk = &SUNK_UART_V2;
pinout.sunkTxSniffer = &sunkTxSnifferV2;
pinout.sunm = &pinout.sunmV2;
pinout.sunkTx = SUN_KTX_V2;
pinout.sunkRx = SUN_KRX_V2;
Expand All @@ -194,6 +198,22 @@ size_t usb3sun_sunk_write(uint8_t *data, size_t len) {
return pinout.sunk->write(data, len);
}

void usb3sun_sunk_sniffer_init(void) {
pinout.sunk->end();
// SerialUART api requires both tx and rx pins, but we can detach tx afterwards
pinout.sunkUart->setPinout(pinout.sunkTx, pinout.sunkRx);
pinout.sunk->begin(1200, SERIAL_8N1);
// SerialPIO has no such requirement; this call detaches tx from hardware uart
pinout.sunkTxSniffer->begin(1200, SERIAL_8N1);
// gpio invert must be set *after* setPinout/begin
usb3sun_gpio_set_as_inverted(pinout.sunkTx);
usb3sun_gpio_set_as_inverted(pinout.sunkRx);
}

int usb3sun_sunk_sniff_tx(void) {
return pinout.sunkTxSniffer->read();
}

void usb3sun_sunm_init(uint32_t baud) {
pinout.sunm->end();
switch (pinout.version) {
Expand Down Expand Up @@ -652,6 +672,15 @@ size_t usb3sun_sunm_write(uint8_t *data, size_t len) {
return 0;
}

void usb3sun_sunk_sniffer_init(void) {
push_history(SunkSnifferInitOp {});
}

int usb3sun_sunk_sniff_tx(void) {
push_history(SunkSniffTxOp {});
return -1;
}

void usb3sun_usb_init(void) {}

void usb3sun_usb_task(void) {}
Expand Down
11 changes: 10 additions & 1 deletion src/hal.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ typedef struct {
struct FsWriteOp { static const uint64_t id = 1 << 11; std::string path; std::vector<uint8_t> data; };
struct RebootOp { static const uint64_t id = 1 << 12; };
struct AlarmOp { static const uint64_t id = 1 << 13; uint32_t ms; };
struct SunkSnifferInitOp { static const uint64_t id = 1 << 14; };
struct SunkSniffTxOp { static const uint64_t id = 1 << 15; };
using Op = std::variant<
PinoutV2Op,
SunkInitOp,
Expand All @@ -60,7 +62,9 @@ typedef struct {
FsReadOp,
FsWriteOp,
RebootOp,
AlarmOp>;
AlarmOp,
SunkSnifferInitOp,
SunkSniffTxOp>;
struct Entry {
uint64_t micros;
Op op;
Expand Down Expand Up @@ -93,6 +97,8 @@ typedef struct {
DERIVE_OP(FsWriteOp, p.path == q.path && p.data == q.data, "fs_write " << o.path << " " << o.data);
DERIVE_OP(RebootOp, ((void) p, (void) q, true), ((void) o, "reboot"));
DERIVE_OP(AlarmOp, p.ms == q.ms, "alarm " << o.ms);
DERIVE_OP(SunkSnifferInitOp, ((void) p, (void) q, true), ((void) o, "sunk_sniffer_init"));
DERIVE_OP(SunkSniffTxOp, ((void) p, (void) q, true), ((void) o, "sunk_sniff_tx"));
void usb3sun_test_init(uint64_t history_filter_mask);
void usb3sun_mock_gpio_read(usb3sun_pin pin, bool value);
void usb3sun_mock_sunk_read(const char *data, size_t len);
Expand All @@ -117,6 +123,9 @@ void usb3sun_sunk_init(void);
int usb3sun_sunk_read(void);
size_t usb3sun_sunk_write(uint8_t *data, size_t len);

void usb3sun_sunk_sniffer_init(void);
int usb3sun_sunk_sniff_tx(void);

void usb3sun_sunm_init(uint32_t baud);
size_t usb3sun_sunm_write(uint8_t *data, size_t len);

Expand Down
47 changes: 35 additions & 12 deletions src/main.cc
Original file line number Diff line number Diff line change
Expand Up @@ -194,23 +194,32 @@ void loop() {
while ((input = usb3sun_debug_uart_read()) != -1) {
handleCliInput(input);
}
#ifdef SUNK_SNIFFER_ENABLE
while ((input = usb3sun_sunk_sniff_tx()) != -1) {
uint8_t command = input;
Sprintf("sunk: sniff tx %02Xh (%d)\n", command, command);
}
#endif


usb3sun_sleep_micros(10'000);
}

#ifdef SUNK_ENABLE
#if defined(SUNK_ENABLE) || defined(SUNK_SNIFFER_ENABLE)
void sunkEvent() {
int result;
while ((result = usb3sun_sunk_read()) != -1) {
uint8_t command = result;
Sprintf("sunk: rx %02Xh\n", command);
switch (command) {
case SUNK_RESET: {
#ifndef SUNK_SNIFFER_ENABLE
// self test fail:
// usb3sun_sunk_write(0x7E);
// usb3sun_sunk_write(0x01);
uint8_t response[]{SUNK_RESET_RESPONSE, 0x04, 0x7F}; // TODO optional make code
usb3sun_sunk_write(response, sizeof response);
#endif
} break;
case SUNK_BELL_ON:
state.bell = true;
Expand Down Expand Up @@ -240,23 +249,25 @@ void sunkEvent() {
usb3sun_fifo_push((uint32_t)Message::UHID_LED_FROM_STATE);
} break;
case SUNK_LAYOUT: {
#ifndef SUNK_SNIFFER_ENABLE
// UNITED STATES (TODO alternate layouts)
uint8_t response[]{SUNK_LAYOUT_RESPONSE, 0b00000000};
usb3sun_sunk_write(response, sizeof response);
#endif
} break;
}
}
}
#endif

void serialEvent1() {
#if defined(SUNK_ENABLE)
#if defined(SUNK_ENABLE) || defined(SUNK_SNIFFER_ENABLE)
sunkEvent();
#endif
}

void serialEvent2() {
#if defined(SUNK_ENABLE)
#if defined(SUNK_ENABLE) || defined(SUNK_SNIFFER_ENABLE)
sunkEvent();
#endif
}
Expand Down Expand Up @@ -531,7 +542,7 @@ void tuh_hid_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t cons
#include <sys/types.h>
#include <sys/wait.h>

#define TEST_REQUIRES(expr) do { fprintf(stderr, ">>> skipping test (%s)\n", #expr); return true; } while (0)
#define TEST_REQUIRES(expr) do { fprintf(stderr, ">>> skipping test (requires %s)\n", #expr); return true; } while (0)
#define TEST_ASSERT_EQ(actual, expected) do { if (actual != expected) { std::cerr << "\n" __FILE__ ":" << __LINE__ << ": assertion failed: " #actual "\n actual: " << actual << "\n expected: " << expected << "\n"; return false; } } while (0)
static bool assert_then_clear_test_history(const char *file, size_t line, const std::vector<Op> &expected) {
const std::vector<Entry> &actual = usb3sun_test_get_history();
Expand Down Expand Up @@ -598,7 +609,7 @@ static std::vector<uint8_t> bytes(size_t len, const char *data) {

static bool run_test(const char *test_name) {
if (!strcmp(test_name, "setup_pinout_v1")) {
usb3sun_test_init(PinoutV2Op::id | SunkInitOp::id | SunmInitOp::id | GpioWriteOp::id | GpioReadOp::id);
usb3sun_test_init(PinoutV2Op::id | SunkInitOp::id | SunmInitOp::id | GpioWriteOp::id | GpioReadOp::id | SunkSnifferInitOp::id);
usb3sun_mock_gpio_read(PINOUT_V2_PIN, false);
setup();
return assert_then_clear_test_history(std::vector<Op> {
Expand All @@ -607,6 +618,9 @@ static bool run_test(const char *test_name) {
#ifdef SUNK_ENABLE
SunkInitOp {},
#endif
#ifdef SUNK_SNIFFER_ENABLE
SunkSnifferInitOp {},
#endif
#ifdef SUNM_ENABLE
SunmInitOp {9600},
#endif
Expand All @@ -615,7 +629,7 @@ static bool run_test(const char *test_name) {
}

if (!strcmp(test_name, "setup_pinout_v2")) {
usb3sun_test_init(PinoutV2Op::id | SunkInitOp::id | SunmInitOp::id | GpioWriteOp::id | GpioReadOp::id);
usb3sun_test_init(PinoutV2Op::id | SunkInitOp::id | SunmInitOp::id | GpioWriteOp::id | GpioReadOp::id | SunkSnifferInitOp::id);
usb3sun_mock_gpio_read(PINOUT_V2_PIN, true);
setup();
return assert_then_clear_test_history(std::vector<Op> {
Expand All @@ -625,6 +639,11 @@ static bool run_test(const char *test_name) {
GpioWriteOp {DISPLAY_ENABLE, true},
#ifdef SUNK_ENABLE
SunkInitOp {},
#endif
#ifdef SUNK_SNIFFER_ENABLE
SunkSnifferInitOp {},
#endif
#if defined(SUNK_ENABLE) || defined(SUNK_SNIFFER_ENABLE)
GpioWriteOp {KTX_ENABLE, false},
#endif
#ifdef SUNM_ENABLE
Expand All @@ -635,8 +654,8 @@ static bool run_test(const char *test_name) {
}

if (!strcmp(test_name, "sunk_reset")) {
#ifndef SUNK_ENABLE
TEST_REQUIRES(SUNK_ENABLE);
#if !defined(SUNK_ENABLE) && !defined(SUNK_SNIFFER_ENABLE)
TEST_REQUIRES(SUNK_ENABLE or SUNK_SNIFFER_ENABLE);
#endif
usb3sun_test_init(SunkReadOp::id | SunkWriteOp::id);
usb3sun_mock_sunk_read("\x01", 1); // SUNK_RESET
Expand All @@ -646,10 +665,14 @@ static bool run_test(const char *test_name) {
serialEvent2();
}
return assert_then_clear_test_history(std::vector<Op> {
#if defined(SUNK_ENABLE) || defined(SUNK_SNIFFER_ENABLE)
SunkReadOp {},
#ifndef SUNK_SNIFFER_ENABLE
SunkWriteOp {{0xFF, 0x04, 0x7F}},
#endif
SunkReadOp {},
SunkReadOp {},
#endif
});
}

Expand Down Expand Up @@ -681,8 +704,8 @@ static bool run_test(const char *test_name) {
}

if (!strcmp(test_name, "buzzer_bell")) {
#ifndef SUNK_ENABLE
TEST_REQUIRES(SUNK_ENABLE);
#if !defined(SUNK_ENABLE) && !defined(SUNK_SNIFFER_ENABLE)
TEST_REQUIRES(SUNK_ENABLE or SUNK_SNIFFER_ENABLE);
#endif
usb3sun_test_init(BuzzerStartOp::id | GpioWriteOp::id);
usb3sun_mock_sunk_read("\x01\x02\x03", 3); // SUNK_RESET, SUNK_BELL_ON, SUNK_BELL_OFF
Expand All @@ -702,8 +725,8 @@ static bool run_test(const char *test_name) {
}

if (!strcmp(test_name, "buzzer_click")) {
#ifndef SUNK_ENABLE
TEST_REQUIRES(SUNK_ENABLE);
#if !defined(SUNK_ENABLE) && !defined(SUNK_SNIFFER_ENABLE)
TEST_REQUIRES(SUNK_ENABLE or SUNK_SNIFFER_ENABLE);
#endif
const auto pumpSunkInput = []() {
while (usb3sun_mock_sunk_read_has_input()) {
Expand Down
6 changes: 5 additions & 1 deletion src/pinout.cc
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,11 @@ void Pinout::begin() {
void Pinout::beginSun() {
#if defined(SUNK_ENABLE)
usb3sun_sunk_init();

#endif
#if defined(SUNK_SNIFFER_ENABLE)
usb3sun_sunk_sniffer_init();
#endif
#if defined(SUNK_ENABLE) || defined(SUNK_SNIFFER_ENABLE)
if (usb3sun_pinout_version() == 2) {
// break preventer: set KTX_ENABLE# low to connect sun keyboard tx.
// the pin is high on reset and boot, which pulls INT_KTX low, which keeps the
Expand Down

0 comments on commit 25d9def

Please sign in to comment.