Removed dependency on uinput, we're using `xdotool` right now.

pull/5/head
Alexandre Bourget 2017-08-14 20:02:59 -04:00
rodzic 4adc1c931d
commit 059cdb49ec
10 zmienionych plików z 10 dodań i 1088 usunięć

4
build.sh 100755
Wyświetl plik

@ -0,0 +1,4 @@
#!/bin/bash -xe
#CGO_ENABLED=0
GOOS=linux GOARCH=amd64 go build -v -o shuttle-go

10
main.go
Wyświetl plik

@ -3,11 +3,9 @@ package main
import (
"flag"
"fmt"
"log"
"os"
"path/filepath"
"github.com/bendahl/uinput"
"github.com/gvalkov/golang-evdev"
)
@ -49,12 +47,6 @@ func main() {
go watcher.Run()
// Virtual keyboard
vk, err := uinput.CreateKeyboard("/dev/uinput", []byte("Go Virtual Shuttle Pro V2"))
if err != nil {
log.Println("Can't open dev:", err)
}
// Shuttle device event receiver
dev, err := evdev.Open(devicePath)
if err != nil {
@ -63,7 +55,7 @@ func main() {
}
fmt.Println("ready")
mapper := NewMapper(vk, dev)
mapper := NewMapper(dev)
mapper.watcher = watcher
for {
if err := mapper.Process(); err != nil {

Wyświetl plik

@ -7,17 +7,15 @@ import (
"strings"
"time"
"github.com/bendahl/uinput"
evdev "github.com/gvalkov/golang-evdev"
)
// Mapper receives events from the Shuttle devices, and maps (through
// configuration) to the Virtual Keyboard events.
type Mapper struct {
virtualKeyboard uinput.Keyboard
inputDevice *evdev.InputDevice
state buttonsState
watcher *watcher
inputDevice *evdev.InputDevice
state buttonsState
watcher *watcher
}
type buttonsState struct {
@ -27,10 +25,9 @@ type buttonsState struct {
lastJog time.Time
}
func NewMapper(virtualKeyboard uinput.Keyboard, inputDevice *evdev.InputDevice) *Mapper {
func NewMapper(inputDevice *evdev.InputDevice) *Mapper {
m := &Mapper{
virtualKeyboard: virtualKeyboard,
inputDevice: inputDevice,
inputDevice: inputDevice,
}
m.state.buttonsHeld = make(map[int]bool)
m.state.jog = -1

21
vendor/github.com/bendahl/uinput/LICENSE wygenerowano vendored
Wyświetl plik

@ -1,21 +0,0 @@
The MIT License (MIT)
Copyright (c) 2014 Benjamin Dahlmanns
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

Wyświetl plik

@ -1,41 +0,0 @@
Uinput [![Build Status](https://travis-ci.org/bendahl/uinput.svg?branch=master)](https://travis-ci.org/bendahl/uinput) [![GoDoc](https://godoc.org/github.com/bendahl/uinput?status.png)](https://godoc.org/github.com/bendahl/uinput) [![Go Report Card](https://goreportcard.com/badge/github.com/bendahl/uinput)](https://goreportcard.com/report/github.com/bendahl/uinput)
====
This package provides pure go wrapper functions for the LINUX uinput device, which allows to create virtual input devices
in userspace. At the moment this package offers a virtual keyboard implementation as well as a virtual mouse device and
a touch pad device.
The keyboard can be used to either send single key presses or hold down a specified key and release it later
(useful for building game controllers). The mouse device issues relative positional change events to the x and y axis
of the mouse pointer and may also fire click events (left and right click). More functionality will be added in future
version.
The touch pad, on the other hand can be used to move the mouse cursor to the specified position on the screen and to
issue left and right clicks. Note that you'll need to specify the region size of your screen first though (happens during
device creation).
Please note that you will need to make sure to have the necessary rights to write to uinput. You can either chmod your
uinput device, or add a rule in /etc/udev/rules.d to allow your user's group or a dedicated group to write to the device.
You may use the following two commands to add the necessary rights for you current user to a file called 99-$USER.rules
(where $USER is your current user's name):
<pre><code>
echo KERNEL==\"uinput\", GROUP=\"$USER\", MODE:=\"0660\" | sudo tee /etc/udev/rules.d/99-$USER.rules
sudo udevadm trigger
</code></pre>
Installation
-------------
Simply check out the repository and use the commands <pre><code>go build && go install</code></pre>
The package will then be installed to your local respository, along with the package documentation.
The documentation contains more details on the usage of this package.
License
--------
The package falls under the MIT license. Please see the "LICENSE" file for details.
ToDos
------------------
All testing has been done on Ubunu 14.04 and 16.04 x86\_64.
Testing for other platforms will need to be done.
To get an idea of the things that are on the current todo list, check out the file "TODO.md".
As always, helpful comments and ideas are always welcome.
Feel free to do some testing on your own if you're up to it.

10
vendor/github.com/bendahl/uinput/TODO.md wygenerowano vendored
Wyświetl plik

@ -1,10 +0,0 @@
TODO
====
1. ~~Create Tests for the uinput package~~
2. ~~Migrate code from C to GO~~
3. ~~Implement relative input~~
4. ~~Implement absolute input~~
5. Test on different platforms (besides x86_64)
6. Implement functions to allow mouse button up and down events (for region selects)
7. Extend test cases

375
vendor/github.com/bendahl/uinput/uinput.go wygenerowano vendored
Wyświetl plik

@ -1,375 +0,0 @@
/*
Package uinput is a pure go package that provides access to the userland input device driver uinput on linux systems.
Virtual keyboard devices as well as virtual mouse input devices may be created using this package.
The keycodes and other event definitions, that are available and can be used to trigger input events,
are part of this package ("Key1" for number 1, for example).
In order to use the virtual keyboard, you will need to follow these three steps:
1. Initialize the device
Example: vk, err := CreateKeyboard("/dev/uinput", "Virtual Keyboard")
2. Send Button events to the device
Example (print a single D):
err = vk.KeyPress(uinput.KeyD)
Example (keep moving right by holding down right arrow key):
err = vk.KeyDown(uinput.KeyRight)
Example (stop moving right by releasing the right arrow key):
err = vk.KeyUp(uinput.KeyRight)
3. Close the device
Example: err = vk.Close()
A virtual mouse input device is just as easy to create and use:
1. Initialize the device:
Example: vm, err := CreateMouse("/dev/uinput", "DangerMouse")
2. Move the cursor around and issue click events
Example (move mouse right):
err = vm.MoveRight(42)
Example (move mouse left):
err = vm.MoveLeft(42)
Example (move mouse up):
err = vm.MoveUp(42)
Example (move mouse down):
err = vm.MoveDown(42)
Example (trigger a left click):
err = vm.LeftClick()
Example (trigger a right click):
err = vm.RightClick()
3. Close the device
Example: err = vm.Close()
If you'd like to use absolute input events (move the cursor to specific positions on screen), use the touch pad.
Note that you'll need to specify the size of the screen area you want to use when you initialize the
device. Here are a few examples of how to use the virtual touch pad:
1. Initialize the device:
Example: vt, err := CreateTouchPad("/dev/uinput", "DontTouchThis", 0, 1024, 0, 768)
2. Move the cursor around and issue click events
Example (move cursor to the top left corner of the screen):
err = vt.MoveTo(0, 0)
Example (move cursor to the position x: 100, y: 250):
err = vt.MoveTo(100, 250)
Example (trigger a left click):
err = vt.LeftClick()
Example (trigger a right click):
err = vt.RightClick()
3. Close the device
Example: err = vt.Close()
*/
package uinput
import (
"errors"
"fmt"
"io"
"os"
)
// A Keyboard is an key event output device. It is used to
// enable a program to simulate HID keyboard input events.
type Keyboard interface {
// KeyPress will cause the key to be pressed and immediately released.
KeyPress(key int) error
// KeyDown will send a keypress event to an existing keyboard device.
// The key can be any of the predefined keycodes from uinputdefs.
// Note that the key will be "held down" until "KeyUp" is called.
KeyDown(key int) error
// KeyUp will send a keyrelease event to an existing keyboard device.
// The key can be any of the predefined keycodes from uinputdefs.
KeyUp(key int) error
io.Closer
}
type vKeyboard struct {
name []byte
deviceFile *os.File
}
// A Mouse is a device that will trigger an absolute change event.
// For details see: https://www.kernel.org/doc/Documentation/input/event-codes.txt
type Mouse interface {
// MoveLeft will move the mouse cursor left by the given number of pixel.
MoveLeft(pixel int32) error
// MoveRight will move the mouse cursor right by the given number of pixel.
MoveRight(pixel int32) error
// MoveUp will move the mouse cursor up by the given number of pixel.
MoveUp(pixel int32) error
// MoveDown will move the mouse cursor down by the given number of pixel.
MoveDown(pixel int32) error
// LeftClick will issue a single left click.
LeftClick() error
// RightClick will issue a right click.
RightClick() error
io.Closer
}
type vMouse struct {
name []byte
deviceFile *os.File
}
// A TouchPad is an input device that uses absolute axis events, meaning that you can specify
// the exact position the cursor should move to. Therefore, it is necessary to define the size
// of the rectangle in which the cursor may move upon creation of the device.
type TouchPad interface {
// MoveTo will move the cursor to the specified position on the screen
MoveTo(x int32, y int32) error
// LeftClick will issue a single left click.
LeftClick() error
// RightClick will issue a right click.
RightClick() error
io.Closer
}
type vTouchPad struct {
name []byte
deviceFile *os.File
}
// CreateTouchPad will create a new touch pad device. note that you will need to define the x and y axis boundaries
// (min and max) within which the cursor maybe moved around.
func CreateTouchPad(path string, name []byte, minX int32, maxX int32, minY int32, maxY int32) (TouchPad, error) {
if path == "" {
return nil, errors.New("device path must not be empty")
}
if len(name) > uinputMaxNameSize {
return nil, fmt.Errorf("device name %s is too long (maximum of %d characters allowed)", name, uinputMaxNameSize)
}
fd, err := createTouchPad(path, name, minX, maxX, minY, maxY)
if err != nil {
return nil, err
}
return vTouchPad{name: name, deviceFile: fd}, nil
}
func (vTouch vTouchPad) MoveTo(x int32, y int32) error {
return sendAbsEvent(vTouch.deviceFile, x, y)
}
func (vTouch vTouchPad) LeftClick() error {
err := sendBtnEvent(vTouch.deviceFile, evBtnLeft, btnStatePressed)
if err != nil {
return fmt.Errorf("Failed to issue the LeftClick event: %v", err)
}
err = sendBtnEvent(vTouch.deviceFile, evBtnLeft, btnStateReleased)
if err != nil {
return fmt.Errorf("Failed to issue the KeyUp event: %v", err)
}
err = syncEvents(vTouch.deviceFile)
if err != nil {
return fmt.Errorf("sync to device file failed: %v", err)
}
return nil
}
func (vTouch vTouchPad) RightClick() error {
err := sendBtnEvent(vTouch.deviceFile, evBtnRight, btnStatePressed)
if err != nil {
return fmt.Errorf("Failed to issue the RightClick event: %v", err)
}
err = sendBtnEvent(vTouch.deviceFile, evBtnRight, btnStateReleased)
if err != nil {
return fmt.Errorf("Failed to issue the KeyUp event: %v", err)
}
err = syncEvents(vTouch.deviceFile)
if err != nil {
return fmt.Errorf("sync to device file failed: %v", err)
}
return nil
}
func (vTouch vTouchPad) Close() error {
return closeDevice(vTouch.deviceFile)
}
// CreateMouse will create a new mouse input device. A mouse is a device that allows relative input.
// Relative input means that all changes to the x and y coordinates of the mouse pointer will be
func CreateMouse(path string, name []byte) (Mouse, error) {
if path == "" {
return nil, errors.New("device path must not be empty")
}
if len(name) > uinputMaxNameSize {
return nil, fmt.Errorf("device name %s is too long (maximum of %d characters allowed)", name, uinputMaxNameSize)
}
fd, err := createMouse(path, name)
if err != nil {
return nil, err
}
return vMouse{name: name, deviceFile: fd}, nil
}
// MoveLeft will move the cursor left by the number of pixel specified.
func (vRel vMouse) MoveLeft(pixel int32) error {
return sendRelEvent(vRel.deviceFile, relX, -pixel)
}
// MoveRight will move the cursor right by the number of pixel specified.
func (vRel vMouse) MoveRight(pixel int32) error {
return sendRelEvent(vRel.deviceFile, relX, pixel)
}
// MoveUp will move the cursor up by the number of pixel specified.
func (vRel vMouse) MoveUp(pixel int32) error {
return sendRelEvent(vRel.deviceFile, relY, -pixel)
}
// MoveDown will move the cursor down by the number of pixel specified.
func (vRel vMouse) MoveDown(pixel int32) error {
return sendRelEvent(vRel.deviceFile, relY, pixel)
}
// LeftClick will issue a LeftClick.
func (vRel vMouse) LeftClick() error {
err := sendBtnEvent(vRel.deviceFile, evBtnLeft, btnStatePressed)
if err != nil {
return fmt.Errorf("Failed to issue the LeftClick event: %v", err)
}
err = sendBtnEvent(vRel.deviceFile, evBtnLeft, btnStateReleased)
if err != nil {
return fmt.Errorf("Failed to issue the KeyUp event: %v", err)
}
err = syncEvents(vRel.deviceFile)
if err != nil {
return fmt.Errorf("sync to device file failed: %v", err)
}
return nil
}
// RightClick will issue a RightClick
func (vRel vMouse) RightClick() error {
err := sendBtnEvent(vRel.deviceFile, evBtnRight, btnStatePressed)
if err != nil {
return fmt.Errorf("Failed to issue the RightClick event: %v", err)
}
err = sendBtnEvent(vRel.deviceFile, evBtnRight, btnStateReleased)
if err != nil {
return fmt.Errorf("Failed to issue the KeyUp event: %v", err)
}
err = syncEvents(vRel.deviceFile)
if err != nil {
return fmt.Errorf("sync to device file failed: %v", err)
}
return nil
}
// Close closes the device and releases the device.
func (vRel vMouse) Close() error {
return closeDevice(vRel.deviceFile)
}
// CreateKeyboard will create a new keyboard using the given uinput
// device path of the uinput device.
func CreateKeyboard(path string, name []byte) (Keyboard, error) {
if path == "" {
return nil, errors.New("device path must not be empty")
}
if len(name) > uinputMaxNameSize {
return nil, fmt.Errorf("device name %s is too long (maximum of %d characters allowed)", name, uinputMaxNameSize)
}
fd, err := createVKeyboardDevice(path, name)
if err != nil {
return nil, err
}
return vKeyboard{name: name, deviceFile: fd}, nil
}
// KeyPress will issue a single key press (push down a key and then immediately release it).
func (vk vKeyboard) KeyPress(key int) error {
err := sendBtnEvent(vk.deviceFile, key, btnStatePressed)
if err != nil {
return fmt.Errorf("Failed to issue the KeyDown event: %v", err)
}
err = sendBtnEvent(vk.deviceFile, key, btnStateReleased)
if err != nil {
return fmt.Errorf("Failed to issue the KeyUp event: %v", err)
}
err = syncEvents(vk.deviceFile)
if err != nil {
return fmt.Errorf("sync to device file failed: %v", err)
}
return nil
}
// KeyDown will send the key code passed (see uinputdefs.go for available keycodes). Note that unless a key release
// event is sent to the device, the key will remain pressed and therefore input will continuously be generated. Therefore,
// do not forget to call "KeyUp" afterwards.
func (vk vKeyboard) KeyDown(key int) error {
err := sendBtnEvent(vk.deviceFile, key, btnStatePressed)
if err != nil {
return fmt.Errorf("Failed to issue the KeyDown event: %v", err)
}
err = syncEvents(vk.deviceFile)
if err != nil {
return fmt.Errorf("sync to device file failed: %v", err)
}
return nil
}
// KeyUp will release the given key passed as a parameter (see uinputdefs.go for available keycodes). In most
// cases it is recommended to call this function immediately after the "KeyDown" function in order to only issue a
// single key press.
func (vk vKeyboard) KeyUp(key int) error {
err := sendBtnEvent(vk.deviceFile, key, btnStatePressed)
if err != nil {
return fmt.Errorf("Failed to issue the KeyUp event: %v", err)
}
err = syncEvents(vk.deviceFile)
if err != nil {
return fmt.Errorf("sync to device file failed: %v", err)
}
return nil
}
// Close will close the device and free resources.
// It's usually a good idea to use defer to call this function.
func (vk vKeyboard) Close() error {
return closeDevice(vk.deviceFile)
}

Wyświetl plik

@ -1,249 +0,0 @@
package uinput
// the constants were copied from input.h for convenience reasons
const (
keyReserved = 0
KeyEsc = 1
Key1 = 2
Key2 = 3
Key3 = 4
Key4 = 5
Key5 = 6
Key6 = 7
Key7 = 8
Key8 = 9
Key9 = 10
Key0 = 11
KeyMinus = 12
KeyEqual = 13
KeyBackspace = 14
KeyTab = 15
KeyQ = 16
KeyW = 17
KeyE = 18
KeyR = 19
KeyT = 20
KeyY = 21
KeyU = 22
KeyI = 23
KeyO = 24
KeyP = 25
KeyLeftbrace = 26
KeyRightbrace = 27
KeyEnter = 28
KeyLeftctrl = 29
KeyA = 30
KeyS = 31
KeyD = 32
KeyF = 33
KeyG = 34
KeyH = 35
KeyJ = 36
KeyK = 37
KeyL = 38
KeySemicolon = 39
KeyApostrophe = 40
KeyGrave = 41
KeyLeftshift = 42
KeyBackslash = 43
KeyZ = 44
KeyX = 45
KeyC = 46
KeyV = 47
KeyB = 48
KeyN = 49
KeyM = 50
KeyComma = 51
KeyDot = 52
KeySlash = 53
KeyRightshift = 54
KeyKpasterisk = 55
KeyLeftalt = 56
KeySpace = 57
KeyCapslock = 58
KeyF1 = 59
KeyF2 = 60
KeyF3 = 61
KeyF4 = 62
KeyF5 = 63
KeyF6 = 64
KeyF7 = 65
KeyF8 = 66
KeyF9 = 67
KeyF10 = 68
KeyNumlock = 69
KeyScrolllock = 70
KeyKp7 = 71
KeyKp8 = 72
KeyKp9 = 73
KeyKpminus = 74
KeyKp4 = 75
KeyKp5 = 76
KeyKp6 = 77
KeyKpplus = 78
KeyKp1 = 79
KeyKp2 = 80
KeyKp3 = 81
KeyKp0 = 82
KeyKpdot = 83
KeyZenkakuhankaku = 85
Key102Nd = 86
KeyF11 = 87
KeyF12 = 88
KeyRo = 89
KeyKatakana = 90
KeyHiragana = 91
KeyHenkan = 92
KeyKatakanahiragana = 93
KeyMuhenkan = 94
KeyKpjpcomma = 95
KeyKpenter = 96
KeyRightctrl = 97
KeyKpslash = 98
KeySysrq = 99
KeyRightalt = 100
KeyLinefeed = 101
KeyHome = 102
KeyUp = 103
KeyPageup = 104
KeyLeft = 105
KeyRight = 106
KeyEnd = 107
KeyDown = 108
KeyPagedown = 109
KeyInsert = 110
KeyDelete = 111
KeyMacro = 112
KeyMute = 113
KeyVolumedown = 114
KeyVolumeup = 115
KeyPower = 116 /*ScSystemPowerDown*/
KeyKpequal = 117
KeyKpplusminus = 118
KeyPause = 119
KeyScale = 120 /*AlCompizScale(Expose)*/
KeyKpcomma = 121
KeyHangeul = 122
KeyHanja = 123
KeyYen = 124
KeyLeftmeta = 125
KeyRightmeta = 126
KeyCompose = 127
KeyStop = 128 /*AcStop*/
KeyAgain = 129
KeyProps = 130 /*AcProperties*/
KeyUndo = 131 /*AcUndo*/
KeyFront = 132
KeyCopy = 133 /*AcCopy*/
KeyOpen = 134 /*AcOpen*/
KeyPaste = 135 /*AcPaste*/
KeyFind = 136 /*AcSearch*/
KeyCut = 137 /*AcCut*/
KeyHelp = 138 /*AlIntegratedHelpCenter*/
KeyMenu = 139 /*Menu(ShowMenu)*/
KeyCalc = 140 /*AlCalculator*/
KeySetup = 141
KeySleep = 142 /*ScSystemSleep*/
KeyWakeup = 143 /*SystemWakeUp*/
KeyFile = 144 /*AlLocalMachineBrowser*/
KeySendfile = 145
KeyDeletefile = 146
KeyXfer = 147
KeyProg1 = 148
KeyProg2 = 149
KeyWww = 150 /*AlInternetBrowser*/
KeyMsdos = 151
KeyCoffee = 152 /*AlTerminalLock/Screensaver*/
KeyDirection = 153
KeyCyclewindows = 154
KeyMail = 155
KeyBookmarks = 156 /*AcBookmarks*/
KeyComputer = 157
KeyBack = 158 /*AcBack*/
KeyForward = 159 /*AcForward*/
KeyClosecd = 160
KeyEjectcd = 161
KeyEjectclosecd = 162
KeyNextsong = 163
KeyPlaypause = 164
KeyPrevioussong = 165
KeyStopcd = 166
KeyRecord = 167
KeyRewind = 168
KeyPhone = 169 /*MediaSelectTelephone*/
KeyIso = 170
KeyConfig = 171 /*AlConsumerControlConfiguration*/
KeyHomepage = 172 /*AcHome*/
KeyRefresh = 173 /*AcRefresh*/
KeyExit = 174 /*AcExit*/
KeyMove = 175
KeyEdit = 176
KeyScrollup = 177
KeyScrolldown = 178
KeyKpleftparen = 179
KeyKprightparen = 180
KeyNew = 181 /*AcNew*/
KeyRedo = 182 /*AcRedo/Repeat*/
KeyF13 = 183
KeyF14 = 184
KeyF15 = 185
KeyF16 = 186
KeyF17 = 187
KeyF18 = 188
KeyF19 = 189
KeyF20 = 190
KeyF21 = 191
KeyF22 = 192
KeyF23 = 193
KeyF24 = 194
KeyPlaycd = 200
KeyPausecd = 201
KeyProg3 = 202
KeyProg4 = 203
KeyDashboard = 204 /*AlDashboard*/
KeySuspend = 205
KeyClose = 206 /*AcClose*/
KeyPlay = 207
KeyFastforward = 208
KeyBassboost = 209
KeyPrint = 210 /*AcPrint*/
KeyHp = 211
KeyCamera = 212
KeySound = 213
KeyQuestion = 214
KeyEmail = 215
KeyChat = 216
KeySearch = 217
KeyConnect = 218
KeyFinance = 219 /*AlCheckbook/Finance*/
KeySport = 220
KeyShop = 221
KeyAlterase = 222
KeyCancel = 223 /*AcCancel*/
KeyBrightnessdown = 224
KeyBrightnessup = 225
KeyMedia = 226
KeySwitchvideomode = 227 /*CycleBetweenAvailableVideo */
KeyKbdillumtoggle = 228
KeyKbdillumdown = 229
KeyKbdillumup = 230
KeySend = 231 /*AcSend*/
KeyReply = 232 /*AcReply*/
KeyForwardmail = 233 /*AcForwardMsg*/
KeySave = 234 /*AcSave*/
KeyDocuments = 235
KeyBattery = 236
KeyBluetooth = 237
KeyWlan = 238
KeyUwb = 239
KeyUnknown = 240
KeyVideoNext = 241 /*DriveNextVideoSource*/
KeyVideoPrev = 242 /*DrivePreviousVideoSource*/
KeyBrightnessCycle = 243 /*BrightnessUp,AfterMaxIsMin*/
KeyBrightnessZero = 244 /*BrightnessOff,UseAmbient*/
KeyDisplayOff = 245 /*DisplayDeviceToOffState*/
KeyWimax = 246
KeyRfkill = 247 /*KeyThatControlsAllRadios*/
KeyMicmute = 248 /*Mute/UnmuteTheMicrophone*/
keyMax = 248 // highest key currently defined
)

Wyświetl plik

@ -1,369 +0,0 @@
package uinput
import (
"bytes"
"encoding/binary"
"errors"
"fmt"
"os"
"syscall"
"time"
)
// types needed from uinput.h
const (
uinputMaxNameSize = 80
uiDevCreate = 0x5501
uiDevDestroy = 0x5502
uiSetEvBit = 0x40045564
uiSetKeyBit = 0x40045565
uiSetRelBit = 0x40045566
uiSetAbsBit = 0x40045567
busUsb = 0x03
)
// input event codes as specified in input-event-codes.h
const (
evSyn = 0x00
evKey = 0x01
evRel = 0x02
evAbs = 0x03
relX = 0x0
relY = 0x1
absX = 0x0
absY = 0x1
synReport = 0
evBtnLeft = 0x110
evBtnRight = 0x111
)
const (
btnStateReleased = 0
btnStatePressed = 1
absSize = 64
)
type inputID struct {
Bustype uint16
Vendor uint16
Product uint16
Version uint16
}
// translated to go from uinput.h
type uinputUserDev struct {
Name [uinputMaxNameSize]byte
ID inputID
EffectsMax uint32
Absmax [absSize]int32
Absmin [absSize]int32
Absfuzz [absSize]int32
Absflat [absSize]int32
}
// translated to go from input.h
type inputEvent struct {
Time syscall.Timeval
Type uint16
Code uint16
Value int32
}
func closeDevice(deviceFile *os.File) (err error) {
err = releaseDevice(deviceFile)
if err != nil {
return fmt.Errorf("failed to close device: %v", err)
}
return deviceFile.Close()
}
func releaseDevice(deviceFile *os.File) (err error) {
return ioctl(deviceFile, uiDevDestroy, uintptr(0))
}
func createDeviceFile(path string) (fd *os.File, err error) {
deviceFile, err := os.OpenFile(path, syscall.O_WRONLY|syscall.O_NONBLOCK, 0660)
if err != nil {
return nil, errors.New("could not open device file")
}
return deviceFile, err
}
func registerDevice(deviceFile *os.File, evType uintptr) error {
err := ioctl(deviceFile, uiSetEvBit, evType)
if err != nil {
err = releaseDevice(deviceFile)
if err != nil {
deviceFile.Close()
return fmt.Errorf("failed to close device: %v", err)
}
deviceFile.Close()
return fmt.Errorf("invalid file handle returned from ioctl: %v", err)
}
return nil
}
func createVKeyboardDevice(path string, name []byte) (fd *os.File, err error) {
deviceFile, err := createDeviceFile(path)
if err != nil {
return nil, fmt.Errorf("failed to create virtual keyboard device: %v", err)
}
err = registerDevice(deviceFile, uintptr(evKey))
if err != nil {
deviceFile.Close()
return nil, fmt.Errorf("failed to register virtual keyboard device: %v", err)
}
// register key events
for i := 0; i < keyMax; i++ {
err = ioctl(deviceFile, uiSetKeyBit, uintptr(i))
if err != nil {
deviceFile.Close()
return nil, fmt.Errorf("failed to register key number %d: %v", i, err)
}
}
return createUsbDevice(deviceFile,
uinputUserDev{
Name: toUinputName(name),
ID: inputID{
Bustype: busUsb,
Vendor: 0x4711,
Product: 0x0815,
Version: 1}})
}
func toUinputName(name []byte) (uinputName [uinputMaxNameSize]byte) {
var fixedSizeName [uinputMaxNameSize]byte
copy(fixedSizeName[:], name)
return fixedSizeName
}
func createTouchPad(path string, name []byte, minX int32, maxX int32, minY int32, maxY int32) (fd *os.File, err error) {
deviceFile, err := createDeviceFile(path)
if err != nil {
return nil, fmt.Errorf("could not create absolute axis input device: %v", err)
}
err = registerDevice(deviceFile, uintptr(evKey))
if err != nil {
deviceFile.Close()
return nil, fmt.Errorf("failed to register key device: %v", err)
}
// register button events (in order to enable left and right click)
err = ioctl(deviceFile, uiSetKeyBit, uintptr(evBtnLeft))
if err != nil {
deviceFile.Close()
return nil, fmt.Errorf("failed to register left click event: %v", err)
}
err = ioctl(deviceFile, uiSetKeyBit, uintptr(evBtnRight))
if err != nil {
deviceFile.Close()
return nil, fmt.Errorf("failed to register right click event: %v", err)
}
err = registerDevice(deviceFile, uintptr(evAbs))
if err != nil {
deviceFile.Close()
return nil, fmt.Errorf("failed to register absolute axis input device: %v", err)
}
// register x and y axis events
err = ioctl(deviceFile, uiSetAbsBit, uintptr(absX))
if err != nil {
deviceFile.Close()
return nil, fmt.Errorf("failed to register absolute x axis events: %v", err)
}
err = ioctl(deviceFile, uiSetAbsBit, uintptr(absY))
if err != nil {
deviceFile.Close()
return nil, fmt.Errorf("failed to register absolute y axis events: %v", err)
}
var absMin [absSize]int32
absMin[absX] = minX
absMin[absY] = minY
var absMax [absSize]int32
absMax[absX] = maxX
absMax[absY] = maxY
return createUsbDevice(deviceFile,
uinputUserDev{
Name: toUinputName(name),
ID: inputID{
Bustype: busUsb,
Vendor: 0x4711,
Product: 0x0817,
Version: 1},
Absmin: absMin,
Absmax: absMax})
}
func createMouse(path string, name []byte) (fd *os.File, err error) {
deviceFile, err := createDeviceFile(path)
if err != nil {
return nil, fmt.Errorf("could not create relative axis input device: %v", err)
}
err = registerDevice(deviceFile, uintptr(evKey))
if err != nil {
deviceFile.Close()
return nil, fmt.Errorf("failed to register key device: %v", err)
}
// register button events (in order to enable left and right click)
err = ioctl(deviceFile, uiSetKeyBit, uintptr(evBtnLeft))
if err != nil {
deviceFile.Close()
return nil, fmt.Errorf("failed to register left click event: %v", err)
}
err = ioctl(deviceFile, uiSetKeyBit, uintptr(evBtnRight))
if err != nil {
deviceFile.Close()
return nil, fmt.Errorf("failed to register right click event: %v", err)
}
err = registerDevice(deviceFile, uintptr(evRel))
if err != nil {
deviceFile.Close()
return nil, fmt.Errorf("failed to register relative axis input device: %v", err)
}
// register x and y axis events
err = ioctl(deviceFile, uiSetRelBit, uintptr(relX))
if err != nil {
deviceFile.Close()
return nil, fmt.Errorf("failed to register relative x axis events: %v", err)
}
err = ioctl(deviceFile, uiSetRelBit, uintptr(relY))
if err != nil {
deviceFile.Close()
return nil, fmt.Errorf("failed to register relative y axis events: %v", err)
}
return createUsbDevice(deviceFile,
uinputUserDev{
Name: toUinputName(name),
ID: inputID{
Bustype: busUsb,
Vendor: 0x4711,
Product: 0x0816,
Version: 1}})
}
func createUsbDevice(deviceFile *os.File, dev uinputUserDev) (fd *os.File, err error) {
buf := new(bytes.Buffer)
err = binary.Write(buf, binary.LittleEndian, dev)
if err != nil {
deviceFile.Close()
return nil, fmt.Errorf("failed to write user device buffer: %v", err)
}
_, err = deviceFile.Write(buf.Bytes())
if err != nil {
deviceFile.Close()
return nil, fmt.Errorf("failed to write uidev struct to device file: %v", err)
}
err = ioctl(deviceFile, uiDevCreate, uintptr(0))
if err != nil {
deviceFile.Close()
return nil, fmt.Errorf("failed to create device: %v", err)
}
time.Sleep(time.Millisecond * 200)
return deviceFile, err
}
func sendBtnEvent(deviceFile *os.File, key int, btnState int) (err error) {
buf, err := inputEventToBuffer(inputEvent{
Time: syscall.Timeval{Sec: 0, Usec: 0},
Type: evKey,
Code: uint16(key),
Value: int32(btnState)})
if err != nil {
return fmt.Errorf("key event could not be set: %v", err)
}
_, err = deviceFile.Write(buf)
if err != nil {
return fmt.Errorf("writing btnEvent structure to the device file failed: %v", err)
}
return err
}
func sendAbsEvent(deviceFile *os.File, xPos int32, yPos int32) error {
var ev [2]inputEvent
ev[0].Type = evAbs
ev[0].Code = absX
ev[0].Value = xPos
ev[1].Type = evAbs
ev[1].Code = absY
ev[1].Value = yPos
for _, iev := range ev {
buf, err := inputEventToBuffer(iev)
if err != nil {
return fmt.Errorf("writing abs event failed: %v", err)
}
_, err = deviceFile.Write(buf)
if err != nil {
return fmt.Errorf("failed to write abs event to device file: %v", err)
}
}
return syncEvents(deviceFile)
}
func sendRelEvent(deviceFile *os.File, eventCode uint16, pixel int32) error {
iev := inputEvent{
Time: syscall.Timeval{Sec: 0, Usec: 0},
Type: evRel,
Code: eventCode,
Value: pixel}
buf, err := inputEventToBuffer(iev)
if err != nil {
return fmt.Errorf("writing abs event failed: %v", err)
}
_, err = deviceFile.Write(buf)
if err != nil {
return fmt.Errorf("failed to write rel event to device file: %v", err)
}
return syncEvents(deviceFile)
}
func syncEvents(deviceFile *os.File) (err error) {
buf, err := inputEventToBuffer(inputEvent{
Time: syscall.Timeval{Sec: 0, Usec: 0},
Type: evSyn,
Code: 0,
Value: int32(synReport)})
if err != nil {
return fmt.Errorf("writing sync event failed: %v", err)
}
_, err = deviceFile.Write(buf)
return err
}
func inputEventToBuffer(iev inputEvent) (buffer []byte, err error) {
buf := new(bytes.Buffer)
err = binary.Write(buf, binary.LittleEndian, iev)
if err != nil {
return nil, fmt.Errorf("failed to write input event to buffer: %v", err)
}
return buf.Bytes(), nil
}
// original function taken from: https://github.com/tianon/debian-golang-pty/blob/master/ioctl.go
func ioctl(deviceFile *os.File, cmd, ptr uintptr) error {
_, _, errorCode := syscall.Syscall(syscall.SYS_IOCTL, deviceFile.Fd(), cmd, ptr)
if errorCode != 0 {
return errorCode
}
return nil
}

6
vendor/vendor.json vendored
Wyświetl plik

@ -20,12 +20,6 @@
"revision": "27f122750802c950b2c869a5b63dafcf590ced95",
"revisionTime": "2016-05-22T18:18:43Z"
},
{
"checksumSHA1": "DuHM9UBDn6AHdGqYDMZZqzFMOkI=",
"path": "github.com/bendahl/uinput",
"revision": "050ec524df761f5a128a5bb9bb5b7609f1886f21",
"revisionTime": "2017-06-20T19:50:18Z"
},
{
"checksumSHA1": "OFu4xJEIjiI8Suu+j/gabfp+y6Q=",
"origin": "github.com/stretchr/testify/vendor/github.com/davecgh/go-spew/spew",