66 lines
1.8 KiB
Go
66 lines
1.8 KiB
Go
//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 <errno.h>
|
|
#include <fcntl.h>
|
|
#include <termios.h>
|
|
#include <unistd.h>
|
|
#include <stdlib.h>
|
|
|
|
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
|
|
}
|