Skip to content

Instantly share code, notes, and snippets.

@pgaskin
Last active July 7, 2024 15:01
Show Gist options
  • Save pgaskin/37553eba141c26029e68140ee5215e04 to your computer and use it in GitHub Desktop.
Save pgaskin/37553eba141c26029e68140ee5215e04 to your computer and use it in GitHub Desktop.
Controlling the Anker Soundcore P20i gaming mode (i.e., low latency mode) on Linux.
package main
import (
"encoding/hex"
"net"
"os"
"golang.org/x/sys/unix"
)
func main() {
var cmd string
if len(os.Args) > 1 {
cmd = os.Args[1]
}
switch cmd {
case "on", "1":
cmd = "08ee00000001870b00018a"
case "off", "0":
cmd = "08ee00000001870b000089"
default:
panic("invalid command")
}
cmdBuf, err := hex.DecodeString(cmd)
if err != nil {
panic(err)
}
var mac string
if len(os.Args) > 2 {
mac = os.Args[2]
}
if mac == "" {
mac = "F0:AE:66:B2:4E:95"
}
macAddr, err := net.ParseMAC(mac)
if err != nil {
panic(err)
}
if len(macAddr) != 6 {
panic("invalid mac address")
}
macBuf := [6]uint8{macAddr[5], macAddr[4], macAddr[3], macAddr[2], macAddr[1], macAddr[0]}
fd, err := unix.Socket(unix.AF_BLUETOOTH, unix.SOCK_STREAM, unix.BTPROTO_RFCOMM)
if err != nil {
panic(err)
}
// p20i rfcomm stuff is always on channel 10
if err := unix.Connect(fd, &unix.SockaddrRFCOMM{Addr: macBuf, Channel: 10}); err != nil {
panic(err)
}
f := os.NewFile(uintptr(fd), "bluetooth rfcomm "+macAddr.String())
defer f.Close()
if _, err := f.Write(cmdBuf); err != nil {
panic(err)
}
}
package main
import (
"encoding/hex"
"fmt"
"net"
"time"
"golang.org/x/sys/unix"
)
/*
- adb root
- enable bluetooth
- enable bluetooth hci snooping in dev options
- disable bluetooth
- enable bluetooth
- do stuff
- adb pull /data/misc/bluetooth/logs/btsnoop_hci.log
- disable bluetooth hci snooping in dev options
- disable bluetooth
- enable bluetooth
- disable bluetooth
- wireshark
*/
func main() {
mac, err := net.ParseMAC("F0:AE:66:B2:4E:95") // soundcore P20i
if err != nil {
panic(err)
}
addr := [6]uint8{mac[5], mac[4], mac[3], mac[2], mac[1], mac[0]}
fd, err := unix.Socket(unix.AF_BLUETOOTH, unix.SOCK_STREAM, unix.BTPROTO_RFCOMM)
if err != nil {
panic(err)
}
// p20i rfcomm stuff is always on channel 10
if err := unix.Connect(fd, &unix.SockaddrRFCOMM{Addr: addr, Channel: 10}); err != nil {
panic(err)
}
fmt.Println("get device info")
if buf, err := hex.DecodeString("08ee00000001010a0002"); err != nil {
panic(err)
} else if _, err := unix.Write(fd, buf); err != nil {
panic(err)
}
{
tmp := make([]byte, 98)
n, err := unix.Read(fd, tmp)
if err != nil {
panic(err)
}
fmt.Println(hex.Dump(tmp[:n]))
}
fmt.Println("gaming mode off")
if buf, err := hex.DecodeString("08ee00000001870b000089"); err != nil {
panic(err)
} else if _, err := unix.Write(fd, buf); err != nil {
panic(err)
}
time.Sleep(time.Second * 5)
fmt.Println("gaming mode on")
if buf, err := hex.DecodeString("08ee00000001870b00018a"); err != nil {
panic(err)
} else if _, err := unix.Write(fd, buf); err != nil {
panic(err)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment