mirror of
https://github.com/grymoire/i2c_puppet-Linux.git
synced 2024-12-26 13:38:21 +01:00
Added support for Control characters and the characters <escape> and "<>{}[]^&%=\"
This commit is contained in:
parent
c44f9546e3
commit
f27d75ea35
67
LINUX.md
Normal file
67
LINUX.md
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
# I2C Puppet mods for Linux systems
|
||||||
|
|
||||||
|
The original version lacked certain characters, such as <ESCAPE>, and the characters "<>{}[]^&%=\"
|
||||||
|
which made it difficult to use on Linux systems
|
||||||
|
|
||||||
|
|
||||||
|
This version of the firmware has been modified to support Linux systems.
|
||||||
|
The following changes have been made
|
||||||
|
1) The backspace key works during the GUI login
|
||||||
|
2) The Sym key not acts as a Control key, so SYM+C is Control-C
|
||||||
|
3) The four top button keys are now used to provide the missing characters.
|
||||||
|
|
||||||
|
The original definiton of the keys were this
|
||||||
|
|
||||||
|
L1 L2 R1 R2 SPKR Mic BS NL SPACE
|
||||||
|
$ ~ \b \n
|
||||||
|
Shift
|
||||||
|
Alt 0
|
||||||
|
Sym | TAB
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
The current definition of the keys are
|
||||||
|
|
||||||
|
L1 L2 R1 R2 SPKR Mic BS NL Spacebar
|
||||||
|
<none> <esc> % = \ $ ~ BS \n <space>
|
||||||
|
Alt > ] } & ` ~ x <tab>
|
||||||
|
Shift < [ { ^ $ ` BS <space>
|
||||||
|
Sym x x x x $ ~ BS | <space>
|
||||||
|
|
||||||
|
|
||||||
|
#Linux Debug tips
|
||||||
|
|
||||||
|
The keyboard was two "outputs" - one is the USB HID interface, the other is the serial port.
|
||||||
|
Any printf() command goes to the serial port.
|
||||||
|
|
||||||
|
When the keyboard is plugged into a Linux system, a new TTY interface will appear. I usually use "ls -lt /dev/tty* | head"
|
||||||
|
to learn the name, as the newest port will appear first. On my system, it's /dev/ttyACM0
|
||||||
|
|
||||||
|
So on one terminal, I type
|
||||||
|
|
||||||
|
cat -v </dev/ttyACM0
|
||||||
|
|
||||||
|
while on a second terminal window, I type
|
||||||
|
|
||||||
|
cat -v
|
||||||
|
|
||||||
|
The first one will print all of the printf output, and the second will show you how the keyboard works normally.
|
||||||
|
|
||||||
|
#Compiling on Linux
|
||||||
|
|
||||||
|
I edit the files in <GIT>/ic2_puppet/all/ using my preferred editor. In my case, I use emacs. I have the keystroke combination "Control-C M" bound to compile, using
|
||||||
|
|
||||||
|
(global-set-key "\C-cm" 'compile)
|
||||||
|
|
||||||
|
And when I press these keys, emacs saves all files, and recompiles the
|
||||||
|
code. I have a small hub with switchable on/off ports, and restart the
|
||||||
|
keyboard into boot mode, and then do a "make install" to load the new
|
||||||
|
firmware
|
||||||
|
|
||||||
|
|
||||||
|
#TODO
|
||||||
|
|
||||||
|
Currently - the SYM+Button keys are defined as the character "x" to indicate it's not been specified.
|
||||||
|
I'l like to make these keys to the 4 arrow keys.
|
||||||
|
|
||||||
|
Also - it might be possible to create key combinations by combining the modified keys, like SYM+Alt+key
|
6
app/Makefile
Normal file
6
app/Makefile
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
# Make it useful for Linux
|
||||||
|
all: keyboard.c keyboard.h usb.c
|
||||||
|
cd ../build;make
|
||||||
|
install: ../build/app/i2c_puppet.uf2
|
||||||
|
cp ../build/app/i2c_puppet.uf2 /media/${USER}/RPI-RP2
|
||||||
|
|
@ -2,6 +2,7 @@
|
|||||||
#include "fifo.h"
|
#include "fifo.h"
|
||||||
#include "keyboard.h"
|
#include "keyboard.h"
|
||||||
#include "reg.h"
|
#include "reg.h"
|
||||||
|
#include <stdio.h> // BGB
|
||||||
|
|
||||||
#include <pico/stdlib.h>
|
#include <pico/stdlib.h>
|
||||||
|
|
||||||
@ -114,12 +115,76 @@ static void transition_to(struct list_item * const p_item, const enum key_state
|
|||||||
if (reg_is_bit_set(REG_ID_CFG, CFG_USE_MODS)) {
|
if (reg_is_bit_set(REG_ID_CFG, CFG_USE_MODS)) {
|
||||||
const bool shift = (self.mods[KEY_MOD_ID_SHL] || self.mods[KEY_MOD_ID_SHR]) | self.capslock;
|
const bool shift = (self.mods[KEY_MOD_ID_SHL] || self.mods[KEY_MOD_ID_SHR]) | self.capslock;
|
||||||
const bool alt = self.mods[KEY_MOD_ID_ALT] | self.numlock;
|
const bool alt = self.mods[KEY_MOD_ID_ALT] | self.numlock;
|
||||||
const bool is_button = (key <= KEY_BTN_RIGHT1) || ((key >= KEY_BTN_LEFT2) && (key <= KEY_BTN_RIGHT2));
|
// const bool is_button = (key <= KEY_BTN_RIGHT1) || ((key >= KEY_BTN_LEFT2) && (key <= KEY_BTN_RIGHT2));
|
||||||
|
const bool is_button = ((key == KEY_BTN_RIGHT1)
|
||||||
|
|| (key == KEY_BTN_RIGHT2)
|
||||||
|
|| (key == KEY_BTN_LEFT1)
|
||||||
|
|| (key == KEY_BTN_LEFT2));
|
||||||
|
const bool control = self.mods[KEY_MOD_ID_SYM];
|
||||||
|
|
||||||
if (alt && !is_button) {
|
|
||||||
|
if (is_button) {
|
||||||
|
switch (key) {
|
||||||
|
case KEY_BTN_LEFT1:
|
||||||
|
if (alt) {
|
||||||
|
key = '>';
|
||||||
|
} else if (shift) {
|
||||||
|
key = '<';
|
||||||
|
} else if (control) {
|
||||||
|
key = 'x';
|
||||||
|
} else {
|
||||||
|
key =0x1B; // ESC
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case KEY_BTN_LEFT2:
|
||||||
|
if (alt) {
|
||||||
|
key = ']';
|
||||||
|
} else if (shift) {
|
||||||
|
key = '[';
|
||||||
|
} else if (control) {
|
||||||
|
key ='x';
|
||||||
|
} else {
|
||||||
|
key = '%';
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case KEY_BTN_RIGHT1:
|
||||||
|
if (alt) {
|
||||||
|
key = '}';
|
||||||
|
} else if (shift) {
|
||||||
|
key = '{';
|
||||||
|
} else if (control) {
|
||||||
|
key = 'x';
|
||||||
|
} else {
|
||||||
|
key = '=';
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case KEY_BTN_RIGHT2:
|
||||||
|
if (alt) {
|
||||||
|
key = '&';
|
||||||
|
} else if (shift) {
|
||||||
|
key = '^';
|
||||||
|
} else if (control) {
|
||||||
|
key = 'x'; // TODO
|
||||||
|
} else {
|
||||||
|
key = '\\';
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// printf(" ERROR: Illegal key: %d\n", key);
|
||||||
|
;
|
||||||
|
}
|
||||||
|
} else if (alt) {
|
||||||
|
printf(" alt \n");
|
||||||
key = p_entry->alt;
|
key = p_entry->alt;
|
||||||
} else if (!shift && (key >= 'A' && key <= 'Z')) {
|
} else if (key >= 'A' && key <= 'Z') {
|
||||||
|
printf(" letter\n");
|
||||||
|
if (control) { // If the SYM key is held down, it's a control key
|
||||||
|
key = key - 0x40;
|
||||||
|
} else if (!shift) { // lower case letter
|
||||||
key = (key + ' ');
|
key = (key + ' ');
|
||||||
|
} else {
|
||||||
|
// it's an uppercase letter - do nothing
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,24 +22,24 @@ enum key_mod
|
|||||||
KEY_MOD_ID_LAST,
|
KEY_MOD_ID_LAST,
|
||||||
};
|
};
|
||||||
|
|
||||||
#define KEY_JOY_UP 0x01
|
#define KEY_JOY_UP 0x81
|
||||||
#define KEY_JOY_DOWN 0x02
|
#define KEY_JOY_DOWN 0x82
|
||||||
#define KEY_JOY_LEFT 0x03
|
#define KEY_JOY_LEFT 0x83
|
||||||
#define KEY_JOY_RIGHT 0x04
|
#define KEY_JOY_RIGHT 0x84
|
||||||
#define KEY_JOY_CENTER 0x05
|
#define KEY_JOY_CENTER 0x85
|
||||||
#define KEY_BTN_LEFT1 0x06
|
#define KEY_BTN_LEFT1 0x86
|
||||||
#define KEY_BTN_RIGHT1 0x07
|
#define KEY_BTN_RIGHT1 0x87
|
||||||
// 0x08 - BACKSPACE
|
// 0x08 - BACKSPACE
|
||||||
// 0x09 - TAB
|
// 0x09 - TAB
|
||||||
// 0x0A - NEW LINE
|
// 0x0A - NEW LINE
|
||||||
// 0x0D - CARRIAGE RETURN
|
// 0x0D - CARRIAGE RETURN
|
||||||
#define KEY_BTN_LEFT2 0x11
|
#define KEY_BTN_LEFT2 0x91
|
||||||
#define KEY_BTN_RIGHT2 0x12
|
#define KEY_BTN_RIGHT2 0x92
|
||||||
|
|
||||||
#define KEY_MOD_ALT 0x1A
|
#define KEY_MOD_ALT 0x9A
|
||||||
#define KEY_MOD_SHL 0x1B // Left Shift
|
#define KEY_MOD_SHL 0x9B // Left Shift
|
||||||
#define KEY_MOD_SHR 0x1C // Right Shift
|
#define KEY_MOD_SHR 0x9C // Right Shift
|
||||||
#define KEY_MOD_SYM 0x1D
|
#define KEY_MOD_SYM 0x9D
|
||||||
|
|
||||||
struct key_callback
|
struct key_callback
|
||||||
{
|
{
|
||||||
|
17
app/usb.c
17
app/usb.c
@ -55,8 +55,10 @@ static void key_cb(char key, enum key_state state)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
if (tud_hid_n_ready(USB_ITF_KEYBOARD) && reg_is_bit_set(REG_ID_CF2, CF2_USB_KEYB_ON)) {
|
if (tud_hid_n_ready(USB_ITF_KEYBOARD) && reg_is_bit_set(REG_ID_CF2, CF2_USB_KEYB_ON)) {
|
||||||
uint8_t conv_table[128][2] = { HID_ASCII_TO_KEYCODE };
|
// conv_table needs to be 256 entries long because the special keys are in range 128-256 (0x80 - 0xFF)
|
||||||
|
uint8_t conv_table[256][2] = { HID_ASCII_TO_KEYCODE };
|
||||||
conv_table['\n'][1] = HID_KEY_ENTER; // Fixup: Enter instead of Return
|
conv_table['\n'][1] = HID_KEY_ENTER; // Fixup: Enter instead of Return
|
||||||
|
conv_table['\b'][1] = HID_KEY_BACKSPACE; // Fixup: HID backspace (0x2A) instead of \b (0x08)
|
||||||
conv_table[KEY_JOY_UP][1] = HID_KEY_ARROW_UP;
|
conv_table[KEY_JOY_UP][1] = HID_KEY_ARROW_UP;
|
||||||
conv_table[KEY_JOY_DOWN][1] = HID_KEY_ARROW_DOWN;
|
conv_table[KEY_JOY_DOWN][1] = HID_KEY_ARROW_DOWN;
|
||||||
conv_table[KEY_JOY_LEFT][1] = HID_KEY_ARROW_LEFT;
|
conv_table[KEY_JOY_LEFT][1] = HID_KEY_ARROW_LEFT;
|
||||||
@ -66,9 +68,20 @@ static void key_cb(char key, enum key_state state)
|
|||||||
uint8_t modifier = 0;
|
uint8_t modifier = 0;
|
||||||
|
|
||||||
if (state == KEY_STATE_PRESSED) {
|
if (state == KEY_STATE_PRESSED) {
|
||||||
if (conv_table[(int)key][0])
|
printf(" conv_table[%d][0,1]=%d,%d ",key, conv_table[(int)key][0], conv_table[(int)key][1]); // bgb
|
||||||
|
if (conv_table[(int)key][0]) {
|
||||||
modifier = KEYBOARD_MODIFIER_LEFTSHIFT;
|
modifier = KEYBOARD_MODIFIER_LEFTSHIFT;
|
||||||
|
} else if (key < 0x20) { // it's a control key
|
||||||
|
if ((key == '\n') || (key == '\b')) {
|
||||||
|
// leave alone - this is necessary because the Linux graphical login processes the HID equivalent
|
||||||
|
// which is done using conv_table[] below
|
||||||
|
} else {
|
||||||
|
// convert control key, i.e. [Control-A] converts to [modifier=control, key=A]
|
||||||
|
modifier=KEYBOARD_MODIFIER_RIGHTCTRL;
|
||||||
|
key=key + 0x40;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
keycode[0] = conv_table[(int)key][1];
|
keycode[0] = conv_table[(int)key][1];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user