//go:build linux && cgo // Copyright (c) 2026 Storm Dragon // Authors: Storm Dragon, Angus Kola // SPDX-License-Identifier: GPL-3.0-or-later package speech /* #include #include #include #include #include static int cth_serial_open(const char *device, int baud) { speed_t speed; switch (baud) { case 1200: speed = B1200; break; case 2400: speed = B2400; break; case 4800: speed = B4800; break; case 9600: speed = B9600; break; case 19200: speed = B19200; break; case 38400: speed = B38400; break; case 57600: speed = B57600; break; case 115200: speed = B115200; break; default: return -EINVAL; } int fd = open(device, O_RDWR | O_NOCTTY | O_NONBLOCK | O_CLOEXEC); if (fd < 0) return -errno; struct termios attrs; if (tcgetattr(fd, &attrs) < 0) { int error = errno; close(fd); return -error; } cfmakeraw(&attrs); attrs.c_cflag |= CLOCAL | CREAD; attrs.c_cc[VMIN] = attrs.c_cc[VTIME] = 0; if (cfsetispeed(&attrs, speed) < 0 || cfsetospeed(&attrs, speed) < 0 || tcsetattr(fd, TCSANOW, &attrs) < 0) { int error = errno; close(fd); return -error; } return fd; } static int cth_serial_flush(int fd) { return tcflush(fd, TCOFLUSH) < 0 ? errno : 0; } */ import "C" import ( "fmt" "syscall" "unsafe" ) func open_serial(device string, baud int) (int, error) { value := C.CString(device) defer C.free(unsafe.Pointer(value)) fd := int(C.cth_serial_open(value, C.int(baud))) if fd < 0 { return -1, fmt.Errorf("open hardware speech device: %w", syscall.Errno(-fd)) } return fd, nil } func flush_serial(fd int) error { if code := C.cth_serial_flush(C.int(fd)); code != 0 { return fmt.Errorf("flush hardware speech: %w", syscall.Errno(code)) } return nil }