Page MenuHomeFreeBSD

D18694.id52492.diff
No OneTemporary

D18694.id52492.diff

Index: sbin/sysctl/sysctl.c
===================================================================
--- sbin/sysctl/sysctl.c
+++ sbin/sysctl/sysctl.c
@@ -49,6 +49,7 @@
#include <sys/stat.h>
#include <sys/sysctl.h>
#include <sys/vmmeter.h>
+#include <dev/evdev/input.h>
#ifdef __amd64__
#include <sys/efi.h>
@@ -680,6 +681,21 @@
return (0);
}
+static int
+S_input_id(size_t l2, void *p)
+{
+ struct input_id *id = (struct input_id*)p;
+
+ if (l2 != sizeof(*id)) {
+ warnx("S_input_id %zu != %zu", l2, sizeof(*id));
+ return (1);
+ }
+
+ printf("{ bustype = 0x%04x, vendor = 0x%04x, product = 0x%04x, version = 0x%04x }",
+ id->bustype, id->vendor, id->product, id->version);
+ return (0);
+}
+
#ifdef __amd64__
static int
S_efi_map(size_t l2, void *p)
@@ -983,6 +999,8 @@
func = S_loadavg;
else if (strcmp(fmt, "S,vmtotal") == 0)
func = S_vmtotal;
+ else if (strcmp(fmt, "S,input_id") == 0)
+ func = S_input_id;
#ifdef __amd64__
else if (strcmp(fmt, "S,efi_map_header") == 0)
func = S_efi_map;
Index: sys/dev/evdev/evdev.c
===================================================================
--- sys/dev/evdev/evdev.c
+++ sys/dev/evdev/evdev.c
@@ -39,6 +39,8 @@
#include <sys/proc.h>
#include <sys/sysctl.h>
#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/sbuf.h>
#include <dev/evdev/evdev.h>
#include <dev/evdev/evdev_private.h>
@@ -76,6 +78,8 @@
"bit2 - mouse hardware, bit3 - keyboard hardware");
SYSCTL_INT(_kern_evdev, OID_AUTO, sysmouse_t_axis, CTLFLAG_RW,
&evdev_sysmouse_t_axis, 0, "Extract T-axis from 0-none, 1-ums, 2-psm");
+SYSCTL_NODE(_dev, OID_AUTO, input, CTLFLAG_RD, 0,
+ "Evdev input devices");
#endif
static void evdev_start_repeat(struct evdev_dev *, uint16_t);
@@ -196,6 +200,145 @@
return (size);
}
+static void
+evdev_notify_addq(const char *type, struct evdev_dev *evdev)
+{
+ struct sbuf *sb;
+
+ sb = sbuf_new_auto();
+ sbuf_printf(sb,
+ "cdev=%s "
+ "unit=%d "
+ "name=\"%s\" "
+ "shortname=%s "
+ "bustype=0x%04x "
+ "vendor=0x%04x "
+ "product=0x%04x "
+ "version=0x%04x ",
+ evdev->ev_cdev->si_name,
+ evdev->ev_unit,
+ evdev->ev_name,
+ evdev->ev_shortname,
+ evdev->ev_id.bustype,
+ evdev->ev_id.vendor,
+ evdev->ev_id.product,
+ evdev->ev_id.version
+ );
+ sbuf_finish(sb);
+ devctl_notify("EVDEV", "DEVICE", type, sbuf_data(sb));
+ sbuf_delete(sb);
+}
+
+static int
+evdev_sysctl_handler_name(SYSCTL_HANDLER_ARGS)
+{
+ struct evdev_dev *evdev = arg1;
+ int err;
+
+ EVDEV_LOCK(evdev);
+ err = SYSCTL_OUT(req, evdev->ev_name, strlen(evdev->ev_name));
+ EVDEV_UNLOCK(evdev);
+
+ return (err);
+}
+
+static int
+evdev_sysctl_handler_shortname(SYSCTL_HANDLER_ARGS)
+{
+ struct evdev_dev *evdev = arg1;
+ int err;
+
+ EVDEV_LOCK(evdev);
+ err = SYSCTL_OUT(req, evdev->ev_shortname, strlen(evdev->ev_shortname));
+ EVDEV_UNLOCK(evdev);
+
+ return (err);
+}
+
+static int
+evdev_sysctl_handler_serial(SYSCTL_HANDLER_ARGS)
+{
+ struct evdev_dev *evdev = arg1;
+ int err;
+
+ EVDEV_LOCK(evdev);
+ err = SYSCTL_OUT(req, evdev->ev_serial, strlen(evdev->ev_serial));
+ EVDEV_UNLOCK(evdev);
+
+ return (err);
+}
+
+static int
+evdev_sysctl_handler_input_id(SYSCTL_HANDLER_ARGS)
+{
+ struct evdev_dev *evdev = arg1;
+ int err;
+
+ EVDEV_LOCK(evdev);
+ err = SYSCTL_OUT(req, &evdev->ev_id, sizeof(struct input_id));
+ EVDEV_UNLOCK(evdev);
+
+ return (err);
+}
+
+static int
+evdev_sysctl_handler_bits(SYSCTL_HANDLER_ARGS)
+{
+ struct evdev_dev *evdev = arg1;
+ unsigned long *bitmap;
+ int err, limit;
+
+ EVDEV_LOCK(evdev);
+ switch (arg2) {
+ case 0:
+ bitmap = evdev->ev_type_flags;
+ limit = EV_CNT;
+ break;
+ case EV_KEY:
+ bitmap = evdev->ev_key_flags;
+ limit = KEY_CNT;
+ break;
+ case EV_REL:
+ bitmap = evdev->ev_rel_flags;
+ limit = REL_CNT;
+ break;
+ case EV_ABS:
+ bitmap = evdev->ev_abs_flags;
+ limit = ABS_CNT;
+ break;
+ case EV_MSC:
+ bitmap = evdev->ev_msc_flags;
+ limit = MSC_CNT;
+ break;
+ case EV_LED:
+ bitmap = evdev->ev_led_flags;
+ limit = LED_CNT;
+ break;
+ case EV_SND:
+ bitmap = evdev->ev_snd_flags;
+ limit = SND_CNT;
+ break;
+ case EV_SW:
+ bitmap = evdev->ev_sw_flags;
+ limit = SW_CNT;
+ break;
+ case EV_MAX:
+ bitmap = evdev->ev_prop_flags;
+ limit = INPUT_PROP_CNT;
+ break;
+ case EV_FF:
+ /*
+ * We don't support EV_FF now.
+ */
+ default:
+ return (ENOTTY);
+ }
+ err = SYSCTL_OUT(req, bitmap, bitstr_size(limit));
+ EVDEV_UNLOCK(evdev);
+
+ return (err);
+}
+
static int
evdev_register_common(struct evdev_dev *evdev)
{
@@ -235,6 +378,96 @@
/* Create char device node */
ret = evdev_cdev_create(evdev);
+ if (ret != 0)
+ goto bail_out;
+
+ /* Create sysctls (for device enumeration without /dev/input access rights) */
+ snprintf(evdev->ev_unit_str, sizeof(evdev->ev_unit_str), "%d", evdev->ev_unit);
+ sysctl_ctx_init(&evdev->ev_sysctl_ctx);
+ evdev->ev_sysctl_tree = SYSCTL_ADD_NODE_WITH_LABEL(&evdev->ev_sysctl_ctx,
+ SYSCTL_STATIC_CHILDREN(_dev_input), OID_AUTO,
+ evdev->ev_unit_str, CTLFLAG_RD, NULL, "", "device index");
+
+ SYSCTL_ADD_PROC(&evdev->ev_sysctl_ctx,
+ SYSCTL_CHILDREN(evdev->ev_sysctl_tree), OID_AUTO, "name",
+ CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE,
+ evdev, 0, evdev_sysctl_handler_name,
+ "", "Input device name");
+
+ SYSCTL_ADD_PROC(&evdev->ev_sysctl_ctx,
+ SYSCTL_CHILDREN(evdev->ev_sysctl_tree), OID_AUTO, "shortname",
+ CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE,
+ evdev, 0, evdev_sysctl_handler_shortname,
+ "", "Input device short name");
+
+ SYSCTL_ADD_PROC(&evdev->ev_sysctl_ctx,
+ SYSCTL_CHILDREN(evdev->ev_sysctl_tree), OID_AUTO, "serial",
+ CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE,
+ evdev, 0, evdev_sysctl_handler_serial,
+ "", "Input device serial number");
+
+ SYSCTL_ADD_PROC(&evdev->ev_sysctl_ctx,
+ SYSCTL_CHILDREN(evdev->ev_sysctl_tree), OID_AUTO, "input_id",
+ CTLTYPE_STRUCT | CTLFLAG_RD | CTLFLAG_MPSAFE,
+ evdev, 0, evdev_sysctl_handler_input_id,
+ "S,input_id", "Input device identification");
+
+ SYSCTL_ADD_PROC(&evdev->ev_sysctl_ctx,
+ SYSCTL_CHILDREN(evdev->ev_sysctl_tree), OID_AUTO, "type_flags",
+ CTLTYPE_STRUCT | CTLFLAG_RD | CTLFLAG_MPSAFE,
+ evdev, 0, evdev_sysctl_handler_bits,
+ "", "Input device supported events types");
+
+ SYSCTL_ADD_PROC(&evdev->ev_sysctl_ctx,
+ SYSCTL_CHILDREN(evdev->ev_sysctl_tree), OID_AUTO, "key_flags",
+ CTLTYPE_STRUCT | CTLFLAG_RD | CTLFLAG_MPSAFE,
+ evdev, EV_KEY, evdev_sysctl_handler_bits,
+ "", "Input device supported keys");
+
+ SYSCTL_ADD_PROC(&evdev->ev_sysctl_ctx,
+ SYSCTL_CHILDREN(evdev->ev_sysctl_tree), OID_AUTO, "rel_flags",
+ CTLTYPE_STRUCT | CTLFLAG_RD | CTLFLAG_MPSAFE,
+ evdev, EV_REL, evdev_sysctl_handler_bits,
+ "", "Input device supported relative events");
+
+ SYSCTL_ADD_PROC(&evdev->ev_sysctl_ctx,
+ SYSCTL_CHILDREN(evdev->ev_sysctl_tree), OID_AUTO, "abs_flags",
+ CTLTYPE_STRUCT | CTLFLAG_RD | CTLFLAG_MPSAFE,
+ evdev, EV_ABS, evdev_sysctl_handler_bits,
+ "", "Input device supported absolute events");
+
+ SYSCTL_ADD_PROC(&evdev->ev_sysctl_ctx,
+ SYSCTL_CHILDREN(evdev->ev_sysctl_tree), OID_AUTO, "msc_flags",
+ CTLTYPE_STRUCT | CTLFLAG_RD | CTLFLAG_MPSAFE,
+ evdev, EV_MSC, evdev_sysctl_handler_bits,
+ "", "Input device supported miscellaneous events");
+
+ SYSCTL_ADD_PROC(&evdev->ev_sysctl_ctx,
+ SYSCTL_CHILDREN(evdev->ev_sysctl_tree), OID_AUTO, "led_flags",
+ CTLTYPE_STRUCT | CTLFLAG_RD | CTLFLAG_MPSAFE,
+ evdev, EV_LED, evdev_sysctl_handler_bits,
+ "", "Input device supported LED events");
+
+ SYSCTL_ADD_PROC(&evdev->ev_sysctl_ctx,
+ SYSCTL_CHILDREN(evdev->ev_sysctl_tree), OID_AUTO, "snd_flags",
+ CTLTYPE_STRUCT | CTLFLAG_RD | CTLFLAG_MPSAFE,
+ evdev, EV_SND, evdev_sysctl_handler_bits,
+ "", "Input device supported sound events");
+
+ SYSCTL_ADD_PROC(&evdev->ev_sysctl_ctx,
+ SYSCTL_CHILDREN(evdev->ev_sysctl_tree), OID_AUTO, "sw_flags",
+ CTLTYPE_STRUCT | CTLFLAG_RD | CTLFLAG_MPSAFE,
+ evdev, EV_SW, evdev_sysctl_handler_bits,
+ "", "Input device supported switch events");
+
+ SYSCTL_ADD_PROC(&evdev->ev_sysctl_ctx,
+ SYSCTL_CHILDREN(evdev->ev_sysctl_tree), OID_AUTO, "props",
+ CTLTYPE_STRUCT | CTLFLAG_RD | CTLFLAG_MPSAFE,
+ evdev, EV_MAX, evdev_sysctl_handler_bits,
+ "", "Input device properties");
+
+ /* Notify userspace with device details via devctl */
+ evdev_notify_addq("ATTACH", evdev);
bail_out:
return (ret);
}
@@ -269,6 +502,7 @@
{
struct evdev_client *client;
int ret;
+ evdev_notify_addq("DETACH", evdev);
debugf(evdev, "%s: unregistered evdev provider: %s\n",
evdev->ev_shortname, evdev->ev_name);
@@ -282,6 +516,7 @@
evdev_notify_event(client);
EVDEV_CLIENT_UNLOCKQ(client);
}
+ sysctl_ctx_free(&evdev->ev_sysctl_ctx);
EVDEV_UNLOCK(evdev);
/* destroy_dev can sleep so release lock */
Index: sys/dev/evdev/evdev_private.h
===================================================================
--- sys/dev/evdev/evdev_private.h
+++ sys/dev/evdev/evdev_private.h
@@ -35,6 +35,7 @@
#include <sys/malloc.h>
#include <sys/queue.h>
#include <sys/selinfo.h>
+#include <sys/sysctl.h>
#include <dev/evdev/evdev.h>
#include <dev/evdev/input.h>
@@ -132,6 +133,11 @@
const struct evdev_methods * ev_methods;
void * ev_softc;
+ /* Sysctl: */
+ char ev_unit_str[8];
+ struct sysctl_ctx_list ev_sysctl_ctx;
+ struct sysctl_oid * ev_sysctl_tree;
+
LIST_ENTRY(evdev_dev) ev_link;
LIST_HEAD(, evdev_client) ev_clients;
};

File Metadata

Mime Type
text/plain
Expires
Sun, Nov 23, 12:51 PM (2 h, 58 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
26014228
Default Alt Text
D18694.id52492.diff (9 KB)

Event Timeline