nrelease - fix/improve livecd
[dragonfly.git] / sys / dev / misc / syscons / sysmouse.c
CommitLineData
984263bc 1/*-
22ff886e
AH
2 * (MPSAFE)
3 *
984263bc
MD
4 * Copyright (c) 1999 Kazutaka YOKOTA <yokota@zodiac.mech.utsunomiya-u.ac.jp>
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer as
12 * the first lines of this file unmodified.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 * $FreeBSD: src/sys/dev/syscons/sysmouse.c,v 1.2.2.2 2001/07/16 05:21:24 yokota Exp $
29 */
30
c2962d9d
IV
31/* MPSAFE NOTE: Take care with locking in sysmouse_event which is called
32 * from syscons.
22ff886e 33 */
984263bc 34#include "opt_syscons.h"
b2dae643 35#include "opt_evdev.h"
984263bc
MD
36
37#include <sys/param.h>
38#include <sys/systm.h>
39#include <sys/conf.h>
c2962d9d
IV
40#include <sys/device.h>
41#include <sys/event.h>
42#include <sys/uio.h>
2b3f93ea 43#include <sys/caps.h>
c2962d9d 44#include <sys/vnode.h>
984263bc 45#include <sys/kernel.h>
2a070c43
IV
46#include <sys/signalvar.h>
47#include <sys/filio.h>
984263bc
MD
48
49#include <machine/console.h>
62770245 50#include <sys/mouse.h>
984263bc 51
b2dae643
PM
52#ifdef EVDEV_SUPPORT
53#include <dev/misc/evdev/input.h>
54#include <dev/misc/evdev/evdev.h>
55#endif
56
1f2de5d4 57#include "syscons.h"
984263bc
MD
58
59#ifndef SC_NO_SYSMOUSE
60
c2962d9d
IV
61#define FIFO_SIZE 256
62
63struct event_fifo {
64 mouse_info_t buf[FIFO_SIZE];
65 int start;
66 int fill;
67 unsigned int dropped;
68};
69
70struct sysmouse_state {
71 struct event_fifo *fifo;
72 int level; /* sysmouse protocol level */
73 mousestatus_t syncstatus;
74 mousestatus_t readstatus; /* Only needed for button status */
75 int opened;
2a070c43 76 int asyncio;
c2962d9d 77 struct lock sm_lock;
2a070c43 78 struct sigio *sm_sigio;
c2962d9d
IV
79 struct kqinfo rkq;
80};
81
984263bc
MD
82static d_open_t smopen;
83static d_close_t smclose;
c2962d9d 84static d_read_t smread;
984263bc 85static d_ioctl_t smioctl;
c2962d9d 86static d_kqfilter_t smkqfilter;
984263bc 87
fef8985e 88static struct dev_ops sm_ops = {
c2962d9d 89 { "sysmouse", 0, D_MPSAFE },
fef8985e
MD
90 .d_open = smopen,
91 .d_close = smclose,
c2962d9d 92 .d_read = smread,
fef8985e 93 .d_ioctl = smioctl,
c2962d9d 94 .d_kqfilter = smkqfilter,
984263bc
MD
95};
96
97/* local variables */
c2962d9d
IV
98static struct sysmouse_state mouse_state;
99
100static int sysmouse_evtopkt(struct sysmouse_state *sc, mouse_info_t *info,
101 u_char *buf);
102static void smqueue(struct sysmouse_state *sc, mouse_info_t *info);
103static int pktlen(struct sysmouse_state *sc);
104static void smfilter_detach(struct knote *);
105static int smfilter(struct knote *, long);
106static void smget(struct sysmouse_state *sc, mouse_info_t *info);
107static void smpop(struct sysmouse_state *sc);
984263bc 108
b2dae643
PM
109#ifdef EVDEV_SUPPORT
110static struct evdev_dev *sysmouse_evdev;
111
112static void
113smdev_evdev_init(void)
114{
115 int i;
116
117 sysmouse_evdev = evdev_alloc();
118 evdev_set_name(sysmouse_evdev, "System mouse");
119 evdev_set_phys(sysmouse_evdev, "sysmouse");
120 evdev_set_id(sysmouse_evdev, BUS_VIRTUAL, 0, 0, 0);
121 evdev_support_prop(sysmouse_evdev, INPUT_PROP_POINTER);
122 evdev_support_event(sysmouse_evdev, EV_SYN);
123 evdev_support_event(sysmouse_evdev, EV_REL);
124 evdev_support_event(sysmouse_evdev, EV_KEY);
125 evdev_support_rel(sysmouse_evdev, REL_X);
126 evdev_support_rel(sysmouse_evdev, REL_Y);
127 evdev_support_rel(sysmouse_evdev, REL_WHEEL);
128 evdev_support_rel(sysmouse_evdev, REL_HWHEEL);
129 for (i = 0; i < 8; i++)
130 evdev_support_key(sysmouse_evdev, BTN_MOUSE + i);
131 if (evdev_register(sysmouse_evdev)) {
132 evdev_free(sysmouse_evdev);
133 sysmouse_evdev = NULL;
134 }
135}
136
137static void
138smdev_evdev_write(int x, int y, int z, int buttons)
139{
140
141 if (sysmouse_evdev == NULL || !(evdev_rcpt_mask & EVDEV_RCPT_SYSMOUSE))
142 return;
143
144 evdev_push_event(sysmouse_evdev, EV_REL, REL_X, x);
145 evdev_push_event(sysmouse_evdev, EV_REL, REL_Y, y);
146 switch (evdev_sysmouse_t_axis) {
147 case EVDEV_SYSMOUSE_T_AXIS_PSM:
148 switch (z) {
149 case 1:
150 case -1:
151 evdev_push_rel(sysmouse_evdev, REL_WHEEL, -z);
152 break;
153 case 2:
154 case -2:
155 evdev_push_rel(sysmouse_evdev, REL_HWHEEL, z / 2);
156 break;
157 }
158 break;
159 case EVDEV_SYSMOUSE_T_AXIS_UMS:
160 if (buttons & (1 << 6))
161 evdev_push_rel(sysmouse_evdev, REL_HWHEEL, 1);
162 else if (buttons & (1 << 5))
163 evdev_push_rel(sysmouse_evdev, REL_HWHEEL, -1);
164 buttons &= ~((1 << 5)|(1 << 6));
165 /* PASSTHROUGH */
166 case EVDEV_SYSMOUSE_T_AXIS_NONE:
167 default:
168 evdev_push_rel(sysmouse_evdev, REL_WHEEL, -z);
169 }
170 evdev_push_mouse_btn(sysmouse_evdev, buttons);
171 evdev_sync(sysmouse_evdev);
172}
173#endif
174
c2962d9d
IV
175static int
176pktlen(struct sysmouse_state *sc)
177{
178 if (sc->level == 0)
179 return 5;
180 else
181 return 8;
182}
984263bc
MD
183
184static int
fef8985e 185smopen(struct dev_open_args *ap)
984263bc 186{
b13267a5 187 cdev_t dev = ap->a_head.a_dev;
c2962d9d 188 struct sysmouse_state *sc = &mouse_state;
22ff886e 189 int ret;
984263bc 190
c2962d9d
IV
191 DPRINTF(5, ("smopen: dev:%d,%d\n",
192 major(dev), minor(dev)));
193
194 lockmgr(&sc->sm_lock, LK_EXCLUSIVE);
195 if (!sc->opened) {
196 sc->fifo = kmalloc(sizeof(struct event_fifo),
197 M_SYSCONS, M_WAITOK | M_ZERO);
198 sc->opened = 1;
2a070c43
IV
199 sc->asyncio = 0;
200 sc->sm_sigio = NULL;
c2962d9d
IV
201 bzero(&sc->readstatus, sizeof(sc->readstatus));
202 bzero(&sc->syncstatus, sizeof(sc->syncstatus));
203 ret = 0;
204 } else {
205 ret = EBUSY;
984263bc 206 }
c2962d9d 207 lockmgr(&sc->sm_lock, LK_RELEASE);
984263bc 208
22ff886e 209 return ret;
984263bc
MD
210}
211
212static int
fef8985e 213smclose(struct dev_close_args *ap)
984263bc 214{
c2962d9d 215 struct sysmouse_state *sc = &mouse_state;
984263bc 216
c2962d9d 217 lockmgr(&sc->sm_lock, LK_EXCLUSIVE);
2a070c43 218 funsetown(&sc->sm_sigio);
c2962d9d 219 sc->opened = 0;
2a070c43 220 sc->asyncio = 0;
c2962d9d
IV
221 sc->level = 0;
222 kfree(sc->fifo, M_SYSCONS);
223 sc->fifo = NULL;
224 lockmgr(&sc->sm_lock, LK_RELEASE);
984263bc
MD
225
226 return 0;
227}
228
c2962d9d
IV
229static int
230smread(struct dev_read_args *ap)
984263bc 231{
c2962d9d
IV
232 struct sysmouse_state *sc = &mouse_state;
233 mousestatus_t backupstatus;
234 mouse_info_t info;
235 u_char buf[8];
236 struct uio *uio = ap->a_uio;
237 int error = 0, val, cnt = 0;
238
239 lockmgr(&sc->sm_lock, LK_EXCLUSIVE);
240 while (sc->fifo->fill <= 0) {
241 /* Buffer too small to fit a complete mouse packet */
242 if (uio->uio_resid < pktlen(sc)) {
243 error = EIO;
244 goto done;
245 }
246 if (ap->a_ioflag & IO_NDELAY) {
247 error = EAGAIN;
248 goto done;
249 }
250 error = lksleep(sc, &sc->sm_lock, PCATCH, "smread", 0);
251 if (error == EINTR || error == ERESTART) {
252 goto done;
253 }
984263bc 254 }
984263bc 255
c2962d9d
IV
256 do {
257 /* Buffer too small to fit a complete mouse packet */
258 if (uio->uio_resid < pktlen(sc)) {
259 error = EIO;
260 goto done;
261 }
262 smget(sc, &info);
263 backupstatus = sc->readstatus;
264 val = sysmouse_evtopkt(sc, &info, buf);
265 if (val > 0) {
266 error = uiomove(buf, val, uio);
267 if (error != 0) {
268 sc->readstatus = backupstatus;
269 goto done;
270 }
271 cnt++;
272 }
273 smpop(sc);
274 } while (sc->fifo->fill > 0);
275
276done:
277 lockmgr(&sc->sm_lock, LK_RELEASE);
278 if (cnt > 0 && error != EFAULT)
279 return 0;
280 return error;
984263bc
MD
281}
282
283static int
fef8985e 284smioctl(struct dev_ioctl_args *ap)
984263bc 285{
c2962d9d 286 struct sysmouse_state *sc = &mouse_state;
984263bc
MD
287 mousehw_t *hw;
288 mousemode_t *mode;
984263bc 289
fef8985e 290 switch (ap->a_cmd) {
2a070c43
IV
291 case FIOSETOWN:
292 lockmgr(&sc->sm_lock, LK_EXCLUSIVE);
293 fsetown(*(int *)ap->a_data, &sc->sm_sigio);
294 lockmgr(&sc->sm_lock, LK_RELEASE);
295 return 0;
296 case FIOGETOWN:
297 lockmgr(&sc->sm_lock, LK_EXCLUSIVE);
298 *(int *)ap->a_data = fgetown(&sc->sm_sigio);
299 lockmgr(&sc->sm_lock, LK_RELEASE);
300 return 0;
301 case FIOASYNC:
302 lockmgr(&sc->sm_lock, LK_EXCLUSIVE);
303 if (*(int *)ap->a_data) {
304 sc->asyncio = 1;
305 } else {
306 sc->asyncio = 0;
307 }
308 lockmgr(&sc->sm_lock, LK_RELEASE);
309 return 0;
984263bc 310 case MOUSE_GETHWINFO: /* get device information */
fef8985e 311 hw = (mousehw_t *)ap->a_data;
984263bc
MD
312 hw->buttons = 10; /* XXX unknown */
313 hw->iftype = MOUSE_IF_SYSMOUSE;
314 hw->type = MOUSE_MOUSE;
315 hw->model = MOUSE_MODEL_GENERIC;
316 hw->hwid = 0;
317 return 0;
318
319 case MOUSE_GETMODE: /* get protocol/mode */
fef8985e 320 mode = (mousemode_t *)ap->a_data;
c2962d9d
IV
321 lockmgr(&sc->sm_lock, LK_EXCLUSIVE);
322 mode->level = sc->level;
323 lockmgr(&sc->sm_lock, LK_RELEASE);
984263bc
MD
324 switch (mode->level) {
325 case 0: /* emulate MouseSystems protocol */
326 mode->protocol = MOUSE_PROTO_MSC;
327 mode->rate = -1; /* unknown */
328 mode->resolution = -1; /* unknown */
329 mode->accelfactor = 0; /* disabled */
330 mode->packetsize = MOUSE_MSC_PACKETSIZE;
331 mode->syncmask[0] = MOUSE_MSC_SYNCMASK;
332 mode->syncmask[1] = MOUSE_MSC_SYNC;
333 break;
334
335 case 1: /* sysmouse protocol */
336 mode->protocol = MOUSE_PROTO_SYSMOUSE;
337 mode->rate = -1;
338 mode->resolution = -1;
339 mode->accelfactor = 0;
340 mode->packetsize = MOUSE_SYS_PACKETSIZE;
341 mode->syncmask[0] = MOUSE_SYS_SYNCMASK;
342 mode->syncmask[1] = MOUSE_SYS_SYNC;
343 break;
344 }
345 return 0;
346
347 case MOUSE_SETMODE: /* set protocol/mode */
fef8985e 348 mode = (mousemode_t *)ap->a_data;
984263bc
MD
349 if (mode->level == -1)
350 ; /* don't change the current setting */
22ff886e 351 else if ((mode->level < 0) || (mode->level > 1)) {
984263bc 352 return EINVAL;
22ff886e 353 } else {
c2962d9d
IV
354 lockmgr(&sc->sm_lock, LK_EXCLUSIVE);
355 sc->level = mode->level;
356 lockmgr(&sc->sm_lock, LK_RELEASE);
22ff886e 357 }
984263bc
MD
358 return 0;
359
360 case MOUSE_GETLEVEL: /* get operation level */
c2962d9d
IV
361 lockmgr(&sc->sm_lock, LK_EXCLUSIVE);
362 *(int *)ap->a_data = sc->level;
363 lockmgr(&sc->sm_lock, LK_RELEASE);
984263bc
MD
364 return 0;
365
366 case MOUSE_SETLEVEL: /* set operation level */
22ff886e 367 if ((*(int *)ap->a_data < 0) || (*(int *)ap->a_data > 1)) {
984263bc 368 return EINVAL;
22ff886e 369 }
c2962d9d
IV
370 lockmgr(&sc->sm_lock, LK_EXCLUSIVE);
371 sc->level = *(int *)ap->a_data;
372 lockmgr(&sc->sm_lock, LK_RELEASE);
984263bc
MD
373 return 0;
374
375 case MOUSE_GETSTATUS: /* get accumulated mouse events */
c2962d9d
IV
376 lockmgr(&sc->sm_lock, LK_EXCLUSIVE);
377 *(mousestatus_t *)ap->a_data = sc->syncstatus;
378 sc->syncstatus.flags = 0;
379 sc->syncstatus.obutton = sc->syncstatus.button;
380 sc->syncstatus.dx = 0;
381 sc->syncstatus.dy = 0;
382 sc->syncstatus.dz = 0;
383 lockmgr(&sc->sm_lock, LK_RELEASE);
984263bc
MD
384 return 0;
385
984263bc
MD
386 case MOUSE_READSTATE: /* read status from the device */
387 case MOUSE_READDATA: /* read data from the device */
388 return ENODEV;
389 }
390
c2962d9d
IV
391 return ENOTTY;
392}
393
394static struct filterops smfiltops =
395 { FILTEROP_MPSAFE | FILTEROP_ISFD, NULL, smfilter_detach, smfilter };
396
397static int
398smkqfilter(struct dev_kqfilter_args *ap)
399{
400 struct sysmouse_state *sc = &mouse_state;
401 struct knote *kn = ap->a_kn;
402 struct klist *klist;
403
404 ap->a_result = 0;
405
406 switch (kn->kn_filter) {
407 case EVFILT_READ:
408 kn->kn_fop = &smfiltops;
409 kn->kn_hook = (caddr_t)sc;
410 break;
411 default:
412 ap->a_result = EOPNOTSUPP;
413 return (0);
414 }
415
416 klist = &sc->rkq.ki_note;
417 knote_insert(klist, kn);
418
419 return (0);
420}
421
422static void
423smfilter_detach(struct knote *kn)
424{
425 struct sysmouse_state *sc = &mouse_state;
426 struct klist *klist;
427
428 klist = &sc->rkq.ki_note;
429 knote_remove(klist, kn);
430}
431
432static int
433smfilter(struct knote *kn, long hint)
434{
435 struct sysmouse_state *sc = &mouse_state;
436 int ready = 0;
437
438 lockmgr(&sc->sm_lock, LK_EXCLUSIVE);
439 if (sc->fifo->fill > 0) {
440 ready = 1;
441 kn->kn_data = 0;
22ff886e 442 }
c2962d9d
IV
443 lockmgr(&sc->sm_lock, LK_RELEASE);
444
445 return ready;
446}
447
448static void
449smqueue(struct sysmouse_state *sc, mouse_info_t *info)
450{
451 struct event_fifo *f = sc->fifo;
452
453 if (f->fill >= FIFO_SIZE) {
454 f->fill = FIFO_SIZE;
455 f->buf[f->start] = *info;
456 f->start = (f->start + 1) % FIFO_SIZE;
457 f->dropped++;
458 } else {
459 f->buf[(f->start + f->fill) % FIFO_SIZE] = *info;
460 f->fill++;
461 }
462
463}
464
465static void
466smget(struct sysmouse_state *sc, mouse_info_t *info)
467{
468 struct event_fifo *f = sc->fifo;
469
470 if (f->fill > 0)
471 *info = f->buf[f->start];
472}
473
474static void
475smpop(struct sysmouse_state *sc)
476{
477 struct event_fifo *f = sc->fifo;
478
479 if (f->fill > 0) {
480 f->fill--;
481 f->start = (f->start + 1) % FIFO_SIZE;
22ff886e 482 }
984263bc
MD
483}
484
485static void
486sm_attach_mouse(void *unused)
487{
c2962d9d 488 struct sysmouse_state *sc = &mouse_state;
b13267a5 489 cdev_t dev;
984263bc 490
c2962d9d
IV
491 lockinit(&mouse_state.sm_lock, "sysmouse", 0, LK_CANRECURSE);
492 sc->fifo = NULL;
493
095f0dab 494 dev = make_dev(&sm_ops, 0, UID_ROOT, GID_WHEEL, 0600, "sysmouse");
b2dae643
PM
495#ifdef EVDEV_SUPPORT
496 smdev_evdev_init();
497#endif
984263bc
MD
498}
499
b0a45e06 500SYSINIT(sysmouse, SI_SUB_DRIVERS, SI_ORDER_ANY, sm_attach_mouse, NULL);
984263bc 501
c2962d9d
IV
502static int
503sysmouse_updatestatus(mousestatus_t *status, mouse_info_t *info)
984263bc 504{
984263bc 505 int x, y, z;
984263bc 506
c2962d9d
IV
507 status->obutton = status->button;
508
984263bc
MD
509 switch (info->operation) {
510 case MOUSE_ACTION:
c2962d9d 511 status->button = info->u.data.buttons;
984263bc
MD
512 /* FALL THROUGH */
513 case MOUSE_MOTION_EVENT:
514 x = info->u.data.x;
515 y = info->u.data.y;
516 z = info->u.data.z;
517 break;
518 case MOUSE_BUTTON_EVENT:
519 x = y = z = 0;
520 if (info->u.event.value > 0)
c2962d9d 521 status->button |= info->u.event.id;
984263bc 522 else
c2962d9d 523 status->button &= ~info->u.event.id;
984263bc
MD
524 break;
525 default:
526 return 0;
527 }
528
c2962d9d
IV
529 status->dx += x;
530 status->dy += y;
531 status->dz += z;
532 status->flags |= ((x || y || z) ? MOUSE_POSCHANGED : 0)
533 | (status->obutton ^ status->button);
534
b2dae643
PM
535#ifdef EVDEV_SUPPORT
536 smdev_evdev_write(x, y, z, status->button);
537#endif
538
c2962d9d
IV
539 return 1;
540}
541
542/* Requires buf to hold at least 8 bytes, returns number of bytes written */
543static int
544sysmouse_evtopkt(struct sysmouse_state *sc, mouse_info_t *info, u_char *buf)
545{
546 /* MOUSE_BUTTON?DOWN -> MOUSE_MSC_BUTTON?UP */
547 static int butmap[8] = {
548 MOUSE_MSC_BUTTON1UP | MOUSE_MSC_BUTTON2UP | MOUSE_MSC_BUTTON3UP,
549 MOUSE_MSC_BUTTON2UP | MOUSE_MSC_BUTTON3UP,
550 MOUSE_MSC_BUTTON1UP | MOUSE_MSC_BUTTON3UP,
551 MOUSE_MSC_BUTTON3UP,
552 MOUSE_MSC_BUTTON1UP | MOUSE_MSC_BUTTON2UP,
553 MOUSE_MSC_BUTTON2UP,
554 MOUSE_MSC_BUTTON1UP,
555 0,
556 };
557 int x, y, z;
558
559 sc->readstatus.dx = 0;
560 sc->readstatus.dy = 0;
561 sc->readstatus.dz = 0;
562 sc->readstatus.flags = 0;
563 if (sysmouse_updatestatus(&sc->readstatus, info) == 0)
984263bc
MD
564 return 0;
565
c2962d9d
IV
566 /* We aren't using the sc->readstatus.dx/dy/dz values */
567
568 if (sc->readstatus.flags == 0)
569 return 0;
570
571 x = (info->operation == MOUSE_BUTTON_EVENT ? 0 : info->u.data.x);
572 y = (info->operation == MOUSE_BUTTON_EVENT ? 0 : info->u.data.y);
573 z = (info->operation == MOUSE_BUTTON_EVENT ? 0 : info->u.data.z);
984263bc
MD
574
575 /* the first five bytes are compatible with MouseSystems' */
576 buf[0] = MOUSE_MSC_SYNC
c2962d9d 577 | butmap[sc->readstatus.button & MOUSE_STDBUTTONS];
984263bc
MD
578 x = imax(imin(x, 255), -256);
579 buf[1] = x >> 1;
580 buf[3] = x - buf[1];
581 y = -imax(imin(y, 255), -256);
582 buf[2] = y >> 1;
583 buf[4] = y - buf[2];
c2962d9d 584 if (sc->level >= 1) {
984263bc 585 /* extended part */
c2962d9d 586 z = imax(imin(z, 127), -128);
984263bc
MD
587 buf[5] = (z >> 1) & 0x7f;
588 buf[6] = (z - (z >> 1)) & 0x7f;
c2962d9d
IV
589 /* buttons 4-10 */
590 buf[7] = (~sc->readstatus.button >> 3) & 0x7f;
984263bc
MD
591 }
592
c2962d9d
IV
593 if (sc->level >= 1)
594 return 8;
595
596 return 5;
597}
598
599int
600sysmouse_event(mouse_info_t *info)
601{
602 struct sysmouse_state *sc = &mouse_state;
603 int ret;
604
605 lockmgr(&sc->sm_lock, LK_EXCLUSIVE);
606 ret = sysmouse_updatestatus(&sc->syncstatus, info);
607 if (ret != 0)
608 ret = sc->syncstatus.flags;
609 if (!sc->opened) {
610 lockmgr(&sc->sm_lock, LK_RELEASE);
611 return ret;
612 }
613
614 switch (info->operation) {
615 case MOUSE_ACTION:
616 case MOUSE_MOTION_EVENT:
617 case MOUSE_BUTTON_EVENT:
618 smqueue(sc, info);
2a070c43
IV
619 if (sc->asyncio)
620 pgsigio(sc->sm_sigio, SIGIO, 0);
c2962d9d
IV
621 lockmgr(&sc->sm_lock, LK_RELEASE);
622 wakeup(sc);
623 KNOTE(&sc->rkq.ki_note, 0);
624 break;
625 default:
626 lockmgr(&sc->sm_lock, LK_RELEASE);
627 break;
628 }
629
630 return ret;
984263bc
MD
631}
632
633#endif /* !SC_NO_SYSMOUSE */