91 lines
3.0 KiB
Go
91 lines
3.0 KiB
Go
package gateway
|
|
|
|
import (
|
|
"encoding/binary"
|
|
"unicode/utf8"
|
|
)
|
|
|
|
const (
|
|
apolloChannelGeneric = 0
|
|
apolloChannelUrgent = 1
|
|
apolloChannelKeyboard = 2
|
|
apolloChannelMouse = 3
|
|
apolloChannelUTF8 = 6
|
|
apolloChannelGamepad = 16
|
|
)
|
|
|
|
type apolloInputPacket struct {
|
|
channel uint8
|
|
payload []byte
|
|
}
|
|
|
|
func encodeApolloInputEvent(event InputEvent) (apolloInputPacket, error) {
|
|
switch event.Device {
|
|
case "keyboard":
|
|
if event.Code < 0 || event.Code > 0xffff || len(event.Payload) > 1 {
|
|
return apolloInputPacket{}, ErrInputMalformed
|
|
}
|
|
packet := make([]byte, 14)
|
|
binary.BigEndian.PutUint32(packet[:4], 10)
|
|
if event.Pressed {
|
|
binary.LittleEndian.PutUint32(packet[4:8], 3)
|
|
} else {
|
|
binary.LittleEndian.PutUint32(packet[4:8], 4)
|
|
}
|
|
binary.LittleEndian.PutUint16(packet[9:11], uint16(event.Code))
|
|
if len(event.Payload) == 1 {
|
|
packet[11] = event.Payload[0]
|
|
}
|
|
return apolloInputPacket{channel: apolloChannelKeyboard, payload: packet}, nil
|
|
case "mouse-button":
|
|
if event.Code < 1 || event.Code > 8 || len(event.Payload) != 0 {
|
|
return apolloInputPacket{}, ErrInputMalformed
|
|
}
|
|
packet := make([]byte, 9)
|
|
binary.BigEndian.PutUint32(packet[:4], 5)
|
|
magic := uint32(8)
|
|
if !event.Pressed {
|
|
magic = 9
|
|
}
|
|
binary.LittleEndian.PutUint32(packet[4:8], magic)
|
|
packet[8] = byte(event.Code)
|
|
return apolloInputPacket{channel: apolloChannelMouse, payload: packet}, nil
|
|
case "mouse-relative":
|
|
if event.Pressed || len(event.Payload) != 4 {
|
|
return apolloInputPacket{}, ErrInputMalformed
|
|
}
|
|
packet := make([]byte, 12)
|
|
binary.BigEndian.PutUint32(packet[:4], 8)
|
|
binary.LittleEndian.PutUint32(packet[4:8], 7)
|
|
copy(packet[8:], event.Payload)
|
|
return apolloInputPacket{channel: apolloChannelMouse, payload: packet}, nil
|
|
case "utf8":
|
|
if event.Pressed || len(event.Payload) == 0 || len(event.Payload) > utf8.UTFMax || !utf8.Valid(event.Payload) || utf8.RuneCount(event.Payload) != 1 {
|
|
return apolloInputPacket{}, ErrInputMalformed
|
|
}
|
|
packet := make([]byte, 8+len(event.Payload))
|
|
binary.BigEndian.PutUint32(packet[:4], uint32(4+len(event.Payload)))
|
|
binary.LittleEndian.PutUint32(packet[4:8], 0x17)
|
|
copy(packet[8:], event.Payload)
|
|
return apolloInputPacket{channel: apolloChannelUTF8, payload: packet}, nil
|
|
case "controller":
|
|
if event.Code < 0 || event.Code > 15 || len(event.Payload) != 16 {
|
|
return apolloInputPacket{}, ErrInputMalformed
|
|
}
|
|
packet := make([]byte, 34)
|
|
binary.BigEndian.PutUint32(packet[:4], 30)
|
|
binary.LittleEndian.PutUint32(packet[4:8], 0x0c)
|
|
binary.LittleEndian.PutUint16(packet[8:10], 0x1a)
|
|
binary.LittleEndian.PutUint16(packet[10:12], uint16(event.Code))
|
|
copy(packet[12:14], event.Payload[:2])
|
|
binary.LittleEndian.PutUint16(packet[14:16], 0x14)
|
|
copy(packet[16:28], event.Payload[2:14])
|
|
binary.LittleEndian.PutUint16(packet[28:30], 0x9c)
|
|
copy(packet[30:32], event.Payload[14:16])
|
|
binary.LittleEndian.PutUint16(packet[32:34], 0x55)
|
|
return apolloInputPacket{channel: apolloChannelGamepad + uint8(event.Code), payload: packet}, nil
|
|
default:
|
|
return apolloInputPacket{}, ErrInputMalformed
|
|
}
|
|
}
|