xref: /illumos-gate/usr/src/uts/common/io/usb/clients/usbkbm/usbkbm.c (revision e44e85a7f9935f0428e188393e3da61b17e83884)
1 /*
2  * CDDL HEADER START
3  *
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.
7  *
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.
12  *
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]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 
27 /*
28  * USB keyboard input streams module - processes USB keypacket
29  * received from HID driver below to either ASCII or event
30  * format for windowing system.
31  */
32 #include <sys/usb/usba/usbai_version.h>
33 
34 #define	KEYMAP_SIZE_VARIABLE
35 #include <sys/usb/usba.h>
36 #include <sys/usb/clients/hid/hid.h>
37 #include <sys/usb/clients/hid/hid_polled.h>
38 #include <sys/usb/clients/hidparser/hidparser.h>
39 #include <sys/stropts.h>
40 #include <sys/stream.h>
41 #include <sys/strsun.h>
42 #include <sys/kbio.h>
43 #include <sys/vuid_event.h>
44 #include <sys/kbd.h>
45 #include <sys/consdev.h>
46 #include <sys/kbtrans.h>
47 #include <sys/usb/clients/usbkbm/usbkbm.h>
48 #include <sys/beep.h>
49 #include <sys/policy.h>
50 #include <sys/inttypes.h>
51 
52 /* debugging information */
53 uint_t	usbkbm_errmask = (uint_t)PRINT_MASK_ALL;
54 uint_t	usbkbm_errlevel = USB_LOG_L2;
55 static usb_log_handle_t usbkbm_log_handle;
56 
57 typedef void (*process_key_callback_t)(usbkbm_state_t *, int, enum keystate);
58 
59 /*
60  * Internal Function Prototypes
61  */
62 static void usbkbm_streams_setled(struct kbtrans_hardware *, int);
63 static void usbkbm_polled_setled(struct kbtrans_hardware *, int);
64 static boolean_t usbkbm_polled_keycheck(struct kbtrans_hardware *,
65 			int *, enum keystate *);
66 static void usbkbm_poll_callback(usbkbm_state_t *, int, enum keystate);
67 static void usbkbm_streams_callback(usbkbm_state_t *, int, enum keystate);
68 static void usbkbm_unpack_usb_packet(usbkbm_state_t *, process_key_callback_t,
69 			uchar_t *);
70 static boolean_t usbkbm_is_modkey(uchar_t);
71 static void usbkbm_reioctl(void	*);
72 static int usbkbm_polled_getchar(cons_polledio_arg_t);
73 static boolean_t usbkbm_polled_ischar(cons_polledio_arg_t);
74 static void usbkbm_polled_enter(cons_polledio_arg_t);
75 static void usbkbm_polled_exit(cons_polledio_arg_t);
76 static void usbkbm_mctl_receive(queue_t *, mblk_t *);
77 static enum kbtrans_message_response usbkbm_ioctl(queue_t *, mblk_t *);
78 static int usbkbm_kioccmd(usbkbm_state_t *, mblk_t *, char, size_t *);
79 static void	usbkbm_usb2pc_xlate(usbkbm_state_t *, int, enum keystate);
80 static void	usbkbm_wrap_kbtrans(usbkbm_state_t *, int, enum keystate);
81 static int	usbkbm_get_input_format(usbkbm_state_t *);
82 static int	usbkbm_get_vid_pid(usbkbm_state_t *);
83 
84 /* stream qinit functions defined here */
85 static int	usbkbm_open(queue_t *, dev_t *, int, int, cred_t *);
86 static int	usbkbm_close(queue_t *, int, cred_t *);
87 static void	usbkbm_wput(queue_t *, mblk_t *);
88 static void	usbkbm_rput(queue_t *, mblk_t *);
89 static ushort_t	usbkbm_get_state(usbkbm_state_t *);
90 static void	usbkbm_get_scancode(usbkbm_state_t *, int *, enum keystate *);
91 
92 static struct keyboard *usbkbm_keyindex;
93 
94 /* External Functions */
95 extern void space_free(char *);
96 extern uintptr_t space_fetch(char *);
97 extern int space_store(char *, uintptr_t);
98 extern struct keyboard *kbtrans_usbkb_maptab_init(void);
99 extern void kbtrans_usbkb_maptab_fini(struct keyboard **);
100 extern keymap_entry_t kbtrans_keycode_usb2pc(int);
101 
102 /*
103  * Structure to setup callbacks
104  */
105 struct kbtrans_callbacks kbd_usb_callbacks = {
106 	usbkbm_streams_setled,
107 	usbkbm_polled_setled,
108 	usbkbm_polled_keycheck,
109 };
110 
111 /*
112  * Global Variables
113  */
114 
115 /* This variable saves the LED state across hotplugging. */
116 static uchar_t	usbkbm_led_state = 0;
117 
118 /* This variable saves the layout state */
119 static uint16_t usbkbm_layout = 0;
120 
121 /*
122  * Function pointer array for mapping of scancodes.
123  */
124 void (*usbkbm_xlate[2])(usbkbm_state_t *, int, enum keystate) = {
125 	usbkbm_wrap_kbtrans,
126 	usbkbm_usb2pc_xlate
127 };
128 
129 static struct streamtab usbkbm_info;
130 static struct fmodsw fsw = {
131 	"usbkbm",
132 	&usbkbm_info,
133 	D_MP | D_MTPERMOD
134 };
135 
136 
137 /*
138  * Module linkage information for the kernel.
139  */
140 static struct modlstrmod modlstrmod = {
141 	&mod_strmodops,
142 	"USB keyboard streams 1.44",
143 	&fsw
144 };
145 
146 static struct modlinkage modlinkage = {
147 	MODREV_1,
148 	(void *)&modlstrmod,
149 	NULL
150 };
151 
152 
153 int
154 _init(void)
155 {
156 	int	rval = mod_install(&modlinkage);
157 	usbkbm_save_state_t *sp;
158 
159 	if (rval != 0) {
160 
161 		return (rval);
162 	}
163 
164 	usbkbm_keyindex = kbtrans_usbkb_maptab_init();
165 
166 	usbkbm_log_handle = usb_alloc_log_hdl(NULL, "usbkbm",
167 	    &usbkbm_errlevel, &usbkbm_errmask, NULL, 0);
168 
169 	sp = (usbkbm_save_state_t *)space_fetch("SUNW,usbkbm_state");
170 
171 	if (sp == NULL) {
172 
173 		return (0);
174 	}
175 
176 	/* Restore LED information */
177 	usbkbm_led_state = sp->usbkbm_save_led;
178 
179 	/* Restore the Layout */
180 	usbkbm_layout = sp->usbkbm_layout;
181 
182 	/* Restore abort information */
183 	usbkbm_keyindex->k_abort1 =
184 	    sp->usbkbm_save_keyindex.k_abort1;
185 
186 	usbkbm_keyindex->k_abort2 =
187 	    sp->usbkbm_save_keyindex.k_abort2;
188 
189 	usbkbm_keyindex->k_newabort1 =
190 	    sp->usbkbm_save_keyindex.k_newabort1;
191 
192 	usbkbm_keyindex->k_newabort2 =
193 	    sp->usbkbm_save_keyindex.k_newabort2;
194 
195 	/* Restore keytables */
196 	bcopy(sp->usbkbm_save_keyindex.k_normal,
197 	    usbkbm_keyindex->k_normal, USB_KEYTABLE_SIZE);
198 
199 	bcopy(sp->usbkbm_save_keyindex.k_shifted,
200 	    usbkbm_keyindex->k_shifted, USB_KEYTABLE_SIZE);
201 
202 	bcopy(sp->usbkbm_save_keyindex.k_caps,
203 	    usbkbm_keyindex->k_caps, USB_KEYTABLE_SIZE);
204 
205 	bcopy(sp->usbkbm_save_keyindex.k_altgraph,
206 	    usbkbm_keyindex->k_altgraph, USB_KEYTABLE_SIZE);
207 
208 	bcopy(sp->usbkbm_save_keyindex.k_numlock,
209 	    usbkbm_keyindex->k_numlock, USB_KEYTABLE_SIZE);
210 
211 	bcopy(sp->usbkbm_save_keyindex.k_control,
212 	    usbkbm_keyindex->k_control, USB_KEYTABLE_SIZE);
213 
214 	bcopy(sp->usbkbm_save_keyindex.k_up,
215 	    usbkbm_keyindex->k_up, USB_KEYTABLE_SIZE);
216 
217 	kmem_free(sp->usbkbm_save_keyindex.k_normal,
218 	    USB_KEYTABLE_SIZE);
219 	kmem_free(sp->usbkbm_save_keyindex.k_shifted,
220 	    USB_KEYTABLE_SIZE);
221 	kmem_free(sp->usbkbm_save_keyindex.k_caps,
222 	    USB_KEYTABLE_SIZE);
223 	kmem_free(sp->usbkbm_save_keyindex.k_altgraph,
224 	    USB_KEYTABLE_SIZE);
225 	kmem_free(sp->usbkbm_save_keyindex.k_numlock,
226 	    USB_KEYTABLE_SIZE);
227 	kmem_free(sp->usbkbm_save_keyindex.k_control,
228 	    USB_KEYTABLE_SIZE);
229 	kmem_free(sp->usbkbm_save_keyindex.k_up,
230 	    USB_KEYTABLE_SIZE);
231 
232 	kmem_free(sp, sizeof (usbkbm_save_state_t));
233 	space_free("SUNW,usbkbm_state");
234 
235 	return (0);
236 }
237 
238 int
239 _fini(void)
240 {
241 	usbkbm_save_state_t *sp;
242 	int sval;
243 	int rval;
244 
245 	sp = kmem_alloc(sizeof (usbkbm_save_state_t), KM_SLEEP);
246 	sval = space_store("SUNW,usbkbm_state", (uintptr_t)sp);
247 
248 	/*
249 	 * If it's not possible to store the state, return
250 	 * EBUSY.
251 	 */
252 	if (sval != 0) {
253 		kmem_free(sp, sizeof (usbkbm_save_state_t));
254 
255 		return (EBUSY);
256 	}
257 
258 	rval = mod_remove(&modlinkage);
259 
260 	if (rval != 0) {
261 		kmem_free(sp, sizeof (usbkbm_save_state_t));
262 		space_free("SUNW,usbkbm_state");
263 
264 		return (rval);
265 	}
266 
267 	usb_free_log_hdl(usbkbm_log_handle);
268 
269 	/* Save the LED state */
270 	sp->usbkbm_save_led = usbkbm_led_state;
271 
272 	/* Save the layout */
273 	sp->usbkbm_layout = (uchar_t)usbkbm_layout;
274 
275 	/*
276 	 * Save entries of the keyboard structure that
277 	 * have changed.
278 	 */
279 	sp->usbkbm_save_keyindex.k_abort1 = usbkbm_keyindex->k_abort1;
280 	sp->usbkbm_save_keyindex.k_abort2 = usbkbm_keyindex->k_abort2;
281 
282 	sp->usbkbm_save_keyindex.k_newabort1 = usbkbm_keyindex->k_newabort1;
283 	sp->usbkbm_save_keyindex.k_newabort2 = usbkbm_keyindex->k_newabort2;
284 
285 	/* Allocate space for keytables to be stored */
286 	sp->usbkbm_save_keyindex.k_normal =
287 	    kmem_alloc(USB_KEYTABLE_SIZE, KM_SLEEP);
288 	sp->usbkbm_save_keyindex.k_shifted =
289 	    kmem_alloc(USB_KEYTABLE_SIZE, KM_SLEEP);
290 	sp->usbkbm_save_keyindex.k_caps =
291 	    kmem_alloc(USB_KEYTABLE_SIZE, KM_SLEEP);
292 	sp->usbkbm_save_keyindex.k_altgraph =
293 	    kmem_alloc(USB_KEYTABLE_SIZE, KM_SLEEP);
294 	sp->usbkbm_save_keyindex.k_numlock =
295 	    kmem_alloc(USB_KEYTABLE_SIZE, KM_SLEEP);
296 	sp->usbkbm_save_keyindex.k_control =
297 	    kmem_alloc(USB_KEYTABLE_SIZE, KM_SLEEP);
298 	sp->usbkbm_save_keyindex.k_up =
299 	    kmem_alloc(USB_KEYTABLE_SIZE, KM_SLEEP);
300 
301 	/* Copy over the keytables */
302 	bcopy(usbkbm_keyindex->k_normal,
303 	    sp->usbkbm_save_keyindex.k_normal, USB_KEYTABLE_SIZE);
304 
305 	bcopy(usbkbm_keyindex->k_shifted,
306 	    sp->usbkbm_save_keyindex.k_shifted, USB_KEYTABLE_SIZE);
307 
308 	bcopy(usbkbm_keyindex->k_caps,
309 	    sp->usbkbm_save_keyindex.k_caps, USB_KEYTABLE_SIZE);
310 
311 	bcopy(usbkbm_keyindex->k_altgraph,
312 	    sp->usbkbm_save_keyindex.k_altgraph, USB_KEYTABLE_SIZE);
313 
314 	bcopy(usbkbm_keyindex->k_numlock,
315 	    sp->usbkbm_save_keyindex.k_numlock, USB_KEYTABLE_SIZE);
316 
317 	bcopy(usbkbm_keyindex->k_control,
318 	    sp->usbkbm_save_keyindex.k_control, USB_KEYTABLE_SIZE);
319 
320 	bcopy(usbkbm_keyindex->k_up,
321 	    sp->usbkbm_save_keyindex.k_up, USB_KEYTABLE_SIZE);
322 
323 	kbtrans_usbkb_maptab_fini(&usbkbm_keyindex);
324 
325 	return (0);
326 }
327 
328 int
329 _info(struct modinfo *modinfop)
330 {
331 	return (mod_info(&modlinkage, modinfop));
332 }
333 
334 /*
335  * Module qinit functions
336  */
337 
338 static struct module_info usbkbm_minfo = {
339 	0,		/* module id number */
340 	"usbkbm",	/* module name */
341 	0,		/* min packet size accepted */
342 	INFPSZ,		/* max packet size accepted */
343 	2048,		/* hi-water mark */
344 	128		/* lo-water mark */
345 	};
346 
347 /* read side for key data and ioctl replies */
348 static struct qinit usbkbm_rinit = {
349 	(int (*)())usbkbm_rput,
350 	(int (*)())NULL,		/* service not used */
351 	usbkbm_open,
352 	usbkbm_close,
353 	(int (*)())NULL,
354 	&usbkbm_minfo
355 	};
356 
357 /* write side for ioctls */
358 static struct qinit usbkbm_winit = {
359 	(int (*)())usbkbm_wput,
360 	(int (*)())NULL,
361 	usbkbm_open,
362 	usbkbm_close,
363 	(int (*)())NULL,
364 	&usbkbm_minfo
365 	};
366 
367 static struct streamtab usbkbm_info = {
368 	&usbkbm_rinit,
369 	&usbkbm_winit,
370 	NULL,		/* for muxes */
371 	NULL,		/* for muxes */
372 };
373 
374 /*
375  * usbkbm_open :
376  *	Open a keyboard
377  */
378 /* ARGSUSED */
379 static int
380 usbkbm_open(queue_t *q, dev_t *devp, int oflag, int sflag, cred_t *crp)
381 {
382 	usbkbm_state_t	*usbkbmd;
383 	struct iocblk	mctlmsg;
384 	mblk_t		*mctl_ptr;
385 	uintptr_t	abortable = (uintptr_t)B_TRUE;
386 	int		error, ret;
387 
388 	if (q->q_ptr) {
389 		USB_DPRINTF_L3(PRINT_MASK_OPEN, usbkbm_log_handle,
390 		    "usbkbm_open already opened");
391 
392 		return (0); /* already opened */
393 	}
394 
395 	/*
396 	 * Only allow open requests to succeed for privileged users.  This
397 	 * necessary to prevent users from pushing the "usbkbm" module again
398 	 * on the stream associated with /dev/kbd.
399 	 */
400 	if (secpolicy_console(crp) != 0)
401 		return (EPERM);
402 
403 	switch (sflag) {
404 
405 	case MODOPEN:
406 		break;
407 
408 	case CLONEOPEN:
409 		USB_DPRINTF_L3(PRINT_MASK_OPEN, usbkbm_log_handle,
410 		    "usbkbm_open: Clone open not supported");
411 
412 		/* FALLTHRU */
413 	default:
414 
415 		return (EINVAL);
416 	}
417 
418 	/* allocate usb keyboard state structure */
419 
420 	usbkbmd = kmem_zalloc(sizeof (usbkbm_state_t), KM_SLEEP);
421 
422 	USB_DPRINTF_L3(PRINT_MASK_OPEN, usbkbm_log_handle,
423 	    "usbkbm_state= %p", (void *)usbkbmd);
424 
425 	/*
426 	 * Set up private data.
427 	 */
428 	usbkbmd->usbkbm_readq = q;
429 	usbkbmd->usbkbm_writeq = WR(q);
430 
431 	usbkbmd->usbkbm_vkbd_type = KB_USB;
432 	/*
433 	 * Set up queue pointers, so that the "put" procedure will accept
434 	 * the reply to the "ioctl" message we send down.
435 	 */
436 	q->q_ptr = (caddr_t)usbkbmd;
437 	WR(q)->q_ptr = (caddr_t)usbkbmd;
438 
439 	error = kbtrans_streams_init(q, sflag, crp,
440 	    (struct kbtrans_hardware *)usbkbmd, &kbd_usb_callbacks,
441 	    &usbkbmd->usbkbm_kbtrans, usbkbm_led_state, 0);
442 
443 	if (error != 0) {
444 		USB_DPRINTF_L3(PRINT_MASK_OPEN, usbkbm_log_handle,
445 		    "kbdopen:  kbtrans_streams_init failed\n");
446 		kmem_free(usbkbmd, sizeof (*usbkbmd));
447 
448 		return (error);
449 	}
450 
451 	/*
452 	 * Set the polled information in the state structure.
453 	 * This information is set once, and doesn't change
454 	 */
455 	usbkbmd->usbkbm_polled_info.cons_polledio_version =
456 	    CONSPOLLEDIO_V1;
457 
458 	usbkbmd->usbkbm_polled_info.cons_polledio_argument =
459 	    (cons_polledio_arg_t)usbkbmd;
460 
461 	usbkbmd->usbkbm_polled_info.cons_polledio_putchar = NULL;
462 
463 	usbkbmd->usbkbm_polled_info.cons_polledio_getchar =
464 	    usbkbm_polled_getchar;
465 
466 	usbkbmd->usbkbm_polled_info.cons_polledio_ischar =
467 	    usbkbm_polled_ischar;
468 
469 	usbkbmd->usbkbm_polled_info.cons_polledio_enter =
470 	    usbkbm_polled_enter;
471 
472 	usbkbmd->usbkbm_polled_info.cons_polledio_exit =
473 	    usbkbm_polled_exit;
474 
475 	usbkbmd->usbkbm_polled_info.cons_polledio_setled =
476 	    (void (*)(cons_polledio_arg_t, int))usbkbm_polled_setled;
477 
478 	usbkbmd->usbkbm_polled_info.cons_polledio_keycheck =
479 	    (boolean_t (*)(cons_polledio_arg_t, int *,
480 	    enum keystate *))usbkbm_polled_keycheck;
481 	/*
482 	 * The head and the tail pointing at the same byte means empty or
483 	 * full. usbkbm_polled_buffer_num_characters is used to
484 	 * tell the difference.
485 	 */
486 	usbkbmd->usbkbm_polled_buffer_head =
487 	    usbkbmd->usbkbm_polled_scancode_buffer;
488 	usbkbmd->usbkbm_polled_buffer_tail =
489 	    usbkbmd->usbkbm_polled_scancode_buffer;
490 	usbkbmd->usbkbm_polled_buffer_num_characters = 0;
491 
492 	qprocson(q);
493 
494 	/* request hid report descriptor from HID */
495 	mctlmsg.ioc_cmd = HID_GET_PARSER_HANDLE;
496 	mctlmsg.ioc_count = 0;
497 	mctl_ptr = usba_mk_mctl(mctlmsg, NULL, 0);
498 	if (mctl_ptr == NULL) {
499 		/* failure to allocate M_CTL message */
500 		(void) kbtrans_streams_fini(usbkbmd->usbkbm_kbtrans);
501 		qprocsoff(q);
502 		kmem_free(usbkbmd, sizeof (*usbkbmd));
503 
504 		return (ENOMEM);
505 	}
506 
507 	/* send message to hid */
508 	putnext(usbkbmd->usbkbm_writeq, mctl_ptr);
509 
510 	/*
511 	 * Now that M_CTL has been sent, wait for report descriptor.  Cleanup
512 	 * if user signals in the mean time (as when this gets opened in an
513 	 * inappropriate context and the user types a ^C).
514 	 */
515 	usbkbmd->usbkbm_flags |= USBKBM_QWAIT;
516 	while (usbkbmd->usbkbm_flags & USBKBM_QWAIT) {
517 
518 		if (qwait_sig(q) == 0) {
519 			usbkbmd->usbkbm_flags = 0;
520 			(void) kbtrans_streams_fini(usbkbmd->usbkbm_kbtrans);
521 			qprocsoff(q);
522 			kmem_free(usbkbmd, sizeof (*usbkbmd));
523 
524 			return (EINTR);
525 		}
526 	}
527 
528 
529 	/* get the input format from the hid descriptor */
530 	if (usbkbm_get_input_format(usbkbmd) != USB_SUCCESS) {
531 
532 		USB_DPRINTF_L3(PRINT_MASK_OPEN, usbkbm_log_handle,
533 		    "usbkbm: Invalid HID Descriptor Tree."
534 		    "setting default report format");
535 	}
536 
537 	/*
538 	 * Although Sun Japanese type6 and type7 keyboards have the same
539 	 * layout number(15), they should be recognized for loading the
540 	 * different keytables on upper apps (e.g. X). The new layout
541 	 * number (271) is defined for the Sun Japanese type6 keyboards.
542 	 * The layout number (15) specified in HID spec is used for other
543 	 * Japanese keyboards. It is a workaround for the old Sun Japanese
544 	 * type6 keyboards defect.
545 	 */
546 	if (usbkbmd->usbkbm_layout == SUN_JAPANESE_TYPE7) {
547 
548 		if ((ret = usbkbm_get_vid_pid(usbkbmd)) != 0) {
549 
550 			return (ret);
551 		}
552 
553 		if ((usbkbmd->usbkbm_vid_pid.VendorId ==
554 		    HID_SUN_JAPANESE_TYPE6_KBD_VID) &&
555 		    (usbkbmd->usbkbm_vid_pid.ProductId ==
556 		    HID_SUN_JAPANESE_TYPE6_KBD_PID)) {
557 			usbkbmd->usbkbm_layout = SUN_JAPANESE_TYPE6;
558 		}
559 	}
560 
561 	kbtrans_streams_set_keyboard(usbkbmd->usbkbm_kbtrans, KB_USB,
562 	    usbkbm_keyindex);
563 
564 	usbkbmd->usbkbm_flags = USBKBM_OPEN;
565 
566 	kbtrans_streams_enable(usbkbmd->usbkbm_kbtrans);
567 
568 	/*
569 	 * Enable abort sequence on inital. For an internal open, conskbd
570 	 * will disable driver abort handling (later through M_IOCTL) and
571 	 * handle it by itself.
572 	 * For an external (aka. physical) open, this is necessary since
573 	 * no STREAMS module linked on top of usbkbm handles abort sequence.
574 	 */
575 	mctlmsg.ioc_cmd = CONSSETABORTENABLE;
576 	mctlmsg.ioc_count = TRANSPARENT;
577 	mctl_ptr = usba_mk_mctl(mctlmsg, &abortable, sizeof (abortable));
578 	if (mctl_ptr != NULL) {
579 		DB_TYPE(mctl_ptr) = M_IOCTL;
580 		if (kbtrans_streams_message(usbkbmd->usbkbm_kbtrans, mctl_ptr)
581 		    != KBTRANS_MESSAGE_HANDLED) {
582 			freemsg(mctl_ptr);
583 		}
584 	} else {
585 		USB_DPRINTF_L3(PRINT_MASK_OPEN, usbkbm_log_handle,
586 		    "usbkbm: enable abort sequence failed");
587 	}
588 
589 	USB_DPRINTF_L3(PRINT_MASK_OPEN, usbkbm_log_handle,
590 	    "usbkbm_open exiting");
591 	return (0);
592 }
593 
594 
595 /*
596  * usbkbm_close :
597  *	Close a keyboard.
598  */
599 /* ARGSUSED1 */
600 static int
601 usbkbm_close(register queue_t *q, int flag, cred_t *crp)
602 {
603 	usbkbm_state_t *usbkbmd = (usbkbm_state_t *)q->q_ptr;
604 
605 	/* If a beep is in progress, stop that */
606 	(void) beeper_off();
607 
608 	(void) kbtrans_streams_fini(usbkbmd->usbkbm_kbtrans);
609 
610 	qprocsoff(q);
611 	/*
612 	 * Since we're about to destroy our private data, turn off
613 	 * our open flag first, so we don't accept any more input
614 	 * and try to use that data.
615 	 */
616 	usbkbmd->usbkbm_flags = 0;
617 
618 	kmem_free(usbkbmd, sizeof (usbkbm_state_t));
619 
620 	USB_DPRINTF_L3(PRINT_MASK_CLOSE, usbkbm_log_handle,
621 	    "usbkbm_close exiting");
622 
623 	return (0);
624 }
625 
626 
627 /*
628  * usbkbm_wput :
629  *	usb keyboard module output queue put procedure: handles M_IOCTL
630  *	messages.
631  */
632 static void
633 usbkbm_wput(register queue_t *q, register mblk_t *mp)
634 {
635 	usbkbm_state_t			*usbkbmd;
636 	enum kbtrans_message_response	ret;
637 
638 	USB_DPRINTF_L3(PRINT_MASK_ALL, usbkbm_log_handle,
639 	    "usbkbm_wput entering");
640 
641 	usbkbmd = (usbkbm_state_t *)q->q_ptr;
642 
643 	/* First, see if kbtrans will handle the message */
644 	ret = kbtrans_streams_message(usbkbmd->usbkbm_kbtrans, mp);
645 
646 	if (ret == KBTRANS_MESSAGE_HANDLED) {
647 
648 		USB_DPRINTF_L3(PRINT_MASK_ALL, usbkbm_log_handle,
649 		    "usbkbm_wput exiting:2");
650 
651 		return;
652 	}
653 
654 	/* kbtrans didn't handle the message.  Try to handle it here */
655 
656 	switch (mp->b_datap->db_type) {
657 
658 	case M_FLUSH:
659 		if (*mp->b_rptr & FLUSHW) {
660 			flushq(q, FLUSHDATA);
661 		}
662 
663 		if (*mp->b_rptr & FLUSHR) {
664 			flushq(RD(q), FLUSHDATA);
665 		}
666 
667 		break;
668 
669 	case M_IOCTL:
670 		ret = usbkbm_ioctl(q, mp);
671 
672 		if (ret == KBTRANS_MESSAGE_HANDLED) {
673 
674 			USB_DPRINTF_L3(PRINT_MASK_ALL, usbkbm_log_handle,
675 			    "usbkbm_wput exiting:1");
676 
677 			return;
678 		}
679 	default:
680 		break;
681 	}
682 
683 	/*
684 	 * The message has not been handled
685 	 * by kbtrans or this module.  Pass it down the stream
686 	 */
687 	putnext(q, mp);
688 
689 	USB_DPRINTF_L3(PRINT_MASK_ALL, usbkbm_log_handle,
690 	    "usbkbm_wput exiting:3");
691 }
692 
693 /*
694  * usbkbm_ioctl :
695  *	Handles the ioctls sent from upper module. Returns
696  *	ACK/NACK back.
697  */
698 static enum kbtrans_message_response
699 usbkbm_ioctl(register queue_t *q, register mblk_t *mp)
700 {
701 	usbkbm_state_t		*usbkbmd;
702 	struct iocblk		mctlmsg;
703 	struct iocblk		*iocp;
704 	mblk_t			*datap, *mctl_ptr;
705 	size_t			ioctlrespsize;
706 	int			err;
707 	int			tmp;
708 	int			cycles;
709 	int			frequency;
710 	int			msecs;
711 	char			command;
712 
713 	err = 0;
714 
715 	usbkbmd = (usbkbm_state_t *)q->q_ptr;
716 	iocp = (struct iocblk *)mp->b_rptr;
717 
718 	switch (iocp->ioc_cmd) {
719 	case CONSSETKBDTYPE:
720 		err = miocpullup(mp, sizeof (int));
721 		if (err != 0) {
722 			break;
723 		}
724 		tmp = *(int *)mp->b_cont->b_rptr;
725 		if (tmp != KB_PC && tmp != KB_USB) {
726 			err = EINVAL;
727 			break;
728 		}
729 		usbkbmd->usbkbm_vkbd_type = tmp;
730 		break;
731 	case KIOCLAYOUT:
732 
733 		datap = allocb(sizeof (int), BPRI_HI);
734 		if (datap == NULL) {
735 			ioctlrespsize = sizeof (int);
736 
737 			goto allocfailure;
738 		}
739 
740 		*(int *)datap->b_wptr = usbkbmd->usbkbm_layout;
741 		datap->b_wptr += sizeof (int);
742 
743 		freemsg(mp->b_cont);
744 
745 		mp->b_cont = datap;
746 		iocp->ioc_count = sizeof (int);
747 		break;
748 
749 	case KIOCSLAYOUT:
750 		/*
751 		 * Supply a layout if not specified by the hardware, or
752 		 * override any that was specified.
753 		 */
754 		if (iocp->ioc_count != TRANSPARENT) {
755 			err = EINVAL;
756 			break;
757 		}
758 
759 		usbkbmd->usbkbm_layout = *(intptr_t *)mp->b_cont->b_rptr;
760 
761 		/*
762 		 * Save the layout in usbkbm_layout so as to handle the
763 		 * the case when the user has re-plugged in the non-self
764 		 * identifying non US keyboard. In this the layout is saved
765 		 * in global variable, so the user does not have to run
766 		 * kdmconfig again after the X server reset
767 		 */
768 
769 		usbkbm_layout = usbkbmd->usbkbm_layout;
770 		break;
771 
772 	case KIOCCMD:
773 		/*
774 		 * Check if we have at least the subcommand field; any
775 		 * other argument validation has to occur inside
776 		 * usbkbm_kioccmd().
777 		 */
778 		err = miocpullup(mp, sizeof (int));
779 		if (err != 0)
780 			break;
781 
782 		/* Subcommand */
783 		command = (char)(*(int *)mp->b_cont->b_rptr);
784 
785 		/*
786 		 * Check if this ioctl is followed by a previous
787 		 * KBD_CMD_SETLED command, in which case we take
788 		 * the command byte as the data for setting the LED
789 		 */
790 		if (usbkbmd->usbkbm_setled_second_byte) {
791 			usbkbm_streams_setled((struct kbtrans_hardware *)
792 			    usbkbmd, command);
793 			usbkbmd->usbkbm_setled_second_byte = 0;
794 			break;
795 		}
796 
797 		/*
798 		 * In  case of allocb failure, this will
799 		 * return the size of the allocation which
800 		 * failed so that it can be allocated later
801 		 * through bufcall.
802 		 */
803 		ioctlrespsize = 0;
804 
805 		err = usbkbm_kioccmd(usbkbmd, mp, command, &ioctlrespsize);
806 
807 		if (ioctlrespsize != 0) {
808 
809 			goto allocfailure;
810 		}
811 
812 		break;
813 
814 	case CONSOPENPOLLEDIO:
815 		USB_DPRINTF_L3(PRINT_MASK_ALL, usbkbm_log_handle,
816 		    "usbkbm_ioctl CONSOPENPOLLEDIO");
817 
818 		err = miocpullup(mp, sizeof (struct cons_polledio *));
819 		if (err != 0) {
820 			USB_DPRINTF_L2(PRINT_MASK_ALL, usbkbm_log_handle,
821 			    "usbkbm_ioctl: malformed request");
822 			break;
823 		}
824 
825 		usbkbmd->usbkbm_pending_link = mp;
826 
827 		/*
828 		 * Get the polled input structure from hid
829 		 */
830 		mctlmsg.ioc_cmd = HID_OPEN_POLLED_INPUT;
831 		mctlmsg.ioc_count = 0;
832 		mctl_ptr = usba_mk_mctl(mctlmsg, NULL, 0);
833 		if (mctl_ptr == NULL) {
834 			ioctlrespsize = sizeof (mctlmsg);
835 
836 			goto allocfailure;
837 		}
838 
839 		putnext(usbkbmd->usbkbm_writeq, mctl_ptr);
840 
841 		/*
842 		 * Do not ack or nack the message, we will wait for the
843 		 * result of HID_OPEN_POLLED_INPUT
844 		 */
845 
846 		return (KBTRANS_MESSAGE_HANDLED);
847 
848 	case CONSCLOSEPOLLEDIO:
849 		USB_DPRINTF_L3(PRINT_MASK_ALL, usbkbm_log_handle,
850 		    "usbkbm_ioctl CONSCLOSEPOLLEDIO mp = 0x%p", (void *)mp);
851 
852 		usbkbmd->usbkbm_pending_link = mp;
853 
854 		/*
855 		 * Get the polled input structure from hid
856 		 */
857 		mctlmsg.ioc_cmd = HID_CLOSE_POLLED_INPUT;
858 		mctlmsg.ioc_count = 0;
859 		mctl_ptr = usba_mk_mctl(mctlmsg, NULL, 0);
860 		if (mctl_ptr == NULL) {
861 			ioctlrespsize = sizeof (mctlmsg);
862 
863 			goto allocfailure;
864 		}
865 
866 		putnext(usbkbmd->usbkbm_writeq, mctl_ptr);
867 
868 		/*
869 		 * Do not ack or nack the message, we will wait for the
870 		 * result of HID_CLOSE_POLLED_INPUT
871 		 */
872 
873 		return (KBTRANS_MESSAGE_HANDLED);
874 
875 	case CONSSETABORTENABLE:
876 		/*
877 		 * Nothing special to do for USB.
878 		 */
879 		break;
880 
881 
882 	case KIOCMKTONE:
883 		if (iocp->ioc_count != TRANSPARENT) {
884 			err = EINVAL;
885 			break;
886 		}
887 
888 		tmp = (int)(*(intptr_t *)mp->b_cont->b_rptr);
889 		cycles = tmp & 0xffff;
890 		msecs = (tmp >> 16) & 0xffff;
891 
892 		if (cycles == 0)
893 			frequency = UINT16_MAX;
894 		else if (cycles == UINT16_MAX)
895 			frequency = 0;
896 		else {
897 			frequency = (PIT_HZ + cycles / 2) / cycles;
898 			if (frequency > UINT16_MAX)
899 				frequency = UINT16_MAX;
900 		}
901 
902 		err = beep_mktone(frequency, msecs);
903 		break;
904 
905 	default:
906 
907 		return (KBTRANS_MESSAGE_NOT_HANDLED);
908 	}
909 
910 	/*
911 	 * Send ACK/NACK to upper module for
912 	 * the messages that have been handled.
913 	 */
914 	if (err != 0) {
915 		iocp->ioc_rval = 0;
916 		iocp->ioc_error = err;
917 		mp->b_datap->db_type = M_IOCNAK;
918 	} else {
919 		iocp->ioc_rval = 0;
920 		iocp->ioc_error = 0;	/* brain rot */
921 		mp->b_datap->db_type = M_IOCACK;
922 	}
923 
924 	/* Send the response back up the stream */
925 	putnext(usbkbmd->usbkbm_readq, mp);
926 
927 	return (KBTRANS_MESSAGE_HANDLED);
928 
929 allocfailure:
930 	/*
931 	 * We needed to allocate something to handle this "ioctl", but
932 	 * couldn't; save this "ioctl" and arrange to get called back when
933 	 * it's more likely that we can get what we need.
934 	 * If there's already one being saved, throw it out, since it
935 	 * must have timed out.
936 	 */
937 	freemsg(usbkbmd->usbkbm_streams_iocpending);
938 	usbkbmd->usbkbm_streams_iocpending = mp;
939 
940 	if (usbkbmd->usbkbm_streams_bufcallid) {
941 
942 		qunbufcall(usbkbmd->usbkbm_readq,
943 		    usbkbmd->usbkbm_streams_bufcallid);
944 	}
945 	usbkbmd->usbkbm_streams_bufcallid =
946 	    qbufcall(usbkbmd->usbkbm_readq, ioctlrespsize, BPRI_HI,
947 	    usbkbm_reioctl, usbkbmd);
948 
949 	return (KBTRANS_MESSAGE_HANDLED);
950 }
951 
952 /*
953  * usbkbm_kioccmd :
954  *	Handles KIOCCMD ioctl.
955  */
956 static int
957 usbkbm_kioccmd(usbkbm_state_t *usbkbmd, register mblk_t *mp,
958 		char command, size_t *ioctlrepsize)
959 {
960 	register mblk_t			*datap;
961 	register struct iocblk		*iocp;
962 	int				err = 0;
963 
964 	iocp = (struct iocblk *)mp->b_rptr;
965 
966 	switch (command) {
967 
968 		/* Keyboard layout command */
969 		case KBD_CMD_GETLAYOUT:
970 			/* layout learned at attached time. */
971 			datap = allocb(sizeof (int), BPRI_HI);
972 
973 			/* Return error  on allocation failure */
974 			if (datap == NULL) {
975 				*ioctlrepsize = sizeof (int);
976 
977 				return (EIO);
978 			}
979 
980 			*(int *)datap->b_wptr = usbkbmd->usbkbm_layout;
981 			datap->b_wptr += sizeof (int);
982 			freemsg(mp->b_cont);
983 			mp->b_cont = datap;
984 			iocp->ioc_count = sizeof (int);
985 			break;
986 
987 		case KBD_CMD_SETLED:
988 			/*
989 			 * Emulate type 4 keyboard :
990 			 * Ignore this ioctl; the following
991 			 * ioctl will specify the data byte for
992 			 * setting the LEDs; setting usbkbm_setled_second_byte
993 			 * will help recognizing that ioctl
994 			 */
995 			usbkbmd->usbkbm_setled_second_byte = 1;
996 			break;
997 
998 		case KBD_CMD_RESET:
999 			break;
1000 
1001 		case KBD_CMD_BELL:
1002 			/*
1003 			 * USB keyboards do not have a beeper
1004 			 * in it, the generic beeper interface
1005 			 * is used. Turn the beeper on.
1006 			 */
1007 			(void) beeper_on(BEEP_TYPE4);
1008 			break;
1009 
1010 		case KBD_CMD_NOBELL:
1011 			/*
1012 			 * USB keyboards do not have a beeper
1013 			 * in it, the generic beeper interface
1014 			 * is used. Turn the beeper off.
1015 			 */
1016 			(void) beeper_off();
1017 			break;
1018 
1019 		case KBD_CMD_CLICK:
1020 			/* FALLTHRU */
1021 		case KBD_CMD_NOCLICK:
1022 			break;
1023 
1024 		default:
1025 			err = EIO;
1026 			break;
1027 
1028 	}
1029 
1030 	return (err);
1031 }
1032 
1033 
1034 /*
1035  * usbkbm_rput :
1036  *	Put procedure for input from driver end of stream (read queue).
1037  */
1038 static void
1039 usbkbm_rput(register queue_t *q, register mblk_t *mp)
1040 {
1041 	usbkbm_state_t		*usbkbmd;
1042 
1043 	usbkbmd = (usbkbm_state_t *)q->q_ptr;
1044 
1045 	USB_DPRINTF_L3(PRINT_MASK_ALL, usbkbm_log_handle,
1046 	    "usbkbm_rput");
1047 
1048 	if (usbkbmd == 0) {
1049 		freemsg(mp);	/* nobody's listening */
1050 
1051 		return;
1052 	}
1053 
1054 	switch (mp->b_datap->db_type) {
1055 
1056 	case M_FLUSH:
1057 		if (*mp->b_rptr & FLUSHW)
1058 			flushq(WR(q), FLUSHDATA);
1059 		if (*mp->b_rptr & FLUSHR)
1060 			flushq(q, FLUSHDATA);
1061 
1062 		freemsg(mp);
1063 
1064 		return;
1065 	case M_BREAK:
1066 		/*
1067 		 * Will get M_BREAK only if this is not the system
1068 		 * keyboard, otherwise serial port will eat break
1069 		 * and call kmdb/OBP, without passing anything up.
1070 		 */
1071 		freemsg(mp);
1072 
1073 		return;
1074 	case M_DATA:
1075 		if (!(usbkbmd->usbkbm_flags & USBKBM_OPEN)) {
1076 			freemsg(mp);	/* not ready to listen */
1077 
1078 			return;
1079 		}
1080 
1081 		break;
1082 	case M_CTL:
1083 		usbkbm_mctl_receive(q, mp);
1084 
1085 		return;
1086 	case M_ERROR:
1087 		usbkbmd->usbkbm_flags &= ~USBKBM_QWAIT;
1088 		if (*mp->b_rptr == ENODEV) {
1089 			putnext(q, mp);
1090 		} else {
1091 			freemsg(mp);
1092 		}
1093 
1094 		return;
1095 	case M_IOCACK:
1096 	case M_IOCNAK:
1097 		putnext(q, mp);
1098 
1099 		return;
1100 	default:
1101 		putnext(q, mp);
1102 
1103 		return;
1104 	}
1105 
1106 	/*
1107 	 * A data message, consisting of bytes from the keyboard.
1108 	 * Ram them through the translator, only if there are
1109 	 * correct no. of bytes.
1110 	 */
1111 	if (MBLKL(mp) == usbkbmd->usbkbm_report_format.tlen) {
1112 		if (usbkbmd->usbkbm_report_format.keyid !=
1113 		    HID_REPORT_ID_UNDEFINED) {
1114 			if (*(mp->b_rptr) !=
1115 			    usbkbmd->usbkbm_report_format.keyid) {
1116 				freemsg(mp);
1117 
1118 				return;
1119 			} else {
1120 				/* We skip the report id prefix */
1121 				mp->b_rptr++;
1122 			}
1123 		}
1124 		usbkbm_unpack_usb_packet(usbkbmd, usbkbm_streams_callback,
1125 		    mp->b_rptr);
1126 	}
1127 
1128 	freemsg(mp);
1129 }
1130 
1131 /*
1132  * usbkbm_mctl_receive :
1133  *	Handle M_CTL messages from hid. If we don't understand
1134  *	the command, send it up.
1135  */
1136 static void
1137 usbkbm_mctl_receive(register queue_t *q, register mblk_t *mp)
1138 {
1139 	register usbkbm_state_t *usbkbmd = (usbkbm_state_t *)q->q_ptr;
1140 	register struct iocblk *iocp;
1141 	caddr_t  data = NULL;
1142 	mblk_t	*reply_mp;
1143 	uchar_t	new_buffer[USBKBM_MAXPKTSIZE];
1144 	size_t	 size;
1145 
1146 	iocp = (struct iocblk *)mp->b_rptr;
1147 	if (mp->b_cont != NULL)
1148 		data = (caddr_t)mp->b_cont->b_rptr;
1149 
1150 	switch (iocp->ioc_cmd) {
1151 
1152 	case HID_SET_REPORT:
1153 		USB_DPRINTF_L3(PRINT_MASK_ALL, usbkbm_log_handle,
1154 		    "usbkbm_mctl_receive HID_SET mctl");
1155 		freemsg(mp);
1156 		/* Setting of the LED is not waiting for this message */
1157 
1158 		break;
1159 	case HID_GET_PARSER_HANDLE:
1160 		if ((data != NULL) &&
1161 		    (iocp->ioc_count == sizeof (hidparser_handle_t)) &&
1162 		    (MBLKL(mp->b_cont) == iocp->ioc_count)) {
1163 			usbkbmd->usbkbm_report_descr =
1164 			    *(hidparser_handle_t *)data;
1165 		} else {
1166 			usbkbmd->usbkbm_report_descr = NULL;
1167 		}
1168 		freemsg(mp);
1169 		usbkbmd->usbkbm_flags &= ~USBKBM_QWAIT;
1170 
1171 		break;
1172 	case HID_GET_VID_PID:
1173 		if ((data != NULL) &&
1174 		    (iocp->ioc_count == sizeof (hid_vid_pid_t)) &&
1175 		    (MBLKL(mp->b_cont) == iocp->ioc_count)) {
1176 			bcopy(data, &usbkbmd->usbkbm_vid_pid, iocp->ioc_count);
1177 		}
1178 		freemsg(mp);
1179 		usbkbmd->usbkbm_flags &= ~USBKBM_QWAIT;
1180 
1181 		break;
1182 	case HID_OPEN_POLLED_INPUT:
1183 		USB_DPRINTF_L3(PRINT_MASK_ALL, usbkbm_log_handle,
1184 		    "usbkbm_mctl_receive HID_OPEN_POLLED_INPUT");
1185 
1186 		size = sizeof (hid_polled_input_callback_t);
1187 		reply_mp = usbkbmd->usbkbm_pending_link;
1188 		if ((data != NULL) &&
1189 		    (iocp->ioc_count == size) &&
1190 		    (MBLKL(mp->b_cont) == size)) {
1191 			/*
1192 			 *  Copy the information from hid into the
1193 			 * state structure
1194 			 */
1195 			bcopy(data, &usbkbmd->usbkbm_hid_callback, size);
1196 			reply_mp->b_datap->db_type = M_IOCACK;
1197 
1198 			/*
1199 			 * We are given an appropriate-sized data block,
1200 			 * and return a pointer to our structure in it.
1201 			 * The structure is saved in the states structure
1202 			 */
1203 			*(cons_polledio_t **)reply_mp->b_cont->b_rptr =
1204 			    &usbkbmd->usbkbm_polled_info;
1205 
1206 		} else {
1207 			reply_mp->b_datap->db_type = M_IOCNAK;
1208 		}
1209 		freemsg(mp);
1210 
1211 		usbkbmd->usbkbm_pending_link = NULL;
1212 
1213 		putnext(q, reply_mp);
1214 
1215 		break;
1216 	case HID_CLOSE_POLLED_INPUT:
1217 		USB_DPRINTF_L3(PRINT_MASK_ALL, usbkbm_log_handle,
1218 		    "usbkbm_mctl_receive HID_CLOSE_POLLED_INPUT");
1219 
1220 
1221 		bzero(&usbkbmd->usbkbm_hid_callback,
1222 		    sizeof (hid_polled_input_callback_t));
1223 
1224 		freemsg(mp);
1225 
1226 		reply_mp = usbkbmd->usbkbm_pending_link;
1227 
1228 		iocp = (struct iocblk *)reply_mp->b_rptr;
1229 
1230 		USB_DPRINTF_L3(PRINT_MASK_ALL, usbkbm_log_handle,
1231 		    "usbkbm_mctl_receive reply reply_mp 0x%p cmd 0x%x",
1232 		    (void *)reply_mp, iocp->ioc_cmd);
1233 
1234 
1235 		reply_mp->b_datap->db_type = M_IOCACK;
1236 
1237 		usbkbmd->usbkbm_pending_link = NULL;
1238 
1239 		putnext(q, reply_mp);
1240 
1241 		break;
1242 	case HID_DISCONNECT_EVENT :
1243 	case HID_POWER_OFF:
1244 		USB_DPRINTF_L3(PRINT_MASK_ALL, usbkbm_log_handle,
1245 		    "usbkbm_mctl_receive HID_DISCONNECT_EVENT/HID_POWER_OFF");
1246 
1247 		/* Indicate all keys have been released */
1248 		bzero(new_buffer, USBKBM_MAXPKTSIZE);
1249 		usbkbm_unpack_usb_packet(usbkbmd, usbkbm_streams_callback,
1250 		    new_buffer);
1251 		freemsg(mp);
1252 
1253 		break;
1254 	case HID_CONNECT_EVENT:
1255 	case HID_FULL_POWER :
1256 		USB_DPRINTF_L3(PRINT_MASK_ALL, usbkbm_log_handle,
1257 		    "usbkbm_mctl_receive restore LEDs");
1258 
1259 		/* send setled command down to restore LED states */
1260 		usbkbm_streams_setled((struct kbtrans_hardware *)usbkbmd,
1261 		    usbkbm_led_state);
1262 
1263 		freemsg(mp);
1264 
1265 		break;
1266 	default:
1267 		putnext(q, mp);
1268 
1269 		break;
1270 	}
1271 }
1272 
1273 
1274 /*
1275  * usbkbm_streams_setled :
1276  *	Update the keyboard LEDs to match the current keyboard state.
1277  *	Send LED state downstreams to hid driver.
1278  */
1279 static void
1280 usbkbm_streams_setled(struct kbtrans_hardware *kbtrans_hw, int state)
1281 {
1282 	struct iocblk	mctlmsg;
1283 	mblk_t		*mctl_ptr;
1284 	hid_req_t	*LED_report;
1285 	usbkbm_state_t	*usbkbmd;
1286 	uchar_t		led_id, led_state;
1287 
1288 	usbkbm_led_state = (uchar_t)state;
1289 
1290 	usbkbmd = (usbkbm_state_t *)kbtrans_hw;
1291 
1292 	LED_report = kmem_zalloc(sizeof (hid_req_t), KM_NOSLEEP);
1293 	if (LED_report == NULL) {
1294 
1295 		return;
1296 	}
1297 
1298 	/*
1299 	 * Send the request to the hid driver to set LED.
1300 	 */
1301 	led_id = usbkbmd->usbkbm_report_format.keyid;
1302 	led_state = 0;
1303 
1304 	/*
1305 	 * Set the led state based on the state that is passed in.
1306 	 */
1307 	if (state & LED_NUM_LOCK) {
1308 		led_state |= USB_LED_NUM_LOCK;
1309 	}
1310 
1311 	if (state & LED_COMPOSE) {
1312 		led_state |= USB_LED_COMPOSE;
1313 	}
1314 
1315 	if (state & LED_SCROLL_LOCK) {
1316 		led_state |= USB_LED_SCROLL_LOCK;
1317 	}
1318 
1319 	if (state & LED_CAPS_LOCK) {
1320 		led_state |= USB_LED_CAPS_LOCK;
1321 	}
1322 
1323 	if (state & LED_KANA) {
1324 		led_state |= USB_LED_KANA;
1325 	}
1326 
1327 	LED_report->hid_req_version_no = HID_VERSION_V_0;
1328 	LED_report->hid_req_wValue = REPORT_TYPE_OUTPUT | led_id;
1329 	LED_report->hid_req_wLength = sizeof (uchar_t);
1330 	LED_report->hid_req_data[0] = led_state;
1331 
1332 	mctlmsg.ioc_cmd = HID_SET_REPORT;
1333 	mctlmsg.ioc_count = sizeof (LED_report);
1334 	mctl_ptr = usba_mk_mctl(mctlmsg, LED_report, sizeof (hid_req_t));
1335 	if (mctl_ptr != NULL) {
1336 		putnext(usbkbmd->usbkbm_writeq, mctl_ptr);
1337 	}
1338 
1339 	/*
1340 	 * We are not waiting for response of HID_SET_REPORT
1341 	 * mctl for setting the LED.
1342 	 */
1343 	kmem_free(LED_report, sizeof (hid_req_t));
1344 }
1345 
1346 
1347 /*
1348  * usbkbm_polled_keycheck :
1349  *	This routine is called to determine if there is a scancode that
1350  *	is available for input.  This routine is called at poll time and
1351  *	returns a key/state pair to the caller.  If there are characters
1352  *	buffered up, the routine returns right away with the key/state pair.
1353  *	Otherwise, the routine calls down to check for characters and returns
1354  *	the first key/state pair if there are any characters pending.
1355  */
1356 static boolean_t
1357 usbkbm_polled_keycheck(struct kbtrans_hardware *hw,
1358 	int *key, enum keystate *state)
1359 {
1360 	usbkbm_state_t			*usbkbmd;
1361 	uchar_t				*buffer;
1362 	unsigned			size;
1363 	hid_polled_handle_t		hid_polled_handle;
1364 
1365 	usbkbmd = (usbkbm_state_t *)hw;
1366 
1367 	/*
1368 	 * If there are already characters buffered up, then we are done.
1369 	 */
1370 	if (usbkbmd->usbkbm_polled_buffer_num_characters != 0) {
1371 
1372 		usbkbm_get_scancode(usbkbmd, key, state);
1373 
1374 		return (B_TRUE);
1375 	}
1376 
1377 	hid_polled_handle =
1378 	    usbkbmd->usbkbm_hid_callback.hid_polled_input_handle;
1379 
1380 	size = (usbkbmd->usbkbm_hid_callback.hid_polled_read)
1381 	    (hid_polled_handle, &buffer);
1382 
1383 	/*
1384 	 * If we don't get a valid input report then indicate that,
1385 	 * and we are done.
1386 	 */
1387 	if (size != usbkbmd->usbkbm_report_format.tlen) {
1388 		return (B_FALSE);
1389 	}
1390 
1391 	/*
1392 	 * We have a usb packet, so pass this packet to
1393 	 * usbkbm_unpack_usb_packet so that it can be broken up into
1394 	 * individual key/state values.
1395 	 */
1396 	if (usbkbmd->usbkbm_report_format.keyid != HID_REPORT_ID_UNDEFINED) {
1397 		if (*buffer != usbkbmd->usbkbm_report_format.keyid) {
1398 			return (B_FALSE);
1399 		} else {
1400 			/* We skip the report id prefix */
1401 			buffer++;
1402 		}
1403 	}
1404 	usbkbm_unpack_usb_packet(usbkbmd, usbkbm_poll_callback, buffer);
1405 
1406 	/*
1407 	 * If a scancode was returned as a result of this packet,
1408 	 * then translate the scancode.
1409 	 */
1410 	if (usbkbmd->usbkbm_polled_buffer_num_characters != 0) {
1411 
1412 		usbkbm_get_scancode(usbkbmd, key, state);
1413 
1414 		return (B_TRUE);
1415 	}
1416 
1417 	return (B_FALSE);
1418 }
1419 
1420 static ushort_t	usbkbm_get_state(usbkbm_state_t *usbkbmd)
1421 {
1422 	ushort_t	ret;
1423 
1424 	ASSERT(usbkbmd->usbkbm_vkbd_type == KB_PC ||
1425 	    usbkbmd->usbkbm_vkbd_type == KB_USB);
1426 
1427 	if (usbkbmd->usbkbm_vkbd_type == KB_PC)
1428 		ret = INDEXTO_PC;
1429 	else
1430 		ret = INDEXTO_USB;
1431 
1432 	return (ret);
1433 }
1434 /*
1435  * usbkbm_streams_callback :
1436  *	This is the routine that is going to be called when unpacking
1437  *	usb packets for normal streams-based input.  We pass a pointer
1438  *	to this routine to usbkbm_unpack_usb_packet.  This routine will
1439  *	get called with an unpacked key (scancode) and state (press/release).
1440  *	We pass it to the generic keyboard module.
1441  *
1442  *	'index' and the function pointers:
1443  *	Map USB scancodes to PC scancodes by lookup table.
1444  *	This fix is mainly meant for x86 platforms. For SPARC systems
1445  *	this fix doesn't change the way in which the scancodes are processed.
1446  */
1447 static void
1448 usbkbm_streams_callback(usbkbm_state_t *usbkbmd, int key, enum keystate state)
1449 {
1450 	ushort_t index = usbkbm_get_state(usbkbmd);
1451 	(*usbkbm_xlate[index])(usbkbmd, key, state);
1452 }
1453 
1454 /*
1455  * Don't do any translations. Send to 'kbtrans' for processing.
1456  */
1457 static void
1458 usbkbm_wrap_kbtrans(usbkbm_state_t *usbkbmd, int key, enum keystate state)
1459 {
1460 	kbtrans_streams_key(usbkbmd->usbkbm_kbtrans, key, state);
1461 }
1462 
1463 /*
1464  * Translate USB scancodes to PC scancodes before sending it to 'kbtrans'
1465  */
1466 void
1467 usbkbm_usb2pc_xlate(usbkbm_state_t *usbkbmd, int key, enum keystate state)
1468 {
1469 	key = kbtrans_keycode_usb2pc(key);
1470 	kbtrans_streams_key(usbkbmd->usbkbm_kbtrans, key, state);
1471 }
1472 
1473 /*
1474  * usbkbm_poll_callback :
1475  *	This is the routine that is going to be called when unpacking
1476  *	usb packets for polled input.  We pass a pointer to this routine
1477  *	to usbkbm_unpack_usb_packet.  This routine will get called with
1478  *	an unpacked key (scancode) and state (press/release).  We will
1479  *	store the key/state pair into a circular buffer so that it can
1480  *	be translated into an ascii key later.
1481  */
1482 static void
1483 usbkbm_poll_callback(usbkbm_state_t *usbkbmd, int key, enum keystate state)
1484 {
1485 	/*
1486 	 * Check to make sure that the buffer isn't already full
1487 	 */
1488 	if (usbkbmd->usbkbm_polled_buffer_num_characters ==
1489 	    USB_POLLED_BUFFER_SIZE) {
1490 
1491 		/*
1492 		 * The buffer is full, we will drop this character.
1493 		 */
1494 		return;
1495 	}
1496 
1497 	/*
1498 	 * Save the scancode in the buffer
1499 	 */
1500 	usbkbmd->usbkbm_polled_buffer_head->poll_key = key;
1501 	usbkbmd->usbkbm_polled_buffer_head->poll_state = state;
1502 
1503 	/*
1504 	 * We have one more character in the buffer
1505 	 */
1506 	usbkbmd->usbkbm_polled_buffer_num_characters++;
1507 
1508 	/*
1509 	 * Increment to the next available slot.
1510 	 */
1511 	usbkbmd->usbkbm_polled_buffer_head++;
1512 
1513 	/*
1514 	 * Check to see if the tail has wrapped.
1515 	 */
1516 	if (usbkbmd->usbkbm_polled_buffer_head -
1517 	    usbkbmd->usbkbm_polled_scancode_buffer ==
1518 	    USB_POLLED_BUFFER_SIZE) {
1519 
1520 		usbkbmd->usbkbm_polled_buffer_head =
1521 		    usbkbmd->usbkbm_polled_scancode_buffer;
1522 	}
1523 }
1524 
1525 /*
1526  * usbkbm_get_scancode :
1527  *	This routine retreives a key/state pair from the circular buffer.
1528  *	The pair was put in the buffer by usbkbm_poll_callback when a
1529  *	USB packet was translated into a key/state by usbkbm_unpack_usb_packet.
1530  */
1531 static void
1532 usbkbm_get_scancode(usbkbm_state_t *usbkbmd, int *key, enum keystate *state)
1533 {
1534 	/*
1535 	 * Copy the character.
1536 	 */
1537 	*key = usbkbmd->usbkbm_polled_buffer_tail->poll_key;
1538 	*state = usbkbmd->usbkbm_polled_buffer_tail->poll_state;
1539 
1540 	/*
1541 	 * Increment to the next character to be copied from
1542 	 * and to.
1543 	 */
1544 	usbkbmd->usbkbm_polled_buffer_tail++;
1545 
1546 	/*
1547 	 * Check to see if the tail has wrapped.
1548 	 */
1549 	if (usbkbmd->usbkbm_polled_buffer_tail -
1550 	    usbkbmd->usbkbm_polled_scancode_buffer ==
1551 	    USB_POLLED_BUFFER_SIZE) {
1552 
1553 		usbkbmd->usbkbm_polled_buffer_tail =
1554 		    usbkbmd->usbkbm_polled_scancode_buffer;
1555 	}
1556 
1557 	/*
1558 	 * We have one less character in the buffer.
1559 	 */
1560 	usbkbmd->usbkbm_polled_buffer_num_characters--;
1561 }
1562 
1563 /*
1564  * usbkbm_polled_setled :
1565  *	This routine is a place holder.  Someday, we may want to allow led
1566  *	state to be updated from within polled mode.
1567  */
1568 /* ARGSUSED */
1569 static void
1570 usbkbm_polled_setled(struct kbtrans_hardware *hw, int led_state)
1571 {
1572 	/* nothing to do for now */
1573 }
1574 
1575 /*
1576  * This is a pass-thru routine to get a character at poll time.
1577  */
1578 static int
1579 usbkbm_polled_getchar(cons_polledio_arg_t arg)
1580 {
1581 	usbkbm_state_t			*usbkbmd;
1582 
1583 	usbkbmd = (usbkbm_state_t *)arg;
1584 
1585 	return (kbtrans_getchar(usbkbmd->usbkbm_kbtrans));
1586 }
1587 
1588 /*
1589  * This is a pass-thru routine to test if character is available for reading
1590  * at poll time.
1591  */
1592 static boolean_t
1593 usbkbm_polled_ischar(cons_polledio_arg_t arg)
1594 {
1595 	usbkbm_state_t			*usbkbmd;
1596 
1597 	usbkbmd = (usbkbm_state_t *)arg;
1598 
1599 	return (kbtrans_ischar(usbkbmd->usbkbm_kbtrans));
1600 }
1601 
1602 /*
1603  * usbkbm_polled_input_enter :
1604  *	This is a pass-thru initialization routine for the lower layer drivers.
1605  *	This routine is called at poll time to set the state for polled input.
1606  */
1607 static void
1608 usbkbm_polled_enter(cons_polledio_arg_t arg)
1609 {
1610 	usbkbm_state_t		*usbkbmd = (usbkbm_state_t *)arg;
1611 	hid_polled_handle_t	hid_polled_handle;
1612 	int			kbstart, kbend, uindex;
1613 
1614 	kbstart = usbkbmd->usbkbm_report_format.kpos;
1615 	kbend = kbstart + usbkbmd->usbkbm_report_format.klen;
1616 
1617 	/*
1618 	 * Before switching to POLLED mode, copy the contents of
1619 	 * usbkbm_pendingusbpacket to usbkbm_lastusbpacket since
1620 	 * usbkbm_pendingusbpacket field has currently processed
1621 	 * key events of the current OS mode usb keyboard packet.
1622 	 */
1623 	for (uindex = kbstart + 2; uindex < kbend; uindex++) {
1624 		usbkbmd->usbkbm_lastusbpacket[uindex] =
1625 		    usbkbmd->usbkbm_pendingusbpacket[uindex];
1626 
1627 		usbkbmd->usbkbm_pendingusbpacket[uindex] = 0;
1628 	}
1629 
1630 	hid_polled_handle =
1631 	    usbkbmd->usbkbm_hid_callback.hid_polled_input_handle;
1632 
1633 	(void) (usbkbmd->usbkbm_hid_callback.hid_polled_input_enter)
1634 	    (hid_polled_handle);
1635 }
1636 
1637 /*
1638  * usbkbm_polled_input_exit :
1639  *	This is a pass-thru restoration routine for the lower layer drivers.
1640  *	This routine is called at poll time to reset the state back to streams
1641  *	input.
1642  */
1643 static void
1644 usbkbm_polled_exit(cons_polledio_arg_t arg)
1645 {
1646 	usbkbm_state_t		*usbkbmd = (usbkbm_state_t *)arg;
1647 	hid_polled_handle_t	hid_polled_handle;
1648 	int			kbstart, kbend, uindex;
1649 
1650 	kbstart = usbkbmd->usbkbm_report_format.kpos;
1651 	kbend = kbstart + usbkbmd->usbkbm_report_format.klen;
1652 
1653 	/*
1654 	 * Before returning to OS mode, copy the contents of
1655 	 * usbkbm_lastusbpacket to usbkbm_pendingusbpacket since
1656 	 * usbkbm_lastusbpacket field has processed key events
1657 	 * of the last POLLED mode usb keyboard packet.
1658 	 */
1659 	for (uindex = kbstart + 2; uindex < kbend; uindex ++) {
1660 		usbkbmd->usbkbm_pendingusbpacket[uindex] =
1661 		    usbkbmd->usbkbm_lastusbpacket[uindex];
1662 
1663 		usbkbmd->usbkbm_lastusbpacket[uindex] = 0;
1664 	}
1665 
1666 	hid_polled_handle =
1667 	    usbkbmd->usbkbm_hid_callback.hid_polled_input_handle;
1668 
1669 	(void) (usbkbmd->usbkbm_hid_callback.hid_polled_input_exit)
1670 	    (hid_polled_handle);
1671 }
1672 
1673 /*
1674  * usbkbm_unpack_usb_packet :
1675  *	USB key packets contain 8 bytes while in boot-protocol mode.
1676  *	The first byte contains bit packed modifier key information.
1677  *	Second byte is reserved. The last 6 bytes contain bytes of
1678  *	currently pressed keys. If a key was not recorded on the
1679  *	previous packet, but present in the current packet, then set
1680  *	state to KEY_PRESSED. If a key was recorded in the previous packet,
1681  *	but not present in the current packet, then state to KEY_RELEASED
1682  *	Follow a similar algorithm for bit packed modifier keys.
1683  */
1684 static void
1685 usbkbm_unpack_usb_packet(usbkbm_state_t *usbkbmd, process_key_callback_t func,
1686 	uchar_t *usbpacket)
1687 {
1688 	uchar_t		mkb;
1689 	uchar_t		lastmkb;
1690 	uchar_t		*lastusbpacket = usbkbmd->usbkbm_lastusbpacket;
1691 	int		packet_size, kbstart, kbend;
1692 	int		uindex, lindex, rollover;
1693 
1694 	packet_size = usbkbmd->usbkbm_report_format.tlen;
1695 	kbstart = usbkbmd->usbkbm_report_format.kpos;
1696 	kbend = kbstart + usbkbmd->usbkbm_report_format.klen;
1697 	mkb = usbpacket[kbstart];
1698 	lastmkb = lastusbpacket[kbstart];
1699 
1700 	for (uindex = 0; uindex < packet_size; uindex++) {
1701 
1702 		USB_DPRINTF_L3(PRINT_MASK_PACKET, usbkbm_log_handle,
1703 		    " %x ", usbpacket[uindex]);
1704 	}
1705 
1706 	USB_DPRINTF_L3(PRINT_MASK_PACKET, usbkbm_log_handle,
1707 	    " is the usbkeypacket");
1708 
1709 	/* check to see if modifier keys are different */
1710 	if (mkb != lastmkb) {
1711 
1712 		if ((mkb & USB_LSHIFTBIT) != (lastmkb & USB_LSHIFTBIT)) {
1713 			(*func)(usbkbmd, USB_LSHIFTKEY, (mkb&USB_LSHIFTBIT) ?
1714 			    KEY_PRESSED : KEY_RELEASED);
1715 			USB_DPRINTF_L3(PRINT_MASK_ALL, usbkbm_log_handle,
1716 			    "unpack: sending USB_LSHIFTKEY");
1717 		}
1718 
1719 		if ((mkb & USB_LCTLBIT) != (lastmkb & USB_LCTLBIT)) {
1720 			(*func)(usbkbmd, USB_LCTLCKEY, mkb&USB_LCTLBIT ?
1721 			    KEY_PRESSED : KEY_RELEASED);
1722 		}
1723 
1724 		if ((mkb & USB_LALTBIT) != (lastmkb & USB_LALTBIT)) {
1725 			(*func)(usbkbmd, USB_LALTKEY, mkb&USB_LALTBIT ?
1726 			    KEY_PRESSED : KEY_RELEASED);
1727 		}
1728 
1729 		if ((mkb & USB_LMETABIT) != (lastmkb & USB_LMETABIT)) {
1730 			(*func)(usbkbmd, USB_LMETAKEY, mkb&USB_LMETABIT ?
1731 			    KEY_PRESSED : KEY_RELEASED);
1732 		}
1733 
1734 		if ((mkb & USB_RMETABIT) != (lastmkb & USB_RMETABIT)) {
1735 			(*func)(usbkbmd, USB_RMETAKEY, mkb&USB_RMETABIT ?
1736 			    KEY_PRESSED : KEY_RELEASED);
1737 		}
1738 
1739 		if ((mkb & USB_RALTBIT) != (lastmkb & USB_RALTBIT)) {
1740 			(*func)(usbkbmd, USB_RALTKEY, mkb&USB_RALTBIT ?
1741 			    KEY_PRESSED : KEY_RELEASED);
1742 		}
1743 
1744 		if ((mkb & USB_RCTLBIT) != (lastmkb & USB_RCTLBIT)) {
1745 			(*func)(usbkbmd, USB_RCTLCKEY, mkb&USB_RCTLBIT ?
1746 			    KEY_PRESSED : KEY_RELEASED);
1747 		}
1748 
1749 		if ((mkb & USB_RSHIFTBIT) != (lastmkb & USB_RSHIFTBIT)) {
1750 			(*func)(usbkbmd, USB_RSHIFTKEY, mkb&USB_RSHIFTBIT ?
1751 			    KEY_PRESSED : KEY_RELEASED);
1752 			USB_DPRINTF_L3(PRINT_MASK_ALL, usbkbm_log_handle,
1753 			    "unpack: sending USB_RSHIFTKEY");
1754 		}
1755 	}
1756 
1757 	/* save modifier bits */
1758 	lastusbpacket[kbstart] = usbpacket[kbstart];
1759 
1760 	/* Check Keyboard rollover error. */
1761 	if (usbpacket[kbstart + 2] == USB_ERRORROLLOVER) {
1762 		rollover = 1;
1763 		for (uindex = kbstart + 3; uindex < kbend;
1764 		    uindex++) {
1765 			if (usbpacket[uindex] != USB_ERRORROLLOVER) {
1766 				rollover = 0;
1767 				break;
1768 			}
1769 		}
1770 		if (rollover) {
1771 			USB_DPRINTF_L3(PRINT_MASK_ALL, usbkbm_log_handle,
1772 			    "unpack: errorrollover");
1773 			return;
1774 		}
1775 	}
1776 
1777 	/* check for released keys */
1778 	for (lindex = kbstart + 2; lindex < kbend; lindex++) {
1779 		int released = 1;
1780 
1781 		if (lastusbpacket[lindex] == 0) {
1782 			continue;
1783 		}
1784 		for (uindex = kbstart + 2; uindex < kbend; uindex++)
1785 			if (usbpacket[uindex] == lastusbpacket[lindex]) {
1786 				released = 0;
1787 				break;
1788 			}
1789 		if (released) {
1790 			(*func)(usbkbmd, lastusbpacket[lindex], KEY_RELEASED);
1791 		}
1792 	}
1793 
1794 	/* check for new presses */
1795 	for (uindex = kbstart + 2; uindex < kbend; uindex++) {
1796 		int newkey = 1;
1797 
1798 		usbkbmd->usbkbm_pendingusbpacket[uindex] = usbpacket[uindex];
1799 
1800 		if (usbpacket[uindex] == 0) {
1801 			continue;
1802 		}
1803 
1804 		for (lindex = kbstart + 2; lindex < kbend; lindex++) {
1805 			if (usbpacket[uindex] == lastusbpacket[lindex]) {
1806 				newkey = 0;
1807 				break;
1808 			}
1809 		}
1810 
1811 		if (newkey) {
1812 			/*
1813 			 * Modifier keys can be present as part of both the
1814 			 * first byte and as separate key bytes. In the sec-
1815 			 * ond case ignore it.
1816 			 */
1817 
1818 			if (!usbkbm_is_modkey(usbpacket[uindex])) {
1819 				(*func)(usbkbmd, usbpacket[uindex],
1820 				    KEY_PRESSED);
1821 			} else {
1822 				usbkbmd->usbkbm_pendingusbpacket[uindex] = 0;
1823 
1824 				continue;
1825 			}
1826 		}
1827 	}
1828 
1829 	/*
1830 	 * Copy the processed key events of the current usb keyboard
1831 	 * packet, which is saved in the usbkbm_pendingusbpacket field
1832 	 * to the usbkbm_lastusbpacket field.
1833 	 */
1834 	for (uindex = kbstart + 2; uindex < kbend; uindex++) {
1835 		lastusbpacket[uindex] =
1836 		    usbkbmd->usbkbm_pendingusbpacket[uindex];
1837 		usbkbmd->usbkbm_pendingusbpacket[uindex] = 0;
1838 	}
1839 }
1840 
1841 static boolean_t
1842 usbkbm_is_modkey(uchar_t key)
1843 {
1844 
1845 	switch (key) {
1846 
1847 	case USB_LSHIFTKEY:
1848 	case USB_LCTLCKEY:
1849 	case USB_LALTKEY:
1850 	case USB_LMETAKEY:
1851 	case USB_RCTLCKEY:
1852 	case USB_RSHIFTKEY:
1853 	case USB_RMETAKEY:
1854 	case USB_RALTKEY:
1855 
1856 		return (B_TRUE);
1857 
1858 	default:
1859 
1860 		break;
1861 	}
1862 
1863 	return (B_FALSE);
1864 }
1865 
1866 /*
1867  * usbkbm_reioctl :
1868  *	This function is set up as call-back function should an ioctl fail.
1869  *	It retries the ioctl
1870  */
1871 static void
1872 usbkbm_reioctl(void	*arg)
1873 {
1874 	usbkbm_state_t	*usbkbmd;
1875 	mblk_t *mp;
1876 
1877 	usbkbmd = (usbkbm_state_t *)arg;
1878 
1879 	usbkbmd->usbkbm_streams_bufcallid = 0;
1880 
1881 	if ((mp = usbkbmd->usbkbm_streams_iocpending) != NULL) {
1882 
1883 		/* not pending any more */
1884 		usbkbmd->usbkbm_streams_iocpending = NULL;
1885 
1886 		(void) usbkbm_ioctl(usbkbmd->usbkbm_writeq, mp);
1887 	}
1888 }
1889 
1890 /*
1891  * usbkbm_get_vid_pid
1892  *	Issue a M_CTL to hid to get the device info
1893  */
1894 static int
1895 usbkbm_get_vid_pid(usbkbm_state_t *usbkbmd)
1896 {
1897 	struct iocblk mctlmsg;
1898 	mblk_t *mctl_ptr;
1899 	queue_t *q = usbkbmd->usbkbm_readq;
1900 
1901 	mctlmsg.ioc_cmd = HID_GET_VID_PID;
1902 	mctlmsg.ioc_count = 0;
1903 
1904 	mctl_ptr = usba_mk_mctl(mctlmsg, NULL, 0);
1905 	if (mctl_ptr == NULL) {
1906 		(void) kbtrans_streams_fini(usbkbmd->usbkbm_kbtrans);
1907 		qprocsoff(q);
1908 		kmem_free(usbkbmd, sizeof (usbkbm_state_t));
1909 
1910 		return (ENOMEM);
1911 	}
1912 
1913 	putnext(usbkbmd->usbkbm_writeq, mctl_ptr);
1914 	usbkbmd->usbkbm_flags |= USBKBM_QWAIT;
1915 	while (usbkbmd->usbkbm_flags & USBKBM_QWAIT) {
1916 		if (qwait_sig(q) == 0) {
1917 			usbkbmd->usbkbm_flags = 0;
1918 			(void) kbtrans_streams_fini(usbkbmd->usbkbm_kbtrans);
1919 			qprocsoff(q);
1920 			kmem_free(usbkbmd, sizeof (usbkbm_state_t));
1921 
1922 			return (EINTR);
1923 		}
1924 	}
1925 
1926 	return (0);
1927 }
1928 
1929 /*
1930  * usbkbm_get_input_format() :
1931  *     Get the input report format of keyboard
1932  */
1933 static int
1934 usbkbm_get_input_format(usbkbm_state_t *usbkbmd)
1935 {
1936 
1937 	hidparser_rpt_t *kb_rpt;
1938 	uint_t i, kbd_page = 0, kpos = 0, klen = 0, limit = 0;
1939 	uint32_t rptcnt, rptsz;
1940 	usbkbm_report_format_t *kbd_fmt = &usbkbmd->usbkbm_report_format;
1941 	int rptid, rval;
1942 
1943 	/* Setup default input report format */
1944 	kbd_fmt->keyid = HID_REPORT_ID_UNDEFINED;
1945 	kbd_fmt->tlen = USB_KBD_BOOT_PROTOCOL_PACKET_SIZE;
1946 	kbd_fmt->klen = kbd_fmt->tlen;
1947 	kbd_fmt->kpos = 0;
1948 
1949 	if (usbkbmd->usbkbm_report_descr == NULL) {
1950 		return (USB_FAILURE);
1951 	}
1952 
1953 	/* Get keyboard layout */
1954 	if (hidparser_get_country_code(usbkbmd->usbkbm_report_descr,
1955 	    (uint16_t *)&usbkbmd->usbkbm_layout) == HIDPARSER_FAILURE) {
1956 
1957 		USB_DPRINTF_L3(PRINT_MASK_OPEN,
1958 		    usbkbm_log_handle, "get_country_code failed"
1959 		    "setting default layout(0)");
1960 
1961 		usbkbmd->usbkbm_layout = usbkbm_layout;
1962 	}
1963 
1964 	/* Get the id of the report which contains keyboard data */
1965 	if (hidparser_get_usage_attribute(
1966 	    usbkbmd->usbkbm_report_descr,
1967 	    0, /* Doesn't matter */
1968 	    HIDPARSER_ITEM_INPUT,
1969 	    HID_KEYBOARD_KEYPAD_KEYS,
1970 	    0,
1971 	    HIDPARSER_ITEM_REPORT_ID,
1972 	    &rptid) == HIDPARSER_NOT_FOUND) {
1973 
1974 		return (USB_SUCCESS);
1975 	}
1976 
1977 	/* Allocate hidparser report structure */
1978 	kb_rpt = kmem_zalloc(sizeof (hidparser_rpt_t), KM_SLEEP);
1979 
1980 	/*
1981 	 * Check what is the total length of the keyboard packet
1982 	 * and get the usages and their lengths in order
1983 	 */
1984 	rval = hidparser_get_usage_list_in_order(
1985 	    usbkbmd->usbkbm_report_descr,
1986 	    rptid,
1987 	    HIDPARSER_ITEM_INPUT,
1988 	    kb_rpt);
1989 	if (rval != HIDPARSER_SUCCESS) {
1990 
1991 		USB_DPRINTF_L3(PRINT_MASK_OPEN, usbkbm_log_handle,
1992 		    "get_usage_list_in_order failed");
1993 		kmem_free(kb_rpt, sizeof (hidparser_rpt_t));
1994 		return (USB_FAILURE);
1995 	}
1996 
1997 	for (i = 0; i < kb_rpt->no_of_usages; i++) {
1998 		rptcnt = kb_rpt->usage_descr[i].rptcnt;
1999 		rptsz = kb_rpt->usage_descr[i].rptsz;
2000 
2001 		switch (kb_rpt->usage_descr[i].usage_page) {
2002 		case HID_KEYBOARD_KEYPAD_KEYS:
2003 			if (!kbd_page) {
2004 				kpos = limit;
2005 				kbd_page = 1;
2006 			}
2007 			klen += rptcnt * rptsz;
2008 			/*FALLTHRU*/
2009 		default:
2010 			limit += rptcnt * rptsz;
2011 			break;
2012 		}
2013 	}
2014 
2015 	kmem_free(kb_rpt, sizeof (hidparser_rpt_t));
2016 
2017 	/* Invalid input report format */
2018 	if (!kbd_page || limit > USBKBM_MAXPKTSIZE * 8 ||
2019 	    kpos + klen > limit || (kpos % 8 != 0)) {
2020 
2021 		USB_DPRINTF_L3(PRINT_MASK_OPEN, usbkbm_log_handle,
2022 		    "Invalid input report format: kbd_page (%d), limit (%d), "
2023 		    "kpos (%d), klen (%d)", kbd_page, limit, kpos, klen);
2024 		return (USB_FAILURE);
2025 	}
2026 
2027 	/* Set report format */
2028 	kbd_fmt->keyid = (uint8_t)rptid;
2029 	kbd_fmt->tlen = limit / 8 + 1;
2030 	kbd_fmt->klen = klen / 8;
2031 	kbd_fmt->kpos = kpos / 8;
2032 
2033 	return (USB_SUCCESS);
2034 }
2035