2 * Copyright (c) 1999 Kazutaka YOKOTA <yokota@zodiac.mech.utsunomiya-u.ac.jp>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer as
10 * the first lines of this file unmodified.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 * $FreeBSD: src/sys/dev/syscons/sysmouse.c,v 1.2.2.2 2001/07/16 05:21:24 yokota Exp $
27 * $DragonFly: src/sys/dev/misc/syscons/sysmouse.c,v 1.12 2006/09/10 03:26:35 dillon Exp $
30 #include "opt_syscons.h"
32 #include <sys/param.h>
33 #include <sys/systm.h>
37 #include <sys/kernel.h>
38 #include <sys/thread2.h>
40 #include <machine/console.h>
41 #include <machine/mouse.h>
45 #ifndef SC_NO_SYSMOUSE
47 #define CDEV_MAJOR 12 /* major number, shared with syscons */
48 #define SC_MOUSE 128 /* minor number */
50 static d_open_t smopen
;
51 static d_close_t smclose
;
52 static d_ioctl_t smioctl
;
54 static struct dev_ops sm_ops
= {
55 { "sysmouse", CDEV_MAJOR
, D_TTY
},
64 static struct tty
*sysmouse_tty
;
65 static int mouse_level
; /* sysmouse protocol level */
66 static mousestatus_t mouse_status
;
68 static void smstart(struct tty
*tp
);
69 static int smparam(struct tty
*tp
, struct termios
*t
);
72 smopen(struct dev_open_args
*ap
)
74 cdev_t dev
= ap
->a_head
.a_dev
;
77 DPRINTF(5, ("smopen: dev:%d,%d, vty:%d\n",
78 major(dev
), minor(dev
), SC_VTY(dev
)));
81 if (SC_VTY(dev
) != SC_MOUSE
)
85 tp
= dev
->si_tty
= ttymalloc(dev
->si_tty
);
86 if (!(tp
->t_state
& TS_ISOPEN
)) {
88 tp
->t_oproc
= smstart
;
89 tp
->t_param
= smparam
;
90 tp
->t_stop
= nottystop
;
96 tp
->t_cflag
= TTYDEF_CFLAG
;
97 tp
->t_ispeed
= tp
->t_ospeed
= TTYDEF_SPEED
;
98 smparam(tp
, &tp
->t_termios
);
99 (*linesw
[tp
->t_line
].l_modem
)(tp
, 1);
100 } else if (tp
->t_state
& TS_XCLUDE
&& suser_cred(ap
->a_cred
, 0)) {
104 return (*linesw
[tp
->t_line
].l_open
)(dev
, tp
);
108 smclose(struct dev_close_args
*ap
)
110 cdev_t dev
= ap
->a_head
.a_dev
;
116 (*linesw
[tp
->t_line
].l_close
)(tp
, ap
->a_fflag
);
124 smstart(struct tty
*tp
)
130 if (!(tp
->t_state
& (TS_TIMEOUT
| TS_BUSY
| TS_TTSTOP
))) {
131 tp
->t_state
|= TS_BUSY
;
134 q_to_b(rbp
, buf
, PCBURST
);
135 tp
->t_state
&= ~TS_BUSY
;
142 smparam(struct tty
*tp
, struct termios
*t
)
144 tp
->t_ispeed
= t
->c_ispeed
;
145 tp
->t_ospeed
= t
->c_ospeed
;
146 tp
->t_cflag
= t
->c_cflag
;
151 smioctl(struct dev_ioctl_args
*ap
)
153 cdev_t dev
= ap
->a_head
.a_dev
;
162 case MOUSE_GETHWINFO
: /* get device information */
163 hw
= (mousehw_t
*)ap
->a_data
;
164 hw
->buttons
= 10; /* XXX unknown */
165 hw
->iftype
= MOUSE_IF_SYSMOUSE
;
166 hw
->type
= MOUSE_MOUSE
;
167 hw
->model
= MOUSE_MODEL_GENERIC
;
171 case MOUSE_GETMODE
: /* get protocol/mode */
172 mode
= (mousemode_t
*)ap
->a_data
;
173 mode
->level
= mouse_level
;
174 switch (mode
->level
) {
175 case 0: /* emulate MouseSystems protocol */
176 mode
->protocol
= MOUSE_PROTO_MSC
;
177 mode
->rate
= -1; /* unknown */
178 mode
->resolution
= -1; /* unknown */
179 mode
->accelfactor
= 0; /* disabled */
180 mode
->packetsize
= MOUSE_MSC_PACKETSIZE
;
181 mode
->syncmask
[0] = MOUSE_MSC_SYNCMASK
;
182 mode
->syncmask
[1] = MOUSE_MSC_SYNC
;
185 case 1: /* sysmouse protocol */
186 mode
->protocol
= MOUSE_PROTO_SYSMOUSE
;
188 mode
->resolution
= -1;
189 mode
->accelfactor
= 0;
190 mode
->packetsize
= MOUSE_SYS_PACKETSIZE
;
191 mode
->syncmask
[0] = MOUSE_SYS_SYNCMASK
;
192 mode
->syncmask
[1] = MOUSE_SYS_SYNC
;
197 case MOUSE_SETMODE
: /* set protocol/mode */
198 mode
= (mousemode_t
*)ap
->a_data
;
199 if (mode
->level
== -1)
200 ; /* don't change the current setting */
201 else if ((mode
->level
< 0) || (mode
->level
> 1))
204 mouse_level
= mode
->level
;
207 case MOUSE_GETLEVEL
: /* get operation level */
208 *(int *)ap
->a_data
= mouse_level
;
211 case MOUSE_SETLEVEL
: /* set operation level */
212 if ((*(int *)ap
->a_data
< 0) || (*(int *)ap
->a_data
> 1))
214 mouse_level
= *(int *)ap
->a_data
;
217 case MOUSE_GETSTATUS
: /* get accumulated mouse events */
219 *(mousestatus_t
*)ap
->a_data
= mouse_status
;
220 mouse_status
.flags
= 0;
221 mouse_status
.obutton
= mouse_status
.button
;
229 case MOUSE_GETVARS
: /* get internal mouse variables */
230 case MOUSE_SETVARS
: /* set internal mouse variables */
234 case MOUSE_READSTATE
: /* read status from the device */
235 case MOUSE_READDATA
: /* read data from the device */
239 error
= (*linesw
[tp
->t_line
].l_ioctl
)(tp
, ap
->a_cmd
, ap
->a_data
, ap
->a_fflag
, ap
->a_cred
);
240 if (error
!= ENOIOCTL
)
242 error
= ttioctl(tp
, ap
->a_cmd
, ap
->a_data
, ap
->a_fflag
);
243 if (error
!= ENOIOCTL
)
249 sm_attach_mouse(void *unused
)
253 dev_ops_add(&sm_ops
, -1, SC_MOUSE
);
254 dev
= make_dev(&sm_ops
, SC_MOUSE
, UID_ROOT
, GID_WHEEL
, 0600,
256 /* sysmouse doesn't have scr_stat */
259 SYSINIT(sysmouse
, SI_SUB_DRIVERS
, SI_ORDER_MIDDLE
+ CDEV_MAJOR
,
260 sm_attach_mouse
, NULL
)
263 sysmouse_event(mouse_info_t
*info
)
265 /* MOUSE_BUTTON?DOWN -> MOUSE_MSC_BUTTON?UP */
266 static int butmap
[8] = {
267 MOUSE_MSC_BUTTON1UP
| MOUSE_MSC_BUTTON2UP
| MOUSE_MSC_BUTTON3UP
,
268 MOUSE_MSC_BUTTON2UP
| MOUSE_MSC_BUTTON3UP
,
269 MOUSE_MSC_BUTTON1UP
| MOUSE_MSC_BUTTON3UP
,
271 MOUSE_MSC_BUTTON1UP
| MOUSE_MSC_BUTTON2UP
,
280 switch (info
->operation
) {
282 mouse_status
.button
= info
->u
.data
.buttons
;
284 case MOUSE_MOTION_EVENT
:
289 case MOUSE_BUTTON_EVENT
:
291 if (info
->u
.event
.value
> 0)
292 mouse_status
.button
|= info
->u
.event
.id
;
294 mouse_status
.button
&= ~info
->u
.event
.id
;
300 mouse_status
.dx
+= x
;
301 mouse_status
.dy
+= y
;
302 mouse_status
.dz
+= z
;
303 mouse_status
.flags
|= ((x
|| y
|| z
) ? MOUSE_POSCHANGED
: 0)
304 | (mouse_status
.obutton
^ mouse_status
.button
);
305 if (mouse_status
.flags
== 0)
308 if ((sysmouse_tty
== NULL
) || !(sysmouse_tty
->t_state
& TS_ISOPEN
))
309 return mouse_status
.flags
;
311 /* the first five bytes are compatible with MouseSystems' */
312 buf
[0] = MOUSE_MSC_SYNC
313 | butmap
[mouse_status
.button
& MOUSE_STDBUTTONS
];
314 x
= imax(imin(x
, 255), -256);
317 y
= -imax(imin(y
, 255), -256);
320 for (i
= 0; i
< MOUSE_MSC_PACKETSIZE
; ++i
)
321 (*linesw
[sysmouse_tty
->t_line
].l_rint
)(buf
[i
], sysmouse_tty
);
322 if (mouse_level
>= 1) {
324 z
= imax(imin(z
, 127), -128);
325 buf
[5] = (z
>> 1) & 0x7f;
326 buf
[6] = (z
- (z
>> 1)) & 0x7f;
328 buf
[7] = (~mouse_status
.button
>> 3) & 0x7f;
329 for (i
= MOUSE_MSC_PACKETSIZE
; i
< MOUSE_SYS_PACKETSIZE
; ++i
)
330 (*linesw
[sysmouse_tty
->t_line
].l_rint
)(buf
[i
],
334 return mouse_status
.flags
;
337 #endif /* !SC_NO_SYSMOUSE */