summaryrefslogtreecommitdiff
path: root/sys/dev/evdev
diff options
context:
space:
mode:
authorVladimir Kondratyev <wulf@FreeBSD.org>2020-03-29 23:00:33 +0000
committerVladimir Kondratyev <wulf@FreeBSD.org>2020-03-29 23:00:33 +0000
commit80ddbddfd70fbf6e99d9be0d0572e9206f8ec139 (patch)
treeb95cfd14ba9cf1fdc67c8f80be6380889ba5ebb9 /sys/dev/evdev
parentc3e9752ea1360595e63ef5f4219faae51ed5bef2 (diff)
Notes
Diffstat (limited to 'sys/dev/evdev')
-rw-r--r--sys/dev/evdev/cdev.c80
1 files changed, 68 insertions, 12 deletions
diff --git a/sys/dev/evdev/cdev.c b/sys/dev/evdev/cdev.c
index 615a70bafc79..f945101932c7 100644
--- a/sys/dev/evdev/cdev.c
+++ b/sys/dev/evdev/cdev.c
@@ -47,6 +47,18 @@
#include <dev/evdev/evdev_private.h>
#include <dev/evdev/input.h>
+#ifdef COMPAT_FREEBSD32
+#include <sys/mount.h>
+#include <sys/sysent.h>
+#include <compat/freebsd32/freebsd32.h>
+struct input_event32 {
+ struct timeval32 time;
+ uint16_t type;
+ uint16_t code;
+ int32_t value;
+};
+#endif
+
#ifdef EVDEV_DEBUG
#define debugf(client, fmt, args...) printf("evdev cdev: "fmt"\n", ##args)
#else
@@ -161,7 +173,14 @@ static int
evdev_read(struct cdev *dev, struct uio *uio, int ioflag)
{
struct evdev_client *client;
- struct input_event event;
+ union {
+ struct input_event t;
+#ifdef COMPAT_FREEBSD32
+ struct input_event32 t32;
+#endif
+ } event;
+ struct input_event *head;
+ size_t evsize;
int ret = 0;
int remaining;
@@ -175,11 +194,18 @@ evdev_read(struct cdev *dev, struct uio *uio, int ioflag)
if (client->ec_revoked)
return (ENODEV);
+#ifdef COMPAT_FREEBSD32
+ if (SV_CURPROC_FLAG(SV_ILP32))
+ evsize = sizeof(struct input_event32);
+ else
+#endif
+ evsize = sizeof(struct input_event);
+
/* Zero-sized reads are allowed for error checking */
- if (uio->uio_resid != 0 && uio->uio_resid < sizeof(struct input_event))
+ if (uio->uio_resid != 0 && uio->uio_resid < evsize)
return (EINVAL);
- remaining = uio->uio_resid / sizeof(struct input_event);
+ remaining = uio->uio_resid / evsize;
EVDEV_CLIENT_LOCKQ(client);
@@ -196,14 +222,24 @@ evdev_read(struct cdev *dev, struct uio *uio, int ioflag)
}
while (ret == 0 && !EVDEV_CLIENT_EMPTYQ(client) && remaining > 0) {
- memcpy(&event, &client->ec_buffer[client->ec_buffer_head],
- sizeof(struct input_event));
+ head = client->ec_buffer + client->ec_buffer_head;
+#ifdef COMPAT_FREEBSD32
+ if (SV_CURPROC_FLAG(SV_ILP32)) {
+ bzero(&event.t32, sizeof(struct input_event32));
+ TV_CP(*head, event.t32, time);
+ CP(*head, event.t32, type);
+ CP(*head, event.t32, code);
+ CP(*head, event.t32, value);
+ } else
+#endif
+ bcopy(head, &event.t, evsize);
+
client->ec_buffer_head =
(client->ec_buffer_head + 1) % client->ec_buffer_size;
remaining--;
EVDEV_CLIENT_UNLOCKQ(client);
- ret = uiomove(&event, sizeof(struct input_event), uio);
+ ret = uiomove(&event, evsize, uio);
EVDEV_CLIENT_LOCKQ(client);
}
@@ -217,7 +253,13 @@ evdev_write(struct cdev *dev, struct uio *uio, int ioflag)
{
struct evdev_dev *evdev = dev->si_drv1;
struct evdev_client *client;
- struct input_event event;
+ union {
+ struct input_event t;
+#ifdef COMPAT_FREEBSD32
+ struct input_event32 t32;
+#endif
+ } event;
+ size_t evsize;
int ret = 0;
ret = devfs_get_cdevpriv((void **)&client);
@@ -230,16 +272,30 @@ evdev_write(struct cdev *dev, struct uio *uio, int ioflag)
if (client->ec_revoked || evdev == NULL)
return (ENODEV);
- if (uio->uio_resid % sizeof(struct input_event) != 0) {
+#ifdef COMPAT_FREEBSD32
+ if (SV_CURPROC_FLAG(SV_ILP32))
+ evsize = sizeof(struct input_event32);
+ else
+#endif
+ evsize = sizeof(struct input_event);
+
+ if (uio->uio_resid % evsize != 0) {
debugf(client, "write size not multiple of input_event size");
return (EINVAL);
}
while (uio->uio_resid > 0 && ret == 0) {
- ret = uiomove(&event, sizeof(struct input_event), uio);
- if (ret == 0)
- ret = evdev_inject_event(evdev, event.type, event.code,
- event.value);
+ ret = uiomove(&event, evsize, uio);
+ if (ret == 0) {
+#ifdef COMPAT_FREEBSD32
+ if (SV_CURPROC_FLAG(SV_ILP32))
+ ret = evdev_inject_event(evdev, event.t32.type,
+ event.t32.code, event.t32.value);
+ else
+#endif
+ ret = evdev_inject_event(evdev, event.t.type,
+ event.t.code, event.t.value);
+ }
}
return (ret);