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.
29 * Console kbd multiplexor driver for Sun.
30 * The console "zs" port is linked under us, with the "kbd" module pushed
32 * Minor device 0 is what programs normally use.
33 * Minor device 1 is used to feed predigested keystrokes to the "workstation
34 * console" driver, which it is linked beneath.
37 * This module can support multiple keyboards to be used simultaneously.
38 * and enable users to use at a time multiple keyboards connected to the
39 * same system. All the keyboards are linked under conskbd, and act as a
40 * keyboard with replicated keys.
42 * The DIN keyboards of SUN, for exmple , type 3/4/5, are supported via
43 * a two-level architecure. The lower one is one of serialport drivers, such
44 * as zs, se, and the upper is "kb" STREAMS module. Currenly, the serialport
45 * drivers don't support polled I/O interfaces, we couldn't group the keyboard
46 * of this kind under conskbd. So we do as the follows:
48 * A new ioctl CONSSETKBDTYPE interface between conskbd and lower
49 * keyboard drivers is added. When conskbd receives I_LINK or I_PLINK
50 * ioctl, it will send a CONSSETKBDTYPE ioctl to the driver which is
51 * requesting to be linked under conskbd. If the lower driver does't
52 * recognize this ioctl, the virtual keyboard will be disabled so that
53 * only one keyboard instance could be linked under conskbd.
55 #define KEYMAP_SIZE_VARIABLE
57 #include <sys/types.h>
58 #include <sys/param.h>
59 #include <sys/stropts.h>
60 #include <sys/stream.h>
61 #include <sys/strsubr.h>
62 #include <sys/strsun.h>
65 #include <sys/errno.h>
66 #include <sys/modctl.h>
69 #include <sys/sunddi.h>
70 #include <sys/consdev.h>
73 #include <sys/kstat.h>
74 #include <sys/policy.h>
76 #include <sys/kbtrans.h>
77 #include <sys/promif.h>
78 #include <sys/vuid_event.h>
79 #include <sys/conskbd.h>
82 extern struct keyboard
*kbtrans_usbkb_maptab_init(void);
83 extern void kbtrans_usbkb_maptab_fini(struct keyboard
**);
84 extern int ddi_create_internal_pathname(dev_info_t
*, char *, int, minor_t
);
87 * Module linkage routines for the kernel
89 static int conskbd_attach(dev_info_t
*, ddi_attach_cmd_t
);
90 static int conskbd_detach(dev_info_t
*, ddi_detach_cmd_t
);
91 static int conskbd_info(dev_info_t
*, ddi_info_cmd_t
, void *, void **);
94 * STREAMS queue processing procedures
96 static void conskbduwsrv(queue_t
*);
97 static void conskbdlwserv(queue_t
*);
98 static void conskbdlrput(queue_t
*, mblk_t
*);
99 static int conskbdclose(queue_t
*, int, cred_t
*);
100 static int conskbdopen(queue_t
*, dev_t
*, int, int, cred_t
*);
103 /* STREAMS driver id and limit value struct */
104 static struct module_info conskbdm_info
= {
106 "conskbd", /* mi_idname */
108 1024, /* mi_maxpsz */
114 * STREAMS queue processing procedure structures
116 /* upper read queue processing procedure structures */
117 static struct qinit conskbdurinit
= {
119 (int (*)())NULL
, /* qi_srvp */
120 conskbdopen
, /* qi_qopen */
121 conskbdclose
, /* qi_qclose */
122 (int (*)())NULL
, /* qi_qadmin */
123 &conskbdm_info
, /* qi_minfo */
127 /* upper write queue processing procedures structuresi */
128 static struct qinit conskbduwinit
= {
129 (int (*)())putq
, /* qi_putp */
130 (int (*)())conskbduwsrv
, /* qi_srvp */
131 conskbdopen
, /* qi_qopen */
132 conskbdclose
, /* qi_qclose */
133 (int (*)())NULL
, /* qi_qadmin */
134 &conskbdm_info
, /* qi_minfo */
138 /* lower read queue processing procedures structures */
139 static struct qinit conskbdlrinit
= {
140 (int (*)())conskbdlrput
, /* qi_putp */
141 (int (*)())NULL
, /* qi_srvp */
142 (int (*)())NULL
, /* qi_qopen */
143 (int (*)())NULL
, /* qi_qclose */
144 (int (*)())NULL
, /* qi_qadmin */
145 &conskbdm_info
, /* qi_minfo */
149 /* lower write processing procedures structures */
150 static struct qinit conskbdlwinit
= {
152 (int (*)())conskbdlwserv
, /* qi_srvp */
153 (int (*)())NULL
, /* qi_qopen */
154 (int (*)())NULL
, /* qi_qclose */
155 (int (*)())NULL
, /* qi_qadmin */
156 &conskbdm_info
, /* qi_minfo */
160 /* STREAMS entity declaration structure */
161 static struct streamtab conskbd_str_info
= {
162 &conskbdurinit
, /* st_rdinit */
163 &conskbduwinit
, /* st_wrinit */
164 &conskbdlrinit
, /* st_muxrinit */
165 &conskbdlwinit
, /* st_muxwinit */
169 /* Entry points structure */
170 static struct cb_ops cb_conskbd_ops
= {
171 nulldev
, /* cb_open */
172 nulldev
, /* cb_close */
173 nodev
, /* cb_strategy */
174 nodev
, /* cb_print */
177 nodev
, /* cb_write */
178 nodev
, /* cb_ioctl */
179 nodev
, /* cb_devmap */
181 nodev
, /* cb_segmap */
182 nochpoll
, /* cb_chpoll */
183 ddi_prop_op
, /* cb_prop_op */
184 &conskbd_str_info
, /* cb_stream */
185 D_MP
| D_MTOUTPERIM
| D_MTOCEXCL
/* cb_flag */
190 * Device operations structure
192 static struct dev_ops conskbd_ops
= {
193 DEVO_REV
, /* devo_rev */
195 conskbd_info
, /* devo_getinfo */
196 nulldev
, /* devo_identify */
197 nulldev
, /* devo_probe */
198 conskbd_attach
, /* devo_attach */
199 conskbd_detach
, /* devo_detach */
200 nodev
, /* devo_reset */
201 &(cb_conskbd_ops
), /* devo_cb_ops */
202 NULL
, /* devo_bus_ops */
203 NULL
, /* devo_power */
204 ddi_quiesce_not_needed
, /* quiesce */
208 * Module linkage information for the kernel.
210 static struct modldrv modldrv
= {
211 &mod_driverops
, /* Type of module. This one is a pseudo driver */
212 "conskbd multiplexer driver",
213 &conskbd_ops
, /* driver ops */
217 * Module linkage structure
219 static struct modlinkage modlinkage
= {
220 MODREV_1
, /* ml_rev */
221 &modldrv
, /* ml_linkage */
222 NULL
/* NULL terminates the list */
230 void conskbd_dprintf(const char *fmt
, ...);
231 #define DPRINTF(l, m, args) \
232 (((l) >= conskbd_errlevel) && ((m) & conskbd_errmask) ? \
233 conskbd_dprintf args : \
237 * Severity levels for printing
239 #define PRINT_L0 0 /* print every message */
240 #define PRINT_L1 1 /* debug */
241 #define PRINT_L2 2 /* quiet */
246 #define PRINT_MASK_ALL 0xFFFFFFFFU
247 uint_t conskbd_errmask
= PRINT_MASK_ALL
;
248 uint_t conskbd_errlevel
= PRINT_L2
;
251 #define DPRINTF(l, m, args) /* NOTHING */
256 * Module global data are protected by outer perimeter. Modifying
257 * these global data is executed in outer perimeter exclusively.
258 * Except in conskbdopen() and conskbdclose(), which are entered
259 * exclusively (Refer to D_MTOCEXCL flag), all changes for the
260 * global variables are protected by qwriter().
262 static queue_t
*conskbd_regqueue
; /* regular keyboard queue above us */
263 static queue_t
*conskbd_consqueue
; /* console queue above us */
266 static dev_info_t
*conskbd_dip
; /* private copy of devinfo pointer */
267 static long conskbd_idle_stamp
; /* seconds tstamp of latest keystroke */
268 static struct keyboard
*conskbd_keyindex
;
271 * Normally, kstats of type KSTAT_TYPE_NAMED have multiple elements. In
272 * this case we use this type for a single element because the ioctl code
273 * for it knows how to handle mixed kernel/user data models. Also, it
274 * will be easier to add new statistics later.
277 kstat_named_t idle_sec
; /* seconds since last keystroke */
279 { "idle_sec", KSTAT_DATA_LONG
, }
283 * Local routines prototypes
285 static int conskbd_kstat_update(kstat_t
*, int);
287 static void conskbd_ioctl(queue_t
*, mblk_t
*);
288 static void conskbd_ioc_plink(queue_t
*, mblk_t
*);
289 static void conskbd_ioc_punlink(queue_t
*, mblk_t
*);
290 static void conskbd_legacy_kbd_ioctl(queue_t
*, mblk_t
*);
291 static void conskbd_virtual_kbd_ioctl(queue_t
*, mblk_t
*);
292 static mblk_t
*conskbd_alloc_firm_event(ushort_t
, int);
294 static conskbd_pending_msg_t
*conskbd_mux_find_msg(mblk_t
*);
295 static void conskbd_mux_enqueue_msg(conskbd_pending_msg_t
*);
296 static void conskbd_mux_dequeue_msg(conskbd_pending_msg_t
*);
297 static void conskbd_link_lowque_virt(queue_t
*, mblk_t
*);
298 static void conskbd_link_lowque_legacy(queue_t
*, mblk_t
*);
300 static void conskbd_handle_downstream_msg(queue_t
*, mblk_t
*);
301 static void conskbd_kioctype_complete(conskbd_lower_queue_t
*, mblk_t
*);
302 static void conskbd_kioctrans_complete(conskbd_lower_queue_t
*, mblk_t
*);
303 static void conskbd_kioclayout_complete(conskbd_lower_queue_t
*, mblk_t
*);
304 static void conskbd_kiocsled_complete(conskbd_lower_queue_t
*, mblk_t
*);
305 static void conskbd_mux_upstream_msg(conskbd_lower_queue_t
*, mblk_t
*);
306 static void conskbd_legacy_upstream_msg(conskbd_lower_queue_t
*, mblk_t
*);
307 static void conskbd_lqs_ack_complete(conskbd_lower_queue_t
*, mblk_t
*);
309 static void conskbd_polledio_enter(cons_polledio_arg_t
);
310 static void conskbd_polledio_exit(cons_polledio_arg_t
);
311 static int conskbd_polledio_ischar(cons_polledio_arg_t
);
312 static int conskbd_polledio_getchar(cons_polledio_arg_t
);
313 static void conskbd_polledio_setled(struct kbtrans_hardware
*, int);
315 static void conskbd_streams_setled(struct kbtrans_hardware
*, int);
316 static boolean_t
conskbd_override_kbtrans(queue_t
*, mblk_t
*);
318 conskbd_polled_keycheck(struct kbtrans_hardware
*,
319 kbtrans_key_t
*, enum keystate
*);
322 * Callbacks needed by kbtrans
324 static struct kbtrans_callbacks conskbd_callbacks
= {
325 conskbd_streams_setled
,
326 conskbd_polledio_setled
,
327 conskbd_polled_keycheck
,
331 * Single private "global" lock for the few rare conditions
332 * we want single-threaded.
334 static kmutex_t conskbd_msgq_lock
;
335 static conskbd_pending_msg_t
*conskbd_msg_queue
;
338 * The software state structure of virtual keyboard.
339 * Currently, only one virtual keyboard is supported.
341 static conskbd_state_t conskbd
= { 0 };
343 /* This variable backs up the layout state for non-self-ID keyboards */
344 static int kbd_layout_bak
= 0;
350 * Driver initialization, called when driver is first loaded.
351 * This is how access is initially given to all the static structures.
357 * ddi_soft_state_init() status, see ddi_soft_state_init(9f), or
358 * mod_install() status, see mod_install(9f)
365 error
= mod_install(&modlinkage
);
370 conskbd_keyindex
= kbtrans_usbkb_maptab_init();
372 mutex_init(&conskbd_msgq_lock
, NULL
, MUTEX_DRIVER
, NULL
);
382 * Module de-initialization, called when the driver is to be unloaded.
388 * mod_remove() status, see mod_remove(9f)
395 error
= mod_remove(&modlinkage
);
398 mutex_destroy(&conskbd_msgq_lock
);
399 kbtrans_usbkb_maptab_fini(&conskbd_keyindex
);
409 * Module information, returns information about the driver.
412 * modinfo *modinfop Pointer to the opaque modinfo structure
415 * mod_info() status, see mod_info(9f)
418 _info(struct modinfo
*modinfop
)
420 return (mod_info(&modlinkage
, modinfop
));
429 * This routine creates two device nodes. One is the "kbd" node, which
430 * is used by user application programs(such as Xserver).The other is the
431 * "conskbd" node, which is an internal node. consconfig_dacf module will
432 * open this internal node, and link the conskbd under the wc (workstaion
436 * dev_info_t *dip Pointer to the device's dev_info struct
437 * ddi_attach_cmd_t cmd Attach command
440 * DDI_SUCCESS The driver was initialized properly
441 * DDI_FAILURE The driver couldn't be initialized properly
445 conskbd_attach(dev_info_t
*devi
, ddi_attach_cmd_t cmd
)
454 return (DDI_FAILURE
);
457 if ((ddi_create_minor_node(devi
, "kbd", S_IFCHR
,
458 0, DDI_PSEUDO
, 0) == DDI_FAILURE
) ||
459 (ddi_create_internal_pathname(devi
, "conskbd", S_IFCHR
,
460 1) == DDI_FAILURE
)) {
461 ddi_remove_minor_node(devi
, NULL
);
462 return (DDI_FAILURE
);
466 ksp
= kstat_create("conskbd", 0, "activity", "misc", KSTAT_TYPE_NAMED
,
467 sizeof (conskbd_kstat
) / sizeof (kstat_named_t
),
470 ksp
->ks_data
= (void *) &conskbd_kstat
;
471 ksp
->ks_update
= conskbd_kstat_update
;
473 conskbd_idle_stamp
= gethrestime_sec(); /* initial value */
476 conskbd
.conskbd_layout
= -1; /* invalid layout */
477 conskbd
.conskbd_led_state
= -1;
478 conskbd
.conskbd_bypassed
= B_FALSE
;
480 return (DDI_SUCCESS
);
482 } /* conskbd_attach() */
488 * Detach an instance of the conskbd driver. In fact, the driver can not
492 * dev_info_t *dip Pointer to the device's dev_info struct
493 * ddi_detach_cmd_t cmd Detach command
496 * DDI_SUCCESS The driver was detached
497 * DDI_FAILURE The driver couldn't be detached
501 conskbd_detach(dev_info_t
*devi
, ddi_detach_cmd_t cmd
)
503 return (DDI_FAILURE
);
505 } /* conskbd_detach() */
509 conskbd_info(dev_info_t
*dip
, ddi_info_cmd_t infocmd
, void *arg
,
515 case DDI_INFO_DEVT2DEVINFO
:
516 if (conskbd_dip
== NULL
) {
519 *result
= (void *) conskbd_dip
;
523 case DDI_INFO_DEVT2INSTANCE
:
532 } /* conskbd_info() */
536 conskbdopen(queue_t
*q
, dev_t
*devp
, int flag
, int sflag
, cred_t
*crp
)
541 unit
= getminor(*devp
);
545 * Opening "/dev/kbd".
547 conskbd_regqueue
= q
;
550 } else if (unit
!= 1) {
551 /* we don't do that under Bozo's Big Tent */
556 * Check if already initialized
558 if (conskbd_consqueue
!= NULL
)
562 * Opening the device to be linked under the console.
564 conskbd_consqueue
= q
;
566 if (secpolicy_console(crp
) != 0)
570 * initialize kbtrans module for conskbd
572 err
= kbtrans_streams_init(q
, sflag
, (struct kbtrans_hardware
*)
573 &conskbd
, &conskbd_callbacks
, &conskbd
.conskbd_kbtrans
, 0, 0);
576 kbtrans_streams_set_keyboard(conskbd
.conskbd_kbtrans
, KB_USB
,
579 conskbd
.conskbd_polledio
.cons_polledio_version
= CONSPOLLEDIO_V1
;
580 conskbd
.conskbd_polledio
.cons_polledio_argument
=
581 (cons_polledio_arg_t
)&conskbd
;
582 conskbd
.conskbd_polledio
.cons_polledio_putchar
= NULL
;
583 conskbd
.conskbd_polledio
.cons_polledio_getchar
=
584 (int (*)(cons_polledio_arg_t
)) conskbd_polledio_getchar
;
585 conskbd
.conskbd_polledio
.cons_polledio_ischar
=
586 (boolean_t (*)(cons_polledio_arg_t
))conskbd_polledio_ischar
;
587 conskbd
.conskbd_polledio
.cons_polledio_enter
= conskbd_polledio_enter
;
588 conskbd
.conskbd_polledio
.cons_polledio_exit
= conskbd_polledio_exit
;
593 } /* conskbdopen() */
598 conskbdclose(queue_t
*q
, int flag
, cred_t
*crp
)
600 if (q
== conskbd_regqueue
) {
602 conskbd_pending_msg_t
*pmsg
, *prev
, *next
;
605 /* switch the input stream back to conskbd_consqueue */
606 conskbd
.conskbd_directio
= B_FALSE
;
608 kbtrans_streams_untimeout(conskbd
.conskbd_kbtrans
);
609 kbtrans_streams_set_queue(conskbd
.conskbd_kbtrans
,
612 conskbd_regqueue
= NULL
;
615 * If there are any pending ioctls which conskbd hasn't
616 * responded to yet, remove them from conskbd_msg_queue.
617 * Otherwise, we might send the response to a nonexistent
618 * closed queue. Refer to: conskbd_mux_upstream_msg().
620 for (prev
= NULL
, pmsg
= conskbd_msg_queue
; pmsg
!= NULL
;
622 next
= pmsg
->kpm_next
;
623 if (pmsg
->kpm_upper_queue
== WR(q
)) {
625 conskbd_msg_queue
= next
;
627 prev
->kpm_next
= next
;
629 while (pmsg
->kpm_resp_list
!= NULL
) {
630 mp
= pmsg
->kpm_resp_list
;
631 pmsg
->kpm_resp_list
= mp
->b_next
;
632 mp
->b_next
= mp
->b_prev
= NULL
;
635 mutex_destroy(&pmsg
->kpm_lock
);
636 kmem_free(pmsg
, sizeof (*pmsg
));
641 } else if (q
== conskbd_consqueue
) {
643 * Well, this is probably a mistake, but we will permit you
644 * to close the path to the console if you really insist.
647 conskbd_consqueue
= NULL
;
652 } /* conskbdclose() */
655 * Service procedure for upper write queue.
656 * To make sure the order of messages, we don't process any
657 * message in qi_putq() routine of upper write queue, instead the
658 * qi_putq() routine, which is a standard putq() routine, puts all
659 * messages into a queue, and lets the following service procedure
660 * deal with all messages.
661 * This routine is invoked when ioctl commands are send down
662 * by a consumer of the keyboard device, eg, when the keyboard
663 * consumer tries to determine the keyboard layout type, or sets
667 conskbduwsrv(queue_t
*q
)
671 enum kbtrans_message_response ret
;
672 struct copyresp
*csp
;
673 struct freq_request
*frqp
;
676 while ((mp
= getq(q
)) != NULL
) {
679 * if the virtual keyboard is supported
681 if (conskbd
.conskbd_bypassed
== B_FALSE
) {
683 if (conskbd_override_kbtrans(q
, mp
) == B_TRUE
)
686 * The conskbd driver is a psaudo driver. It has two
687 * devcice nodes, one is used by kernel, and the other
688 * is used by end-users. There are two STREAMS queues
689 * corresponding to the two device nodes, console queue
691 * In conskbd_override_kbtrans() routine, when receives
692 * KIOCSDIRECT ioctl, we need change the direction of
693 * keyboard input messages, and direct the input stream
694 * from keyboard into right queue. It causes this queue
695 * to be switched between regular queue and console
696 * queue. And here, in this routine, the in-parameter
697 * "q" can be any one of the two. Moreover, this module
698 * is executed in multithreaded environment, even if the
699 * q is switched to regular queue, it is possible that
700 * the in-parameter is still the console queue, and we
701 * need to return response to right queue.
702 * The response is sent to upstream by the kbtrans
703 * module. so we need to save the old queue, and wait
704 * kbtrans to proces message and to send response out,
705 * and then switch back to old queue.
707 oldq
= kbtrans_streams_get_queue(
708 conskbd
.conskbd_kbtrans
);
709 kbtrans_streams_set_queue(
710 conskbd
.conskbd_kbtrans
, RD(q
));
711 ret
= kbtrans_streams_message(
712 conskbd
.conskbd_kbtrans
, mp
);
713 kbtrans_streams_set_queue(
714 conskbd
.conskbd_kbtrans
, oldq
);
717 case KBTRANS_MESSAGE_HANDLED
:
719 case KBTRANS_MESSAGE_NOT_HANDLED
:
724 switch (mp
->b_datap
->db_type
) {
727 conskbd_ioctl(q
, mp
);
731 if (*mp
->b_rptr
& FLUSHW
) {
732 flushq(q
, FLUSHDATA
);
735 * here, if flush read queue, some key-up messages
736 * may be lost so that upper module or applications
737 * treat corresponding keys as being held down for
745 * virtual keyboard doesn't support this interface.
746 * only when it is disabled, we pass the message
747 * down to lower queue.
749 if ((conskbd
.conskbd_bypassed
) &&
750 (conskbd
.conskbd_lqueue_nums
> 0)) {
751 if (putq(conskbd
.conskbd_lqueue_list
->
761 * Only deal with copyresp to KIOCSETFREQ
762 * transparent ioctl now
764 csp
= (struct copyresp
*)mp
->b_rptr
;
766 miocnak(q
, mp
, 0, EINVAL
);
771 switch (csp
->cp_cmd
) {
773 frqp
= (struct freq_request
*)mp
->
776 switch (frqp
->type
) {
778 error
= beeper_freq(BEEP_CONSOLE
,
783 error
= beeper_freq(BEEP_TYPE4
,
798 miocack(q
, mp
, 0, 0);
800 miocnak(q
, mp
, 0, EINVAL
);
806 * Pass an error message up.
808 mp
->b_datap
->db_type
= M_ERROR
;
813 mp
->b_rptr
= mp
->b_datap
->db_base
;
814 mp
->b_wptr
= mp
->b_rptr
+ sizeof (char);
815 *mp
->b_rptr
= EINVAL
;
820 } /* conskbduwsrv() */
823 conskbd_ioctl(queue_t
*q
, mblk_t
*mp
)
828 iocp
= (struct iocblk
*)mp
->b_rptr
;
830 switch (iocp
->ioc_cmd
) {
834 if (conskbd
.conskbd_bypassed
== B_TRUE
) {
836 * A legacy keyboard can NOT be connected to conskbd together
837 * with other keyboards. So when a legacy keyboard is already
838 * linked under conkbd, we just reject all others.
840 miocnak(q
, mp
, 0, EAGAIN
);
843 qwriter(q
, mp
, conskbd_ioc_plink
, PERIM_OUTER
);
848 qwriter(q
, mp
, conskbd_ioc_punlink
, PERIM_OUTER
);
853 * Check if privileged
855 if ((error
= secpolicy_sys_config(iocp
->ioc_cr
, B_FALSE
))) {
856 miocnak(q
, mp
, 0, error
);
860 error
= miocpullup(mp
, sizeof (int));
862 miocnak(q
, mp
, 0, error
);
866 abort_enable
= *(int *)mp
->b_cont
->b_rptr
;
867 miocack(q
, mp
, 0, 0);
871 if (iocp
->ioc_count
!= TRANSPARENT
) {
873 * We don't support non-transparent ioctls,
876 miocnak(q
, mp
, 0, EINVAL
);
878 /* Transparent ioctl */
879 mcopyin(mp
, NULL
, sizeof (struct freq_request
), NULL
);
885 if (conskbd
.conskbd_bypassed
== B_TRUE
) {
886 conskbd_legacy_kbd_ioctl(q
, mp
);
888 conskbd_virtual_kbd_ioctl(q
, mp
);
892 } /* conskbd_ioctl() */
896 conskbd_virtual_kbd_ioctl(queue_t
*q
, mblk_t
*mp
)
903 iocp
= (struct iocblk
*)mp
->b_rptr
;
905 switch (iocp
->ioc_cmd
) {
907 if ((datap
= allocb(sizeof (int), BPRI_HI
)) == NULL
) {
908 miocnak(q
, mp
, 0, ENOMEM
);
912 if (conskbd
.conskbd_layout
== -1)
913 *(int *)datap
->b_wptr
= KBTRANS_USBKB_DEFAULT_LAYOUT
;
915 *(int *)datap
->b_wptr
= conskbd
.conskbd_layout
;
917 datap
->b_wptr
+= sizeof (int);
921 miocack(q
, mp
, sizeof (int), 0);
925 if (iocp
->ioc_count
!= TRANSPARENT
) {
926 miocnak(q
, mp
, 0, EINVAL
);
929 kbd_layout_bak
= conskbd
.conskbd_layout
;
930 conskbd
.conskbd_layout
= *(intptr_t *)(mp
->b_cont
->b_rptr
);
931 if (conskbd
.conskbd_layout
!= kbd_layout_bak
) {
933 /* notify the upper of the change event */
934 if ((datap
= conskbd_alloc_firm_event(
935 KEYBOARD_LAYOUT_CHANGE
,
936 conskbd
.conskbd_layout
)) != NULL
) {
937 if (conskbd
.conskbd_directio
) {
938 putnext(conskbd_regqueue
, datap
);
944 miocack(q
, mp
, 0, 0);
947 case CONSOPENPOLLEDIO
:
948 error
= miocpullup(mp
, sizeof (struct cons_polledio
*));
950 miocnak(q
, mp
, 0, error
);
953 if (conskbd
.conskbd_lqueue_list
== NULL
) {
954 miocnak(q
, mp
, 0, EINVAL
);
957 conskbd_handle_downstream_msg(q
, mp
);
960 case CONSCLOSEPOLLEDIO
:
961 if (conskbd
.conskbd_lqueue_list
== NULL
) {
962 miocnak(q
, mp
, 0, EINVAL
);
965 conskbd_handle_downstream_msg(q
, mp
);
968 case CONSSETABORTENABLE
:
970 * To enable combined STOP-A(or F1-A) to trap into kmdb,
971 * the lower physical keyboard drivers are always told not
972 * to parse abort sequence(refer to consconfig_dacf module).
973 * Instead, lower drivers always send all keydown & keyup
974 * messages up to conskbd, so that when key STOP(or F1) is
975 * pressed on one keyboard and key A is pressed on another
976 * keyboard, the system could trap into kmdb.
978 * When we by kbtrans_streams_message() invoked kbtrans to
979 * handle ioctls in conskbduwsrv() routine, kbtrans module
980 * already handle the message though it returned to us a
981 * KBTRANS_MESSAGE_NOT_HANDLED. For virtual keyboard, no
982 * special initialization or un-initialization is needed.
983 * So we just return ACK to upper module.
985 miocack(q
, mp
, 0, 0);
990 if (conskbd
.conskbd_lqueue_list
== NULL
||
991 mp
->b_cont
== NULL
) {
992 miocnak(q
, mp
, 0, EINVAL
);
995 cmd
= *(int *)mp
->b_cont
->b_rptr
;
996 if (cmd
== KBD_CMD_GETLAYOUT
) {
998 datap
= allocb(sizeof (int), BPRI_HI
);
1000 miocnak(q
, mp
, 0, ENOMEM
);
1003 if (conskbd
.conskbd_layout
== -1)
1004 *(int *)datap
->b_wptr
=
1005 KBTRANS_USBKB_DEFAULT_LAYOUT
;
1007 *(int *)datap
->b_wptr
= conskbd
.conskbd_layout
;
1010 miocack(q
, mp
, sizeof (int), 0);
1013 conskbd_handle_downstream_msg(q
, mp
);
1017 miocnak(q
, mp
, 0, EINVAL
);
1021 } /* conskbd_virtual_kbd_ioctl() */
1024 conskbd_legacy_kbd_ioctl(queue_t
*q
, mblk_t
*mp
)
1026 conskbd_lower_queue_t
*lq
;
1027 struct iocblk
*iocp
;
1030 iocp
= (struct iocblk
*)mp
->b_rptr
;
1032 ASSERT(conskbd
.conskbd_lqueue_nums
== 1);
1033 switch (iocp
->ioc_cmd
) {
1038 if ((datap
= allocb(sizeof (int), BPRI_MED
)) == NULL
) {
1039 miocnak(q
, mp
, 0, ENOMEM
);
1043 *(int *)datap
->b_wptr
= conskbd
.conskbd_directio
;
1044 datap
->b_wptr
+= sizeof (int);
1045 if (mp
->b_cont
!= NULL
) {
1046 freemsg(mp
->b_cont
);
1050 miocack(q
, mp
, sizeof (int), 0);
1055 error
= miocpullup(mp
, sizeof (int));
1057 miocnak(q
, mp
, 0, error
);
1060 conskbd
.conskbd_directio
= *(int *)mp
->b_cont
->b_rptr
;
1063 * Pass this through, if there's something to pass
1064 * it through to, so the system keyboard can reset
1067 if (conskbd
.conskbd_lqueue_nums
> 0) {
1068 lq
= conskbd
.conskbd_lqueue_list
;
1069 ASSERT(lq
&& lq
->lqs_next
== NULL
);
1070 if (putq(lq
->lqs_queue
, mp
) != 1) {
1071 miocnak(q
, mp
, 0, ENOMEM
);
1077 miocack(q
, mp
, 0, 0);
1082 * Pass this through, if there's something to pass it
1083 * through to; otherwise, reject it.
1085 if (conskbd
.conskbd_lqueue_nums
> 0) {
1086 lq
= conskbd
.conskbd_lqueue_list
;
1087 ASSERT(lq
&& lq
->lqs_next
== NULL
);
1088 if (putq(lq
->lqs_queue
, mp
) != 1) {
1089 miocnak(q
, mp
, 0, ENOMEM
);
1095 /* nobody below us; reject it */
1096 miocnak(q
, mp
, 0, EINVAL
);
1100 } /* conskbd_legacy_kbd_ioctl() */
1104 * Service procedure for lower write queue.
1105 * Puts things on the queue below us, if it lets us.
1108 conskbdlwserv(queue_t
*q
)
1110 register mblk_t
*mp
;
1112 while (canput(q
->q_next
) && (mp
= getq(q
)) != NULL
)
1115 } /* conskbdlwserv() */
1118 * Put procedure for lower read queue.
1119 * Pass everything up to minor device 0 if "directio" set, otherwise to minor
1123 conskbdlrput(queue_t
*q
, mblk_t
*mp
)
1125 conskbd_lower_queue_t
*lqs
;
1126 struct iocblk
*iocp
;
1129 DPRINTF(PRINT_L1
, PRINT_MASK_ALL
, ("conskbdlrput\n"));
1131 switch (mp
->b_datap
->db_type
) {
1134 if (*mp
->b_rptr
== FLUSHR
) {
1135 flushq(q
, FLUSHDATA
); /* XXX doesn't flush M_DELAY */
1136 *mp
->b_rptr
&= ~FLUSHR
; /* it has been flushed */
1138 if (*mp
->b_rptr
== FLUSHW
) {
1139 flushq(WR(q
), FLUSHDATA
);
1140 qreply(q
, mp
); /* give the read queues a crack at it */
1146 if (conskbd
.conskbd_bypassed
== B_FALSE
) {
1148 fe
= (Firm_event
*)mp
->b_rptr
;
1151 * This is a workaround.
1153 * According to HID specification, there are the
1154 * following keycode mapping between PS2 and USB,
1156 * PS2 AT-101 keycode(29) ---> USB(49)
1157 * PS2 AT-102 keycode(42) ---> USB(50)
1159 * However, the two keys, AT-101(29) and AT-102(42),
1160 * have the same scancode,0x2B, in PS2 scancode SET1
1161 * which we are using. The Kb8042 driver always
1162 * recognizes the two keys as PS2(29) so that we could
1163 * not know which is being pressed or released when we
1164 * receive scancode 0x2B. Fortunately, the two keys can
1165 * not co-exist in a specific layout. In other words,
1166 * in the table of keycode-to-symbol mapping, either
1167 * entry 49 or 50 is a hole. So, if we're processing a
1168 * keycode 49, we look at the entry for 49. If it's
1169 * HOLE, remap the key to 50; If we're processing a 50,
1170 * look at the entry for 50. If it's HOLE, we remap
1173 if (fe
->id
== 49 || fe
->id
== 50) {
1174 if (conskbd_keyindex
->k_normal
[50] == HOLE
)
1181 * Remember key state of each key of lower physical
1182 * keyboard. When a keyboard is umplumbed from conskbd,
1183 * we will check all key states. By then, we will fake
1184 * a KEY_RELEASED message for each key in KEY_PRESSED
1185 * state. Otherwise, upper module will treat these keys
1186 * as held-down for ever.
1188 iocp
= (struct iocblk
*)mp
->b_rptr
;
1189 lqs
= (conskbd_lower_queue_t
*)q
->q_ptr
;
1191 lqs
->lqs_key_state
[fe
->id
] = KEY_PRESSED
;
1193 lqs
->lqs_key_state
[fe
->id
] = KEY_RELEASED
;
1195 kbtrans_streams_key(conskbd
.conskbd_kbtrans
,
1196 fe
->id
, fe
->value
? KEY_PRESSED
: KEY_RELEASED
);
1199 if (conskbd
.conskbd_directio
)
1200 putnext(conskbd_regqueue
, mp
);
1201 else if (conskbd_consqueue
!= NULL
)
1202 putnext(conskbd_consqueue
, mp
);
1206 conskbd_idle_stamp
= gethrestime_sec();
1211 iocp
= (struct iocblk
*)mp
->b_rptr
;
1212 lqs
= (conskbd_lower_queue_t
*)q
->q_ptr
;
1214 DPRINTF(PRINT_L1
, PRINT_MASK_ALL
, ("conskbdlrput: "
1215 "ACK/NAK - cmd 0x%x\n", iocp
->ioc_cmd
));
1217 conskbd_lqs_ack_complete(lqs
, mp
);
1223 freemsg(mp
); /* anything useful here? */
1227 } /* conskbdlrput() */
1232 conskbd_kstat_update(kstat_t
*ksp
, int rw
)
1234 if (rw
== KSTAT_WRITE
)
1237 conskbd_kstat
.idle_sec
.value
.l
= gethrestime_sec() - conskbd_idle_stamp
;
1241 } /* conskbd_kstat_update() */
1244 * STREAMS architecuture provides guarantee that the ID of each
1245 * message, iocblk.ioc_id, in a stream is unique. The following
1246 * routine performes the task: When receive request from upstream,
1247 * it saves the request in a global link list, clones the request,
1248 * and then sends a copy of the request to each of lower queues
1249 * which are plumbed into conskbd. And then, when receives responses
1250 * from lower queues in conskbdlrput() routine, we can know the
1251 * request matching received responses by searching the global linked
1252 * list to find the request which has the same message ID of the
1253 * response. Then, when all lower queues response this request, we
1254 * give a response to upstreams based the following policy:
1255 * If any one of lower queues acks our reuqest, then we return ack
1256 * to upstreams; only if all lower queues nak our request, we return
1257 * nak to upstreams. If all responses are nak, the error number of
1258 * the first response is sent to upstream.
1261 conskbd_handle_downstream_msg(queue_t
*q
, mblk_t
*mp
)
1263 conskbd_pending_msg_t
*msg
;
1264 conskbd_lower_queue_t
*lqs
;
1265 struct iocblk
*iocp
;
1269 if (conskbd
.conskbd_lqueue_nums
== 0) {
1270 miocnak(q
, mp
, 0, EINVAL
);
1274 msg
= (conskbd_pending_msg_t
*)
1275 kmem_zalloc(sizeof (conskbd_pending_msg_t
), KM_SLEEP
);
1276 mutex_init(&msg
->kpm_lock
, NULL
, MUTEX_DRIVER
, NULL
);
1277 lqs
= conskbd
.conskbd_lqueue_list
;
1278 iocp
= (struct iocblk
*)mp
->b_rptr
;
1280 ASSERT(iocp
->ioc_cmd
== CONSOPENPOLLEDIO
||
1281 iocp
->ioc_cmd
== CONSCLOSEPOLLEDIO
||
1282 iocp
->ioc_cmd
== KIOCCMD
||
1283 iocp
->ioc_cmd
== KIOCMKTONE
);
1285 msg
->kpm_upper_queue
= q
;
1286 msg
->kpm_req_msg
= mp
;
1287 msg
->kpm_req_id
= iocp
->ioc_id
;
1288 msg
->kpm_req_cmd
= iocp
->ioc_cmd
;
1289 msg
->kpm_req_nums
= conskbd
.conskbd_lqueue_nums
;
1290 conskbd_mux_enqueue_msg(msg
);
1292 for (retry
= 0, lqs
= conskbd
.conskbd_lqueue_list
; lqs
; ) {
1295 * if a lower physical keyboard is not in polled I/O
1296 * mode, we couldn't send CONSCLOSEPOLLEDIO to it,
1297 * otherwise, system will panic.
1299 if (iocp
->ioc_cmd
== CONSCLOSEPOLLEDIO
&&
1300 lqs
->lqs_polledio
== NULL
) {
1301 lqs
= lqs
->lqs_next
;
1302 msg
->kpm_req_nums
--;
1307 clonemp
= copymsg(mp
);
1308 if (clonemp
!= NULL
) {
1309 if (putq(lqs
->lqs_queue
, clonemp
) == 1) {
1310 lqs
= lqs
->lqs_next
;
1316 * failed to invoke putq(), retry.
1322 * During testing it was observed that occasionally
1323 * copymsg() would fail during boot. The reason for
1324 * these failures is unknown. Since we really want
1325 * to successfully plumb up all the attached keyboards
1326 * during boot we do a best effort here by retrying
1327 * the copymsg() call in the hopes that it will
1328 * succeeded upon subsequent invocations.
1330 * If all the calls to copymsg() fails, it will cause
1331 * the corresponding keyboard to be unavailable, or
1332 * or behave weirdly,
1334 * 1) for CONSOPENPOLLEDIO
1335 * if copymsg()fails, the corresponding keyboard
1336 * is not available in polled I/O mode once
1338 * 2) for CONSCLOSEPOLLEDIO
1339 * if copymsg() fails, the corresponding keyboard
1340 * is not available in normal mode once returning
1343 * 3.1) for KBD_CMD_NOBELL
1344 * there's no beep in USB and PS2 keyboard,
1345 * this ioctl actually disables the beep on
1346 * system mainboard. Note that all the cloned
1347 * messages sent down to lower queues do the
1348 * same job for system mainboard. Therefore,
1349 * even if we fail to send this ioctl to most
1350 * of lower queues, the beep still would be
1351 * disabled. So, no trouble exists here.
1355 * However, all cases could be resume next time when the
1356 * same request comes again.
1358 if (retry
++ >= 5) {
1360 char path
[MAXPATHLEN
+ 1];
1362 devt
= lqs
->lqs_queue
->q_stream
->sd_vnode
->v_rdev
;
1363 switch (iocp
->ioc_cmd
) {
1364 case CONSOPENPOLLEDIO
:
1365 if (ddi_dev_pathname(devt
, S_IFCHR
,
1366 path
) == DDI_SUCCESS
)
1367 cmn_err(CE_WARN
, "conskbd: "
1368 "keyboard is not available"
1369 " for system debugging: %s",
1373 case CONSCLOSEPOLLEDIO
:
1374 if (ddi_dev_pathname(devt
, S_IFCHR
,
1375 path
) == DDI_SUCCESS
)
1376 cmn_err(CE_WARN
, "conskbd: "
1377 "keyboard is not available:"
1384 msg
->kpm_req_nums
--;
1385 lqs
= lqs
->lqs_next
;
1390 if (msg
->kpm_req_nums
== 0) {
1391 conskbd_mux_dequeue_msg(msg
);
1392 kmem_free(msg
, sizeof (*msg
));
1393 miocnak(q
, mp
, 0, ENOMEM
);
1396 } /* conskbd_handle_downstream_msg() */
1400 conskbd_ioc_plink(queue_t
*q
, mblk_t
*mp
)
1404 struct linkblk
*linkp
;
1405 conskbd_lower_queue_t
*lqs
;
1407 lqs
= kmem_zalloc(sizeof (*lqs
), KM_SLEEP
);
1408 ASSERT(lqs
->lqs_state
== LQS_UNINITIALIZED
);
1410 linkp
= (struct linkblk
*)mp
->b_cont
->b_rptr
;
1411 lowque
= linkp
->l_qbot
;
1413 lqs
->lqs_queue
= lowque
;
1414 lqs
->lqs_pending_plink
= mp
;
1415 lqs
->lqs_pending_queue
= q
;
1417 req
= mkiocb(CONSSETKBDTYPE
);
1419 miocnak(q
, mp
, 0, ENOMEM
);
1420 kmem_free(lqs
, sizeof (*lqs
));
1424 req
->b_cont
= allocb(sizeof (int), BPRI_MED
);
1425 if (req
->b_cont
== NULL
) {
1427 miocnak(q
, mp
, 0, ENOMEM
);
1428 kmem_free(lqs
, sizeof (*lqs
));
1432 lowque
->q_ptr
= lqs
;
1433 OTHERQ(lowque
)->q_ptr
= lqs
;
1434 *(int *)req
->b_cont
->b_wptr
= KB_USB
;
1435 req
->b_cont
->b_wptr
+= sizeof (int);
1437 lqs
->lqs_state
= LQS_KIOCTYPE_ACK_PENDING
;
1439 if (putq(lowque
, req
) != 1) {
1441 miocnak(lqs
->lqs_pending_queue
,
1442 lqs
->lqs_pending_plink
, 0, ENOMEM
);
1443 lowque
->q_ptr
= NULL
;
1444 OTHERQ(lowque
)->q_ptr
= NULL
;
1445 kmem_free(lqs
, sizeof (*lqs
));
1448 } /* conskbd_ioc_plink() */
1452 conskbd_ioc_punlink(queue_t
*q
, mblk_t
*mp
)
1455 struct linkblk
*linkp
;
1456 conskbd_lower_queue_t
*lqs
;
1457 conskbd_lower_queue_t
*prev
;
1459 linkp
= (struct linkblk
*)mp
->b_cont
->b_rptr
;
1460 prev
= conskbd
.conskbd_lqueue_list
;
1461 for (lqs
= prev
; lqs
; lqs
= lqs
->lqs_next
) {
1462 if (lqs
->lqs_queue
== linkp
->l_qbot
) {
1464 conskbd
.conskbd_lqueue_list
=
1467 prev
->lqs_next
= lqs
->lqs_next
;
1469 lqs
->lqs_queue
->q_ptr
= NULL
;
1470 OTHERQ(lqs
->lqs_queue
)->q_ptr
= NULL
;
1471 conskbd
.conskbd_lqueue_nums
--;
1472 if (conskbd
.conskbd_lqueue_nums
== 0) {
1473 kbd_layout_bak
= conskbd
.conskbd_layout
;
1474 conskbd
.conskbd_layout
= -1;
1477 for (index
= 0; index
< KBTRANS_KEYNUMS_MAX
; index
++) {
1478 if (lqs
->lqs_key_state
[index
] == KEY_PRESSED
)
1479 kbtrans_streams_key(
1480 conskbd
.conskbd_kbtrans
,
1485 kmem_free(lqs
, sizeof (*lqs
));
1486 miocack(q
, mp
, 0, 0);
1491 miocnak(q
, mp
, 0, EINVAL
);
1493 } /* conskbd_ioc_punlink() */
1496 * Every physical keyboard has a corresponding STREAMS queue. We call this
1497 * queue lower queue. Every lower queue has a state, refer to conskbd.h file
1498 * about "enum conskbd_lqs_state".
1499 * The following routine is used to handle response messages from lower queue.
1500 * When receiving ack/nak message from lower queue(s), the routine determines
1501 * the passage for it according to the current state of this lower queue.
1504 conskbd_lqs_ack_complete(conskbd_lower_queue_t
*lqs
, mblk_t
*mp
)
1506 switch (lqs
->lqs_state
) {
1508 /* S6: working in virtual keyboard mode, multi-keyboards are usable */
1509 case LQS_INITIALIZED
:
1510 conskbd_mux_upstream_msg(lqs
, mp
);
1513 /* S5: working in legacy mode, only one keyboard is usable */
1514 case LQS_INITIALIZED_LEGACY
:
1515 conskbd_legacy_upstream_msg(lqs
, mp
);
1518 /* S4: wait lower queue to acknowledge KIOCSLED/KIOCGLED message */
1519 case LQS_KIOCSLED_ACK_PENDING
:
1520 conskbd_kiocsled_complete(lqs
, mp
);
1523 /* S3: wait lower queue to acknowledge KIOCLAYOUT message */
1524 case LQS_KIOCLAYOUT_ACK_PENDING
:
1525 conskbd_kioclayout_complete(lqs
, mp
);
1528 /* S2: wait lower queue to acknowledge KIOCTRANS message */
1529 case LQS_KIOCTRANS_ACK_PENDING
:
1530 conskbd_kioctrans_complete(lqs
, mp
);
1533 /* S1: wait lower queue to acknowledge KIOCTYPE message */
1534 case LQS_KIOCTYPE_ACK_PENDING
:
1535 conskbd_kioctype_complete(lqs
, mp
);
1538 /* if reaching here, there must be a error */
1541 cmn_err(CE_WARN
, "conskbd: lqs_ack_complete() state error");
1545 } /* conskbd_lqs_ack_complete() */
1549 conskbd_kioctype_complete(conskbd_lower_queue_t
*lqs
, mblk_t
*mp
)
1551 struct iocblk
*iocp
;
1556 ASSERT(lqs
->lqs_pending_plink
);
1557 ASSERT(lqs
->lqs_state
== LQS_KIOCTYPE_ACK_PENDING
);
1559 lowerque
= lqs
->lqs_queue
;
1561 switch (mp
->b_datap
->db_type
) {
1563 req
= mkiocb(KIOCTRANS
);
1568 req
->b_cont
= allocb(sizeof (int), BPRI_MED
);
1569 if (req
->b_cont
== NULL
) {
1574 /* Set the translate mode to TR_UNTRANS_EVENT */
1575 *(int *)req
->b_cont
->b_wptr
= TR_UNTRANS_EVENT
;
1576 req
->b_cont
->b_wptr
+= sizeof (int);
1578 /* Ready to handle the response to KIOCTRANS */
1579 lqs
->lqs_state
= LQS_KIOCTRANS_ACK_PENDING
;
1581 if (putq(lowerque
, req
) != 1) {
1590 * The lower keyboard driver can't mimic USB keyboard,
1591 * that's say, the physical keyboard is an old one, such
1592 * as TYPE 3/4/5 one. In this case, the virtual keyboard
1593 * is disabled, and the data from lower keyboard driver
1594 * will bypass the conskbd module.
1598 * if there is any other keyborad already linked under the
1599 * conskbd, we reject the current one.
1601 if (conskbd
.conskbd_lqueue_nums
> 0) {
1602 iocp
= (struct iocblk
*)mp
->b_rptr
;
1603 err
= iocp
->ioc_error
;
1608 * link this keyboard under conskbd.
1610 qwriter(lowerque
, mp
, conskbd_link_lowque_legacy
, PERIM_OUTER
);
1615 miocnak(lqs
->lqs_pending_queue
, lqs
->lqs_pending_plink
, 0, err
);
1616 lowerque
->q_ptr
= NULL
;
1617 OTHERQ(lowerque
)->q_ptr
= NULL
;
1618 kmem_free(lqs
, sizeof (*lqs
));
1621 } /* conskbd_kioctype_complete() */
1624 conskbd_kioctrans_complete(conskbd_lower_queue_t
*lqs
, mblk_t
*mp
)
1626 struct iocblk
*iocp
;
1631 ASSERT(lqs
->lqs_pending_plink
!= NULL
);
1632 ASSERT(lqs
->lqs_state
== LQS_KIOCTRANS_ACK_PENDING
);
1634 lowerque
= lqs
->lqs_queue
;
1636 switch (mp
->b_datap
->db_type
) {
1638 req
= mkiocb(KIOCLAYOUT
);
1643 req
->b_cont
= allocb(sizeof (int), BPRI_MED
);
1644 if (req
->b_cont
== NULL
) {
1649 /* waiting for response to KIOCLAYOUT */
1650 lqs
->lqs_state
= LQS_KIOCLAYOUT_ACK_PENDING
;
1651 if (putq(lqs
->lqs_queue
, req
) != 1) {
1659 iocp
= (struct iocblk
*)mp
->b_rptr
;
1660 err
= iocp
->ioc_error
;
1665 miocnak(lqs
->lqs_pending_queue
, lqs
->lqs_pending_plink
, 0, err
);
1666 lowerque
->q_ptr
= NULL
;
1667 OTHERQ(lowerque
)->q_ptr
= NULL
;
1668 kmem_free(lqs
, sizeof (*lqs
));
1671 } /* conskbd_kioctrans_complete() */
1674 * Allocate a firm event
1677 conskbd_alloc_firm_event(ushort_t id
, int value
)
1682 if ((mb
= allocb(sizeof (Firm_event
), BPRI_HI
)) != NULL
) {
1683 fe
= (Firm_event
*)mb
->b_wptr
;
1685 fe
->pair_type
= FE_PAIR_NONE
;
1688 mb
->b_wptr
+= sizeof (Firm_event
);
1695 conskbd_kioclayout_complete(conskbd_lower_queue_t
*lqs
, mblk_t
*mp
)
1701 ASSERT(lqs
->lqs_pending_plink
!= NULL
);
1702 ASSERT(lqs
->lqs_state
== LQS_KIOCLAYOUT_ACK_PENDING
);
1704 switch (mp
->b_datap
->db_type
) {
1706 if (miocpullup(mp
, sizeof (int)) == 0) {
1707 layout
= *(int *)mp
->b_cont
->b_rptr
;
1709 * We just accept the layout of the first keyboard
1710 * requesting to be linked under conskbd. If current
1711 * keyboard is the first one, and if we get right
1712 * layout from it, we set conskbd's layout
1714 if (layout
!= -1 && conskbd
.conskbd_layout
== -1) {
1716 conskbd
.conskbd_layout
= kbd_layout_bak
;
1718 conskbd
.conskbd_layout
= layout
;
1719 if (layout
== kbd_layout_bak
) {
1722 if ((req
= conskbd_alloc_firm_event(
1723 KEYBOARD_LAYOUT_CHANGE
,
1725 if (conskbd
.conskbd_directio
) {
1729 } else if (conskbd_consqueue
1744 /* if fail, leave conskbd's layout as it is */
1751 if (conskbd
.conskbd_led_state
== -1)
1752 req
= mkiocb(KIOCGLED
);
1754 req
= mkiocb(KIOCSLED
);
1757 req
->b_cont
= allocb(sizeof (uchar_t
), BPRI_MED
);
1759 if (conskbd
.conskbd_led_state
!= -1) {
1760 *(uchar_t
*)req
->b_cont
->b_wptr
=
1761 conskbd
.conskbd_led_state
;
1762 req
->b_cont
->b_wptr
+= sizeof (uchar_t
);
1765 /* waiting for response to KIOCSLED */
1766 lqs
->lqs_state
= LQS_KIOCSLED_ACK_PENDING
;
1767 if (putq(lqs
->lqs_queue
, req
) == 1) {
1780 * If fail to allocate KIOCSLED/KIOCGLED message or put
1781 * the message into lower queue, we immediately link
1782 * current keyboard under conskbd. Thus, even if fails
1783 * to set/get LED, this keyboard could be available.
1785 qwriter(lqs
->lqs_queue
,
1786 mp
, conskbd_link_lowque_virt
, PERIM_OUTER
);
1791 } /* conskbd_kioclayout_complete() */
1795 conskbd_kiocsled_complete(conskbd_lower_queue_t
*lqs
, mblk_t
*mp
)
1799 ASSERT(lqs
->lqs_pending_plink
!= NULL
);
1800 ASSERT(lqs
->lqs_state
== LQS_KIOCSLED_ACK_PENDING
);
1802 if (conskbd
.conskbd_led_state
== -1) {
1803 switch (mp
->b_datap
->db_type
) {
1805 if (miocpullup(mp
, sizeof (uchar_t
)) == 0) {
1806 led_state
= *(uchar_t
*)mp
->b_cont
->b_rptr
;
1807 conskbd
.conskbd_led_state
= led_state
;
1808 kbtrans_streams_setled(conskbd
.conskbd_kbtrans
,
1813 /* if fail, leave conskbd's led_state as it is */
1820 * Basically, failure of setting/getting LED is not a fatal
1821 * error, so we will plumb the lower queue into conskbd whether
1822 * setting/getting LED succeeds or fails.
1824 qwriter(lqs
->lqs_queue
, mp
, conskbd_link_lowque_virt
, PERIM_OUTER
);
1826 } /* conskbd_kiocsled_complete() */
1830 conskbd_mux_upstream_msg(conskbd_lower_queue_t
*lqs
, mblk_t
*mp
)
1832 conskbd_pending_msg_t
*msg
;
1833 struct iocblk
*iocp
;
1836 char path
[MAXPATHLEN
+ 1];
1838 ASSERT(lqs
->lqs_state
== LQS_INITIALIZED
);
1839 msg
= conskbd_mux_find_msg(mp
);
1843 * Here we discard the response if:
1845 * 1. It's an KIOCSLED request; see conskbd_streams_setled().
1846 * 2. The application has already closed the upper stream;
1847 * see conskbdclose()
1854 * We use the b_next field of mblk_t structure to link all
1855 * response coming from lower queues into a linkage list,
1856 * and make use of the b_prev field to save a pointer to
1857 * the lower queue from which the current response message
1860 ASSERT(mp
->b_next
== NULL
&& mp
->b_prev
== NULL
);
1861 mutex_enter(&msg
->kpm_lock
);
1862 mp
->b_next
= msg
->kpm_resp_list
;
1863 mp
->b_prev
= (mblk_t
*)lqs
;
1864 msg
->kpm_resp_list
= mp
;
1865 msg
->kpm_resp_nums
++;
1867 if (msg
->kpm_resp_nums
< msg
->kpm_req_nums
) {
1868 mutex_exit(&msg
->kpm_lock
);
1872 ASSERT(msg
->kpm_resp_nums
== msg
->kpm_req_nums
);
1873 ASSERT(mp
== msg
->kpm_resp_list
);
1875 mutex_exit(&msg
->kpm_lock
);
1877 conskbd_mux_dequeue_msg(msg
);
1881 * Here, we have the policy that, if any one lower queue ACK
1882 * our reuqest, then we return ACK to upstreams; only if all
1883 * lower queues NAK our request, we return NAK to upstreams.
1884 * if all responses are nak, the errno of the first response
1885 * is sent to upstreams
1888 error
= ((struct iocblk
*)mp
->b_rptr
)->ioc_error
;
1890 switch (msg
->kpm_req_cmd
) {
1891 case CONSOPENPOLLEDIO
:
1893 * Here, we can safely ignore the NAK message. If any one lower
1894 * queue returns NAK, the pointer to the corresponding polledio
1895 * structure will remain null, that's say lqs->lqs_polledio =
1896 * null. When we need to invoke polled I/O interface, we will
1897 * check if the pointer is null.
1899 for (mp
= msg
->kpm_resp_list
; mp
; ) {
1900 cons_polledio_t
*polledio
;
1902 msg
->kpm_resp_list
= mp
->b_next
;
1903 lqs
= (conskbd_lower_queue_t
*)mp
->b_prev
;
1904 devt
= lqs
->lqs_queue
->q_stream
->sd_vnode
->v_rdev
;
1905 if (mp
->b_datap
->db_type
== M_IOCACK
) {
1906 polledio
= *(struct cons_polledio
**)
1908 if (polledio
->cons_polledio_version
==
1910 lqs
->lqs_polledio
= polledio
;
1914 * USB and PS2 keyboard drivers should
1915 * use the same cons_polledio structure
1918 if (ddi_dev_pathname(devt
, S_IFCHR
,
1919 path
) == DDI_SUCCESS
) {
1920 cmn_err(CE_WARN
, "keyboard "
1921 "driver does not support "
1922 "system debugging: %s",
1928 if (ddi_dev_pathname(devt
, S_IFCHR
, path
) ==
1930 cmn_err(CE_WARN
, "conskbd: keyboard is"
1931 " not available for system"
1932 " debugging: %s", path
);
1938 mp
= msg
->kpm_resp_list
;
1941 mp
= msg
->kpm_req_msg
;
1943 *(struct cons_polledio
**)mp
->b_cont
->b_rptr
=
1944 &conskbd
.conskbd_polledio
;
1948 case CONSCLOSEPOLLEDIO
:
1949 for (mp
= msg
->kpm_resp_list
; mp
; ) {
1950 msg
->kpm_resp_list
= mp
->b_next
;
1951 lqs
= (conskbd_lower_queue_t
*)mp
->b_prev
;
1952 if (mp
->b_datap
->db_type
== M_IOCACK
) {
1953 lqs
->lqs_polledio
= NULL
;
1957 lqs
->lqs_queue
->q_stream
->sd_vnode
->v_rdev
;
1959 if (ddi_dev_pathname(devt
, S_IFCHR
, path
) ==
1961 cmn_err(CE_WARN
, "conskbd: keyboard is"
1962 " not available: %s", path
);
1969 mp
= msg
->kpm_resp_list
;
1975 for (mp
= msg
->kpm_resp_list
; mp
; ) {
1976 msg
->kpm_resp_list
= mp
->b_next
;
1978 if (mp
->b_datap
->db_type
== M_IOCACK
)
1983 mp
= msg
->kpm_resp_list
;
1987 default: /* it is impossible to reach here */
1988 cmn_err(CE_WARN
, "conskbd: unexpected ioctl reply");
1991 mp
= msg
->kpm_req_msg
;
1993 mp
->b_datap
->db_type
= M_IOCACK
;
1995 mp
->b_datap
->db_type
= M_IOCNAK
;
1997 iocp
= (struct iocblk
*)mp
->b_rptr
;
1998 iocp
->ioc_error
= error
;
1999 qreply(msg
->kpm_upper_queue
, mp
);
2000 mutex_destroy(&msg
->kpm_lock
);
2001 kmem_free(msg
, sizeof (*msg
));
2003 } /* conskbd_mux_upstream_msg() */
2006 conskbd_link_lowque_legacy(queue_t
*lowque
, mblk_t
*mp
)
2008 conskbd_lower_queue_t
*lqs
;
2013 * Bypass the virutal keyboard for old hardware,
2014 * Now, only current legacy keyboard can be linked
2017 conskbd
.conskbd_bypassed
= B_TRUE
;
2020 * Link the lower queue under conskbd
2022 lqs
= (conskbd_lower_queue_t
*)lowque
->q_ptr
;
2023 lqs
->lqs_state
= LQS_INITIALIZED_LEGACY
;
2024 lqs
->lqs_next
= conskbd
.conskbd_lqueue_list
;
2025 conskbd
.conskbd_lqueue_list
= lqs
;
2026 conskbd
.conskbd_lqueue_nums
++;
2028 mioc2ack(lqs
->lqs_pending_plink
, NULL
, 0, 0);
2029 qreply(lqs
->lqs_pending_queue
, lqs
->lqs_pending_plink
);
2031 } /* conskbd_link_lowque_legacy() */
2034 conskbd_link_lowque_virt(queue_t
*lowque
, mblk_t
*mp
)
2037 conskbd_lower_queue_t
*lqs
;
2041 lqs
= (conskbd_lower_queue_t
*)lowque
->q_ptr
;
2043 ASSERT(lqs
->lqs_queue
== lowque
);
2044 ASSERT(lqs
->lqs_pending_plink
!= NULL
);
2047 * Now, link the lower queue under conskbd
2049 for (index
= 0; index
< KBTRANS_KEYNUMS_MAX
; index
++) {
2050 lqs
->lqs_key_state
[index
] = KEY_RELEASED
;
2052 lqs
->lqs_next
= conskbd
.conskbd_lqueue_list
;
2053 lqs
->lqs_state
= LQS_INITIALIZED
;
2054 conskbd
.conskbd_lqueue_nums
++;
2055 conskbd
.conskbd_lqueue_list
= lqs
;
2056 mioc2ack(lqs
->lqs_pending_plink
, NULL
, 0, 0);
2057 qreply(lqs
->lqs_pending_queue
, lqs
->lqs_pending_plink
);
2059 } /* conskbd_link_lowque_virt() */
2063 conskbd_legacy_upstream_msg(conskbd_lower_queue_t
*lqs
, mblk_t
*mp
)
2065 struct iocblk
*iocp
;
2067 ASSERT(lqs
&& lqs
->lqs_state
== LQS_INITIALIZED_LEGACY
);
2070 * We assume that all of the ioctls are headed to the
2071 * conskbd_regqueue if it is open. We are intercepting a few ioctls
2072 * that we know belong to conskbd_consqueue, and sending them there.
2073 * Any other, new ioctls that have to be routed to conskbd_consqueue
2074 * should be added to this list.
2076 iocp
= (struct iocblk
*)mp
->b_rptr
;
2078 if ((iocp
->ioc_cmd
== CONSOPENPOLLEDIO
) ||
2079 (iocp
->ioc_cmd
== CONSCLOSEPOLLEDIO
)) {
2081 DPRINTF(PRINT_L1
, PRINT_MASK_ALL
,
2082 ("conskbd_legacy_upstream_msg: "
2083 "CONSOPEN/CLOSEPOLLEDIO ACK/NAK\n"));
2084 putnext(conskbd_consqueue
, mp
);
2086 } else if (conskbd_regqueue
!= NULL
) {
2087 DPRINTF(PRINT_L1
, PRINT_MASK_ALL
,
2088 ("conskbd_legacy_upstream_msg: conskbd_regqueue != NULL"));
2090 putnext(conskbd_regqueue
, mp
);
2092 } else if (conskbd_consqueue
!= NULL
) {
2093 DPRINTF(PRINT_L1
, PRINT_MASK_ALL
,
2094 ("conskbd_legacy_upstream_msg: conskbd_consqueue != NULL"));
2095 putnext(conskbd_consqueue
, mp
);
2097 /* if reached here, it must be a error */
2099 "kb: no destination for IOCACK/IOCNAK!");
2103 } /* conskbd_legacy_upstream_msg() */
2106 * This routine is a callback routine for kbtrans module to set LED.
2107 * Kbtrans will invoke it in two cases:
2109 * 1) application initiated request
2110 * A KIOCSLED ioctl is sent by an application. The ioctl will be
2111 * be prcoessed by queue service procedure conskbduwsrv(), which
2112 * in turn calls kbtrans to process the ioctl. Then kbtrans invokes
2113 * conskbd_streams_setled() to set LED, after that, kbtrans will
2114 * return an ACK message to upper module.
2116 * 2) Kbtrans initiated the request
2117 * When conskbd works in TR_ASCII translation mode, if anyone of
2118 * CapsLock, NumberLock and Compose keys is pressed, kbtrans need
2119 * to set LED. In this case, there is no ioctl from upper module.
2120 * There is no requirement to send response to somebody.
2122 * In first case, kbtrans will send response to upper module; and in the
2123 * second, we don't need to send response. So conskbd_streams_setled()
2124 * has no return value.
2127 conskbd_streams_setled(struct kbtrans_hardware
*hw
, int led_state
)
2129 conskbd_state_t
*conskbdp
= (conskbd_state_t
*)hw
;
2130 conskbd_lower_queue_t
*lqs
;
2133 ASSERT(&conskbd
== conskbdp
);
2135 if (led_state
== -1)
2138 conskbdp
->conskbd_led_state
= led_state
;
2141 * Basically, failing to set LED is not a fatal error, we just skip
2142 * it if this happens.
2144 for (lqs
= conskbdp
->conskbd_lqueue_list
; lqs
; lqs
= lqs
->lqs_next
) {
2145 req
= mkiocb(KIOCSLED
);
2151 req
->b_cont
= allocb(sizeof (uchar_t
), BPRI_MED
);
2156 *(uchar_t
*)req
->b_cont
->b_wptr
= led_state
;
2157 req
->b_cont
->b_wptr
+= sizeof (uchar_t
);
2158 if (putq(lqs
->lqs_queue
, req
) != 1)
2162 } /* conskbd_streams_setled() */
2165 conskbd_polledio_setled(struct kbtrans_hardware
*hw
, int led_state
)
2167 conskbd_state_t
*conskbdp
= (conskbd_state_t
*)hw
;
2168 struct cons_polledio
*cb
;
2169 conskbd_lower_queue_t
*lqs
;
2171 for (lqs
= conskbdp
->conskbd_lqueue_list
; lqs
; lqs
= lqs
->lqs_next
) {
2172 cb
= lqs
->lqs_polledio
;
2173 if ((cb
!= NULL
) && (cb
->cons_polledio_setled
!= NULL
)) {
2174 cb
->cons_polledio_setled(cb
->cons_polledio_argument
,
2179 } /* conskbd_polledio_setled() */
2182 conskbd_polled_keycheck(struct kbtrans_hardware
*hw
,
2183 kbtrans_key_t
*keycode
, enum keystate
*state
)
2185 conskbd_state_t
*conskbdp
= (conskbd_state_t
*)hw
;
2186 struct cons_polledio
*cb
;
2187 conskbd_lower_queue_t
*lqs
;
2188 boolean_t ret
= B_FALSE
;
2190 for (ret
= B_FALSE
, lqs
= conskbdp
->conskbd_lqueue_list
; lqs
!= NULL
;
2191 lqs
= lqs
->lqs_next
) {
2192 cb
= lqs
->lqs_polledio
;
2194 (cb
->cons_polledio_keycheck
!= NULL
)) {
2195 ret
= cb
->cons_polledio_keycheck(
2196 cb
->cons_polledio_argument
, keycode
, state
);
2199 /* Get a char from lower queue(hardware) ? */
2200 if (ret
== B_TRUE
) {
2202 /* A legacy keyboard ? */
2203 if (conskbd
.conskbd_bypassed
== B_TRUE
)
2207 * This is the PS2 scancode 0x2B -> USB(49) /
2208 * USB(50) keycode mapping workaround, for
2211 * There are two possible USB keycode mappings
2212 * for PS2 scancode 0x2B and this workaround
2213 * makes sure that we use the USB keycode that
2214 * does not end up being mapped to a HOLE key
2215 * using the current keyboard translation
2218 * See conskbdlrput() for a detailed
2219 * explanation of the problem.
2221 if (*keycode
== 49 || *keycode
== 50) {
2222 if (conskbd_keyindex
->k_normal
[50] == HOLE
)
2234 } /* conskbd_polled_keycheck() */
2237 conskbd_override_kbtrans(queue_t
*q
, mblk_t
*mp
)
2239 struct iocblk
*iocp
;
2243 if (mp
->b_datap
->db_type
!= M_IOCTL
)
2246 iocp
= (struct iocblk
*)mp
->b_rptr
;
2248 switch (iocp
->ioc_cmd
) {
2251 * Don't let the kbtrans-based code see this; it will
2252 * respond incorrectly.
2254 register mblk_t
*datap
;
2256 if ((datap
= allocb((int)sizeof (int), BPRI_MED
)) == NULL
) {
2257 miocnak(q
, mp
, 0, ENOMEM
);
2261 *(int *)datap
->b_wptr
= conskbd
.conskbd_directio
;
2262 datap
->b_wptr
+= sizeof (int);
2264 freemsg(mp
->b_cont
);
2268 miocack(q
, mp
, sizeof (int), 0);
2274 * Peek at this, set our variables, and then let the kbtrans
2275 * based code see it and respond to it.
2277 error
= miocpullup(mp
, sizeof (int));
2282 directio
= *(int *)mp
->b_cont
->b_rptr
;
2283 if (directio
!= 0 && directio
!= 1) {
2284 miocnak(q
, mp
, 0, EINVAL
);
2287 conskbd
.conskbd_directio
= directio
;
2289 if (conskbd
.conskbd_directio
) {
2290 kbtrans_streams_set_queue(
2291 conskbd
.conskbd_kbtrans
, conskbd_regqueue
);
2293 kbtrans_streams_set_queue(
2294 conskbd
.conskbd_kbtrans
, conskbd_consqueue
);
2298 * Let the kbtrans-based code see this and respond to it.
2306 } /* conskbd_override_kbtrans() */
2310 conskbd_polledio_enter(cons_polledio_arg_t arg
)
2312 conskbd_state_t
*conskbdp
;
2313 struct cons_polledio
*cb
;
2314 conskbd_lower_queue_t
*lqs
;
2316 conskbdp
= (conskbd_state_t
*)arg
;
2317 for (lqs
= conskbdp
->conskbd_lqueue_list
; lqs
; lqs
= lqs
->lqs_next
) {
2318 cb
= lqs
->lqs_polledio
;
2319 if ((cb
!= NULL
) && (cb
->cons_polledio_enter
!= NULL
)) {
2320 cb
->cons_polledio_enter(cb
->cons_polledio_argument
);
2324 } /* conskbd_polledio_enter() */
2327 conskbd_polledio_exit(cons_polledio_arg_t arg
)
2329 conskbd_state_t
*conskbdp
;
2330 struct cons_polledio
*cb
;
2331 conskbd_lower_queue_t
*lqs
;
2333 conskbdp
= (conskbd_state_t
*)arg
;
2334 for (lqs
= conskbdp
->conskbd_lqueue_list
; lqs
; lqs
= lqs
->lqs_next
) {
2335 cb
= lqs
->lqs_polledio
;
2336 if ((cb
!= NULL
) && (cb
->cons_polledio_exit
!= NULL
)) {
2337 cb
->cons_polledio_exit(cb
->cons_polledio_argument
);
2341 } /* conskbd_polledio_exit() */
2344 conskbd_polledio_getchar(cons_polledio_arg_t arg
)
2346 conskbd_state_t
*conskbdp
;
2348 conskbdp
= (conskbd_state_t
*)arg
;
2350 return (kbtrans_getchar(conskbdp
->conskbd_kbtrans
));
2352 } /* conskbd_polledio_getchar() */
2355 conskbd_polledio_ischar(cons_polledio_arg_t arg
)
2357 conskbd_state_t
*conskbdp
;
2359 conskbdp
= (conskbd_state_t
*)arg
;
2361 return (kbtrans_ischar(conskbdp
->conskbd_kbtrans
));
2363 } /* conskbd_polledio_ischar() */
2367 conskbd_mux_enqueue_msg(conskbd_pending_msg_t
*msg
)
2369 mutex_enter(&conskbd_msgq_lock
);
2370 msg
->kpm_next
= conskbd_msg_queue
;
2371 conskbd_msg_queue
= msg
;
2372 mutex_exit(&conskbd_msgq_lock
);
2374 } /* conskbd_mux_enqueue_msg() */
2377 * the messages in conskbd_msg_queue we just enqueue
2379 static conskbd_pending_msg_t
*
2380 conskbd_mux_find_msg(mblk_t
*mp
)
2382 conskbd_pending_msg_t
*msg
;
2383 struct iocblk
*iocp
;
2386 mutex_enter(&conskbd_msgq_lock
);
2387 msg
= conskbd_msg_queue
;
2389 iocp
= (struct iocblk
*)mp
->b_rptr
;
2392 while (msg
&& msg
->kpm_req_id
!= id
) {
2393 msg
= msg
->kpm_next
;
2395 mutex_exit(&conskbd_msgq_lock
);
2399 } /* conskbd_mux_find_msg() */
2403 conskbd_mux_dequeue_msg(conskbd_pending_msg_t
*msg
)
2405 conskbd_pending_msg_t
*prev
;
2406 conskbd_pending_msg_t
*p
;
2408 mutex_enter(&conskbd_msgq_lock
);
2409 prev
= conskbd_msg_queue
;
2411 for (p
= prev
; p
&& p
!= msg
; p
= p
->kpm_next
)
2414 ASSERT(p
&& p
== msg
);
2417 conskbd_msg_queue
= msg
->kpm_next
;
2419 prev
->kpm_next
= p
->kpm_next
;
2422 mutex_exit(&conskbd_msgq_lock
);
2424 } /* conskbd_mux_dequeue_msg() */
2429 conskbd_dprintf(const char *fmt
, ...)
2435 (void) vsprintf(buf
, fmt
, ap
);
2438 cmn_err(CE_CONT
, "conskbd: %s", buf
);
2440 } /* conskbd_dprintf() */