XInput Extension Specifications (Developmental Proposal)
This page is out of date and its content is provided for historic reasons only. Some of the features below is superfluous, others have been implemented already. This is not a guide to the future of input development.
Table of Contents
Overview
This page is intended as a place to evolve the design specifications for the next version of the XINPUT for the X.org server. This includes a long needed update to the XINPUT specification to improve support for better device controls, hotplugging, and multiple core devices. This page focuses on the XInput protocol. The implementation in the XOrg server should be documented in XOrgInputDriverSpec.
Introduction
First, an important question: Should the XInput improvements all be part of XInput 2.0? XInput includes several commands that resemble a general purpose interface to extension events. Furthermore, many of the needed improvements for managing and configuring input devices are applicable to output devices, including something as substantial as a hot-pluggable PCMCIA video card.
So, in addition to the much-needed update to the XInput protocol, should there also be another extension called (perhaps) XDevice, that defines all of the runtime device configuration and management issues that are not part of the existing XInput?
Or, should we just extend XInput, and not worry that it is really applicable to more than just input devices, despite the name? This is already true for XInput because Feedback events are a form of output. (In a way, a graphical display is just a very elaborate central Feedback device.) Besides, HID is similarly misnamed.
HID Protocol Features
The HID design is a verbose and inflexible, rather than a simple but extensible design. This does not really fit the overall X design concept very well, so it does not make sense to incorporate the actual HID spec into X. However, most modern input devices are designed around HID, so XInput should attempt to be HID compatible. In otherwords, XInput should be able to include device and control attributes that correspond to HID names, but these should all conveyed by name rather than using all of the HID enum values.
One useful aspect of HID is Device and Control Usages. XInput has some support for Device Usage by including a type Atom in the XDeviceInfo structure, although it has not been adequately implemented. It is reasonable to define the standard type Atoms with the corresponding HID Usage names, which already include several common type names typically used in X, such as Pointer, Keyboard, Joystick.
Individual controls do not have a similar type identifier, but one should be incorporated into the various control Info structures. Each info structure includes a length value. That means it is possible to extend these structures and keep backwards compatibility. The extended structures should also include additional details about each control. For example, buttons can be described as momentary or toggle switches.
Rather than trying to define a few additional specific properties, it is probably best to support a variable number of parameter+value pairs for each device and each control. This allows for extensibility, and can work similar to Window properties.
Security Considerations
Device event handling has important security implications. Currently, security is handled with global Display access, and temporary Device Grabs. With the possibility of multiple input devices, multiple servers, and even multiple users on the same Display, event access control needs to be more explicit. So, devices need security attributes, which probably need to be implemented in a similar way for explicit access to/from individual windows.
Proposed Additional XInput Functions
X[Get|Change|Delete]DeviceProperty(), X[List|Rotate]DeviceProperties()
A straightforward method of implementing extensible and diverse device properties is to provide each device with a set of properties that is accessible in a manner similar to Window properties. This allows for a variety of data formats and sizes, and would use the existing Window Property infrastructure. Device Properties can relay all of the information about input usages, advanced pointer-acceleration curves, etc.
XChangeDeviceControl(), XGetDeviceControl()
This function is important, but drastically incomplete. The Device Property interface could probably work as a complete replacement for these functions, but it is useful to have separate interface for active commands that affect the hardware. However, note that the single defined device control, DEVICE_RESOLUTION, is more of a property than a hardware command.
Rather than adding a new data structure for each new control type, it is better to use an approach similar to window properties, except that control data is interpreted rather than simply being saved in a database.
Some undecided issues:
- Should XDeviceControl() simply be left as a 'legacy' function and use general Device Properties instead? If so, is it reasonable to have a property be acted on as an active command by a device (i.e. set property DEVICE_COMMAND = "reset")?
- Is it useful to implement new, specific data structures for some common device controls, as intended in the original XInput design, or should all new controls be implemented using the generic mechanism?
- Should the generic control value also support 16-bit and 32-bit data? Window Properties and Client Messages both support multiple data sizes, but it may be an unnecessary complication. Are there any good examples control parameters that would benefit from 16 or 32 bit data? Data for a force-feedback would be an example, except that it is better implemented as a Feedback, not a Control.
- How will the control be implemented? One possibility is to send the control data as a new Device Control in the existing XChangeDeviceControl(). Another possibility is to implement a new function that is designed around generic character data values.
This approach is completely compatible with the existing XInput protocol, but is not really using the control type argument as originally intended, and adds unnecessary complexity.
X[Add|Remove][Keyboard|Pointer]Device()
There should be a formal mechanism for multiple Pointer and Keyboard devices capable of sending core events. Question: how will these functions interoperate with XChangePointerDevice and XChangeKeyboardDevice? Should X retain the concept of a single "primary" mouse and keyboard, and have the new functions enable/disable devices to emit core events in addition to the core devices? Or, should the old functions be considered obsolete and just have them always return BadDevice? Any other ideas?
XSetDeviceMode() and Motion Event Types
This function assumes that devices can only emit relative or absolute events for all clients listening to the device. This probably should not be true for any device. Therefore, it may be reasonable to always return BadMode, which is the proper response for devices not supporting XSetDeviceMode requests.
The problem is that no other mechanism is defined to select relative versus absolute events. Therefore, it would probably be necessary to add RelativeMotionNotify and AbsoluteMotionNotify event types. It may also be acceptable to use the existing MotionNotify to handle Absolute events, which are more common. On the other hand, a new Absolute event type would also add an opportunity to support fractional motion events.
Absolute events should also be better defined. Most drivers are pointer oriented, and consider absolute motion events to mean screen coordinates, rather than device coordinates. Perhaps Absolute events should always be in device coordinates, and only be converted to screen coordinates for core pointer events. Note that MotionEvents also send x_root and y_root, so clients will always get pointer coordinates.
There are also some problems with the definition of Absolute versus Relative events. Many input devices send control data that is intended to be used for relative motion, even though the device state is actually an absolute position. For example, a centering joystick is intended to direct relative motion, but a non-centering joystick is accurately represented by an absolute position. Consider how you would would want to use these two joystick types to direct pointer motion. Although the control state is absolute in both cases, the data for the centering joystick should (arguably) be defined as Relative data, partly because the derivative is fairly useless but integrating from Relative to Absolute could be useful.
XListInputDrivers()
A device driver can be automatically associated with a device, depending on the device type, or otherwise controlled at the OS level. However, it may be useful to allow some client control, especially if more than one driver can handle the same device.
Get a list of available device drivers; information format not yet defined. It is probably useful to include information about supported hardware, but that can be quite complex. Perhaps just a list of driver names and versions is sufficient.
XAddInputDriver(), XRemoveInputDriver()
Just an idea for now: Should it be possible to add/remove drivers in a running server? If so, should it be managed by a formal X event, or should this be managed simply by adding or removing driver binaries from the module directory?
XAddInputDevice(), XRemoveInputDevice()
These functions add or remove a device instance from the server. These are similar to the internal dix functions AddInputDevice() and RemoveDevice().
In the current server design, a newly added device but uninitialized device is in the off_devices
list, and not available in XListInputDevices(). Before the device is initialized and made available to clients, it needs to be configured, presumably by the client that sent the request to add the device. Here are possibilities for handling the initial configuration.
- XAddInputDevice() can include as an argument a complete array of configuration directives.
- The initial state of the new device can be as Grabbed by the requesting client, which can release the Grab when it decides the device is ready for use.
The off_devices
list may be considered an obsolete feature when proper hotplugging is implemented. However, there are a few cases where it may still be useful. First, if a device fails initialization, it remains in the off_devices
list. The list could be used to give devices another opportunity to attempt initialization. Secondly, if a device is opened by a client, but the hardware becomes unavailable, it may be useful to keep the off_devices
instance around until all clients have closed the device.
How does one get a list of the "off devices"? XListInputDevices() has no option flags, so the current design would best handle this by listing all devices, and defining an DeviceInfo.use=IsOffline type.
XEnableDevice(), XDisableDevice()
These functions move a device from/to the off_devices list, and succeed depending on the result from the drivers response to DEVICE_INIT and DEVICE_CLOSE.
Proposed Additional XInput Data Structures
Issues with Extended XEvents and Other Data Structures
The XEvent structure was designed with a fixed size to simplify memory management. Events are passed to the client by passing an entire XEvent structure, rather than passing an event pointer. This limits possibilities for defining Event types with larger data sizes.
One approach for handling large event types would be to include a data pointer in the XEvent structure. The extended data can be automatically freed by Xlib upon the next event retrieval.
The ClassInfo
structures include a length element, which means that extending existing structures can be backwards compatible. The XDeviceInfo structure does not have a length field, so changes will be incompatible. However, a much more versatile approach to extended device properties is to support property attributes similar to window properties, and to leave much of the current data structures unchanged.
XDeviceListChangeEvent
A new event is added to XInput to notify clients that the device list has changed.
The event structure could be similar to XChangeDeviceNotifyEvent, where the XID is identifies the lost or gained device. This would require an event for each lost or gained device, but could be useful for clients that only want to monitor the status of one device.
typedef struct { int type; unsigned long serial; Bool send_event; Display *display; Window window; /* Root Window, or unused ? */ XID deviceid; /* ID of new or lost device */ Time time; int state; /* DeviceNew, DeviceLost. Maybe also: DeviceEnabled, DeviceDisabled? */ } XDeviceListChangeEvent;
XDeviceConfigureControl
One possible solution for generalizing Device Controls. This uses existing XInput functions, with a generic, extensible control type:
typedef struct { XID control = DEVICE_CONFIGURE; int length = sizeof(XDeviceConfigureControl); Atom name; int format; unsigned char *value; int length; } XDeviceConfigureControl;
Input Device Properties
This is a listing of generalized device properties to consider. These would be available via a DeviceControl function that returns a string given a parameter named by a string or associated Atom.
Description
- UUID -- Unique ID for this device, which is valid outside of the current server context. What makes it unique is not defined here. It would be easy if all devices had a serial number.
- HardwareID -- Identifies the hardware connection (i.e. HAL/devfs name, network address:port, etc.)
- SerialNumber -- embedded device serial number, when available
- Name -- Some sort of short 'friendly' name unique on the server (Mouse0, Keyboard0)
- Description -- A verbose device description
- VendorName -- Vendor name
- ProductName -- Product name
- ProductRevision -- Product version
- UserName -- Identify who is using the device, if it is Grabbed.
It may be good to always include numeric product and vendor ID's, to avoid ambiguities for cases where names are unknown, or have changed. Should these be a separate field, or grouped with the text name? In addition to user name, devices should probably include support for security (authentication, access-control) features.
Device Event Properties
- Valuator properties (partly based on HID):
- Relative / Absolute
- Preferred State (Auto-Center valuators and Momentary buttons)
- Wrap (or Periodic)
- Volatile (Value is settable)
- Units
- Minimum Value
- Maximum Value
- Granularity (Precision)
- Null Position (says if an input can have an "invalid" state) -- This property was invented to handle Hat switches, which can be idle, or pointing a direction. It is probably best to represent these as an X,Y valuator pair, or as a directional valuator and a 'valid' or 'active' button.
Other HID Properties
The following HID properties are not so useful for XClients, but might be needed for devices calibration, which should probably be handled by the X Client Input Device Manager:
- Logical (raw input) range
- Current Physical (event data) range
- Default Physical range
- Saturation (assuming the actual max-val may not be exact)
Linearity Properties
Non-linear input should probably be converted to linear at the server level. Acceleration is probably best handled by the server, with all devices set for linear output, in order to provide uniform acceleration parameters for all devices. (Q: Are there cases where acceleration at the device level is really an advantage?)
- Linear
- Unit Exponent
- Acceleration parameters, or point data for general line/curve
- Null radius