Documentation
¶
Overview ¶
Package beast talks to a VITURE Beast headset in pure Go, with CGO_ENABLED=0.
⛔ IT IS NOT THE SAME PROTOCOL AS THE LUMA, and the two do not even share an envelope: a Beast frame begins 0x10 and a Luma frame begins FA 55. Habits do not carry across. What they do share is a house style -- ask before you write, and judge by what the device answers rather than by what the screen does.
⭐ THE HEADSET ANSWERS EVERY COMMAND WITH A STATUS, and that is worth more than watching the display: a screen that does not change cannot tell a refusal from a command that never arrived. Finding that out took nineteen failed writes.
The frames themselves live in go-macos/iokit/viture, which decoded them. This package is the transport and the ergonomics on top: open the right interface, listen before asking, and hand back what the headset said.
Index ¶
Constants ¶
const ( VendorID uint16 = 0x35ca UsagePage uint16 = 0xff00 )
The device this speaks to.
⭐ 35ca:1201 ON THE VENDOR USAGE PAGE is the control interface, and it is the only one of the three the glasses publish that carries the protocol: the others are called "VITURE Microphone" and are a Consumer-page audio set. The name misleads and the usage page does not -- a mistake this fleet has now made in both directions.
const Wait = 2 * time.Second
Wait is how long the headset is given to answer.
Generous for a device that answers in milliseconds, and short enough that a menu row does not appear to hang.
Variables ¶
var ErrNoAnswer = errors.New("beast: the headset did not answer")
ErrNoAnswer says the headset did not reply in time.
var ErrNoDevice = errors.New("beast: no VITURE Beast found")
ErrNoDevice says no Beast control interface is on the bus.
var ErrNoSetting = errors.New("beast: the headset has no such setting")
ErrNoSetting means the headset answered that it has no such message.
⚠ AND IT IS A STATE, NOT A FACT ABOUT THE PROTOCOL. Measured 2026-09-05: 0x22 and 0x30 both answered a read at 17:00 and both were gone by 18:46, with the same cable and no replug -- while every other id still answered. 0x22 came back the next morning. So report it; do not compile it in.
var ErrUnsupported = errors.New("beast: only macOS is wired up")
ErrUnsupported is returned off macOS.
Functions ¶
This section is empty.
Types ¶
type Glasses ¶
type Glasses struct {
// contains filtered or unexported fields
}
Glasses is one open headset.
func (*Glasses) Close ¶
Close releases it.
⛔ IT WAITS FOR THE LISTENER. Closing a HID device while a stream still holds it does not fail, it ends the PROCESS -- macOS kills the program with "os_unfair_lock is corrupt", no Go panic, no stack, nothing on the program's own output. go-macos/iokit refuses that now; this does it in the right order anyway.
func (*Glasses) Get ¶
Get reads one setting and returns its value.
⛔ A READ CHANGES NOTHING, which is what makes it the right first experiment on any device: it is safe to repeat, and its success is visible in a way a command's is not.
⭐ AND A READ ANSWERING 2 MEANS "NO SUCH MESSAGE", which makes the whole id space discoverable without ever writing. Measured: twenty messages exist between 0x00 and 0x7f and every other id answers 2.
func (*Glasses) Nudge ¶
Nudge moves a setting by one step, clamped, and says where it ended up.
⛔ IT READS FIRST. A key that means "brighter" has to know what it is brighter than, and the headset is the only thing that knows: somebody may have used the buttons on the arm since anything here last looked.
func (*Glasses) Set ¶
Set writes one setting and reports what the headset said about it.
⛔ THE VALUE GOES IN TWICE, LITTLE-ENDIAN. That one detail is what nineteen attempts had wrong: the headset's own REPLIES carry a value little-endian and then big-endian, and copying that shape into a command has it refused. A reply and a command are not the same frame.
type Status ¶
type Status uint16
Status is what the headset answers to a write.
⭐ IT ANSWERS EVERY ONE, and that is the whole reason this package judges by the reply rather than by the display. Nineteen writes were lost watching a screen: a screen that does not change cannot tell a refusal from a command that never arrived, and one read settled in a second what those nineteen had not.
const ( // StatusOK means the command was taken. StatusOK Status = 0 // StatusRefused means the headset understood and said no -- which is how // its own limits were mapped: brightness accepted 0 to 8 and refused 9, // with nothing to watch and nobody guessing. StatusRefused Status = 4 // StatusTooShort means the command carried fewer than two payload bytes. StatusTooShort Status = 6 )
What the headset says back.