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 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 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 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 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 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 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 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 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