Lines Matching +full:- +full:state

1 /*-
3 * Copyright (c) 2015-2016 Vladimir Kondratyev <wulf@FreeBSD.org>
50 #define debugf(state, fmt, args...) printf("uinput: " fmt "\n", ##args) argument
52 #define debugf(state, fmt, args...) argument
57 #define UINPUT_LOCK(state) sx_xlock(&(state)->ucs_lock) argument
58 #define UINPUT_UNLOCK(state) sx_unlock(&(state)->ucs_lock) argument
59 #define UINPUT_LOCK_ASSERT(state) sx_assert(&(state)->ucs_lock, SA_LOCKED) argument
60 #define UINPUT_EMPTYQ(state) \ argument
61 ((state)->ucs_buffer_head == (state)->ucs_buffer_tail)
159 struct uinput_cdev_state *state = evdev_get_softc(evdev); in uinput_ev_event() local
164 UINPUT_LOCK(state); in uinput_ev_event()
165 if (state->ucs_state == UINPUT_RUNNING) { in uinput_ev_event()
166 uinput_enqueue_event(state, type, code, value); in uinput_ev_event()
167 uinput_notify(state); in uinput_ev_event()
169 UINPUT_UNLOCK(state); in uinput_ev_event()
173 uinput_enqueue_event(struct uinput_cdev_state *state, uint16_t type, in uinput_enqueue_event() argument
178 UINPUT_LOCK_ASSERT(state); in uinput_enqueue_event()
180 head = state->ucs_buffer_head; in uinput_enqueue_event()
181 tail = (state->ucs_buffer_tail + 1) % UINPUT_BUFFER_SIZE; in uinput_enqueue_event()
183 microtime(&state->ucs_buffer[tail].time); in uinput_enqueue_event()
184 state->ucs_buffer[tail].type = type; in uinput_enqueue_event()
185 state->ucs_buffer[tail].code = code; in uinput_enqueue_event()
186 state->ucs_buffer[tail].value = value; in uinput_enqueue_event()
187 state->ucs_buffer_tail = tail; in uinput_enqueue_event()
191 debugf(state, "state %p: buffer overflow", state); in uinput_enqueue_event()
194 state->ucs_buffer_head = head; in uinput_enqueue_event()
201 struct uinput_cdev_state *state; in uinput_open() local
203 state = malloc(sizeof(struct uinput_cdev_state), M_EVDEV, in uinput_open()
205 state->ucs_evdev = evdev_alloc(); in uinput_open()
207 sx_init(&state->ucs_lock, "uinput"); in uinput_open()
208 knlist_init(&state->ucs_selp.si_note, &state->ucs_lock, uinput_knllock, in uinput_open()
211 devfs_set_cdevpriv(state, uinput_dtor); in uinput_open()
218 struct uinput_cdev_state *state = (struct uinput_cdev_state *)data; in uinput_dtor() local
220 evdev_free(state->ucs_evdev); in uinput_dtor()
222 knlist_clear(&state->ucs_selp.si_note, 0); in uinput_dtor()
223 seldrain(&state->ucs_selp); in uinput_dtor()
224 knlist_destroy(&state->ucs_selp.si_note); in uinput_dtor()
225 sx_destroy(&state->ucs_lock); in uinput_dtor()
232 struct uinput_cdev_state *state; in uinput_read() local
236 ret = devfs_get_cdevpriv((void **)&state); in uinput_read()
240 debugf(state, "read %zd bytes by thread %d", uio->uio_resid, in uinput_read()
241 uio->uio_td->td_tid); in uinput_read()
243 /* Zero-sized reads are allowed for error checking */ in uinput_read()
244 if (uio->uio_resid != 0 && uio->uio_resid < sizeof(struct input_event)) in uinput_read()
247 remaining = uio->uio_resid / sizeof(struct input_event); in uinput_read()
249 UINPUT_LOCK(state); in uinput_read()
251 if (state->ucs_state != UINPUT_RUNNING) in uinput_read()
254 if (ret == 0 && UINPUT_EMPTYQ(state)) { in uinput_read()
259 state->ucs_blocked = true; in uinput_read()
260 ret = sx_sleep(state, &state->ucs_lock, in uinput_read()
266 while (ret == 0 && !UINPUT_EMPTYQ(state) && remaining > 0) { in uinput_read()
267 event = &state->ucs_buffer[state->ucs_buffer_head]; in uinput_read()
268 state->ucs_buffer_head = (state->ucs_buffer_head + 1) % in uinput_read()
270 remaining--; in uinput_read()
274 UINPUT_UNLOCK(state); in uinput_read()
282 struct uinput_cdev_state *state; in uinput_write() local
287 ret = devfs_get_cdevpriv((void **)&state); in uinput_write()
291 debugf(state, "write %zd bytes by thread %d", uio->uio_resid, in uinput_write()
292 uio->uio_td->td_tid); in uinput_write()
294 UINPUT_LOCK(state); in uinput_write()
296 if (state->ucs_state != UINPUT_RUNNING) { in uinput_write()
298 if (uio->uio_resid != sizeof(struct uinput_user_dev)) { in uinput_write()
299 debugf(state, "write size not multiple of " in uinput_write()
306 uinput_setup_provider(state, &userdev); in uinput_write()
310 if (uio->uio_resid % sizeof(struct input_event) != 0) { in uinput_write()
311 debugf(state, "write size not multiple of " in uinput_write()
316 while (ret == 0 && uio->uio_resid > 0) { in uinput_write()
318 ret = evdev_push_event(state->ucs_evdev, event.type, in uinput_write()
323 UINPUT_UNLOCK(state); in uinput_write()
329 uinput_setup_dev(struct uinput_cdev_state *state, struct input_id *id, in uinput_setup_dev() argument
336 evdev_set_name(state->ucs_evdev, name); in uinput_setup_dev()
337 evdev_set_id(state->ucs_evdev, id->bustype, id->vendor, id->product, in uinput_setup_dev()
338 id->version); in uinput_setup_dev()
339 state->ucs_state = UINPUT_CONFIGURED; in uinput_setup_dev()
345 uinput_setup_provider(struct uinput_cdev_state *state, in uinput_setup_provider() argument
351 debugf(state, "setup_provider called, udev=%p", udev); in uinput_setup_provider()
353 ret = uinput_setup_dev(state, &udev->id, udev->name, in uinput_setup_provider()
354 udev->ff_effects_max); in uinput_setup_provider()
360 if (!bit_test(state->ucs_evdev->ev_abs_flags, i)) in uinput_setup_provider()
363 absinfo.minimum = udev->absmin[i]; in uinput_setup_provider()
364 absinfo.maximum = udev->absmax[i]; in uinput_setup_provider()
365 absinfo.fuzz = udev->absfuzz[i]; in uinput_setup_provider()
366 absinfo.flat = udev->absflat[i]; in uinput_setup_provider()
367 evdev_set_absinfo(state->ucs_evdev, i, &absinfo); in uinput_setup_provider()
376 struct uinput_cdev_state *state; in uinput_poll() local
379 if (devfs_get_cdevpriv((void **)&state) != 0) in uinput_poll()
382 debugf(state, "poll by thread %d", td->td_tid); in uinput_poll()
389 UINPUT_LOCK(state); in uinput_poll()
390 if (!UINPUT_EMPTYQ(state)) in uinput_poll()
393 state->ucs_selected = true; in uinput_poll()
394 selrecord(td, &state->ucs_selp); in uinput_poll()
396 UINPUT_UNLOCK(state); in uinput_poll()
405 struct uinput_cdev_state *state; in uinput_kqfilter() local
408 ret = devfs_get_cdevpriv((void **)&state); in uinput_kqfilter()
412 switch(kn->kn_filter) { in uinput_kqfilter()
414 kn->kn_fop = &uinput_filterops; in uinput_kqfilter()
419 kn->kn_hook = (caddr_t)state; in uinput_kqfilter()
421 knlist_add(&state->ucs_selp.si_note, kn, 0); in uinput_kqfilter()
428 struct uinput_cdev_state *state; in uinput_kqread() local
431 state = (struct uinput_cdev_state *)kn->kn_hook; in uinput_kqread()
433 UINPUT_LOCK_ASSERT(state); in uinput_kqread()
435 ret = !UINPUT_EMPTYQ(state); in uinput_kqread()
442 struct uinput_cdev_state *state; in uinput_kqdetach() local
444 state = (struct uinput_cdev_state *)kn->kn_hook; in uinput_kqdetach()
445 knlist_remove(&state->ucs_selp.si_note, kn, 0); in uinput_kqdetach()
449 uinput_notify(struct uinput_cdev_state *state) in uinput_notify() argument
452 UINPUT_LOCK_ASSERT(state); in uinput_notify()
454 if (state->ucs_blocked) { in uinput_notify()
455 state->ucs_blocked = false; in uinput_notify()
456 wakeup(state); in uinput_notify()
458 if (state->ucs_selected) { in uinput_notify()
459 state->ucs_selected = false; in uinput_notify()
460 selwakeup(&state->ucs_selp); in uinput_notify()
462 KNOTE_LOCKED(&state->ucs_selp.si_note, 0); in uinput_notify()
466 uinput_ioctl_sub(struct uinput_cdev_state *state, u_long cmd, caddr_t data) in uinput_ioctl_sub() argument
473 UINPUT_LOCK_ASSERT(state); in uinput_ioctl_sub()
481 if (state->ucs_state != UINPUT_RUNNING) in uinput_ioctl_sub()
485 snprintf(data, len, "event%d", state->ucs_evdev->ev_unit); in uinput_ioctl_sub()
491 if (state->ucs_state != UINPUT_CONFIGURED) in uinput_ioctl_sub()
494 evdev_set_methods(state->ucs_evdev, state, &uinput_ev_methods); in uinput_ioctl_sub()
495 evdev_set_flag(state->ucs_evdev, EVDEV_FLAG_SOFTREPEAT); in uinput_ioctl_sub()
496 evdev_set_flag(state->ucs_evdev, EVDEV_FLAG_MT_KEEPID); in uinput_ioctl_sub()
497 ret = evdev_register(state->ucs_evdev); in uinput_ioctl_sub()
499 state->ucs_state = UINPUT_RUNNING; in uinput_ioctl_sub()
503 if (state->ucs_state != UINPUT_RUNNING) in uinput_ioctl_sub()
506 evdev_unregister(state->ucs_evdev); in uinput_ioctl_sub()
507 bzero(state->ucs_evdev, sizeof(struct evdev_dev)); in uinput_ioctl_sub()
508 state->ucs_state = UINPUT_NEW; in uinput_ioctl_sub()
512 if (state->ucs_state == UINPUT_RUNNING) in uinput_ioctl_sub()
516 return (uinput_setup_dev(state, &us->id, us->name, in uinput_ioctl_sub()
517 us->ff_effects_max)); in uinput_ioctl_sub()
520 if (state->ucs_state == UINPUT_RUNNING) in uinput_ioctl_sub()
524 if (uabs->code > ABS_MAX) in uinput_ioctl_sub()
527 evdev_set_abs_bit(state->ucs_evdev, uabs->code); in uinput_ioctl_sub()
528 evdev_set_absinfo(state->ucs_evdev, uabs->code, in uinput_ioctl_sub()
529 &uabs->absinfo); in uinput_ioctl_sub()
533 if (state->ucs_state == UINPUT_RUNNING || in uinput_ioctl_sub()
536 evdev_support_event(state->ucs_evdev, intdata); in uinput_ioctl_sub()
540 if (state->ucs_state == UINPUT_RUNNING || in uinput_ioctl_sub()
543 evdev_support_key(state->ucs_evdev, intdata); in uinput_ioctl_sub()
547 if (state->ucs_state == UINPUT_RUNNING || in uinput_ioctl_sub()
550 evdev_support_rel(state->ucs_evdev, intdata); in uinput_ioctl_sub()
554 if (state->ucs_state == UINPUT_RUNNING || in uinput_ioctl_sub()
557 evdev_set_abs_bit(state->ucs_evdev, intdata); in uinput_ioctl_sub()
561 if (state->ucs_state == UINPUT_RUNNING || in uinput_ioctl_sub()
564 evdev_support_msc(state->ucs_evdev, intdata); in uinput_ioctl_sub()
568 if (state->ucs_state == UINPUT_RUNNING || in uinput_ioctl_sub()
571 evdev_support_led(state->ucs_evdev, intdata); in uinput_ioctl_sub()
575 if (state->ucs_state == UINPUT_RUNNING || in uinput_ioctl_sub()
578 evdev_support_snd(state->ucs_evdev, intdata); in uinput_ioctl_sub()
582 if (state->ucs_state == UINPUT_RUNNING || in uinput_ioctl_sub()
589 if (state->ucs_state == UINPUT_RUNNING) in uinput_ioctl_sub()
597 evdev_set_phys(state->ucs_evdev, buf); in uinput_ioctl_sub()
601 if (state->ucs_state == UINPUT_RUNNING) in uinput_ioctl_sub()
606 evdev_set_serial(state->ucs_evdev, buf); in uinput_ioctl_sub()
610 if (state->ucs_state == UINPUT_RUNNING || in uinput_ioctl_sub()
613 evdev_support_sw(state->ucs_evdev, intdata); in uinput_ioctl_sub()
617 if (state->ucs_state == UINPUT_RUNNING || in uinput_ioctl_sub()
620 evdev_support_prop(state->ucs_evdev, intdata); in uinput_ioctl_sub()
627 if (state->ucs_state == UINPUT_RUNNING) in uinput_ioctl_sub()
644 struct uinput_cdev_state *state; in uinput_ioctl() local
647 ret = devfs_get_cdevpriv((void **)&state); in uinput_ioctl()
651 debugf(state, "ioctl called: cmd=0x%08lx, data=%p", cmd, data); in uinput_ioctl()
653 UINPUT_LOCK(state); in uinput_ioctl()
654 ret = uinput_ioctl_sub(state, cmd, data); in uinput_ioctl()
655 UINPUT_UNLOCK(state); in uinput_ioctl()