1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 /*
27  * 3-Byte Mouse Protocol
28  */
29 
30 #include <sys/param.h>
31 #include <sys/stream.h>
32 #include <sys/strsun.h>
33 #include <sys/vuid_event.h>
34 #include "vuidmice.h"
35 
36 #define	VUID_BUT(b)		BUT((b*2)+1)
37 
38 /*
39  * VUID_BUT(0)	BUT(1)		LEFT  BUTTON
40  * VUID_BUT(1)	BUT(3)		RIGHT BUTTON
41  */
42 
43 #define	MOUSE_BUTTON_L		(uchar_t)(0x20)	/* Left button pressed	*/
44 #define	MOUSE_BUTTON_R		(uchar_t)(0x10)	/* Right button pressed	*/
45 
46 #define	MOUSE_START_CODE	(uchar_t)(0x40)	/* Start code in char	*/
47 
48 #define	MOUSE_START		0		/* Beginning of packet	*/
49 #define	MOUSE_BUTTON		1		/* Got button status	*/
50 #define	MOUSE_DELTA_X		2		/* got delta X		*/
51 
52 extern void VUID_PUTNEXT(queue_t *const, uchar_t, uchar_t, uchar_t, int);
53 
54 int
VUID_OPEN(queue_t * const qp)55 VUID_OPEN(queue_t *const qp)
56 {
57 	STATEP->nbuttons = 2;
58 
59 	return (0);
60 }
61 
62 static void
vuidm3p_sendButtonEvent(queue_t * const qp)63 vuidm3p_sendButtonEvent(queue_t *const qp)
64 {
65 	int b;
66 
67 	if ((STATEP->buttons == 0x30) && (!STATEP->oldbuttons)) {
68 		/*
69 		 * both buttons going down simultaneously means button
70 		 * two going down
71 		 */
72 		vuidm3p_putnext(qp, (uchar_t)MS_MIDDLE, FE_PAIR_NONE, 0, 1);
73 		return;
74 	} else if ((!STATEP->buttons) && (STATEP->oldbuttons == 0x30)) {
75 		/*
76 		 * both buttons going up simultaneously means button
77 		 * two going up
78 		 */
79 		vuidm3p_putnext(qp, (uchar_t)MS_MIDDLE, FE_PAIR_NONE, 0, 0);
80 		return;
81 	}
82 
83 	/*
84 	 * for each button, see if it has changed
85 	 */
86 	for (b = 0; b < 2; b++) {
87 		uchar_t mask = 0x20 >> b;
88 
89 		if ((STATEP->buttons & mask) != (STATEP->oldbuttons & mask))
90 			VUID_PUTNEXT(qp, VUID_BUT(b), FE_PAIR_NONE, 0,
91 			    (STATEP->buttons & mask ? 1 : 0));
92 	}
93 }
94 
95 void
vuidm3p(queue_t * const qp,mblk_t * mp)96 vuidm3p(queue_t *const qp, mblk_t *mp)
97 {
98 	int r, code;
99 	uchar_t *bufp;
100 
101 	bufp = mp->b_rptr;
102 	r = MBLKL(mp);
103 
104 	for (r--; r >= 0; r--) {
105 		code = *bufp++;
106 
107 		/* strip the high-order bit (mouse sends 7-bit data) */
108 		code &= 0x7f;
109 
110 		switch (STATEP->state) {
111 
112 		/*
113 		 * Start state. We stay here if the start code is not
114 		 * received thus forcing us back into sync. When we
115 		 * get a start code the	button mask comes with it
116 		 * forcing us to the next state.
117 		 */
118 
119 		default:
120 		case MOUSE_START:
121 start_code:
122 			STATEP->deltax = STATEP->deltay = 0;
123 
124 			/* look for sync */
125 			if ((code & MOUSE_START_CODE) == 0)
126 				break;
127 
128 			STATEP->buttons = code & 0x30;
129 
130 			if (STATEP->buttons != STATEP->oldbuttons) {
131 				vuidm3p_sendButtonEvent(qp);
132 				/*
133 				 * remember state
134 				 */
135 				STATEP->oldbuttons = STATEP->buttons;
136 			}
137 
138 			/*
139 			 * bits 0 & 1 are bits 6 & 7 of X value
140 			 * (Sign extend them with the cast.)
141 			 */
142 			STATEP->deltax = (signed char)((code & 0x03) << 6);
143 
144 			/*
145 			 * bits 2 & 3 are bits 6 & 7 of Y value
146 			 * (Sign extend them with the cast.)
147 			 */
148 			STATEP->deltay = (signed char)((code & 0x0c) << 4);
149 
150 			/*
151 			 * go to the next state
152 			 */
153 			STATEP->state = MOUSE_BUTTON;
154 			break;
155 
156 			/*
157 			 * We receive the remaining 6 bits of delta x, forcing
158 			 * us to the next state. We just piece the value of
159 			 * delta x together.
160 			 */
161 		case MOUSE_BUTTON:
162 			if (code & MOUSE_START_CODE) {
163 				STATEP->state = MOUSE_START;
164 				goto start_code;	/* restart */
165 			}
166 
167 			STATEP->deltax |= code & 0x3f;
168 			STATEP->state = MOUSE_DELTA_X;
169 			break;
170 
171 			/*
172 			 * The last part of delta Y, and the packet
173 			 * *may be* complete
174 			 */
175 		case MOUSE_DELTA_X:
176 			if (code & MOUSE_START_CODE) {
177 				STATEP->state = MOUSE_START;
178 				goto start_code;	/* restart */
179 			}
180 
181 			STATEP->deltay |= code & 0x3f;
182 
183 			/*
184 			 * generate motion Event
185 			 */
186 			if (STATEP->deltax)
187 				VUID_PUTNEXT(qp, (uchar_t)LOC_X_DELTA,
188 				    FE_PAIR_ABSOLUTE, (uchar_t)LOC_X_ABSOLUTE,
189 				    STATEP->deltax);
190 
191 			if (STATEP->deltay)
192 				VUID_PUTNEXT(qp, (uchar_t)LOC_Y_DELTA,
193 				    FE_PAIR_ABSOLUTE, (uchar_t)LOC_Y_ABSOLUTE,
194 				    -STATEP->deltay);
195 
196 			STATEP->deltax = STATEP->deltay = 0;
197 			break;
198 		}
199 	}
200 
201 	freemsg(mp);
202 }
203