Lines Matching +full:coexist +full:- +full:support

1 /*-
3 * Copyright (c) 2015-2016 Vladimir Kondratyev <wulf@FreeBSD.org>
104 struct evdev_dev *evdev = dev->si_drv1; in evdev_open()
113 buffer_size = evdev->ev_report_size * DEF_RING_REPORTS; in evdev_open()
119 client->ec_buffer_size = buffer_size; in evdev_open()
120 client->ec_buffer_head = 0; in evdev_open()
121 client->ec_buffer_tail = 0; in evdev_open()
122 client->ec_buffer_ready = 0; in evdev_open()
124 client->ec_evdev = evdev; in evdev_open()
125 mtx_init(&client->ec_buffer_mtx, "evclient", "evdev", MTX_DEF); in evdev_open()
126 knlist_init_mtx(&client->ec_selp.si_note, &client->ec_buffer_mtx); in evdev_open()
132 if (dev->si_drv1 == NULL) in evdev_open()
141 client->ec_revoked = true; in evdev_open()
156 EVDEV_LIST_LOCK(client->ec_evdev); in evdev_dtor()
157 if (!client->ec_revoked) in evdev_dtor()
158 evdev_dispose_client(client->ec_evdev, client); in evdev_dtor()
159 EVDEV_LIST_UNLOCK(client->ec_evdev); in evdev_dtor()
161 if (client->ec_evdev->ev_lock_type != EV_LOCK_MTX) in evdev_dtor()
163 knlist_clear(&client->ec_selp.si_note, 0); in evdev_dtor()
164 seldrain(&client->ec_selp); in evdev_dtor()
165 knlist_destroy(&client->ec_selp.si_note); in evdev_dtor()
166 funsetown(&client->ec_sigio); in evdev_dtor()
167 mtx_destroy(&client->ec_buffer_mtx); in evdev_dtor()
190 debugf(client, "read %zd bytes by thread %d", uio->uio_resid, in evdev_read()
191 uio->uio_td->td_tid); in evdev_read()
193 if (client->ec_revoked) in evdev_read()
203 /* Zero-sized reads are allowed for error checking */ in evdev_read()
204 if (uio->uio_resid != 0 && uio->uio_resid < evsize) in evdev_read()
207 remaining = uio->uio_resid / evsize; in evdev_read()
216 client->ec_blocked = true; in evdev_read()
217 ret = mtx_sleep(client, &client->ec_buffer_mtx, in evdev_read()
219 if (ret == 0 && client->ec_revoked) in evdev_read()
226 head = client->ec_buffer + client->ec_buffer_head; in evdev_read()
238 client->ec_buffer_head = in evdev_read()
239 (client->ec_buffer_head + 1) % client->ec_buffer_size; in evdev_read()
240 remaining--; in evdev_read()
255 struct evdev_dev *evdev = dev->si_drv1; in evdev_write()
270 debugf(client, "write %zd bytes by thread %d", uio->uio_resid, in evdev_write()
271 uio->uio_td->td_tid); in evdev_write()
273 if (client->ec_revoked || evdev == NULL) in evdev_write()
283 if (uio->uio_resid % evsize != 0) { in evdev_write()
288 while (uio->uio_resid > 0 && ret == 0) { in evdev_write()
316 debugf(client, "poll by thread %d", td->td_tid); in evdev_poll()
318 if (client->ec_revoked) in evdev_poll()
326 client->ec_selected = true; in evdev_poll()
327 selrecord(td, &client->ec_selp); in evdev_poll()
345 if (client->ec_revoked) in evdev_kqfilter()
348 switch(kn->kn_filter) { in evdev_kqfilter()
350 kn->kn_fop = &evdev_cdev_filterops; in evdev_kqfilter()
355 kn->kn_hook = (caddr_t)client; in evdev_kqfilter()
357 knlist_add(&client->ec_selp.si_note, kn, 0); in evdev_kqfilter()
367 client = (struct evdev_client *)kn->kn_hook; in evdev_kqread()
371 if (client->ec_revoked) { in evdev_kqread()
372 kn->kn_flags |= EV_EOF; in evdev_kqread()
375 kn->kn_data = EVDEV_CLIENT_SIZEQ(client) * in evdev_kqread()
387 client = (struct evdev_client *)kn->kn_hook; in evdev_kqdetach()
388 knlist_remove(&client->ec_selp.si_note, kn, 0); in evdev_kqdetach()
395 struct evdev_dev *evdev = dev->si_drv1; in evdev_ioctl()
407 if (client->ec_revoked || evdev == NULL) in evdev_ioctl()
414 if (evdev->ev_kdb_active) { in evdev_ioctl()
416 if (evdev->ev_kdb_active) { in evdev_ioctl()
417 evdev->ev_kdb_active = false; in evdev_ioctl()
418 if (evdev->ev_lock_type == EV_LOCK_EXT_EPOCH) in evdev_ioctl()
421 if (evdev->ev_lock_type == EV_LOCK_EXT_EPOCH) in evdev_ioctl()
430 return (fsetown(*(int *)data, &client->ec_sigio)); in evdev_ioctl()
433 *(int *)data = fgetown(&client->ec_sigio); in evdev_ioctl()
441 client->ec_async = true; in evdev_ioctl()
443 client->ec_async = false; in evdev_ioctl()
458 /* evdev fixed-length ioctls handling */ in evdev_ioctl()
466 evdev->ev_id.bustype, evdev->ev_id.vendor, in evdev_ioctl()
467 evdev->ev_id.product); in evdev_ioctl()
468 memcpy(data, &evdev->ev_id, sizeof(struct input_id)); in evdev_ioctl()
475 memcpy(data, evdev->ev_rep, sizeof(evdev->ev_rep)); in evdev_ioctl()
492 if (evdev->ev_methods == NULL || in evdev_ioctl()
493 evdev->ev_methods->ev_get_keycode == NULL) in evdev_ioctl()
497 evdev->ev_methods->ev_get_keycode(evdev, ke); in evdev_ioctl()
505 if (evdev->ev_methods == NULL || in evdev_ioctl()
506 evdev->ev_methods->ev_set_keycode == NULL) in evdev_ioctl()
510 evdev->ev_methods->ev_set_keycode(evdev, ke); in evdev_ioctl()
514 if (evdev->ev_absinfo == NULL) in evdev_ioctl()
517 memcpy(data, &evdev->ev_absinfo[cmd - EVIOCGABS(0)], in evdev_ioctl()
522 if (evdev->ev_absinfo == NULL) in evdev_ioctl()
525 code = cmd - EVIOCSABS(0); in evdev_ioctl()
526 /* mt-slot number can not be changed */ in evdev_ioctl()
555 if (dev->si_drv1 != NULL && !client->ec_revoked) { in evdev_ioctl()
565 client->ec_clock_id = EV_CLOCK_REALTIME; in evdev_ioctl()
568 client->ec_clock_id = EV_CLOCK_MONOTONIC; in evdev_ioctl()
575 /* evdev variable-length ioctls handling */ in evdev_ioctl()
579 limit = MIN(strlen(evdev->ev_name) + 1, len); in evdev_ioctl()
580 memcpy(data, evdev->ev_name, limit); in evdev_ioctl()
581 td->td_retval[0] = limit; in evdev_ioctl()
585 if (evdev->ev_shortname[0] == 0) in evdev_ioctl()
588 limit = MIN(strlen(evdev->ev_shortname) + 1, len); in evdev_ioctl()
589 memcpy(data, evdev->ev_shortname, limit); in evdev_ioctl()
590 td->td_retval[0] = limit; in evdev_ioctl()
594 if (evdev->ev_serial[0] == 0) in evdev_ioctl()
597 limit = MIN(strlen(evdev->ev_serial) + 1, len); in evdev_ioctl()
598 memcpy(data, evdev->ev_serial, limit); in evdev_ioctl()
599 td->td_retval[0] = limit; in evdev_ioctl()
604 memcpy(data, evdev->ev_prop_flags, limit); in evdev_ioctl()
605 td->td_retval[0] = limit; in evdev_ioctl()
610 if (evdev->ev_mt == NULL) in evdev_ioctl()
619 MIN(len / sizeof(int32_t) - 1, MAXIMAL_MT_SLOT(evdev) + 1); in evdev_ioctl()
629 memcpy(data, evdev->ev_key_states, limit); in evdev_ioctl()
631 td->td_retval[0] = limit; in evdev_ioctl()
638 memcpy(data, evdev->ev_led_states, limit); in evdev_ioctl()
640 td->td_retval[0] = limit; in evdev_ioctl()
647 memcpy(data, evdev->ev_snd_states, limit); in evdev_ioctl()
649 td->td_retval[0] = limit; in evdev_ioctl()
656 memcpy(data, evdev->ev_sw_states, limit); in evdev_ioctl()
658 td->td_retval[0] = limit; in evdev_ioctl()
662 type_num = IOCBASECMD(cmd) - EVIOCGBIT(0, 0); in evdev_ioctl()
680 bitmap = evdev->ev_type_flags; in evdev_ioctl_eviocgbit()
684 bitmap = evdev->ev_key_flags; in evdev_ioctl_eviocgbit()
688 bitmap = evdev->ev_rel_flags; in evdev_ioctl_eviocgbit()
692 bitmap = evdev->ev_abs_flags; in evdev_ioctl_eviocgbit()
696 bitmap = evdev->ev_msc_flags; in evdev_ioctl_eviocgbit()
700 bitmap = evdev->ev_led_flags; in evdev_ioctl_eviocgbit()
704 bitmap = evdev->ev_snd_flags; in evdev_ioctl_eviocgbit()
708 bitmap = evdev->ev_sw_flags; in evdev_ioctl_eviocgbit()
713 * We don't support EV_FF now, so let's in evdev_ioctl_eviocgbit()
717 td->td_retval[0] = len; in evdev_ioctl_eviocgbit()
732 td->td_retval[0] = len; in evdev_ioctl_eviocgbit()
740 EVDEV_LIST_LOCK_ASSERT(client->ec_evdev); in evdev_revoke_client()
742 client->ec_revoked = true; in evdev_revoke_client()
751 if (client->ec_blocked) { in evdev_notify_event()
752 client->ec_blocked = false; in evdev_notify_event()
755 if (client->ec_selected) { in evdev_notify_event()
756 client->ec_selected = false; in evdev_notify_event()
757 selwakeup(&client->ec_selp); in evdev_notify_event()
759 KNOTE_LOCKED(&client->ec_selp.si_note, 0); in evdev_notify_event()
761 if (client->ec_async && client->ec_sigio != NULL) in evdev_notify_event()
762 pgsigio(&client->ec_sigio, SIGIO, 0); in evdev_notify_event()
779 /* Try to coexist with cuse-backed input/event devices */ in evdev_cdev_create()
780 while ((ret = make_dev_s(&mda, &evdev->ev_cdev, "input/event%d", unit)) in evdev_cdev_create()
785 evdev->ev_unit = unit; in evdev_cdev_create()
794 destroy_dev(evdev->ev_cdev); in evdev_cdev_destroy()
802 switch (client->ec_clock_id) { in evdev_client_gettime()
805 * XXX: FreeBSD does not support true POSIX monotonic clock. in evdev_client_gettime()
827 head = client->ec_buffer_head; in evdev_client_push()
828 tail = client->ec_buffer_tail; in evdev_client_push()
829 ready = client->ec_buffer_ready; in evdev_client_push()
830 count = client->ec_buffer_size; in evdev_client_push()
836 head = (tail + count - 1) % count; in evdev_client_push()
837 client->ec_buffer[head] = (struct input_event) { in evdev_client_push()
850 client->ec_buffer_head = head; in evdev_client_push()
851 client->ec_buffer_ready = head; in evdev_client_push()
854 client->ec_buffer[tail].type = type; in evdev_client_push()
855 client->ec_buffer[tail].code = code; in evdev_client_push()
856 client->ec_buffer[tail].value = value; in evdev_client_push()
857 client->ec_buffer_tail = (tail + 1) % count; in evdev_client_push()
862 for (; ready != client->ec_buffer_tail; in evdev_client_push()
864 client->ec_buffer[ready].time = time; in evdev_client_push()
865 client->ec_buffer_ready = client->ec_buffer_tail; in evdev_client_push()
875 head = client->ec_buffer_head; in evdev_client_dumpqueue()
876 tail = client->ec_buffer_tail; in evdev_client_dumpqueue()
877 ready = client->ec_buffer_ready; in evdev_client_dumpqueue()
878 size = client->ec_buffer_size; in evdev_client_dumpqueue()
887 event = &client->ec_buffer[i]; in evdev_client_dumpqueue()
893 printf("type=%d code=%d value=%d ", event->type, in evdev_client_dumpqueue()
894 event->code, event->value); in evdev_client_dumpqueue()
897 printf("<- head\n"); in evdev_client_dumpqueue()
899 printf("<- tail\n"); in evdev_client_dumpqueue()
901 printf("<- ready\n"); in evdev_client_dumpqueue()
916 i = head = client->ec_buffer_head; in evdev_client_filter_queue()
917 tail = client->ec_buffer_tail; in evdev_client_filter_queue()
918 count = client->ec_buffer_size; in evdev_client_filter_queue()
919 client->ec_buffer_ready = client->ec_buffer_tail; in evdev_client_filter_queue()
921 while (i != client->ec_buffer_tail) { in evdev_client_filter_queue()
922 event = &client->ec_buffer[i]; in evdev_client_filter_queue()
926 if (event->type == type) in evdev_client_filter_queue()
930 if (event->type == EV_SYN && event->code == SYN_REPORT) { in evdev_client_filter_queue()
934 client->ec_buffer_ready = (tail + 1) % count; in evdev_client_filter_queue()
938 memcpy(&client->ec_buffer[tail], event, in evdev_client_filter_queue()
941 last_was_syn = (event->type == EV_SYN && in evdev_client_filter_queue()
942 event->code == SYN_REPORT); in evdev_client_filter_queue()
947 client->ec_buffer_head = i; in evdev_client_filter_queue()
948 client->ec_buffer_tail = tail; in evdev_client_filter_queue()