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