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