blob: 8bca382112c97d19202c6e4a840456f87f6c032b [file] [log] [blame]
// Copyright 2018 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Package input supports injecting input events via kernel devices.
package input
import (
"context"
"encoding/binary"
"io"
"os"
"syscall"
"time"
"unsafe"
"chromiumos/tast/errors"
)
// RawEventWriter supports injecting raw input events into a device.
type RawEventWriter struct {
w io.WriteCloser // device
nowFunc func() time.Time
}
// Device returns a RawEventWriter for injecting input events into the input event device at path.
func Device(ctx context.Context, path string) (*RawEventWriter, error) {
f, err := os.OpenFile(path, os.O_WRONLY, 0600)
if err != nil {
return nil, err
}
return &RawEventWriter{f, time.Now}, nil
}
// Close closes the device.
func (ew *RawEventWriter) Close() error {
return ew.w.Close()
}
// Event injects an event containing the supplied values into the device.
func (ew *RawEventWriter) Event(et EventType, ec EventCode, val int32) error {
tv := syscall.NsecToTimeval(ew.nowFunc().UnixNano())
// input_event contains a timeval struct, which uses "long" for its members.
// binary.Write wants explicitly-sized data, so we need to pass a different
// struct depending on the system's int size.
var ev interface{}
switch intSize := unsafe.Sizeof(int(1)); intSize {
case 4:
ev = &event32{int32(tv.Sec), int32(tv.Usec), uint16(et), uint16(ec), val}
case 8:
ev = &event64{tv, uint16(et), uint16(ec), val}
default:
return errors.Errorf("unexpected int size of %d byte(s)", intSize)
}
return binary.Write(ew.w, kernelByteOrder, ev)
}
// event32 corresponds to a 32-bit input_event struct.
type event32 struct {
Sec, Usec int32
Type, Code uint16
Val int32
}
// event64 corresponds to a 64-bit input_event struct.
type event64 struct {
Tv syscall.Timeval
Type, Code uint16
Val int32
}
// Sync writes a synchronization event delineating a packet of input data occurring at a single point in time.
// It's shorthand for Event(t, EV_SYN, SYN_REPORT, 0).
func (ew *RawEventWriter) Sync() error {
return ew.Event(EV_SYN, SYN_REPORT, 0)
}