From 554d32f7e8a953909ebb566140d5be5f8f5532ba Mon Sep 17 00:00:00 2001 From: Anders Holck Date: Sat, 11 Apr 2026 00:21:06 +0200 Subject: [PATCH] added tty --- tty/Makefile | 5 + tty/tty.S | 255 +++++++++++++++++++++++++++++++++++++++++++++++ tty_c/Makefile | 4 + tty_c/tty.c | 58 +++++++++++ vedit/worklog.md | 44 ++++++++ 5 files changed, 366 insertions(+) create mode 100644 tty/Makefile create mode 100644 tty/tty.S create mode 100644 tty_c/Makefile create mode 100644 tty_c/tty.c create mode 100644 vedit/worklog.md diff --git a/tty/Makefile b/tty/Makefile new file mode 100644 index 0000000..3fed1f3 --- /dev/null +++ b/tty/Makefile @@ -0,0 +1,5 @@ +tty: tty.S + as -o tty.o tty.S + ld -o tty tty.o +clean: + rm -f tty tty.o diff --git a/tty/tty.S b/tty/tty.S new file mode 100644 index 0000000..897f11b --- /dev/null +++ b/tty/tty.S @@ -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 diff --git a/tty_c/Makefile b/tty_c/Makefile new file mode 100644 index 0000000..ae799ba --- /dev/null +++ b/tty_c/Makefile @@ -0,0 +1,4 @@ +tty: tty.c + $(CC) -o $@ $< +clean: + rm -f tty diff --git a/tty_c/tty.c b/tty_c/tty.c new file mode 100644 index 0000000..4b8816c --- /dev/null +++ b/tty_c/tty.c @@ -0,0 +1,58 @@ +#include +#include +#include +#include +#include +#include +#include + +int main(void) { + int fd = open("/dev/ttyUSB0", O_RDWR | O_NOCTTY); + if (fd < 0) { perror("open"); return 1; } + + // Configure serial port + struct termios tty; + tcgetattr(fd, &tty); + cfmakeraw(&tty); + cfsetspeed(&tty, B115200); + tty.c_cflag |= CLOCAL | CREAD; + tty.c_cc[VMIN] = 0; + tty.c_cc[VTIME] = 1; + tcsetattr(fd, TCSANOW, &tty); + + // Set stdin to raw mode + struct termios old_stdin, raw_stdin; + tcgetattr(STDIN_FILENO, &old_stdin); + raw_stdin = old_stdin; + cfmakeraw(&raw_stdin); + tcsetattr(STDIN_FILENO, TCSANOW, &raw_stdin); + + write(STDOUT_FILENO, "Holcks minitty - ctrl-d to exit\r\n", 33); + + struct pollfd fds[2] = { + { .fd = STDIN_FILENO, .events = POLLIN }, + { .fd = fd, .events = POLLIN }, + }; + + char buf[256]; + while (1) { + poll(fds, 2, -1); + if (fds[0].revents & POLLIN) { + int n = read(STDIN_FILENO, buf, sizeof(buf)); + if (n > 0) { + for (int i = 0; i < n; i++) + if (buf[i] == 4) goto done; // Ctrl-D + write(fd, buf, n); + } + } + if (fds[1].revents & POLLIN) { + int n = read(fd, buf, sizeof(buf)); + if (n > 0) write(STDOUT_FILENO, buf, n); + } + } + +done: + tcsetattr(STDIN_FILENO, TCSANOW, &old_stdin); + close(fd); + return 0; +} diff --git a/vedit/worklog.md b/vedit/worklog.md new file mode 100644 index 0000000..10d2aea --- /dev/null +++ b/vedit/worklog.md @@ -0,0 +1,44 @@ + +## 2026-04-10 20:39:49 +User [chat]: Hello! +AI: Hello, Anders! How are you doing today? Is there anything specific you'd like to talk about or any questions I can help you with? + +## 2026-04-10 20:40:00 +User [chat]: What are you doing? +AI: I'm currently processing your messages and waiting to see how I can help you, Anders! Since I'm an AI, I don't have a physical life, so I spend my time analyzing text, answering questions, and chattin + +## 2026-04-10 20:41:29 +User [chat]: How can I control fans in Linux? +AI: Controlling fans in Linux, Anders, is a bit of a delicate process because it requires interacting directly with your motherboard's hardware controllers. The most standard approach involves using a com + +## 2026-04-10 21:45:34 +User [chat]: How can I control fans in Linux? +AI: Since you are asking again, Anders, perhaps you are looking for a more structured way to approach this, or maybe you are looking for alternatives to the command-line method I mentioned previously. Let + +## 2026-04-10 23:24:11 +User: Are you here? +AI: Yes, I am here. + +## 2026-04-10 23:24:17 +User [chat]: Hello +AI: Hello there. How are you doing today, Anders? + +## 2026-04-10 23:24:25 +User [chat]: Not much +AI: I'm sorry to hear that. Is everything okay? Or are you just having a quiet day? + +## 2026-04-10 23:26:19 +User [chat]: All is ok! +AI: That's good to hear! Sometimes just having an okay day is exactly what you need. Is there anything on your mind, or anything you'd like to talk about? + +## 2026-04-10 23:26:35 +User [chat]: Not really, I am just checking if you are running properly. +AI: I am running perfectly, thank you for checking in on me, Anders. I am here and ready to chat whenever you are. Is there anything specific you wanted to test or discuss? + +## 2026-04-10 23:27:32 +User [chat]: Hello +AI: Hello again, Anders! Still testing things out, or just saying hi one more time? + +## 2026-04-10 23:28:19 +User [chat]: Hej +AI: Hej! How are things going on your end right now?