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