diff options
Diffstat (limited to 'linux/305keyboard.subx')
-rw-r--r-- | linux/305keyboard.subx | 219 |
1 files changed, 219 insertions, 0 deletions
diff --git a/linux/305keyboard.subx b/linux/305keyboard.subx new file mode 100644 index 00000000..32159e49 --- /dev/null +++ b/linux/305keyboard.subx @@ -0,0 +1,219 @@ +# Primitives for keyboard control. +# Require Linux and a modern terminal. + +== code + +enable-keyboard-immediate-mode: + # . prologue + 55/push-ebp + 89/<- %ebp 4/r32/esp + # . save registers + 50/push-eax + 51/push-ecx + 52/push-edx + 53/push-ebx + 56/push-esi + 57/push-edi + # + (_maybe-open-terminal) + # var terminal-info/esi: (addr termios) + # termios is a type from the Linux kernel. We don't care how large it is. + 81 5/subop/subtract %esp 0x100/imm32 + 89/<- %esi 4/r32/esp + # ioctl(*Terminal-file-descriptor, TCGETS, terminal-info) + 89/<- %edx 6/r32/esi + b9/copy-to-ecx 0x5401/imm32/TCGETS + 8b/-> *Terminal-file-descriptor 3/r32/ebx + e8/call syscall_ioctl/disp32 + # terminal-info->c_iflags &= Keyboard-immediate-mode-iflags +#? (write-buffered Stderr "iflags before: ") +#? (write-int32-hex-buffered Stderr *esi) +#? (write-buffered Stderr Newline) +#? (flush Stderr) + 8b/-> *esi 0/r32/eax # Termios-c_iflag + 23/and *Keyboard-immediate-mode-iflags 0/r32/eax + 89/<- *esi 0/r32/eax # Termios-c_iflag +#? (write-buffered Stderr "iflags after: ") +#? (write-int32-hex-buffered Stderr *esi) +#? (write-buffered Stderr Newline) +#? (flush Stderr) + # terminal-info->c_lflags &= Keyboard-immediate-mode-lflags +#? (write-buffered Stderr "lflags before: ") +#? (write-int32-hex-buffered Stderr *(esi+0xc)) +#? (write-buffered Stderr Newline) +#? (flush Stderr) + 8b/-> *(esi+0xc) 0/r32/eax # Termios-c_lflag + 23/and *Keyboard-immediate-mode-lflags 0/r32/eax + 89/<- *(esi+0xc) 0/r32/eax # Termios-c_lflag +#? (write-buffered Stderr "lflags after: ") +#? (write-int32-hex-buffered Stderr *(esi+0xc)) +#? (write-buffered Stderr Newline) +#? (flush Stderr) + # ioctl(*Terminal-file-descriptor, TCSETS, terminal-info) + 89/<- %edx 6/r32/esi + b9/copy-to-ecx 0x5402/imm32/TCSETS + 8b/-> *Terminal-file-descriptor 3/r32/ebx + e8/call syscall_ioctl/disp32 +$enable-keyboard-immediate-mode:end: + # . reclaim locals + 81 0/subop/add %esp 0x100/imm32 + # . restore registers + 5f/pop-to-edi + 5e/pop-to-esi + 5b/pop-to-ebx + 5a/pop-to-edx + 59/pop-to-ecx + 58/pop-to-eax + # . epilogue + 89/<- %esp 5/r32/ebp + 5d/pop-to-ebp + c3/return + +enable-keyboard-type-mode: + # . prologue + 55/push-ebp + 89/<- %ebp 4/r32/esp + # . save registers + 50/push-eax + 51/push-ecx + 52/push-edx + 53/push-ebx + 56/push-esi + 57/push-edi + # + (_maybe-open-terminal) + # var terminal-info/esi: (addr termios) + # termios is a type from the Linux kernel. We don't care how large it is. + 81 5/subop/subtract %esp 0x100/imm32 + 89/<- %esi 4/r32/esp + # ioctl(*Terminal-file-descriptor, TCGETS, terminal-info) + 89/<- %edx 6/r32/esi + b9/copy-to-ecx 0x5401/imm32/TCGETS + 8b/-> *Terminal-file-descriptor 3/r32/ebx + e8/call syscall_ioctl/disp32 + # terminal-info->c_iflags |= Keyboard-type-mode-iflags + 8b/-> *esi 0/r32/eax # Termios-c_iflag + 0b/or *Keyboard-type-mode-iflags 0/r32/eax + 89/<- *esi 0/r32/eax # Termios-c_iflag + # terminal-info->c_lflags |= Keyboard-type-mode-lflags + 8b/-> *(esi+0xc) 0/r32/eax # Termios-c_lflag + 0b/or *Keyboard-type-mode-lflags 0/r32/eax + 89/<- *(esi+0xc) 0/r32/eax # Termios-c_lflag + # ioctl(*Terminal-file-descriptor, TCSETS, terminal-info) + 89/<- %edx 6/r32/esi + b9/copy-to-ecx 0x5402/imm32/TCSETS + 8b/-> *Terminal-file-descriptor 3/r32/ebx + e8/call syscall_ioctl/disp32 +$enable-keyboard-type-mode:end: + # . reclaim locals + 81 0/subop/add %esp 0x100/imm32 + # . restore registers + 5f/pop-to-edi + 5e/pop-to-esi + 5b/pop-to-ebx + 5a/pop-to-edx + 59/pop-to-ecx + 58/pop-to-eax + # . epilogue + 89/<- %esp 5/r32/ebp + 5d/pop-to-ebp + c3/return + +# read keys or escapes up to 4 bytes +# +# fun fact: terminal escapes and graphemes in utf-8 don't conflict! +# - in graphemes all but the first/lowest byte will have a 1 in the MSB (be +# greater than 0x7f) +# - in escapes every byte will have a 0 in the MSB +# the two categories overlap only when the first/lowest byte is 0x1b or 'esc' +# +# Only use this in immediate mode; in type (typewriter) mode 4 bytes may get +# parts of multiple keys. +read-key-from-real-keyboard: # -> result/eax: grapheme + # . prologue + 55/push-ebp + 89/<- %ebp 4/r32/esp + # . save registers + 51/push-ecx + # var buf/ecx: (stream byte 4) + 68/push 0/imm32/data + 68/push 4/imm32/size + 68/push 0/imm32/read + 68/push 0/imm32/write + 89/<- %ecx 4/r32/esp + # + (read 0 %ecx) # => eax + 8b/-> *(ecx+0xc) 0/r32/eax +$read-key-from-real-keyboard:end: + # . reclaim locals + 81 0/subop/add %esp 0x10/imm32 + # . restore registers + 59/pop-to-ecx + # . epilogue + 89/<- %esp 5/r32/ebp + 5d/pop-to-ebp + c3/return + +# use this in type mode +read-line-from-real-keyboard: # out: (addr stream byte) + # . prologue + 55/push-ebp + 89/<- %ebp 4/r32/esp + # + (read-line-buffered Stdin *(ebp+8)) +$read-line-from-real-keyboard:end: + # . epilogue + 89/<- %esp 5/r32/ebp + 5d/pop-to-ebp + c3/return + +== data + +# iflags: octal hex +# IGNBRK 0000001 0x0001 +# BRKINT 0000002 0x0002 +# IGNPAR 0000004 0x0004 +# PARMRK 0000010 0x0008 +# INPCK 0000020 0x0010 +# ISTRIP 0000040 0x0020 +# INLCR 0000100 0x0040 +# IGNCR 0000200 0x0080 +# ICRNL 0000400 0x0100 +# IUCLC 0001000 0x0200 +# IXON 0002000 0x0400 +# IXANY 0004000 0x0800 +# IXOFF 0010000 0x1000 +# IMAXBEL 0020000 0x2000 +# IUTF8 0040000 0x4000 + +# lflags: +# ISIG 0000001 0x0001 +# ICANON 0000002 0x0002 +# ECHO 0000010 0x0008 +# ECHOE 0000020 0x0010 +# ECHOK 0000040 0x0020 +# ECHONL 0000100 0x0040 +# NOFLSH 0000200 0x0080 +# TOSTOP 0000400 0x0100 +# IEXTEN 0100000 0x8000 + +# recipe for raw mode according to the termios.3 manpage on Linux: +# termios_p->c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON); +# termios_p->c_oflag &= ~OPOST; +# termios_p->c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN); +# termios_p->c_cflag &= ~(CSIZE | PARENB); +# termios_p->c_cflag |= CS8; + +Keyboard-immediate-mode-iflags: # (addr tcflag_t) +#? 0xfffffa14 # ~IGNBRK & ~BRKINT & ~PARMRK & ~ISTRIP & ~INLCR & ~IGNCR & ~ICRNL & ~IXON + 0xffffffff/imm32 + +Keyboard-immediate-mode-lflags: # (addr tcflag_t) +#? 0xffff7fb4/imm32 # ~ICANON & ~ISIG & ~IEXTEN & ~ECHO & ~ECHONL + 0xffffffb5/imm32 # ~ICANON & ~ECHO & ~ECHONL + +Keyboard-type-mode-iflags: # (addr tcflag_t) + 0x00000000/imm32 # ~Keyboard-immediate-mode-iflags + +Keyboard-type-mode-lflags: # (addr tcflag_t) + 0x0000004a/imm32 # ~Keyboard-immediate-mode-lflags |