Skip to content

Commit

Permalink
API cleanup - using struct for vkeyboard now
Browse files Browse the repository at this point in the history
  • Loading branch information
Benjamin Dahlmanns committed May 29, 2014
1 parent b05aca9 commit c16f06d
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 40 deletions.
73 changes: 56 additions & 17 deletions uinput.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,16 @@ example).
In order to use the virtual keyboard, you will need to follow these three steps:
1. Initialize the device (don't forget to store the deviceId)
Example: devId, err := uinput.CreateVKeyboardDevice("/dev/uinput")
1. Initialize the device
Example: vk := VKeyboard{}
err := vk.Create("/dev/uinput")
2. Send Button events to the device
Example: err = uinput.SendBtnEvent(devId, uinput.KEY_D, 1)
Example: err = vk.SendKeyPress(uinput.KEY_D)
3. Close the device
Example: err = uinput.CloseDevice(devId)
Example: err = vk.Close()
*/
package uinput

Expand All @@ -26,39 +28,76 @@ import (
"unsafe"
)

// CreateVKeyboardDevice creates a new uinput device.
// VKeyboard represents a virtual keyboard device. There are several
// methods available to work with this virtual device. Devices can be
// created, receive events, and closed.
type VKeyboard struct {
id int
}

// Create creates a new virtual keyboard device.
// Make sure to pass the correct path to the current system's
// uinput device (usually either "/dev/uinput" or "/dev/input/uinput".
func CreateVKeyboardDevice(path string) (deviceId int, err error) {
func (vk *VKeyboard) Create(path string) (err error) {
vk.id = -1
var ret error
vk.id, ret = createVKeyboardDevice(path)
return ret
}

// SendKeyPress will send a keypress event to an existing keyboard device.
// The key can be any of the predefined keycodes from uinputdefs.
func (vk *VKeyboard) SendKeyPress(key int) (err error) {
if vk.id < 0 {
return errors.New("Keyboard not initialized. Sending keypress event failed.")
}

return sendBtnEvent(vk.id, key, 1)
}

// SendKeyRelease will send a keyrelease event to an existing keyboard device.
// The key can be any of the predefined keycodes from uinputdefs.
func (vk *VKeyboard) SendKeyRelease(key int) (err error) {
if vk.id < 0 {
return errors.New("Keyboard not initialized. Sending keyrelease event failed.")
}

return sendBtnEvent(vk.id, key, 0)
}

// 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() (err error) {
if vk.id < 0 {
return errors.New("Keyboard not initialized. Closing device failed.")
}
return closeDevice(vk.id)
}

func createVKeyboardDevice(path string) (deviceId int, err error) {
var fd C.int
var deviceName = C.CString(path)
defer C.free(unsafe.Pointer(deviceName))

fd = C.initVKeyboardDevice(deviceName)
if fd < 0 {
return 0, errors.New("Could not initialize device")
return 0, errors.New("Could not initialize device.")
}

return int(fd), nil
}

// SendBtnEvent will send a button event to the newly created device.
// The id refers to the deviceId returned by the create method. The key
// can be any of the predefined keycodes. The btnState can either be
// pressed (1) or released (0).
func SendBtnEvent(deviceId int, key int, btnState int) (err error) {
func sendBtnEvent(deviceId int, key int, btnState int) (err error) {
if C.sendBtnEvent(C.int(deviceId), C.int(key), C.int(btnState)) < 0 {
return errors.New("Sending keypress failed")
return errors.New("Sending keypress failed.")
} else {
return nil
}
}

// CloseDevice will close the device and free resources.
// It's usually a good idea to use defer to call this function.
func CloseDevice(deviceId int) (err error) {
func closeDevice(deviceId int) (err error) {
if int(C.releaseDevice(C.int(deviceId))) < 0 {
return errors.New("Closing device failed")
return errors.New("Closing device failed.")
} else {
return nil
}
Expand Down
41 changes: 18 additions & 23 deletions uinput_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,26 @@ import (

// This test will create a basic VKeyboard, send a key command and then close the keyboard device
func TestBasicVKeyboard(t *testing.T) {
devId, err := CreateVKeyboardDevice("/dev/uinput")
vk := VKeyboard{}
err := vk.Create("/dev/uinput")

if err != nil {
t.Fatalf("Failed to create the virtual keyboard. Last error was: %s\n", err)
}

err = SendBtnEvent(devId, KEY_1, 1)
err = vk.SendKeyPress(KEY_1)

if err != nil {
t.Fatalf("Failed to send key event. Last error was: %s\n", err)
}

err = CloseDevice(devId)
err = vk.SendKeyRelease(KEY_1)

if err != nil {
t.Fatalf("Failed to send key event. Last error was: %s\n", err)
}

err = vk.Close()

if err != nil {
t.Fatalf("Failed to close device. Last error was: %s\n", err)
Expand All @@ -28,43 +35,31 @@ func TestBasicVKeyboard(t *testing.T) {
// This test will confirm that a proper error code is returned if an invalid uinput path is
// passed to the library
func TestInvalidDevicePath(t *testing.T) {
devId, err := CreateVKeyboardDevice("/invalid/path")
vk := VKeyboard{}
err := vk.Create("/invalid/path")

if err == nil {
// this usually shouldn't happen, but if the device is created, we need to close it
CloseDevice(devId)
vk.Close()
t.Fatalf("Expected error code,but received %s instead.\n", err)
}
}

// This test will confirm that a proper error code is returned if an invalid keycode is
// This test will confirm that a proper error code is returned if an invalid keycode is
// passed to the library
func TestInvalidKeycode(t *testing.T) {
devId, err := CreateVKeyboardDevice("/dev/uinput")
vk := VKeyboard{}
err := vk.Create("/dev/uinput")

if err != nil {
t.Fatalf("Failed to create the virtual keyboard. Last error was: %s\n", err)
}

err = SendBtnEvent(devId, 4711, 1)
err = vk.SendKeyPress(4711)

if err == nil {
t.Fatalf("Sending an invalid keycode did not trigger an error. Got: %d.\n")
}
}

// This test will confirm that a proper error code is returned if an invalid button state is
// passed to the library
func TestInvalidBtnState(t *testing.T) {
devId, err := CreateVKeyboardDevice("/dev/uinput")

if err != nil {
t.Fatalf("Failed to create the virtual keyboard. Last error was: %s\n", err)
}

err = SendBtnEvent(devId, KEY_1, 3)

if err == nil {
t.Fatalf("Sending an invalid btnState did not trigger an error. Got: %d.\n")
}
vk.Close()
}

0 comments on commit c16f06d

Please sign in to comment.