minor issues

This commit is contained in:
Siyuan Miao 2025-09-18 12:16:51 +02:00
parent ade9a4961a
commit b5978016af
7 changed files with 41 additions and 39 deletions

View File

@ -37,7 +37,7 @@ func handleHidRPCMessage(message hidrpc.Message, session *Session) {
logger.Warn().Err(err).Msg("failed to get keyboard macro report") logger.Warn().Err(err).Msg("failed to get keyboard macro report")
return return
} }
_, rpcErr = rpcExecuteKeyboardMacro(keyboardMacroReport.Macro) _, rpcErr = rpcExecuteKeyboardMacro(keyboardMacroReport.Steps)
case hidrpc.TypeCancelKeyboardMacroReport: case hidrpc.TypeCancelKeyboardMacroReport:
rpcCancelKeyboardMacro() rpcCancelKeyboardMacro()
return return

View File

@ -91,17 +91,19 @@ func (m *Message) KeyboardReport() (KeyboardReport, error) {
} }
// Macro .. // Macro ..
type KeyboardMacro struct { type KeyboardMacroStep struct {
Modifier byte // 1 byte Modifier byte // 1 byte
Keys []byte // 6 bytes, to make things easier, the keys length is fixed to 6 Keys []byte // 6 bytes: hidKeyBufferSize
Delay uint16 // 2 bytes Delay uint16 // 2 bytes
} }
type KeyboardMacroReport struct { type KeyboardMacroReport struct {
IsPaste bool IsPaste bool
Length uint32 StepCount uint32
Macro []KeyboardMacro Steps []KeyboardMacroStep
} }
const hidKeyBufferSize = 6
// KeyboardMacroReport returns the keyboard macro report from the message. // KeyboardMacroReport returns the keyboard macro report from the message.
func (m *Message) KeyboardMacroReport() (KeyboardMacroReport, error) { func (m *Message) KeyboardMacroReport() (KeyboardMacroReport, error) {
if m.t != TypeKeyboardMacroReport { if m.t != TypeKeyboardMacroReport {
@ -109,29 +111,30 @@ func (m *Message) KeyboardMacroReport() (KeyboardMacroReport, error) {
} }
isPaste := m.d[0] == uint8(1) isPaste := m.d[0] == uint8(1)
length := binary.BigEndian.Uint32(m.d[1:5]) stepCount := binary.BigEndian.Uint32(m.d[1:5])
// check total length // check total length
expectedLength := int(length)*9 + 5 expectedLength := int(stepCount)*9 + 5
if len(m.d) != expectedLength { if len(m.d) != expectedLength {
return KeyboardMacroReport{}, fmt.Errorf("invalid length: %d, expected: %d", len(m.d), expectedLength) return KeyboardMacroReport{}, fmt.Errorf("invalid length: %d, expected: %d", len(m.d), expectedLength)
} }
macro := make([]KeyboardMacro, 0, int(length)) steps := make([]KeyboardMacroStep, 0, int(stepCount))
for i := 0; i < int(length); i++ { offset := 5
offset := 5 + i*9 for i := 0; i < int(stepCount); i++ {
steps = append(steps, KeyboardMacroStep{
macro = append(macro, KeyboardMacro{
Modifier: m.d[offset], Modifier: m.d[offset],
Keys: m.d[offset+1 : offset+7], Keys: m.d[offset+1 : offset+7],
Delay: binary.BigEndian.Uint16(m.d[offset+7 : offset+9]), Delay: binary.BigEndian.Uint16(m.d[offset+7 : offset+9]),
}) })
offset += 1 + hidKeyBufferSize + 2
} }
return KeyboardMacroReport{ return KeyboardMacroReport{
IsPaste: isPaste, IsPaste: isPaste,
Macro: macro, Steps: steps,
Length: length, StepCount: stepCount,
}, nil }, nil
} }

View File

@ -1076,7 +1076,7 @@ func setKeyboardMacroCancel(cancel context.CancelFunc) {
keyboardMacroCancel = cancel keyboardMacroCancel = cancel
} }
func rpcExecuteKeyboardMacro(macro []hidrpc.KeyboardMacro) (usbgadget.KeysDownState, error) { func rpcExecuteKeyboardMacro(macro []hidrpc.KeyboardMacroStep) (usbgadget.KeysDownState, error) {
cancelKeyboardMacro() cancelKeyboardMacro()
ctx, cancel := context.WithCancel(context.Background()) ctx, cancel := context.WithCancel(context.Background())
@ -1109,11 +1109,11 @@ func rpcCancelKeyboardMacro() {
var keyboardClearStateKeys = make([]byte, 6) var keyboardClearStateKeys = make([]byte, 6)
func isClearKeyStep(step hidrpc.KeyboardMacro) bool { func isClearKeyStep(step hidrpc.KeyboardMacroStep) bool {
return step.Modifier == 0 && bytes.Equal(step.Keys, keyboardClearStateKeys) return step.Modifier == 0 && bytes.Equal(step.Keys, keyboardClearStateKeys)
} }
func rpcDoExecuteKeyboardMacro(ctx context.Context, macro []hidrpc.KeyboardMacro) (usbgadget.KeysDownState, error) { func rpcDoExecuteKeyboardMacro(ctx context.Context, macro []hidrpc.KeyboardMacroStep) (usbgadget.KeysDownState, error) {
var last usbgadget.KeysDownState var last usbgadget.KeysDownState
var err error var err error

View File

@ -219,32 +219,32 @@ export interface KeyboardMacroStep extends KeysDownState {
export class KeyboardMacroReportMessage extends RpcMessage { export class KeyboardMacroReportMessage extends RpcMessage {
isPaste: boolean; isPaste: boolean;
length: number; stepCount: number;
steps: KeyboardMacroStep[]; steps: KeyboardMacroStep[];
KEYS_LENGTH = 6; KEYS_LENGTH = 6;
constructor(isPaste: boolean, length: number, steps: KeyboardMacroStep[]) { constructor(isPaste: boolean, stepCount: number, steps: KeyboardMacroStep[]) {
super(HID_RPC_MESSAGE_TYPES.KeyboardMacroReport); super(HID_RPC_MESSAGE_TYPES.KeyboardMacroReport);
this.isPaste = isPaste; this.isPaste = isPaste;
this.length = length; this.stepCount = stepCount;
this.steps = steps; this.steps = steps;
} }
marshal(): Uint8Array { marshal(): Uint8Array {
// validate if length is correct // validate if length is correct
if (this.length !== this.steps.length) { if (this.stepCount !== this.steps.length) {
throw new Error(`Length ${this.length} is not equal to the number of steps ${this.steps.length}`); throw new Error(`Length ${this.stepCount} is not equal to the number of steps ${this.steps.length}`);
} }
const data = new Uint8Array(this.length * 9 + 6); const data = new Uint8Array(this.stepCount * 9 + 6);
data.set(new Uint8Array([ data.set(new Uint8Array([
this.messageType, this.messageType,
this.isPaste ? 1 : 0, this.isPaste ? 1 : 0,
...fromUint32toUint8(this.length), ...fromUint32toUint8(this.stepCount),
]), 0); ]), 0);
for (let i = 0; i < this.length; i++) { for (let i = 0; i < this.stepCount; i++) {
const step = this.steps[i]; const step = this.steps[i];
if (!withinUint8Range(step.modifier)) { if (!withinUint8Range(step.modifier)) {
throw new Error(`Modifier ${step.modifier} is not within the uint8 range`); throw new Error(`Modifier ${step.modifier} is not within the uint8 range`);
@ -279,7 +279,7 @@ export class KeyboardMacroReportMessage extends RpcMessage {
} }
} }
export class KeyboardMacroStateReportMessage extends RpcMessage { export class KeyboardMacroStateMessage extends RpcMessage {
state: boolean; state: boolean;
isPaste: boolean; isPaste: boolean;
@ -297,12 +297,12 @@ export class KeyboardMacroStateReportMessage extends RpcMessage {
]); ]);
} }
public static unmarshal(data: Uint8Array): KeyboardMacroStateReportMessage | undefined { public static unmarshal(data: Uint8Array): KeyboardMacroStateMessage | undefined {
if (data.length < 1) { if (data.length < 1) {
throw new Error(`Invalid keyboard macro state report message length: ${data.length}`); throw new Error(`Invalid keyboard macro state report message length: ${data.length}`);
} }
return new KeyboardMacroStateReportMessage(data[0] === 1, data[1] === 1); return new KeyboardMacroStateMessage(data[0] === 1, data[1] === 1);
} }
} }
@ -417,7 +417,7 @@ export const messageRegistry = {
[HID_RPC_MESSAGE_TYPES.KeypressReport]: KeypressReportMessage, [HID_RPC_MESSAGE_TYPES.KeypressReport]: KeypressReportMessage,
[HID_RPC_MESSAGE_TYPES.KeyboardMacroReport]: KeyboardMacroReportMessage, [HID_RPC_MESSAGE_TYPES.KeyboardMacroReport]: KeyboardMacroReportMessage,
[HID_RPC_MESSAGE_TYPES.CancelKeyboardMacroReport]: CancelKeyboardMacroReportMessage, [HID_RPC_MESSAGE_TYPES.CancelKeyboardMacroReport]: CancelKeyboardMacroReportMessage,
[HID_RPC_MESSAGE_TYPES.KeyboardMacroStateReport]: KeyboardMacroStateReportMessage, [HID_RPC_MESSAGE_TYPES.KeyboardMacroStateReport]: KeyboardMacroStateMessage,
} }
export const unmarshalHidRpcMessage = (data: Uint8Array): RpcMessage | undefined => { export const unmarshalHidRpcMessage = (data: Uint8Array): RpcMessage | undefined => {

View File

@ -76,9 +76,8 @@ export function useHidRpc(onHidRpcMessage?: (payload: RpcMessage) => void) {
); );
const reportKeyboardMacroEvent = useCallback( const reportKeyboardMacroEvent = useCallback(
(macro: KeyboardMacroStep[]) => { (steps: KeyboardMacroStep[]) => {
const d = new KeyboardMacroReportMessage(false, macro.length, macro); sendMessage(new KeyboardMacroReportMessage(false, steps.length, steps));
sendMessage(d);
}, },
[sendMessage], [sendMessage],
); );

View File

@ -11,7 +11,7 @@ import { JsonRpcResponse, useJsonRpc } from "@/hooks/useJsonRpc";
import { useHidRpc } from "@/hooks/useHidRpc"; import { useHidRpc } from "@/hooks/useHidRpc";
import { import {
KeyboardLedStateMessage, KeyboardLedStateMessage,
KeyboardMacroStateReportMessage, KeyboardMacroStateMessage,
KeyboardMacroStep, KeyboardMacroStep,
KeysDownStateMessage, KeysDownStateMessage,
} from "@/hooks/hidRpc"; } from "@/hooks/hidRpc";
@ -70,9 +70,9 @@ export default function useKeyboard() {
case KeyboardLedStateMessage: case KeyboardLedStateMessage:
setKeyboardLedState((message as KeyboardLedStateMessage).keyboardLedState); setKeyboardLedState((message as KeyboardLedStateMessage).keyboardLedState);
break; break;
case KeyboardMacroStateReportMessage: case KeyboardMacroStateMessage:
if (!(message as KeyboardMacroStateReportMessage).isPaste) break; if (!(message as KeyboardMacroStateMessage).isPaste) break;
setPasteModeEnabled((message as KeyboardMacroStateReportMessage).state); setPasteModeEnabled((message as KeyboardMacroStateMessage).state);
break; break;
default: default:
break; break;

2
web.go
View File

@ -199,7 +199,7 @@ func handleWebRTCSession(c *gin.Context) {
}() }()
} }
// Cancel any ongoing keyboard report multi when session changes // Cancel any ongoing keyboard macro when session changes
cancelKeyboardMacro() cancelKeyboardMacro()
currentSession = session currentSession = session