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