mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-02-17 01:11:45 +00:00
[input] Rework device registration
And provide functions for collecting axis and button information from a device id.
This commit is contained in:
parent
70812b3c49
commit
cc730c90b4
4 changed files with 192 additions and 22 deletions
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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))
|
||||
|
|
Loading…
Reference in a new issue