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