Skip to content

Instantly share code, notes, and snippets.

@Code-Hex
Created June 2, 2024 07:18
Show Gist options
  • Save Code-Hex/f1741c0f2b19c43a28c3173721fcc638 to your computer and use it in GitHub Desktop.
Save Code-Hex/f1741c0f2b19c43a28c3173721fcc638 to your computer and use it in GitHub Desktop.
Get keyball config
package main
import (
"bytes"
"encoding/binary"
"fmt"
"io"
"log"
"sort"
"time"
"github.com/karalabe/hid"
"github.com/ulikunitz/xz"
)
const (
CMD_VIA_VIAL_PREFIX = 0xFE
CMD_VIAL_GET_KEYBOARD_ID = 0x00
CMD_VIAL_GET_SIZE = 0x01
CMD_VIAL_GET_DEFINITION = 0x02
MSG_LEN = 32 // 適切なMSG_LENを設定してください
)
type Device struct {
dev *hid.Device
vial_protocol uint32
keyboard_id uint64
}
func (d *Device) hidSend(dev *hid.Device, msg []byte, retries int) ([]byte, error) {
if len(msg) > MSG_LEN {
return nil, fmt.Errorf("message must be less than 32 bytes")
}
msg = append(msg, make([]byte, MSG_LEN-len(msg))...)
data := make([]byte, MSG_LEN)
first := true
for retries > 0 {
retries--
if !first {
time.Sleep(500 * time.Millisecond)
}
first = false
if _, err := dev.Write(append([]byte{0x00}, msg...)); err != nil {
continue
}
n, err := dev.Read(data)
if err != nil || n == 0 {
continue
}
break
}
if len(data) == 0 {
return nil, fmt.Errorf("failed to communicate with the device")
}
return data, nil
}
func (d *Device) reloadLayout() ([]byte, error) {
// get keyboard identification
data, err := d.hidSend(d.dev, []byte{CMD_VIA_VIAL_PREFIX, CMD_VIAL_GET_KEYBOARD_ID}, 20)
if err != nil {
return nil, err
}
log.Println("get keyboard identification", data)
buf := bytes.NewReader(data[:12])
if err := binary.Read(buf, binary.LittleEndian, &d.vial_protocol); err != nil {
return nil, err
}
if err := binary.Read(buf, binary.LittleEndian, &d.keyboard_id); err != nil {
return nil, err
}
// get the size
data, err = d.hidSend(d.dev, []byte{CMD_VIA_VIAL_PREFIX, CMD_VIAL_GET_SIZE}, 20)
if err != nil {
return nil, err
}
var sz int32
log.Println("get the size", data)
buf = bytes.NewReader(data[:4])
if err := binary.Read(buf, binary.LittleEndian, &sz); err != nil {
return nil, err
}
log.Println("size:", sz)
// get the payload
var lzmaPayload []byte
var block uint32
for sz > 0 {
data, err = d.hidSend(d.dev, append([]byte{CMD_VIA_VIAL_PREFIX, CMD_VIAL_GET_DEFINITION}, byte(block)), 20)
if err != nil {
return nil, err
}
log.Println("current:", sz)
if sz < MSG_LEN {
data = data[:sz]
}
lzmaPayload = append(lzmaPayload, data...)
block++
sz -= MSG_LEN
}
log.Println("received payload")
// lzma解凍
dec, err := xz.NewReader(bytes.NewReader(lzmaPayload))
if err != nil {
return nil, err
}
decoded, err := io.ReadAll(dec)
if err != nil {
return nil, fmt.Errorf("failed to decode: %w", err)
}
return decoded, nil
}
func main() {
var (
vendorID uint16 = 0x5957
productID uint16 = 0x0100
)
devices := hid.Enumerate(vendorID, productID) // 適切なベンダーIDとプロダクトIDを設定してください
if len(devices) == 0 {
log.Fatal("No HID devices found")
}
sort.Slice(devices, func(i, j int) bool {
return devices[i].UsagePage > devices[j].UsagePage
})
deviceInfo := devices[0]
dev, err := deviceInfo.Open()
if err != nil {
log.Fatalf("Failed to open device: %v", err)
}
defer dev.Close()
device := &Device{
dev: dev,
}
payload, err := device.reloadLayout()
if err != nil {
log.Fatalf("Error: %v", err)
}
fmt.Println(string(payload))
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment