uinput: user level driver support for input subsystem ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1. Basic use ~~~~~~~~~~~~ The uinput driver creates a character device, usually at /dev/uinput, that can be used to create Linux input devices from userspace. The rest of this text assumes you are already familiar with writing input drivers in kernelspace. The device's capabilities and identity are established primarily by write()'ing a struct uinput_device. Information not contained in this structure is provided with the UI_SET_* family of ioctl()s. After all this, UI_DEV_CREATE actually registers a new device with the input subsystem. Between UI_DEV_CREATE and UI_DEV_DESTROY, the UI_SET_* ioctl()s can't be used. Once the device has been created, /dev/uinput acts much like an event device. write() sends a struct input_event out of the device, read() fetches input events sent back to the driver by applications. Note that events written will also be echoed back on read. 2. Force Feedback ~~~~~~~~~~~~~~~~~ To write a force-feedback-capable driver, the upload_effect and erase_effect callbacks in input_dev must be implemented. The uinput driver will generate a fake input event when one of these callbacks are invoked. The userspace code then uses ioctls to retrieve additional parameters and send the return code. The callback blocks until this return code is sent. The described callback mechanism is only used if EV_FF is set. Otherwise, default implementations of upload_effect and erase_effect are used. To implement upload_effect(): 1. Wait for an event with type==EV_UINPUT and code==UI_FF_UPLOAD. A request ID will be given in 'value'. 2. Allocate a uinput_ff_upload struct, fill in request_id with the 'value' from the EV_UINPUT event. 3. Issue a UI_BEGIN_FF_UPLOAD ioctl, giving it the uinput_ff_upload struct. It will be filled in with the ff_effect passed to upload_effect(). 4. Perform the effect upload. Place the modified ff_effect and a return code back into the uinput_ff_upload struct. 5. Issue a UI_END_FF_UPLOAD ioctl, also giving it the uinput_ff_upload_effect struct. This will complete execution of our upload_effect() handler. To implement erase_effect(): 1. Wait for an event with type==EV_UINPUT and code==UI_FF_ERASE. A request ID will be given in 'value'. 2. Allocate a uinput_ff_erase struct, fill in request_id with the 'value' from the EV_UINPUT event. 3. Issue a UI_BEGIN_FF_ERASE ioctl, giving it the uinput_ff_erase struct. It will be filled in with the effect ID passed to erase_effect(). 4. Perform the effect erasure, and place a return code back into the uinput_ff_erase struct. 5. Issue a UI_END_FF_ERASE ioctl, also giving it the uinput_ff_erase_effect struct. This will complete execution of our erase_effect() handler.