Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/evdev/evdev.c
Context not available. | |||||
#include <sys/proc.h> | #include <sys/proc.h> | ||||
#include <sys/sysctl.h> | #include <sys/sysctl.h> | ||||
#include <sys/systm.h> | #include <sys/systm.h> | ||||
#include <sys/bus.h> | |||||
#include <sys/sbuf.h> | |||||
wulf: style(9) requires #includes to be sorted alphabetically | |||||
#include <dev/evdev/evdev.h> | #include <dev/evdev/evdev.h> | ||||
#include <dev/evdev/evdev_private.h> | #include <dev/evdev/evdev_private.h> | ||||
Context not available. | |||||
"bit2 - mouse hardware, bit3 - keyboard hardware"); | "bit2 - mouse hardware, bit3 - keyboard hardware"); | ||||
SYSCTL_INT(_kern_evdev, OID_AUTO, sysmouse_t_axis, CTLFLAG_RW, | 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"); | &evdev_sysmouse_t_axis, 0, "Extract T-axis from 0-none, 1-ums, 2-psm"); | ||||
SYSCTL_NODE(_dev, OID_AUTO, input, CTLFLAG_RD, 0, | |||||
wulfUnsubmitted Done Inline ActionsI am not sure if dev.input is appropriate path to evdev sysctl interface. Most of dev. citizens are device(9) instances rather than cdevs. wulf: I am not sure if dev.input is appropriate path to evdev sysctl interface. Most of dev. citizens… | |||||
"Evdev input devices"); | |||||
#endif | #endif | ||||
static void evdev_start_repeat(struct evdev_dev *, uint16_t); | static void evdev_start_repeat(struct evdev_dev *, uint16_t); | ||||
Context not available. | |||||
return (size); | 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 | static int | ||||
evdev_register_common(struct evdev_dev *evdev) | evdev_register_common(struct evdev_dev *evdev) | ||||
{ | { | ||||
Context not available. | |||||
/* Create char device node */ | /* Create char device node */ | ||||
ret = evdev_cdev_create(evdev); | 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); | |||||
wulfUnsubmitted Done Inline ActionsPlease, place sysctl part in to separate routine wulf: Please, place sysctl part in to separate routine | |||||
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, | |||||
wulfUnsubmitted Done Inline ActionsSYSCTL_ADD_STRING is better here (and after). ev_name and other fields are read-only so it is not strictly necessary to protect them with lock. wulf: SYSCTL_ADD_STRING is better here (and after). ev_name and other fields are read-only so it is… | |||||
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", | |||||
wulfUnsubmitted Done Inline ActionsPlease, make sysctl names consistent with ioctl's. Change shortname -> phys, serial -> uniq, flags -> bits and so on. wulf: Please, make sysctl names consistent with ioctl's. Change shortname -> phys, serial -> uniq… | |||||
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: | bail_out: | ||||
return (ret); | return (ret); | ||||
} | } | ||||
Context not available. | |||||
{ | { | ||||
struct evdev_client *client; | struct evdev_client *client; | ||||
int ret; | int ret; | ||||
evdev_notify_addq("DETACH", evdev); | |||||
debugf(evdev, "%s: unregistered evdev provider: %s\n", | debugf(evdev, "%s: unregistered evdev provider: %s\n", | ||||
evdev->ev_shortname, evdev->ev_name); | evdev->ev_shortname, evdev->ev_name); | ||||
Context not available. | |||||
evdev_notify_event(client); | evdev_notify_event(client); | ||||
EVDEV_CLIENT_UNLOCKQ(client); | EVDEV_CLIENT_UNLOCKQ(client); | ||||
} | } | ||||
sysctl_ctx_free(&evdev->ev_sysctl_ctx); | |||||
EVDEV_UNLOCK(evdev); | EVDEV_UNLOCK(evdev); | ||||
/* destroy_dev can sleep so release lock */ | /* destroy_dev can sleep so release lock */ | ||||
Context not available. |
style(9) requires #includes to be sorted alphabetically