1 /* $NetBSD: wsmouse.c,v 1.61 2009/01/13 18:05:55 christos Exp $ */
4 * Copyright (c) 2006 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Julio M. Merino Vidal.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
33 * Copyright (c) 1996, 1997 Christopher G. Demetriou. All rights reserved.
35 * Redistribution and use in source and binary forms, with or without
36 * modification, are permitted provided that the following conditions
38 * 1. Redistributions of source code must retain the above copyright
39 * notice, this list of conditions and the following disclaimer.
40 * 2. Redistributions in binary form must reproduce the above copyright
41 * notice, this list of conditions and the following disclaimer in the
42 * documentation and/or other materials provided with the distribution.
43 * 3. All advertising materials mentioning features or use of this software
44 * must display the following acknowledgement:
45 * This product includes software developed by Christopher G. Demetriou
46 * for the NetBSD Project.
47 * 4. The name of the author may not be used to endorse or promote products
48 * derived from this software without specific prior written permission
50 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
51 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
52 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
53 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
54 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
55 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
56 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
57 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
58 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
59 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
63 * Copyright (c) 1992, 1993
64 * The Regents of the University of California. All rights reserved.
66 * This software was developed by the Computer Systems Engineering group
67 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
68 * contributed to Berkeley.
70 * All advertising materials mentioning features or use of this software
71 * must display the following acknowledgement:
72 * This product includes software developed by the University of
73 * California, Lawrence Berkeley Laboratory.
75 * Redistribution and use in source and binary forms, with or without
76 * modification, are permitted provided that the following conditions
78 * 1. Redistributions of source code must retain the above copyright
79 * notice, this list of conditions and the following disclaimer.
80 * 2. Redistributions in binary form must reproduce the above copyright
81 * notice, this list of conditions and the following disclaimer in the
82 * documentation and/or other materials provided with the distribution.
83 * 3. Neither the name of the University nor the names of its contributors
84 * may be used to endorse or promote products derived from this software
85 * without specific prior written permission.
87 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
88 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
89 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
90 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
91 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
92 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
93 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
94 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
95 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
96 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
99 * @(#)ms.c 8.1 (Berkeley) 6/11/93
106 #include <sys/cdefs.h>
107 __KERNEL_RCSID(0, "$NetBSD: wsmouse.c,v 1.61 2009/01/13 18:05:55 christos Exp $");
110 #include "wsdisplay.h"
113 #include <sys/param.h>
114 #include <sys/conf.h>
115 #include <sys/ioctl.h>
116 #include <sys/poll.h>
117 #include <sys/fcntl.h>
118 #include <sys/kernel.h>
119 #include <sys/proc.h>
120 #include <sys/syslog.h>
121 #include <sys/systm.h>
123 #include <sys/signalvar.h>
124 #include <sys/device.h>
125 #include <sys/vnode.h>
126 #include <sys/callout.h>
127 #include <sys/malloc.h>
129 #include <dev/wscons/wsconsio.h>
130 #include <dev/wscons/wsmousevar.h>
131 #include <dev/wscons/wseventvar.h>
132 #include <dev/wscons/wsmuxvar.h>
134 #if defined(WSMUX_DEBUG) && NWSMUX > 0
135 #define DPRINTF(x) if (wsmuxdebug) printf x
136 #define DPRINTFN(n,x) if (wsmuxdebug > (n)) printf x
137 extern int wsmuxdebug
;
140 #define DPRINTFN(n,x)
143 #define INVALID_X INT_MAX
144 #define INVALID_Y INT_MAX
145 #define INVALID_Z INT_MAX
147 struct wsmouse_softc
{
148 struct wsevsrc sc_base
;
150 const struct wsmouse_accessops
*sc_accessops
;
151 void *sc_accesscookie
;
153 u_int sc_mb
; /* mouse button state */
154 u_int sc_ub
; /* user button state */
155 int sc_dx
; /* delta-x */
156 int sc_dy
; /* delta-y */
157 int sc_dz
; /* delta-z */
158 int sc_dw
; /* delta-w */
159 int sc_x
; /* absolute-x */
160 int sc_y
; /* absolute-y */
161 int sc_z
; /* absolute-z */
162 int sc_w
; /* absolute-w */
165 u_char sc_dying
; /* device is being detached */
167 struct wsmouse_repeat sc_repeat
;
168 int sc_repeat_button
;
169 callout_t sc_repeat_callout
;
170 unsigned int sc_repeat_delay
;
173 static int wsmouse_match(device_t
, cfdata_t
, void *);
174 static void wsmouse_attach(device_t
, device_t
, void *);
175 static int wsmouse_detach(device_t
, int);
176 static int wsmouse_activate(device_t
, enum devact
);
178 static int wsmouse_do_ioctl(struct wsmouse_softc
*, u_long
, void *,
182 static int wsmouse_mux_open(struct wsevsrc
*, struct wseventvar
*);
183 static int wsmouse_mux_close(struct wsevsrc
*);
186 static int wsmousedoioctl(device_t
, u_long
, void *, int, struct lwp
*);
188 static int wsmousedoopen(struct wsmouse_softc
*, struct wseventvar
*);
190 CFATTACH_DECL_NEW(wsmouse
, sizeof (struct wsmouse_softc
),
191 wsmouse_match
, wsmouse_attach
, wsmouse_detach
, wsmouse_activate
);
193 static void wsmouse_repeat(void *v
);
195 extern struct cfdriver wsmouse_cd
;
197 dev_type_open(wsmouseopen
);
198 dev_type_close(wsmouseclose
);
199 dev_type_read(wsmouseread
);
200 dev_type_ioctl(wsmouseioctl
);
201 dev_type_poll(wsmousepoll
);
202 dev_type_kqfilter(wsmousekqfilter
);
204 const struct cdevsw wsmouse_cdevsw
= {
205 wsmouseopen
, wsmouseclose
, wsmouseread
, nowrite
, wsmouseioctl
,
206 nostop
, notty
, wsmousepoll
, nommap
, wsmousekqfilter
, D_OTHER
210 struct wssrcops wsmouse_srcops
= {
212 wsmouse_mux_open
, wsmouse_mux_close
, wsmousedoioctl
, NULL
, NULL
217 * Print function (for parent devices).
220 wsmousedevprint(void *aux
, const char *pnp
)
224 aprint_normal("wsmouse at %s", pnp
);
229 wsmouse_match(device_t parent
, cfdata_t match
, void *aux
)
235 wsmouse_attach(device_t parent
, device_t self
, void *aux
)
237 struct wsmouse_softc
*sc
= device_private(self
);
238 struct wsmousedev_attach_args
*ap
= aux
;
243 sc
->sc_base
.me_dv
= self
;
244 sc
->sc_accessops
= ap
->accessops
;
245 sc
->sc_accesscookie
= ap
->accesscookie
;
247 /* Initialize button repeating. */
248 memset(&sc
->sc_repeat
, 0, sizeof(sc
->sc_repeat
));
249 sc
->sc_repeat_button
= -1;
250 sc
->sc_repeat_delay
= 0;
251 callout_init(&sc
->sc_repeat_callout
, 0);
252 callout_setfunc(&sc
->sc_repeat_callout
, wsmouse_repeat
, sc
);
255 sc
->sc_base
.me_ops
= &wsmouse_srcops
;
256 mux
= device_cfdata(self
)->wsmousedevcf_mux
;
258 error
= wsmux_attach_sc(wsmux_getmux(mux
), &sc
->sc_base
);
260 aprint_error(" attach error=%d", error
);
262 aprint_normal(" mux %d", mux
);
265 if (device_cfdata(self
)->wsmousedevcf_mux
>= 0)
266 aprint_normal(" (mux ignored)");
272 if (!pmf_device_register(self
, NULL
, NULL
))
273 aprint_error_dev(self
, "couldn't establish power handler\n");
277 wsmouse_activate(device_t self
, enum devact act
)
279 struct wsmouse_softc
*sc
= device_private(self
);
281 if (act
== DVACT_DEACTIVATE
)
287 * Detach a mouse. To keep track of users of the softc we keep
288 * a reference count that's incremented while inside, e.g., read.
289 * If the mouse is active and the reference count is > 0 (0 is the
290 * normal state) we post an event and then wait for the process
291 * that had the reference to wake us up again. Then we blow away the
292 * vnode and return (which will deallocate the softc).
295 wsmouse_detach(device_t self
, int flags
)
297 struct wsmouse_softc
*sc
= device_private(self
);
298 struct wseventvar
*evar
;
303 /* Tell parent mux we're leaving. */
304 if (sc
->sc_base
.me_parent
!= NULL
) {
305 DPRINTF(("wsmouse_detach:\n"));
306 wsmux_detach_sc(&sc
->sc_base
);
310 /* If we're open ... */
311 evar
= sc
->sc_base
.me_evp
;
312 if (evar
!= NULL
&& evar
->io
!= NULL
) {
314 if (--sc
->sc_refcnt
>= 0) {
315 struct wscons_event event
;
317 /* Wake everyone by generating a dummy event. */
320 if (wsevent_inject(evar
, &event
, 1) != 0)
321 wsevent_wakeup(evar
);
323 /* Wait for processes to go away. */
324 if (tsleep(sc
, PZERO
, "wsmdet", hz
* 60))
325 printf("wsmouse_detach: %s didn't detach\n",
331 /* locate the major number */
332 maj
= cdevsw_lookup_major(&wsmouse_cdevsw
);
334 /* Nuke the vnodes for any open instances (calls close). */
335 mn
= device_unit(self
);
336 vdevgone(maj
, mn
, mn
, VCHR
);
342 wsmouse_input(device_t wsmousedev
, u_int btns
/* 0 is up */,
343 int x
, int y
, int z
, int w
, u_int flags
)
345 struct wsmouse_softc
*sc
= device_private(wsmousedev
);
346 struct wseventvar
*evar
;
347 int mb
, ub
, d
, nevents
;
348 /* one for each dimension (4) + a bit for each button */
349 struct wscons_event events
[4 + sizeof(d
) * 8];
352 * Discard input if not open.
354 evar
= sc
->sc_base
.me_evp
;
359 if (evar
->q
== NULL
) {
360 printf("wsmouse_input: evar->q=NULL\n");
366 DPRINTFN(5,("wsmouse_input: %s mux=%p, evar=%p\n",
367 device_xname(sc
->sc_base
.me_dv
),
368 sc
->sc_base
.me_parent
, evar
));
372 if (!(flags
& WSMOUSE_INPUT_ABSOLUTE_X
))
374 if (!(flags
& WSMOUSE_INPUT_ABSOLUTE_Y
))
376 if (!(flags
& WSMOUSE_INPUT_ABSOLUTE_Z
))
378 if (!(flags
& WSMOUSE_INPUT_ABSOLUTE_W
))
382 * We have at least one event (mouse button, delta-X, or
383 * delta-Y; possibly all three, and possibly three separate
384 * button events). Deliver these events until we are out
385 * of changes or out of room. As events get delivered,
386 * mark them `unchanged'.
391 if (flags
& WSMOUSE_INPUT_ABSOLUTE_X
) {
393 events
[nevents
].type
= WSCONS_EVENT_MOUSE_ABSOLUTE_X
;
394 events
[nevents
].value
= x
;
399 events
[nevents
].type
= WSCONS_EVENT_MOUSE_DELTA_X
;
400 events
[nevents
].value
= sc
->sc_dx
;
404 if (flags
& WSMOUSE_INPUT_ABSOLUTE_Y
) {
406 events
[nevents
].type
= WSCONS_EVENT_MOUSE_ABSOLUTE_Y
;
407 events
[nevents
].value
= y
;
412 events
[nevents
].type
= WSCONS_EVENT_MOUSE_DELTA_Y
;
413 events
[nevents
].value
= sc
->sc_dy
;
417 if (flags
& WSMOUSE_INPUT_ABSOLUTE_Z
) {
419 events
[nevents
].type
= WSCONS_EVENT_MOUSE_ABSOLUTE_Z
;
420 events
[nevents
].value
= z
;
425 events
[nevents
].type
= WSCONS_EVENT_MOUSE_DELTA_Z
;
426 events
[nevents
].value
= sc
->sc_dz
;
430 if (flags
& WSMOUSE_INPUT_ABSOLUTE_W
) {
432 events
[nevents
].type
= WSCONS_EVENT_MOUSE_ABSOLUTE_W
;
433 events
[nevents
].value
= w
;
438 events
[nevents
].type
= WSCONS_EVENT_MOUSE_DELTA_W
;
439 events
[nevents
].value
= sc
->sc_dw
;
445 while ((d
= mb
^ ub
) != 0) {
449 * Cancel button repeating if button status changed.
451 if (sc
->sc_repeat_button
!= -1) {
452 KASSERT(sc
->sc_repeat_button
>= 0);
453 KASSERT(sc
->sc_repeat
.wr_buttons
&
454 (1 << sc
->sc_repeat_button
));
455 ub
&= ~(1 << sc
->sc_repeat_button
);
456 sc
->sc_repeat_button
= -1;
457 callout_stop(&sc
->sc_repeat_callout
);
461 * Mouse button change. Find the first change and drop
462 * it into the event queue.
467 if (nevents
>= sizeof(events
) / sizeof(events
[0])) {
468 aprint_error_dev(sc
->sc_base
.me_dv
,
469 "Event queue full (button status mb=0x%x"
470 " ub=0x%x)\n", mb
, ub
);
474 events
[nevents
].type
=
475 (mb
& d
) ? WSCONS_EVENT_MOUSE_DOWN
: WSCONS_EVENT_MOUSE_UP
;
476 events
[nevents
].value
= btnno
;
482 * Program button repeating if configured for this button.
484 if ((mb
& d
) && (sc
->sc_repeat
.wr_buttons
& (1 << btnno
)) &&
485 sc
->sc_repeat
.wr_delay_first
> 0) {
486 sc
->sc_repeat_button
= btnno
;
487 sc
->sc_repeat_delay
= sc
->sc_repeat
.wr_delay_first
;
488 callout_schedule(&sc
->sc_repeat_callout
,
489 mstohz(sc
->sc_repeat_delay
));
493 if (nevents
== 0 || wsevent_inject(evar
, events
, nevents
) == 0) {
494 /* All events were correctly injected into the queue.
495 * Synchronize the mouse's status with what the user
497 sc
->sc_x
= x
; sc
->sc_dx
= 0;
498 sc
->sc_y
= y
; sc
->sc_dy
= 0;
499 sc
->sc_z
= z
; sc
->sc_dz
= 0;
500 sc
->sc_w
= w
; sc
->sc_dw
= 0;
503 DPRINTFN(5,("wsmouse_input: %s wakeup evar=%p\n",
504 device_xname(sc
->sc_base
.me_dv
), evar
));
510 wsmouse_repeat(void *v
)
513 unsigned int newdelay
;
514 struct wsmouse_softc
*sc
;
515 struct wscons_event events
[2];
518 sc
= (struct wsmouse_softc
*)v
;
520 if (sc
->sc_repeat_button
== -1) {
521 /* Race condition: a "button up" event came in when
522 * this function was already called but did not do
527 KASSERT(sc
->sc_repeat_button
>= 0);
529 KASSERT(sc
->sc_repeat
.wr_buttons
& (1 << sc
->sc_repeat_button
));
531 newdelay
= sc
->sc_repeat_delay
;
533 events
[0].type
= WSCONS_EVENT_MOUSE_UP
;
534 events
[0].value
= sc
->sc_repeat_button
;
535 events
[1].type
= WSCONS_EVENT_MOUSE_DOWN
;
536 events
[1].value
= sc
->sc_repeat_button
;
538 if (wsevent_inject(sc
->sc_base
.me_evp
, events
, 2) == 0) {
539 sc
->sc_ub
= 1 << sc
->sc_repeat_button
;
541 if (newdelay
- sc
->sc_repeat
.wr_delay_decrement
<
542 sc
->sc_repeat
.wr_delay_minimum
)
543 newdelay
= sc
->sc_repeat
.wr_delay_minimum
;
544 else if (newdelay
> sc
->sc_repeat
.wr_delay_minimum
)
545 newdelay
-= sc
->sc_repeat
.wr_delay_decrement
;
546 KASSERT(newdelay
>= sc
->sc_repeat
.wr_delay_minimum
&&
547 newdelay
<= sc
->sc_repeat
.wr_delay_first
);
551 * Reprogram the repeating event.
553 sc
->sc_repeat_delay
= newdelay
;
554 callout_schedule(&sc
->sc_repeat_callout
, mstohz(newdelay
));
560 wsmouseopen(dev_t dev
, int flags
, int mode
, struct lwp
*l
)
562 struct wsmouse_softc
*sc
;
563 struct wseventvar
*evar
;
566 sc
= device_lookup_private(&wsmouse_cd
, minor(dev
));
571 DPRINTF(("wsmouseopen: %s mux=%p p=%p\n", device_xname(sc
->sc_base
.me_dv
),
572 sc
->sc_base
.me_parent
, l
));
578 if ((flags
& (FREAD
| FWRITE
)) == FWRITE
)
579 return (0); /* always allow open for write
580 so ioctl() is possible. */
582 if (sc
->sc_base
.me_evp
!= NULL
)
585 evar
= &sc
->sc_base
.me_evar
;
586 wsevent_init(evar
, l
->l_proc
);
587 sc
->sc_base
.me_evp
= evar
;
589 error
= wsmousedoopen(sc
, evar
);
591 DPRINTF(("wsmouseopen: %s open failed\n",
592 device_xname(sc
->sc_base
.me_dv
)));
593 sc
->sc_base
.me_evp
= NULL
;
600 wsmouseclose(dev_t dev
, int flags
, int mode
,
603 struct wsmouse_softc
*sc
=
604 device_lookup_private(&wsmouse_cd
, minor(dev
));
605 struct wseventvar
*evar
= sc
->sc_base
.me_evp
;
608 /* not open for read */
610 sc
->sc_base
.me_evp
= NULL
;
611 (*sc
->sc_accessops
->disable
)(sc
->sc_accesscookie
);
618 wsmousedoopen(struct wsmouse_softc
*sc
, struct wseventvar
*evp
)
620 sc
->sc_base
.me_evp
= evp
;
621 sc
->sc_x
= INVALID_X
;
622 sc
->sc_y
= INVALID_Y
;
623 sc
->sc_z
= INVALID_Z
;
625 /* Stop button repeating when messing with the device. */
626 if (sc
->sc_repeat_button
!= -1) {
627 KASSERT(sc
->sc_repeat_button
>= 0);
628 sc
->sc_repeat_button
= -1;
629 callout_stop(&sc
->sc_repeat_callout
);
632 /* enable the device, and punt if that's not possible */
633 return (*sc
->sc_accessops
->enable
)(sc
->sc_accesscookie
);
637 wsmouseread(dev_t dev
, struct uio
*uio
, int flags
)
639 struct wsmouse_softc
*sc
=
640 device_lookup_private(&wsmouse_cd
, minor(dev
));
647 if (sc
->sc_base
.me_evp
== NULL
) {
648 printf("wsmouseread: evp == NULL\n");
654 error
= wsevent_read(sc
->sc_base
.me_evp
, uio
, flags
);
655 if (--sc
->sc_refcnt
< 0) {
663 wsmouseioctl(dev_t dev
, u_long cmd
, void *data
, int flag
, struct lwp
*l
)
665 return (wsmousedoioctl(device_lookup(&wsmouse_cd
, minor(dev
)),
666 cmd
, data
, flag
, l
));
669 /* A wrapper around the ioctl() workhorse to make reference counting easy. */
671 wsmousedoioctl(device_t dv
, u_long cmd
, void *data
, int flag
,
674 struct wsmouse_softc
*sc
= device_private(dv
);
678 error
= wsmouse_do_ioctl(sc
, cmd
, data
, flag
, l
);
679 if (--sc
->sc_refcnt
< 0)
685 wsmouse_do_ioctl(struct wsmouse_softc
*sc
, u_long cmd
, void *data
,
686 int flag
, struct lwp
*l
)
689 struct wsmouse_repeat
*wr
;
695 * Try the generic ioctls that the wsmouse interface supports.
698 case FIONBIO
: /* we will remove this someday (soon???) */
702 if (sc
->sc_base
.me_evp
== NULL
)
704 sc
->sc_base
.me_evp
->async
= *(int *)data
!= 0;
708 if (sc
->sc_base
.me_evp
== NULL
)
710 if (-*(int *)data
!= sc
->sc_base
.me_evp
->io
->p_pgid
711 && *(int *)data
!= sc
->sc_base
.me_evp
->io
->p_pid
)
716 if (sc
->sc_base
.me_evp
== NULL
)
718 if (*(int *)data
!= sc
->sc_base
.me_evp
->io
->p_pgid
)
724 * Try the wsmouse specific ioctls.
727 case WSMOUSEIO_GETREPEAT
:
728 wr
= (struct wsmouse_repeat
*)data
;
729 memcpy(wr
, &sc
->sc_repeat
, sizeof(sc
->sc_repeat
));
732 case WSMOUSEIO_SETREPEAT
:
733 if ((flag
& FWRITE
) == 0)
736 /* Validate input data. */
737 wr
= (struct wsmouse_repeat
*)data
;
738 if (wr
->wr_delay_first
!= 0 &&
739 (wr
->wr_delay_first
< wr
->wr_delay_decrement
||
740 wr
->wr_delay_first
< wr
->wr_delay_minimum
||
741 wr
->wr_delay_first
< wr
->wr_delay_minimum
+
742 wr
->wr_delay_decrement
))
745 /* Stop current repeating and set new data. */
746 sc
->sc_repeat_button
= -1;
747 callout_stop(&sc
->sc_repeat_callout
);
748 memcpy(&sc
->sc_repeat
, wr
, sizeof(sc
->sc_repeat
));
752 case WSMOUSEIO_SETVERSION
:
753 return wsevent_setversion(sc
->sc_base
.me_evp
, *(int *)data
);
757 * Try the mouse driver for WSMOUSEIO ioctls. It returns -1
758 * if it didn't recognize the request.
760 error
= (*sc
->sc_accessops
->ioctl
)(sc
->sc_accesscookie
, cmd
,
762 return (error
); /* may be EPASSTHROUGH */
766 wsmousepoll(dev_t dev
, int events
, struct lwp
*l
)
768 struct wsmouse_softc
*sc
=
769 device_lookup_private(&wsmouse_cd
, minor(dev
));
771 if (sc
->sc_base
.me_evp
== NULL
)
773 return (wsevent_poll(sc
->sc_base
.me_evp
, events
, l
));
777 wsmousekqfilter(dev_t dev
, struct knote
*kn
)
779 struct wsmouse_softc
*sc
=
780 device_lookup_private(&wsmouse_cd
, minor(dev
));
782 if (sc
->sc_base
.me_evp
== NULL
)
784 return (wsevent_kqfilter(sc
->sc_base
.me_evp
, kn
));
789 wsmouse_mux_open(struct wsevsrc
*me
, struct wseventvar
*evp
)
791 struct wsmouse_softc
*sc
= (struct wsmouse_softc
*)me
;
793 if (sc
->sc_base
.me_evp
!= NULL
)
796 return wsmousedoopen(sc
, evp
);
800 wsmouse_mux_close(struct wsevsrc
*me
)
802 struct wsmouse_softc
*sc
= (struct wsmouse_softc
*)me
;
804 sc
->sc_base
.me_evp
= NULL
;
805 (*sc
->sc_accessops
->disable
)(sc
->sc_accesscookie
);
811 wsmouse_add_mux(int unit
, struct wsmux_softc
*muxsc
)
813 struct wsmouse_softc
*sc
;
815 sc
= device_lookup_private(&wsmouse_cd
, unit
);
819 if (sc
->sc_base
.me_parent
!= NULL
|| sc
->sc_base
.me_evp
!= NULL
)
822 return (wsmux_attach_sc(muxsc
, &sc
->sc_base
));
824 #endif /* NWSMUX > 0 */