cgo-samples-2024

Форк
0
113 строк · 2.7 Кб
1
package evdev
2

3
/*
4
#include <linux/input.h>
5
static int _EVIOCGNAME(int len) {return EVIOCGNAME(len);}
6
*/
7
import "C"
8

9
import (
10
	"bytes"
11
	"encoding/binary"
12
	"errors"
13
	"os"
14
	"path/filepath"
15
	"syscall"
16
	"unsafe"
17
)
18

19
const (
20
	DeviceFilesGlob = "/dev/input/event*"
21
	MAX_NAME_SIZE   = 256
22
	// брал обозначения из github.com/gvalkov/golang-evdev в ecodes.go, events.go, остальные значение нам не нужны, но можно взять при необходимости оттуда
23
	EV_KEY = 0x01 // событие о кнопке
24

25
	KEY_UP   = 0x0 // кнопка была отжата
26
	KEY_DOWN = 0x1 // кнопка была нажата
27
	KEY_HOLD = 0x2 // кнопка зажата (повторяется)
28
)
29

30
var EVIOCGNAME = C._EVIOCGNAME(MAX_NAME_SIZE) // get device name
31

32
type InputEvent struct {
33
	Time  syscall.Timeval // время события
34
	Type  uint16          // тип события, используется только события о кнопках EV_KEY
35
	Code  uint16          // код из события, для кнопок передается код клавиши
36
	Value int32           // что именно произошло, для кнопок - нажата, отжата или зажата ли была кнопка
37
}
38

39
var eventsize = int(unsafe.Sizeof(InputEvent{}))
40

41
func IsInputDevice(path string) bool {
42
	fi, err := os.Stat(path)
43

44
	if os.IsNotExist(err) {
45
		return false
46
	}
47

48
	m := fi.Mode()
49

50
	return m&os.ModeCharDevice != 0
51
}
52

53
func ListInputDevices(devGlob string) ([]string, error) {
54
	filenames := make([]string, 0)
55

56
	paths, err := filepath.Glob(devGlob)
57
	if err != nil {
58
		return filenames, err
59
	}
60
	for i := range paths {
61
		if IsInputDevice(paths[i]) {
62
			filenames = append(filenames, paths[i])
63
		}
64
	}
65

66
	return filenames, nil
67
}
68

69
func GetInputDevice(nameDevice string) (*os.File, error) {
70
	inputFiles, err := ListInputDevices(DeviceFilesGlob)
71
	if err != nil {
72
		return nil, err
73
	}
74

75
	for i := range inputFiles {
76
		f, err := os.Open(inputFiles[i])
77
		if err != nil {
78
			continue
79
		}
80
		name := new([MAX_NAME_SIZE]byte)
81
		syscall.RawSyscall(syscall.SYS_IOCTL, f.Fd(), uintptr(EVIOCGNAME), uintptr(unsafe.Pointer(name)))
82
		if bytes_to_string(name) == nameDevice {
83
			return f, nil
84
		}
85

86
	}
87

88
	return nil, errors.New("not found")
89
}
90

91
func ReadOne(f *os.File) (*InputEvent, error) {
92
	if f == nil {
93
		return nil, errors.New("null file device")
94
	}
95
	event := InputEvent{}
96
	buffer := make([]byte, eventsize)
97
	_, err := f.Read(buffer)
98
	if err != nil {
99
		return &event, err
100
	}
101
	b := bytes.NewBuffer(buffer)
102
	err = binary.Read(b, binary.LittleEndian, &event)
103
	if err != nil {
104
		return &event, err
105
	}
106

107
	return &event, err
108
}
109

110
func bytes_to_string(b *[MAX_NAME_SIZE]byte) string {
111
	idx := bytes.IndexByte(b[:], 0)
112
	return string(b[:idx])
113
}
114

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.