added tty

This commit is contained in:
2026-04-11 00:21:06 +02:00
parent c870ab8561
commit 554d32f7e8
5 changed files with 366 additions and 0 deletions
+5
View File
@@ -0,0 +1,5 @@
tty: tty.S
as -o tty.o tty.S
ld -o tty tty.o
clean:
rm -f tty tty.o
+255
View File
@@ -0,0 +1,255 @@
.intel_syntax noprefix
# syscall numbers
.equ SYS_READ, 0
.equ SYS_WRITE, 1
.equ SYS_OPEN, 2
.equ SYS_CLOSE, 3
.equ SYS_POLL, 7
.equ SYS_IOCTL, 16
.equ SYS_EXIT, 60
# ioctl / termios
.equ TCGETS, 0x5401
.equ TCSETS, 0x5402
.equ TERMIOS_SIZE, 60 # sizeof(struct termios) on x86_64
# termios c_lflag bits to clear
.equ ICANON, 0x2
.equ ECHO, 0x8
.equ ISIG, 0x1
# termios c_iflag bits to clear
.equ IGNBRK, 0x1
.equ BRKINT, 0x2
.equ PARMRK, 0x8
.equ ISTRIP, 0x20
.equ INLCR, 0x40
.equ IGNCR, 0x80
.equ ICRNL, 0x100
.equ IXON, 0x400
# termios c_oflag bits to clear
.equ OPOST, 0x1
# termios c_cflag
.equ CSIZE, 0x30
.equ PARENB, 0x100
.equ CS8, 0x30
.equ CLOCAL, 0x800
.equ CREAD, 0x80
# baud
.equ B115200, 0x1002
# open flags
.equ O_RDWR, 0x2
.equ O_NOCTTY, 0x100
# poll
.equ POLLIN, 0x1
.equ POLLFD_SIZE, 8
# termios field offsets
.equ OFLAG_OFF, 4
.equ CFLAG_OFF, 8
.equ LFLAG_OFF, 12
.equ CC_OFF, 17 # c_cc array offset
.equ VMIN, 6 # c_cc index
.equ VTIME, 5 # c_cc index
.equ ISPEED_OFF, 52
.equ OSPEED_OFF, 56
.data
devpath: .asciz "/dev/ttyUSB0"
banner: .ascii "Holck's minitty - ctrl-d to exit!\r\n"
.equ BANNER_LEN, . - banner
.bss
.align 8
serial_fd: .quad 0
old_termios: .space TERMIOS_SIZE
raw_termios: .space TERMIOS_SIZE
ser_termios: .space TERMIOS_SIZE
pollfds: .space POLLFD_SIZE * 2 # two pollfd structs
buf: .space 256
.text
.globl _start
_start:
# Open serial port
mov rdi, offset devpath
mov rsi, O_RDWR | O_NOCTTY
xor rdx, rdx
mov rax, SYS_OPEN
syscall
test rax, rax
js exit_fail
mov [serial_fd], rax
# Get serial termios & configure
mov rdi, rax
mov rsi, TCGETS
lea rdx, [ser_termios]
mov rax, SYS_IOCTL
syscall
# cfmakeraw equivalent for serial
lea rbx, [ser_termios]
# iflag: clear everything raw clears
and dword ptr [rbx], ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON)
# oflag: clear OPOST
and dword ptr [rbx + OFLAG_OFF], ~OPOST
# cflag: CS8, CLOCAL, CREAD, no parity
mov eax, [rbx + CFLAG_OFF]
and eax, ~(CSIZE | PARENB)
or eax, CS8 | CLOCAL | CREAD
mov [rbx + CFLAG_OFF], eax
# lflag: clear ECHO, ICANON, ISIG
and dword ptr [rbx + LFLAG_OFF], ~(ECHO|ICANON|ISIG)
# VMIN=0, VTIME=1
mov byte ptr [rbx + CC_OFF + VMIN], 0
mov byte ptr [rbx + CC_OFF + VTIME], 1
# baud 115200
mov dword ptr [rbx + ISPEED_OFF], B115200
mov dword ptr [rbx + OSPEED_OFF], B115200
mov rdi, [serial_fd]
mov rsi, TCSETS
lea rdx, [ser_termios]
mov rax, SYS_IOCTL
syscall
# Save stdin termios
xor rdi, rdi
mov rsi, TCGETS
lea rdx, [old_termios]
mov rax, SYS_IOCTL
syscall
# Copy old to raw and make raw
lea rsi, [old_termios]
lea rdi, [raw_termios]
mov rcx, TERMIOS_SIZE
rep movsb
lea rbx, [raw_termios]
and dword ptr [rbx], ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON)
and dword ptr [rbx + OFLAG_OFF], ~OPOST
mov eax, [rbx + CFLAG_OFF]
and eax, ~(CSIZE | PARENB)
or eax, CS8
mov [rbx + CFLAG_OFF], eax
and dword ptr [rbx + LFLAG_OFF], ~(ECHO|ICANON|ISIG)
mov byte ptr [rbx + CC_OFF + VMIN], 1
mov byte ptr [rbx + CC_OFF + VTIME], 0
# Set stdin raw
xor rdi, rdi
mov rsi, TCSETS
lea rdx, [raw_termios]
mov rax, SYS_IOCTL
syscall
# Print banner
mov rdi, 1
lea rsi, [banner]
mov rdx, BANNER_LEN
mov rax, SYS_WRITE
syscall
# Setup pollfds: [0]=stdin, [1]=serial
lea rbx, [pollfds]
mov dword ptr [rbx], 0 # fd = stdin
mov word ptr [rbx + 4], POLLIN # events
mov word ptr [rbx + 6], 0 # revents
mov eax, [serial_fd]
mov dword ptr [rbx + 8], eax # fd = serial
mov word ptr [rbx + 12], POLLIN
mov word ptr [rbx + 14], 0
poll_loop:
lea rdi, [pollfds]
mov rsi, 2
mov rdx, -1 # infinite timeout
mov rax, SYS_POLL
syscall
# Check stdin
lea rbx, [pollfds]
movzx eax, word ptr [rbx + 6] # revents
test eax, POLLIN
jz check_serial
# Read stdin
xor rdi, rdi
lea rsi, [buf]
mov rdx, 256
mov rax, SYS_READ
syscall
test rax, rax
jle done
# Scan for Ctrl-D (0x04)
mov rcx, rax
lea rsi, [buf]
scan:
cmp byte ptr [rsi], 4
je done
inc rsi
dec rcx
jnz scan
# Write to serial
mov rdi, [serial_fd]
lea rsi, [buf]
mov rdx, rax
mov rax, SYS_WRITE
syscall
check_serial:
lea rbx, [pollfds]
movzx eax, word ptr [rbx + 14] # revents
test eax, POLLIN
jz poll_loop
# Read serial
mov rdi, [serial_fd]
lea rsi, [buf]
mov rdx, 256
mov rax, SYS_READ
syscall
test rax, rax
jle poll_loop
# Write to stdout
mov rdx, rax
mov rdi, 1
lea rsi, [buf]
mov rax, SYS_WRITE
syscall
jmp poll_loop
done:
# Restore stdin termios
xor rdi, rdi
mov rsi, TCSETS
lea rdx, [old_termios]
mov rax, SYS_IOCTL
syscall
# Close serial
mov rdi, [serial_fd]
mov rax, SYS_CLOSE
syscall
xor rdi, rdi
mov rax, SYS_EXIT
syscall
exit_fail:
mov rdi, 1
mov rax, SYS_EXIT
syscall