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