aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/mds-kkbd.c195
-rw-r--r--src/mds-kkbd.h16
2 files changed, 173 insertions, 38 deletions
diff --git a/src/mds-kkbd.c b/src/mds-kkbd.c
index 51a8953..afa9cac 100644
--- a/src/mds-kkbd.c
+++ b/src/mds-kkbd.c
@@ -111,6 +111,25 @@ static struct termios saved_stty;
*/
static int saved_kbd_mode;
+/**
+ * Keycode remapping table
+ */
+static int* restrict mapping = NULL;
+
+/**
+ * The size of `mapping`
+ */
+static size_t mapping_size = 0;
+
+/**
+ * Scancode buffer
+ */
+static int scancode_buf[3] = { 0, 0, 0 };
+
+/**
+ * The number of elements stored in `scancode_buf`
+ */
+static int scancode_ptr = 0;
@@ -211,7 +230,8 @@ void fork_cleanup(int status)
*/
size_t marshal_server_size(void)
{
- size_t rc = 5 * sizeof(int) + sizeof(int32_t) + sizeof(struct termios);
+ size_t rc = 9 * sizeof(int) + sizeof(int32_t) + sizeof(struct termios);
+ rc += sizeof(size_t) + mapping_size * sizeof(int);
rc += mds_message_marshal_size(&received);
return rc;
}
@@ -232,9 +252,20 @@ int marshal_server(char* state_buf)
buf_set_next(state_buf, int, saved_leds);
buf_set_next(state_buf, struct termios, saved_stty);
buf_set_next(state_buf, int, saved_kbd_mode);
+ buf_set_next(state_buf, int, scancode_ptr);
+ buf_set_next(state_buf, int, scancode_buf[0]);
+ buf_set_next(state_buf, int, scancode_buf[1]);
+ buf_set_next(state_buf, int, scancode_buf[2]);
+ buf_set_next(state_buf, size_t, mapping_size);
+ if (mapping_size > 0)
+ {
+ memcpy(state_buf, mapping, mapping_size * sizeof(int));
+ state_buf += mapping_size * sizeof(int) / sizeof(char);
+ }
mds_message_marshal(&received, state_buf);
mds_message_destroy(&received);
+ free(mapping);
return 0;
}
@@ -259,12 +290,24 @@ int unmarshal_server(char* state_buf)
buf_get_next(state_buf, int, saved_leds);
buf_get_next(state_buf, struct termios, saved_stty);
buf_get_next(state_buf, int, saved_kbd_mode);
+ buf_get_next(state_buf, int, scancode_ptr);
+ buf_get_next(state_buf, int, scancode_buf[0]);
+ buf_get_next(state_buf, int, scancode_buf[1]);
+ buf_get_next(state_buf, int, scancode_buf[2]);
+ buf_get_next(state_buf, size_t, mapping_size);
+ if (mapping_size > 0)
+ {
+ fail_if (xmalloc(mapping, mapping_size, int));
+ memcpy(mapping, state_buf, mapping_size * sizeof(int));
+ state_buf += mapping_size * sizeof(int) / sizeof(char);
+ }
fail_if (mds_message_unmarshal(&received, state_buf));
return 0;
pfail:
xperror(*argv);
mds_message_destroy(&received);
+ free(mapping);
abort(); /* We must abort on failure to not risk the keyboard
getting stuck and freeze up the computer until
someone ssh:es into it and kill the server. */
@@ -292,44 +335,11 @@ int __attribute__((const)) reexec_failure_recover(void)
int master_loop(void)
{
int rc = 1;
- int c, keycode, released;
- int scancode[3];
-
- while ((c = getchar()) != 1) /* Exit with ESCAPE */
- {
- redo:
- keycode = c & 0x7F;
- released = !!(c & 0x80);
- scancode[0] = keycode;
-
- if (keycode == 0)
- {
- scancode[1] = getchar();
- if ((scancode[1] & 0x80) == 0)
- {
- c = scancode[1];
- goto redo;
- }
- scancode[2] = getchar();
- if ((scancode[2] & 0x80) == 0)
- {
- printf("scancode: %i\n", scancode[1]);
- printf("keycode: %i\n", scancode[1]);
- printf("released: no\n");
- c = scancode[2];
- goto redo;
- }
- keycode = (scancode[1] & 0x7F) << 7;
- keycode |= (scancode[2] & 0x7F);
- printf("scancode: %i %i %i\n",
- scancode[0], scancode[1], scancode[2]);
- }
- else
- printf("scancode: %i\n", scancode[0]);
- printf("keycode: %i\n", keycode);
- printf("released: %s\n", released ? "yes" : "no");
- }
+ while (!reexecing && !terminating)
+ if (fetch_keys() < 0)
+ if (errno != EINTR)
+ goto pfail;
/*
while (!reexecing && !terminating)
{
@@ -368,6 +378,7 @@ int master_loop(void)
if (!rc && reexecing)
return 0;
mds_message_destroy(&received);
+ free(mapping);
return rc;
}
@@ -505,5 +516,113 @@ void close_input(void)
}
+/**
+ * Broadcast a keyboard input event
+ *
+ * @param scancode The scancode
+ * @param trio Whether the scancode has three integers rather than one
+ * @return Zero on success, -1 on error
+ */
+int send_key(int* restrict scancode, int trio)
+{
+ int keycode, released = (scancode[0] & 0x80) == 0x80;
+ scancode[0] &= 0x7F;
+ if (trio)
+ {
+ keycode = (scancode[1] &= 0x7F) << 7;
+ keycode |= (scancode[2] &= 0x7F);
+ }
+ else
+ keycode = scancode[0];
+
+ if ((size_t)keycode < mapping_size)
+ keycode = mapping[keycode];
+
+ printf("Command: key-sent\n");
+ if (trio)
+ printf("Scancode: %i %i %i\n", scancode[0], scancode[1], scancode[2]);
+ else
+ printf("Scancode: %i\n", scancode[0]);
+ printf("Keycode: %i\n", keycode);
+ printf("Released: %s\n", released ? "yes" : "no");
+ printf("Keyboard: kernel\n\n");
+
+ return 0;
+}
+
+
+/**
+ * Fetch and broadcast keys until interrupted
+ *
+ * @return Zero on success, -1 on error
+ */
+int fetch_keys(void)
+{
+#ifdef DEBUG
+ int consecutive_escapes = 0;
+#endif
+ int c;
+ ssize_t r;
+
+ for (;;)
+ {
+ r = read(STDIN_FILENO, &c, sizeof(int));
+ if (r <= 0)
+ {
+ if (r == 0)
+ {
+ raise(SIGTERM);
+ errno = 0;
+ }
+ break;
+ }
+
+#ifdef DEBUG
+ if ((c & 0x7F) == 1) /* Exit with ESCAPE, ESCAPE, ESCAPE */
+ {
+ if (++consecutive_escapes >= 6)
+ {
+ raise(SIGTERM);
+ break;
+ }
+ }
+ else
+ consecutive_escapes = 0;
+#endif
+
+ redo:
+ scancode_buf[scancode_ptr] = c;
+ if (scancode_ptr == 0)
+ {
+ if ((c & 0x7F) == 0)
+ scancode_ptr++;
+ else
+ send_key(scancode_buf, 0);
+ }
+ else if (scancode_ptr == 1)
+ {
+ if ((c & 0x80) == 0)
+ {
+ scancode_ptr = 0;
+ goto redo;
+ }
+ scancode_ptr++;
+ }
+ else
+ {
+ scancode_ptr = 0;
+ if ((c & 0x80) == 0)
+ {
+ send_key(scancode_buf + 1, 0);
+ goto redo;
+ }
+ send_key(scancode_buf, 1);
+ }
+ }
+
+ return errno == 0 ? 0 : -1;
+}
+
+
/* TODO delay and repetition */
diff --git a/src/mds-kkbd.h b/src/mds-kkbd.h
index fc22f2b..3fa7eca 100644
--- a/src/mds-kkbd.h
+++ b/src/mds-kkbd.h
@@ -70,6 +70,22 @@ int open_input(void);
*/
void close_input(void);
+/**
+ * Broadcast a keyboard input event
+ *
+ * @param scancode The scancode
+ * @param trio Whether the scancode has three integers rather than one
+ * @return Zero on success, -1 on error
+ */
+int send_key(int* restrict scancode, int trio);
+
+/**
+ * Fetch and broadcast keys until interrupted
+ *
+ * @return Zero on success, -1 on error
+ */
+int fetch_keys(void);
+
#endif