4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
28 * Generic keyboard support: streams and administration.
31 #define KEYMAP_SIZE_VARIABLE
33 #include <sys/types.h>
35 #include <sys/stream.h>
36 #include <sys/stropts.h>
37 #include <sys/strsun.h>
39 #include <sys/vuid_event.h>
40 #include <sys/modctl.h>
41 #include <sys/errno.h>
43 #include <sys/cmn_err.h>
46 #include <sys/consdev.h>
47 #include <sys/kbtrans.h>
48 #include <sys/policy.h>
49 #include <sys/sunldi.h>
50 #include <sys/class.h>
52 #include "kbtrans_lower.h"
53 #include "kbtrans_streams.h"
60 #define KB_NR_FUNCKEYS 12
63 * Repeat rates set in static variables so they can be tweeked with
66 static int kbtrans_repeat_rate
;
67 static int kbtrans_repeat_delay
;
69 /* Printing message on q overflow */
70 static int kbtrans_overflow_msg
= 1;
73 * This value corresponds approximately to max 10 fingers
75 static int kbtrans_downs_size
= 15;
80 extern struct mod_ops mod_miscops
;
82 static struct modlmisc modlmisc
= {
83 &mod_miscops
, /* Type of module */
84 "kbtrans (key translation)"
87 static struct modlinkage modlinkage
= {
88 MODREV_1
, (void *)&modlmisc
, NULL
94 return (mod_install(&modlinkage
));
100 return (mod_remove(&modlinkage
));
104 _info(struct modinfo
*modinfop
)
106 return (mod_info(&modlinkage
, modinfop
));
110 * Internal Function Prototypes
112 static char *kbtrans_strsetwithdecimal(char *, uint_t
, uint_t
);
113 static void kbtrans_set_translation_callback(struct kbtrans
*);
114 static void kbtrans_reioctl(void *);
115 static void kbtrans_send_esc_event(char, struct kbtrans
*);
116 static void kbtrans_keypressed(struct kbtrans
*, uchar_t
, Firm_event
*,
118 static void kbtrans_putbuf(char *, queue_t
*);
119 static void kbtrans_cancelrpt(struct kbtrans
*);
120 static void kbtrans_queuepress(struct kbtrans
*, uchar_t
, Firm_event
*);
121 static void kbtrans_putcode(register struct kbtrans
*, uint_t
);
122 static void kbtrans_keyreleased(struct kbtrans
*, uchar_t
);
123 static void kbtrans_queueevent(struct kbtrans
*, Firm_event
*);
124 static void kbtrans_untrans_keypressed_raw(struct kbtrans
*, kbtrans_key_t
);
125 static void kbtrans_untrans_keyreleased_raw(struct kbtrans
*,
127 static void kbtrans_ascii_keypressed(struct kbtrans
*, uint_t
,
128 kbtrans_key_t
, uint_t
);
129 static void kbtrans_ascii_keyreleased(struct kbtrans
*, kbtrans_key_t
);
130 static void kbtrans_ascii_setup_repeat(struct kbtrans
*, uint_t
,
132 static void kbtrans_trans_event_keypressed(struct kbtrans
*, uint_t
,
133 kbtrans_key_t
, uint_t
);
134 static void kbtrans_trans_event_keyreleased(struct kbtrans
*,
136 static void kbtrans_trans_event_setup_repeat(struct kbtrans
*, uint_t
,
138 static void kbtrans_rpt(void *);
139 static void kbtrans_setled(struct kbtrans
*);
140 static void kbtrans_flush(struct kbtrans
*);
141 static enum kbtrans_message_response
kbtrans_ioctl(struct kbtrans
*upper
,
143 static int kbtrans_setkey(struct kbtrans_lower
*, struct kiockey
*,
145 static int kbtrans_getkey(struct kbtrans_lower
*, struct kiockey
*);
146 static int kbtrans_skey(struct kbtrans_lower
*, struct kiockeymap
*,
148 static int kbtrans_gkey(struct kbtrans_lower
*, struct kiockeymap
*);
151 * Keyboard Translation Mode (TR_NONE)
153 * Functions to be called when keyboard translation is turned off
154 * and up/down key codes are reported.
156 struct keyboard_callback untrans_event_callback
= {
157 kbtrans_untrans_keypressed_raw
,
158 kbtrans_untrans_keyreleased_raw
,
167 * Keyboard Translation Mode (TR_ASCII)
169 * Functions to be called when ISO 8859/1 codes are reported
171 struct keyboard_callback ascii_callback
= {
174 kbtrans_ascii_keypressed
,
175 kbtrans_ascii_keyreleased
,
176 kbtrans_ascii_setup_repeat
,
182 * Keyboard Translation Mode (TR_EVENT)
184 * Functions to be called when firm_events are reported.
186 struct keyboard_callback trans_event_callback
= {
189 kbtrans_trans_event_keypressed
,
190 kbtrans_trans_event_keyreleased
,
191 kbtrans_trans_event_setup_repeat
,
197 progressbar_key_abort_thread(struct kbtrans
*upper
)
200 extern void progressbar_key_abort(ldi_ident_t
);
202 if (ldi_ident_from_stream(upper
->kbtrans_streams_readq
, &li
) != 0) {
203 cmn_err(CE_NOTE
, "!ldi_ident_from_stream failed");
205 mutex_enter(&upper
->progressbar_key_abort_lock
);
206 while (upper
->progressbar_key_abort_flag
== 0)
207 cv_wait(&upper
->progressbar_key_abort_cv
,
208 &upper
->progressbar_key_abort_lock
);
209 if (upper
->progressbar_key_abort_flag
== 1) {
210 mutex_exit(&upper
->progressbar_key_abort_lock
);
211 progressbar_key_abort(li
);
213 mutex_exit(&upper
->progressbar_key_abort_lock
);
215 ldi_ident_release(li
);
222 * kbtrans_streams_init:
223 * Initialize the stream, keytables, callbacks, etc.
226 kbtrans_streams_init(
229 struct kbtrans_hardware
*hw
,
230 struct kbtrans_callbacks
*hw_cb
,
231 struct kbtrans
**ret_kbd
,
233 int initial_led_mask
)
235 struct kbtrans
*upper
;
236 struct kbtrans_lower
*lower
;
240 * Default to relatively generic tables.
242 extern signed char kb_compose_map
[];
243 extern struct compose_sequence_t kb_compose_table
[];
244 extern struct fltaccent_sequence_t kb_fltaccent_table
[];
245 extern char keystringtab
[][KTAB_STRLEN
];
246 extern unsigned char kb_numlock_table
[];
248 /* Set these up only once so that they could be changed from adb */
249 if (!kbtrans_repeat_rate
) {
250 kbtrans_repeat_rate
= (hz
+29)/30;
251 kbtrans_repeat_delay
= hz
/2;
260 DPRINTF(PRINT_L1
, PRINT_MASK_OPEN
, (NULL
,
261 "kbtrans_streams_init: Clone open not supported"));
266 /* allocate keyboard state structure */
267 upper
= kmem_zalloc(sizeof (struct kbtrans
), KM_SLEEP
);
271 upper
->kbtrans_polled_buf
[0] = '\0';
272 upper
->kbtrans_polled_pending_chars
= upper
->kbtrans_polled_buf
;
274 upper
->kbtrans_streams_hw
= hw
;
275 upper
->kbtrans_streams_hw_callbacks
= hw_cb
;
276 upper
->kbtrans_streams_readq
= q
;
277 upper
->kbtrans_streams_iocpending
= NULL
;
278 upper
->kbtrans_streams_translatable
= TR_CAN
;
279 upper
->kbtrans_overflow_cnt
= 0;
280 upper
->kbtrans_streams_translate_mode
= TR_ASCII
;
282 /* Set the translation callback based on the translation type */
283 kbtrans_set_translation_callback(upper
);
285 lower
= &upper
->kbtrans_lower
;
288 * Set defaults for relatively generic tables.
290 lower
->kbtrans_compose_map
= kb_compose_map
;
291 lower
->kbtrans_compose_table
= kb_compose_table
;
292 lower
->kbtrans_fltaccent_table
= kb_fltaccent_table
;
293 lower
->kbtrans_numlock_table
= kb_numlock_table
;
294 lower
->kbtrans_keystringtab
= keystringtab
;
296 lower
->kbtrans_upper
= upper
;
297 lower
->kbtrans_compat
= 1;
300 * We have a generic default for the LED state, and let the
301 * hardware-specific driver supply overrides.
303 lower
->kbtrans_led_state
= 0;
304 lower
->kbtrans_led_state
&= ~initial_led_mask
;
305 lower
->kbtrans_led_state
|= initial_leds
;
306 lower
->kbtrans_togglemask
= 0;
308 if (lower
->kbtrans_led_state
& LED_CAPS_LOCK
)
309 lower
->kbtrans_togglemask
|= CAPSMASK
;
310 if (lower
->kbtrans_led_state
& LED_NUM_LOCK
)
311 lower
->kbtrans_togglemask
|= NUMLOCKMASK
;
313 #if defined(SCROLLMASK)
314 if (lower
->kbtrans_led_state
& LED_SCROLL_LOCK
)
315 lower
->kbtrans_togglemask
|= SCROLLMASK
;
318 lower
->kbtrans_shiftmask
= lower
->kbtrans_togglemask
;
320 upper
->kbtrans_streams_vuid_addr
.ascii
= ASCII_FIRST
;
321 upper
->kbtrans_streams_vuid_addr
.top
= TOP_FIRST
;
322 upper
->kbtrans_streams_vuid_addr
.vkey
= VKEY_FIRST
;
324 /* Allocate dynamic memory for downs table */
325 upper
->kbtrans_streams_num_downs_entries
= kbtrans_downs_size
;
326 upper
->kbtrans_streams_downs_bytes
=
327 (uint32_t)(kbtrans_downs_size
* sizeof (Key_event
));
328 upper
->kbtrans_streams_downs
=
329 kmem_zalloc(upper
->kbtrans_streams_downs_bytes
, KM_SLEEP
);
330 upper
->kbtrans_streams_abortable
= B_FALSE
;
332 upper
->kbtrans_streams_flags
= KBTRANS_STREAMS_OPEN
;
334 upper
->progressbar_key_abort_flag
= 0;
335 cv_init(&upper
->progressbar_key_abort_cv
, NULL
, CV_DEFAULT
, NULL
);
336 /* this counts on no keyboards being above ipl 12 */
337 mutex_init(&upper
->progressbar_key_abort_lock
, NULL
, MUTEX_SPIN
,
338 (void *)ipltospl(12));
339 tid
= thread_create(NULL
, 0, progressbar_key_abort_thread
, upper
,
340 0, &p0
, TS_RUN
, minclsyspri
);
341 upper
->progressbar_key_abort_t_did
= tid
->t_did
;
343 DPRINTF(PRINT_L1
, PRINT_MASK_OPEN
, (upper
, "kbtrans_streams_init "
350 * kbtrans_streams_fini:
351 * Free structures and uninitialize the stream
354 kbtrans_streams_fini(struct kbtrans
*upper
)
357 * Since we're about to destroy our private data, turn off
358 * our open flag first, so we don't accept any more input
359 * and try to use that data.
361 upper
->kbtrans_streams_flags
= 0;
363 /* clear all timeouts */
364 if (upper
->kbtrans_streams_bufcallid
) {
365 qunbufcall(upper
->kbtrans_streams_readq
,
366 upper
->kbtrans_streams_bufcallid
);
368 if (upper
->kbtrans_streams_rptid
) {
369 (void) quntimeout(upper
->kbtrans_streams_readq
,
370 upper
->kbtrans_streams_rptid
);
372 kmem_free(upper
->kbtrans_streams_downs
,
373 upper
->kbtrans_streams_downs_bytes
);
375 mutex_enter(&upper
->progressbar_key_abort_lock
);
376 if (upper
->progressbar_key_abort_flag
== 0) {
377 upper
->progressbar_key_abort_flag
= 2;
378 cv_signal(&upper
->progressbar_key_abort_cv
);
379 mutex_exit(&upper
->progressbar_key_abort_lock
);
380 thread_join(upper
->progressbar_key_abort_t_did
);
382 mutex_exit(&upper
->progressbar_key_abort_lock
);
384 cv_destroy(&upper
->progressbar_key_abort_cv
);
385 mutex_destroy(&upper
->progressbar_key_abort_lock
);
387 kmem_free(upper
, sizeof (struct kbtrans
));
389 DPRINTF(PRINT_L1
, PRINT_MASK_CLOSE
, (upper
, "kbtrans_streams_fini "
395 * kbtrans_streams_releaseall :
396 * This function releases all the held keys.
399 kbtrans_streams_releaseall(struct kbtrans
*upper
)
401 register struct key_event
*ke
;
404 DPRINTF(PRINT_L0
, PRINT_MASK_ALL
, (NULL
, "USBKBM RELEASE ALL\n"));
406 /* Scan table of down key stations */
407 for (i
= 0, ke
= upper
->kbtrans_streams_downs
;
408 i
< upper
->kbtrans_streams_num_downs_entries
; i
++, ke
++) {
410 /* Key station not zero */
411 if (ke
->key_station
) {
413 kbtrans_keyreleased(upper
, ke
->key_station
);
414 /* kbtrans_keyreleased resets downs entry */
420 * kbtrans_streams_message:
421 * keyboard module output queue put procedure: handles M_IOCTL
424 * Return KBTRANS_MESSAGE_HANDLED if the message was handled by
425 * kbtrans and KBTRANS_MESSAGE_NOT_HANDLED otherwise. If
426 * KBTRANS_MESSAGE_HANDLED is returned, no further action is required.
427 * If KBTRANS_MESSAGE_NOT_HANDLED is returned, the hardware module
428 * is responsible for any action.
430 enum kbtrans_message_response
431 kbtrans_streams_message(struct kbtrans
*upper
, register mblk_t
*mp
)
433 queue_t
*q
= upper
->kbtrans_streams_readq
;
434 enum kbtrans_message_response ret
;
436 DPRINTF(PRINT_L1
, PRINT_MASK_ALL
, (upper
,
437 "kbtrans_streams_message entering"));
439 * Process M_FLUSH, and some M_IOCTL, messages here; pass
440 * everything else down.
442 switch (mp
->b_datap
->db_type
) {
445 ret
= kbtrans_ioctl(upper
, mp
);
449 if (*mp
->b_rptr
& FLUSHW
)
450 flushq(q
, FLUSHDATA
);
451 if (*mp
->b_rptr
& FLUSHR
)
452 flushq(RD(q
), FLUSHDATA
);
454 * White lie: we say we didn't handle the message,
455 * so that it gets handled by our client.
457 ret
= KBTRANS_MESSAGE_NOT_HANDLED
;
461 ret
= KBTRANS_MESSAGE_NOT_HANDLED
;
465 DPRINTF(PRINT_L1
, PRINT_MASK_ALL
, (upper
,
466 "kbtrans_streams_message exiting\n"));
472 * kbtrans_streams_key:
473 * When a key is pressed or released, the hardware module should
474 * call kbtrans, passing the key number and its new
475 * state. kbtrans is responsible for autorepeat handling;
476 * the hardware module should report only actual press/release
477 * events, suppressing any hardware-generated autorepeat.
481 struct kbtrans
*upper
,
485 struct kbtrans_lower
*lower
;
488 lower
= &upper
->kbtrans_lower
;
489 kp
= lower
->kbtrans_keyboard
;
491 /* trigger switch back to text mode */
492 mutex_enter(&upper
->progressbar_key_abort_lock
);
493 if (upper
->progressbar_key_abort_flag
== 0) {
494 upper
->progressbar_key_abort_flag
= 1;
495 cv_signal(&upper
->progressbar_key_abort_cv
);
497 mutex_exit(&upper
->progressbar_key_abort_lock
);
499 if (upper
->kbtrans_streams_abortable
) {
500 switch (upper
->kbtrans_streams_abort_state
) {
502 if (state
!= KEY_PRESSED
)
505 if (key
== (kbtrans_key_t
)kp
->k_abort1
||
506 key
== (kbtrans_key_t
)kp
->k_abort1a
) {
507 upper
->kbtrans_streams_abort_state
=
508 ABORT_ABORT1_RECEIVED
;
509 upper
->kbtrans_streams_abort1_key
= key
;
512 /* Shift key needs to be sent to upper immediately */
513 if (key
== (kbtrans_key_t
)kp
->k_newabort1
||
514 key
== (kbtrans_key_t
)kp
->k_newabort1a
) {
515 upper
->kbtrans_streams_abort_state
=
516 NEW_ABORT_ABORT1_RECEIVED
;
517 upper
->kbtrans_streams_new_abort1_key
= key
;
520 case ABORT_ABORT1_RECEIVED
:
521 upper
->kbtrans_streams_abort_state
= ABORT_NORMAL
;
522 if (state
== KEY_PRESSED
&&
523 key
== (kbtrans_key_t
)kp
->k_abort2
) {
524 abort_sequence_enter(NULL
);
527 kbtrans_processkey(lower
,
528 upper
->kbtrans_streams_callback
,
529 upper
->kbtrans_streams_abort1_key
,
533 case NEW_ABORT_ABORT1_RECEIVED
:
534 upper
->kbtrans_streams_abort_state
= ABORT_NORMAL
;
535 if (state
== KEY_PRESSED
&&
536 key
== (kbtrans_key_t
)kp
->k_newabort2
) {
537 abort_sequence_enter(NULL
);
538 kbtrans_processkey(lower
,
539 upper
->kbtrans_streams_callback
,
540 upper
->kbtrans_streams_new_abort1_key
,
547 kbtrans_processkey(lower
, upper
->kbtrans_streams_callback
, key
, state
);
551 * kbtrans_streams_set_keyboard:
552 * At any time after calling kbtrans_streams_init, the hardware
553 * module should make this call to report the id of the keyboard
554 * attached. id is the keyboard type, typically KB_SUN4,
558 kbtrans_streams_set_keyboard(
559 struct kbtrans
*upper
,
563 upper
->kbtrans_lower
.kbtrans_keyboard
= k
;
564 upper
->kbtrans_streams_id
= id
;
568 * kbtrans_streams_has_reset:
569 * At any time between kbtrans_streams_init and kbtrans_streams_fini,
570 * the hardware module can call this routine to report that the
571 * keyboard has been reset, e.g. by being unplugged and reattached.
575 kbtrans_streams_has_reset(struct kbtrans
*upper
)
578 * If this routine is implemented it should probably (a)
579 * simulate releases of all pressed keys and (b) call
580 * the hardware module to set the LEDs.
585 * kbtrans_streams_enable:
586 * This is the routine that is called back when the the stream is ready
590 kbtrans_streams_enable(struct kbtrans
*upper
)
593 kbtrans_setled(upper
);
597 * kbtrans_streams_setled():
598 * This is the routine that is called to only update the led state
602 kbtrans_streams_setled(struct kbtrans
*upper
, int led_state
)
604 struct kbtrans_lower
*lower
;
606 lower
= &upper
->kbtrans_lower
;
607 lower
->kbtrans_led_state
= (uchar_t
)led_state
;
609 if (lower
->kbtrans_led_state
& LED_CAPS_LOCK
)
610 lower
->kbtrans_togglemask
|= CAPSMASK
;
611 if (lower
->kbtrans_led_state
& LED_NUM_LOCK
)
612 lower
->kbtrans_togglemask
|= NUMLOCKMASK
;
614 #if defined(SCROLLMASK)
615 if (lower
->kbtrans_led_state
& LED_SCROLL_LOCK
)
616 lower
->kbtrans_togglemask
|= SCROLLMASK
;
619 lower
->kbtrans_shiftmask
= lower
->kbtrans_togglemask
;
624 * kbtrans_streams_set_queue:
625 * Set the overlying queue, to support multiplexors.
628 kbtrans_streams_set_queue(struct kbtrans
*upper
, queue_t
*q
)
631 upper
->kbtrans_streams_readq
= q
;
635 * kbtrans_streams_get_queue:
636 * Return the overlying queue.
639 kbtrans_streams_get_queue(struct kbtrans
*upper
)
641 return (upper
->kbtrans_streams_readq
);
645 * kbtrans_streams_untimeout
646 * Cancell all timeout
649 kbtrans_streams_untimeout(struct kbtrans
*upper
)
651 /* clear all timeouts */
652 if (upper
->kbtrans_streams_bufcallid
) {
653 qunbufcall(upper
->kbtrans_streams_readq
,
654 upper
->kbtrans_streams_bufcallid
);
655 upper
->kbtrans_streams_bufcallid
= 0;
657 if (upper
->kbtrans_streams_rptid
) {
658 (void) quntimeout(upper
->kbtrans_streams_readq
,
659 upper
->kbtrans_streams_rptid
);
660 upper
->kbtrans_streams_rptid
= 0;
666 * This function is set up as call-back function should an ioctl fail
667 * to allocate required resources.
670 kbtrans_reioctl(void *arg
)
672 struct kbtrans
*upper
= (struct kbtrans
*)arg
;
675 upper
->kbtrans_streams_bufcallid
= 0;
677 if ((mp
= upper
->kbtrans_streams_iocpending
) != NULL
) {
678 /* not pending any more */
679 upper
->kbtrans_streams_iocpending
= NULL
;
680 (void) kbtrans_ioctl(upper
, mp
);
686 * process ioctls we recognize and own. Otherwise, pass it down.
688 static enum kbtrans_message_response
689 kbtrans_ioctl(struct kbtrans
*upper
, register mblk_t
*mp
)
691 register struct iocblk
*iocp
;
692 register short new_translate
;
693 register Vuid_addr_probe
*addr_probe
;
694 register short *addr_ptr
;
695 size_t ioctlrespsize
;
697 struct kbtrans_lower
*lower
;
701 static int kiocgetkey
, kiocsetkey
;
703 lower
= &upper
->kbtrans_lower
;
705 iocp
= (struct iocblk
*)mp
->b_rptr
;
707 DPRINTF(PRINT_L0
, PRINT_MASK_ALL
, (upper
,
708 "kbtrans_ioctl: ioc_cmd 0x%x - ", iocp
->ioc_cmd
));
709 switch (iocp
->ioc_cmd
) {
712 DPRINTF(PRINT_L0
, PRINT_MASK_ALL
, (upper
, "VUIDSFORMAT\n"));
714 err
= miocpullup(mp
, sizeof (int));
717 new_translate
= (*(int *)mp
->b_cont
->b_rptr
== VUID_NATIVE
) ?
720 if (new_translate
== upper
->kbtrans_streams_translate_mode
)
722 upper
->kbtrans_streams_translate_mode
= new_translate
;
724 kbtrans_set_translation_callback(upper
);
726 kbtrans_flush(upper
);
730 DPRINTF(PRINT_L0
, PRINT_MASK_ALL
, (upper
, "KIOCTRANS\n"));
731 err
= miocpullup(mp
, sizeof (int));
734 new_translate
= *(int *)mp
->b_cont
->b_rptr
;
735 if (new_translate
== upper
->kbtrans_streams_translate_mode
)
737 upper
->kbtrans_streams_translate_mode
= new_translate
;
738 kbtrans_set_translation_callback(upper
);
740 kbtrans_flush(upper
);
744 DPRINTF(PRINT_L0
, PRINT_MASK_ALL
, (upper
, "KIOCSLED\n"));
746 err
= miocpullup(mp
, sizeof (uchar_t
));
749 lower
->kbtrans_led_state
= *(uchar_t
*)mp
->b_cont
->b_rptr
;
751 kbtrans_setled(upper
);
755 DPRINTF(PRINT_L0
, PRINT_MASK_ALL
, (upper
, "KIOCGLED\n"));
756 if ((datap
= allocb(sizeof (uchar_t
), BPRI_HI
)) == NULL
) {
757 ioctlrespsize
= sizeof (int);
761 *(uchar_t
*)datap
->b_wptr
= lower
->kbtrans_led_state
;
762 datap
->b_wptr
+= sizeof (uchar_t
);
766 iocp
->ioc_count
= sizeof (uchar_t
);
770 DPRINTF(PRINT_L0
, PRINT_MASK_ALL
, (upper
, "VUIDGFORMAT\n"));
771 if ((datap
= allocb(sizeof (int), BPRI_HI
)) == NULL
) {
772 ioctlrespsize
= sizeof (int);
775 *(int *)datap
->b_wptr
=
776 (upper
->kbtrans_streams_translate_mode
== TR_EVENT
||
777 upper
->kbtrans_streams_translate_mode
== TR_UNTRANS_EVENT
) ?
778 VUID_FIRM_EVENT
: VUID_NATIVE
;
779 datap
->b_wptr
+= sizeof (int);
780 if (mp
->b_cont
) /* free msg to prevent memory leak */
783 iocp
->ioc_count
= sizeof (int);
787 DPRINTF(PRINT_L0
, PRINT_MASK_ALL
, (upper
, "KIOCGTRANS\n"));
788 if ((datap
= allocb(sizeof (int), BPRI_HI
)) == NULL
) {
789 ioctlrespsize
= sizeof (int);
792 *(int *)datap
->b_wptr
= upper
->kbtrans_streams_translate_mode
;
793 datap
->b_wptr
+= sizeof (int);
794 if (mp
->b_cont
) /* free msg to prevent memory leak */
797 iocp
->ioc_count
= sizeof (int);
801 DPRINTF(PRINT_L0
, PRINT_MASK_ALL
, (upper
, "VUIDSADDR\n"));
803 err
= miocpullup(mp
, sizeof (Vuid_addr_probe
));
806 addr_probe
= (Vuid_addr_probe
*)mp
->b_cont
->b_rptr
;
807 switch (addr_probe
->base
) {
810 addr_ptr
= &upper
->kbtrans_streams_vuid_addr
.ascii
;
814 addr_ptr
= &upper
->kbtrans_streams_vuid_addr
.top
;
818 addr_ptr
= &upper
->kbtrans_streams_vuid_addr
.vkey
;
825 if ((err
== 0) && (*addr_ptr
!= addr_probe
->data
.next
)) {
826 *addr_ptr
= addr_probe
->data
.next
;
827 kbtrans_flush(upper
);
832 DPRINTF(PRINT_L0
, PRINT_MASK_ALL
, (upper
, "VUIDGADDR\n"));
834 err
= miocpullup(mp
, sizeof (Vuid_addr_probe
));
837 addr_probe
= (Vuid_addr_probe
*)mp
->b_cont
->b_rptr
;
838 switch (addr_probe
->base
) {
841 addr_probe
->data
.current
=
842 upper
->kbtrans_streams_vuid_addr
.ascii
;
846 addr_probe
->data
.current
=
847 upper
->kbtrans_streams_vuid_addr
.top
;
851 addr_probe
->data
.current
=
852 upper
->kbtrans_streams_vuid_addr
.vkey
;
861 DPRINTF(PRINT_L0
, PRINT_MASK_ALL
, (upper
, "KIOCTRANSABLE\n"));
863 err
= miocpullup(mp
, sizeof (int));
867 * called during console setup in kbconfig()
868 * If set to false, means we are a serial keyboard,
869 * and we should pass all data up without modification.
871 translate
= *(int *)mp
->b_cont
->b_rptr
;
872 if (upper
->kbtrans_streams_translatable
!= translate
)
873 upper
->kbtrans_streams_translatable
= translate
;
875 if (translate
!= TR_CAN
)
876 DPRINTF(PRINT_L4
, PRINT_MASK_ALL
, (upper
,
877 "Cannot translate keyboard using tables.\n"));
881 DPRINTF(PRINT_L0
, PRINT_MASK_ALL
, (upper
, "KIOCGTRANSABLE\n"));
882 if ((datap
= allocb(sizeof (int), BPRI_HI
)) == NULL
) {
883 ioctlrespsize
= sizeof (int);
886 *(int *)datap
->b_wptr
= upper
->kbtrans_streams_translatable
;
887 datap
->b_wptr
+= sizeof (int);
888 if (mp
->b_cont
) /* free msg to prevent memory leak */
891 iocp
->ioc_count
= sizeof (int);
895 DPRINTF(PRINT_L0
, PRINT_MASK_ALL
, (upper
, "KIOCSCOMPAT\n"));
897 err
= miocpullup(mp
, sizeof (int));
900 lower
->kbtrans_compat
= *(int *)mp
->b_cont
->b_rptr
;
904 DPRINTF(PRINT_L0
, PRINT_MASK_ALL
, (upper
, "KIOCGCOMPAT\n"));
905 if ((datap
= allocb(sizeof (int), BPRI_HI
)) == NULL
) {
906 ioctlrespsize
= sizeof (int);
909 *(int *)datap
->b_wptr
= lower
->kbtrans_compat
;
910 datap
->b_wptr
+= sizeof (int);
911 if (mp
->b_cont
) /* free msg to prevent memory leak */
914 iocp
->ioc_count
= sizeof (int);
918 DPRINTF(PRINT_L0
, PRINT_MASK_ALL
, (upper
, "KIOCSETKEY %d\n",
920 err
= miocpullup(mp
, sizeof (struct kiockey
));
923 err
= kbtrans_setkey(&upper
->kbtrans_lower
,
924 (struct kiockey
*)mp
->b_cont
->b_rptr
, iocp
->ioc_cr
);
926 * Since this only affects any subsequent key presses,
927 * don't flush soft state. One might want to
928 * toggle the keytable entries dynamically.
933 DPRINTF(PRINT_L0
, PRINT_MASK_ALL
, (upper
, "KIOCGETKEY %d\n",
935 err
= miocpullup(mp
, sizeof (struct kiockey
));
938 err
= kbtrans_getkey(&upper
->kbtrans_lower
,
939 (struct kiockey
*)mp
->b_cont
->b_rptr
);
943 err
= miocpullup(mp
, sizeof (struct kiockeymap
));
946 err
= kbtrans_skey(&upper
->kbtrans_lower
,
947 (struct kiockeymap
*)mp
->b_cont
->b_rptr
, iocp
->ioc_cr
);
949 * Since this only affects any subsequent key presses,
950 * don't flush soft state. One might want to
951 * toggle the keytable entries dynamically.
956 err
= miocpullup(mp
, sizeof (struct kiockeymap
));
959 err
= kbtrans_gkey(&upper
->kbtrans_lower
,
960 (struct kiockeymap
*)mp
->b_cont
->b_rptr
);
964 DPRINTF(PRINT_L0
, PRINT_MASK_ALL
, (upper
, "KIOCSDIRECT\n"));
965 kbtrans_flush(upper
);
969 DPRINTF(PRINT_L0
, PRINT_MASK_ALL
, (upper
, "KIOCSGDIRECT\n"));
970 if ((datap
= allocb(sizeof (int), BPRI_HI
)) == NULL
) {
971 ioctlrespsize
= sizeof (int);
974 *(int *)datap
->b_wptr
= 1; /* always direct */
975 datap
->b_wptr
+= sizeof (int);
976 if (mp
->b_cont
) /* free msg to prevent memory leak */
979 iocp
->ioc_count
= sizeof (int);
983 DPRINTF(PRINT_L0
, PRINT_MASK_ALL
, (upper
, "KIOCTYPE\n"));
984 if ((datap
= allocb(sizeof (int), BPRI_HI
)) == NULL
) {
985 ioctlrespsize
= sizeof (int);
988 *(int *)datap
->b_wptr
= upper
->kbtrans_streams_id
;
989 datap
->b_wptr
+= sizeof (int);
990 if (mp
->b_cont
) /* free msg to prevent memory leak */
993 iocp
->ioc_count
= sizeof (int);
996 case CONSSETABORTENABLE
:
998 * Peek as it goes by; must be a TRANSPARENT ioctl.
1000 if (iocp
->ioc_count
!= TRANSPARENT
) {
1005 upper
->kbtrans_streams_abortable
=
1006 (boolean_t
)*(intptr_t *)mp
->b_cont
->b_rptr
;
1009 * Let the hardware module see it too.
1011 return (KBTRANS_MESSAGE_NOT_HANDLED
);
1015 * Report the autorepeat delay, unit in millisecond
1017 DPRINTF(PRINT_L0
, PRINT_MASK_ALL
, (upper
, "KIOCGRPTDELAY\n"));
1018 if ((datap
= allocb(sizeof (int), BPRI_HI
)) == NULL
) {
1019 ioctlrespsize
= sizeof (int);
1022 *(int *)datap
->b_wptr
= TICK_TO_MSEC(kbtrans_repeat_delay
);
1023 datap
->b_wptr
+= sizeof (int);
1025 /* free msg to prevent memory leak */
1026 if (mp
->b_cont
!= NULL
)
1027 freemsg(mp
->b_cont
);
1029 iocp
->ioc_count
= sizeof (int);
1034 * Set the autorepeat delay
1036 DPRINTF(PRINT_L0
, PRINT_MASK_ALL
, (upper
, "KIOCSRPTDELAY\n"));
1037 err
= miocpullup(mp
, sizeof (int));
1042 /* validate the input */
1043 if (*(int *)mp
->b_cont
->b_rptr
< KIOCRPTDELAY_MIN
) {
1047 kbtrans_repeat_delay
= MSEC_TO_TICK(*(int *)mp
->b_cont
->b_rptr
);
1048 if (kbtrans_repeat_delay
<= 0)
1049 kbtrans_repeat_delay
= 1;
1054 * Report the autorepeat rate
1056 DPRINTF(PRINT_L0
, PRINT_MASK_ALL
, (upper
, "KIOCGRPTRATE\n"));
1057 if ((datap
= allocb(sizeof (int), BPRI_HI
)) == NULL
) {
1058 ioctlrespsize
= sizeof (int);
1061 *(int *)datap
->b_wptr
= TICK_TO_MSEC(kbtrans_repeat_rate
);
1062 datap
->b_wptr
+= sizeof (int);
1064 /* free msg to prevent memory leak */
1065 if (mp
->b_cont
!= NULL
)
1066 freemsg(mp
->b_cont
);
1068 iocp
->ioc_count
= sizeof (int);
1073 * Set the autorepeat rate
1075 DPRINTF(PRINT_L0
, PRINT_MASK_ALL
, (upper
, "KIOCSRPTRATE\n"));
1076 err
= miocpullup(mp
, sizeof (int));
1081 /* validate the input */
1082 if (*(int *)mp
->b_cont
->b_rptr
< KIOCRPTRATE_MIN
) {
1086 kbtrans_repeat_rate
= MSEC_TO_TICK(*(int *)mp
->b_cont
->b_rptr
);
1087 if (kbtrans_repeat_rate
<= 0)
1088 kbtrans_repeat_rate
= 1;
1092 DPRINTF(PRINT_L0
, PRINT_MASK_ALL
, (upper
, "unknown\n"));
1093 return (KBTRANS_MESSAGE_NOT_HANDLED
);
1098 iocp
->ioc_error
= err
;
1099 mp
->b_datap
->db_type
= M_IOCNAK
;
1102 iocp
->ioc_error
= 0; /* brain rot */
1103 mp
->b_datap
->db_type
= M_IOCACK
;
1105 putnext(upper
->kbtrans_streams_readq
, mp
);
1107 return (KBTRANS_MESSAGE_HANDLED
);
1111 * We needed to allocate something to handle this "ioctl", but
1112 * couldn't; save this "ioctl" and arrange to get called back when
1113 * it's more likely that we can get what we need.
1114 * If there's already one being saved, throw it out, since it
1115 * must have timed out.
1117 if (upper
->kbtrans_streams_iocpending
!= NULL
)
1118 freemsg(upper
->kbtrans_streams_iocpending
);
1119 upper
->kbtrans_streams_iocpending
= mp
;
1120 if (upper
->kbtrans_streams_bufcallid
) {
1121 qunbufcall(upper
->kbtrans_streams_readq
,
1122 upper
->kbtrans_streams_bufcallid
);
1124 upper
->kbtrans_streams_bufcallid
=
1125 qbufcall(upper
->kbtrans_streams_readq
, ioctlrespsize
, BPRI_HI
,
1126 kbtrans_reioctl
, upper
);
1128 * This is a white lie... we *will* handle it, eventually.
1130 return (KBTRANS_MESSAGE_HANDLED
);
1135 * Flush data upstream
1138 kbtrans_flush(register struct kbtrans
*upper
)
1140 register queue_t
*q
;
1142 /* Flush pending data already sent upstream */
1143 if ((q
= upper
->kbtrans_streams_readq
) != NULL
&& q
->q_next
!= NULL
)
1144 (void) putnextctl1(q
, M_FLUSH
, FLUSHR
);
1146 /* Flush pending ups */
1147 bzero(upper
->kbtrans_streams_downs
, upper
->kbtrans_streams_downs_bytes
);
1149 kbtrans_cancelrpt(upper
);
1154 * Update the keyboard LEDs to match the current keyboard state.
1157 kbtrans_setled(struct kbtrans
*upper
)
1159 upper
->kbtrans_streams_hw_callbacks
->kbtrans_streams_setled(
1160 upper
->kbtrans_streams_hw
,
1161 upper
->kbtrans_lower
.kbtrans_led_state
);
1166 * If a key is held down, this function is set up to be called
1167 * after kbtrans_repeat_rate time elapses.
1170 kbtrans_rpt(void *arg
)
1172 struct kbtrans
*upper
= arg
;
1173 struct kbtrans_lower
*lower
= &upper
->kbtrans_lower
;
1175 DPRINTF(PRINT_L0
, PRINT_MASK_ALL
, (NULL
,
1176 "kbtrans_rpt: repeat key %X\n",
1177 lower
->kbtrans_repeatkey
));
1179 upper
->kbtrans_streams_rptid
= 0;
1182 * NB: polled code zaps kbtrans_repeatkey without cancelling
1185 if (lower
->kbtrans_repeatkey
!= 0) {
1186 kbtrans_keyreleased(upper
, lower
->kbtrans_repeatkey
);
1188 kbtrans_processkey(lower
,
1189 upper
->kbtrans_streams_callback
,
1190 lower
->kbtrans_repeatkey
,
1193 upper
->kbtrans_streams_rptid
=
1194 qtimeout(upper
->kbtrans_streams_readq
, kbtrans_rpt
,
1195 (caddr_t
)upper
, kbtrans_repeat_rate
);
1200 * kbtrans_cancelrpt:
1201 * Cancel the repeating key
1204 kbtrans_cancelrpt(struct kbtrans
*upper
)
1206 upper
->kbtrans_lower
.kbtrans_repeatkey
= 0;
1208 if (upper
->kbtrans_streams_rptid
!= 0) {
1209 (void) quntimeout(upper
->kbtrans_streams_readq
,
1210 upper
->kbtrans_streams_rptid
);
1211 upper
->kbtrans_streams_rptid
= 0;
1216 * kbtrans_send_esc_event:
1217 * Send character up stream. Used for the case of
1218 * sending strings upstream.
1221 kbtrans_send_esc_event(char c
, register struct kbtrans
*upper
)
1227 fe
.pair_type
= FE_PAIR_NONE
;
1230 * Pretend as if each cp pushed and released
1231 * Calling kbtrans_queueevent avoids addr translation
1232 * and pair base determination of kbtrans_keypressed.
1234 kbtrans_queueevent(upper
, &fe
);
1236 kbtrans_queueevent(upper
, &fe
);
1240 * kbtrans_strsetwithdecimal:
1241 * Used for expanding a function key to the ascii equivalent
1244 kbtrans_strsetwithdecimal(char *buf
, uint_t val
, uint_t maxdigs
)
1249 char *tab
= "0123456789abcdef";
1256 *(--bp
) = tab
[val
% hradix
* 2 + lowbit
];
1263 * kbtrans_keypressed:
1264 * Modify Firm event to be sent up the stream
1267 kbtrans_keypressed(struct kbtrans
*upper
, uchar_t key_station
,
1268 Firm_event
*fe
, ushort_t base
)
1271 register short id_addr
;
1272 struct kbtrans_lower
*lower
= &upper
->kbtrans_lower
;
1274 /* Set pair values */
1275 if (fe
->id
< (ushort_t
)VKEY_FIRST
) {
1277 * If CTRLed, find the ID that would have been used had it
1280 if (lower
->kbtrans_shiftmask
& (CTRLMASK
| CTLSMASK
)) {
1284 mask
= lower
->kbtrans_shiftmask
&
1285 ~(CTRLMASK
| CTLSMASK
| UPMASK
);
1287 ke
= kbtrans_find_entry(lower
, mask
, key_station
);
1293 if (base
!= fe
->id
) {
1294 fe
->pair_type
= FE_PAIR_SET
;
1295 fe
->pair
= (uchar_t
)base
;
1300 fe
->pair_type
= FE_PAIR_NONE
;
1304 /* Adjust event id address for multiple keyboard/workstation support */
1305 switch (vuid_id_addr(fe
->id
)) {
1307 id_addr
= upper
->kbtrans_streams_vuid_addr
.ascii
;
1310 id_addr
= upper
->kbtrans_streams_vuid_addr
.top
;
1313 id_addr
= upper
->kbtrans_streams_vuid_addr
.vkey
;
1316 id_addr
= vuid_id_addr(fe
->id
);
1319 fe
->id
= vuid_id_offset(fe
->id
) | id_addr
;
1321 kbtrans_queuepress(upper
, key_station
, fe
);
1325 * kbtrans_queuepress:
1326 * Add keypress to the "downs" table
1329 kbtrans_queuepress(struct kbtrans
*upper
,
1330 uchar_t key_station
, Firm_event
*fe
)
1332 register struct key_event
*ke
, *ke_free
;
1335 DPRINTF(PRINT_L0
, PRINT_MASK_ALL
, (NULL
, "kbtrans_queuepress:"
1336 " key=%d", key_station
));
1340 /* Scan table of down key stations */
1342 for (i
= 0, ke
= upper
->kbtrans_streams_downs
;
1343 i
< upper
->kbtrans_streams_num_downs_entries
; i
++, ke
++) {
1345 /* Keycode already down? */
1346 if (ke
->key_station
== key_station
) {
1348 DPRINTF(PRINT_L0
, PRINT_MASK_ALL
,
1349 (NULL
, "kbtrans: Double "
1350 "entry in downs table (%d,%d)!\n",
1356 if (ke
->key_station
== 0)
1365 ke
= upper
->kbtrans_streams_downs
;
1368 ke
->key_station
= key_station
;
1370 kbtrans_queueevent(upper
, fe
);
1374 * kbtrans_keyreleased:
1375 * Remove entry from the downs table
1378 kbtrans_keyreleased(register struct kbtrans
*upper
, uchar_t key_station
)
1380 register struct key_event
*ke
;
1383 DPRINTF(PRINT_L0
, PRINT_MASK_ALL
, (NULL
, "RELEASE key=%d\n",
1386 if (upper
->kbtrans_streams_translate_mode
!= TR_EVENT
&&
1387 upper
->kbtrans_streams_translate_mode
!= TR_UNTRANS_EVENT
) {
1392 /* Scan table of down key stations */
1393 for (i
= 0, ke
= upper
->kbtrans_streams_downs
;
1394 i
< upper
->kbtrans_streams_num_downs_entries
;
1397 if (ke
->key_station
== key_station
) {
1398 ke
->key_station
= 0;
1399 ke
->event
.value
= 0;
1400 kbtrans_queueevent(upper
, &ke
->event
);
1405 * Ignore if couldn't find because may be called twice
1406 * for the same key station in the case of the kbtrans_rpt
1407 * routine being called unnecessarily.
1414 * Pass a keycode up the stream, if you can, otherwise throw it away.
1417 kbtrans_putcode(register struct kbtrans
*upper
, uint_t code
)
1419 register mblk_t
*bp
;
1422 * If we can't send it up, then we just drop it.
1424 if (!canputnext(upper
->kbtrans_streams_readq
)) {
1430 * Allocate a messsage block to send up.
1432 if ((bp
= allocb(sizeof (uint_t
), BPRI_HI
)) == NULL
) {
1434 cmn_err(CE_WARN
, "kbtrans_putcode: Can't allocate block\
1441 * We will strip out any high order information here.
1444 code
= KEYCHAR(code
);
1446 *bp
->b_wptr
++ = (char)code
;
1447 } else if (code
< 0x800) {
1448 *bp
->b_wptr
++ = 0xc0 | (code
>> 6);
1449 *bp
->b_wptr
++ = 0x80 | (code
& 0x3f);
1450 } else if (code
< 0x10000) {
1451 *bp
->b_wptr
++ = 0xe0 | (code
>> 12);
1452 *bp
->b_wptr
++ = 0x80 | ((code
>> 6) & 0x3f);
1453 *bp
->b_wptr
++ = 0x80 | (code
& 0x3f);
1455 *bp
->b_wptr
++ = 0xf0 | (code
>> 18);
1456 *bp
->b_wptr
++ = 0x80 | ((code
>> 12) & 0x3f);
1457 *bp
->b_wptr
++ = 0x80 | ((code
>> 6) & 0x3f);
1458 *bp
->b_wptr
++ = 0x80 | (code
& 0x3f);
1462 * Send the message up.
1464 (void) putnext(upper
->kbtrans_streams_readq
, bp
);
1470 * Pass generated keycode sequence to upstream, if possible.
1473 kbtrans_putbuf(char *buf
, queue_t
*q
)
1475 register mblk_t
*bp
;
1477 if (!canputnext(q
)) {
1478 cmn_err(CE_WARN
, "kbtrans_putbuf: Can't put block for keycode");
1480 if ((bp
= allocb((int)strlen(buf
), BPRI_HI
)) == NULL
) {
1481 cmn_err(CE_WARN
, "kbtrans_putbuf: "
1482 "Can't allocate block for keycode");
1485 *bp
->b_wptr
++ = *buf
;
1494 * kbtrans_queueevent:
1495 * Pass a VUID "firm event" up the stream, if you can.
1498 kbtrans_queueevent(struct kbtrans
*upper
, Firm_event
*fe
)
1500 register queue_t
*q
;
1501 register mblk_t
*bp
;
1503 if ((q
= upper
->kbtrans_streams_readq
) == NULL
)
1507 if (!canputnext(q
)) {
1508 if (kbtrans_overflow_msg
) {
1509 DPRINTF(PRINT_L2
, PRINT_MASK_ALL
, (NULL
,
1510 "kbtrans: Buffer flushed when overflowed."));
1513 kbtrans_flush(upper
);
1514 upper
->kbtrans_overflow_cnt
++;
1516 if ((bp
= allocb(sizeof (Firm_event
), BPRI_HI
)) == NULL
) {
1517 cmn_err(CE_WARN
, "kbtrans_queueevent: Can't allocate \
1520 uniqtime32(&fe
->time
);
1521 *(Firm_event
*)bp
->b_wptr
= *fe
;
1522 bp
->b_wptr
+= sizeof (Firm_event
);
1523 (void) putnext(q
, bp
);
1531 * kbtrans_set_translation_callback:
1532 * This code sets the translation_callback pointer based on the
1536 kbtrans_set_translation_callback(register struct kbtrans
*upper
)
1538 switch (upper
->kbtrans_streams_translate_mode
) {
1542 upper
->vt_switch_keystate
= VT_SWITCH_KEY_NONE
;
1544 /* Discard any obsolete CTRL/ALT/SHIFT keys */
1545 upper
->kbtrans_lower
.kbtrans_shiftmask
&=
1546 ~(CTRLMASK
| ALTMASK
| SHIFTMASK
);
1547 upper
->kbtrans_lower
.kbtrans_togglemask
&=
1548 ~(CTRLMASK
| ALTMASK
| SHIFTMASK
);
1550 upper
->kbtrans_streams_callback
= &ascii_callback
;
1555 upper
->kbtrans_streams_callback
= &trans_event_callback
;
1559 case TR_UNTRANS_EVENT
:
1560 upper
->kbtrans_streams_callback
= &untrans_event_callback
;
1567 * kbtrans_untrans_keypressed_raw:
1568 * This is the callback we get if we are in TR_UNTRANS_EVENT and a
1569 * key is pressed. This code will just send the scancode up the
1573 kbtrans_untrans_keypressed_raw(struct kbtrans
*upper
, kbtrans_key_t key
)
1577 bzero(&fe
, sizeof (fe
));
1582 fe
.id
= (unsigned short)key
;
1586 * Send the event upstream.
1588 kbtrans_queuepress(upper
, key
, &fe
);
1592 * kbtrans_untrans_keyreleased_raw:
1593 * This is the callback we get if we are in TR_UNTRANS_EVENT mode
1594 * and a key is released. This code will just send the scancode up
1598 kbtrans_untrans_keyreleased_raw(struct kbtrans
*upper
, kbtrans_key_t key
)
1601 * Deal with a key released event.
1603 kbtrans_keyreleased(upper
, key
);
1607 * kbtrans_vt_compose:
1608 * To compose the key sequences for virtual terminal switching.
1610 * 'ALTL + F#' for 1-12 terminals
1611 * 'ALTGR + F#' for 13-24 terminals
1612 * 'ALT + UPARROW' for last terminal
1613 * 'ALT + LEFTARROW' for previous terminal
1614 * 'ALT + RIGHTARROW' for next terminal
1616 * the vt switching message is encoded as:
1618 * -------------------------------------------------------------
1619 * | \033 | 'Q' | vtno + 'A' | opcode | 'z' | '\0' |
1620 * -------------------------------------------------------------
1623 * 'B' to switch to previous terminal
1624 * 'F' to switch to next terminal
1625 * 'L' to switch to last terminal
1626 * 'H' to switch to the terminal as specified by vtno,
1627 * which is from 1 to 24.
1629 * Here keyid is the keycode of UPARROW, LEFTARROW, or RIGHTARROW
1630 * when it is a kind of arrow key as indicated by is_arrow_key,
1631 * otherwise it indicates a function key and keyid is the number
1632 * corresponding to that function key.
1635 kbtrans_vt_compose(struct kbtrans
*upper
, unsigned short keyid
,
1636 boolean_t is_arrow_key
, char *buf
)
1641 *bufp
++ = '\033'; /* Escape */
1646 case UPARROW
: /* last vt */
1649 case LEFTARROW
: /* previous vt */
1652 case RIGHTARROW
: /* next vt */
1659 /* this is funckey specifying vtno for switch */
1661 (upper
->vt_switch_keystate
- VT_SWITCH_KEY_ALT
) *
1662 KB_NR_FUNCKEYS
+ 'A';
1669 * Send the result upstream.
1671 kbtrans_putbuf(buf
, upper
->kbtrans_streams_readq
);
1676 * kbtrans_ascii_keypressed:
1677 * This is the code if we are in TR_ASCII mode and a key
1678 * is pressed. This is where we will do any special processing that
1679 * is specific to ASCII key translation.
1683 kbtrans_ascii_keypressed(
1684 struct kbtrans
*upper
,
1690 register char *bufp
;
1692 unsigned short keyid
;
1693 struct kbtrans_lower
*lower
= &upper
->kbtrans_lower
;
1696 * Based on the type of key, we may need to do some ASCII
1697 * specific post processing. Note that the translated entry
1698 * is constructed as the actual keycode plus entrytype. see
1699 * sys/kbd.h for details of each entrytype.
1701 switch (entrytype
) {
1707 keyid
= entry
& 0xFF;
1709 upper
->vt_switch_keystate
= VT_SWITCH_KEY_ALT
;
1710 } else if (keyid
== ALTGRAPH
) {
1711 upper
->vt_switch_keystate
= VT_SWITCH_KEY_ALTGR
;
1717 * There is no ascii equivalent. We will ignore these
1723 if (upper
->vt_switch_keystate
> VT_SWITCH_KEY_NONE
) {
1724 if (entry
>= TOPFUNC
&&
1725 entry
< (TOPFUNC
+ KB_NR_FUNCKEYS
)) {
1728 * keyid is the number correspoding to F#
1729 * and its value is from 1 to 12.
1731 keyid
= (entry
& 0xF) + 1;
1733 kbtrans_vt_compose(upper
, keyid
, B_FALSE
, buf
);
1739 * We need to expand this key to get the ascii
1740 * equivalent. These are the function keys (F1, F2 ...)
1743 cp
= kbtrans_strsetwithdecimal(bufp
+ 2,
1744 (uint_t
)((entry
& 0x003F) + 192),
1746 *bufp
++ = '\033'; /* Escape */
1754 * Send the result upstream.
1756 kbtrans_putbuf(buf
, upper
->kbtrans_streams_readq
);
1761 if (upper
->vt_switch_keystate
> VT_SWITCH_KEY_NONE
) {
1762 keyid
= entry
& 0xFF;
1763 if (keyid
== UPARROW
||
1764 keyid
== RIGHTARROW
||
1765 keyid
== LEFTARROW
) {
1767 kbtrans_vt_compose(upper
, keyid
, B_TRUE
, buf
);
1773 * These are the multi byte keys (Home, Up, Down ...)
1775 cp
= &lower
->kbtrans_keystringtab
[entry
& 0x0F][0];
1778 * Copy the string from the keystringtable, and send it
1779 * upstream a character at a time.
1781 while (*cp
!= '\0') {
1783 kbtrans_putcode(upper
, (uchar_t
)*cp
);
1792 * These are the keys on the keypad. Look up the
1793 * answer in the kb_numlock_table and send it upstream.
1795 kbtrans_putcode(upper
,
1796 lower
->kbtrans_numlock_table
[entry
&0x1F]);
1800 case 0: /* normal character */
1806 * Send the char upstream.
1808 kbtrans_putcode(upper
, entry
);
1812 #define KB_SCANCODE_ALT 0xe2
1813 #define KB_SCANCODE_ALTGRAPH 0xe6
1816 * kbtrans_ascii_keyreleased:
1817 * This is the function if we are in TR_ASCII mode and a key
1818 * is released. ASCII doesn't have the concept of released keys,
1819 * or make/break codes. So there is nothing for us to do except
1820 * checking 'Alt/AltGraph' release key in order to reset the state
1821 * of vt switch key sequence.
1825 kbtrans_ascii_keyreleased(struct kbtrans
*upper
, kbtrans_key_t key
)
1827 if (key
== KB_SCANCODE_ALT
|| key
== KB_SCANCODE_ALTGRAPH
) {
1828 upper
->vt_switch_keystate
= VT_SWITCH_KEY_NONE
;
1833 * kbtrans_ascii_setup_repeat:
1834 * This is the function if we are in TR_ASCII mode and the
1835 * translation module has decided that a key needs to be repeated.
1839 kbtrans_ascii_setup_repeat(
1840 struct kbtrans
*upper
,
1844 struct kbtrans_lower
*lower
= &upper
->kbtrans_lower
;
1847 * Cancel any currently repeating keys. This will be a new
1850 kbtrans_cancelrpt(upper
);
1853 * Set the value of the key to be repeated.
1855 lower
->kbtrans_repeatkey
= key
;
1858 * Start the timeout for repeating this key. kbtrans_rpt will
1859 * be called to repeat the key.
1861 upper
->kbtrans_streams_rptid
= qtimeout(upper
->kbtrans_streams_readq
,
1862 kbtrans_rpt
, (caddr_t
)upper
, kbtrans_repeat_delay
);
1866 * kbtrans_trans_event_keypressed:
1867 * This is the function if we are in TR_EVENT mode and a key
1868 * is pressed. This is where we will do any special processing that
1869 * is specific to EVENT key translation.
1872 kbtrans_trans_event_keypressed(
1873 struct kbtrans
*upper
,
1880 struct kbtrans_lower
*lower
= &upper
->kbtrans_lower
;
1883 * Based on the type of key, we may need to do some EVENT
1884 * specific post processing.
1886 switch (entrytype
) {
1890 * Relying on ordinal correspondence between
1891 * vuid_event.h SHIFT_META-SHIFT_TOP &
1892 * kbd.h METABIT-SYSTEMBIT in order to
1893 * correctly translate entry into fe.id.
1895 fe
.id
= SHIFT_CAPSLOCK
+ (entry
& 0x0F);
1897 kbtrans_keypressed(upper
, key
, &fe
, fe
.id
);
1903 * Relying on ordinal correspondence between
1904 * vuid_event.h SHIFT_CAPSLOCK-SHIFT_RIGHTCTRL &
1905 * kbd.h CAPSLOCK-RIGHTCTRL in order to
1906 * correctly translate entry into fe.id.
1908 fe
.id
= SHIFT_META
+ (entry
& 0x0F);
1910 kbtrans_keypressed(upper
, key
, &fe
, fe
.id
);
1916 * Take advantage of the similar
1917 * ordering of kbd.h function keys and
1918 * vuid_event.h function keys to do a
1919 * simple translation to achieve a
1920 * mapping between the 2 different
1923 fe
.id
= KEY_LEFTFIRST
+ (entry
& 0x003F);
1927 * Assume "up" table only generates
1930 kbtrans_keypressed(upper
, key
, &fe
, fe
.id
);
1933 * Function key events can be expanded
1934 * by terminal emulator software to
1935 * produce the standard escape sequence
1936 * generated by the TR_ASCII case above
1937 * if a function key event is not used
1938 * by terminal emulator software
1945 * These are the multi byte keys (Home, Up, Down ...)
1947 cp
= &lower
->kbtrans_keystringtab
[entry
& 0x0F][0];
1950 * Copy the string from the keystringtable, and send it
1951 * upstream a character at a time.
1953 while (*cp
!= '\0') {
1955 kbtrans_send_esc_event(*cp
, upper
);
1964 * Take advantage of the similar
1965 * ordering of kbd.h keypad keys and
1966 * vuid_event.h keypad keys to do a
1967 * simple translation to achieve a
1968 * mapping between the 2 different
1971 fe
.id
= VKEY_FIRSTPAD
+ (entry
& 0x001F);
1975 * Assume "up" table only generates
1978 kbtrans_keypressed(upper
, key
, &fe
, fe
.id
);
1981 * Keypad key events can be expanded
1982 * by terminal emulator software to
1983 * produce the standard ascii character
1984 * generated by the TR_ASCII case above
1985 * if a keypad key event is not used
1986 * by terminal emulator software
1993 * These are not events.
2000 * Something has happened. Mark all keys as released.
2002 kbtrans_streams_releaseall(upper
);
2008 case 0: /* normal character */
2014 * Send the event upstream.
2020 kbtrans_queueevent(upper
, &fe
);
2024 * kbtrans_trans_event_keyreleased:
2025 * This is the function if we are in TR_EVENT mode and a key
2030 kbtrans_trans_event_keyreleased(struct kbtrans
*upper
, kbtrans_key_t key
)
2033 * Mark the key as released and send an event upstream.
2035 kbtrans_keyreleased(upper
, key
);
2039 * kbtrans_trans_event_setup_repeat:
2040 * This is the function if we are in TR_EVENT mode and the
2041 * translation module has decided that a key needs to be repeated.
2042 * We will set a timeout to retranslate the repeat key.
2045 kbtrans_trans_event_setup_repeat(
2046 struct kbtrans
*upper
,
2050 struct kbtrans_lower
*lower
= &upper
->kbtrans_lower
;
2053 * Function keys and keypad keys do not repeat when we are in
2056 if (entrytype
== FUNCKEYS
|| entrytype
== PADKEYS
) {
2062 * Cancel any currently repeating keys. This will be a new
2065 kbtrans_cancelrpt(upper
);
2068 * Set the value of the key to be repeated.
2070 lower
->kbtrans_repeatkey
= key
;
2073 * Start the timeout for repeating this key. kbtrans_rpt will
2074 * be called to repeat the key.
2076 upper
->kbtrans_streams_rptid
= qtimeout(upper
->kbtrans_streams_readq
,
2077 kbtrans_rpt
, (caddr_t
)upper
, kbtrans_repeat_delay
);
2081 * Administer the key tables.
2085 * Old special codes.
2087 #define OLD_SHIFTKEYS 0x80
2088 #define OLD_BUCKYBITS 0x90
2089 #define OLD_FUNNY 0xA0
2090 #define OLD_FA_UMLAUT 0xA9
2091 #define OLD_FA_CFLEX 0xAA
2092 #define OLD_FA_TILDE 0xAB
2093 #define OLD_FA_CEDILLA 0xAC
2094 #define OLD_FA_ACUTE 0xAD
2095 #define OLD_FA_GRAVE 0xAE
2096 #define OLD_ISOCHAR 0xAF
2097 #define OLD_STRING 0xB0
2098 #define OLD_LEFTFUNC 0xC0
2099 #define OLD_RIGHTFUNC 0xD0
2100 #define OLD_TOPFUNC 0xE0
2101 #define OLD_BOTTOMFUNC 0xF0
2104 * Map old special codes to new ones.
2105 * Indexed by ((old special code) >> 4) & 0x07; add (old special code) & 0x0F.
2107 static keymap_entry_t special_old_to_new
[] = {
2121 * Set individual keystation translation from old-style entry.
2124 kbtrans_setkey(struct kbtrans_lower
*lower
, struct kiockey
*key
, cred_t
*cr
)
2128 register int tablemask
;
2129 register keymap_entry_t entry
;
2130 register struct keyboard
*kp
;
2132 kp
= lower
->kbtrans_keyboard
;
2134 if (key
->kio_station
>= kp
->k_keymap_size
)
2137 if (lower
->kbtrans_keyboard
== NULL
)
2141 tablemask
= key
->kio_tablemask
;
2143 switch (tablemask
) {
2147 i
= secpolicy_console(cr
);
2151 switch (tablemask
) {
2153 kp
->k_abort1
= key
->kio_station
;
2156 kp
->k_abort1a
= key
->kio_station
;
2159 kp
->k_abort2
= key
->kio_station
;
2165 if (tablemask
& ALTGRAPHMASK
)
2168 ke
= kbtrans_find_entry(lower
, (uint_t
)tablemask
, key
->kio_station
);
2172 if (key
->kio_entry
>= (uchar_t
)OLD_STRING
&&
2173 key
->kio_entry
<= (uchar_t
)(OLD_STRING
+ 15)) {
2174 strtabindex
= key
->kio_entry
- OLD_STRING
;
2175 bcopy(key
->kio_string
,
2176 lower
->kbtrans_keystringtab
[strtabindex
], KTAB_STRLEN
);
2177 lower
->kbtrans_keystringtab
[strtabindex
][KTAB_STRLEN
-1] = '\0';
2180 entry
= key
->kio_entry
;
2183 * There's nothing we need do with OLD_ISOCHAR.
2185 if (entry
!= OLD_ISOCHAR
) {
2187 if (entry
>= OLD_FA_UMLAUT
&& entry
<= OLD_FA_GRAVE
)
2188 entry
= FA_CLASS
+ (entry
& 0x0F) - 9;
2191 special_old_to_new
[entry
>> 4 & 0x07]
2203 * Map new special codes to old ones.
2204 * Indexed by (new special code) >> 8; add (new special code) & 0xFF.
2206 static uchar_t special_new_to_old
[] = {
2208 OLD_SHIFTKEYS
, /* SHIFTKEYS */
2209 OLD_BUCKYBITS
, /* BUCKYBITS */
2210 OLD_FUNNY
, /* FUNNY */
2211 OLD_FA_UMLAUT
, /* FA_CLASS */
2212 OLD_STRING
, /* STRING */
2213 OLD_LEFTFUNC
, /* FUNCKEYS */
2219 * Get individual keystation translation as old-style entry.
2222 kbtrans_getkey(struct kbtrans_lower
*lower
, struct kiockey
*key
)
2226 register keymap_entry_t entry
;
2227 struct keyboard
*kp
;
2229 kp
= lower
->kbtrans_keyboard
;
2231 if (key
->kio_station
>= kp
->k_keymap_size
)
2234 if (lower
->kbtrans_keyboard
== NULL
)
2237 switch (key
->kio_tablemask
) {
2239 key
->kio_station
= kp
->k_abort1
;
2242 key
->kio_station
= kp
->k_abort1a
;
2245 key
->kio_station
= kp
->k_abort2
;
2249 ke
= kbtrans_find_entry(lower
, (uint_t
)key
->kio_tablemask
,
2258 special_new_to_old
[(ushort_t
)(entry
& 0xFF00) >> 8]
2262 key
->kio_entry
= (ushort_t
)OLD_ISOCHAR
; /* you lose */
2264 key
->kio_entry
= (ushort_t
)entry
;
2267 if (entry
>= STRING
&& entry
<= (uchar_t
)(STRING
+ 15)) {
2268 strtabindex
= entry
- STRING
;
2269 bcopy(lower
->kbtrans_keystringtab
[strtabindex
],
2270 key
->kio_string
, KTAB_STRLEN
);
2278 * Set individual keystation translation from new-style entry.
2281 kbtrans_skey(struct kbtrans_lower
*lower
, struct kiockeymap
*key
, cred_t
*cr
)
2285 struct keyboard
*kp
;
2287 kp
= lower
->kbtrans_keyboard
;
2289 if (key
->kio_station
>= kp
->k_keymap_size
) {
2294 if (lower
->kbtrans_keyboard
== NULL
) {
2298 switch (key
->kio_tablemask
) {
2302 i
= secpolicy_console(cr
);
2305 switch (key
->kio_tablemask
) {
2307 kp
->k_abort1
= key
->kio_station
;
2310 kp
->k_abort1a
= key
->kio_station
;
2313 kp
->k_abort2
= key
->kio_station
;
2319 ke
= kbtrans_find_entry(lower
, (uint_t
)key
->kio_tablemask
,
2324 if (key
->kio_entry
>= STRING
&&
2325 key
->kio_entry
<= (STRING
+ 15)) {
2326 strtabindex
= key
->kio_entry
-STRING
;
2327 bcopy(key
->kio_string
,
2328 lower
->kbtrans_keystringtab
[strtabindex
], KTAB_STRLEN
);
2329 lower
->kbtrans_keystringtab
[strtabindex
][KTAB_STRLEN
-1] = '\0';
2332 *ke
= key
->kio_entry
;
2340 * Get individual keystation translation as new-style entry.
2343 kbtrans_gkey(struct kbtrans_lower
*lower
, struct kiockeymap
*key
)
2347 struct keyboard
*kp
;
2349 kp
= lower
->kbtrans_keyboard
;
2351 if (key
->kio_station
>= kp
->k_keymap_size
)
2354 if (lower
->kbtrans_keyboard
== NULL
)
2357 switch (key
->kio_tablemask
) {
2359 key
->kio_station
= kp
->k_abort1
;
2362 key
->kio_station
= kp
->k_abort1a
;
2365 key
->kio_station
= kp
->k_abort2
;
2369 ke
= kbtrans_find_entry(lower
, (uint_t
)key
->kio_tablemask
,
2374 key
->kio_entry
= *ke
;
2376 if (key
->kio_entry
>= STRING
&&
2377 key
->kio_entry
<= (STRING
+ 15)) {
2378 strtabindex
= key
->kio_entry
-STRING
;
2379 bcopy(lower
->kbtrans_keystringtab
[strtabindex
],
2380 key
->kio_string
, KTAB_STRLEN
);