uinput

package module
v1.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 7, 2020 License: MIT Imports: 8 Imported by: 1

README

Uinput Build Status GoDoc Go Report Card

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, a touch pad device & a dial 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). For implementing things like region selects via a virtual mouse pointer, press and release functions for the mouse device are also included.

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).

Dial devices support triggering rotation events, like turns on a volume knob.

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):


echo KERNEL==\"uinput\", GROUP=\"$USER\", MODE:=\"0660\" | sudo tee /etc/udev/rules.d/99-$USER.rules
sudo udevadm trigger

Installation

Simply check out the repository and use the commands

go build && go install
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.

Alternatively, if you'd like to use a specific version/tag of this library, you may use the gopkg.in service. To get v.1.x.x (latest stable v1), simply enter this on your command line:

go get gopkg.in/bendahl/uinput.v1

To import this version in your code use:

import "gopkg.in/bendahl/uinput.v1"

You may then refer to it as "uinput" in your code. For further details see: https://gopkg.in/bendahl/uinput.v1

Thanks to gopkg.in for offering this great service!

Usage

The following section explains some common ways to use this lib.

Using the virtual keyboard device:
package main

import "github.com/bendahl/uinput"
// alternatively (to use specific version), use this:
//import "gopkg.in/bendahl/uinput.v1"

func main() {
	// initialize keyboard and check for possible errors
	keyboard, err := uinput.CreateKeyboard("/dev/uinput", []byte("testkeyboard"))
	if err != nil {
		return
	}
	// always do this after the initialization in order to guarantee that the device will be properly closed
	defer keyboard.Close()

	// prints "a"
	keyboard.KeyPress(uinput.KeyA)

	// prints "A"
	// Note that you could use caps lock instead of using shift with KeyDown and KeyUp
	keyboard.KeyDown(uinput.KeyLeftshift)
	keyboard.KeyPress(uinput.KeyA)
	keyboard.KeyUp(uinput.KeyLeftshift)

	// prints "00000"
	for i := 0; i < 5; i++ {
		keyboard.KeyPress(uinput.Key0)
	}
}
Using the virtual mouse device:
package main

import "github.com/bendahl/uinput"
// alternatively (to use specific version), use this:
//import "gopkg.in/bendahl/uinput.v1"

func main() {
	// initialize mouse and check for possible errors
	mouse, err := uinput.CreateMouse("/dev/uinput", []byte("testmouse"))
	if err != nil {
		return
	}
	// always do this after the initialization in order to guarantee that the device will be properly closed
	defer mouse.Close()

	// mouse pointer will be moved up by 10 pixels
	mouse.MoveUp(10)
	// mouse pointer will be moved to the right by 10 pixels
	mouse.MoveRight(10)
	// mouse pointer will be moved down by 10 pixels
	mouse.MoveDown(10)
	// mouse pointer will be moved to the left by 10 pixels (we're back to where we started)
	mouse.MoveLeft(10)

	// click left
	mouse.LeftClick()
	// click right (depending on context a context menu may appear)
	mouse.RightClick()

	// hold down left mouse button
	mouse.LeftPress()
	// move mouse pointer down by 100 pixels while holding down the left key
	mouse.MoveDown(100)
	// release the left mouse button
	mouse.LeftRelease()

	// wheel up
	mouse.Wheel(false, 1)
	// wheel down
	mouse.Wheel(false, -1)
	// horizontal wheel left
	mouse.Wheel(true, 1)
	// horizontal wheel right
	mouse.Wheel(true, -1)
}
Using the virtual touch pad device:
package main

import "github.com/bendahl/uinput"
// alternatively (to use specific version), use this:
//import "gopkg.in/bendahl/uinput.v1"

func main() {
	// initialization of the touch device requires to set the screen boundaries
	// min and max values for x and y axis need to be set (usually, 0 should be a sane lower bound)
	touch, err := uinput.CreateTouchPad("/dev/uinput", []byte("testpad"), 0, 800, 0, 600)
	if err != nil {
		return
	}
	// always do this after the initialization in order to guarantee that the device will be properly closed
	defer touch.Close()

	// move pointer to the position 300, 200
	touch.MoveTo(300, 200)
	// press the left mouse key, holding it down
	touch.LeftPress()
	// move pointer to position 400, 400
	touch.MoveTo(400, 400)
	// release the left mouse key
	touch.LeftRelease()
	// create a single tab using a finger and immediately release
	touch.TouchDown()
	touch.TouchUp()

}
Using the virtual dial device:
package main

import "github.com/bendahl/uinput"
// alternatively (to use specific version), use this:
//import "gopkg.in/bendahl/uinput.v1"

func main() {
	// initialize dial and check for possible errors
	dial, err := uinput.CreateDial("/dev/uinput", []byte("testdial"))
	if err != nil {
		return
	}
	// always do this after the initialization in order to guarantee that the device will be properly closed
	defer dial.Close()

	// turn dial left
	dial.Turn(-1)
	// turn dial right
	dial.Turn(1)
}

License

The package falls under the MIT license. Please see the "LICENSE" file for details.

Current Status

2018-03-31: I am happy to announce that v1.0.0 is finally out! Go ahead and use this library in your own projects! Feedback is always welcome.

2019-03-24: Release v1.0.1 fixes a positioning issue that affects the touchpad. See issue #11 for details (positioning works now, but a (possibly) better solution is under investigation).

2019-07-24: Don't panic! As of version v1.0.2 the uinput library will provide an error instead of raising a panic in case of a faulty initialization. See pull request #12 for details (many thanks to muesli for the contribution).

2019-09-15: Add single touch event (resistive)

2019-12-31: Release v1.1.0 introduces yet another cool feature: Mouse wheel support. Thanks to muesli for this contribution!

TODO

The current API can be considered stable and the overall functionality (as originally envisioned) is complete. Testing on x86_64 and ARM platforms (specifically the RaspberryPi) has been successful. If you'd like to use this library on a different platform that supports Linux, feel free to test it and share the results. This would be greatly appreciated. One thing that I'd still like to improve, however, are the test cases. The basic functionality is covered, but more extensive testing is something that needs to be worked on.

  • Create Tests for the uinput package
  • Migrate code from C to GO
  • Implement relative input
  • Implement absolute input
  • Test on different platforms
    • x86_64
    • ARMv6 (RaspberryPi)
  • Implement functions to allow mouse button up and down events (for region selects)
  • Extend test cases

Documentation

Overview

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()

Index

Constants

View Source
const (
	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*/

)

the constants that are defined here relate 1:1 to the constants defined in input.h and represent actual key codes that can be triggered as key events

Variables

This section is empty.

Functions

This section is empty.

Types

type Dial added in v1.2.0

type Dial interface {
	// Turn will simulate a dial movement.
	Turn(delta int32) error

	io.Closer
}

A Dial is a device that will trigger rotation events. For details see: https://www.kernel.org/doc/Documentation/input/event-codes.txt

func CreateDial added in v1.2.0

func CreateDial(path string, name []byte) (Dial, error)

CreateDial will create a new dial input device. A dial is a device that can trigger rotation events.

type Keyboard

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 keycodes.go.
	// 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 keycodes.go.
	KeyUp(key int) error

	io.Closer
}

A Keyboard is an key event output device. It is used to enable a program to simulate HID keyboard input events.

func CreateKeyboard

func CreateKeyboard(path string, name []byte) (Keyboard, error)

CreateKeyboard will create a new keyboard using the given uinput device path of the uinput device.

type Mouse

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

	// LeftPress will simulate a press of the left mouse button. Note that the button will not be released until
	// LeftRelease is invoked.
	LeftPress() error

	// LeftRelease will simulate the release of the left mouse button.
	LeftRelease() error

	// RightPress will simulate the press of the right mouse button. Note that the button will not be released until
	// RightRelease is invoked.
	RightPress() error

	// RightRelease will simulate the release of the right mouse button.
	RightRelease() error

	// Wheel will simulate a wheel movement.
	Wheel(horizontal bool, delta int32) error

	io.Closer
}

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

func CreateMouse

func CreateMouse(path string, name []byte) (Mouse, error)

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

type TouchPad

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

	// LeftPress will simulate a press of the left mouse button. Note that the button will not be released until
	// LeftRelease is invoked.
	LeftPress() error

	// LeftRelease will simulate the release of the left mouse button.
	LeftRelease() error

	// RightPress will simulate the press of the right mouse button. Note that the button will not be released until
	// RightRelease is invoked.
	RightPress() error

	// RightRelease will simulate the release of the right mouse button.
	RightRelease() error

	// TouchDown will simulate a single touch to a virtual touch device. Use TouchUp to end the touch gesture.
	TouchDown() error

	// TouchUp will end or ,more precisely, unset the touch event issued by TouchDown
	TouchUp() error

	io.Closer
}

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.

func CreateTouchPad

func CreateTouchPad(path string, name []byte, minX int32, maxX int32, minY int32, maxY int32) (TouchPad, error)

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.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL