package main

import (
	"fmt"
	"os"
	"os/signal"
	"strconv"
	"strings"
	"syscall"
	"unsafe"
)

const (
	AF_BLUETOOTH   = 31
	BTPROTO_SCO    = 2
	SOCK_SEQPACKET = 5

	SOL_BLUETOOTH        = 274
	BT_VOICE             = 11
	BT_VOICE_CVSD_16BIT  = 0x0060
)

type sockaddrSCO struct {
	Family uint16
	Bdaddr [6]byte
}

type btVoice struct {
	Setting uint16
}

func parseBDAddr(s string) ([6]byte, error) {
	var addr [6]byte
	parts := strings.Split(s, ":")
	if len(parts) != 6 {
		return addr, fmt.Errorf("invalid BD address: %s", s)
	}
	for i := 0; i < 6; i++ {
		v, err := strconv.ParseUint(parts[5-i], 16, 8)
		if err != nil {
			return addr, err
		}
		addr[i] = byte(v)
	}
	return addr, nil
}

func main() {
	if len(os.Args) < 2 {
		fmt.Fprintf(os.Stderr, "Usage: %s <bt_addr>\n", os.Args[0])
		fmt.Fprintf(os.Stderr, "Example: %s F7:08:00:CB:1E:E1\n", os.Args[0])
		os.Exit(1)
	}

	bdaddr, err := parseBDAddr(os.Args[1])
	if err != nil {
		fmt.Fprintf(os.Stderr, "Parse address failed: %v\n", err)
		os.Exit(1)
	}

	// Create SCO socket
	fd, _, errno := syscall.Syscall(syscall.SYS_SOCKET,
		uintptr(AF_BLUETOOTH),
		uintptr(SOCK_SEQPACKET),
		uintptr(BTPROTO_SCO))
	if int(fd) < 0 {
		fmt.Fprintf(os.Stderr, "Socket failed: %v\n", errno)
		os.Exit(1)
	}
	defer syscall.Close(int(fd))

	// Set voice setting: CVSD, 16-bit linear
	const BT_VOICE_TRANSPARENT_16BIT = 0x0063
	voice := btVoice{Setting: BT_VOICE_TRANSPARENT_16BIT}
	// const BT_VOICE_CVSD_16BIT = 0x0060
// voice := btVoice{Setting: BT_VOICE_CVSD_16BIT}
	_, _, errno = syscall.Syscall6(syscall.SYS_SETSOCKOPT,
		fd,
		uintptr(SOL_BLUETOOTH),
		uintptr(BT_VOICE),
		uintptr(unsafe.Pointer(&voice)),
		uintptr(unsafe.Sizeof(voice)),
		0)
	if errno != 0 {
		fmt.Fprintf(os.Stderr, "Set voice setting failed: %v\n", errno)
		os.Exit(1)
	}
	fmt.Printf("Voice setting set to 0x%04X\n", voice.Setting)

	// Bind to local adapter
	var localAddr sockaddrSCO
	localAddr.Family = AF_BLUETOOTH

	for {
		_, _, errno = syscall.Syscall(syscall.SYS_BIND,
			fd,
			uintptr(unsafe.Pointer(&localAddr)),
			uintptr(unsafe.Sizeof(localAddr)))
		if errno != syscall.EINTR {
			break
		}
	}
	if errno != 0 {
		fmt.Fprintf(os.Stderr, "Bind failed: %v\n", errno)
		os.Exit(1)
	}

	// Connect to remote device
	var remoteAddr sockaddrSCO
	remoteAddr.Family = AF_BLUETOOTH
	remoteAddr.Bdaddr = bdaddr

	fmt.Printf("Connecting to %s ...\n", os.Args[1])

	for {
		_, _, errno = syscall.Syscall(syscall.SYS_CONNECT,
			fd,
			uintptr(unsafe.Pointer(&remoteAddr)),
			uintptr(unsafe.Sizeof(remoteAddr)))
		if errno != syscall.EINTR {
			break
		}
	}
	if errno != 0 {
		fmt.Fprintf(os.Stderr, "Connect failed: %v\n", errno)
		os.Exit(1)
	}

	fmt.Println("SCO connected, Ctrl+C to disconnect")

	sig := make(chan os.Signal, 1)
	signal.Notify(sig, syscall.SIGINT, syscall.SIGTERM)
	<-sig

	fmt.Println("Disconnected")
}