10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 51272Slq150181 * Common Development and Distribution License (the "License"). 61272Slq150181 * You may not use this file except in compliance with the License. 70Sstevel@tonic-gate * 80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 100Sstevel@tonic-gate * See the License for the specific language governing permissions 110Sstevel@tonic-gate * and limitations under the License. 120Sstevel@tonic-gate * 130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 180Sstevel@tonic-gate * 190Sstevel@tonic-gate * CDDL HEADER END 200Sstevel@tonic-gate */ 211272Slq150181 220Sstevel@tonic-gate /* 238960SJan.Setje-Eilers@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 240Sstevel@tonic-gate * Use is subject to license terms. 250Sstevel@tonic-gate */ 260Sstevel@tonic-gate 270Sstevel@tonic-gate /* 280Sstevel@tonic-gate * Generic keyboard support: streams and administration. 290Sstevel@tonic-gate */ 300Sstevel@tonic-gate 310Sstevel@tonic-gate #define KEYMAP_SIZE_VARIABLE 320Sstevel@tonic-gate 330Sstevel@tonic-gate #include <sys/types.h> 340Sstevel@tonic-gate #include <sys/cred.h> 350Sstevel@tonic-gate #include <sys/stream.h> 360Sstevel@tonic-gate #include <sys/stropts.h> 370Sstevel@tonic-gate #include <sys/strsun.h> 380Sstevel@tonic-gate #include <sys/ddi.h> 390Sstevel@tonic-gate #include <sys/vuid_event.h> 400Sstevel@tonic-gate #include <sys/modctl.h> 410Sstevel@tonic-gate #include <sys/errno.h> 420Sstevel@tonic-gate #include <sys/kmem.h> 430Sstevel@tonic-gate #include <sys/cmn_err.h> 440Sstevel@tonic-gate #include <sys/kbd.h> 450Sstevel@tonic-gate #include <sys/kbio.h> 460Sstevel@tonic-gate #include <sys/consdev.h> 470Sstevel@tonic-gate #include <sys/kbtrans.h> 480Sstevel@tonic-gate #include <sys/policy.h> 498960SJan.Setje-Eilers@Sun.COM #include <sys/sunldi.h> 508974SJan.Setje-Eilers@Sun.COM #include <sys/class.h> 518974SJan.Setje-Eilers@Sun.COM #include <sys/spl.h> 520Sstevel@tonic-gate #include "kbtrans_lower.h" 530Sstevel@tonic-gate #include "kbtrans_streams.h" 540Sstevel@tonic-gate 550Sstevel@tonic-gate #ifdef DEBUG 560Sstevel@tonic-gate int kbtrans_errmask; 570Sstevel@tonic-gate int kbtrans_errlevel; 580Sstevel@tonic-gate #endif 590Sstevel@tonic-gate 607688SAaron.Zang@Sun.COM #define KB_NR_FUNCKEYS 12 617688SAaron.Zang@Sun.COM 620Sstevel@tonic-gate /* 630Sstevel@tonic-gate * Repeat rates set in static variables so they can be tweeked with 640Sstevel@tonic-gate * debugger. 650Sstevel@tonic-gate */ 660Sstevel@tonic-gate static int kbtrans_repeat_rate; 670Sstevel@tonic-gate static int kbtrans_repeat_delay; 680Sstevel@tonic-gate 690Sstevel@tonic-gate /* Printing message on q overflow */ 700Sstevel@tonic-gate static int kbtrans_overflow_msg = 1; 710Sstevel@tonic-gate 720Sstevel@tonic-gate /* 730Sstevel@tonic-gate * This value corresponds approximately to max 10 fingers 740Sstevel@tonic-gate */ 750Sstevel@tonic-gate static int kbtrans_downs_size = 15; 760Sstevel@tonic-gate 770Sstevel@tonic-gate /* 780Sstevel@tonic-gate * modload support 790Sstevel@tonic-gate */ 800Sstevel@tonic-gate extern struct mod_ops mod_miscops; 810Sstevel@tonic-gate 820Sstevel@tonic-gate static struct modlmisc modlmisc = { 830Sstevel@tonic-gate &mod_miscops, /* Type of module */ 847688SAaron.Zang@Sun.COM "kbtrans (key translation)" 850Sstevel@tonic-gate }; 860Sstevel@tonic-gate 870Sstevel@tonic-gate static struct modlinkage modlinkage = { 880Sstevel@tonic-gate MODREV_1, (void *)&modlmisc, NULL 890Sstevel@tonic-gate }; 900Sstevel@tonic-gate 910Sstevel@tonic-gate int 920Sstevel@tonic-gate _init(void) 930Sstevel@tonic-gate { 940Sstevel@tonic-gate return (mod_install(&modlinkage)); 950Sstevel@tonic-gate } 960Sstevel@tonic-gate 970Sstevel@tonic-gate int 980Sstevel@tonic-gate _fini(void) 990Sstevel@tonic-gate { 1000Sstevel@tonic-gate return (mod_remove(&modlinkage)); 1010Sstevel@tonic-gate } 1020Sstevel@tonic-gate 1030Sstevel@tonic-gate int 1040Sstevel@tonic-gate _info(struct modinfo *modinfop) 1050Sstevel@tonic-gate { 1060Sstevel@tonic-gate return (mod_info(&modlinkage, modinfop)); 1070Sstevel@tonic-gate } 1080Sstevel@tonic-gate 1090Sstevel@tonic-gate /* 1100Sstevel@tonic-gate * Internal Function Prototypes 1110Sstevel@tonic-gate */ 1120Sstevel@tonic-gate static char *kbtrans_strsetwithdecimal(char *, uint_t, uint_t); 1130Sstevel@tonic-gate static void kbtrans_set_translation_callback(struct kbtrans *); 1140Sstevel@tonic-gate static void kbtrans_reioctl(void *); 1150Sstevel@tonic-gate static void kbtrans_send_esc_event(char, struct kbtrans *); 1160Sstevel@tonic-gate static void kbtrans_keypressed(struct kbtrans *, uchar_t, Firm_event *, 1170Sstevel@tonic-gate ushort_t); 1180Sstevel@tonic-gate static void kbtrans_putbuf(char *, queue_t *); 1190Sstevel@tonic-gate static void kbtrans_cancelrpt(struct kbtrans *); 1200Sstevel@tonic-gate static void kbtrans_queuepress(struct kbtrans *, uchar_t, Firm_event *); 1210Sstevel@tonic-gate static void kbtrans_putcode(register struct kbtrans *, uint_t); 1220Sstevel@tonic-gate static void kbtrans_keyreleased(struct kbtrans *, uchar_t); 1230Sstevel@tonic-gate static void kbtrans_queueevent(struct kbtrans *, Firm_event *); 1240Sstevel@tonic-gate static void kbtrans_untrans_keypressed_raw(struct kbtrans *, kbtrans_key_t); 1250Sstevel@tonic-gate static void kbtrans_untrans_keyreleased_raw(struct kbtrans *, 1260Sstevel@tonic-gate kbtrans_key_t); 1270Sstevel@tonic-gate static void kbtrans_ascii_keypressed(struct kbtrans *, uint_t, 1280Sstevel@tonic-gate kbtrans_key_t, uint_t); 1290Sstevel@tonic-gate static void kbtrans_ascii_keyreleased(struct kbtrans *, kbtrans_key_t); 1300Sstevel@tonic-gate static void kbtrans_ascii_setup_repeat(struct kbtrans *, uint_t, 1310Sstevel@tonic-gate kbtrans_key_t); 1320Sstevel@tonic-gate static void kbtrans_trans_event_keypressed(struct kbtrans *, uint_t, 1330Sstevel@tonic-gate kbtrans_key_t, uint_t); 1340Sstevel@tonic-gate static void kbtrans_trans_event_keyreleased(struct kbtrans *, 1350Sstevel@tonic-gate kbtrans_key_t); 1360Sstevel@tonic-gate static void kbtrans_trans_event_setup_repeat(struct kbtrans *, uint_t, 1370Sstevel@tonic-gate kbtrans_key_t); 1380Sstevel@tonic-gate static void kbtrans_rpt(void *); 1390Sstevel@tonic-gate static void kbtrans_setled(struct kbtrans *); 1400Sstevel@tonic-gate static void kbtrans_flush(struct kbtrans *); 1410Sstevel@tonic-gate static enum kbtrans_message_response kbtrans_ioctl(struct kbtrans *upper, 1420Sstevel@tonic-gate mblk_t *mp); 1430Sstevel@tonic-gate static int kbtrans_setkey(struct kbtrans_lower *, struct kiockey *, 1440Sstevel@tonic-gate cred_t *); 1450Sstevel@tonic-gate static int kbtrans_getkey(struct kbtrans_lower *, struct kiockey *); 1460Sstevel@tonic-gate static int kbtrans_skey(struct kbtrans_lower *, struct kiockeymap *, 1470Sstevel@tonic-gate cred_t *cr); 1480Sstevel@tonic-gate static int kbtrans_gkey(struct kbtrans_lower *, struct kiockeymap *); 1490Sstevel@tonic-gate 1500Sstevel@tonic-gate /* 1510Sstevel@tonic-gate * Keyboard Translation Mode (TR_NONE) 1520Sstevel@tonic-gate * 1530Sstevel@tonic-gate * Functions to be called when keyboard translation is turned off 1540Sstevel@tonic-gate * and up/down key codes are reported. 1550Sstevel@tonic-gate */ 1560Sstevel@tonic-gate struct keyboard_callback untrans_event_callback = { 1570Sstevel@tonic-gate kbtrans_untrans_keypressed_raw, 1580Sstevel@tonic-gate kbtrans_untrans_keyreleased_raw, 1590Sstevel@tonic-gate NULL, 1600Sstevel@tonic-gate NULL, 1610Sstevel@tonic-gate NULL, 1620Sstevel@tonic-gate NULL, 1630Sstevel@tonic-gate NULL, 1640Sstevel@tonic-gate }; 1650Sstevel@tonic-gate 1660Sstevel@tonic-gate /* 1670Sstevel@tonic-gate * Keyboard Translation Mode (TR_ASCII) 1680Sstevel@tonic-gate * 1690Sstevel@tonic-gate * Functions to be called when ISO 8859/1 codes are reported 1700Sstevel@tonic-gate */ 1710Sstevel@tonic-gate struct keyboard_callback ascii_callback = { 1720Sstevel@tonic-gate NULL, 1730Sstevel@tonic-gate NULL, 1740Sstevel@tonic-gate kbtrans_ascii_keypressed, 1750Sstevel@tonic-gate kbtrans_ascii_keyreleased, 1760Sstevel@tonic-gate kbtrans_ascii_setup_repeat, 1770Sstevel@tonic-gate kbtrans_cancelrpt, 1780Sstevel@tonic-gate kbtrans_setled, 1790Sstevel@tonic-gate }; 1800Sstevel@tonic-gate 1810Sstevel@tonic-gate /* 1820Sstevel@tonic-gate * Keyboard Translation Mode (TR_EVENT) 1830Sstevel@tonic-gate * 1840Sstevel@tonic-gate * Functions to be called when firm_events are reported. 1850Sstevel@tonic-gate */ 1860Sstevel@tonic-gate struct keyboard_callback trans_event_callback = { 1870Sstevel@tonic-gate NULL, 1880Sstevel@tonic-gate NULL, 1890Sstevel@tonic-gate kbtrans_trans_event_keypressed, 1900Sstevel@tonic-gate kbtrans_trans_event_keyreleased, 1910Sstevel@tonic-gate kbtrans_trans_event_setup_repeat, 1920Sstevel@tonic-gate kbtrans_cancelrpt, 1930Sstevel@tonic-gate kbtrans_setled, 1940Sstevel@tonic-gate }; 1950Sstevel@tonic-gate 1968974SJan.Setje-Eilers@Sun.COM static void 1978974SJan.Setje-Eilers@Sun.COM progressbar_key_abort_thread(struct kbtrans *upper) 1988974SJan.Setje-Eilers@Sun.COM { 1998974SJan.Setje-Eilers@Sun.COM ldi_ident_t li; 2008974SJan.Setje-Eilers@Sun.COM extern void progressbar_key_abort(ldi_ident_t); 2018974SJan.Setje-Eilers@Sun.COM 2028974SJan.Setje-Eilers@Sun.COM if (ldi_ident_from_stream(upper->kbtrans_streams_readq, &li) != 0) { 2038974SJan.Setje-Eilers@Sun.COM cmn_err(CE_NOTE, "!ldi_ident_from_stream failed"); 2048974SJan.Setje-Eilers@Sun.COM } else { 2058974SJan.Setje-Eilers@Sun.COM mutex_enter(&upper->progressbar_key_abort_lock); 2068974SJan.Setje-Eilers@Sun.COM while (upper->progressbar_key_abort_flag == 0) 2078974SJan.Setje-Eilers@Sun.COM cv_wait(&upper->progressbar_key_abort_cv, 2088974SJan.Setje-Eilers@Sun.COM &upper->progressbar_key_abort_lock); 209*9462SJan.Setje-Eilers@Sun.COM if (upper->progressbar_key_abort_flag == 1) { 210*9462SJan.Setje-Eilers@Sun.COM mutex_exit(&upper->progressbar_key_abort_lock); 2118974SJan.Setje-Eilers@Sun.COM progressbar_key_abort(li); 212*9462SJan.Setje-Eilers@Sun.COM } else { 213*9462SJan.Setje-Eilers@Sun.COM mutex_exit(&upper->progressbar_key_abort_lock); 214*9462SJan.Setje-Eilers@Sun.COM } 2158974SJan.Setje-Eilers@Sun.COM ldi_ident_release(li); 2168974SJan.Setje-Eilers@Sun.COM } 2178974SJan.Setje-Eilers@Sun.COM 2188974SJan.Setje-Eilers@Sun.COM thread_exit(); 2198974SJan.Setje-Eilers@Sun.COM } 2208974SJan.Setje-Eilers@Sun.COM 2210Sstevel@tonic-gate /* 2220Sstevel@tonic-gate * kbtrans_streams_init: 2230Sstevel@tonic-gate * Initialize the stream, keytables, callbacks, etc. 2240Sstevel@tonic-gate */ 2250Sstevel@tonic-gate int 2260Sstevel@tonic-gate kbtrans_streams_init( 2270Sstevel@tonic-gate queue_t *q, 2280Sstevel@tonic-gate int sflag, 2290Sstevel@tonic-gate cred_t *crp, 2300Sstevel@tonic-gate struct kbtrans_hardware *hw, 2310Sstevel@tonic-gate struct kbtrans_callbacks *hw_cb, 2320Sstevel@tonic-gate struct kbtrans **ret_kbd, 2330Sstevel@tonic-gate int initial_leds, 2340Sstevel@tonic-gate int initial_led_mask) 2350Sstevel@tonic-gate { 2360Sstevel@tonic-gate struct kbtrans *upper; 2370Sstevel@tonic-gate struct kbtrans_lower *lower; 2380Sstevel@tonic-gate int err; 2399022SJan.Setje-Eilers@Sun.COM kthread_t *tid; 2400Sstevel@tonic-gate 2410Sstevel@tonic-gate /* 2420Sstevel@tonic-gate * Default to relatively generic tables. 2430Sstevel@tonic-gate */ 2440Sstevel@tonic-gate extern signed char kb_compose_map[]; 2450Sstevel@tonic-gate extern struct compose_sequence_t kb_compose_table[]; 2460Sstevel@tonic-gate extern struct fltaccent_sequence_t kb_fltaccent_table[]; 2470Sstevel@tonic-gate extern char keystringtab[][KTAB_STRLEN]; 2480Sstevel@tonic-gate extern unsigned char kb_numlock_table[]; 2490Sstevel@tonic-gate 2500Sstevel@tonic-gate /* Set these up only once so that they could be changed from adb */ 2510Sstevel@tonic-gate if (!kbtrans_repeat_rate) { 2520Sstevel@tonic-gate kbtrans_repeat_rate = (hz+29)/30; 2530Sstevel@tonic-gate kbtrans_repeat_delay = hz/2; 2540Sstevel@tonic-gate } 2550Sstevel@tonic-gate 2560Sstevel@tonic-gate /* 2570Sstevel@tonic-gate * Only allow open requests to succeed for privileged users. This 2580Sstevel@tonic-gate * necessary to prevent users from pushing the this module again 2590Sstevel@tonic-gate * on the stream associated with /dev/kbd. 2600Sstevel@tonic-gate */ 2610Sstevel@tonic-gate err = secpolicy_console(crp); 2620Sstevel@tonic-gate 2630Sstevel@tonic-gate if (err != 0) { 2640Sstevel@tonic-gate return (err); 2650Sstevel@tonic-gate } 2660Sstevel@tonic-gate 2670Sstevel@tonic-gate switch (sflag) { 2680Sstevel@tonic-gate 2690Sstevel@tonic-gate case MODOPEN: 2700Sstevel@tonic-gate break; 2710Sstevel@tonic-gate 2720Sstevel@tonic-gate case CLONEOPEN: 2730Sstevel@tonic-gate DPRINTF(PRINT_L1, PRINT_MASK_OPEN, (NULL, 2747688SAaron.Zang@Sun.COM "kbtrans_streams_init: Clone open not supported")); 2750Sstevel@tonic-gate 2760Sstevel@tonic-gate return (EINVAL); 2770Sstevel@tonic-gate } 2780Sstevel@tonic-gate 2790Sstevel@tonic-gate /* allocate keyboard state structure */ 2800Sstevel@tonic-gate upper = kmem_zalloc(sizeof (struct kbtrans), KM_SLEEP); 2810Sstevel@tonic-gate 2820Sstevel@tonic-gate *ret_kbd = upper; 2830Sstevel@tonic-gate 2840Sstevel@tonic-gate upper->kbtrans_polled_buf[0] = '\0'; 2850Sstevel@tonic-gate upper->kbtrans_polled_pending_chars = upper->kbtrans_polled_buf; 2860Sstevel@tonic-gate 2870Sstevel@tonic-gate upper->kbtrans_streams_hw = hw; 2880Sstevel@tonic-gate upper->kbtrans_streams_hw_callbacks = hw_cb; 2890Sstevel@tonic-gate upper->kbtrans_streams_readq = q; 2900Sstevel@tonic-gate upper->kbtrans_streams_iocpending = NULL; 2910Sstevel@tonic-gate upper->kbtrans_streams_translatable = TR_CAN; 2920Sstevel@tonic-gate upper->kbtrans_overflow_cnt = 0; 2930Sstevel@tonic-gate upper->kbtrans_streams_translate_mode = TR_ASCII; 2940Sstevel@tonic-gate 2950Sstevel@tonic-gate /* Set the translation callback based on the translation type */ 2960Sstevel@tonic-gate kbtrans_set_translation_callback(upper); 2970Sstevel@tonic-gate 2980Sstevel@tonic-gate lower = &upper->kbtrans_lower; 2990Sstevel@tonic-gate 3000Sstevel@tonic-gate /* 3010Sstevel@tonic-gate * Set defaults for relatively generic tables. 3020Sstevel@tonic-gate */ 3030Sstevel@tonic-gate lower->kbtrans_compose_map = kb_compose_map; 3040Sstevel@tonic-gate lower->kbtrans_compose_table = kb_compose_table; 3050Sstevel@tonic-gate lower->kbtrans_fltaccent_table = kb_fltaccent_table; 3060Sstevel@tonic-gate lower->kbtrans_numlock_table = kb_numlock_table; 3070Sstevel@tonic-gate lower->kbtrans_keystringtab = keystringtab; 3080Sstevel@tonic-gate 3090Sstevel@tonic-gate lower->kbtrans_upper = upper; 3100Sstevel@tonic-gate lower->kbtrans_compat = 1; 3110Sstevel@tonic-gate 3120Sstevel@tonic-gate /* 3130Sstevel@tonic-gate * We have a generic default for the LED state, and let the 3140Sstevel@tonic-gate * hardware-specific driver supply overrides. 3150Sstevel@tonic-gate */ 3160Sstevel@tonic-gate lower->kbtrans_led_state = 0; 3170Sstevel@tonic-gate lower->kbtrans_led_state &= ~initial_led_mask; 3180Sstevel@tonic-gate lower->kbtrans_led_state |= initial_leds; 3190Sstevel@tonic-gate lower->kbtrans_togglemask = 0; 3200Sstevel@tonic-gate 3210Sstevel@tonic-gate if (lower->kbtrans_led_state & LED_CAPS_LOCK) 3220Sstevel@tonic-gate lower->kbtrans_togglemask |= CAPSMASK; 3230Sstevel@tonic-gate if (lower->kbtrans_led_state & LED_NUM_LOCK) 3240Sstevel@tonic-gate lower->kbtrans_togglemask |= NUMLOCKMASK; 3250Sstevel@tonic-gate 3260Sstevel@tonic-gate #if defined(SCROLLMASK) 3270Sstevel@tonic-gate if (lower->kbtrans_led_state & LED_SCROLL_LOCK) 3280Sstevel@tonic-gate lower->kbtrans_togglemask |= SCROLLMASK; 3290Sstevel@tonic-gate #endif 3300Sstevel@tonic-gate 3310Sstevel@tonic-gate lower->kbtrans_shiftmask = lower->kbtrans_togglemask; 3320Sstevel@tonic-gate 3330Sstevel@tonic-gate upper->kbtrans_streams_vuid_addr.ascii = ASCII_FIRST; 3340Sstevel@tonic-gate upper->kbtrans_streams_vuid_addr.top = TOP_FIRST; 3350Sstevel@tonic-gate upper->kbtrans_streams_vuid_addr.vkey = VKEY_FIRST; 3360Sstevel@tonic-gate 3370Sstevel@tonic-gate /* Allocate dynamic memory for downs table */ 3380Sstevel@tonic-gate upper->kbtrans_streams_num_downs_entries = kbtrans_downs_size; 3390Sstevel@tonic-gate upper->kbtrans_streams_downs_bytes = 3407688SAaron.Zang@Sun.COM (uint32_t)(kbtrans_downs_size * sizeof (Key_event)); 3410Sstevel@tonic-gate upper->kbtrans_streams_downs = 3427688SAaron.Zang@Sun.COM kmem_zalloc(upper->kbtrans_streams_downs_bytes, KM_SLEEP); 3430Sstevel@tonic-gate upper->kbtrans_streams_abortable = B_FALSE; 3440Sstevel@tonic-gate 3450Sstevel@tonic-gate upper->kbtrans_streams_flags = KBTRANS_STREAMS_OPEN; 3460Sstevel@tonic-gate 3478974SJan.Setje-Eilers@Sun.COM upper->progressbar_key_abort_flag = 0; 3488974SJan.Setje-Eilers@Sun.COM cv_init(&upper->progressbar_key_abort_cv, NULL, CV_DEFAULT, NULL); 3498974SJan.Setje-Eilers@Sun.COM /* this counts on no keyboards being above ipl 12 */ 3508974SJan.Setje-Eilers@Sun.COM mutex_init(&upper->progressbar_key_abort_lock, NULL, MUTEX_SPIN, 3518974SJan.Setje-Eilers@Sun.COM (void *)ipltospl(12)); 3529022SJan.Setje-Eilers@Sun.COM tid = thread_create(NULL, 0, progressbar_key_abort_thread, upper, 3539022SJan.Setje-Eilers@Sun.COM 0, &p0, TS_RUN, minclsyspri); 3549022SJan.Setje-Eilers@Sun.COM upper->progressbar_key_abort_t_did = tid->t_did; 3558974SJan.Setje-Eilers@Sun.COM 3560Sstevel@tonic-gate DPRINTF(PRINT_L1, PRINT_MASK_OPEN, (upper, "kbtrans_streams_init " 3577688SAaron.Zang@Sun.COM "exiting")); 3580Sstevel@tonic-gate return (0); 3590Sstevel@tonic-gate } 3600Sstevel@tonic-gate 3610Sstevel@tonic-gate 3620Sstevel@tonic-gate /* 3630Sstevel@tonic-gate * kbtrans_streams_fini: 3640Sstevel@tonic-gate * Free structures and uninitialize the stream 3650Sstevel@tonic-gate */ 3660Sstevel@tonic-gate int 3670Sstevel@tonic-gate kbtrans_streams_fini(struct kbtrans *upper) 3680Sstevel@tonic-gate { 3690Sstevel@tonic-gate /* 3700Sstevel@tonic-gate * Since we're about to destroy our private data, turn off 3710Sstevel@tonic-gate * our open flag first, so we don't accept any more input 3720Sstevel@tonic-gate * and try to use that data. 3730Sstevel@tonic-gate */ 3740Sstevel@tonic-gate upper->kbtrans_streams_flags = 0; 3750Sstevel@tonic-gate 3760Sstevel@tonic-gate /* clear all timeouts */ 3770Sstevel@tonic-gate if (upper->kbtrans_streams_bufcallid) { 3780Sstevel@tonic-gate qunbufcall(upper->kbtrans_streams_readq, 3797688SAaron.Zang@Sun.COM upper->kbtrans_streams_bufcallid); 3800Sstevel@tonic-gate } 3810Sstevel@tonic-gate if (upper->kbtrans_streams_rptid) { 3820Sstevel@tonic-gate (void) quntimeout(upper->kbtrans_streams_readq, 3837688SAaron.Zang@Sun.COM upper->kbtrans_streams_rptid); 3840Sstevel@tonic-gate } 3850Sstevel@tonic-gate kmem_free(upper->kbtrans_streams_downs, 3867688SAaron.Zang@Sun.COM upper->kbtrans_streams_downs_bytes); 3878974SJan.Setje-Eilers@Sun.COM 3888974SJan.Setje-Eilers@Sun.COM mutex_enter(&upper->progressbar_key_abort_lock); 3898974SJan.Setje-Eilers@Sun.COM if (upper->progressbar_key_abort_flag == 0) { 3908974SJan.Setje-Eilers@Sun.COM upper->progressbar_key_abort_flag = 2; 3918974SJan.Setje-Eilers@Sun.COM cv_signal(&upper->progressbar_key_abort_cv); 3929022SJan.Setje-Eilers@Sun.COM mutex_exit(&upper->progressbar_key_abort_lock); 3939022SJan.Setje-Eilers@Sun.COM thread_join(upper->progressbar_key_abort_t_did); 3949022SJan.Setje-Eilers@Sun.COM } else { 3959022SJan.Setje-Eilers@Sun.COM mutex_exit(&upper->progressbar_key_abort_lock); 3968974SJan.Setje-Eilers@Sun.COM } 3978974SJan.Setje-Eilers@Sun.COM cv_destroy(&upper->progressbar_key_abort_cv); 3988974SJan.Setje-Eilers@Sun.COM mutex_destroy(&upper->progressbar_key_abort_lock); 3998974SJan.Setje-Eilers@Sun.COM 4000Sstevel@tonic-gate kmem_free(upper, sizeof (struct kbtrans)); 4010Sstevel@tonic-gate 4020Sstevel@tonic-gate DPRINTF(PRINT_L1, PRINT_MASK_CLOSE, (upper, "kbtrans_streams_fini " 4037688SAaron.Zang@Sun.COM "exiting")); 4040Sstevel@tonic-gate return (0); 4050Sstevel@tonic-gate } 4060Sstevel@tonic-gate 4070Sstevel@tonic-gate /* 4080Sstevel@tonic-gate * kbtrans_streams_releaseall : 4090Sstevel@tonic-gate * This function releases all the held keys. 4100Sstevel@tonic-gate */ 4110Sstevel@tonic-gate void 4120Sstevel@tonic-gate kbtrans_streams_releaseall(struct kbtrans *upper) 4130Sstevel@tonic-gate { 4140Sstevel@tonic-gate register struct key_event *ke; 4150Sstevel@tonic-gate register int i; 4160Sstevel@tonic-gate 4170Sstevel@tonic-gate DPRINTF(PRINT_L0, PRINT_MASK_ALL, (NULL, "USBKBM RELEASE ALL\n")); 4180Sstevel@tonic-gate 4190Sstevel@tonic-gate /* Scan table of down key stations */ 4200Sstevel@tonic-gate for (i = 0, ke = upper->kbtrans_streams_downs; 4210Sstevel@tonic-gate i < upper->kbtrans_streams_num_downs_entries; i++, ke++) { 4220Sstevel@tonic-gate 4230Sstevel@tonic-gate /* Key station not zero */ 4240Sstevel@tonic-gate if (ke->key_station) { 4250Sstevel@tonic-gate 4260Sstevel@tonic-gate kbtrans_keyreleased(upper, ke->key_station); 4270Sstevel@tonic-gate /* kbtrans_keyreleased resets downs entry */ 4280Sstevel@tonic-gate } 4290Sstevel@tonic-gate } 4300Sstevel@tonic-gate } 4310Sstevel@tonic-gate 4320Sstevel@tonic-gate /* 4330Sstevel@tonic-gate * kbtrans_streams_message: 4340Sstevel@tonic-gate * keyboard module output queue put procedure: handles M_IOCTL 4350Sstevel@tonic-gate * messages. 4360Sstevel@tonic-gate * 4370Sstevel@tonic-gate * Return KBTRANS_MESSAGE_HANDLED if the message was handled by 4380Sstevel@tonic-gate * kbtrans and KBTRANS_MESSAGE_NOT_HANDLED otherwise. If 4390Sstevel@tonic-gate * KBTRANS_MESSAGE_HANDLED is returned, no further action is required. 4400Sstevel@tonic-gate * If KBTRANS_MESSAGE_NOT_HANDLED is returned, the hardware module 4410Sstevel@tonic-gate * is responsible for any action. 4420Sstevel@tonic-gate */ 4430Sstevel@tonic-gate enum kbtrans_message_response 4440Sstevel@tonic-gate kbtrans_streams_message(struct kbtrans *upper, register mblk_t *mp) 4450Sstevel@tonic-gate { 4460Sstevel@tonic-gate queue_t *q = upper->kbtrans_streams_readq; 4470Sstevel@tonic-gate enum kbtrans_message_response ret; 4480Sstevel@tonic-gate 4490Sstevel@tonic-gate DPRINTF(PRINT_L1, PRINT_MASK_ALL, (upper, 4507688SAaron.Zang@Sun.COM "kbtrans_streams_message entering")); 4510Sstevel@tonic-gate /* 4520Sstevel@tonic-gate * Process M_FLUSH, and some M_IOCTL, messages here; pass 4530Sstevel@tonic-gate * everything else down. 4540Sstevel@tonic-gate */ 4550Sstevel@tonic-gate switch (mp->b_datap->db_type) { 4560Sstevel@tonic-gate 4570Sstevel@tonic-gate case M_IOCTL: 4580Sstevel@tonic-gate ret = kbtrans_ioctl(upper, mp); 4590Sstevel@tonic-gate break; 4600Sstevel@tonic-gate 4610Sstevel@tonic-gate case M_FLUSH: 4620Sstevel@tonic-gate if (*mp->b_rptr & FLUSHW) 4630Sstevel@tonic-gate flushq(q, FLUSHDATA); 4640Sstevel@tonic-gate if (*mp->b_rptr & FLUSHR) 4650Sstevel@tonic-gate flushq(RD(q), FLUSHDATA); 4660Sstevel@tonic-gate /* 4670Sstevel@tonic-gate * White lie: we say we didn't handle the message, 4680Sstevel@tonic-gate * so that it gets handled by our client. 4690Sstevel@tonic-gate */ 4700Sstevel@tonic-gate ret = KBTRANS_MESSAGE_NOT_HANDLED; 4710Sstevel@tonic-gate break; 4720Sstevel@tonic-gate 4730Sstevel@tonic-gate default: 4740Sstevel@tonic-gate ret = KBTRANS_MESSAGE_NOT_HANDLED; 4750Sstevel@tonic-gate break; 4760Sstevel@tonic-gate 4770Sstevel@tonic-gate } 4780Sstevel@tonic-gate DPRINTF(PRINT_L1, PRINT_MASK_ALL, (upper, 4797688SAaron.Zang@Sun.COM "kbtrans_streams_message exiting\n")); 4800Sstevel@tonic-gate 4810Sstevel@tonic-gate return (ret); 4820Sstevel@tonic-gate } 4830Sstevel@tonic-gate 4840Sstevel@tonic-gate /* 4850Sstevel@tonic-gate * kbtrans_streams_key: 4860Sstevel@tonic-gate * When a key is pressed or released, the hardware module should 4870Sstevel@tonic-gate * call kbtrans, passing the key number and its new 4880Sstevel@tonic-gate * state. kbtrans is responsible for autorepeat handling; 4890Sstevel@tonic-gate * the hardware module should report only actual press/release 4900Sstevel@tonic-gate * events, suppressing any hardware-generated autorepeat. 4910Sstevel@tonic-gate */ 4920Sstevel@tonic-gate void 4930Sstevel@tonic-gate kbtrans_streams_key( 4940Sstevel@tonic-gate struct kbtrans *upper, 4950Sstevel@tonic-gate kbtrans_key_t key, 4960Sstevel@tonic-gate enum keystate state) 4970Sstevel@tonic-gate { 4980Sstevel@tonic-gate struct kbtrans_lower *lower; 4990Sstevel@tonic-gate struct keyboard *kp; 5000Sstevel@tonic-gate 5010Sstevel@tonic-gate lower = &upper->kbtrans_lower; 5020Sstevel@tonic-gate kp = lower->kbtrans_keyboard; 5030Sstevel@tonic-gate 5048960SJan.Setje-Eilers@Sun.COM /* trigger switch back to text mode */ 5058974SJan.Setje-Eilers@Sun.COM mutex_enter(&upper->progressbar_key_abort_lock); 5068974SJan.Setje-Eilers@Sun.COM if (upper->progressbar_key_abort_flag == 0) { 5078974SJan.Setje-Eilers@Sun.COM upper->progressbar_key_abort_flag = 1; 5088974SJan.Setje-Eilers@Sun.COM cv_signal(&upper->progressbar_key_abort_cv); 5098960SJan.Setje-Eilers@Sun.COM } 5108974SJan.Setje-Eilers@Sun.COM mutex_exit(&upper->progressbar_key_abort_lock); 5118960SJan.Setje-Eilers@Sun.COM 5120Sstevel@tonic-gate if (upper->kbtrans_streams_abortable) { 5130Sstevel@tonic-gate switch (upper->kbtrans_streams_abort_state) { 5140Sstevel@tonic-gate case ABORT_NORMAL: 5150Sstevel@tonic-gate if (state != KEY_PRESSED) 5160Sstevel@tonic-gate break; 5170Sstevel@tonic-gate 5180Sstevel@tonic-gate if (key == (kbtrans_key_t)kp->k_abort1 || 5190Sstevel@tonic-gate key == (kbtrans_key_t)kp->k_abort1a) { 5200Sstevel@tonic-gate upper->kbtrans_streams_abort_state = 5217688SAaron.Zang@Sun.COM ABORT_ABORT1_RECEIVED; 5220Sstevel@tonic-gate upper->kbtrans_streams_abort1_key = key; 5230Sstevel@tonic-gate return; 5240Sstevel@tonic-gate } 5253739Sqz150045 /* Shift key needs to be sent to upper immediately */ 5263505Sqz150045 if (key == (kbtrans_key_t)kp->k_newabort1 || 5273505Sqz150045 key == (kbtrans_key_t)kp->k_newabort1a) { 5283505Sqz150045 upper->kbtrans_streams_abort_state = 5297688SAaron.Zang@Sun.COM NEW_ABORT_ABORT1_RECEIVED; 5303505Sqz150045 upper->kbtrans_streams_new_abort1_key = key; 5313505Sqz150045 } 5320Sstevel@tonic-gate break; 5330Sstevel@tonic-gate case ABORT_ABORT1_RECEIVED: 5340Sstevel@tonic-gate upper->kbtrans_streams_abort_state = ABORT_NORMAL; 5350Sstevel@tonic-gate if (state == KEY_PRESSED && 5360Sstevel@tonic-gate key == (kbtrans_key_t)kp->k_abort2) { 5370Sstevel@tonic-gate abort_sequence_enter((char *)NULL); 5380Sstevel@tonic-gate return; 5390Sstevel@tonic-gate } else { 5400Sstevel@tonic-gate kbtrans_processkey(lower, 5417688SAaron.Zang@Sun.COM upper->kbtrans_streams_callback, 5427688SAaron.Zang@Sun.COM upper->kbtrans_streams_abort1_key, 5437688SAaron.Zang@Sun.COM KEY_PRESSED); 5440Sstevel@tonic-gate } 5453505Sqz150045 break; 5463505Sqz150045 case NEW_ABORT_ABORT1_RECEIVED: 5473505Sqz150045 upper->kbtrans_streams_abort_state = ABORT_NORMAL; 5483505Sqz150045 if (state == KEY_PRESSED && 5493505Sqz150045 key == (kbtrans_key_t)kp->k_newabort2) { 5503505Sqz150045 abort_sequence_enter((char *)NULL); 5513505Sqz150045 kbtrans_processkey(lower, 5527688SAaron.Zang@Sun.COM upper->kbtrans_streams_callback, 5537688SAaron.Zang@Sun.COM upper->kbtrans_streams_new_abort1_key, 5547688SAaron.Zang@Sun.COM KEY_RELEASED); 5553739Sqz150045 return; 5563505Sqz150045 } 5570Sstevel@tonic-gate } 5580Sstevel@tonic-gate } 5590Sstevel@tonic-gate 5600Sstevel@tonic-gate kbtrans_processkey(lower, upper->kbtrans_streams_callback, key, state); 5610Sstevel@tonic-gate } 5620Sstevel@tonic-gate 5630Sstevel@tonic-gate /* 5640Sstevel@tonic-gate * kbtrans_streams_set_keyboard: 5650Sstevel@tonic-gate * At any time after calling kbtrans_streams_init, the hardware 5660Sstevel@tonic-gate * module should make this call to report the id of the keyboard 5670Sstevel@tonic-gate * attached. id is the keyboard type, typically KB_SUN4, 5680Sstevel@tonic-gate * KB_PC, or KB_USB. 5690Sstevel@tonic-gate */ 5700Sstevel@tonic-gate void 5710Sstevel@tonic-gate kbtrans_streams_set_keyboard( 5720Sstevel@tonic-gate struct kbtrans *upper, 5730Sstevel@tonic-gate int id, 5740Sstevel@tonic-gate struct keyboard *k) 5750Sstevel@tonic-gate { 5760Sstevel@tonic-gate upper->kbtrans_lower.kbtrans_keyboard = k; 5770Sstevel@tonic-gate upper->kbtrans_streams_id = id; 5780Sstevel@tonic-gate } 5790Sstevel@tonic-gate 5800Sstevel@tonic-gate /* 5810Sstevel@tonic-gate * kbtrans_streams_has_reset: 5820Sstevel@tonic-gate * At any time between kbtrans_streams_init and kbtrans_streams_fini, 5830Sstevel@tonic-gate * the hardware module can call this routine to report that the 5840Sstevel@tonic-gate * keyboard has been reset, e.g. by being unplugged and reattached. 5850Sstevel@tonic-gate */ 5860Sstevel@tonic-gate /*ARGSUSED*/ 5870Sstevel@tonic-gate void 5880Sstevel@tonic-gate kbtrans_streams_has_reset(struct kbtrans *upper) 5890Sstevel@tonic-gate { 5900Sstevel@tonic-gate /* 5910Sstevel@tonic-gate * If this routine is implemented it should probably (a) 5920Sstevel@tonic-gate * simulate releases of all pressed keys and (b) call 5930Sstevel@tonic-gate * the hardware module to set the LEDs. 5940Sstevel@tonic-gate */ 5950Sstevel@tonic-gate } 5960Sstevel@tonic-gate 5970Sstevel@tonic-gate /* 5980Sstevel@tonic-gate * kbtrans_streams_enable: 5990Sstevel@tonic-gate * This is the routine that is called back when the the stream is ready 6000Sstevel@tonic-gate * to take messages. 6010Sstevel@tonic-gate */ 6020Sstevel@tonic-gate void 6030Sstevel@tonic-gate kbtrans_streams_enable(struct kbtrans *upper) 6040Sstevel@tonic-gate { 6050Sstevel@tonic-gate /* Set the LED's */ 6060Sstevel@tonic-gate kbtrans_setled(upper); 6070Sstevel@tonic-gate } 6080Sstevel@tonic-gate 6090Sstevel@tonic-gate /* 6101272Slq150181 * kbtrans_streams_setled(): 6111272Slq150181 * This is the routine that is called to only update the led state 6121272Slq150181 * in kbtrans. 6131272Slq150181 */ 6141272Slq150181 void 6151272Slq150181 kbtrans_streams_setled(struct kbtrans *upper, int led_state) 6161272Slq150181 { 6171272Slq150181 struct kbtrans_lower *lower; 6181272Slq150181 6191272Slq150181 lower = &upper->kbtrans_lower; 6201272Slq150181 lower->kbtrans_led_state = (uchar_t)led_state; 6211272Slq150181 6221272Slq150181 if (lower->kbtrans_led_state & LED_CAPS_LOCK) 6231272Slq150181 lower->kbtrans_togglemask |= CAPSMASK; 6241272Slq150181 if (lower->kbtrans_led_state & LED_NUM_LOCK) 6251272Slq150181 lower->kbtrans_togglemask |= NUMLOCKMASK; 6261272Slq150181 6271272Slq150181 #if defined(SCROLLMASK) 6281272Slq150181 if (lower->kbtrans_led_state & LED_SCROLL_LOCK) 6291272Slq150181 lower->kbtrans_togglemask |= SCROLLMASK; 6301272Slq150181 #endif 6311272Slq150181 6321272Slq150181 lower->kbtrans_shiftmask = lower->kbtrans_togglemask; 6331272Slq150181 6341272Slq150181 } 6351272Slq150181 6361272Slq150181 /* 6370Sstevel@tonic-gate * kbtrans_streams_set_queue: 6380Sstevel@tonic-gate * Set the overlying queue, to support multiplexors. 6390Sstevel@tonic-gate */ 6400Sstevel@tonic-gate void 6410Sstevel@tonic-gate kbtrans_streams_set_queue(struct kbtrans *upper, queue_t *q) 6420Sstevel@tonic-gate { 6430Sstevel@tonic-gate 6440Sstevel@tonic-gate upper->kbtrans_streams_readq = q; 6450Sstevel@tonic-gate } 6460Sstevel@tonic-gate 6470Sstevel@tonic-gate /* 6480Sstevel@tonic-gate * kbtrans_streams_get_queue: 6490Sstevel@tonic-gate * Return the overlying queue. 6500Sstevel@tonic-gate */ 6510Sstevel@tonic-gate queue_t * 6520Sstevel@tonic-gate kbtrans_streams_get_queue(struct kbtrans *upper) 6530Sstevel@tonic-gate { 6540Sstevel@tonic-gate return (upper->kbtrans_streams_readq); 6550Sstevel@tonic-gate } 6560Sstevel@tonic-gate 6570Sstevel@tonic-gate /* 6580Sstevel@tonic-gate * kbtrans_streams_untimeout 6590Sstevel@tonic-gate * Cancell all timeout 6600Sstevel@tonic-gate */ 6610Sstevel@tonic-gate void 6620Sstevel@tonic-gate kbtrans_streams_untimeout(struct kbtrans *upper) 6630Sstevel@tonic-gate { 6640Sstevel@tonic-gate /* clear all timeouts */ 6650Sstevel@tonic-gate if (upper->kbtrans_streams_bufcallid) { 6660Sstevel@tonic-gate qunbufcall(upper->kbtrans_streams_readq, 6677688SAaron.Zang@Sun.COM upper->kbtrans_streams_bufcallid); 6680Sstevel@tonic-gate upper->kbtrans_streams_bufcallid = 0; 6690Sstevel@tonic-gate } 6700Sstevel@tonic-gate if (upper->kbtrans_streams_rptid) { 6710Sstevel@tonic-gate (void) quntimeout(upper->kbtrans_streams_readq, 6727688SAaron.Zang@Sun.COM upper->kbtrans_streams_rptid); 6730Sstevel@tonic-gate upper->kbtrans_streams_rptid = 0; 6740Sstevel@tonic-gate } 6750Sstevel@tonic-gate } 6760Sstevel@tonic-gate 6770Sstevel@tonic-gate /* 6780Sstevel@tonic-gate * kbtrans_reioctl: 6790Sstevel@tonic-gate * This function is set up as call-back function should an ioctl fail 6800Sstevel@tonic-gate * to allocate required resources. 6810Sstevel@tonic-gate */ 6820Sstevel@tonic-gate static void 6830Sstevel@tonic-gate kbtrans_reioctl(void *arg) 6840Sstevel@tonic-gate { 6850Sstevel@tonic-gate struct kbtrans *upper = (struct kbtrans *)arg; 6860Sstevel@tonic-gate mblk_t *mp; 6870Sstevel@tonic-gate 6880Sstevel@tonic-gate upper->kbtrans_streams_bufcallid = 0; 6890Sstevel@tonic-gate 6900Sstevel@tonic-gate if ((mp = upper->kbtrans_streams_iocpending) != NULL) { 6910Sstevel@tonic-gate /* not pending any more */ 6920Sstevel@tonic-gate upper->kbtrans_streams_iocpending = NULL; 6930Sstevel@tonic-gate (void) kbtrans_ioctl(upper, mp); 6940Sstevel@tonic-gate } 6950Sstevel@tonic-gate } 6960Sstevel@tonic-gate 6970Sstevel@tonic-gate /* 6980Sstevel@tonic-gate * kbtrans_ioctl: 6990Sstevel@tonic-gate * process ioctls we recognize and own. Otherwise, pass it down. 7000Sstevel@tonic-gate */ 7010Sstevel@tonic-gate static enum kbtrans_message_response 7020Sstevel@tonic-gate kbtrans_ioctl(struct kbtrans *upper, register mblk_t *mp) 7030Sstevel@tonic-gate { 7040Sstevel@tonic-gate register struct iocblk *iocp; 7050Sstevel@tonic-gate register short new_translate; 7060Sstevel@tonic-gate register Vuid_addr_probe *addr_probe; 7070Sstevel@tonic-gate register short *addr_ptr; 7080Sstevel@tonic-gate size_t ioctlrespsize; 7090Sstevel@tonic-gate int err = 0; 7100Sstevel@tonic-gate struct kbtrans_lower *lower; 7110Sstevel@tonic-gate mblk_t *datap; 7120Sstevel@tonic-gate int translate; 7130Sstevel@tonic-gate 7140Sstevel@tonic-gate static int kiocgetkey, kiocsetkey; 7150Sstevel@tonic-gate 7160Sstevel@tonic-gate lower = &upper->kbtrans_lower; 7170Sstevel@tonic-gate 7180Sstevel@tonic-gate iocp = (struct iocblk *)mp->b_rptr; 7190Sstevel@tonic-gate 7200Sstevel@tonic-gate DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, 7217688SAaron.Zang@Sun.COM "kbtrans_ioctl: ioc_cmd 0x%x - ", iocp->ioc_cmd)); 7220Sstevel@tonic-gate switch (iocp->ioc_cmd) { 7230Sstevel@tonic-gate 7240Sstevel@tonic-gate case VUIDSFORMAT: 7250Sstevel@tonic-gate DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "VUIDSFORMAT\n")); 7260Sstevel@tonic-gate 7270Sstevel@tonic-gate err = miocpullup(mp, sizeof (int)); 7280Sstevel@tonic-gate if (err != 0) 7290Sstevel@tonic-gate break; 7300Sstevel@tonic-gate new_translate = (*(int *)mp->b_cont->b_rptr == VUID_NATIVE) ? 7310Sstevel@tonic-gate TR_ASCII : TR_EVENT; 7320Sstevel@tonic-gate 7330Sstevel@tonic-gate if (new_translate == upper->kbtrans_streams_translate_mode) 7340Sstevel@tonic-gate break; 7350Sstevel@tonic-gate upper->kbtrans_streams_translate_mode = new_translate; 7360Sstevel@tonic-gate 7370Sstevel@tonic-gate kbtrans_set_translation_callback(upper); 7380Sstevel@tonic-gate 7390Sstevel@tonic-gate kbtrans_flush(upper); 7400Sstevel@tonic-gate break; 7410Sstevel@tonic-gate 7420Sstevel@tonic-gate case KIOCTRANS: 7430Sstevel@tonic-gate DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "KIOCTRANS\n")); 7440Sstevel@tonic-gate err = miocpullup(mp, sizeof (int)); 7450Sstevel@tonic-gate if (err != 0) 7460Sstevel@tonic-gate break; 7470Sstevel@tonic-gate new_translate = *(int *)mp->b_cont->b_rptr; 7480Sstevel@tonic-gate if (new_translate == upper->kbtrans_streams_translate_mode) 7490Sstevel@tonic-gate break; 7500Sstevel@tonic-gate upper->kbtrans_streams_translate_mode = new_translate; 7510Sstevel@tonic-gate kbtrans_set_translation_callback(upper); 7520Sstevel@tonic-gate 7530Sstevel@tonic-gate kbtrans_flush(upper); 7540Sstevel@tonic-gate break; 7550Sstevel@tonic-gate 7560Sstevel@tonic-gate case KIOCSLED: 7570Sstevel@tonic-gate DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "KIOCSLED\n")); 7580Sstevel@tonic-gate 7590Sstevel@tonic-gate err = miocpullup(mp, sizeof (uchar_t)); 7600Sstevel@tonic-gate if (err != 0) 7610Sstevel@tonic-gate break; 7620Sstevel@tonic-gate lower->kbtrans_led_state = *(uchar_t *)mp->b_cont->b_rptr; 7630Sstevel@tonic-gate 7640Sstevel@tonic-gate kbtrans_setled(upper); 7650Sstevel@tonic-gate break; 7660Sstevel@tonic-gate 7670Sstevel@tonic-gate case KIOCGLED: 7680Sstevel@tonic-gate DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "KIOCGLED\n")); 7690Sstevel@tonic-gate if ((datap = allocb(sizeof (uchar_t), BPRI_HI)) == NULL) { 7700Sstevel@tonic-gate ioctlrespsize = sizeof (int); 7710Sstevel@tonic-gate goto allocfailure; 7720Sstevel@tonic-gate } 7730Sstevel@tonic-gate 7740Sstevel@tonic-gate *(uchar_t *)datap->b_wptr = lower->kbtrans_led_state; 7750Sstevel@tonic-gate datap->b_wptr += sizeof (uchar_t); 7760Sstevel@tonic-gate if (mp->b_cont) 7770Sstevel@tonic-gate freemsg(mp->b_cont); 7780Sstevel@tonic-gate mp->b_cont = datap; 7790Sstevel@tonic-gate iocp->ioc_count = sizeof (uchar_t); 7800Sstevel@tonic-gate break; 7810Sstevel@tonic-gate 7820Sstevel@tonic-gate case VUIDGFORMAT: 7830Sstevel@tonic-gate DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "VUIDGFORMAT\n")); 7840Sstevel@tonic-gate if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) { 7850Sstevel@tonic-gate ioctlrespsize = sizeof (int); 7860Sstevel@tonic-gate goto allocfailure; 7870Sstevel@tonic-gate } 7880Sstevel@tonic-gate *(int *)datap->b_wptr = 7890Sstevel@tonic-gate (upper->kbtrans_streams_translate_mode == TR_EVENT || 7900Sstevel@tonic-gate upper->kbtrans_streams_translate_mode == TR_UNTRANS_EVENT) ? 7917688SAaron.Zang@Sun.COM VUID_FIRM_EVENT: VUID_NATIVE; 7920Sstevel@tonic-gate datap->b_wptr += sizeof (int); 7930Sstevel@tonic-gate if (mp->b_cont) /* free msg to prevent memory leak */ 7940Sstevel@tonic-gate freemsg(mp->b_cont); 7950Sstevel@tonic-gate mp->b_cont = datap; 7960Sstevel@tonic-gate iocp->ioc_count = sizeof (int); 7970Sstevel@tonic-gate break; 7980Sstevel@tonic-gate 7990Sstevel@tonic-gate case KIOCGTRANS: 8000Sstevel@tonic-gate DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "KIOCGTRANS\n")); 8010Sstevel@tonic-gate if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) { 8020Sstevel@tonic-gate ioctlrespsize = sizeof (int); 8030Sstevel@tonic-gate goto allocfailure; 8040Sstevel@tonic-gate } 8050Sstevel@tonic-gate *(int *)datap->b_wptr = upper->kbtrans_streams_translate_mode; 8060Sstevel@tonic-gate datap->b_wptr += sizeof (int); 8070Sstevel@tonic-gate if (mp->b_cont) /* free msg to prevent memory leak */ 8080Sstevel@tonic-gate freemsg(mp->b_cont); 8090Sstevel@tonic-gate mp->b_cont = datap; 8100Sstevel@tonic-gate iocp->ioc_count = sizeof (int); 8110Sstevel@tonic-gate break; 8120Sstevel@tonic-gate 8130Sstevel@tonic-gate case VUIDSADDR: 8140Sstevel@tonic-gate DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "VUIDSADDR\n")); 8150Sstevel@tonic-gate 8160Sstevel@tonic-gate err = miocpullup(mp, sizeof (Vuid_addr_probe)); 8170Sstevel@tonic-gate if (err != 0) 8180Sstevel@tonic-gate break; 8190Sstevel@tonic-gate addr_probe = (Vuid_addr_probe *)mp->b_cont->b_rptr; 8200Sstevel@tonic-gate switch (addr_probe->base) { 8210Sstevel@tonic-gate 8220Sstevel@tonic-gate case ASCII_FIRST: 8230Sstevel@tonic-gate addr_ptr = &upper->kbtrans_streams_vuid_addr.ascii; 8240Sstevel@tonic-gate break; 8250Sstevel@tonic-gate 8260Sstevel@tonic-gate case TOP_FIRST: 8270Sstevel@tonic-gate addr_ptr = &upper->kbtrans_streams_vuid_addr.top; 8280Sstevel@tonic-gate break; 8290Sstevel@tonic-gate 8300Sstevel@tonic-gate case VKEY_FIRST: 8310Sstevel@tonic-gate addr_ptr = &upper->kbtrans_streams_vuid_addr.vkey; 8320Sstevel@tonic-gate break; 8330Sstevel@tonic-gate 8340Sstevel@tonic-gate default: 8350Sstevel@tonic-gate err = ENODEV; 8360Sstevel@tonic-gate } 8370Sstevel@tonic-gate 8380Sstevel@tonic-gate if ((err == 0) && (*addr_ptr != addr_probe->data.next)) { 8390Sstevel@tonic-gate *addr_ptr = addr_probe->data.next; 8400Sstevel@tonic-gate kbtrans_flush(upper); 8410Sstevel@tonic-gate } 8420Sstevel@tonic-gate break; 8430Sstevel@tonic-gate 8440Sstevel@tonic-gate case VUIDGADDR: 8450Sstevel@tonic-gate DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "VUIDGADDR\n")); 8460Sstevel@tonic-gate 8470Sstevel@tonic-gate err = miocpullup(mp, sizeof (Vuid_addr_probe)); 8480Sstevel@tonic-gate if (err != 0) 8490Sstevel@tonic-gate break; 8500Sstevel@tonic-gate addr_probe = (Vuid_addr_probe *)mp->b_cont->b_rptr; 8510Sstevel@tonic-gate switch (addr_probe->base) { 8520Sstevel@tonic-gate 8530Sstevel@tonic-gate case ASCII_FIRST: 8540Sstevel@tonic-gate addr_probe->data.current = 8557688SAaron.Zang@Sun.COM upper->kbtrans_streams_vuid_addr.ascii; 8560Sstevel@tonic-gate break; 8570Sstevel@tonic-gate 8580Sstevel@tonic-gate case TOP_FIRST: 8590Sstevel@tonic-gate addr_probe->data.current = 8607688SAaron.Zang@Sun.COM upper->kbtrans_streams_vuid_addr.top; 8610Sstevel@tonic-gate break; 8620Sstevel@tonic-gate 8630Sstevel@tonic-gate case VKEY_FIRST: 8640Sstevel@tonic-gate addr_probe->data.current = 8657688SAaron.Zang@Sun.COM upper->kbtrans_streams_vuid_addr.vkey; 8660Sstevel@tonic-gate break; 8670Sstevel@tonic-gate 8680Sstevel@tonic-gate default: 8690Sstevel@tonic-gate err = ENODEV; 8700Sstevel@tonic-gate } 8710Sstevel@tonic-gate break; 8720Sstevel@tonic-gate 8730Sstevel@tonic-gate case KIOCTRANSABLE: 8740Sstevel@tonic-gate DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "KIOCTRANSABLE\n")); 8750Sstevel@tonic-gate 8760Sstevel@tonic-gate err = miocpullup(mp, sizeof (int)); 8770Sstevel@tonic-gate if (err != 0) 8780Sstevel@tonic-gate break; 8790Sstevel@tonic-gate /* 8800Sstevel@tonic-gate * called during console setup in kbconfig() 8810Sstevel@tonic-gate * If set to false, means we are a serial keyboard, 8820Sstevel@tonic-gate * and we should pass all data up without modification. 8830Sstevel@tonic-gate */ 8840Sstevel@tonic-gate translate = *(int *)mp->b_cont->b_rptr; 8850Sstevel@tonic-gate if (upper->kbtrans_streams_translatable != translate) 8860Sstevel@tonic-gate upper->kbtrans_streams_translatable = translate; 8870Sstevel@tonic-gate 8880Sstevel@tonic-gate if (translate != TR_CAN) 8890Sstevel@tonic-gate DPRINTF(PRINT_L4, PRINT_MASK_ALL, (upper, 8900Sstevel@tonic-gate "Cannot translate keyboard using tables.\n")); 8910Sstevel@tonic-gate break; 8920Sstevel@tonic-gate 8930Sstevel@tonic-gate case KIOCGTRANSABLE: 8940Sstevel@tonic-gate DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "KIOCGTRANSABLE\n")); 8950Sstevel@tonic-gate if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) { 8960Sstevel@tonic-gate ioctlrespsize = sizeof (int); 8970Sstevel@tonic-gate goto allocfailure; 8980Sstevel@tonic-gate } 8990Sstevel@tonic-gate *(int *)datap->b_wptr = upper->kbtrans_streams_translatable; 9000Sstevel@tonic-gate datap->b_wptr += sizeof (int); 9010Sstevel@tonic-gate if (mp->b_cont) /* free msg to prevent memory leak */ 9020Sstevel@tonic-gate freemsg(mp->b_cont); 9030Sstevel@tonic-gate mp->b_cont = datap; 9040Sstevel@tonic-gate iocp->ioc_count = sizeof (int); 9050Sstevel@tonic-gate break; 9060Sstevel@tonic-gate 9070Sstevel@tonic-gate case KIOCSCOMPAT: 9080Sstevel@tonic-gate DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "KIOCSCOMPAT\n")); 9090Sstevel@tonic-gate 9100Sstevel@tonic-gate err = miocpullup(mp, sizeof (int)); 9110Sstevel@tonic-gate if (err != 0) 9120Sstevel@tonic-gate break; 9130Sstevel@tonic-gate lower->kbtrans_compat = *(int *)mp->b_cont->b_rptr; 9140Sstevel@tonic-gate break; 9150Sstevel@tonic-gate 9160Sstevel@tonic-gate case KIOCGCOMPAT: 9170Sstevel@tonic-gate DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "KIOCGCOMPAT\n")); 9180Sstevel@tonic-gate if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) { 9190Sstevel@tonic-gate ioctlrespsize = sizeof (int); 9200Sstevel@tonic-gate goto allocfailure; 9210Sstevel@tonic-gate } 9220Sstevel@tonic-gate *(int *)datap->b_wptr = lower->kbtrans_compat; 9230Sstevel@tonic-gate datap->b_wptr += sizeof (int); 9240Sstevel@tonic-gate if (mp->b_cont) /* free msg to prevent memory leak */ 9250Sstevel@tonic-gate freemsg(mp->b_cont); 9260Sstevel@tonic-gate mp->b_cont = datap; 9270Sstevel@tonic-gate iocp->ioc_count = sizeof (int); 9280Sstevel@tonic-gate break; 9290Sstevel@tonic-gate 9300Sstevel@tonic-gate case KIOCSETKEY: 9310Sstevel@tonic-gate DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "KIOCSETKEY %d\n", 9327688SAaron.Zang@Sun.COM kiocsetkey++)); 9330Sstevel@tonic-gate err = miocpullup(mp, sizeof (struct kiockey)); 9340Sstevel@tonic-gate if (err != 0) 9350Sstevel@tonic-gate break; 9360Sstevel@tonic-gate err = kbtrans_setkey(&upper->kbtrans_lower, 9370Sstevel@tonic-gate (struct kiockey *)mp->b_cont->b_rptr, iocp->ioc_cr); 9380Sstevel@tonic-gate /* 9390Sstevel@tonic-gate * Since this only affects any subsequent key presses, 9400Sstevel@tonic-gate * don't flush soft state. One might want to 9410Sstevel@tonic-gate * toggle the keytable entries dynamically. 9420Sstevel@tonic-gate */ 9430Sstevel@tonic-gate break; 9440Sstevel@tonic-gate 9450Sstevel@tonic-gate case KIOCGETKEY: 9460Sstevel@tonic-gate DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "KIOCGETKEY %d\n", 9477688SAaron.Zang@Sun.COM kiocgetkey++)); 9480Sstevel@tonic-gate err = miocpullup(mp, sizeof (struct kiockey)); 9490Sstevel@tonic-gate if (err != 0) 9500Sstevel@tonic-gate break; 9510Sstevel@tonic-gate err = kbtrans_getkey(&upper->kbtrans_lower, 9520Sstevel@tonic-gate (struct kiockey *)mp->b_cont->b_rptr); 9530Sstevel@tonic-gate break; 9540Sstevel@tonic-gate 9550Sstevel@tonic-gate case KIOCSKEY: 9560Sstevel@tonic-gate err = miocpullup(mp, sizeof (struct kiockeymap)); 9570Sstevel@tonic-gate if (err != 0) 9580Sstevel@tonic-gate break; 9590Sstevel@tonic-gate err = kbtrans_skey(&upper->kbtrans_lower, 9600Sstevel@tonic-gate (struct kiockeymap *)mp->b_cont->b_rptr, iocp->ioc_cr); 9610Sstevel@tonic-gate /* 9620Sstevel@tonic-gate * Since this only affects any subsequent key presses, 9630Sstevel@tonic-gate * don't flush soft state. One might want to 9640Sstevel@tonic-gate * toggle the keytable entries dynamically. 9650Sstevel@tonic-gate */ 9660Sstevel@tonic-gate break; 9670Sstevel@tonic-gate 9680Sstevel@tonic-gate case KIOCGKEY: 9690Sstevel@tonic-gate err = miocpullup(mp, sizeof (struct kiockeymap)); 9700Sstevel@tonic-gate if (err != 0) 9710Sstevel@tonic-gate break; 9720Sstevel@tonic-gate err = kbtrans_gkey(&upper->kbtrans_lower, 9730Sstevel@tonic-gate (struct kiockeymap *)mp->b_cont->b_rptr); 9740Sstevel@tonic-gate break; 9750Sstevel@tonic-gate 9760Sstevel@tonic-gate case KIOCSDIRECT: 9770Sstevel@tonic-gate DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "KIOCSDIRECT\n")); 9780Sstevel@tonic-gate kbtrans_flush(upper); 9790Sstevel@tonic-gate break; 9800Sstevel@tonic-gate 9810Sstevel@tonic-gate case KIOCGDIRECT: 9820Sstevel@tonic-gate DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "KIOCSGDIRECT\n")); 9830Sstevel@tonic-gate if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) { 9840Sstevel@tonic-gate ioctlrespsize = sizeof (int); 9850Sstevel@tonic-gate goto allocfailure; 9860Sstevel@tonic-gate } 9870Sstevel@tonic-gate *(int *)datap->b_wptr = 1; /* always direct */ 9880Sstevel@tonic-gate datap->b_wptr += sizeof (int); 9890Sstevel@tonic-gate if (mp->b_cont) /* free msg to prevent memory leak */ 9900Sstevel@tonic-gate freemsg(mp->b_cont); 9910Sstevel@tonic-gate mp->b_cont = datap; 9920Sstevel@tonic-gate iocp->ioc_count = sizeof (int); 9930Sstevel@tonic-gate break; 9940Sstevel@tonic-gate 9950Sstevel@tonic-gate case KIOCTYPE: 9960Sstevel@tonic-gate DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "KIOCTYPE\n")); 9970Sstevel@tonic-gate if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) { 9980Sstevel@tonic-gate ioctlrespsize = sizeof (int); 9990Sstevel@tonic-gate goto allocfailure; 10000Sstevel@tonic-gate } 10010Sstevel@tonic-gate *(int *)datap->b_wptr = upper->kbtrans_streams_id; 10020Sstevel@tonic-gate datap->b_wptr += sizeof (int); 10030Sstevel@tonic-gate if (mp->b_cont) /* free msg to prevent memory leak */ 10040Sstevel@tonic-gate freemsg(mp->b_cont); 10050Sstevel@tonic-gate mp->b_cont = datap; 10060Sstevel@tonic-gate iocp->ioc_count = sizeof (int); 10070Sstevel@tonic-gate break; 10080Sstevel@tonic-gate 10090Sstevel@tonic-gate case CONSSETABORTENABLE: 10100Sstevel@tonic-gate /* 10110Sstevel@tonic-gate * Peek as it goes by; must be a TRANSPARENT ioctl. 10120Sstevel@tonic-gate */ 10130Sstevel@tonic-gate if (iocp->ioc_count != TRANSPARENT) { 10140Sstevel@tonic-gate err = EINVAL; 10150Sstevel@tonic-gate break; 10160Sstevel@tonic-gate } 10170Sstevel@tonic-gate 10180Sstevel@tonic-gate upper->kbtrans_streams_abortable = 10190Sstevel@tonic-gate (boolean_t)*(intptr_t *)mp->b_cont->b_rptr; 10200Sstevel@tonic-gate 10210Sstevel@tonic-gate /* 10220Sstevel@tonic-gate * Let the hardware module see it too. 10230Sstevel@tonic-gate */ 10240Sstevel@tonic-gate return (KBTRANS_MESSAGE_NOT_HANDLED); 10250Sstevel@tonic-gate 10260Sstevel@tonic-gate case KIOCGRPTDELAY: 10270Sstevel@tonic-gate /* 10280Sstevel@tonic-gate * Report the autorepeat delay, unit in millisecond 10290Sstevel@tonic-gate */ 10300Sstevel@tonic-gate DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "KIOCGRPTDELAY\n")); 10310Sstevel@tonic-gate if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) { 10320Sstevel@tonic-gate ioctlrespsize = sizeof (int); 10330Sstevel@tonic-gate goto allocfailure; 10340Sstevel@tonic-gate } 10350Sstevel@tonic-gate *(int *)datap->b_wptr = TICK_TO_MSEC(kbtrans_repeat_delay); 10360Sstevel@tonic-gate datap->b_wptr += sizeof (int); 10370Sstevel@tonic-gate 10380Sstevel@tonic-gate /* free msg to prevent memory leak */ 10390Sstevel@tonic-gate if (mp->b_cont != NULL) 10400Sstevel@tonic-gate freemsg(mp->b_cont); 10410Sstevel@tonic-gate mp->b_cont = datap; 10420Sstevel@tonic-gate iocp->ioc_count = sizeof (int); 10430Sstevel@tonic-gate break; 10440Sstevel@tonic-gate 10450Sstevel@tonic-gate case KIOCSRPTDELAY: 10460Sstevel@tonic-gate /* 10470Sstevel@tonic-gate * Set the autorepeat delay 10480Sstevel@tonic-gate */ 10490Sstevel@tonic-gate DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "KIOCSRPTDELAY\n")); 10500Sstevel@tonic-gate err = miocpullup(mp, sizeof (int)); 10510Sstevel@tonic-gate 10520Sstevel@tonic-gate if (err != 0) 10530Sstevel@tonic-gate break; 10540Sstevel@tonic-gate 10550Sstevel@tonic-gate /* validate the input */ 10560Sstevel@tonic-gate if (*(int *)mp->b_cont->b_rptr < KIOCRPTDELAY_MIN) { 10570Sstevel@tonic-gate err = EINVAL; 10580Sstevel@tonic-gate break; 10590Sstevel@tonic-gate } 10600Sstevel@tonic-gate kbtrans_repeat_delay = MSEC_TO_TICK(*(int *)mp->b_cont->b_rptr); 10610Sstevel@tonic-gate if (kbtrans_repeat_delay <= 0) 10620Sstevel@tonic-gate kbtrans_repeat_delay = 1; 10630Sstevel@tonic-gate break; 10640Sstevel@tonic-gate 10650Sstevel@tonic-gate case KIOCGRPTRATE: 10660Sstevel@tonic-gate /* 10670Sstevel@tonic-gate * Report the autorepeat rate 10680Sstevel@tonic-gate */ 10690Sstevel@tonic-gate DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "KIOCGRPTRATE\n")); 10700Sstevel@tonic-gate if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) { 10710Sstevel@tonic-gate ioctlrespsize = sizeof (int); 10720Sstevel@tonic-gate goto allocfailure; 10730Sstevel@tonic-gate } 10740Sstevel@tonic-gate *(int *)datap->b_wptr = TICK_TO_MSEC(kbtrans_repeat_rate); 10750Sstevel@tonic-gate datap->b_wptr += sizeof (int); 10760Sstevel@tonic-gate 10770Sstevel@tonic-gate /* free msg to prevent memory leak */ 10780Sstevel@tonic-gate if (mp->b_cont != NULL) 10790Sstevel@tonic-gate freemsg(mp->b_cont); 10800Sstevel@tonic-gate mp->b_cont = datap; 10810Sstevel@tonic-gate iocp->ioc_count = sizeof (int); 10820Sstevel@tonic-gate break; 10830Sstevel@tonic-gate 10840Sstevel@tonic-gate case KIOCSRPTRATE: 10850Sstevel@tonic-gate /* 10860Sstevel@tonic-gate * Set the autorepeat rate 10870Sstevel@tonic-gate */ 10880Sstevel@tonic-gate DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "KIOCSRPTRATE\n")); 10890Sstevel@tonic-gate err = miocpullup(mp, sizeof (int)); 10900Sstevel@tonic-gate 10910Sstevel@tonic-gate if (err != 0) 10920Sstevel@tonic-gate break; 10930Sstevel@tonic-gate 10940Sstevel@tonic-gate /* validate the input */ 10950Sstevel@tonic-gate if (*(int *)mp->b_cont->b_rptr < KIOCRPTRATE_MIN) { 10960Sstevel@tonic-gate err = EINVAL; 10970Sstevel@tonic-gate break; 10980Sstevel@tonic-gate } 10990Sstevel@tonic-gate kbtrans_repeat_rate = MSEC_TO_TICK(*(int *)mp->b_cont->b_rptr); 11000Sstevel@tonic-gate if (kbtrans_repeat_rate <= 0) 11010Sstevel@tonic-gate kbtrans_repeat_rate = 1; 11020Sstevel@tonic-gate break; 11030Sstevel@tonic-gate 11040Sstevel@tonic-gate default: 11050Sstevel@tonic-gate DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "unknown\n")); 11060Sstevel@tonic-gate return (KBTRANS_MESSAGE_NOT_HANDLED); 11070Sstevel@tonic-gate } /* end switch */ 11080Sstevel@tonic-gate 11090Sstevel@tonic-gate if (err != 0) { 11100Sstevel@tonic-gate iocp->ioc_rval = 0; 11110Sstevel@tonic-gate iocp->ioc_error = err; 11120Sstevel@tonic-gate mp->b_datap->db_type = M_IOCNAK; 11130Sstevel@tonic-gate } else { 11140Sstevel@tonic-gate iocp->ioc_rval = 0; 11150Sstevel@tonic-gate iocp->ioc_error = 0; /* brain rot */ 11160Sstevel@tonic-gate mp->b_datap->db_type = M_IOCACK; 11170Sstevel@tonic-gate } 11180Sstevel@tonic-gate putnext(upper->kbtrans_streams_readq, mp); 11190Sstevel@tonic-gate 11200Sstevel@tonic-gate return (KBTRANS_MESSAGE_HANDLED); 11210Sstevel@tonic-gate 11220Sstevel@tonic-gate allocfailure: 11230Sstevel@tonic-gate /* 11240Sstevel@tonic-gate * We needed to allocate something to handle this "ioctl", but 11250Sstevel@tonic-gate * couldn't; save this "ioctl" and arrange to get called back when 11260Sstevel@tonic-gate * it's more likely that we can get what we need. 11270Sstevel@tonic-gate * If there's already one being saved, throw it out, since it 11280Sstevel@tonic-gate * must have timed out. 11290Sstevel@tonic-gate */ 11300Sstevel@tonic-gate if (upper->kbtrans_streams_iocpending != NULL) 11310Sstevel@tonic-gate freemsg(upper->kbtrans_streams_iocpending); 11320Sstevel@tonic-gate upper->kbtrans_streams_iocpending = mp; 11330Sstevel@tonic-gate if (upper->kbtrans_streams_bufcallid) { 11340Sstevel@tonic-gate qunbufcall(upper->kbtrans_streams_readq, 11357688SAaron.Zang@Sun.COM upper->kbtrans_streams_bufcallid); 11360Sstevel@tonic-gate } 11370Sstevel@tonic-gate upper->kbtrans_streams_bufcallid = 11387688SAaron.Zang@Sun.COM qbufcall(upper->kbtrans_streams_readq, ioctlrespsize, BPRI_HI, 11397688SAaron.Zang@Sun.COM kbtrans_reioctl, upper); 11400Sstevel@tonic-gate /* 11410Sstevel@tonic-gate * This is a white lie... we *will* handle it, eventually. 11420Sstevel@tonic-gate */ 11430Sstevel@tonic-gate return (KBTRANS_MESSAGE_HANDLED); 11440Sstevel@tonic-gate } 11450Sstevel@tonic-gate 11460Sstevel@tonic-gate /* 11470Sstevel@tonic-gate * kbtrans_flush: 11480Sstevel@tonic-gate * Flush data upstream 11490Sstevel@tonic-gate */ 11500Sstevel@tonic-gate static void 11510Sstevel@tonic-gate kbtrans_flush(register struct kbtrans *upper) 11520Sstevel@tonic-gate { 11530Sstevel@tonic-gate register queue_t *q; 11540Sstevel@tonic-gate 11550Sstevel@tonic-gate /* Flush pending data already sent upstream */ 11560Sstevel@tonic-gate if ((q = upper->kbtrans_streams_readq) != NULL && q->q_next != NULL) 11570Sstevel@tonic-gate (void) putnextctl1(q, M_FLUSH, FLUSHR); 11580Sstevel@tonic-gate 11590Sstevel@tonic-gate /* Flush pending ups */ 11600Sstevel@tonic-gate bzero(upper->kbtrans_streams_downs, upper->kbtrans_streams_downs_bytes); 11610Sstevel@tonic-gate 11620Sstevel@tonic-gate kbtrans_cancelrpt(upper); 11630Sstevel@tonic-gate } 11640Sstevel@tonic-gate 11650Sstevel@tonic-gate /* 11660Sstevel@tonic-gate * kbtrans_setled: 11670Sstevel@tonic-gate * Update the keyboard LEDs to match the current keyboard state. 11680Sstevel@tonic-gate */ 11690Sstevel@tonic-gate static void 11700Sstevel@tonic-gate kbtrans_setled(struct kbtrans *upper) 11710Sstevel@tonic-gate { 11720Sstevel@tonic-gate upper->kbtrans_streams_hw_callbacks->kbtrans_streams_setled( 11737688SAaron.Zang@Sun.COM upper->kbtrans_streams_hw, 11747688SAaron.Zang@Sun.COM upper->kbtrans_lower.kbtrans_led_state); 11750Sstevel@tonic-gate } 11760Sstevel@tonic-gate 11770Sstevel@tonic-gate /* 11780Sstevel@tonic-gate * kbtrans_rpt: 11790Sstevel@tonic-gate * If a key is held down, this function is set up to be called 11800Sstevel@tonic-gate * after kbtrans_repeat_rate time elapses. 11810Sstevel@tonic-gate */ 11820Sstevel@tonic-gate static void 11830Sstevel@tonic-gate kbtrans_rpt(void *arg) 11840Sstevel@tonic-gate { 11850Sstevel@tonic-gate struct kbtrans *upper = arg; 11860Sstevel@tonic-gate struct kbtrans_lower *lower = &upper->kbtrans_lower; 11870Sstevel@tonic-gate 11880Sstevel@tonic-gate DPRINTF(PRINT_L0, PRINT_MASK_ALL, (NULL, 11897688SAaron.Zang@Sun.COM "kbtrans_rpt: repeat key %X\n", 11907688SAaron.Zang@Sun.COM lower->kbtrans_repeatkey)); 11910Sstevel@tonic-gate 11920Sstevel@tonic-gate upper->kbtrans_streams_rptid = 0; 11930Sstevel@tonic-gate 11940Sstevel@tonic-gate /* 11950Sstevel@tonic-gate * NB: polled code zaps kbtrans_repeatkey without cancelling 11960Sstevel@tonic-gate * timeout. 11970Sstevel@tonic-gate */ 11980Sstevel@tonic-gate if (lower->kbtrans_repeatkey != 0) { 11990Sstevel@tonic-gate kbtrans_keyreleased(upper, lower->kbtrans_repeatkey); 12000Sstevel@tonic-gate 12010Sstevel@tonic-gate kbtrans_processkey(lower, 12027688SAaron.Zang@Sun.COM upper->kbtrans_streams_callback, 12037688SAaron.Zang@Sun.COM lower->kbtrans_repeatkey, 12047688SAaron.Zang@Sun.COM KEY_PRESSED); 12050Sstevel@tonic-gate 12060Sstevel@tonic-gate upper->kbtrans_streams_rptid = 12077688SAaron.Zang@Sun.COM qtimeout(upper->kbtrans_streams_readq, kbtrans_rpt, 12087688SAaron.Zang@Sun.COM (caddr_t)upper, kbtrans_repeat_rate); 12090Sstevel@tonic-gate } 12100Sstevel@tonic-gate } 12110Sstevel@tonic-gate 12120Sstevel@tonic-gate /* 12130Sstevel@tonic-gate * kbtrans_cancelrpt: 12140Sstevel@tonic-gate * Cancel the repeating key 12150Sstevel@tonic-gate */ 12160Sstevel@tonic-gate static void 12170Sstevel@tonic-gate kbtrans_cancelrpt(struct kbtrans *upper) 12180Sstevel@tonic-gate { 12190Sstevel@tonic-gate upper->kbtrans_lower.kbtrans_repeatkey = 0; 12200Sstevel@tonic-gate 12210Sstevel@tonic-gate if (upper->kbtrans_streams_rptid != 0) { 12220Sstevel@tonic-gate (void) quntimeout(upper->kbtrans_streams_readq, 12237688SAaron.Zang@Sun.COM upper->kbtrans_streams_rptid); 12240Sstevel@tonic-gate upper->kbtrans_streams_rptid = 0; 12250Sstevel@tonic-gate } 12260Sstevel@tonic-gate } 12270Sstevel@tonic-gate 12280Sstevel@tonic-gate /* 12290Sstevel@tonic-gate * kbtrans_send_esc_event: 12300Sstevel@tonic-gate * Send character up stream. Used for the case of 12310Sstevel@tonic-gate * sending strings upstream. 12320Sstevel@tonic-gate */ 12330Sstevel@tonic-gate static void 12340Sstevel@tonic-gate kbtrans_send_esc_event(char c, register struct kbtrans *upper) 12350Sstevel@tonic-gate { 12360Sstevel@tonic-gate Firm_event fe; 12370Sstevel@tonic-gate 12380Sstevel@tonic-gate fe.id = c; 12390Sstevel@tonic-gate fe.value = 1; 12400Sstevel@tonic-gate fe.pair_type = FE_PAIR_NONE; 12410Sstevel@tonic-gate fe.pair = 0; 12420Sstevel@tonic-gate /* 12430Sstevel@tonic-gate * Pretend as if each cp pushed and released 12440Sstevel@tonic-gate * Calling kbtrans_queueevent avoids addr translation 12450Sstevel@tonic-gate * and pair base determination of kbtrans_keypressed. 12460Sstevel@tonic-gate */ 12470Sstevel@tonic-gate kbtrans_queueevent(upper, &fe); 12480Sstevel@tonic-gate fe.value = 0; 12490Sstevel@tonic-gate kbtrans_queueevent(upper, &fe); 12500Sstevel@tonic-gate } 12510Sstevel@tonic-gate 12520Sstevel@tonic-gate /* 12530Sstevel@tonic-gate * kbtrans_strsetwithdecimal: 12540Sstevel@tonic-gate * Used for expanding a function key to the ascii equivalent 12550Sstevel@tonic-gate */ 12560Sstevel@tonic-gate static char * 12570Sstevel@tonic-gate kbtrans_strsetwithdecimal(char *buf, uint_t val, uint_t maxdigs) 12580Sstevel@tonic-gate { 12590Sstevel@tonic-gate int hradix = 5; 12600Sstevel@tonic-gate char *bp; 12610Sstevel@tonic-gate int lowbit; 12620Sstevel@tonic-gate char *tab = "0123456789abcdef"; 12630Sstevel@tonic-gate 12640Sstevel@tonic-gate bp = buf + maxdigs; 12650Sstevel@tonic-gate *(--bp) = '\0'; 12660Sstevel@tonic-gate while (val) { 12670Sstevel@tonic-gate lowbit = val & 1; 12680Sstevel@tonic-gate val = (val >> 1); 12690Sstevel@tonic-gate *(--bp) = tab[val % hradix * 2 + lowbit]; 12700Sstevel@tonic-gate val /= hradix; 12710Sstevel@tonic-gate } 12720Sstevel@tonic-gate return (bp); 12730Sstevel@tonic-gate } 12740Sstevel@tonic-gate 12750Sstevel@tonic-gate /* 12760Sstevel@tonic-gate * kbtrans_keypressed: 12770Sstevel@tonic-gate * Modify Firm event to be sent up the stream 12780Sstevel@tonic-gate */ 12790Sstevel@tonic-gate static void 12800Sstevel@tonic-gate kbtrans_keypressed(struct kbtrans *upper, uchar_t key_station, 12810Sstevel@tonic-gate Firm_event *fe, ushort_t base) 12820Sstevel@tonic-gate { 12830Sstevel@tonic-gate 12840Sstevel@tonic-gate register short id_addr; 12850Sstevel@tonic-gate struct kbtrans_lower *lower = &upper->kbtrans_lower; 12860Sstevel@tonic-gate 12870Sstevel@tonic-gate /* Set pair values */ 12880Sstevel@tonic-gate if (fe->id < (ushort_t)VKEY_FIRST) { 12890Sstevel@tonic-gate /* 12900Sstevel@tonic-gate * If CTRLed, find the ID that would have been used had it 12910Sstevel@tonic-gate * not been CTRLed. 12920Sstevel@tonic-gate */ 12930Sstevel@tonic-gate if (lower->kbtrans_shiftmask & (CTRLMASK | CTLSMASK)) { 12940Sstevel@tonic-gate unsigned short *ke; 12950Sstevel@tonic-gate unsigned int mask; 12960Sstevel@tonic-gate 12970Sstevel@tonic-gate mask = lower->kbtrans_shiftmask & 12987688SAaron.Zang@Sun.COM ~(CTRLMASK | CTLSMASK | UPMASK); 12990Sstevel@tonic-gate 13000Sstevel@tonic-gate ke = kbtrans_find_entry(lower, mask, key_station); 13010Sstevel@tonic-gate if (ke == NULL) 13020Sstevel@tonic-gate return; 13030Sstevel@tonic-gate 13040Sstevel@tonic-gate base = *ke; 13050Sstevel@tonic-gate } 13060Sstevel@tonic-gate if (base != fe->id) { 13070Sstevel@tonic-gate fe->pair_type = FE_PAIR_SET; 13080Sstevel@tonic-gate fe->pair = (uchar_t)base; 13090Sstevel@tonic-gate 13100Sstevel@tonic-gate goto send; 13110Sstevel@tonic-gate } 13120Sstevel@tonic-gate } 13130Sstevel@tonic-gate fe->pair_type = FE_PAIR_NONE; 13140Sstevel@tonic-gate fe->pair = 0; 13150Sstevel@tonic-gate 13160Sstevel@tonic-gate send: 13170Sstevel@tonic-gate /* Adjust event id address for multiple keyboard/workstation support */ 13180Sstevel@tonic-gate switch (vuid_id_addr(fe->id)) { 13190Sstevel@tonic-gate case ASCII_FIRST: 13200Sstevel@tonic-gate id_addr = upper->kbtrans_streams_vuid_addr.ascii; 13210Sstevel@tonic-gate break; 13220Sstevel@tonic-gate case TOP_FIRST: 13230Sstevel@tonic-gate id_addr = upper->kbtrans_streams_vuid_addr.top; 13240Sstevel@tonic-gate break; 13250Sstevel@tonic-gate case VKEY_FIRST: 13260Sstevel@tonic-gate id_addr = upper->kbtrans_streams_vuid_addr.vkey; 13270Sstevel@tonic-gate break; 13280Sstevel@tonic-gate default: 13290Sstevel@tonic-gate id_addr = vuid_id_addr(fe->id); 13300Sstevel@tonic-gate break; 13310Sstevel@tonic-gate } 13320Sstevel@tonic-gate fe->id = vuid_id_offset(fe->id) | id_addr; 13330Sstevel@tonic-gate 13340Sstevel@tonic-gate kbtrans_queuepress(upper, key_station, fe); 13350Sstevel@tonic-gate } 13360Sstevel@tonic-gate 13370Sstevel@tonic-gate /* 13380Sstevel@tonic-gate * kbtrans_queuepress: 13390Sstevel@tonic-gate * Add keypress to the "downs" table 13400Sstevel@tonic-gate */ 13410Sstevel@tonic-gate static void 13420Sstevel@tonic-gate kbtrans_queuepress(struct kbtrans *upper, 13430Sstevel@tonic-gate uchar_t key_station, Firm_event *fe) 13440Sstevel@tonic-gate { 13450Sstevel@tonic-gate register struct key_event *ke, *ke_free; 13460Sstevel@tonic-gate register int i; 13470Sstevel@tonic-gate 13480Sstevel@tonic-gate DPRINTF(PRINT_L0, PRINT_MASK_ALL, (NULL, "kbtrans_queuepress:" 13497688SAaron.Zang@Sun.COM " key=%d", key_station)); 13500Sstevel@tonic-gate 13510Sstevel@tonic-gate ke_free = 0; 13520Sstevel@tonic-gate 13530Sstevel@tonic-gate /* Scan table of down key stations */ 13540Sstevel@tonic-gate 13550Sstevel@tonic-gate for (i = 0, ke = upper->kbtrans_streams_downs; 13560Sstevel@tonic-gate i < upper->kbtrans_streams_num_downs_entries; i++, ke++) { 13570Sstevel@tonic-gate 13580Sstevel@tonic-gate /* Keycode already down? */ 13590Sstevel@tonic-gate if (ke->key_station == key_station) { 13600Sstevel@tonic-gate 13610Sstevel@tonic-gate DPRINTF(PRINT_L0, PRINT_MASK_ALL, 13627688SAaron.Zang@Sun.COM (NULL, "kbtrans: Double " 13637688SAaron.Zang@Sun.COM "entry in downs table (%d,%d)!\n", 13647688SAaron.Zang@Sun.COM key_station, i)); 13650Sstevel@tonic-gate 13660Sstevel@tonic-gate goto add_event; 13670Sstevel@tonic-gate } 13680Sstevel@tonic-gate 13690Sstevel@tonic-gate if (ke->key_station == 0) 13700Sstevel@tonic-gate ke_free = ke; 13710Sstevel@tonic-gate } 13720Sstevel@tonic-gate 13730Sstevel@tonic-gate if (ke_free) { 13740Sstevel@tonic-gate ke = ke_free; 13750Sstevel@tonic-gate goto add_event; 13760Sstevel@tonic-gate } 13770Sstevel@tonic-gate 13780Sstevel@tonic-gate ke = upper->kbtrans_streams_downs; 13790Sstevel@tonic-gate 13800Sstevel@tonic-gate add_event: 13810Sstevel@tonic-gate ke->key_station = key_station; 13820Sstevel@tonic-gate ke->event = *fe; 13830Sstevel@tonic-gate kbtrans_queueevent(upper, fe); 13840Sstevel@tonic-gate } 13850Sstevel@tonic-gate 13860Sstevel@tonic-gate /* 13870Sstevel@tonic-gate * kbtrans_keyreleased: 13880Sstevel@tonic-gate * Remove entry from the downs table 13890Sstevel@tonic-gate */ 13900Sstevel@tonic-gate static void 13910Sstevel@tonic-gate kbtrans_keyreleased(register struct kbtrans *upper, uchar_t key_station) 13920Sstevel@tonic-gate { 13930Sstevel@tonic-gate register struct key_event *ke; 13940Sstevel@tonic-gate register int i; 13950Sstevel@tonic-gate 13960Sstevel@tonic-gate DPRINTF(PRINT_L0, PRINT_MASK_ALL, (NULL, "RELEASE key=%d\n", 13977688SAaron.Zang@Sun.COM key_station)); 13980Sstevel@tonic-gate 13990Sstevel@tonic-gate if (upper->kbtrans_streams_translate_mode != TR_EVENT && 14000Sstevel@tonic-gate upper->kbtrans_streams_translate_mode != TR_UNTRANS_EVENT) { 14010Sstevel@tonic-gate 14020Sstevel@tonic-gate return; 14030Sstevel@tonic-gate } 14040Sstevel@tonic-gate 14050Sstevel@tonic-gate /* Scan table of down key stations */ 14060Sstevel@tonic-gate for (i = 0, ke = upper->kbtrans_streams_downs; 14070Sstevel@tonic-gate i < upper->kbtrans_streams_num_downs_entries; 14080Sstevel@tonic-gate i++, ke++) { 14090Sstevel@tonic-gate /* Found? */ 14100Sstevel@tonic-gate if (ke->key_station == key_station) { 14110Sstevel@tonic-gate ke->key_station = 0; 14120Sstevel@tonic-gate ke->event.value = 0; 14130Sstevel@tonic-gate kbtrans_queueevent(upper, &ke->event); 14140Sstevel@tonic-gate } 14150Sstevel@tonic-gate } 14160Sstevel@tonic-gate 14170Sstevel@tonic-gate /* 14180Sstevel@tonic-gate * Ignore if couldn't find because may be called twice 14190Sstevel@tonic-gate * for the same key station in the case of the kbtrans_rpt 14200Sstevel@tonic-gate * routine being called unnecessarily. 14210Sstevel@tonic-gate */ 14220Sstevel@tonic-gate } 14230Sstevel@tonic-gate 14240Sstevel@tonic-gate 14250Sstevel@tonic-gate /* 14260Sstevel@tonic-gate * kbtrans_putcode: 14270Sstevel@tonic-gate * Pass a keycode up the stream, if you can, otherwise throw it away. 14280Sstevel@tonic-gate */ 14290Sstevel@tonic-gate static void 14300Sstevel@tonic-gate kbtrans_putcode(register struct kbtrans *upper, uint_t code) 14310Sstevel@tonic-gate { 14320Sstevel@tonic-gate register mblk_t *bp; 14330Sstevel@tonic-gate 14340Sstevel@tonic-gate /* 14350Sstevel@tonic-gate * If we can't send it up, then we just drop it. 14360Sstevel@tonic-gate */ 14370Sstevel@tonic-gate if (!canputnext(upper->kbtrans_streams_readq)) { 14380Sstevel@tonic-gate 14390Sstevel@tonic-gate return; 14400Sstevel@tonic-gate } 14410Sstevel@tonic-gate 14420Sstevel@tonic-gate /* 14430Sstevel@tonic-gate * Allocate a messsage block to send up. 14440Sstevel@tonic-gate */ 14450Sstevel@tonic-gate if ((bp = allocb(sizeof (uint_t), BPRI_HI)) == NULL) { 14460Sstevel@tonic-gate 14470Sstevel@tonic-gate cmn_err(CE_WARN, "kbtrans_putcode: Can't allocate block\ 14480Sstevel@tonic-gate for keycode."); 14490Sstevel@tonic-gate 14500Sstevel@tonic-gate return; 14510Sstevel@tonic-gate } 14520Sstevel@tonic-gate 14530Sstevel@tonic-gate /* 14540Sstevel@tonic-gate * We will strip out any high order information here. 14550Sstevel@tonic-gate */ 14560Sstevel@tonic-gate /* NOTE the implicit cast here */ 14570Sstevel@tonic-gate *bp->b_wptr++ = (uchar_t)code; 14580Sstevel@tonic-gate 14590Sstevel@tonic-gate /* 14600Sstevel@tonic-gate * Send the message up. 14610Sstevel@tonic-gate */ 14620Sstevel@tonic-gate (void) putnext(upper->kbtrans_streams_readq, bp); 14630Sstevel@tonic-gate } 14640Sstevel@tonic-gate 14650Sstevel@tonic-gate 14660Sstevel@tonic-gate /* 14670Sstevel@tonic-gate * kbtrans_putbuf: 14680Sstevel@tonic-gate * Pass generated keycode sequence to upstream, if possible. 14690Sstevel@tonic-gate */ 14700Sstevel@tonic-gate static void 14710Sstevel@tonic-gate kbtrans_putbuf(char *buf, queue_t *q) 14720Sstevel@tonic-gate { 14730Sstevel@tonic-gate register mblk_t *bp; 14740Sstevel@tonic-gate 14750Sstevel@tonic-gate if (!canputnext(q)) { 14760Sstevel@tonic-gate cmn_err(CE_WARN, "kbtrans_putbuf: Can't put block for keycode"); 14770Sstevel@tonic-gate } else { 14780Sstevel@tonic-gate if ((bp = allocb((int)strlen(buf), BPRI_HI)) == NULL) { 14790Sstevel@tonic-gate cmn_err(CE_WARN, "kbtrans_putbuf: " 14800Sstevel@tonic-gate "Can't allocate block for keycode"); 14810Sstevel@tonic-gate } else { 14820Sstevel@tonic-gate while (*buf) { 14830Sstevel@tonic-gate *bp->b_wptr++ = *buf; 14840Sstevel@tonic-gate buf++; 14850Sstevel@tonic-gate } 14860Sstevel@tonic-gate putnext(q, bp); 14870Sstevel@tonic-gate } 14880Sstevel@tonic-gate } 14890Sstevel@tonic-gate } 14900Sstevel@tonic-gate 14910Sstevel@tonic-gate /* 14920Sstevel@tonic-gate * kbtrans_queueevent: 14930Sstevel@tonic-gate * Pass a VUID "firm event" up the stream, if you can. 14940Sstevel@tonic-gate */ 14950Sstevel@tonic-gate static void 14960Sstevel@tonic-gate kbtrans_queueevent(struct kbtrans *upper, Firm_event *fe) 14970Sstevel@tonic-gate { 14980Sstevel@tonic-gate register queue_t *q; 14990Sstevel@tonic-gate register mblk_t *bp; 15000Sstevel@tonic-gate 15010Sstevel@tonic-gate if ((q = upper->kbtrans_streams_readq) == NULL) 15020Sstevel@tonic-gate 15030Sstevel@tonic-gate return; 15040Sstevel@tonic-gate 15050Sstevel@tonic-gate if (!canputnext(q)) { 15060Sstevel@tonic-gate if (kbtrans_overflow_msg) { 15070Sstevel@tonic-gate DPRINTF(PRINT_L2, PRINT_MASK_ALL, (NULL, 15087688SAaron.Zang@Sun.COM "kbtrans: Buffer flushed when overflowed.")); 15090Sstevel@tonic-gate } 15100Sstevel@tonic-gate 15110Sstevel@tonic-gate kbtrans_flush(upper); 15120Sstevel@tonic-gate upper->kbtrans_overflow_cnt++; 15130Sstevel@tonic-gate } else { 15140Sstevel@tonic-gate if ((bp = allocb(sizeof (Firm_event), BPRI_HI)) == NULL) { 15150Sstevel@tonic-gate cmn_err(CE_WARN, "kbtrans_queueevent: Can't allocate \ 15160Sstevel@tonic-gate block for event."); 15170Sstevel@tonic-gate } else { 15180Sstevel@tonic-gate uniqtime32(&fe->time); 15197688SAaron.Zang@Sun.COM *(Firm_event *)bp->b_wptr = *fe; 15200Sstevel@tonic-gate bp->b_wptr += sizeof (Firm_event); 15210Sstevel@tonic-gate (void) putnext(q, bp); 15220Sstevel@tonic-gate 15230Sstevel@tonic-gate 15240Sstevel@tonic-gate } 15250Sstevel@tonic-gate } 15260Sstevel@tonic-gate } 15270Sstevel@tonic-gate 15280Sstevel@tonic-gate /* 15290Sstevel@tonic-gate * kbtrans_set_translation_callback: 15300Sstevel@tonic-gate * This code sets the translation_callback pointer based on the 15310Sstevel@tonic-gate * translation mode. 15320Sstevel@tonic-gate */ 15330Sstevel@tonic-gate static void 15340Sstevel@tonic-gate kbtrans_set_translation_callback(register struct kbtrans *upper) 15350Sstevel@tonic-gate { 15360Sstevel@tonic-gate switch (upper->kbtrans_streams_translate_mode) { 15370Sstevel@tonic-gate 15380Sstevel@tonic-gate default: 15390Sstevel@tonic-gate case TR_ASCII: 15407688SAaron.Zang@Sun.COM upper->vt_switch_keystate = VT_SWITCH_KEY_NONE; 15417688SAaron.Zang@Sun.COM 15427688SAaron.Zang@Sun.COM /* Discard any obsolete CTRL/ALT/SHIFT keys */ 15437688SAaron.Zang@Sun.COM upper->kbtrans_lower.kbtrans_shiftmask &= 15447688SAaron.Zang@Sun.COM ~(CTRLMASK | ALTMASK | SHIFTMASK); 15457688SAaron.Zang@Sun.COM upper->kbtrans_lower.kbtrans_togglemask &= 15467688SAaron.Zang@Sun.COM ~(CTRLMASK | ALTMASK | SHIFTMASK); 15477688SAaron.Zang@Sun.COM 15480Sstevel@tonic-gate upper->kbtrans_streams_callback = &ascii_callback; 15490Sstevel@tonic-gate 15500Sstevel@tonic-gate break; 15510Sstevel@tonic-gate 15520Sstevel@tonic-gate case TR_EVENT: 15530Sstevel@tonic-gate upper->kbtrans_streams_callback = &trans_event_callback; 15540Sstevel@tonic-gate 15550Sstevel@tonic-gate break; 15560Sstevel@tonic-gate 15570Sstevel@tonic-gate case TR_UNTRANS_EVENT: 15580Sstevel@tonic-gate upper->kbtrans_streams_callback = &untrans_event_callback; 15590Sstevel@tonic-gate 15600Sstevel@tonic-gate break; 15610Sstevel@tonic-gate } 15620Sstevel@tonic-gate } 15630Sstevel@tonic-gate 15640Sstevel@tonic-gate /* 15650Sstevel@tonic-gate * kbtrans_untrans_keypressed_raw: 15660Sstevel@tonic-gate * This is the callback we get if we are in TR_UNTRANS_EVENT and a 15670Sstevel@tonic-gate * key is pressed. This code will just send the scancode up the 15680Sstevel@tonic-gate * stream. 15690Sstevel@tonic-gate */ 15700Sstevel@tonic-gate static void 15710Sstevel@tonic-gate kbtrans_untrans_keypressed_raw(struct kbtrans *upper, kbtrans_key_t key) 15720Sstevel@tonic-gate { 15730Sstevel@tonic-gate Firm_event fe; 15740Sstevel@tonic-gate 15750Sstevel@tonic-gate bzero(&fe, sizeof (fe)); 15760Sstevel@tonic-gate 15770Sstevel@tonic-gate /* 15780Sstevel@tonic-gate * fill in the event 15790Sstevel@tonic-gate */ 15800Sstevel@tonic-gate fe.id = (unsigned short)key; 15810Sstevel@tonic-gate fe.value = 1; 15820Sstevel@tonic-gate 15830Sstevel@tonic-gate /* 15840Sstevel@tonic-gate * Send the event upstream. 15850Sstevel@tonic-gate */ 15860Sstevel@tonic-gate kbtrans_queuepress(upper, key, &fe); 15870Sstevel@tonic-gate } 15880Sstevel@tonic-gate 15890Sstevel@tonic-gate /* 15900Sstevel@tonic-gate * kbtrans_untrans_keyreleased_raw: 15910Sstevel@tonic-gate * This is the callback we get if we are in TR_UNTRANS_EVENT mode 15920Sstevel@tonic-gate * and a key is released. This code will just send the scancode up 15930Sstevel@tonic-gate * the stream. 15940Sstevel@tonic-gate */ 15950Sstevel@tonic-gate static void 15960Sstevel@tonic-gate kbtrans_untrans_keyreleased_raw(struct kbtrans *upper, kbtrans_key_t key) 15970Sstevel@tonic-gate { 15980Sstevel@tonic-gate /* 15990Sstevel@tonic-gate * Deal with a key released event. 16000Sstevel@tonic-gate */ 16010Sstevel@tonic-gate kbtrans_keyreleased(upper, key); 16020Sstevel@tonic-gate } 16030Sstevel@tonic-gate 16040Sstevel@tonic-gate /* 16057688SAaron.Zang@Sun.COM * kbtrans_vt_compose: 16067688SAaron.Zang@Sun.COM * To compose the key sequences for virtual terminal switching. 16077688SAaron.Zang@Sun.COM * 16087688SAaron.Zang@Sun.COM * 'ALTL + F#' for 1-12 terminals 16097688SAaron.Zang@Sun.COM * 'ALTGR + F#' for 13-24 terminals 16107688SAaron.Zang@Sun.COM * 'ALT + UPARROW' for last terminal 16117688SAaron.Zang@Sun.COM * 'ALT + LEFTARROW' for previous terminal 16127688SAaron.Zang@Sun.COM * 'ALT + RIGHTARROW' for next terminal 16137688SAaron.Zang@Sun.COM * 16147688SAaron.Zang@Sun.COM * the vt switching message is encoded as: 16157688SAaron.Zang@Sun.COM * 16167688SAaron.Zang@Sun.COM * ------------------------------------------------------------- 16177688SAaron.Zang@Sun.COM * | \033 | 'Q' | vtno + 'A' | opcode | 'z' | '\0' | 16187688SAaron.Zang@Sun.COM * ------------------------------------------------------------- 16197688SAaron.Zang@Sun.COM * 16207688SAaron.Zang@Sun.COM * opcode: 16217688SAaron.Zang@Sun.COM * 'B' to switch to previous terminal 16227688SAaron.Zang@Sun.COM * 'F' to switch to next terminal 16237688SAaron.Zang@Sun.COM * 'L' to switch to last terminal 16247688SAaron.Zang@Sun.COM * 'H' to switch to the terminal as specified by vtno, 16257688SAaron.Zang@Sun.COM * which is from 1 to 24. 16267688SAaron.Zang@Sun.COM * 16277688SAaron.Zang@Sun.COM * Here keyid is the keycode of UPARROW, LEFTARROW, or RIGHTARROW 16287688SAaron.Zang@Sun.COM * when it is a kind of arrow key as indicated by is_arrow_key, 16297688SAaron.Zang@Sun.COM * otherwise it indicates a function key and keyid is the number 16307688SAaron.Zang@Sun.COM * corresponding to that function key. 16317688SAaron.Zang@Sun.COM */ 16327688SAaron.Zang@Sun.COM static void 16337688SAaron.Zang@Sun.COM kbtrans_vt_compose(struct kbtrans *upper, unsigned short keyid, 16347688SAaron.Zang@Sun.COM boolean_t is_arrow_key, char *buf) 16357688SAaron.Zang@Sun.COM { 16367688SAaron.Zang@Sun.COM char *bufp; 16377688SAaron.Zang@Sun.COM 16387688SAaron.Zang@Sun.COM bufp = buf; 16397688SAaron.Zang@Sun.COM *bufp++ = '\033'; /* Escape */ 16407688SAaron.Zang@Sun.COM *bufp++ = 'Q'; 16417688SAaron.Zang@Sun.COM if (is_arrow_key) { 16427688SAaron.Zang@Sun.COM *bufp++ = 'A'; 16437688SAaron.Zang@Sun.COM switch (keyid) { 16447688SAaron.Zang@Sun.COM case UPARROW: /* last vt */ 16457688SAaron.Zang@Sun.COM *bufp++ = 'L'; 16467688SAaron.Zang@Sun.COM break; 16477688SAaron.Zang@Sun.COM case LEFTARROW: /* previous vt */ 16487688SAaron.Zang@Sun.COM *bufp++ = 'B'; 16497688SAaron.Zang@Sun.COM break; 16507688SAaron.Zang@Sun.COM case RIGHTARROW: /* next vt */ 16517688SAaron.Zang@Sun.COM *bufp++ = 'F'; 16527688SAaron.Zang@Sun.COM break; 16537688SAaron.Zang@Sun.COM default: 16547688SAaron.Zang@Sun.COM break; 16557688SAaron.Zang@Sun.COM } 16567688SAaron.Zang@Sun.COM } else { 16577688SAaron.Zang@Sun.COM /* this is funckey specifying vtno for switch */ 16587688SAaron.Zang@Sun.COM *bufp++ = keyid + 16597688SAaron.Zang@Sun.COM (upper->vt_switch_keystate - VT_SWITCH_KEY_ALT) * 16607688SAaron.Zang@Sun.COM KB_NR_FUNCKEYS + 'A'; 16617688SAaron.Zang@Sun.COM *bufp++ = 'H'; 16627688SAaron.Zang@Sun.COM } 16637688SAaron.Zang@Sun.COM *bufp++ = 'z'; 16647688SAaron.Zang@Sun.COM *bufp = '\0'; 16657688SAaron.Zang@Sun.COM 16667688SAaron.Zang@Sun.COM /* 16677688SAaron.Zang@Sun.COM * Send the result upstream. 16687688SAaron.Zang@Sun.COM */ 16697688SAaron.Zang@Sun.COM kbtrans_putbuf(buf, upper->kbtrans_streams_readq); 16707688SAaron.Zang@Sun.COM 16717688SAaron.Zang@Sun.COM } 16727688SAaron.Zang@Sun.COM 16737688SAaron.Zang@Sun.COM /* 16740Sstevel@tonic-gate * kbtrans_ascii_keypressed: 16750Sstevel@tonic-gate * This is the code if we are in TR_ASCII mode and a key 16760Sstevel@tonic-gate * is pressed. This is where we will do any special processing that 16770Sstevel@tonic-gate * is specific to ASCII key translation. 16780Sstevel@tonic-gate */ 16790Sstevel@tonic-gate /* ARGSUSED */ 16800Sstevel@tonic-gate static void 16810Sstevel@tonic-gate kbtrans_ascii_keypressed( 16820Sstevel@tonic-gate struct kbtrans *upper, 16830Sstevel@tonic-gate uint_t entrytype, 16840Sstevel@tonic-gate kbtrans_key_t key, 16850Sstevel@tonic-gate uint_t entry) 16860Sstevel@tonic-gate { 16870Sstevel@tonic-gate register char *cp; 16880Sstevel@tonic-gate register char *bufp; 16890Sstevel@tonic-gate char buf[14]; 16907688SAaron.Zang@Sun.COM unsigned short keyid; 16910Sstevel@tonic-gate struct kbtrans_lower *lower = &upper->kbtrans_lower; 16920Sstevel@tonic-gate 16930Sstevel@tonic-gate /* 16940Sstevel@tonic-gate * Based on the type of key, we may need to do some ASCII 16957688SAaron.Zang@Sun.COM * specific post processing. Note that the translated entry 16967688SAaron.Zang@Sun.COM * is constructed as the actual keycode plus entrytype. see 16977688SAaron.Zang@Sun.COM * sys/kbd.h for details of each entrytype. 16980Sstevel@tonic-gate */ 16990Sstevel@tonic-gate switch (entrytype) { 17000Sstevel@tonic-gate 17010Sstevel@tonic-gate case BUCKYBITS: 17027688SAaron.Zang@Sun.COM return; 17037688SAaron.Zang@Sun.COM 17040Sstevel@tonic-gate case SHIFTKEYS: 17057688SAaron.Zang@Sun.COM keyid = entry & 0xFF; 17067688SAaron.Zang@Sun.COM if (keyid == ALT) { 17077688SAaron.Zang@Sun.COM upper->vt_switch_keystate = VT_SWITCH_KEY_ALT; 17087688SAaron.Zang@Sun.COM } else if (keyid == ALTGRAPH) { 17097688SAaron.Zang@Sun.COM upper->vt_switch_keystate = VT_SWITCH_KEY_ALTGR; 17107688SAaron.Zang@Sun.COM } 17117688SAaron.Zang@Sun.COM return; 17127688SAaron.Zang@Sun.COM 17130Sstevel@tonic-gate case FUNNY: 17140Sstevel@tonic-gate /* 17150Sstevel@tonic-gate * There is no ascii equivalent. We will ignore these 17160Sstevel@tonic-gate * keys 17170Sstevel@tonic-gate */ 17180Sstevel@tonic-gate return; 17190Sstevel@tonic-gate 17200Sstevel@tonic-gate case FUNCKEYS: 17217688SAaron.Zang@Sun.COM if (upper->vt_switch_keystate > VT_SWITCH_KEY_NONE) { 17227688SAaron.Zang@Sun.COM if (entry >= TOPFUNC && 17237688SAaron.Zang@Sun.COM entry < (TOPFUNC + KB_NR_FUNCKEYS)) { 17247688SAaron.Zang@Sun.COM 17257688SAaron.Zang@Sun.COM /* 17267688SAaron.Zang@Sun.COM * keyid is the number correspoding to F# 17277688SAaron.Zang@Sun.COM * and its value is from 1 to 12. 17287688SAaron.Zang@Sun.COM */ 17297688SAaron.Zang@Sun.COM keyid = (entry & 0xF) + 1; 17307688SAaron.Zang@Sun.COM 17317688SAaron.Zang@Sun.COM kbtrans_vt_compose(upper, keyid, B_FALSE, buf); 17327688SAaron.Zang@Sun.COM return; 17337688SAaron.Zang@Sun.COM } 17347688SAaron.Zang@Sun.COM } 17357688SAaron.Zang@Sun.COM 17360Sstevel@tonic-gate /* 17370Sstevel@tonic-gate * We need to expand this key to get the ascii 17380Sstevel@tonic-gate * equivalent. These are the function keys (F1, F2 ...) 17390Sstevel@tonic-gate */ 17400Sstevel@tonic-gate bufp = buf; 17410Sstevel@tonic-gate cp = kbtrans_strsetwithdecimal(bufp + 2, 17427688SAaron.Zang@Sun.COM (uint_t)((entry & 0x003F) + 192), 17437688SAaron.Zang@Sun.COM sizeof (buf) - 5); 17440Sstevel@tonic-gate *bufp++ = '\033'; /* Escape */ 17450Sstevel@tonic-gate *bufp++ = '['; 17460Sstevel@tonic-gate while (*cp != '\0') 17470Sstevel@tonic-gate *bufp++ = *cp++; 17480Sstevel@tonic-gate *bufp++ = 'z'; 17490Sstevel@tonic-gate *bufp = '\0'; 17500Sstevel@tonic-gate 17510Sstevel@tonic-gate /* 17520Sstevel@tonic-gate * Send the result upstream. 17530Sstevel@tonic-gate */ 17540Sstevel@tonic-gate kbtrans_putbuf(buf, upper->kbtrans_streams_readq); 17550Sstevel@tonic-gate 17560Sstevel@tonic-gate return; 17570Sstevel@tonic-gate 17580Sstevel@tonic-gate case STRING: 17597688SAaron.Zang@Sun.COM if (upper->vt_switch_keystate > VT_SWITCH_KEY_NONE) { 17607688SAaron.Zang@Sun.COM keyid = entry & 0xFF; 17617688SAaron.Zang@Sun.COM if (keyid == UPARROW || 17627688SAaron.Zang@Sun.COM keyid == RIGHTARROW || 17637688SAaron.Zang@Sun.COM keyid == LEFTARROW) { 17647688SAaron.Zang@Sun.COM 17657688SAaron.Zang@Sun.COM kbtrans_vt_compose(upper, keyid, B_TRUE, buf); 17667688SAaron.Zang@Sun.COM return; 17677688SAaron.Zang@Sun.COM } 17687688SAaron.Zang@Sun.COM } 17697688SAaron.Zang@Sun.COM 17700Sstevel@tonic-gate /* 17710Sstevel@tonic-gate * These are the multi byte keys (Home, Up, Down ...) 17720Sstevel@tonic-gate */ 17730Sstevel@tonic-gate cp = &lower->kbtrans_keystringtab[entry & 0x0F][0]; 17740Sstevel@tonic-gate 17750Sstevel@tonic-gate /* 17760Sstevel@tonic-gate * Copy the string from the keystringtable, and send it 17770Sstevel@tonic-gate * upstream a character at a time. 17780Sstevel@tonic-gate */ 17790Sstevel@tonic-gate while (*cp != '\0') { 17800Sstevel@tonic-gate 17810Sstevel@tonic-gate kbtrans_putcode(upper, (uchar_t)*cp); 17820Sstevel@tonic-gate 17830Sstevel@tonic-gate cp++; 17840Sstevel@tonic-gate } 17850Sstevel@tonic-gate 17860Sstevel@tonic-gate return; 17870Sstevel@tonic-gate 17880Sstevel@tonic-gate case PADKEYS: 17890Sstevel@tonic-gate /* 17900Sstevel@tonic-gate * These are the keys on the keypad. Look up the 17910Sstevel@tonic-gate * answer in the kb_numlock_table and send it upstream. 17920Sstevel@tonic-gate */ 17930Sstevel@tonic-gate kbtrans_putcode(upper, 17947688SAaron.Zang@Sun.COM lower->kbtrans_numlock_table[entry&0x1F]); 17950Sstevel@tonic-gate 17960Sstevel@tonic-gate return; 17970Sstevel@tonic-gate 17980Sstevel@tonic-gate case 0: /* normal character */ 17990Sstevel@tonic-gate default: 18000Sstevel@tonic-gate break; 18010Sstevel@tonic-gate } 18020Sstevel@tonic-gate 18030Sstevel@tonic-gate /* 18040Sstevel@tonic-gate * Send the byte upstream. 18050Sstevel@tonic-gate */ 18060Sstevel@tonic-gate kbtrans_putcode(upper, entry); 18070Sstevel@tonic-gate 18080Sstevel@tonic-gate } 18090Sstevel@tonic-gate 18107688SAaron.Zang@Sun.COM #define KB_SCANCODE_ALT 0xe2 18117688SAaron.Zang@Sun.COM #define KB_SCANCODE_ALTGRAPH 0xe6 18127688SAaron.Zang@Sun.COM 18130Sstevel@tonic-gate /* 18140Sstevel@tonic-gate * kbtrans_ascii_keyreleased: 18150Sstevel@tonic-gate * This is the function if we are in TR_ASCII mode and a key 18160Sstevel@tonic-gate * is released. ASCII doesn't have the concept of released keys, 18177688SAaron.Zang@Sun.COM * or make/break codes. So there is nothing for us to do except 18187688SAaron.Zang@Sun.COM * checking 'Alt/AltGraph' release key in order to reset the state 18197688SAaron.Zang@Sun.COM * of vt switch key sequence. 18200Sstevel@tonic-gate */ 18210Sstevel@tonic-gate /* ARGSUSED */ 18220Sstevel@tonic-gate static void 18230Sstevel@tonic-gate kbtrans_ascii_keyreleased(struct kbtrans *upper, kbtrans_key_t key) 18240Sstevel@tonic-gate { 18257688SAaron.Zang@Sun.COM if (key == KB_SCANCODE_ALT || key == KB_SCANCODE_ALTGRAPH) { 18267688SAaron.Zang@Sun.COM upper->vt_switch_keystate = VT_SWITCH_KEY_NONE; 18277688SAaron.Zang@Sun.COM } 18280Sstevel@tonic-gate } 18290Sstevel@tonic-gate 18300Sstevel@tonic-gate /* 18310Sstevel@tonic-gate * kbtrans_ascii_setup_repeat: 18320Sstevel@tonic-gate * This is the function if we are in TR_ASCII mode and the 18330Sstevel@tonic-gate * translation module has decided that a key needs to be repeated. 18340Sstevel@tonic-gate */ 18350Sstevel@tonic-gate /* ARGSUSED */ 18360Sstevel@tonic-gate static void 18370Sstevel@tonic-gate kbtrans_ascii_setup_repeat( 18380Sstevel@tonic-gate struct kbtrans *upper, 18390Sstevel@tonic-gate uint_t entrytype, 18400Sstevel@tonic-gate kbtrans_key_t key) 18410Sstevel@tonic-gate { 18420Sstevel@tonic-gate struct kbtrans_lower *lower = &upper->kbtrans_lower; 18430Sstevel@tonic-gate 18440Sstevel@tonic-gate /* 18450Sstevel@tonic-gate * Cancel any currently repeating keys. This will be a new 18460Sstevel@tonic-gate * key to repeat. 18470Sstevel@tonic-gate */ 18480Sstevel@tonic-gate kbtrans_cancelrpt(upper); 18490Sstevel@tonic-gate 18500Sstevel@tonic-gate /* 18510Sstevel@tonic-gate * Set the value of the key to be repeated. 18520Sstevel@tonic-gate */ 18530Sstevel@tonic-gate lower->kbtrans_repeatkey = key; 18540Sstevel@tonic-gate 18550Sstevel@tonic-gate /* 18560Sstevel@tonic-gate * Start the timeout for repeating this key. kbtrans_rpt will 18570Sstevel@tonic-gate * be called to repeat the key. 18580Sstevel@tonic-gate */ 18590Sstevel@tonic-gate upper->kbtrans_streams_rptid = qtimeout(upper->kbtrans_streams_readq, 18607688SAaron.Zang@Sun.COM kbtrans_rpt, (caddr_t)upper, kbtrans_repeat_delay); 18610Sstevel@tonic-gate } 18620Sstevel@tonic-gate 18630Sstevel@tonic-gate /* 18640Sstevel@tonic-gate * kbtrans_trans_event_keypressed: 18650Sstevel@tonic-gate * This is the function if we are in TR_EVENT mode and a key 18660Sstevel@tonic-gate * is pressed. This is where we will do any special processing that 18670Sstevel@tonic-gate * is specific to EVENT key translation. 18680Sstevel@tonic-gate */ 18690Sstevel@tonic-gate static void 18700Sstevel@tonic-gate kbtrans_trans_event_keypressed( 18710Sstevel@tonic-gate struct kbtrans *upper, 18720Sstevel@tonic-gate uint_t entrytype, 18730Sstevel@tonic-gate kbtrans_key_t key, 18740Sstevel@tonic-gate uint_t entry) 18750Sstevel@tonic-gate { 18760Sstevel@tonic-gate Firm_event fe; 18770Sstevel@tonic-gate register char *cp; 18780Sstevel@tonic-gate struct kbtrans_lower *lower = &upper->kbtrans_lower; 18790Sstevel@tonic-gate 18800Sstevel@tonic-gate /* 18810Sstevel@tonic-gate * Based on the type of key, we may need to do some EVENT 18820Sstevel@tonic-gate * specific post processing. 18830Sstevel@tonic-gate */ 18840Sstevel@tonic-gate switch (entrytype) { 18850Sstevel@tonic-gate 18860Sstevel@tonic-gate case SHIFTKEYS: 18870Sstevel@tonic-gate /* 18880Sstevel@tonic-gate * Relying on ordinal correspondence between 18890Sstevel@tonic-gate * vuid_event.h SHIFT_META-SHIFT_TOP & 18900Sstevel@tonic-gate * kbd.h METABIT-SYSTEMBIT in order to 18910Sstevel@tonic-gate * correctly translate entry into fe.id. 18920Sstevel@tonic-gate */ 18930Sstevel@tonic-gate fe.id = SHIFT_CAPSLOCK + (entry & 0x0F); 18940Sstevel@tonic-gate fe.value = 1; 18950Sstevel@tonic-gate kbtrans_keypressed(upper, key, &fe, fe.id); 18960Sstevel@tonic-gate 18970Sstevel@tonic-gate return; 18980Sstevel@tonic-gate 18990Sstevel@tonic-gate case BUCKYBITS: 19000Sstevel@tonic-gate /* 19010Sstevel@tonic-gate * Relying on ordinal correspondence between 19020Sstevel@tonic-gate * vuid_event.h SHIFT_CAPSLOCK-SHIFT_RIGHTCTRL & 19030Sstevel@tonic-gate * kbd.h CAPSLOCK-RIGHTCTRL in order to 19040Sstevel@tonic-gate * correctly translate entry into fe.id. 19050Sstevel@tonic-gate */ 19060Sstevel@tonic-gate fe.id = SHIFT_META + (entry & 0x0F); 19070Sstevel@tonic-gate fe.value = 1; 19080Sstevel@tonic-gate kbtrans_keypressed(upper, key, &fe, fe.id); 19090Sstevel@tonic-gate 19100Sstevel@tonic-gate return; 19110Sstevel@tonic-gate 19120Sstevel@tonic-gate case FUNCKEYS: 19130Sstevel@tonic-gate /* 19140Sstevel@tonic-gate * Take advantage of the similar 19150Sstevel@tonic-gate * ordering of kbd.h function keys and 19160Sstevel@tonic-gate * vuid_event.h function keys to do a 19170Sstevel@tonic-gate * simple translation to achieve a 19180Sstevel@tonic-gate * mapping between the 2 different 19190Sstevel@tonic-gate * address spaces. 19200Sstevel@tonic-gate */ 19210Sstevel@tonic-gate fe.id = KEY_LEFTFIRST + (entry & 0x003F); 19220Sstevel@tonic-gate fe.value = 1; 19230Sstevel@tonic-gate 19240Sstevel@tonic-gate /* 19250Sstevel@tonic-gate * Assume "up" table only generates 19260Sstevel@tonic-gate * shift changes. 19270Sstevel@tonic-gate */ 19280Sstevel@tonic-gate kbtrans_keypressed(upper, key, &fe, fe.id); 19290Sstevel@tonic-gate 19300Sstevel@tonic-gate /* 19310Sstevel@tonic-gate * Function key events can be expanded 19320Sstevel@tonic-gate * by terminal emulator software to 19330Sstevel@tonic-gate * produce the standard escape sequence 19340Sstevel@tonic-gate * generated by the TR_ASCII case above 19350Sstevel@tonic-gate * if a function key event is not used 19360Sstevel@tonic-gate * by terminal emulator software 19370Sstevel@tonic-gate * directly. 19380Sstevel@tonic-gate */ 19390Sstevel@tonic-gate return; 19400Sstevel@tonic-gate 19410Sstevel@tonic-gate case STRING: 19420Sstevel@tonic-gate /* 19430Sstevel@tonic-gate * These are the multi byte keys (Home, Up, Down ...) 19440Sstevel@tonic-gate */ 19450Sstevel@tonic-gate cp = &lower->kbtrans_keystringtab[entry & 0x0F][0]; 19460Sstevel@tonic-gate 19470Sstevel@tonic-gate /* 19480Sstevel@tonic-gate * Copy the string from the keystringtable, and send it 19490Sstevel@tonic-gate * upstream a character at a time. 19500Sstevel@tonic-gate */ 19510Sstevel@tonic-gate while (*cp != '\0') { 19520Sstevel@tonic-gate 19530Sstevel@tonic-gate kbtrans_send_esc_event(*cp, upper); 19540Sstevel@tonic-gate 19550Sstevel@tonic-gate cp++; 19560Sstevel@tonic-gate } 19570Sstevel@tonic-gate 19580Sstevel@tonic-gate return; 19590Sstevel@tonic-gate 19600Sstevel@tonic-gate case PADKEYS: 19610Sstevel@tonic-gate /* 19620Sstevel@tonic-gate * Take advantage of the similar 19630Sstevel@tonic-gate * ordering of kbd.h keypad keys and 19640Sstevel@tonic-gate * vuid_event.h keypad keys to do a 19650Sstevel@tonic-gate * simple translation to achieve a 19660Sstevel@tonic-gate * mapping between the 2 different 19670Sstevel@tonic-gate * address spaces. 19680Sstevel@tonic-gate */ 19690Sstevel@tonic-gate fe.id = VKEY_FIRSTPAD + (entry & 0x001F); 19700Sstevel@tonic-gate fe.value = 1; 19710Sstevel@tonic-gate 19720Sstevel@tonic-gate /* 19730Sstevel@tonic-gate * Assume "up" table only generates 19740Sstevel@tonic-gate * shift changes. 19750Sstevel@tonic-gate */ 19760Sstevel@tonic-gate kbtrans_keypressed(upper, key, &fe, fe.id); 19770Sstevel@tonic-gate 19780Sstevel@tonic-gate /* 19790Sstevel@tonic-gate * Keypad key events can be expanded 19800Sstevel@tonic-gate * by terminal emulator software to 19810Sstevel@tonic-gate * produce the standard ascii character 19820Sstevel@tonic-gate * generated by the TR_ASCII case above 19830Sstevel@tonic-gate * if a keypad key event is not used 19840Sstevel@tonic-gate * by terminal emulator software 19850Sstevel@tonic-gate * directly. 19860Sstevel@tonic-gate */ 19870Sstevel@tonic-gate return; 19880Sstevel@tonic-gate 19890Sstevel@tonic-gate case FUNNY: 19900Sstevel@tonic-gate /* 19910Sstevel@tonic-gate * These are not events. 19920Sstevel@tonic-gate */ 19930Sstevel@tonic-gate switch (entry) { 19940Sstevel@tonic-gate case IDLE: 19950Sstevel@tonic-gate case RESET: 19960Sstevel@tonic-gate case ERROR: 19970Sstevel@tonic-gate /* 19980Sstevel@tonic-gate * Something has happened. Mark all keys as released. 19990Sstevel@tonic-gate */ 20000Sstevel@tonic-gate kbtrans_streams_releaseall(upper); 20010Sstevel@tonic-gate break; 20020Sstevel@tonic-gate } 20030Sstevel@tonic-gate 20040Sstevel@tonic-gate return; 20050Sstevel@tonic-gate 20060Sstevel@tonic-gate case 0: /* normal character */ 20070Sstevel@tonic-gate default: 20080Sstevel@tonic-gate break; 20090Sstevel@tonic-gate } 20100Sstevel@tonic-gate 20110Sstevel@tonic-gate /* 20120Sstevel@tonic-gate * Send the event upstream. 20130Sstevel@tonic-gate */ 20140Sstevel@tonic-gate fe.id = entry; 20150Sstevel@tonic-gate 20160Sstevel@tonic-gate fe.value = 1; 20170Sstevel@tonic-gate 20180Sstevel@tonic-gate kbtrans_queueevent(upper, &fe); 20190Sstevel@tonic-gate } 20200Sstevel@tonic-gate 20210Sstevel@tonic-gate /* 20220Sstevel@tonic-gate * kbtrans_trans_event_keyreleased: 20230Sstevel@tonic-gate * This is the function if we are in TR_EVENT mode and a key 20240Sstevel@tonic-gate * is released. 20250Sstevel@tonic-gate */ 20260Sstevel@tonic-gate /* ARGSUSED */ 20270Sstevel@tonic-gate static void 20280Sstevel@tonic-gate kbtrans_trans_event_keyreleased(struct kbtrans *upper, kbtrans_key_t key) 20290Sstevel@tonic-gate { 20300Sstevel@tonic-gate /* 20310Sstevel@tonic-gate * Mark the key as released and send an event upstream. 20320Sstevel@tonic-gate */ 20330Sstevel@tonic-gate kbtrans_keyreleased(upper, key); 20340Sstevel@tonic-gate } 20350Sstevel@tonic-gate 20360Sstevel@tonic-gate /* 20370Sstevel@tonic-gate * kbtrans_trans_event_setup_repeat: 20380Sstevel@tonic-gate * This is the function if we are in TR_EVENT mode and the 20390Sstevel@tonic-gate * translation module has decided that a key needs to be repeated. 20400Sstevel@tonic-gate * We will set a timeout to retranslate the repeat key. 20410Sstevel@tonic-gate */ 20420Sstevel@tonic-gate static void 20430Sstevel@tonic-gate kbtrans_trans_event_setup_repeat( 20440Sstevel@tonic-gate struct kbtrans *upper, 20450Sstevel@tonic-gate uint_t entrytype, 20460Sstevel@tonic-gate kbtrans_key_t key) 20470Sstevel@tonic-gate { 20480Sstevel@tonic-gate struct kbtrans_lower *lower = &upper->kbtrans_lower; 20490Sstevel@tonic-gate 20500Sstevel@tonic-gate /* 20510Sstevel@tonic-gate * Function keys and keypad keys do not repeat when we are in 20520Sstevel@tonic-gate * EVENT mode. 20530Sstevel@tonic-gate */ 20540Sstevel@tonic-gate if (entrytype == FUNCKEYS || entrytype == PADKEYS) { 20550Sstevel@tonic-gate 20560Sstevel@tonic-gate return; 20570Sstevel@tonic-gate } 20580Sstevel@tonic-gate 20590Sstevel@tonic-gate /* 20600Sstevel@tonic-gate * Cancel any currently repeating keys. This will be a new 20610Sstevel@tonic-gate * key to repeat. 20620Sstevel@tonic-gate */ 20630Sstevel@tonic-gate kbtrans_cancelrpt(upper); 20640Sstevel@tonic-gate 20650Sstevel@tonic-gate /* 20660Sstevel@tonic-gate * Set the value of the key to be repeated. 20670Sstevel@tonic-gate */ 20680Sstevel@tonic-gate lower->kbtrans_repeatkey = key; 20690Sstevel@tonic-gate 20700Sstevel@tonic-gate /* 20710Sstevel@tonic-gate * Start the timeout for repeating this key. kbtrans_rpt will 20720Sstevel@tonic-gate * be called to repeat the key. 20730Sstevel@tonic-gate */ 20740Sstevel@tonic-gate upper->kbtrans_streams_rptid = qtimeout(upper->kbtrans_streams_readq, 20757688SAaron.Zang@Sun.COM kbtrans_rpt, (caddr_t)upper, kbtrans_repeat_delay); 20760Sstevel@tonic-gate } 20770Sstevel@tonic-gate 20780Sstevel@tonic-gate /* 20790Sstevel@tonic-gate * Administer the key tables. 20800Sstevel@tonic-gate */ 20810Sstevel@tonic-gate 20820Sstevel@tonic-gate /* 20830Sstevel@tonic-gate * Old special codes. 20840Sstevel@tonic-gate */ 20850Sstevel@tonic-gate #define OLD_SHIFTKEYS 0x80 20860Sstevel@tonic-gate #define OLD_BUCKYBITS 0x90 20870Sstevel@tonic-gate #define OLD_FUNNY 0xA0 20880Sstevel@tonic-gate #define OLD_FA_UMLAUT 0xA9 20890Sstevel@tonic-gate #define OLD_FA_CFLEX 0xAA 20900Sstevel@tonic-gate #define OLD_FA_TILDE 0xAB 20910Sstevel@tonic-gate #define OLD_FA_CEDILLA 0xAC 20920Sstevel@tonic-gate #define OLD_FA_ACUTE 0xAD 20930Sstevel@tonic-gate #define OLD_FA_GRAVE 0xAE 20940Sstevel@tonic-gate #define OLD_ISOCHAR 0xAF 20950Sstevel@tonic-gate #define OLD_STRING 0xB0 20960Sstevel@tonic-gate #define OLD_LEFTFUNC 0xC0 20970Sstevel@tonic-gate #define OLD_RIGHTFUNC 0xD0 20980Sstevel@tonic-gate #define OLD_TOPFUNC 0xE0 20990Sstevel@tonic-gate #define OLD_BOTTOMFUNC 0xF0 21000Sstevel@tonic-gate 21010Sstevel@tonic-gate /* 21020Sstevel@tonic-gate * Map old special codes to new ones. 21030Sstevel@tonic-gate * Indexed by ((old special code) >> 4) & 0x07; add (old special code) & 0x0F. 21040Sstevel@tonic-gate */ 21050Sstevel@tonic-gate static ushort_t special_old_to_new[] = { 21060Sstevel@tonic-gate SHIFTKEYS, 21070Sstevel@tonic-gate BUCKYBITS, 21080Sstevel@tonic-gate FUNNY, 21090Sstevel@tonic-gate STRING, 21100Sstevel@tonic-gate LEFTFUNC, 21110Sstevel@tonic-gate RIGHTFUNC, 21120Sstevel@tonic-gate TOPFUNC, 21130Sstevel@tonic-gate BOTTOMFUNC, 21140Sstevel@tonic-gate }; 21150Sstevel@tonic-gate 21160Sstevel@tonic-gate 21170Sstevel@tonic-gate /* 21180Sstevel@tonic-gate * kbtrans_setkey: 21190Sstevel@tonic-gate * Set individual keystation translation from old-style entry. 21200Sstevel@tonic-gate */ 21210Sstevel@tonic-gate static int 21220Sstevel@tonic-gate kbtrans_setkey(struct kbtrans_lower *lower, struct kiockey *key, cred_t *cr) 21230Sstevel@tonic-gate { 21240Sstevel@tonic-gate int strtabindex, i; 21250Sstevel@tonic-gate unsigned short *ke; 21260Sstevel@tonic-gate register int tablemask; 21270Sstevel@tonic-gate register ushort_t entry; 21280Sstevel@tonic-gate register struct keyboard *kp; 21290Sstevel@tonic-gate 21300Sstevel@tonic-gate kp = lower->kbtrans_keyboard; 21310Sstevel@tonic-gate 21320Sstevel@tonic-gate if (key->kio_station >= kp->k_keymap_size) 21330Sstevel@tonic-gate 21340Sstevel@tonic-gate return (EINVAL); 21350Sstevel@tonic-gate 21360Sstevel@tonic-gate if (lower->kbtrans_keyboard == NULL) 21370Sstevel@tonic-gate 21380Sstevel@tonic-gate return (EINVAL); 21390Sstevel@tonic-gate 21400Sstevel@tonic-gate tablemask = key->kio_tablemask; 21410Sstevel@tonic-gate 21420Sstevel@tonic-gate switch (tablemask) { 21430Sstevel@tonic-gate case KIOCABORT1: 21440Sstevel@tonic-gate case KIOCABORT1A: 21450Sstevel@tonic-gate case KIOCABORT2: 21460Sstevel@tonic-gate i = secpolicy_console(cr); 21470Sstevel@tonic-gate if (i != 0) 21480Sstevel@tonic-gate return (i); 21490Sstevel@tonic-gate 21500Sstevel@tonic-gate switch (tablemask) { 21510Sstevel@tonic-gate case KIOCABORT1: 21520Sstevel@tonic-gate kp->k_abort1 = key->kio_station; 21530Sstevel@tonic-gate break; 21540Sstevel@tonic-gate case KIOCABORT1A: 21550Sstevel@tonic-gate kp->k_abort1a = key->kio_station; 21560Sstevel@tonic-gate break; 21570Sstevel@tonic-gate case KIOCABORT2: 21580Sstevel@tonic-gate kp->k_abort2 = key->kio_station; 21590Sstevel@tonic-gate break; 21600Sstevel@tonic-gate } 21610Sstevel@tonic-gate return (0); 21620Sstevel@tonic-gate } 21630Sstevel@tonic-gate 21640Sstevel@tonic-gate if (tablemask & ALTGRAPHMASK) 21650Sstevel@tonic-gate return (EINVAL); 21660Sstevel@tonic-gate 21670Sstevel@tonic-gate ke = kbtrans_find_entry(lower, (uint_t)tablemask, key->kio_station); 21680Sstevel@tonic-gate if (ke == NULL) 21690Sstevel@tonic-gate return (EINVAL); 21700Sstevel@tonic-gate 21710Sstevel@tonic-gate if (key->kio_entry >= (uchar_t)OLD_STRING && 21720Sstevel@tonic-gate key->kio_entry <= (uchar_t)(OLD_STRING + 15)) { 21730Sstevel@tonic-gate strtabindex = key->kio_entry - OLD_STRING; 21740Sstevel@tonic-gate bcopy(key->kio_string, 21757688SAaron.Zang@Sun.COM lower->kbtrans_keystringtab[strtabindex], KTAB_STRLEN); 21760Sstevel@tonic-gate lower->kbtrans_keystringtab[strtabindex][KTAB_STRLEN-1] = '\0'; 21770Sstevel@tonic-gate } 21780Sstevel@tonic-gate 21790Sstevel@tonic-gate entry = key->kio_entry; 21800Sstevel@tonic-gate 21810Sstevel@tonic-gate /* 21820Sstevel@tonic-gate * There's nothing we need do with OLD_ISOCHAR. 21830Sstevel@tonic-gate */ 21840Sstevel@tonic-gate if (entry != OLD_ISOCHAR) { 21850Sstevel@tonic-gate if (entry & 0x80) { 21860Sstevel@tonic-gate if (entry >= OLD_FA_UMLAUT && entry <= OLD_FA_GRAVE) 21870Sstevel@tonic-gate entry = FA_CLASS + (entry & 0x0F) - 9; 21880Sstevel@tonic-gate else 21890Sstevel@tonic-gate entry = 21900Sstevel@tonic-gate special_old_to_new[entry >> 4 & 0x07] 21910Sstevel@tonic-gate + (entry & 0x0F); 21920Sstevel@tonic-gate } 21930Sstevel@tonic-gate } 21940Sstevel@tonic-gate 21950Sstevel@tonic-gate *ke = entry; 21960Sstevel@tonic-gate 21970Sstevel@tonic-gate return (0); 21980Sstevel@tonic-gate } 21990Sstevel@tonic-gate 22000Sstevel@tonic-gate 22010Sstevel@tonic-gate /* 22020Sstevel@tonic-gate * Map new special codes to old ones. 22030Sstevel@tonic-gate * Indexed by (new special code) >> 8; add (new special code) & 0xFF. 22040Sstevel@tonic-gate */ 22050Sstevel@tonic-gate static uchar_t special_new_to_old[] = { 22060Sstevel@tonic-gate 0, /* normal */ 22070Sstevel@tonic-gate OLD_SHIFTKEYS, /* SHIFTKEYS */ 22080Sstevel@tonic-gate OLD_BUCKYBITS, /* BUCKYBITS */ 22090Sstevel@tonic-gate OLD_FUNNY, /* FUNNY */ 22100Sstevel@tonic-gate OLD_FA_UMLAUT, /* FA_CLASS */ 22110Sstevel@tonic-gate OLD_STRING, /* STRING */ 22120Sstevel@tonic-gate OLD_LEFTFUNC, /* FUNCKEYS */ 22130Sstevel@tonic-gate }; 22140Sstevel@tonic-gate 22150Sstevel@tonic-gate 22160Sstevel@tonic-gate /* 22170Sstevel@tonic-gate * kbtrans_getkey: 22180Sstevel@tonic-gate * Get individual keystation translation as old-style entry. 22190Sstevel@tonic-gate */ 22200Sstevel@tonic-gate static int 22210Sstevel@tonic-gate kbtrans_getkey(struct kbtrans_lower *lower, struct kiockey *key) 22220Sstevel@tonic-gate { 22230Sstevel@tonic-gate int strtabindex; 22240Sstevel@tonic-gate unsigned short *ke; 22250Sstevel@tonic-gate register ushort_t entry; 22260Sstevel@tonic-gate struct keyboard *kp; 22270Sstevel@tonic-gate 22280Sstevel@tonic-gate kp = lower->kbtrans_keyboard; 22290Sstevel@tonic-gate 22300Sstevel@tonic-gate if (key->kio_station >= kp->k_keymap_size) 22310Sstevel@tonic-gate return (EINVAL); 22320Sstevel@tonic-gate 22330Sstevel@tonic-gate if (lower->kbtrans_keyboard == NULL) 22340Sstevel@tonic-gate return (EINVAL); 22350Sstevel@tonic-gate 22360Sstevel@tonic-gate switch (key->kio_tablemask) { 22370Sstevel@tonic-gate case KIOCABORT1: 22380Sstevel@tonic-gate key->kio_station = kp->k_abort1; 22390Sstevel@tonic-gate return (0); 22400Sstevel@tonic-gate case KIOCABORT1A: 22410Sstevel@tonic-gate key->kio_station = kp->k_abort1a; 22420Sstevel@tonic-gate return (0); 22430Sstevel@tonic-gate case KIOCABORT2: 22440Sstevel@tonic-gate key->kio_station = kp->k_abort2; 22450Sstevel@tonic-gate return (0); 22460Sstevel@tonic-gate } 22470Sstevel@tonic-gate 22480Sstevel@tonic-gate ke = kbtrans_find_entry(lower, (uint_t)key->kio_tablemask, 22497688SAaron.Zang@Sun.COM key->kio_station); 22500Sstevel@tonic-gate if (ke == NULL) 22510Sstevel@tonic-gate return (EINVAL); 22520Sstevel@tonic-gate 22530Sstevel@tonic-gate entry = *ke; 22540Sstevel@tonic-gate 22550Sstevel@tonic-gate if (entry & 0xFF00) 22560Sstevel@tonic-gate key->kio_entry = 22570Sstevel@tonic-gate special_new_to_old[(ushort_t)(entry & 0xFF00) >> 8] 22580Sstevel@tonic-gate + (entry & 0x00FF); 22590Sstevel@tonic-gate else { 22600Sstevel@tonic-gate if (entry & 0x80) 22610Sstevel@tonic-gate key->kio_entry = (ushort_t)OLD_ISOCHAR; /* you lose */ 22620Sstevel@tonic-gate else 22630Sstevel@tonic-gate key->kio_entry = (ushort_t)entry; 22640Sstevel@tonic-gate } 22650Sstevel@tonic-gate 22660Sstevel@tonic-gate if (entry >= STRING && entry <= (uchar_t)(STRING + 15)) { 22670Sstevel@tonic-gate strtabindex = entry - STRING; 22680Sstevel@tonic-gate bcopy(lower->kbtrans_keystringtab[strtabindex], 22697688SAaron.Zang@Sun.COM key->kio_string, KTAB_STRLEN); 22700Sstevel@tonic-gate } 22710Sstevel@tonic-gate return (0); 22720Sstevel@tonic-gate } 22730Sstevel@tonic-gate 22740Sstevel@tonic-gate 22750Sstevel@tonic-gate /* 22760Sstevel@tonic-gate * kbtrans_skey: 22770Sstevel@tonic-gate * Set individual keystation translation from new-style entry. 22780Sstevel@tonic-gate */ 22790Sstevel@tonic-gate static int 22800Sstevel@tonic-gate kbtrans_skey(struct kbtrans_lower *lower, struct kiockeymap *key, cred_t *cr) 22810Sstevel@tonic-gate { 22820Sstevel@tonic-gate int strtabindex, i; 22830Sstevel@tonic-gate unsigned short *ke; 22840Sstevel@tonic-gate struct keyboard *kp; 22850Sstevel@tonic-gate 22860Sstevel@tonic-gate kp = lower->kbtrans_keyboard; 22870Sstevel@tonic-gate 22880Sstevel@tonic-gate if (key->kio_station >= kp->k_keymap_size) { 22890Sstevel@tonic-gate return (EINVAL); 22900Sstevel@tonic-gate 22910Sstevel@tonic-gate } 22920Sstevel@tonic-gate 22930Sstevel@tonic-gate if (lower->kbtrans_keyboard == NULL) { 22940Sstevel@tonic-gate return (EINVAL); 22950Sstevel@tonic-gate } 22960Sstevel@tonic-gate 22970Sstevel@tonic-gate switch (key->kio_tablemask) { 22980Sstevel@tonic-gate case KIOCABORT1: 22990Sstevel@tonic-gate case KIOCABORT1A: 23000Sstevel@tonic-gate case KIOCABORT2: 23010Sstevel@tonic-gate i = secpolicy_console(cr); 23020Sstevel@tonic-gate if (i != 0) 23030Sstevel@tonic-gate return (i); 23040Sstevel@tonic-gate switch (key->kio_tablemask) { 23050Sstevel@tonic-gate case KIOCABORT1: 23060Sstevel@tonic-gate kp->k_abort1 = key->kio_station; 23070Sstevel@tonic-gate break; 23080Sstevel@tonic-gate case KIOCABORT1A: 23090Sstevel@tonic-gate kp->k_abort1a = key->kio_station; 23100Sstevel@tonic-gate break; 23110Sstevel@tonic-gate case KIOCABORT2: 23120Sstevel@tonic-gate kp->k_abort2 = key->kio_station; 23130Sstevel@tonic-gate break; 23140Sstevel@tonic-gate } 23150Sstevel@tonic-gate return (0); 23160Sstevel@tonic-gate } 23170Sstevel@tonic-gate 23180Sstevel@tonic-gate ke = kbtrans_find_entry(lower, (uint_t)key->kio_tablemask, 23197688SAaron.Zang@Sun.COM key->kio_station); 23200Sstevel@tonic-gate if (ke == NULL) 23210Sstevel@tonic-gate return (EINVAL); 23220Sstevel@tonic-gate 23230Sstevel@tonic-gate if (key->kio_entry >= STRING && 23240Sstevel@tonic-gate key->kio_entry <= (ushort_t)(STRING + 15)) { 23250Sstevel@tonic-gate strtabindex = key->kio_entry-STRING; 23260Sstevel@tonic-gate bcopy(key->kio_string, 23277688SAaron.Zang@Sun.COM lower->kbtrans_keystringtab[strtabindex], KTAB_STRLEN); 23280Sstevel@tonic-gate lower->kbtrans_keystringtab[strtabindex][KTAB_STRLEN-1] = '\0'; 23290Sstevel@tonic-gate } 23300Sstevel@tonic-gate 23310Sstevel@tonic-gate *ke = key->kio_entry; 23320Sstevel@tonic-gate 23330Sstevel@tonic-gate return (0); 23340Sstevel@tonic-gate } 23350Sstevel@tonic-gate 23360Sstevel@tonic-gate 23370Sstevel@tonic-gate /* 23380Sstevel@tonic-gate * kbtrans_gkey: 23390Sstevel@tonic-gate * Get individual keystation translation as new-style entry. 23400Sstevel@tonic-gate */ 23410Sstevel@tonic-gate static int 23420Sstevel@tonic-gate kbtrans_gkey(struct kbtrans_lower *lower, struct kiockeymap *key) 23430Sstevel@tonic-gate { 23440Sstevel@tonic-gate int strtabindex; 23450Sstevel@tonic-gate unsigned short *ke; 23460Sstevel@tonic-gate struct keyboard *kp; 23470Sstevel@tonic-gate 23480Sstevel@tonic-gate kp = lower->kbtrans_keyboard; 23490Sstevel@tonic-gate 23500Sstevel@tonic-gate if (key->kio_station >= kp->k_keymap_size) 23510Sstevel@tonic-gate return (EINVAL); 23520Sstevel@tonic-gate 23530Sstevel@tonic-gate if (lower->kbtrans_keyboard == NULL) 23540Sstevel@tonic-gate return (EINVAL); 23550Sstevel@tonic-gate 23560Sstevel@tonic-gate switch (key->kio_tablemask) { 23570Sstevel@tonic-gate case KIOCABORT1: 23580Sstevel@tonic-gate key->kio_station = kp->k_abort1; 23590Sstevel@tonic-gate return (0); 23600Sstevel@tonic-gate case KIOCABORT1A: 23610Sstevel@tonic-gate key->kio_station = kp->k_abort1a; 23620Sstevel@tonic-gate return (0); 23630Sstevel@tonic-gate case KIOCABORT2: 23640Sstevel@tonic-gate key->kio_station = kp->k_abort2; 23650Sstevel@tonic-gate return (0); 23660Sstevel@tonic-gate } 23670Sstevel@tonic-gate 23680Sstevel@tonic-gate ke = kbtrans_find_entry(lower, (uint_t)key->kio_tablemask, 23697688SAaron.Zang@Sun.COM key->kio_station); 23700Sstevel@tonic-gate if (ke == NULL) 23710Sstevel@tonic-gate return (EINVAL); 23720Sstevel@tonic-gate 23730Sstevel@tonic-gate key->kio_entry = *ke; 23740Sstevel@tonic-gate 23750Sstevel@tonic-gate if (key->kio_entry >= STRING && 23760Sstevel@tonic-gate key->kio_entry <= (ushort_t)(STRING + 15)) { 23770Sstevel@tonic-gate strtabindex = key->kio_entry-STRING; 23780Sstevel@tonic-gate bcopy(lower->kbtrans_keystringtab[strtabindex], 23797688SAaron.Zang@Sun.COM key->kio_string, KTAB_STRLEN); 23800Sstevel@tonic-gate } 23810Sstevel@tonic-gate return (0); 23820Sstevel@tonic-gate } 2383