1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate *
4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate * with the License.
8*7c478bd9Sstevel@tonic-gate *
9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate *
14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate *
20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate */
26*7c478bd9Sstevel@tonic-gate
27*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI"
28*7c478bd9Sstevel@tonic-gate
29*7c478bd9Sstevel@tonic-gate /*
30*7c478bd9Sstevel@tonic-gate * Generic Keyboard Support: Polled I/O support for kbtrans-supported keyboards.
31*7c478bd9Sstevel@tonic-gate */
32*7c478bd9Sstevel@tonic-gate
33*7c478bd9Sstevel@tonic-gate #define KEYMAP_SIZE_VARIABLE
34*7c478bd9Sstevel@tonic-gate
35*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
36*7c478bd9Sstevel@tonic-gate #include <sys/stream.h>
37*7c478bd9Sstevel@tonic-gate #include <sys/kbd.h>
38*7c478bd9Sstevel@tonic-gate #include <sys/kbio.h>
39*7c478bd9Sstevel@tonic-gate #include <sys/vuid_event.h>
40*7c478bd9Sstevel@tonic-gate #include <sys/consdev.h>
41*7c478bd9Sstevel@tonic-gate #include <sys/kbtrans.h>
42*7c478bd9Sstevel@tonic-gate #include "kbtrans_lower.h"
43*7c478bd9Sstevel@tonic-gate #include "kbtrans_streams.h"
44*7c478bd9Sstevel@tonic-gate
45*7c478bd9Sstevel@tonic-gate /*
46*7c478bd9Sstevel@tonic-gate * Internal Function Prototypes
47*7c478bd9Sstevel@tonic-gate */
48*7c478bd9Sstevel@tonic-gate static void kbtrans_polled_pressed(struct kbtrans *, uint_t, kbtrans_key_t,
49*7c478bd9Sstevel@tonic-gate uint_t);
50*7c478bd9Sstevel@tonic-gate static void kbtrans_polled_released(struct kbtrans *, kbtrans_key_t);
51*7c478bd9Sstevel@tonic-gate static void kbtrans_polled_setled(struct kbtrans *);
52*7c478bd9Sstevel@tonic-gate static void kbtrans_polled_setup_repeat(struct kbtrans *, uint_t,
53*7c478bd9Sstevel@tonic-gate kbtrans_key_t);
54*7c478bd9Sstevel@tonic-gate static void kbtrans_polled_cancel_repeat(struct kbtrans *);
55*7c478bd9Sstevel@tonic-gate
56*7c478bd9Sstevel@tonic-gate /*
57*7c478bd9Sstevel@tonic-gate * Functions to be called when a key is translated during polled
58*7c478bd9Sstevel@tonic-gate * mode
59*7c478bd9Sstevel@tonic-gate */
60*7c478bd9Sstevel@tonic-gate struct keyboard_callback kbtrans_polled_callbacks = {
61*7c478bd9Sstevel@tonic-gate NULL, /* keypressed_raw */
62*7c478bd9Sstevel@tonic-gate NULL, /* keyreleased_raw */
63*7c478bd9Sstevel@tonic-gate kbtrans_polled_pressed, /* keypressed */
64*7c478bd9Sstevel@tonic-gate kbtrans_polled_released, /* keyreleased */
65*7c478bd9Sstevel@tonic-gate kbtrans_polled_setup_repeat, /* setup_repeat */
66*7c478bd9Sstevel@tonic-gate kbtrans_polled_cancel_repeat, /* cancel_repeat */
67*7c478bd9Sstevel@tonic-gate kbtrans_polled_setled, /* setled */
68*7c478bd9Sstevel@tonic-gate };
69*7c478bd9Sstevel@tonic-gate
70*7c478bd9Sstevel@tonic-gate /*
71*7c478bd9Sstevel@tonic-gate * kbtrans_ischar:
72*7c478bd9Sstevel@tonic-gate * Return B_TRUE if character is pending, else return B_FALSE
73*7c478bd9Sstevel@tonic-gate */
74*7c478bd9Sstevel@tonic-gate boolean_t
kbtrans_ischar(struct kbtrans * upper)75*7c478bd9Sstevel@tonic-gate kbtrans_ischar(struct kbtrans *upper)
76*7c478bd9Sstevel@tonic-gate {
77*7c478bd9Sstevel@tonic-gate struct kbtrans_callbacks *cb;
78*7c478bd9Sstevel@tonic-gate struct kbtrans_hardware *hw;
79*7c478bd9Sstevel@tonic-gate kbtrans_key_t key;
80*7c478bd9Sstevel@tonic-gate enum keystate state;
81*7c478bd9Sstevel@tonic-gate
82*7c478bd9Sstevel@tonic-gate /*
83*7c478bd9Sstevel@tonic-gate * If we've still got input pending, say so.
84*7c478bd9Sstevel@tonic-gate */
85*7c478bd9Sstevel@tonic-gate if (*upper->kbtrans_polled_pending_chars != '\0') {
86*7c478bd9Sstevel@tonic-gate return (B_TRUE);
87*7c478bd9Sstevel@tonic-gate }
88*7c478bd9Sstevel@tonic-gate
89*7c478bd9Sstevel@tonic-gate /*
90*7c478bd9Sstevel@tonic-gate * Reset to an empty buffer.
91*7c478bd9Sstevel@tonic-gate */
92*7c478bd9Sstevel@tonic-gate upper->kbtrans_polled_buf[0] = '\0';
93*7c478bd9Sstevel@tonic-gate upper->kbtrans_polled_pending_chars = upper->kbtrans_polled_buf;
94*7c478bd9Sstevel@tonic-gate
95*7c478bd9Sstevel@tonic-gate cb = upper->kbtrans_streams_hw_callbacks;
96*7c478bd9Sstevel@tonic-gate hw = upper->kbtrans_streams_hw;
97*7c478bd9Sstevel@tonic-gate
98*7c478bd9Sstevel@tonic-gate /*
99*7c478bd9Sstevel@tonic-gate * Process scancodes until either we have input ready
100*7c478bd9Sstevel@tonic-gate * or we run out of scancodes.
101*7c478bd9Sstevel@tonic-gate */
102*7c478bd9Sstevel@tonic-gate while (cb->kbtrans_polled_keycheck(hw, &key, &state)) {
103*7c478bd9Sstevel@tonic-gate kbtrans_processkey(&upper->kbtrans_lower,
104*7c478bd9Sstevel@tonic-gate &kbtrans_polled_callbacks, key, state);
105*7c478bd9Sstevel@tonic-gate /*
106*7c478bd9Sstevel@tonic-gate * If that generated any input, we're ready.
107*7c478bd9Sstevel@tonic-gate */
108*7c478bd9Sstevel@tonic-gate if (*upper->kbtrans_polled_pending_chars != '\0') {
109*7c478bd9Sstevel@tonic-gate return (B_TRUE);
110*7c478bd9Sstevel@tonic-gate }
111*7c478bd9Sstevel@tonic-gate }
112*7c478bd9Sstevel@tonic-gate
113*7c478bd9Sstevel@tonic-gate return (B_FALSE);
114*7c478bd9Sstevel@tonic-gate }
115*7c478bd9Sstevel@tonic-gate
116*7c478bd9Sstevel@tonic-gate /*
117*7c478bd9Sstevel@tonic-gate * kbtrans_getchar:
118*7c478bd9Sstevel@tonic-gate * Return a character
119*7c478bd9Sstevel@tonic-gate */
120*7c478bd9Sstevel@tonic-gate int
kbtrans_getchar(struct kbtrans * upper)121*7c478bd9Sstevel@tonic-gate kbtrans_getchar(struct kbtrans *upper)
122*7c478bd9Sstevel@tonic-gate {
123*7c478bd9Sstevel@tonic-gate while (!kbtrans_ischar(upper))
124*7c478bd9Sstevel@tonic-gate /* LOOP */;
125*7c478bd9Sstevel@tonic-gate
126*7c478bd9Sstevel@tonic-gate return (*upper->kbtrans_polled_pending_chars++);
127*7c478bd9Sstevel@tonic-gate }
128*7c478bd9Sstevel@tonic-gate
129*7c478bd9Sstevel@tonic-gate void
kbtrans_polled_putcode(struct kbtrans * upper,char code)130*7c478bd9Sstevel@tonic-gate kbtrans_polled_putcode(struct kbtrans *upper, char code)
131*7c478bd9Sstevel@tonic-gate {
132*7c478bd9Sstevel@tonic-gate int i;
133*7c478bd9Sstevel@tonic-gate
134*7c478bd9Sstevel@tonic-gate /*
135*7c478bd9Sstevel@tonic-gate * NB: KBTRANS_POLLED_BUF_SIZE is one smaller than
136*7c478bd9Sstevel@tonic-gate * the size of the buffer, to allow for a trailing
137*7c478bd9Sstevel@tonic-gate * null.
138*7c478bd9Sstevel@tonic-gate */
139*7c478bd9Sstevel@tonic-gate for (i = 0; i < KBTRANS_POLLED_BUF_SIZE; i++) {
140*7c478bd9Sstevel@tonic-gate if (upper->kbtrans_polled_buf[i] == '\0') {
141*7c478bd9Sstevel@tonic-gate upper->kbtrans_polled_buf[i] = code;
142*7c478bd9Sstevel@tonic-gate upper->kbtrans_polled_buf[i+1] = '\0';
143*7c478bd9Sstevel@tonic-gate return;
144*7c478bd9Sstevel@tonic-gate }
145*7c478bd9Sstevel@tonic-gate }
146*7c478bd9Sstevel@tonic-gate DPRINTF(PRINT_L2, PRINT_MASK_PACKET,
147*7c478bd9Sstevel@tonic-gate (upper, "kbtrans_polled_pressed: "
148*7c478bd9Sstevel@tonic-gate "buffer overflow, character 0x%x discarded\n", code));
149*7c478bd9Sstevel@tonic-gate /*
150*7c478bd9Sstevel@tonic-gate * Didn't fit, throw it on the floor.
151*7c478bd9Sstevel@tonic-gate */
152*7c478bd9Sstevel@tonic-gate }
153*7c478bd9Sstevel@tonic-gate
154*7c478bd9Sstevel@tonic-gate /*
155*7c478bd9Sstevel@tonic-gate * kbtrans_polled_pressed:
156*7c478bd9Sstevel@tonic-gate * This function is called when we are in polled mode and a key is
157*7c478bd9Sstevel@tonic-gate * pressed. The key is put into the kbtrans_polled_buf so that it
158*7c478bd9Sstevel@tonic-gate * can be picked up later by kbtrans_ischar()
159*7c478bd9Sstevel@tonic-gate */
160*7c478bd9Sstevel@tonic-gate /*ARGSUSED2*/
161*7c478bd9Sstevel@tonic-gate static void
kbtrans_polled_pressed(struct kbtrans * upper,uint_t entrytype,kbtrans_key_t key,uint_t entry)162*7c478bd9Sstevel@tonic-gate kbtrans_polled_pressed(
163*7c478bd9Sstevel@tonic-gate struct kbtrans *upper,
164*7c478bd9Sstevel@tonic-gate uint_t entrytype,
165*7c478bd9Sstevel@tonic-gate kbtrans_key_t key,
166*7c478bd9Sstevel@tonic-gate uint_t entry)
167*7c478bd9Sstevel@tonic-gate {
168*7c478bd9Sstevel@tonic-gate struct kbtrans_lower *lower = &upper->kbtrans_lower;
169*7c478bd9Sstevel@tonic-gate register char *cp;
170*7c478bd9Sstevel@tonic-gate
171*7c478bd9Sstevel@tonic-gate /*
172*7c478bd9Sstevel@tonic-gate * Based on the type of key, we may need to do some ASCII
173*7c478bd9Sstevel@tonic-gate * specific post processing.
174*7c478bd9Sstevel@tonic-gate */
175*7c478bd9Sstevel@tonic-gate switch (entrytype) {
176*7c478bd9Sstevel@tonic-gate
177*7c478bd9Sstevel@tonic-gate case BUCKYBITS:
178*7c478bd9Sstevel@tonic-gate case SHIFTKEYS:
179*7c478bd9Sstevel@tonic-gate case FUNNY:
180*7c478bd9Sstevel@tonic-gate /*
181*7c478bd9Sstevel@tonic-gate * There is no ascii equivalent. We will ignore these
182*7c478bd9Sstevel@tonic-gate * keys
183*7c478bd9Sstevel@tonic-gate */
184*7c478bd9Sstevel@tonic-gate break;
185*7c478bd9Sstevel@tonic-gate
186*7c478bd9Sstevel@tonic-gate case FUNCKEYS:
187*7c478bd9Sstevel@tonic-gate /*
188*7c478bd9Sstevel@tonic-gate * These will no doubt only cause problems. Ignore them.
189*7c478bd9Sstevel@tonic-gate */
190*7c478bd9Sstevel@tonic-gate
191*7c478bd9Sstevel@tonic-gate break;
192*7c478bd9Sstevel@tonic-gate
193*7c478bd9Sstevel@tonic-gate case STRING:
194*7c478bd9Sstevel@tonic-gate /*
195*7c478bd9Sstevel@tonic-gate * These are the multi byte keys (Home, Up, Down ...)
196*7c478bd9Sstevel@tonic-gate */
197*7c478bd9Sstevel@tonic-gate cp = &lower->kbtrans_keystringtab[entry & 0x0F][0];
198*7c478bd9Sstevel@tonic-gate
199*7c478bd9Sstevel@tonic-gate /*
200*7c478bd9Sstevel@tonic-gate * Copy the string from the keystringtable, and send it
201*7c478bd9Sstevel@tonic-gate * upstream a character at a time.
202*7c478bd9Sstevel@tonic-gate */
203*7c478bd9Sstevel@tonic-gate while (*cp != '\0') {
204*7c478bd9Sstevel@tonic-gate kbtrans_polled_putcode(upper, *cp);
205*7c478bd9Sstevel@tonic-gate cp++;
206*7c478bd9Sstevel@tonic-gate }
207*7c478bd9Sstevel@tonic-gate
208*7c478bd9Sstevel@tonic-gate return;
209*7c478bd9Sstevel@tonic-gate
210*7c478bd9Sstevel@tonic-gate case PADKEYS:
211*7c478bd9Sstevel@tonic-gate /*
212*7c478bd9Sstevel@tonic-gate * These are the keys on the keypad. Look up the
213*7c478bd9Sstevel@tonic-gate * answer in the kb_numlock_table and send it upstream.
214*7c478bd9Sstevel@tonic-gate */
215*7c478bd9Sstevel@tonic-gate kbtrans_polled_putcode(upper,
216*7c478bd9Sstevel@tonic-gate lower->kbtrans_numlock_table[entry&0x1F]);
217*7c478bd9Sstevel@tonic-gate
218*7c478bd9Sstevel@tonic-gate break;
219*7c478bd9Sstevel@tonic-gate
220*7c478bd9Sstevel@tonic-gate case 0: /* normal character */
221*7c478bd9Sstevel@tonic-gate default:
222*7c478bd9Sstevel@tonic-gate /*
223*7c478bd9Sstevel@tonic-gate * Send the byte upstream.
224*7c478bd9Sstevel@tonic-gate */
225*7c478bd9Sstevel@tonic-gate kbtrans_polled_putcode(upper, (char)entry);
226*7c478bd9Sstevel@tonic-gate break;
227*7c478bd9Sstevel@tonic-gate }
228*7c478bd9Sstevel@tonic-gate }
229*7c478bd9Sstevel@tonic-gate
230*7c478bd9Sstevel@tonic-gate /*
231*7c478bd9Sstevel@tonic-gate * kbtrans_polled_released:
232*7c478bd9Sstevel@tonic-gate * This function is called when a key is released. Nothing is
233*7c478bd9Sstevel@tonic-gate * done.
234*7c478bd9Sstevel@tonic-gate */
235*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/
236*7c478bd9Sstevel@tonic-gate static void
kbtrans_polled_released(struct kbtrans * upper,kbtrans_key_t key)237*7c478bd9Sstevel@tonic-gate kbtrans_polled_released(struct kbtrans *upper, kbtrans_key_t key)
238*7c478bd9Sstevel@tonic-gate {
239*7c478bd9Sstevel@tonic-gate /* Nothing for now */
240*7c478bd9Sstevel@tonic-gate }
241*7c478bd9Sstevel@tonic-gate
242*7c478bd9Sstevel@tonic-gate /*
243*7c478bd9Sstevel@tonic-gate * kbtrans_polled_setled:
244*7c478bd9Sstevel@tonic-gate * This function is called to set the LEDs.
245*7c478bd9Sstevel@tonic-gate */
246*7c478bd9Sstevel@tonic-gate static void
kbtrans_polled_setled(struct kbtrans * upper)247*7c478bd9Sstevel@tonic-gate kbtrans_polled_setled(struct kbtrans *upper)
248*7c478bd9Sstevel@tonic-gate {
249*7c478bd9Sstevel@tonic-gate struct kbtrans_callbacks *cb;
250*7c478bd9Sstevel@tonic-gate struct kbtrans_hardware *hw;
251*7c478bd9Sstevel@tonic-gate
252*7c478bd9Sstevel@tonic-gate cb = upper->kbtrans_streams_hw_callbacks;
253*7c478bd9Sstevel@tonic-gate hw = upper->kbtrans_streams_hw;
254*7c478bd9Sstevel@tonic-gate
255*7c478bd9Sstevel@tonic-gate cb->kbtrans_polled_setled(hw, upper->kbtrans_lower.kbtrans_led_state);
256*7c478bd9Sstevel@tonic-gate }
257*7c478bd9Sstevel@tonic-gate
258*7c478bd9Sstevel@tonic-gate /*
259*7c478bd9Sstevel@tonic-gate * kbtrans_polled_setup_repeat:
260*7c478bd9Sstevel@tonic-gate * Function to be called in order to handle a repeating key.
261*7c478bd9Sstevel@tonic-gate * Nothing is done.
262*7c478bd9Sstevel@tonic-gate */
263*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/
264*7c478bd9Sstevel@tonic-gate static void
kbtrans_polled_setup_repeat(struct kbtrans * upper,uint_t entrytype,kbtrans_key_t key)265*7c478bd9Sstevel@tonic-gate kbtrans_polled_setup_repeat(
266*7c478bd9Sstevel@tonic-gate struct kbtrans *upper,
267*7c478bd9Sstevel@tonic-gate uint_t entrytype,
268*7c478bd9Sstevel@tonic-gate kbtrans_key_t key)
269*7c478bd9Sstevel@tonic-gate {
270*7c478bd9Sstevel@tonic-gate /* Nothing for now */
271*7c478bd9Sstevel@tonic-gate }
272*7c478bd9Sstevel@tonic-gate
273*7c478bd9Sstevel@tonic-gate /*
274*7c478bd9Sstevel@tonic-gate * kbtrans_polled_cancel_repeat:
275*7c478bd9Sstevel@tonic-gate * Function to be called to cancel a repeating key,
276*7c478bd9Sstevel@tonic-gate * so that we don't end up with an autorepeating key
277*7c478bd9Sstevel@tonic-gate * on the stream because its release was handled by the
278*7c478bd9Sstevel@tonic-gate * polled code.
279*7c478bd9Sstevel@tonic-gate */
280*7c478bd9Sstevel@tonic-gate static void
kbtrans_polled_cancel_repeat(struct kbtrans * upper)281*7c478bd9Sstevel@tonic-gate kbtrans_polled_cancel_repeat(struct kbtrans *upper)
282*7c478bd9Sstevel@tonic-gate {
283*7c478bd9Sstevel@tonic-gate /*
284*7c478bd9Sstevel@tonic-gate * Streams code will time out and will discard the
285*7c478bd9Sstevel@tonic-gate * autorepeat.
286*7c478bd9Sstevel@tonic-gate */
287*7c478bd9Sstevel@tonic-gate upper->kbtrans_lower.kbtrans_repeatkey = 0;
288*7c478bd9Sstevel@tonic-gate }
289