Print this page
7127 remove -Wno-missing-braces from Makefile.uts
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/common/io/kbtrans/kbtrans_streams.c
+++ new/usr/src/uts/common/io/kbtrans/kbtrans_streams.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21
22 22 /*
23 23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 24 * Use is subject to license terms.
25 25 */
26 26
27 27 /*
28 28 * Generic keyboard support: streams and administration.
29 29 */
30 30
31 31 #define KEYMAP_SIZE_VARIABLE
32 32
33 33 #include <sys/types.h>
34 34 #include <sys/cred.h>
35 35 #include <sys/stream.h>
36 36 #include <sys/stropts.h>
37 37 #include <sys/strsun.h>
38 38 #include <sys/ddi.h>
39 39 #include <sys/vuid_event.h>
40 40 #include <sys/modctl.h>
41 41 #include <sys/errno.h>
42 42 #include <sys/kmem.h>
43 43 #include <sys/cmn_err.h>
44 44 #include <sys/kbd.h>
45 45 #include <sys/kbio.h>
46 46 #include <sys/consdev.h>
47 47 #include <sys/kbtrans.h>
48 48 #include <sys/policy.h>
49 49 #include <sys/sunldi.h>
50 50 #include <sys/class.h>
51 51 #include <sys/spl.h>
52 52 #include "kbtrans_lower.h"
53 53 #include "kbtrans_streams.h"
54 54
55 55 #ifdef DEBUG
56 56 int kbtrans_errmask;
57 57 int kbtrans_errlevel;
58 58 #endif
59 59
60 60 #define KB_NR_FUNCKEYS 12
61 61
62 62 /*
63 63 * Repeat rates set in static variables so they can be tweeked with
64 64 * debugger.
65 65 */
66 66 static int kbtrans_repeat_rate;
67 67 static int kbtrans_repeat_delay;
68 68
69 69 /* Printing message on q overflow */
70 70 static int kbtrans_overflow_msg = 1;
71 71
72 72 /*
73 73 * This value corresponds approximately to max 10 fingers
74 74 */
75 75 static int kbtrans_downs_size = 15;
76 76
77 77 /*
↓ open down ↓ |
77 lines elided |
↑ open up ↑ |
78 78 * modload support
79 79 */
80 80 extern struct mod_ops mod_miscops;
81 81
82 82 static struct modlmisc modlmisc = {
83 83 &mod_miscops, /* Type of module */
84 84 "kbtrans (key translation)"
85 85 };
86 86
87 87 static struct modlinkage modlinkage = {
88 - MODREV_1, (void *)&modlmisc, NULL
88 + MODREV_1, { (void *)&modlmisc, NULL }
89 89 };
90 90
91 91 int
92 92 _init(void)
93 93 {
94 94 return (mod_install(&modlinkage));
95 95 }
96 96
97 97 int
98 98 _fini(void)
99 99 {
100 100 return (mod_remove(&modlinkage));
101 101 }
102 102
103 103 int
104 104 _info(struct modinfo *modinfop)
105 105 {
106 106 return (mod_info(&modlinkage, modinfop));
107 107 }
108 108
109 109 /*
110 110 * Internal Function Prototypes
111 111 */
112 112 static char *kbtrans_strsetwithdecimal(char *, uint_t, uint_t);
113 113 static void kbtrans_set_translation_callback(struct kbtrans *);
114 114 static void kbtrans_reioctl(void *);
115 115 static void kbtrans_send_esc_event(char, struct kbtrans *);
116 116 static void kbtrans_keypressed(struct kbtrans *, uchar_t, Firm_event *,
117 117 ushort_t);
118 118 static void kbtrans_putbuf(char *, queue_t *);
119 119 static void kbtrans_cancelrpt(struct kbtrans *);
120 120 static void kbtrans_queuepress(struct kbtrans *, uchar_t, Firm_event *);
121 121 static void kbtrans_putcode(register struct kbtrans *, uint_t);
122 122 static void kbtrans_keyreleased(struct kbtrans *, uchar_t);
123 123 static void kbtrans_queueevent(struct kbtrans *, Firm_event *);
124 124 static void kbtrans_untrans_keypressed_raw(struct kbtrans *, kbtrans_key_t);
125 125 static void kbtrans_untrans_keyreleased_raw(struct kbtrans *,
126 126 kbtrans_key_t);
127 127 static void kbtrans_ascii_keypressed(struct kbtrans *, uint_t,
128 128 kbtrans_key_t, uint_t);
129 129 static void kbtrans_ascii_keyreleased(struct kbtrans *, kbtrans_key_t);
130 130 static void kbtrans_ascii_setup_repeat(struct kbtrans *, uint_t,
131 131 kbtrans_key_t);
132 132 static void kbtrans_trans_event_keypressed(struct kbtrans *, uint_t,
133 133 kbtrans_key_t, uint_t);
134 134 static void kbtrans_trans_event_keyreleased(struct kbtrans *,
135 135 kbtrans_key_t);
136 136 static void kbtrans_trans_event_setup_repeat(struct kbtrans *, uint_t,
137 137 kbtrans_key_t);
138 138 static void kbtrans_rpt(void *);
139 139 static void kbtrans_setled(struct kbtrans *);
140 140 static void kbtrans_flush(struct kbtrans *);
141 141 static enum kbtrans_message_response kbtrans_ioctl(struct kbtrans *upper,
142 142 mblk_t *mp);
143 143 static int kbtrans_setkey(struct kbtrans_lower *, struct kiockey *,
144 144 cred_t *);
145 145 static int kbtrans_getkey(struct kbtrans_lower *, struct kiockey *);
146 146 static int kbtrans_skey(struct kbtrans_lower *, struct kiockeymap *,
147 147 cred_t *cr);
148 148 static int kbtrans_gkey(struct kbtrans_lower *, struct kiockeymap *);
149 149
150 150 /*
151 151 * Keyboard Translation Mode (TR_NONE)
152 152 *
153 153 * Functions to be called when keyboard translation is turned off
154 154 * and up/down key codes are reported.
155 155 */
156 156 struct keyboard_callback untrans_event_callback = {
157 157 kbtrans_untrans_keypressed_raw,
158 158 kbtrans_untrans_keyreleased_raw,
159 159 NULL,
160 160 NULL,
161 161 NULL,
162 162 NULL,
163 163 NULL,
164 164 };
165 165
166 166 /*
167 167 * Keyboard Translation Mode (TR_ASCII)
168 168 *
169 169 * Functions to be called when ISO 8859/1 codes are reported
170 170 */
171 171 struct keyboard_callback ascii_callback = {
172 172 NULL,
173 173 NULL,
174 174 kbtrans_ascii_keypressed,
175 175 kbtrans_ascii_keyreleased,
176 176 kbtrans_ascii_setup_repeat,
177 177 kbtrans_cancelrpt,
178 178 kbtrans_setled,
179 179 };
180 180
181 181 /*
182 182 * Keyboard Translation Mode (TR_EVENT)
183 183 *
184 184 * Functions to be called when firm_events are reported.
185 185 */
186 186 struct keyboard_callback trans_event_callback = {
187 187 NULL,
188 188 NULL,
189 189 kbtrans_trans_event_keypressed,
190 190 kbtrans_trans_event_keyreleased,
191 191 kbtrans_trans_event_setup_repeat,
192 192 kbtrans_cancelrpt,
193 193 kbtrans_setled,
194 194 };
195 195
196 196 static void
197 197 progressbar_key_abort_thread(struct kbtrans *upper)
198 198 {
199 199 ldi_ident_t li;
200 200 extern void progressbar_key_abort(ldi_ident_t);
201 201
202 202 if (ldi_ident_from_stream(upper->kbtrans_streams_readq, &li) != 0) {
203 203 cmn_err(CE_NOTE, "!ldi_ident_from_stream failed");
204 204 } else {
205 205 mutex_enter(&upper->progressbar_key_abort_lock);
206 206 while (upper->progressbar_key_abort_flag == 0)
207 207 cv_wait(&upper->progressbar_key_abort_cv,
208 208 &upper->progressbar_key_abort_lock);
209 209 if (upper->progressbar_key_abort_flag == 1) {
210 210 mutex_exit(&upper->progressbar_key_abort_lock);
211 211 progressbar_key_abort(li);
212 212 } else {
213 213 mutex_exit(&upper->progressbar_key_abort_lock);
214 214 }
215 215 ldi_ident_release(li);
216 216 }
217 217
218 218 thread_exit();
219 219 }
220 220
221 221 /*
222 222 * kbtrans_streams_init:
223 223 * Initialize the stream, keytables, callbacks, etc.
224 224 */
225 225 int
226 226 kbtrans_streams_init(
227 227 queue_t *q,
228 228 int sflag,
229 229 struct kbtrans_hardware *hw,
230 230 struct kbtrans_callbacks *hw_cb,
231 231 struct kbtrans **ret_kbd,
232 232 int initial_leds,
233 233 int initial_led_mask)
234 234 {
235 235 struct kbtrans *upper;
236 236 struct kbtrans_lower *lower;
237 237 kthread_t *tid;
238 238
239 239 /*
240 240 * Default to relatively generic tables.
241 241 */
242 242 extern signed char kb_compose_map[];
243 243 extern struct compose_sequence_t kb_compose_table[];
244 244 extern struct fltaccent_sequence_t kb_fltaccent_table[];
245 245 extern char keystringtab[][KTAB_STRLEN];
246 246 extern unsigned char kb_numlock_table[];
247 247
248 248 /* Set these up only once so that they could be changed from adb */
249 249 if (!kbtrans_repeat_rate) {
250 250 kbtrans_repeat_rate = (hz+29)/30;
251 251 kbtrans_repeat_delay = hz/2;
252 252 }
253 253
254 254 switch (sflag) {
255 255
256 256 case MODOPEN:
257 257 break;
258 258
259 259 case CLONEOPEN:
260 260 DPRINTF(PRINT_L1, PRINT_MASK_OPEN, (NULL,
261 261 "kbtrans_streams_init: Clone open not supported"));
262 262
263 263 return (EINVAL);
264 264 }
265 265
266 266 /* allocate keyboard state structure */
267 267 upper = kmem_zalloc(sizeof (struct kbtrans), KM_SLEEP);
268 268
269 269 *ret_kbd = upper;
270 270
271 271 upper->kbtrans_polled_buf[0] = '\0';
272 272 upper->kbtrans_polled_pending_chars = upper->kbtrans_polled_buf;
273 273
274 274 upper->kbtrans_streams_hw = hw;
275 275 upper->kbtrans_streams_hw_callbacks = hw_cb;
276 276 upper->kbtrans_streams_readq = q;
277 277 upper->kbtrans_streams_iocpending = NULL;
278 278 upper->kbtrans_streams_translatable = TR_CAN;
279 279 upper->kbtrans_overflow_cnt = 0;
280 280 upper->kbtrans_streams_translate_mode = TR_ASCII;
281 281
282 282 /* Set the translation callback based on the translation type */
283 283 kbtrans_set_translation_callback(upper);
284 284
285 285 lower = &upper->kbtrans_lower;
286 286
287 287 /*
288 288 * Set defaults for relatively generic tables.
289 289 */
290 290 lower->kbtrans_compose_map = kb_compose_map;
291 291 lower->kbtrans_compose_table = kb_compose_table;
292 292 lower->kbtrans_fltaccent_table = kb_fltaccent_table;
293 293 lower->kbtrans_numlock_table = kb_numlock_table;
294 294 lower->kbtrans_keystringtab = keystringtab;
295 295
296 296 lower->kbtrans_upper = upper;
297 297 lower->kbtrans_compat = 1;
298 298
299 299 /*
300 300 * We have a generic default for the LED state, and let the
301 301 * hardware-specific driver supply overrides.
302 302 */
303 303 lower->kbtrans_led_state = 0;
304 304 lower->kbtrans_led_state &= ~initial_led_mask;
305 305 lower->kbtrans_led_state |= initial_leds;
306 306 lower->kbtrans_togglemask = 0;
307 307
308 308 if (lower->kbtrans_led_state & LED_CAPS_LOCK)
309 309 lower->kbtrans_togglemask |= CAPSMASK;
310 310 if (lower->kbtrans_led_state & LED_NUM_LOCK)
311 311 lower->kbtrans_togglemask |= NUMLOCKMASK;
312 312
313 313 #if defined(SCROLLMASK)
314 314 if (lower->kbtrans_led_state & LED_SCROLL_LOCK)
315 315 lower->kbtrans_togglemask |= SCROLLMASK;
316 316 #endif
317 317
318 318 lower->kbtrans_shiftmask = lower->kbtrans_togglemask;
319 319
320 320 upper->kbtrans_streams_vuid_addr.ascii = ASCII_FIRST;
321 321 upper->kbtrans_streams_vuid_addr.top = TOP_FIRST;
322 322 upper->kbtrans_streams_vuid_addr.vkey = VKEY_FIRST;
323 323
324 324 /* Allocate dynamic memory for downs table */
325 325 upper->kbtrans_streams_num_downs_entries = kbtrans_downs_size;
326 326 upper->kbtrans_streams_downs_bytes =
327 327 (uint32_t)(kbtrans_downs_size * sizeof (Key_event));
328 328 upper->kbtrans_streams_downs =
329 329 kmem_zalloc(upper->kbtrans_streams_downs_bytes, KM_SLEEP);
330 330 upper->kbtrans_streams_abortable = B_FALSE;
331 331
332 332 upper->kbtrans_streams_flags = KBTRANS_STREAMS_OPEN;
333 333
334 334 upper->progressbar_key_abort_flag = 0;
335 335 cv_init(&upper->progressbar_key_abort_cv, NULL, CV_DEFAULT, NULL);
336 336 /* this counts on no keyboards being above ipl 12 */
337 337 mutex_init(&upper->progressbar_key_abort_lock, NULL, MUTEX_SPIN,
338 338 (void *)ipltospl(12));
339 339 tid = thread_create(NULL, 0, progressbar_key_abort_thread, upper,
340 340 0, &p0, TS_RUN, minclsyspri);
341 341 upper->progressbar_key_abort_t_did = tid->t_did;
342 342
343 343 DPRINTF(PRINT_L1, PRINT_MASK_OPEN, (upper, "kbtrans_streams_init "
344 344 "exiting"));
345 345 return (0);
346 346 }
347 347
348 348
349 349 /*
350 350 * kbtrans_streams_fini:
351 351 * Free structures and uninitialize the stream
352 352 */
353 353 int
354 354 kbtrans_streams_fini(struct kbtrans *upper)
355 355 {
356 356 /*
357 357 * Since we're about to destroy our private data, turn off
358 358 * our open flag first, so we don't accept any more input
359 359 * and try to use that data.
360 360 */
361 361 upper->kbtrans_streams_flags = 0;
362 362
363 363 /* clear all timeouts */
364 364 if (upper->kbtrans_streams_bufcallid) {
365 365 qunbufcall(upper->kbtrans_streams_readq,
366 366 upper->kbtrans_streams_bufcallid);
367 367 }
368 368 if (upper->kbtrans_streams_rptid) {
369 369 (void) quntimeout(upper->kbtrans_streams_readq,
370 370 upper->kbtrans_streams_rptid);
371 371 }
372 372 kmem_free(upper->kbtrans_streams_downs,
373 373 upper->kbtrans_streams_downs_bytes);
374 374
375 375 mutex_enter(&upper->progressbar_key_abort_lock);
376 376 if (upper->progressbar_key_abort_flag == 0) {
377 377 upper->progressbar_key_abort_flag = 2;
378 378 cv_signal(&upper->progressbar_key_abort_cv);
379 379 mutex_exit(&upper->progressbar_key_abort_lock);
380 380 thread_join(upper->progressbar_key_abort_t_did);
381 381 } else {
382 382 mutex_exit(&upper->progressbar_key_abort_lock);
383 383 }
384 384 cv_destroy(&upper->progressbar_key_abort_cv);
385 385 mutex_destroy(&upper->progressbar_key_abort_lock);
386 386
387 387 kmem_free(upper, sizeof (struct kbtrans));
388 388
389 389 DPRINTF(PRINT_L1, PRINT_MASK_CLOSE, (upper, "kbtrans_streams_fini "
390 390 "exiting"));
391 391 return (0);
392 392 }
393 393
394 394 /*
395 395 * kbtrans_streams_releaseall :
396 396 * This function releases all the held keys.
397 397 */
398 398 void
399 399 kbtrans_streams_releaseall(struct kbtrans *upper)
400 400 {
401 401 register struct key_event *ke;
402 402 register int i;
403 403
404 404 DPRINTF(PRINT_L0, PRINT_MASK_ALL, (NULL, "USBKBM RELEASE ALL\n"));
405 405
406 406 /* Scan table of down key stations */
407 407 for (i = 0, ke = upper->kbtrans_streams_downs;
408 408 i < upper->kbtrans_streams_num_downs_entries; i++, ke++) {
409 409
410 410 /* Key station not zero */
411 411 if (ke->key_station) {
412 412
413 413 kbtrans_keyreleased(upper, ke->key_station);
414 414 /* kbtrans_keyreleased resets downs entry */
415 415 }
416 416 }
417 417 }
418 418
419 419 /*
420 420 * kbtrans_streams_message:
421 421 * keyboard module output queue put procedure: handles M_IOCTL
422 422 * messages.
423 423 *
424 424 * Return KBTRANS_MESSAGE_HANDLED if the message was handled by
425 425 * kbtrans and KBTRANS_MESSAGE_NOT_HANDLED otherwise. If
426 426 * KBTRANS_MESSAGE_HANDLED is returned, no further action is required.
427 427 * If KBTRANS_MESSAGE_NOT_HANDLED is returned, the hardware module
428 428 * is responsible for any action.
429 429 */
430 430 enum kbtrans_message_response
431 431 kbtrans_streams_message(struct kbtrans *upper, register mblk_t *mp)
432 432 {
433 433 queue_t *q = upper->kbtrans_streams_readq;
434 434 enum kbtrans_message_response ret;
435 435
436 436 DPRINTF(PRINT_L1, PRINT_MASK_ALL, (upper,
437 437 "kbtrans_streams_message entering"));
438 438 /*
439 439 * Process M_FLUSH, and some M_IOCTL, messages here; pass
440 440 * everything else down.
441 441 */
442 442 switch (mp->b_datap->db_type) {
443 443
444 444 case M_IOCTL:
445 445 ret = kbtrans_ioctl(upper, mp);
446 446 break;
447 447
448 448 case M_FLUSH:
449 449 if (*mp->b_rptr & FLUSHW)
450 450 flushq(q, FLUSHDATA);
451 451 if (*mp->b_rptr & FLUSHR)
452 452 flushq(RD(q), FLUSHDATA);
453 453 /*
454 454 * White lie: we say we didn't handle the message,
455 455 * so that it gets handled by our client.
456 456 */
457 457 ret = KBTRANS_MESSAGE_NOT_HANDLED;
458 458 break;
459 459
460 460 default:
461 461 ret = KBTRANS_MESSAGE_NOT_HANDLED;
462 462 break;
463 463
464 464 }
465 465 DPRINTF(PRINT_L1, PRINT_MASK_ALL, (upper,
466 466 "kbtrans_streams_message exiting\n"));
467 467
468 468 return (ret);
469 469 }
470 470
471 471 /*
472 472 * kbtrans_streams_key:
473 473 * When a key is pressed or released, the hardware module should
474 474 * call kbtrans, passing the key number and its new
475 475 * state. kbtrans is responsible for autorepeat handling;
476 476 * the hardware module should report only actual press/release
477 477 * events, suppressing any hardware-generated autorepeat.
478 478 */
479 479 void
480 480 kbtrans_streams_key(
481 481 struct kbtrans *upper,
482 482 kbtrans_key_t key,
483 483 enum keystate state)
484 484 {
485 485 struct kbtrans_lower *lower;
486 486 struct keyboard *kp;
487 487
488 488 lower = &upper->kbtrans_lower;
489 489 kp = lower->kbtrans_keyboard;
490 490
491 491 /* trigger switch back to text mode */
492 492 mutex_enter(&upper->progressbar_key_abort_lock);
493 493 if (upper->progressbar_key_abort_flag == 0) {
494 494 upper->progressbar_key_abort_flag = 1;
495 495 cv_signal(&upper->progressbar_key_abort_cv);
496 496 }
497 497 mutex_exit(&upper->progressbar_key_abort_lock);
498 498
499 499 if (upper->kbtrans_streams_abortable) {
500 500 switch (upper->kbtrans_streams_abort_state) {
501 501 case ABORT_NORMAL:
502 502 if (state != KEY_PRESSED)
503 503 break;
504 504
505 505 if (key == (kbtrans_key_t)kp->k_abort1 ||
506 506 key == (kbtrans_key_t)kp->k_abort1a) {
507 507 upper->kbtrans_streams_abort_state =
508 508 ABORT_ABORT1_RECEIVED;
509 509 upper->kbtrans_streams_abort1_key = key;
510 510 return;
511 511 }
512 512 /* Shift key needs to be sent to upper immediately */
513 513 if (key == (kbtrans_key_t)kp->k_newabort1 ||
514 514 key == (kbtrans_key_t)kp->k_newabort1a) {
515 515 upper->kbtrans_streams_abort_state =
516 516 NEW_ABORT_ABORT1_RECEIVED;
517 517 upper->kbtrans_streams_new_abort1_key = key;
518 518 }
519 519 break;
520 520 case ABORT_ABORT1_RECEIVED:
521 521 upper->kbtrans_streams_abort_state = ABORT_NORMAL;
522 522 if (state == KEY_PRESSED &&
523 523 key == (kbtrans_key_t)kp->k_abort2) {
524 524 abort_sequence_enter((char *)NULL);
525 525 return;
526 526 } else {
527 527 kbtrans_processkey(lower,
528 528 upper->kbtrans_streams_callback,
529 529 upper->kbtrans_streams_abort1_key,
530 530 KEY_PRESSED);
531 531 }
532 532 break;
533 533 case NEW_ABORT_ABORT1_RECEIVED:
534 534 upper->kbtrans_streams_abort_state = ABORT_NORMAL;
535 535 if (state == KEY_PRESSED &&
536 536 key == (kbtrans_key_t)kp->k_newabort2) {
537 537 abort_sequence_enter((char *)NULL);
538 538 kbtrans_processkey(lower,
539 539 upper->kbtrans_streams_callback,
540 540 upper->kbtrans_streams_new_abort1_key,
541 541 KEY_RELEASED);
542 542 return;
543 543 }
544 544 }
545 545 }
546 546
547 547 kbtrans_processkey(lower, upper->kbtrans_streams_callback, key, state);
548 548 }
549 549
550 550 /*
551 551 * kbtrans_streams_set_keyboard:
552 552 * At any time after calling kbtrans_streams_init, the hardware
553 553 * module should make this call to report the id of the keyboard
554 554 * attached. id is the keyboard type, typically KB_SUN4,
555 555 * KB_PC, or KB_USB.
556 556 */
557 557 void
558 558 kbtrans_streams_set_keyboard(
559 559 struct kbtrans *upper,
560 560 int id,
561 561 struct keyboard *k)
562 562 {
563 563 upper->kbtrans_lower.kbtrans_keyboard = k;
564 564 upper->kbtrans_streams_id = id;
565 565 }
566 566
567 567 /*
568 568 * kbtrans_streams_has_reset:
569 569 * At any time between kbtrans_streams_init and kbtrans_streams_fini,
570 570 * the hardware module can call this routine to report that the
571 571 * keyboard has been reset, e.g. by being unplugged and reattached.
572 572 */
573 573 /*ARGSUSED*/
574 574 void
575 575 kbtrans_streams_has_reset(struct kbtrans *upper)
576 576 {
577 577 /*
578 578 * If this routine is implemented it should probably (a)
579 579 * simulate releases of all pressed keys and (b) call
580 580 * the hardware module to set the LEDs.
581 581 */
582 582 }
583 583
584 584 /*
585 585 * kbtrans_streams_enable:
586 586 * This is the routine that is called back when the the stream is ready
587 587 * to take messages.
588 588 */
589 589 void
590 590 kbtrans_streams_enable(struct kbtrans *upper)
591 591 {
592 592 /* Set the LED's */
593 593 kbtrans_setled(upper);
594 594 }
595 595
596 596 /*
597 597 * kbtrans_streams_setled():
598 598 * This is the routine that is called to only update the led state
599 599 * in kbtrans.
600 600 */
601 601 void
602 602 kbtrans_streams_setled(struct kbtrans *upper, int led_state)
603 603 {
604 604 struct kbtrans_lower *lower;
605 605
606 606 lower = &upper->kbtrans_lower;
607 607 lower->kbtrans_led_state = (uchar_t)led_state;
608 608
609 609 if (lower->kbtrans_led_state & LED_CAPS_LOCK)
610 610 lower->kbtrans_togglemask |= CAPSMASK;
611 611 if (lower->kbtrans_led_state & LED_NUM_LOCK)
612 612 lower->kbtrans_togglemask |= NUMLOCKMASK;
613 613
614 614 #if defined(SCROLLMASK)
615 615 if (lower->kbtrans_led_state & LED_SCROLL_LOCK)
616 616 lower->kbtrans_togglemask |= SCROLLMASK;
617 617 #endif
618 618
619 619 lower->kbtrans_shiftmask = lower->kbtrans_togglemask;
620 620
621 621 }
622 622
623 623 /*
624 624 * kbtrans_streams_set_queue:
625 625 * Set the overlying queue, to support multiplexors.
626 626 */
627 627 void
628 628 kbtrans_streams_set_queue(struct kbtrans *upper, queue_t *q)
629 629 {
630 630
631 631 upper->kbtrans_streams_readq = q;
632 632 }
633 633
634 634 /*
635 635 * kbtrans_streams_get_queue:
636 636 * Return the overlying queue.
637 637 */
638 638 queue_t *
639 639 kbtrans_streams_get_queue(struct kbtrans *upper)
640 640 {
641 641 return (upper->kbtrans_streams_readq);
642 642 }
643 643
644 644 /*
645 645 * kbtrans_streams_untimeout
646 646 * Cancell all timeout
647 647 */
648 648 void
649 649 kbtrans_streams_untimeout(struct kbtrans *upper)
650 650 {
651 651 /* clear all timeouts */
652 652 if (upper->kbtrans_streams_bufcallid) {
653 653 qunbufcall(upper->kbtrans_streams_readq,
654 654 upper->kbtrans_streams_bufcallid);
655 655 upper->kbtrans_streams_bufcallid = 0;
656 656 }
657 657 if (upper->kbtrans_streams_rptid) {
658 658 (void) quntimeout(upper->kbtrans_streams_readq,
659 659 upper->kbtrans_streams_rptid);
660 660 upper->kbtrans_streams_rptid = 0;
661 661 }
662 662 }
663 663
664 664 /*
665 665 * kbtrans_reioctl:
666 666 * This function is set up as call-back function should an ioctl fail
667 667 * to allocate required resources.
668 668 */
669 669 static void
670 670 kbtrans_reioctl(void *arg)
671 671 {
672 672 struct kbtrans *upper = (struct kbtrans *)arg;
673 673 mblk_t *mp;
674 674
675 675 upper->kbtrans_streams_bufcallid = 0;
676 676
677 677 if ((mp = upper->kbtrans_streams_iocpending) != NULL) {
678 678 /* not pending any more */
679 679 upper->kbtrans_streams_iocpending = NULL;
680 680 (void) kbtrans_ioctl(upper, mp);
681 681 }
682 682 }
683 683
684 684 /*
685 685 * kbtrans_ioctl:
686 686 * process ioctls we recognize and own. Otherwise, pass it down.
687 687 */
688 688 static enum kbtrans_message_response
689 689 kbtrans_ioctl(struct kbtrans *upper, register mblk_t *mp)
690 690 {
691 691 register struct iocblk *iocp;
692 692 register short new_translate;
693 693 register Vuid_addr_probe *addr_probe;
694 694 register short *addr_ptr;
695 695 size_t ioctlrespsize;
696 696 int err = 0;
697 697 struct kbtrans_lower *lower;
698 698 mblk_t *datap;
699 699 int translate;
700 700
701 701 static int kiocgetkey, kiocsetkey;
702 702
703 703 lower = &upper->kbtrans_lower;
704 704
705 705 iocp = (struct iocblk *)mp->b_rptr;
706 706
707 707 DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper,
708 708 "kbtrans_ioctl: ioc_cmd 0x%x - ", iocp->ioc_cmd));
709 709 switch (iocp->ioc_cmd) {
710 710
711 711 case VUIDSFORMAT:
712 712 DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "VUIDSFORMAT\n"));
713 713
714 714 err = miocpullup(mp, sizeof (int));
715 715 if (err != 0)
716 716 break;
717 717 new_translate = (*(int *)mp->b_cont->b_rptr == VUID_NATIVE) ?
718 718 TR_ASCII : TR_EVENT;
719 719
720 720 if (new_translate == upper->kbtrans_streams_translate_mode)
721 721 break;
722 722 upper->kbtrans_streams_translate_mode = new_translate;
723 723
724 724 kbtrans_set_translation_callback(upper);
725 725
726 726 kbtrans_flush(upper);
727 727 break;
728 728
729 729 case KIOCTRANS:
730 730 DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "KIOCTRANS\n"));
731 731 err = miocpullup(mp, sizeof (int));
732 732 if (err != 0)
733 733 break;
734 734 new_translate = *(int *)mp->b_cont->b_rptr;
735 735 if (new_translate == upper->kbtrans_streams_translate_mode)
736 736 break;
737 737 upper->kbtrans_streams_translate_mode = new_translate;
738 738 kbtrans_set_translation_callback(upper);
739 739
740 740 kbtrans_flush(upper);
741 741 break;
742 742
743 743 case KIOCSLED:
744 744 DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "KIOCSLED\n"));
745 745
746 746 err = miocpullup(mp, sizeof (uchar_t));
747 747 if (err != 0)
748 748 break;
749 749 lower->kbtrans_led_state = *(uchar_t *)mp->b_cont->b_rptr;
750 750
751 751 kbtrans_setled(upper);
752 752 break;
753 753
754 754 case KIOCGLED:
755 755 DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "KIOCGLED\n"));
756 756 if ((datap = allocb(sizeof (uchar_t), BPRI_HI)) == NULL) {
757 757 ioctlrespsize = sizeof (int);
758 758 goto allocfailure;
759 759 }
760 760
761 761 *(uchar_t *)datap->b_wptr = lower->kbtrans_led_state;
762 762 datap->b_wptr += sizeof (uchar_t);
763 763 if (mp->b_cont)
764 764 freemsg(mp->b_cont);
765 765 mp->b_cont = datap;
766 766 iocp->ioc_count = sizeof (uchar_t);
767 767 break;
768 768
769 769 case VUIDGFORMAT:
770 770 DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "VUIDGFORMAT\n"));
771 771 if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) {
772 772 ioctlrespsize = sizeof (int);
773 773 goto allocfailure;
774 774 }
775 775 *(int *)datap->b_wptr =
776 776 (upper->kbtrans_streams_translate_mode == TR_EVENT ||
777 777 upper->kbtrans_streams_translate_mode == TR_UNTRANS_EVENT) ?
778 778 VUID_FIRM_EVENT: VUID_NATIVE;
779 779 datap->b_wptr += sizeof (int);
780 780 if (mp->b_cont) /* free msg to prevent memory leak */
781 781 freemsg(mp->b_cont);
782 782 mp->b_cont = datap;
783 783 iocp->ioc_count = sizeof (int);
784 784 break;
785 785
786 786 case KIOCGTRANS:
787 787 DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "KIOCGTRANS\n"));
788 788 if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) {
789 789 ioctlrespsize = sizeof (int);
790 790 goto allocfailure;
791 791 }
792 792 *(int *)datap->b_wptr = upper->kbtrans_streams_translate_mode;
793 793 datap->b_wptr += sizeof (int);
794 794 if (mp->b_cont) /* free msg to prevent memory leak */
795 795 freemsg(mp->b_cont);
796 796 mp->b_cont = datap;
797 797 iocp->ioc_count = sizeof (int);
798 798 break;
799 799
800 800 case VUIDSADDR:
801 801 DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "VUIDSADDR\n"));
802 802
803 803 err = miocpullup(mp, sizeof (Vuid_addr_probe));
804 804 if (err != 0)
805 805 break;
806 806 addr_probe = (Vuid_addr_probe *)mp->b_cont->b_rptr;
807 807 switch (addr_probe->base) {
808 808
809 809 case ASCII_FIRST:
810 810 addr_ptr = &upper->kbtrans_streams_vuid_addr.ascii;
811 811 break;
812 812
813 813 case TOP_FIRST:
814 814 addr_ptr = &upper->kbtrans_streams_vuid_addr.top;
815 815 break;
816 816
817 817 case VKEY_FIRST:
818 818 addr_ptr = &upper->kbtrans_streams_vuid_addr.vkey;
819 819 break;
820 820
821 821 default:
822 822 err = ENODEV;
823 823 }
824 824
825 825 if ((err == 0) && (*addr_ptr != addr_probe->data.next)) {
826 826 *addr_ptr = addr_probe->data.next;
827 827 kbtrans_flush(upper);
828 828 }
829 829 break;
830 830
831 831 case VUIDGADDR:
832 832 DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "VUIDGADDR\n"));
833 833
834 834 err = miocpullup(mp, sizeof (Vuid_addr_probe));
835 835 if (err != 0)
836 836 break;
837 837 addr_probe = (Vuid_addr_probe *)mp->b_cont->b_rptr;
838 838 switch (addr_probe->base) {
839 839
840 840 case ASCII_FIRST:
841 841 addr_probe->data.current =
842 842 upper->kbtrans_streams_vuid_addr.ascii;
843 843 break;
844 844
845 845 case TOP_FIRST:
846 846 addr_probe->data.current =
847 847 upper->kbtrans_streams_vuid_addr.top;
848 848 break;
849 849
850 850 case VKEY_FIRST:
851 851 addr_probe->data.current =
852 852 upper->kbtrans_streams_vuid_addr.vkey;
853 853 break;
854 854
855 855 default:
856 856 err = ENODEV;
857 857 }
858 858 break;
859 859
860 860 case KIOCTRANSABLE:
861 861 DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "KIOCTRANSABLE\n"));
862 862
863 863 err = miocpullup(mp, sizeof (int));
864 864 if (err != 0)
865 865 break;
866 866 /*
867 867 * called during console setup in kbconfig()
868 868 * If set to false, means we are a serial keyboard,
869 869 * and we should pass all data up without modification.
870 870 */
871 871 translate = *(int *)mp->b_cont->b_rptr;
872 872 if (upper->kbtrans_streams_translatable != translate)
873 873 upper->kbtrans_streams_translatable = translate;
874 874
875 875 if (translate != TR_CAN)
876 876 DPRINTF(PRINT_L4, PRINT_MASK_ALL, (upper,
877 877 "Cannot translate keyboard using tables.\n"));
878 878 break;
879 879
880 880 case KIOCGTRANSABLE:
881 881 DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "KIOCGTRANSABLE\n"));
882 882 if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) {
883 883 ioctlrespsize = sizeof (int);
884 884 goto allocfailure;
885 885 }
886 886 *(int *)datap->b_wptr = upper->kbtrans_streams_translatable;
887 887 datap->b_wptr += sizeof (int);
888 888 if (mp->b_cont) /* free msg to prevent memory leak */
889 889 freemsg(mp->b_cont);
890 890 mp->b_cont = datap;
891 891 iocp->ioc_count = sizeof (int);
892 892 break;
893 893
894 894 case KIOCSCOMPAT:
895 895 DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "KIOCSCOMPAT\n"));
896 896
897 897 err = miocpullup(mp, sizeof (int));
898 898 if (err != 0)
899 899 break;
900 900 lower->kbtrans_compat = *(int *)mp->b_cont->b_rptr;
901 901 break;
902 902
903 903 case KIOCGCOMPAT:
904 904 DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "KIOCGCOMPAT\n"));
905 905 if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) {
906 906 ioctlrespsize = sizeof (int);
907 907 goto allocfailure;
908 908 }
909 909 *(int *)datap->b_wptr = lower->kbtrans_compat;
910 910 datap->b_wptr += sizeof (int);
911 911 if (mp->b_cont) /* free msg to prevent memory leak */
912 912 freemsg(mp->b_cont);
913 913 mp->b_cont = datap;
914 914 iocp->ioc_count = sizeof (int);
915 915 break;
916 916
917 917 case KIOCSETKEY:
918 918 DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "KIOCSETKEY %d\n",
919 919 kiocsetkey++));
920 920 err = miocpullup(mp, sizeof (struct kiockey));
921 921 if (err != 0)
922 922 break;
923 923 err = kbtrans_setkey(&upper->kbtrans_lower,
924 924 (struct kiockey *)mp->b_cont->b_rptr, iocp->ioc_cr);
925 925 /*
926 926 * Since this only affects any subsequent key presses,
927 927 * don't flush soft state. One might want to
928 928 * toggle the keytable entries dynamically.
929 929 */
930 930 break;
931 931
932 932 case KIOCGETKEY:
933 933 DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "KIOCGETKEY %d\n",
934 934 kiocgetkey++));
935 935 err = miocpullup(mp, sizeof (struct kiockey));
936 936 if (err != 0)
937 937 break;
938 938 err = kbtrans_getkey(&upper->kbtrans_lower,
939 939 (struct kiockey *)mp->b_cont->b_rptr);
940 940 break;
941 941
942 942 case KIOCSKEY:
943 943 err = miocpullup(mp, sizeof (struct kiockeymap));
944 944 if (err != 0)
945 945 break;
946 946 err = kbtrans_skey(&upper->kbtrans_lower,
947 947 (struct kiockeymap *)mp->b_cont->b_rptr, iocp->ioc_cr);
948 948 /*
949 949 * Since this only affects any subsequent key presses,
950 950 * don't flush soft state. One might want to
951 951 * toggle the keytable entries dynamically.
952 952 */
953 953 break;
954 954
955 955 case KIOCGKEY:
956 956 err = miocpullup(mp, sizeof (struct kiockeymap));
957 957 if (err != 0)
958 958 break;
959 959 err = kbtrans_gkey(&upper->kbtrans_lower,
960 960 (struct kiockeymap *)mp->b_cont->b_rptr);
961 961 break;
962 962
963 963 case KIOCSDIRECT:
964 964 DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "KIOCSDIRECT\n"));
965 965 kbtrans_flush(upper);
966 966 break;
967 967
968 968 case KIOCGDIRECT:
969 969 DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "KIOCSGDIRECT\n"));
970 970 if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) {
971 971 ioctlrespsize = sizeof (int);
972 972 goto allocfailure;
973 973 }
974 974 *(int *)datap->b_wptr = 1; /* always direct */
975 975 datap->b_wptr += sizeof (int);
976 976 if (mp->b_cont) /* free msg to prevent memory leak */
977 977 freemsg(mp->b_cont);
978 978 mp->b_cont = datap;
979 979 iocp->ioc_count = sizeof (int);
980 980 break;
981 981
982 982 case KIOCTYPE:
983 983 DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "KIOCTYPE\n"));
984 984 if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) {
985 985 ioctlrespsize = sizeof (int);
986 986 goto allocfailure;
987 987 }
988 988 *(int *)datap->b_wptr = upper->kbtrans_streams_id;
989 989 datap->b_wptr += sizeof (int);
990 990 if (mp->b_cont) /* free msg to prevent memory leak */
991 991 freemsg(mp->b_cont);
992 992 mp->b_cont = datap;
993 993 iocp->ioc_count = sizeof (int);
994 994 break;
995 995
996 996 case CONSSETABORTENABLE:
997 997 /*
998 998 * Peek as it goes by; must be a TRANSPARENT ioctl.
999 999 */
1000 1000 if (iocp->ioc_count != TRANSPARENT) {
1001 1001 err = EINVAL;
1002 1002 break;
1003 1003 }
1004 1004
1005 1005 upper->kbtrans_streams_abortable =
1006 1006 (boolean_t)*(intptr_t *)mp->b_cont->b_rptr;
1007 1007
1008 1008 /*
1009 1009 * Let the hardware module see it too.
1010 1010 */
1011 1011 return (KBTRANS_MESSAGE_NOT_HANDLED);
1012 1012
1013 1013 case KIOCGRPTDELAY:
1014 1014 /*
1015 1015 * Report the autorepeat delay, unit in millisecond
1016 1016 */
1017 1017 DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "KIOCGRPTDELAY\n"));
1018 1018 if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) {
1019 1019 ioctlrespsize = sizeof (int);
1020 1020 goto allocfailure;
1021 1021 }
1022 1022 *(int *)datap->b_wptr = TICK_TO_MSEC(kbtrans_repeat_delay);
1023 1023 datap->b_wptr += sizeof (int);
1024 1024
1025 1025 /* free msg to prevent memory leak */
1026 1026 if (mp->b_cont != NULL)
1027 1027 freemsg(mp->b_cont);
1028 1028 mp->b_cont = datap;
1029 1029 iocp->ioc_count = sizeof (int);
1030 1030 break;
1031 1031
1032 1032 case KIOCSRPTDELAY:
1033 1033 /*
1034 1034 * Set the autorepeat delay
1035 1035 */
1036 1036 DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "KIOCSRPTDELAY\n"));
1037 1037 err = miocpullup(mp, sizeof (int));
1038 1038
1039 1039 if (err != 0)
1040 1040 break;
1041 1041
1042 1042 /* validate the input */
1043 1043 if (*(int *)mp->b_cont->b_rptr < KIOCRPTDELAY_MIN) {
1044 1044 err = EINVAL;
1045 1045 break;
1046 1046 }
1047 1047 kbtrans_repeat_delay = MSEC_TO_TICK(*(int *)mp->b_cont->b_rptr);
1048 1048 if (kbtrans_repeat_delay <= 0)
1049 1049 kbtrans_repeat_delay = 1;
1050 1050 break;
1051 1051
1052 1052 case KIOCGRPTRATE:
1053 1053 /*
1054 1054 * Report the autorepeat rate
1055 1055 */
1056 1056 DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "KIOCGRPTRATE\n"));
1057 1057 if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) {
1058 1058 ioctlrespsize = sizeof (int);
1059 1059 goto allocfailure;
1060 1060 }
1061 1061 *(int *)datap->b_wptr = TICK_TO_MSEC(kbtrans_repeat_rate);
1062 1062 datap->b_wptr += sizeof (int);
1063 1063
1064 1064 /* free msg to prevent memory leak */
1065 1065 if (mp->b_cont != NULL)
1066 1066 freemsg(mp->b_cont);
1067 1067 mp->b_cont = datap;
1068 1068 iocp->ioc_count = sizeof (int);
1069 1069 break;
1070 1070
1071 1071 case KIOCSRPTRATE:
1072 1072 /*
1073 1073 * Set the autorepeat rate
1074 1074 */
1075 1075 DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "KIOCSRPTRATE\n"));
1076 1076 err = miocpullup(mp, sizeof (int));
1077 1077
1078 1078 if (err != 0)
1079 1079 break;
1080 1080
1081 1081 /* validate the input */
1082 1082 if (*(int *)mp->b_cont->b_rptr < KIOCRPTRATE_MIN) {
1083 1083 err = EINVAL;
1084 1084 break;
1085 1085 }
1086 1086 kbtrans_repeat_rate = MSEC_TO_TICK(*(int *)mp->b_cont->b_rptr);
1087 1087 if (kbtrans_repeat_rate <= 0)
1088 1088 kbtrans_repeat_rate = 1;
1089 1089 break;
1090 1090
1091 1091 default:
1092 1092 DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "unknown\n"));
1093 1093 return (KBTRANS_MESSAGE_NOT_HANDLED);
1094 1094 } /* end switch */
1095 1095
1096 1096 if (err != 0) {
1097 1097 iocp->ioc_rval = 0;
1098 1098 iocp->ioc_error = err;
1099 1099 mp->b_datap->db_type = M_IOCNAK;
1100 1100 } else {
1101 1101 iocp->ioc_rval = 0;
1102 1102 iocp->ioc_error = 0; /* brain rot */
1103 1103 mp->b_datap->db_type = M_IOCACK;
1104 1104 }
1105 1105 putnext(upper->kbtrans_streams_readq, mp);
1106 1106
1107 1107 return (KBTRANS_MESSAGE_HANDLED);
1108 1108
1109 1109 allocfailure:
1110 1110 /*
1111 1111 * We needed to allocate something to handle this "ioctl", but
1112 1112 * couldn't; save this "ioctl" and arrange to get called back when
1113 1113 * it's more likely that we can get what we need.
1114 1114 * If there's already one being saved, throw it out, since it
1115 1115 * must have timed out.
1116 1116 */
1117 1117 if (upper->kbtrans_streams_iocpending != NULL)
1118 1118 freemsg(upper->kbtrans_streams_iocpending);
1119 1119 upper->kbtrans_streams_iocpending = mp;
1120 1120 if (upper->kbtrans_streams_bufcallid) {
1121 1121 qunbufcall(upper->kbtrans_streams_readq,
1122 1122 upper->kbtrans_streams_bufcallid);
1123 1123 }
1124 1124 upper->kbtrans_streams_bufcallid =
1125 1125 qbufcall(upper->kbtrans_streams_readq, ioctlrespsize, BPRI_HI,
1126 1126 kbtrans_reioctl, upper);
1127 1127 /*
1128 1128 * This is a white lie... we *will* handle it, eventually.
1129 1129 */
1130 1130 return (KBTRANS_MESSAGE_HANDLED);
1131 1131 }
1132 1132
1133 1133 /*
1134 1134 * kbtrans_flush:
1135 1135 * Flush data upstream
1136 1136 */
1137 1137 static void
1138 1138 kbtrans_flush(register struct kbtrans *upper)
1139 1139 {
1140 1140 register queue_t *q;
1141 1141
1142 1142 /* Flush pending data already sent upstream */
1143 1143 if ((q = upper->kbtrans_streams_readq) != NULL && q->q_next != NULL)
1144 1144 (void) putnextctl1(q, M_FLUSH, FLUSHR);
1145 1145
1146 1146 /* Flush pending ups */
1147 1147 bzero(upper->kbtrans_streams_downs, upper->kbtrans_streams_downs_bytes);
1148 1148
1149 1149 kbtrans_cancelrpt(upper);
1150 1150 }
1151 1151
1152 1152 /*
1153 1153 * kbtrans_setled:
1154 1154 * Update the keyboard LEDs to match the current keyboard state.
1155 1155 */
1156 1156 static void
1157 1157 kbtrans_setled(struct kbtrans *upper)
1158 1158 {
1159 1159 upper->kbtrans_streams_hw_callbacks->kbtrans_streams_setled(
1160 1160 upper->kbtrans_streams_hw,
1161 1161 upper->kbtrans_lower.kbtrans_led_state);
1162 1162 }
1163 1163
1164 1164 /*
1165 1165 * kbtrans_rpt:
1166 1166 * If a key is held down, this function is set up to be called
1167 1167 * after kbtrans_repeat_rate time elapses.
1168 1168 */
1169 1169 static void
1170 1170 kbtrans_rpt(void *arg)
1171 1171 {
1172 1172 struct kbtrans *upper = arg;
1173 1173 struct kbtrans_lower *lower = &upper->kbtrans_lower;
1174 1174
1175 1175 DPRINTF(PRINT_L0, PRINT_MASK_ALL, (NULL,
1176 1176 "kbtrans_rpt: repeat key %X\n",
1177 1177 lower->kbtrans_repeatkey));
1178 1178
1179 1179 upper->kbtrans_streams_rptid = 0;
1180 1180
1181 1181 /*
1182 1182 * NB: polled code zaps kbtrans_repeatkey without cancelling
1183 1183 * timeout.
1184 1184 */
1185 1185 if (lower->kbtrans_repeatkey != 0) {
1186 1186 kbtrans_keyreleased(upper, lower->kbtrans_repeatkey);
1187 1187
1188 1188 kbtrans_processkey(lower,
1189 1189 upper->kbtrans_streams_callback,
1190 1190 lower->kbtrans_repeatkey,
1191 1191 KEY_PRESSED);
1192 1192
1193 1193 upper->kbtrans_streams_rptid =
1194 1194 qtimeout(upper->kbtrans_streams_readq, kbtrans_rpt,
1195 1195 (caddr_t)upper, kbtrans_repeat_rate);
1196 1196 }
1197 1197 }
1198 1198
1199 1199 /*
1200 1200 * kbtrans_cancelrpt:
1201 1201 * Cancel the repeating key
1202 1202 */
1203 1203 static void
1204 1204 kbtrans_cancelrpt(struct kbtrans *upper)
1205 1205 {
1206 1206 upper->kbtrans_lower.kbtrans_repeatkey = 0;
1207 1207
1208 1208 if (upper->kbtrans_streams_rptid != 0) {
1209 1209 (void) quntimeout(upper->kbtrans_streams_readq,
1210 1210 upper->kbtrans_streams_rptid);
1211 1211 upper->kbtrans_streams_rptid = 0;
1212 1212 }
1213 1213 }
1214 1214
1215 1215 /*
1216 1216 * kbtrans_send_esc_event:
1217 1217 * Send character up stream. Used for the case of
1218 1218 * sending strings upstream.
1219 1219 */
1220 1220 static void
1221 1221 kbtrans_send_esc_event(char c, register struct kbtrans *upper)
1222 1222 {
1223 1223 Firm_event fe;
1224 1224
1225 1225 fe.id = c;
1226 1226 fe.value = 1;
1227 1227 fe.pair_type = FE_PAIR_NONE;
1228 1228 fe.pair = 0;
1229 1229 /*
1230 1230 * Pretend as if each cp pushed and released
1231 1231 * Calling kbtrans_queueevent avoids addr translation
1232 1232 * and pair base determination of kbtrans_keypressed.
1233 1233 */
1234 1234 kbtrans_queueevent(upper, &fe);
1235 1235 fe.value = 0;
1236 1236 kbtrans_queueevent(upper, &fe);
1237 1237 }
1238 1238
1239 1239 /*
1240 1240 * kbtrans_strsetwithdecimal:
1241 1241 * Used for expanding a function key to the ascii equivalent
1242 1242 */
1243 1243 static char *
1244 1244 kbtrans_strsetwithdecimal(char *buf, uint_t val, uint_t maxdigs)
1245 1245 {
1246 1246 int hradix = 5;
1247 1247 char *bp;
1248 1248 int lowbit;
1249 1249 char *tab = "0123456789abcdef";
1250 1250
1251 1251 bp = buf + maxdigs;
1252 1252 *(--bp) = '\0';
1253 1253 while (val) {
1254 1254 lowbit = val & 1;
1255 1255 val = (val >> 1);
1256 1256 *(--bp) = tab[val % hradix * 2 + lowbit];
1257 1257 val /= hradix;
1258 1258 }
1259 1259 return (bp);
1260 1260 }
1261 1261
1262 1262 /*
1263 1263 * kbtrans_keypressed:
1264 1264 * Modify Firm event to be sent up the stream
1265 1265 */
1266 1266 static void
1267 1267 kbtrans_keypressed(struct kbtrans *upper, uchar_t key_station,
1268 1268 Firm_event *fe, ushort_t base)
1269 1269 {
1270 1270
1271 1271 register short id_addr;
1272 1272 struct kbtrans_lower *lower = &upper->kbtrans_lower;
1273 1273
1274 1274 /* Set pair values */
1275 1275 if (fe->id < (ushort_t)VKEY_FIRST) {
1276 1276 /*
1277 1277 * If CTRLed, find the ID that would have been used had it
1278 1278 * not been CTRLed.
1279 1279 */
1280 1280 if (lower->kbtrans_shiftmask & (CTRLMASK | CTLSMASK)) {
1281 1281 unsigned short *ke;
1282 1282 unsigned int mask;
1283 1283
1284 1284 mask = lower->kbtrans_shiftmask &
1285 1285 ~(CTRLMASK | CTLSMASK | UPMASK);
1286 1286
1287 1287 ke = kbtrans_find_entry(lower, mask, key_station);
1288 1288 if (ke == NULL)
1289 1289 return;
1290 1290
1291 1291 base = *ke;
1292 1292 }
1293 1293 if (base != fe->id) {
1294 1294 fe->pair_type = FE_PAIR_SET;
1295 1295 fe->pair = (uchar_t)base;
1296 1296
1297 1297 goto send;
1298 1298 }
1299 1299 }
1300 1300 fe->pair_type = FE_PAIR_NONE;
1301 1301 fe->pair = 0;
1302 1302
1303 1303 send:
1304 1304 /* Adjust event id address for multiple keyboard/workstation support */
1305 1305 switch (vuid_id_addr(fe->id)) {
1306 1306 case ASCII_FIRST:
1307 1307 id_addr = upper->kbtrans_streams_vuid_addr.ascii;
1308 1308 break;
1309 1309 case TOP_FIRST:
1310 1310 id_addr = upper->kbtrans_streams_vuid_addr.top;
1311 1311 break;
1312 1312 case VKEY_FIRST:
1313 1313 id_addr = upper->kbtrans_streams_vuid_addr.vkey;
1314 1314 break;
1315 1315 default:
1316 1316 id_addr = vuid_id_addr(fe->id);
1317 1317 break;
1318 1318 }
1319 1319 fe->id = vuid_id_offset(fe->id) | id_addr;
1320 1320
1321 1321 kbtrans_queuepress(upper, key_station, fe);
1322 1322 }
1323 1323
1324 1324 /*
1325 1325 * kbtrans_queuepress:
1326 1326 * Add keypress to the "downs" table
1327 1327 */
1328 1328 static void
1329 1329 kbtrans_queuepress(struct kbtrans *upper,
1330 1330 uchar_t key_station, Firm_event *fe)
1331 1331 {
1332 1332 register struct key_event *ke, *ke_free;
1333 1333 register int i;
1334 1334
1335 1335 DPRINTF(PRINT_L0, PRINT_MASK_ALL, (NULL, "kbtrans_queuepress:"
1336 1336 " key=%d", key_station));
1337 1337
1338 1338 ke_free = 0;
1339 1339
1340 1340 /* Scan table of down key stations */
1341 1341
1342 1342 for (i = 0, ke = upper->kbtrans_streams_downs;
1343 1343 i < upper->kbtrans_streams_num_downs_entries; i++, ke++) {
1344 1344
1345 1345 /* Keycode already down? */
1346 1346 if (ke->key_station == key_station) {
1347 1347
1348 1348 DPRINTF(PRINT_L0, PRINT_MASK_ALL,
1349 1349 (NULL, "kbtrans: Double "
1350 1350 "entry in downs table (%d,%d)!\n",
1351 1351 key_station, i));
1352 1352
1353 1353 goto add_event;
1354 1354 }
1355 1355
1356 1356 if (ke->key_station == 0)
1357 1357 ke_free = ke;
1358 1358 }
1359 1359
1360 1360 if (ke_free) {
1361 1361 ke = ke_free;
1362 1362 goto add_event;
1363 1363 }
1364 1364
1365 1365 ke = upper->kbtrans_streams_downs;
1366 1366
1367 1367 add_event:
1368 1368 ke->key_station = key_station;
1369 1369 ke->event = *fe;
1370 1370 kbtrans_queueevent(upper, fe);
1371 1371 }
1372 1372
1373 1373 /*
1374 1374 * kbtrans_keyreleased:
1375 1375 * Remove entry from the downs table
1376 1376 */
1377 1377 static void
1378 1378 kbtrans_keyreleased(register struct kbtrans *upper, uchar_t key_station)
1379 1379 {
1380 1380 register struct key_event *ke;
1381 1381 register int i;
1382 1382
1383 1383 DPRINTF(PRINT_L0, PRINT_MASK_ALL, (NULL, "RELEASE key=%d\n",
1384 1384 key_station));
1385 1385
1386 1386 if (upper->kbtrans_streams_translate_mode != TR_EVENT &&
1387 1387 upper->kbtrans_streams_translate_mode != TR_UNTRANS_EVENT) {
1388 1388
1389 1389 return;
1390 1390 }
1391 1391
1392 1392 /* Scan table of down key stations */
1393 1393 for (i = 0, ke = upper->kbtrans_streams_downs;
1394 1394 i < upper->kbtrans_streams_num_downs_entries;
1395 1395 i++, ke++) {
1396 1396 /* Found? */
1397 1397 if (ke->key_station == key_station) {
1398 1398 ke->key_station = 0;
1399 1399 ke->event.value = 0;
1400 1400 kbtrans_queueevent(upper, &ke->event);
1401 1401 }
1402 1402 }
1403 1403
1404 1404 /*
1405 1405 * Ignore if couldn't find because may be called twice
1406 1406 * for the same key station in the case of the kbtrans_rpt
1407 1407 * routine being called unnecessarily.
1408 1408 */
1409 1409 }
1410 1410
1411 1411
1412 1412 /*
1413 1413 * kbtrans_putcode:
1414 1414 * Pass a keycode up the stream, if you can, otherwise throw it away.
1415 1415 */
1416 1416 static void
1417 1417 kbtrans_putcode(register struct kbtrans *upper, uint_t code)
1418 1418 {
1419 1419 register mblk_t *bp;
1420 1420
1421 1421 /*
1422 1422 * If we can't send it up, then we just drop it.
1423 1423 */
1424 1424 if (!canputnext(upper->kbtrans_streams_readq)) {
1425 1425
1426 1426 return;
1427 1427 }
1428 1428
1429 1429 /*
1430 1430 * Allocate a messsage block to send up.
1431 1431 */
1432 1432 if ((bp = allocb(sizeof (uint_t), BPRI_HI)) == NULL) {
1433 1433
1434 1434 cmn_err(CE_WARN, "kbtrans_putcode: Can't allocate block\
1435 1435 for keycode.");
1436 1436
1437 1437 return;
1438 1438 }
1439 1439
1440 1440 /*
1441 1441 * We will strip out any high order information here.
1442 1442 */
1443 1443 /* NOTE the implicit cast here */
1444 1444 *bp->b_wptr++ = (uchar_t)code;
1445 1445
1446 1446 /*
1447 1447 * Send the message up.
1448 1448 */
1449 1449 (void) putnext(upper->kbtrans_streams_readq, bp);
1450 1450 }
1451 1451
1452 1452
1453 1453 /*
1454 1454 * kbtrans_putbuf:
1455 1455 * Pass generated keycode sequence to upstream, if possible.
1456 1456 */
1457 1457 static void
1458 1458 kbtrans_putbuf(char *buf, queue_t *q)
1459 1459 {
1460 1460 register mblk_t *bp;
1461 1461
1462 1462 if (!canputnext(q)) {
1463 1463 cmn_err(CE_WARN, "kbtrans_putbuf: Can't put block for keycode");
1464 1464 } else {
1465 1465 if ((bp = allocb((int)strlen(buf), BPRI_HI)) == NULL) {
1466 1466 cmn_err(CE_WARN, "kbtrans_putbuf: "
1467 1467 "Can't allocate block for keycode");
1468 1468 } else {
1469 1469 while (*buf) {
1470 1470 *bp->b_wptr++ = *buf;
1471 1471 buf++;
1472 1472 }
1473 1473 putnext(q, bp);
1474 1474 }
1475 1475 }
1476 1476 }
1477 1477
1478 1478 /*
1479 1479 * kbtrans_queueevent:
1480 1480 * Pass a VUID "firm event" up the stream, if you can.
1481 1481 */
1482 1482 static void
1483 1483 kbtrans_queueevent(struct kbtrans *upper, Firm_event *fe)
1484 1484 {
1485 1485 register queue_t *q;
1486 1486 register mblk_t *bp;
1487 1487
1488 1488 if ((q = upper->kbtrans_streams_readq) == NULL)
1489 1489
1490 1490 return;
1491 1491
1492 1492 if (!canputnext(q)) {
1493 1493 if (kbtrans_overflow_msg) {
1494 1494 DPRINTF(PRINT_L2, PRINT_MASK_ALL, (NULL,
1495 1495 "kbtrans: Buffer flushed when overflowed."));
1496 1496 }
1497 1497
1498 1498 kbtrans_flush(upper);
1499 1499 upper->kbtrans_overflow_cnt++;
1500 1500 } else {
1501 1501 if ((bp = allocb(sizeof (Firm_event), BPRI_HI)) == NULL) {
1502 1502 cmn_err(CE_WARN, "kbtrans_queueevent: Can't allocate \
1503 1503 block for event.");
1504 1504 } else {
1505 1505 uniqtime32(&fe->time);
1506 1506 *(Firm_event *)bp->b_wptr = *fe;
1507 1507 bp->b_wptr += sizeof (Firm_event);
1508 1508 (void) putnext(q, bp);
1509 1509
1510 1510
1511 1511 }
1512 1512 }
1513 1513 }
1514 1514
1515 1515 /*
1516 1516 * kbtrans_set_translation_callback:
1517 1517 * This code sets the translation_callback pointer based on the
1518 1518 * translation mode.
1519 1519 */
1520 1520 static void
1521 1521 kbtrans_set_translation_callback(register struct kbtrans *upper)
1522 1522 {
1523 1523 switch (upper->kbtrans_streams_translate_mode) {
1524 1524
1525 1525 default:
1526 1526 case TR_ASCII:
1527 1527 upper->vt_switch_keystate = VT_SWITCH_KEY_NONE;
1528 1528
1529 1529 /* Discard any obsolete CTRL/ALT/SHIFT keys */
1530 1530 upper->kbtrans_lower.kbtrans_shiftmask &=
1531 1531 ~(CTRLMASK | ALTMASK | SHIFTMASK);
1532 1532 upper->kbtrans_lower.kbtrans_togglemask &=
1533 1533 ~(CTRLMASK | ALTMASK | SHIFTMASK);
1534 1534
1535 1535 upper->kbtrans_streams_callback = &ascii_callback;
1536 1536
1537 1537 break;
1538 1538
1539 1539 case TR_EVENT:
1540 1540 upper->kbtrans_streams_callback = &trans_event_callback;
1541 1541
1542 1542 break;
1543 1543
1544 1544 case TR_UNTRANS_EVENT:
1545 1545 upper->kbtrans_streams_callback = &untrans_event_callback;
1546 1546
1547 1547 break;
1548 1548 }
1549 1549 }
1550 1550
1551 1551 /*
1552 1552 * kbtrans_untrans_keypressed_raw:
1553 1553 * This is the callback we get if we are in TR_UNTRANS_EVENT and a
1554 1554 * key is pressed. This code will just send the scancode up the
1555 1555 * stream.
1556 1556 */
1557 1557 static void
1558 1558 kbtrans_untrans_keypressed_raw(struct kbtrans *upper, kbtrans_key_t key)
1559 1559 {
1560 1560 Firm_event fe;
1561 1561
1562 1562 bzero(&fe, sizeof (fe));
1563 1563
1564 1564 /*
1565 1565 * fill in the event
1566 1566 */
1567 1567 fe.id = (unsigned short)key;
1568 1568 fe.value = 1;
1569 1569
1570 1570 /*
1571 1571 * Send the event upstream.
1572 1572 */
1573 1573 kbtrans_queuepress(upper, key, &fe);
1574 1574 }
1575 1575
1576 1576 /*
1577 1577 * kbtrans_untrans_keyreleased_raw:
1578 1578 * This is the callback we get if we are in TR_UNTRANS_EVENT mode
1579 1579 * and a key is released. This code will just send the scancode up
1580 1580 * the stream.
1581 1581 */
1582 1582 static void
1583 1583 kbtrans_untrans_keyreleased_raw(struct kbtrans *upper, kbtrans_key_t key)
1584 1584 {
1585 1585 /*
1586 1586 * Deal with a key released event.
1587 1587 */
1588 1588 kbtrans_keyreleased(upper, key);
1589 1589 }
1590 1590
1591 1591 /*
1592 1592 * kbtrans_vt_compose:
1593 1593 * To compose the key sequences for virtual terminal switching.
1594 1594 *
1595 1595 * 'ALTL + F#' for 1-12 terminals
1596 1596 * 'ALTGR + F#' for 13-24 terminals
1597 1597 * 'ALT + UPARROW' for last terminal
1598 1598 * 'ALT + LEFTARROW' for previous terminal
1599 1599 * 'ALT + RIGHTARROW' for next terminal
1600 1600 *
1601 1601 * the vt switching message is encoded as:
1602 1602 *
1603 1603 * -------------------------------------------------------------
1604 1604 * | \033 | 'Q' | vtno + 'A' | opcode | 'z' | '\0' |
1605 1605 * -------------------------------------------------------------
1606 1606 *
1607 1607 * opcode:
1608 1608 * 'B' to switch to previous terminal
1609 1609 * 'F' to switch to next terminal
1610 1610 * 'L' to switch to last terminal
1611 1611 * 'H' to switch to the terminal as specified by vtno,
1612 1612 * which is from 1 to 24.
1613 1613 *
1614 1614 * Here keyid is the keycode of UPARROW, LEFTARROW, or RIGHTARROW
1615 1615 * when it is a kind of arrow key as indicated by is_arrow_key,
1616 1616 * otherwise it indicates a function key and keyid is the number
1617 1617 * corresponding to that function key.
1618 1618 */
1619 1619 static void
1620 1620 kbtrans_vt_compose(struct kbtrans *upper, unsigned short keyid,
1621 1621 boolean_t is_arrow_key, char *buf)
1622 1622 {
1623 1623 char *bufp;
1624 1624
1625 1625 bufp = buf;
1626 1626 *bufp++ = '\033'; /* Escape */
1627 1627 *bufp++ = 'Q';
1628 1628 if (is_arrow_key) {
1629 1629 *bufp++ = 'A';
1630 1630 switch (keyid) {
1631 1631 case UPARROW: /* last vt */
1632 1632 *bufp++ = 'L';
1633 1633 break;
1634 1634 case LEFTARROW: /* previous vt */
1635 1635 *bufp++ = 'B';
1636 1636 break;
1637 1637 case RIGHTARROW: /* next vt */
1638 1638 *bufp++ = 'F';
1639 1639 break;
1640 1640 default:
1641 1641 break;
1642 1642 }
1643 1643 } else {
1644 1644 /* this is funckey specifying vtno for switch */
1645 1645 *bufp++ = keyid +
1646 1646 (upper->vt_switch_keystate - VT_SWITCH_KEY_ALT) *
1647 1647 KB_NR_FUNCKEYS + 'A';
1648 1648 *bufp++ = 'H';
1649 1649 }
1650 1650 *bufp++ = 'z';
1651 1651 *bufp = '\0';
1652 1652
1653 1653 /*
1654 1654 * Send the result upstream.
1655 1655 */
1656 1656 kbtrans_putbuf(buf, upper->kbtrans_streams_readq);
1657 1657
1658 1658 }
1659 1659
1660 1660 /*
1661 1661 * kbtrans_ascii_keypressed:
1662 1662 * This is the code if we are in TR_ASCII mode and a key
1663 1663 * is pressed. This is where we will do any special processing that
1664 1664 * is specific to ASCII key translation.
1665 1665 */
1666 1666 /* ARGSUSED */
1667 1667 static void
1668 1668 kbtrans_ascii_keypressed(
1669 1669 struct kbtrans *upper,
1670 1670 uint_t entrytype,
1671 1671 kbtrans_key_t key,
1672 1672 uint_t entry)
1673 1673 {
1674 1674 register char *cp;
1675 1675 register char *bufp;
1676 1676 char buf[14];
1677 1677 unsigned short keyid;
1678 1678 struct kbtrans_lower *lower = &upper->kbtrans_lower;
1679 1679
1680 1680 /*
1681 1681 * Based on the type of key, we may need to do some ASCII
1682 1682 * specific post processing. Note that the translated entry
1683 1683 * is constructed as the actual keycode plus entrytype. see
1684 1684 * sys/kbd.h for details of each entrytype.
1685 1685 */
1686 1686 switch (entrytype) {
1687 1687
1688 1688 case BUCKYBITS:
1689 1689 return;
1690 1690
1691 1691 case SHIFTKEYS:
1692 1692 keyid = entry & 0xFF;
1693 1693 if (keyid == ALT) {
1694 1694 upper->vt_switch_keystate = VT_SWITCH_KEY_ALT;
1695 1695 } else if (keyid == ALTGRAPH) {
1696 1696 upper->vt_switch_keystate = VT_SWITCH_KEY_ALTGR;
1697 1697 }
1698 1698 return;
1699 1699
1700 1700 case FUNNY:
1701 1701 /*
1702 1702 * There is no ascii equivalent. We will ignore these
1703 1703 * keys
1704 1704 */
1705 1705 return;
1706 1706
1707 1707 case FUNCKEYS:
1708 1708 if (upper->vt_switch_keystate > VT_SWITCH_KEY_NONE) {
1709 1709 if (entry >= TOPFUNC &&
1710 1710 entry < (TOPFUNC + KB_NR_FUNCKEYS)) {
1711 1711
1712 1712 /*
1713 1713 * keyid is the number correspoding to F#
1714 1714 * and its value is from 1 to 12.
1715 1715 */
1716 1716 keyid = (entry & 0xF) + 1;
1717 1717
1718 1718 kbtrans_vt_compose(upper, keyid, B_FALSE, buf);
1719 1719 return;
1720 1720 }
1721 1721 }
1722 1722
1723 1723 /*
1724 1724 * We need to expand this key to get the ascii
1725 1725 * equivalent. These are the function keys (F1, F2 ...)
1726 1726 */
1727 1727 bufp = buf;
1728 1728 cp = kbtrans_strsetwithdecimal(bufp + 2,
1729 1729 (uint_t)((entry & 0x003F) + 192),
1730 1730 sizeof (buf) - 5);
1731 1731 *bufp++ = '\033'; /* Escape */
1732 1732 *bufp++ = '[';
1733 1733 while (*cp != '\0')
1734 1734 *bufp++ = *cp++;
1735 1735 *bufp++ = 'z';
1736 1736 *bufp = '\0';
1737 1737
1738 1738 /*
1739 1739 * Send the result upstream.
1740 1740 */
1741 1741 kbtrans_putbuf(buf, upper->kbtrans_streams_readq);
1742 1742
1743 1743 return;
1744 1744
1745 1745 case STRING:
1746 1746 if (upper->vt_switch_keystate > VT_SWITCH_KEY_NONE) {
1747 1747 keyid = entry & 0xFF;
1748 1748 if (keyid == UPARROW ||
1749 1749 keyid == RIGHTARROW ||
1750 1750 keyid == LEFTARROW) {
1751 1751
1752 1752 kbtrans_vt_compose(upper, keyid, B_TRUE, buf);
1753 1753 return;
1754 1754 }
1755 1755 }
1756 1756
1757 1757 /*
1758 1758 * These are the multi byte keys (Home, Up, Down ...)
1759 1759 */
1760 1760 cp = &lower->kbtrans_keystringtab[entry & 0x0F][0];
1761 1761
1762 1762 /*
1763 1763 * Copy the string from the keystringtable, and send it
1764 1764 * upstream a character at a time.
1765 1765 */
1766 1766 while (*cp != '\0') {
1767 1767
1768 1768 kbtrans_putcode(upper, (uchar_t)*cp);
1769 1769
1770 1770 cp++;
1771 1771 }
1772 1772
1773 1773 return;
1774 1774
1775 1775 case PADKEYS:
1776 1776 /*
1777 1777 * These are the keys on the keypad. Look up the
1778 1778 * answer in the kb_numlock_table and send it upstream.
1779 1779 */
1780 1780 kbtrans_putcode(upper,
1781 1781 lower->kbtrans_numlock_table[entry&0x1F]);
1782 1782
1783 1783 return;
1784 1784
1785 1785 case 0: /* normal character */
1786 1786 default:
1787 1787 break;
1788 1788 }
1789 1789
1790 1790 /*
1791 1791 * Send the byte upstream.
1792 1792 */
1793 1793 kbtrans_putcode(upper, entry);
1794 1794
1795 1795 }
1796 1796
1797 1797 #define KB_SCANCODE_ALT 0xe2
1798 1798 #define KB_SCANCODE_ALTGRAPH 0xe6
1799 1799
1800 1800 /*
1801 1801 * kbtrans_ascii_keyreleased:
1802 1802 * This is the function if we are in TR_ASCII mode and a key
1803 1803 * is released. ASCII doesn't have the concept of released keys,
1804 1804 * or make/break codes. So there is nothing for us to do except
1805 1805 * checking 'Alt/AltGraph' release key in order to reset the state
1806 1806 * of vt switch key sequence.
1807 1807 */
1808 1808 /* ARGSUSED */
1809 1809 static void
1810 1810 kbtrans_ascii_keyreleased(struct kbtrans *upper, kbtrans_key_t key)
1811 1811 {
1812 1812 if (key == KB_SCANCODE_ALT || key == KB_SCANCODE_ALTGRAPH) {
1813 1813 upper->vt_switch_keystate = VT_SWITCH_KEY_NONE;
1814 1814 }
1815 1815 }
1816 1816
1817 1817 /*
1818 1818 * kbtrans_ascii_setup_repeat:
1819 1819 * This is the function if we are in TR_ASCII mode and the
1820 1820 * translation module has decided that a key needs to be repeated.
1821 1821 */
1822 1822 /* ARGSUSED */
1823 1823 static void
1824 1824 kbtrans_ascii_setup_repeat(
1825 1825 struct kbtrans *upper,
1826 1826 uint_t entrytype,
1827 1827 kbtrans_key_t key)
1828 1828 {
1829 1829 struct kbtrans_lower *lower = &upper->kbtrans_lower;
1830 1830
1831 1831 /*
1832 1832 * Cancel any currently repeating keys. This will be a new
1833 1833 * key to repeat.
1834 1834 */
1835 1835 kbtrans_cancelrpt(upper);
1836 1836
1837 1837 /*
1838 1838 * Set the value of the key to be repeated.
1839 1839 */
1840 1840 lower->kbtrans_repeatkey = key;
1841 1841
1842 1842 /*
1843 1843 * Start the timeout for repeating this key. kbtrans_rpt will
1844 1844 * be called to repeat the key.
1845 1845 */
1846 1846 upper->kbtrans_streams_rptid = qtimeout(upper->kbtrans_streams_readq,
1847 1847 kbtrans_rpt, (caddr_t)upper, kbtrans_repeat_delay);
1848 1848 }
1849 1849
1850 1850 /*
1851 1851 * kbtrans_trans_event_keypressed:
1852 1852 * This is the function if we are in TR_EVENT mode and a key
1853 1853 * is pressed. This is where we will do any special processing that
1854 1854 * is specific to EVENT key translation.
1855 1855 */
1856 1856 static void
1857 1857 kbtrans_trans_event_keypressed(
1858 1858 struct kbtrans *upper,
1859 1859 uint_t entrytype,
1860 1860 kbtrans_key_t key,
1861 1861 uint_t entry)
1862 1862 {
1863 1863 Firm_event fe;
1864 1864 register char *cp;
1865 1865 struct kbtrans_lower *lower = &upper->kbtrans_lower;
1866 1866
1867 1867 /*
1868 1868 * Based on the type of key, we may need to do some EVENT
1869 1869 * specific post processing.
1870 1870 */
1871 1871 switch (entrytype) {
1872 1872
1873 1873 case SHIFTKEYS:
1874 1874 /*
1875 1875 * Relying on ordinal correspondence between
1876 1876 * vuid_event.h SHIFT_META-SHIFT_TOP &
1877 1877 * kbd.h METABIT-SYSTEMBIT in order to
1878 1878 * correctly translate entry into fe.id.
1879 1879 */
1880 1880 fe.id = SHIFT_CAPSLOCK + (entry & 0x0F);
1881 1881 fe.value = 1;
1882 1882 kbtrans_keypressed(upper, key, &fe, fe.id);
1883 1883
1884 1884 return;
1885 1885
1886 1886 case BUCKYBITS:
1887 1887 /*
1888 1888 * Relying on ordinal correspondence between
1889 1889 * vuid_event.h SHIFT_CAPSLOCK-SHIFT_RIGHTCTRL &
1890 1890 * kbd.h CAPSLOCK-RIGHTCTRL in order to
1891 1891 * correctly translate entry into fe.id.
1892 1892 */
1893 1893 fe.id = SHIFT_META + (entry & 0x0F);
1894 1894 fe.value = 1;
1895 1895 kbtrans_keypressed(upper, key, &fe, fe.id);
1896 1896
1897 1897 return;
1898 1898
1899 1899 case FUNCKEYS:
1900 1900 /*
1901 1901 * Take advantage of the similar
1902 1902 * ordering of kbd.h function keys and
1903 1903 * vuid_event.h function keys to do a
1904 1904 * simple translation to achieve a
1905 1905 * mapping between the 2 different
1906 1906 * address spaces.
1907 1907 */
1908 1908 fe.id = KEY_LEFTFIRST + (entry & 0x003F);
1909 1909 fe.value = 1;
1910 1910
1911 1911 /*
1912 1912 * Assume "up" table only generates
1913 1913 * shift changes.
1914 1914 */
1915 1915 kbtrans_keypressed(upper, key, &fe, fe.id);
1916 1916
1917 1917 /*
1918 1918 * Function key events can be expanded
1919 1919 * by terminal emulator software to
1920 1920 * produce the standard escape sequence
1921 1921 * generated by the TR_ASCII case above
1922 1922 * if a function key event is not used
1923 1923 * by terminal emulator software
1924 1924 * directly.
1925 1925 */
1926 1926 return;
1927 1927
1928 1928 case STRING:
1929 1929 /*
1930 1930 * These are the multi byte keys (Home, Up, Down ...)
1931 1931 */
1932 1932 cp = &lower->kbtrans_keystringtab[entry & 0x0F][0];
1933 1933
1934 1934 /*
1935 1935 * Copy the string from the keystringtable, and send it
1936 1936 * upstream a character at a time.
1937 1937 */
1938 1938 while (*cp != '\0') {
1939 1939
1940 1940 kbtrans_send_esc_event(*cp, upper);
1941 1941
1942 1942 cp++;
1943 1943 }
1944 1944
1945 1945 return;
1946 1946
1947 1947 case PADKEYS:
1948 1948 /*
1949 1949 * Take advantage of the similar
1950 1950 * ordering of kbd.h keypad keys and
1951 1951 * vuid_event.h keypad keys to do a
1952 1952 * simple translation to achieve a
1953 1953 * mapping between the 2 different
1954 1954 * address spaces.
1955 1955 */
1956 1956 fe.id = VKEY_FIRSTPAD + (entry & 0x001F);
1957 1957 fe.value = 1;
1958 1958
1959 1959 /*
1960 1960 * Assume "up" table only generates
1961 1961 * shift changes.
1962 1962 */
1963 1963 kbtrans_keypressed(upper, key, &fe, fe.id);
1964 1964
1965 1965 /*
1966 1966 * Keypad key events can be expanded
1967 1967 * by terminal emulator software to
1968 1968 * produce the standard ascii character
1969 1969 * generated by the TR_ASCII case above
1970 1970 * if a keypad key event is not used
1971 1971 * by terminal emulator software
1972 1972 * directly.
1973 1973 */
1974 1974 return;
1975 1975
1976 1976 case FUNNY:
1977 1977 /*
1978 1978 * These are not events.
1979 1979 */
1980 1980 switch (entry) {
1981 1981 case IDLE:
1982 1982 case RESET:
1983 1983 case ERROR:
1984 1984 /*
1985 1985 * Something has happened. Mark all keys as released.
1986 1986 */
1987 1987 kbtrans_streams_releaseall(upper);
1988 1988 break;
1989 1989 }
1990 1990
1991 1991 return;
1992 1992
1993 1993 case 0: /* normal character */
1994 1994 default:
1995 1995 break;
1996 1996 }
1997 1997
1998 1998 /*
1999 1999 * Send the event upstream.
2000 2000 */
2001 2001 fe.id = entry;
2002 2002
2003 2003 fe.value = 1;
2004 2004
2005 2005 kbtrans_queueevent(upper, &fe);
2006 2006 }
2007 2007
2008 2008 /*
2009 2009 * kbtrans_trans_event_keyreleased:
2010 2010 * This is the function if we are in TR_EVENT mode and a key
2011 2011 * is released.
2012 2012 */
2013 2013 /* ARGSUSED */
2014 2014 static void
2015 2015 kbtrans_trans_event_keyreleased(struct kbtrans *upper, kbtrans_key_t key)
2016 2016 {
2017 2017 /*
2018 2018 * Mark the key as released and send an event upstream.
2019 2019 */
2020 2020 kbtrans_keyreleased(upper, key);
2021 2021 }
2022 2022
2023 2023 /*
2024 2024 * kbtrans_trans_event_setup_repeat:
2025 2025 * This is the function if we are in TR_EVENT mode and the
2026 2026 * translation module has decided that a key needs to be repeated.
2027 2027 * We will set a timeout to retranslate the repeat key.
2028 2028 */
2029 2029 static void
2030 2030 kbtrans_trans_event_setup_repeat(
2031 2031 struct kbtrans *upper,
2032 2032 uint_t entrytype,
2033 2033 kbtrans_key_t key)
2034 2034 {
2035 2035 struct kbtrans_lower *lower = &upper->kbtrans_lower;
2036 2036
2037 2037 /*
2038 2038 * Function keys and keypad keys do not repeat when we are in
2039 2039 * EVENT mode.
2040 2040 */
2041 2041 if (entrytype == FUNCKEYS || entrytype == PADKEYS) {
2042 2042
2043 2043 return;
2044 2044 }
2045 2045
2046 2046 /*
2047 2047 * Cancel any currently repeating keys. This will be a new
2048 2048 * key to repeat.
2049 2049 */
2050 2050 kbtrans_cancelrpt(upper);
2051 2051
2052 2052 /*
2053 2053 * Set the value of the key to be repeated.
2054 2054 */
2055 2055 lower->kbtrans_repeatkey = key;
2056 2056
2057 2057 /*
2058 2058 * Start the timeout for repeating this key. kbtrans_rpt will
2059 2059 * be called to repeat the key.
2060 2060 */
2061 2061 upper->kbtrans_streams_rptid = qtimeout(upper->kbtrans_streams_readq,
2062 2062 kbtrans_rpt, (caddr_t)upper, kbtrans_repeat_delay);
2063 2063 }
2064 2064
2065 2065 /*
2066 2066 * Administer the key tables.
2067 2067 */
2068 2068
2069 2069 /*
2070 2070 * Old special codes.
2071 2071 */
2072 2072 #define OLD_SHIFTKEYS 0x80
2073 2073 #define OLD_BUCKYBITS 0x90
2074 2074 #define OLD_FUNNY 0xA0
2075 2075 #define OLD_FA_UMLAUT 0xA9
2076 2076 #define OLD_FA_CFLEX 0xAA
2077 2077 #define OLD_FA_TILDE 0xAB
2078 2078 #define OLD_FA_CEDILLA 0xAC
2079 2079 #define OLD_FA_ACUTE 0xAD
2080 2080 #define OLD_FA_GRAVE 0xAE
2081 2081 #define OLD_ISOCHAR 0xAF
2082 2082 #define OLD_STRING 0xB0
2083 2083 #define OLD_LEFTFUNC 0xC0
2084 2084 #define OLD_RIGHTFUNC 0xD0
2085 2085 #define OLD_TOPFUNC 0xE0
2086 2086 #define OLD_BOTTOMFUNC 0xF0
2087 2087
2088 2088 /*
2089 2089 * Map old special codes to new ones.
2090 2090 * Indexed by ((old special code) >> 4) & 0x07; add (old special code) & 0x0F.
2091 2091 */
2092 2092 static ushort_t special_old_to_new[] = {
2093 2093 SHIFTKEYS,
2094 2094 BUCKYBITS,
2095 2095 FUNNY,
2096 2096 STRING,
2097 2097 LEFTFUNC,
2098 2098 RIGHTFUNC,
2099 2099 TOPFUNC,
2100 2100 BOTTOMFUNC,
2101 2101 };
2102 2102
2103 2103
2104 2104 /*
2105 2105 * kbtrans_setkey:
2106 2106 * Set individual keystation translation from old-style entry.
2107 2107 */
2108 2108 static int
2109 2109 kbtrans_setkey(struct kbtrans_lower *lower, struct kiockey *key, cred_t *cr)
2110 2110 {
2111 2111 int strtabindex, i;
2112 2112 unsigned short *ke;
2113 2113 register int tablemask;
2114 2114 register ushort_t entry;
2115 2115 register struct keyboard *kp;
2116 2116
2117 2117 kp = lower->kbtrans_keyboard;
2118 2118
2119 2119 if (key->kio_station >= kp->k_keymap_size)
2120 2120
2121 2121 return (EINVAL);
2122 2122
2123 2123 if (lower->kbtrans_keyboard == NULL)
2124 2124
2125 2125 return (EINVAL);
2126 2126
2127 2127 tablemask = key->kio_tablemask;
2128 2128
2129 2129 switch (tablemask) {
2130 2130 case KIOCABORT1:
2131 2131 case KIOCABORT1A:
2132 2132 case KIOCABORT2:
2133 2133 i = secpolicy_console(cr);
2134 2134 if (i != 0)
2135 2135 return (i);
2136 2136
2137 2137 switch (tablemask) {
2138 2138 case KIOCABORT1:
2139 2139 kp->k_abort1 = key->kio_station;
2140 2140 break;
2141 2141 case KIOCABORT1A:
2142 2142 kp->k_abort1a = key->kio_station;
2143 2143 break;
2144 2144 case KIOCABORT2:
2145 2145 kp->k_abort2 = key->kio_station;
2146 2146 break;
2147 2147 }
2148 2148 return (0);
2149 2149 }
2150 2150
2151 2151 if (tablemask & ALTGRAPHMASK)
2152 2152 return (EINVAL);
2153 2153
2154 2154 ke = kbtrans_find_entry(lower, (uint_t)tablemask, key->kio_station);
2155 2155 if (ke == NULL)
2156 2156 return (EINVAL);
2157 2157
2158 2158 if (key->kio_entry >= (uchar_t)OLD_STRING &&
2159 2159 key->kio_entry <= (uchar_t)(OLD_STRING + 15)) {
2160 2160 strtabindex = key->kio_entry - OLD_STRING;
2161 2161 bcopy(key->kio_string,
2162 2162 lower->kbtrans_keystringtab[strtabindex], KTAB_STRLEN);
2163 2163 lower->kbtrans_keystringtab[strtabindex][KTAB_STRLEN-1] = '\0';
2164 2164 }
2165 2165
2166 2166 entry = key->kio_entry;
2167 2167
2168 2168 /*
2169 2169 * There's nothing we need do with OLD_ISOCHAR.
2170 2170 */
2171 2171 if (entry != OLD_ISOCHAR) {
2172 2172 if (entry & 0x80) {
2173 2173 if (entry >= OLD_FA_UMLAUT && entry <= OLD_FA_GRAVE)
2174 2174 entry = FA_CLASS + (entry & 0x0F) - 9;
2175 2175 else
2176 2176 entry =
2177 2177 special_old_to_new[entry >> 4 & 0x07]
2178 2178 + (entry & 0x0F);
2179 2179 }
2180 2180 }
2181 2181
2182 2182 *ke = entry;
2183 2183
2184 2184 return (0);
2185 2185 }
2186 2186
2187 2187
2188 2188 /*
2189 2189 * Map new special codes to old ones.
2190 2190 * Indexed by (new special code) >> 8; add (new special code) & 0xFF.
2191 2191 */
2192 2192 static uchar_t special_new_to_old[] = {
2193 2193 0, /* normal */
2194 2194 OLD_SHIFTKEYS, /* SHIFTKEYS */
2195 2195 OLD_BUCKYBITS, /* BUCKYBITS */
2196 2196 OLD_FUNNY, /* FUNNY */
2197 2197 OLD_FA_UMLAUT, /* FA_CLASS */
2198 2198 OLD_STRING, /* STRING */
2199 2199 OLD_LEFTFUNC, /* FUNCKEYS */
2200 2200 };
2201 2201
2202 2202
2203 2203 /*
2204 2204 * kbtrans_getkey:
2205 2205 * Get individual keystation translation as old-style entry.
2206 2206 */
2207 2207 static int
2208 2208 kbtrans_getkey(struct kbtrans_lower *lower, struct kiockey *key)
2209 2209 {
2210 2210 int strtabindex;
2211 2211 unsigned short *ke;
2212 2212 register ushort_t entry;
2213 2213 struct keyboard *kp;
2214 2214
2215 2215 kp = lower->kbtrans_keyboard;
2216 2216
2217 2217 if (key->kio_station >= kp->k_keymap_size)
2218 2218 return (EINVAL);
2219 2219
2220 2220 if (lower->kbtrans_keyboard == NULL)
2221 2221 return (EINVAL);
2222 2222
2223 2223 switch (key->kio_tablemask) {
2224 2224 case KIOCABORT1:
2225 2225 key->kio_station = kp->k_abort1;
2226 2226 return (0);
2227 2227 case KIOCABORT1A:
2228 2228 key->kio_station = kp->k_abort1a;
2229 2229 return (0);
2230 2230 case KIOCABORT2:
2231 2231 key->kio_station = kp->k_abort2;
2232 2232 return (0);
2233 2233 }
2234 2234
2235 2235 ke = kbtrans_find_entry(lower, (uint_t)key->kio_tablemask,
2236 2236 key->kio_station);
2237 2237 if (ke == NULL)
2238 2238 return (EINVAL);
2239 2239
2240 2240 entry = *ke;
2241 2241
2242 2242 if (entry & 0xFF00)
2243 2243 key->kio_entry =
2244 2244 special_new_to_old[(ushort_t)(entry & 0xFF00) >> 8]
2245 2245 + (entry & 0x00FF);
2246 2246 else {
2247 2247 if (entry & 0x80)
2248 2248 key->kio_entry = (ushort_t)OLD_ISOCHAR; /* you lose */
2249 2249 else
2250 2250 key->kio_entry = (ushort_t)entry;
2251 2251 }
2252 2252
2253 2253 if (entry >= STRING && entry <= (uchar_t)(STRING + 15)) {
2254 2254 strtabindex = entry - STRING;
2255 2255 bcopy(lower->kbtrans_keystringtab[strtabindex],
2256 2256 key->kio_string, KTAB_STRLEN);
2257 2257 }
2258 2258 return (0);
2259 2259 }
2260 2260
2261 2261
2262 2262 /*
2263 2263 * kbtrans_skey:
2264 2264 * Set individual keystation translation from new-style entry.
2265 2265 */
2266 2266 static int
2267 2267 kbtrans_skey(struct kbtrans_lower *lower, struct kiockeymap *key, cred_t *cr)
2268 2268 {
2269 2269 int strtabindex, i;
2270 2270 unsigned short *ke;
2271 2271 struct keyboard *kp;
2272 2272
2273 2273 kp = lower->kbtrans_keyboard;
2274 2274
2275 2275 if (key->kio_station >= kp->k_keymap_size) {
2276 2276 return (EINVAL);
2277 2277
2278 2278 }
2279 2279
2280 2280 if (lower->kbtrans_keyboard == NULL) {
2281 2281 return (EINVAL);
2282 2282 }
2283 2283
2284 2284 switch (key->kio_tablemask) {
2285 2285 case KIOCABORT1:
2286 2286 case KIOCABORT1A:
2287 2287 case KIOCABORT2:
2288 2288 i = secpolicy_console(cr);
2289 2289 if (i != 0)
2290 2290 return (i);
2291 2291 switch (key->kio_tablemask) {
2292 2292 case KIOCABORT1:
2293 2293 kp->k_abort1 = key->kio_station;
2294 2294 break;
2295 2295 case KIOCABORT1A:
2296 2296 kp->k_abort1a = key->kio_station;
2297 2297 break;
2298 2298 case KIOCABORT2:
2299 2299 kp->k_abort2 = key->kio_station;
2300 2300 break;
2301 2301 }
2302 2302 return (0);
2303 2303 }
2304 2304
2305 2305 ke = kbtrans_find_entry(lower, (uint_t)key->kio_tablemask,
2306 2306 key->kio_station);
2307 2307 if (ke == NULL)
2308 2308 return (EINVAL);
2309 2309
2310 2310 if (key->kio_entry >= STRING &&
2311 2311 key->kio_entry <= (ushort_t)(STRING + 15)) {
2312 2312 strtabindex = key->kio_entry-STRING;
2313 2313 bcopy(key->kio_string,
2314 2314 lower->kbtrans_keystringtab[strtabindex], KTAB_STRLEN);
2315 2315 lower->kbtrans_keystringtab[strtabindex][KTAB_STRLEN-1] = '\0';
2316 2316 }
2317 2317
2318 2318 *ke = key->kio_entry;
2319 2319
2320 2320 return (0);
2321 2321 }
2322 2322
2323 2323
2324 2324 /*
2325 2325 * kbtrans_gkey:
2326 2326 * Get individual keystation translation as new-style entry.
2327 2327 */
2328 2328 static int
2329 2329 kbtrans_gkey(struct kbtrans_lower *lower, struct kiockeymap *key)
2330 2330 {
2331 2331 int strtabindex;
2332 2332 unsigned short *ke;
2333 2333 struct keyboard *kp;
2334 2334
2335 2335 kp = lower->kbtrans_keyboard;
2336 2336
2337 2337 if (key->kio_station >= kp->k_keymap_size)
2338 2338 return (EINVAL);
2339 2339
2340 2340 if (lower->kbtrans_keyboard == NULL)
2341 2341 return (EINVAL);
2342 2342
2343 2343 switch (key->kio_tablemask) {
2344 2344 case KIOCABORT1:
2345 2345 key->kio_station = kp->k_abort1;
2346 2346 return (0);
2347 2347 case KIOCABORT1A:
2348 2348 key->kio_station = kp->k_abort1a;
2349 2349 return (0);
2350 2350 case KIOCABORT2:
2351 2351 key->kio_station = kp->k_abort2;
2352 2352 return (0);
2353 2353 }
2354 2354
2355 2355 ke = kbtrans_find_entry(lower, (uint_t)key->kio_tablemask,
2356 2356 key->kio_station);
2357 2357 if (ke == NULL)
2358 2358 return (EINVAL);
2359 2359
2360 2360 key->kio_entry = *ke;
2361 2361
2362 2362 if (key->kio_entry >= STRING &&
2363 2363 key->kio_entry <= (ushort_t)(STRING + 15)) {
2364 2364 strtabindex = key->kio_entry-STRING;
2365 2365 bcopy(lower->kbtrans_keystringtab[strtabindex],
2366 2366 key->kio_string, KTAB_STRLEN);
2367 2367 }
2368 2368 return (0);
2369 2369 }
↓ open down ↓ |
2271 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX