[input] Rework device registration

And provide functions for collecting axis and button information from a
device id.
This commit is contained in:
Bill Currie 2021-09-20 15:21:11 +09:00
parent 70812b3c49
commit cc730c90b4
4 changed files with 192 additions and 22 deletions

View file

@ -30,6 +30,21 @@
#include "QF/keys.h"
typedef struct in_axisinfo_s {
int deviceid;
int axis;
int value;
int min;
int max;
} in_axisinfo_t;
typedef struct in_buttoninfo_s {
int deviceid;
int button;
int state;
} in_buttoninfo_t;
#ifndef __QFCC__
typedef struct {
vec3_t angles;
vec3_t position;
@ -41,13 +56,18 @@ typedef struct in_driver_s {
void (*process_events) (void *data);
void (*clear_states) (void *data);
void (*grab_input) (void *data, int grab);
void (*axis_info) (void *data, void *device, in_axisinfo_t *axes,
int *numaxes);
void (*button_info) (void *data, void *device, in_buttoninfo_t *buttons,
int *numbuttons);
} in_driver_t;
typedef struct in_device_s {
int driverid;
void *device;
const char *name;
const char *path;
const char *id;
} in_device_t;
extern viewdelta_t viewdelta;
@ -61,9 +81,15 @@ void IN_DriverData (int handlle, void *data);
void IN_Init (struct cbuf_s *cbuf);
void IN_Init_Cvars (void);
int IN_AddDevice (in_device_t *device);
int IN_AddDevice (int driver, void *device, const char *name, const char *id);
void IN_RemoveDevice (int devid);
void IN_SendConnectedDevices (void);
const char *IN_GetDeviceName (int devid);
const char *IN_GetDeviceId (int devid);
int IN_AxisInfo (int devid, in_axisinfo_t *axes, int *numaxes);
int IN_ButtonInfo (int devid, in_buttoninfo_t *button, int *numbuttons);
void IN_ProcessEvents (void);
void IN_UpdateGrab (struct cvar_s *);
@ -86,5 +112,6 @@ extern float in_mouse_x, in_mouse_y;
extern kbutton_t in_strafe, in_klook, in_speed, in_mlook;
#endif
#endif//__QF_input_h

View file

@ -31,7 +31,7 @@
/** Type declaration for a type-safe ring buffer.
*
* While not in itself thread-safe, the buffer is designed (and tested) to be
* used in a threaded environment using sutable locking mechanisms.
* used in a threaded environment using suitable locking mechanisms.
*
* \param type The type of data element stored in the ring buffer.
* \param size The number of objects in the ring buffer. Note that the

View file

@ -64,7 +64,7 @@ typedef struct {
} in_regdriver_t;
static struct DARRAY_TYPE (in_regdriver_t) in_drivers = { .grow = 8 };
static struct DARRAY_TYPE (in_device_t *) in_devices = { .grow = 8 };
static struct DARRAY_TYPE (in_device_t) in_devices = { .grow = 8 };
VISIBLE viewdelta_t viewdelta;
@ -100,24 +100,35 @@ IN_DriverData (int handle, void *data)
}
static int
in_add_device (in_device_t *device)
in_add_device (int driver, in_device_t *device, const char *name,
const char *id)
{
size_t devid;
in_device_t indev = {
.driverid = driver,
.device = device,
.name = name,
.id = id,
};
for (devid = 0; devid < in_devices.size; devid++) {
if (!in_devices.a[devid]) {
in_devices.a[devid] = device;
if (in_devices.a[devid].driverid == -1) {
in_devices.a[devid] = indev;
return devid;
}
}
DARRAY_APPEND (&in_devices, device);
DARRAY_APPEND (&in_devices, indev);
return devid;
}
int
IN_AddDevice (in_device_t *device)
IN_AddDevice (int driver, void *device, const char *name, const char *id)
{
int devid = in_add_device (device);
if ((size_t) driver >= in_drivers.size) {
Sys_Error ("IN_AddDevice: invalid driver: %d", driver);
}
int devid = in_add_device (driver, device, name, id);
IE_event_t event = {
.type = ie_add_device,
@ -133,9 +144,7 @@ IN_AddDevice (in_device_t *device)
void
IN_RemoveDevice (int devid)
{
size_t d = devid;
if (d >= in_devices.size) {
if ((size_t) devid >= in_devices.size) {
Sys_Error ("IN_RemoveDevice: invalid devid: %d", devid);
}
@ -148,7 +157,96 @@ IN_RemoveDevice (int devid)
};
IE_Send_Event (&event);
in_devices.a[devid] = 0;
in_devices.a[devid].device = 0;
}
void
IN_SendConnectedDevices (void)
{
for (size_t devid = 0; devid < in_devices.size; devid++) {
if (in_devices.a[devid].driverid >= 0
&& in_devices.a[devid].device) {
IE_event_t event = {
.type = ie_add_device,
.when = Sys_LongTime (),//FIXME actual time?
.device = {
.devid = devid,
},
};
IE_Send_Event (&event);
}
}
}
const char *
IN_GetDeviceName (int devid)
{
if ((size_t) devid >= in_devices.size) {
return 0;
}
if (!in_devices.a[devid].device || in_devices.a[devid].driverid == -1) {
return 0;
}
return in_devices.a[devid].name;
}
const char *
IN_GetDeviceId (int devid)
{
if ((size_t) devid >= in_devices.size) {
return 0;
}
if (!in_devices.a[devid].device || in_devices.a[devid].driverid == -1) {
return 0;
}
return in_devices.a[devid].id;
}
int
IN_AxisInfo (int devid, in_axisinfo_t *axes, int *numaxes)
{
if ((size_t) devid >= in_devices.size) {
return -1;
}
if (!in_devices.a[devid].device || in_devices.a[devid].driverid == -1) {
return -1;
}
int driver = in_devices.a[devid].driverid;
in_regdriver_t *rd = &in_drivers.a[driver];
if (!rd->driver.axis_info) {
return -1;
}
rd->driver.axis_info (rd->data, in_devices.a[devid].device, axes, numaxes);
if (axes) {
for (int i = 0; i < *numaxes; i++) {
axes[i].deviceid = devid;
}
}
return 0;
}
int
IN_ButtonInfo (int devid, in_buttoninfo_t *buttons, int *numbuttons)
{
if ((size_t) devid >= in_devices.size) {
return -1;
}
if (!in_devices.a[devid].device || in_devices.a[devid].driverid == -1) {
return -1;
}
int driver = in_devices.a[devid].driverid;
in_regdriver_t *rd = &in_drivers.a[driver];
if (!rd->driver.button_info) {
return -1;
}
rd->driver.button_info (rd->data, in_devices.a[devid].device,
buttons, numbuttons);
if (buttons) {
for (int i = 0; i < *numbuttons; i++) {
buttons[i].deviceid = devid;
}
}
return 0;
}
void

View file

@ -46,7 +46,7 @@
#include "evdev/inputlib.h"
typedef struct {
in_device_t in_dev;
device_t *device;
int devid;
} devmap_t;
@ -110,12 +110,17 @@ in_evdev_button_event (button_t *button, void *_dm)
static void
device_add (device_t *dev)
{
const char *name = dev->name;
// prefer device unique string if available, otherwise fall back to
// the physical path
const char *id = dev->uniq;
if (!id || !*id) {
id = dev->phys;
}
devmap_t *dm = PR_RESNEW (devmap);
dm->in_dev.driverid = evdev_driver_handle;
dm->in_dev.device = dev;
dm->in_dev.name = dev->name;
dm->in_dev.path = dev->phys;
dm->devid = IN_AddDevice (&dm->in_dev);
dm->device = dev;
dm->devid = IN_AddDevice (evdev_driver_handle, dev, name, id);
dev->data = dm;
dev->axis_event = in_evdev_axis_event;
@ -142,9 +147,8 @@ device_remove (device_t *dev)
//Sys_Printf ("in_evdev: remove %s\n", dev->path);
for (unsigned i = 0; i < devmap._size; i++) {
devmap_t *dm = PR_RESGET (devmap, ~i);
if (dm->in_dev.device == dev) {
if (dm->device == dev) {
IN_RemoveDevice (dm->devid);
memset (dm, 0, sizeof (*dm));
PR_RESFREE (devmap, dm);
break;
}
@ -164,11 +168,52 @@ in_evdev_clear_states (void *data)
{
}
static void
in_evdev_axis_info (void *data, void *device, in_axisinfo_t *axes,
int *numaxes)
{
device_t *dev = device;
if (!axes) {
*numaxes = dev->num_axes;
return;
}
if (*numaxes > dev->num_axes) {
*numaxes = dev->num_axes;
}
for (int i = 0; i < *numaxes; i++) {
axes[i].axis = dev->axes[i].num;
axes[i].value = dev->axes[i].value;
axes[i].min = dev->axes[i].min;
axes[i].max = dev->axes[i].max;
}
}
static void
in_evdev_button_info (void *data, void *device, in_buttoninfo_t *buttons,
int *numbuttons)
{
device_t *dev = device;
if (!buttons) {
*numbuttons = dev->num_buttons;
return;
}
if (*numbuttons > dev->num_buttons) {
*numbuttons = dev->num_buttons;
}
for (int i = 0; i < *numbuttons; i++) {
buttons[i].button = dev->buttons[i].num;
buttons[i].state = dev->buttons[i].state;
}
}
static in_driver_t in_evdev_driver = {
.init = in_evdev_init,
.shutdown = in_evdev_shutdown,
.process_events = in_evdev_process_events,
.clear_states = in_evdev_clear_states,
.axis_info = in_evdev_axis_info,
.button_info = in_evdev_button_info,
};
static void __attribute__((constructor))