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