17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
5281f0747Slt200341 * Common Development and Distribution License (the "License").
6281f0747Slt200341 * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate *
87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate * and limitations under the License.
127c478bd9Sstevel@tonic-gate *
137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate *
197c478bd9Sstevel@tonic-gate * CDDL HEADER END
207c478bd9Sstevel@tonic-gate */
217c478bd9Sstevel@tonic-gate /*
22827f5d6bSStrony Zhang - Solaris China Team * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
237c478bd9Sstevel@tonic-gate * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate */
257c478bd9Sstevel@tonic-gate
267c478bd9Sstevel@tonic-gate
277c478bd9Sstevel@tonic-gate /*
287c478bd9Sstevel@tonic-gate * USB keyboard input streams module - processes USB keypacket
297c478bd9Sstevel@tonic-gate * received from HID driver below to either ASCII or event
307c478bd9Sstevel@tonic-gate * format for windowing system.
317c478bd9Sstevel@tonic-gate */
327c478bd9Sstevel@tonic-gate #include <sys/usb/usba/usbai_version.h>
337c478bd9Sstevel@tonic-gate
347c478bd9Sstevel@tonic-gate #define KEYMAP_SIZE_VARIABLE
357c478bd9Sstevel@tonic-gate #include <sys/usb/usba.h>
367c478bd9Sstevel@tonic-gate #include <sys/usb/clients/hid/hid.h>
377c478bd9Sstevel@tonic-gate #include <sys/usb/clients/hid/hid_polled.h>
387c478bd9Sstevel@tonic-gate #include <sys/usb/clients/hidparser/hidparser.h>
397c478bd9Sstevel@tonic-gate #include <sys/stropts.h>
407c478bd9Sstevel@tonic-gate #include <sys/stream.h>
417c478bd9Sstevel@tonic-gate #include <sys/strsun.h>
427c478bd9Sstevel@tonic-gate #include <sys/kbio.h>
437c478bd9Sstevel@tonic-gate #include <sys/vuid_event.h>
447c478bd9Sstevel@tonic-gate #include <sys/kbd.h>
457c478bd9Sstevel@tonic-gate #include <sys/consdev.h>
467c478bd9Sstevel@tonic-gate #include <sys/kbtrans.h>
477c478bd9Sstevel@tonic-gate #include <sys/usb/clients/usbkbm/usbkbm.h>
487c478bd9Sstevel@tonic-gate #include <sys/beep.h>
49c35aa225Smarx #include <sys/inttypes.h>
507c478bd9Sstevel@tonic-gate
517c478bd9Sstevel@tonic-gate /* debugging information */
524610e4a0Sfrits uint_t usbkbm_errmask = (uint_t)PRINT_MASK_ALL;
534610e4a0Sfrits uint_t usbkbm_errlevel = USB_LOG_L2;
547c478bd9Sstevel@tonic-gate static usb_log_handle_t usbkbm_log_handle;
557c478bd9Sstevel@tonic-gate
567c478bd9Sstevel@tonic-gate typedef void (*process_key_callback_t)(usbkbm_state_t *, int, enum keystate);
577c478bd9Sstevel@tonic-gate
587c478bd9Sstevel@tonic-gate /*
597c478bd9Sstevel@tonic-gate * Internal Function Prototypes
607c478bd9Sstevel@tonic-gate */
617c478bd9Sstevel@tonic-gate static void usbkbm_streams_setled(struct kbtrans_hardware *, int);
627c478bd9Sstevel@tonic-gate static void usbkbm_polled_setled(struct kbtrans_hardware *, int);
637c478bd9Sstevel@tonic-gate static boolean_t usbkbm_polled_keycheck(struct kbtrans_hardware *,
647c478bd9Sstevel@tonic-gate int *, enum keystate *);
657c478bd9Sstevel@tonic-gate static void usbkbm_poll_callback(usbkbm_state_t *, int, enum keystate);
667c478bd9Sstevel@tonic-gate static void usbkbm_streams_callback(usbkbm_state_t *, int, enum keystate);
677c478bd9Sstevel@tonic-gate static void usbkbm_unpack_usb_packet(usbkbm_state_t *, process_key_callback_t,
684db52957Spengcheng chen - Sun Microsystems - Beijing China uchar_t *);
697c478bd9Sstevel@tonic-gate static boolean_t usbkbm_is_modkey(uchar_t);
707c478bd9Sstevel@tonic-gate static void usbkbm_reioctl(void *);
71281f0747Slt200341 static int usbkbm_polled_getchar(cons_polledio_arg_t);
72281f0747Slt200341 static boolean_t usbkbm_polled_ischar(cons_polledio_arg_t);
73281f0747Slt200341 static void usbkbm_polled_enter(cons_polledio_arg_t);
74281f0747Slt200341 static void usbkbm_polled_exit(cons_polledio_arg_t);
757c478bd9Sstevel@tonic-gate static void usbkbm_mctl_receive(queue_t *, mblk_t *);
767c478bd9Sstevel@tonic-gate static enum kbtrans_message_response usbkbm_ioctl(queue_t *, mblk_t *);
777c478bd9Sstevel@tonic-gate static int usbkbm_kioccmd(usbkbm_state_t *, mblk_t *, char, size_t *);
787c478bd9Sstevel@tonic-gate static void usbkbm_usb2pc_xlate(usbkbm_state_t *, int, enum keystate);
797c478bd9Sstevel@tonic-gate static void usbkbm_wrap_kbtrans(usbkbm_state_t *, int, enum keystate);
804db52957Spengcheng chen - Sun Microsystems - Beijing China static int usbkbm_get_input_format(usbkbm_state_t *);
816d9a41ffSqz150045 static int usbkbm_get_vid_pid(usbkbm_state_t *);
827c478bd9Sstevel@tonic-gate
837c478bd9Sstevel@tonic-gate /* stream qinit functions defined here */
847c478bd9Sstevel@tonic-gate static int usbkbm_open(queue_t *, dev_t *, int, int, cred_t *);
857c478bd9Sstevel@tonic-gate static int usbkbm_close(queue_t *, int, cred_t *);
863bb8546dSToomas Soome static int usbkbm_wput(queue_t *, mblk_t *);
873bb8546dSToomas Soome static int usbkbm_rput(queue_t *, mblk_t *);
88*100e26fcSToomas Soome static int usbkbm_rsrv(queue_t *);
897c478bd9Sstevel@tonic-gate static ushort_t usbkbm_get_state(usbkbm_state_t *);
907c478bd9Sstevel@tonic-gate static void usbkbm_get_scancode(usbkbm_state_t *, int *, enum keystate *);
917c478bd9Sstevel@tonic-gate
927c478bd9Sstevel@tonic-gate static struct keyboard *usbkbm_keyindex;
937c478bd9Sstevel@tonic-gate
947c478bd9Sstevel@tonic-gate /* External Functions */
957c478bd9Sstevel@tonic-gate extern void space_free(char *);
967c478bd9Sstevel@tonic-gate extern uintptr_t space_fetch(char *);
977c478bd9Sstevel@tonic-gate extern int space_store(char *, uintptr_t);
987c478bd9Sstevel@tonic-gate extern struct keyboard *kbtrans_usbkb_maptab_init(void);
997c478bd9Sstevel@tonic-gate extern void kbtrans_usbkb_maptab_fini(struct keyboard **);
1007c478bd9Sstevel@tonic-gate extern keymap_entry_t kbtrans_keycode_usb2pc(int);
1017c478bd9Sstevel@tonic-gate
1027c478bd9Sstevel@tonic-gate /*
1037c478bd9Sstevel@tonic-gate * Structure to setup callbacks
1047c478bd9Sstevel@tonic-gate */
1057c478bd9Sstevel@tonic-gate struct kbtrans_callbacks kbd_usb_callbacks = {
1067c478bd9Sstevel@tonic-gate usbkbm_streams_setled,
1077c478bd9Sstevel@tonic-gate usbkbm_polled_setled,
1087c478bd9Sstevel@tonic-gate usbkbm_polled_keycheck,
1097c478bd9Sstevel@tonic-gate };
1107c478bd9Sstevel@tonic-gate
1117c478bd9Sstevel@tonic-gate /*
1127c478bd9Sstevel@tonic-gate * Global Variables
1137c478bd9Sstevel@tonic-gate */
1147c478bd9Sstevel@tonic-gate
1157c478bd9Sstevel@tonic-gate /* This variable saves the LED state across hotplugging. */
1167c478bd9Sstevel@tonic-gate static uchar_t usbkbm_led_state = 0;
1177c478bd9Sstevel@tonic-gate
1187c478bd9Sstevel@tonic-gate /* This variable saves the layout state */
1196d9a41ffSqz150045 static uint16_t usbkbm_layout = 0;
1207c478bd9Sstevel@tonic-gate
1217c478bd9Sstevel@tonic-gate /*
1227c478bd9Sstevel@tonic-gate * Function pointer array for mapping of scancodes.
1237c478bd9Sstevel@tonic-gate */
1247c478bd9Sstevel@tonic-gate void (*usbkbm_xlate[2])(usbkbm_state_t *, int, enum keystate) = {
1257c478bd9Sstevel@tonic-gate usbkbm_wrap_kbtrans,
1267c478bd9Sstevel@tonic-gate usbkbm_usb2pc_xlate
1277c478bd9Sstevel@tonic-gate };
1287c478bd9Sstevel@tonic-gate
1297c478bd9Sstevel@tonic-gate static struct streamtab usbkbm_info;
1307c478bd9Sstevel@tonic-gate static struct fmodsw fsw = {
1317c478bd9Sstevel@tonic-gate "usbkbm",
1327c478bd9Sstevel@tonic-gate &usbkbm_info,
1337c478bd9Sstevel@tonic-gate D_MP | D_MTPERMOD
1347c478bd9Sstevel@tonic-gate };
1357c478bd9Sstevel@tonic-gate
1367c478bd9Sstevel@tonic-gate
1377c478bd9Sstevel@tonic-gate /*
1387c478bd9Sstevel@tonic-gate * Module linkage information for the kernel.
1397c478bd9Sstevel@tonic-gate */
1407c478bd9Sstevel@tonic-gate static struct modlstrmod modlstrmod = {
1417c478bd9Sstevel@tonic-gate &mod_strmodops,
1422e83744eSsethg "USB keyboard streams 1.44",
1437c478bd9Sstevel@tonic-gate &fsw
1447c478bd9Sstevel@tonic-gate };
1457c478bd9Sstevel@tonic-gate
1467c478bd9Sstevel@tonic-gate static struct modlinkage modlinkage = {
1477c478bd9Sstevel@tonic-gate MODREV_1,
1487c478bd9Sstevel@tonic-gate (void *)&modlstrmod,
1497c478bd9Sstevel@tonic-gate NULL
1507c478bd9Sstevel@tonic-gate };
1517c478bd9Sstevel@tonic-gate
1527c478bd9Sstevel@tonic-gate
1537c478bd9Sstevel@tonic-gate int
_init(void)1547c478bd9Sstevel@tonic-gate _init(void)
1557c478bd9Sstevel@tonic-gate {
1567c478bd9Sstevel@tonic-gate int rval = mod_install(&modlinkage);
1577c478bd9Sstevel@tonic-gate usbkbm_save_state_t *sp;
1587c478bd9Sstevel@tonic-gate
1597c478bd9Sstevel@tonic-gate if (rval != 0) {
1607c478bd9Sstevel@tonic-gate
1617c478bd9Sstevel@tonic-gate return (rval);
1627c478bd9Sstevel@tonic-gate }
1637c478bd9Sstevel@tonic-gate
1647c478bd9Sstevel@tonic-gate usbkbm_keyindex = kbtrans_usbkb_maptab_init();
1657c478bd9Sstevel@tonic-gate
1667c478bd9Sstevel@tonic-gate usbkbm_log_handle = usb_alloc_log_hdl(NULL, "usbkbm",
1677c478bd9Sstevel@tonic-gate &usbkbm_errlevel, &usbkbm_errmask, NULL, 0);
1687c478bd9Sstevel@tonic-gate
1697c478bd9Sstevel@tonic-gate sp = (usbkbm_save_state_t *)space_fetch("SUNW,usbkbm_state");
1707c478bd9Sstevel@tonic-gate
1717c478bd9Sstevel@tonic-gate if (sp == NULL) {
1727c478bd9Sstevel@tonic-gate
1737c478bd9Sstevel@tonic-gate return (0);
1747c478bd9Sstevel@tonic-gate }
1757c478bd9Sstevel@tonic-gate
1767c478bd9Sstevel@tonic-gate /* Restore LED information */
1777c478bd9Sstevel@tonic-gate usbkbm_led_state = sp->usbkbm_save_led;
1787c478bd9Sstevel@tonic-gate
1797c478bd9Sstevel@tonic-gate /* Restore the Layout */
1807c478bd9Sstevel@tonic-gate usbkbm_layout = sp->usbkbm_layout;
1817c478bd9Sstevel@tonic-gate
1827c478bd9Sstevel@tonic-gate /* Restore abort information */
1837c478bd9Sstevel@tonic-gate usbkbm_keyindex->k_abort1 =
1847c478bd9Sstevel@tonic-gate sp->usbkbm_save_keyindex.k_abort1;
1857c478bd9Sstevel@tonic-gate
1867c478bd9Sstevel@tonic-gate usbkbm_keyindex->k_abort2 =
1877c478bd9Sstevel@tonic-gate sp->usbkbm_save_keyindex.k_abort2;
1887c478bd9Sstevel@tonic-gate
189e4603304Sqz150045 usbkbm_keyindex->k_newabort1 =
190e4603304Sqz150045 sp->usbkbm_save_keyindex.k_newabort1;
191e4603304Sqz150045
192e4603304Sqz150045 usbkbm_keyindex->k_newabort2 =
193e4603304Sqz150045 sp->usbkbm_save_keyindex.k_newabort2;
194e4603304Sqz150045
1957c478bd9Sstevel@tonic-gate /* Restore keytables */
1967c478bd9Sstevel@tonic-gate bcopy(sp->usbkbm_save_keyindex.k_normal,
1977c478bd9Sstevel@tonic-gate usbkbm_keyindex->k_normal, USB_KEYTABLE_SIZE);
1987c478bd9Sstevel@tonic-gate
1997c478bd9Sstevel@tonic-gate bcopy(sp->usbkbm_save_keyindex.k_shifted,
2007c478bd9Sstevel@tonic-gate usbkbm_keyindex->k_shifted, USB_KEYTABLE_SIZE);
2017c478bd9Sstevel@tonic-gate
2027c478bd9Sstevel@tonic-gate bcopy(sp->usbkbm_save_keyindex.k_caps,
2037c478bd9Sstevel@tonic-gate usbkbm_keyindex->k_caps, USB_KEYTABLE_SIZE);
2047c478bd9Sstevel@tonic-gate
2057c478bd9Sstevel@tonic-gate bcopy(sp->usbkbm_save_keyindex.k_altgraph,
2067c478bd9Sstevel@tonic-gate usbkbm_keyindex->k_altgraph, USB_KEYTABLE_SIZE);
2077c478bd9Sstevel@tonic-gate
2087c478bd9Sstevel@tonic-gate bcopy(sp->usbkbm_save_keyindex.k_numlock,
2097c478bd9Sstevel@tonic-gate usbkbm_keyindex->k_numlock, USB_KEYTABLE_SIZE);
2107c478bd9Sstevel@tonic-gate
2117c478bd9Sstevel@tonic-gate bcopy(sp->usbkbm_save_keyindex.k_control,
2127c478bd9Sstevel@tonic-gate usbkbm_keyindex->k_control, USB_KEYTABLE_SIZE);
2137c478bd9Sstevel@tonic-gate
2147c478bd9Sstevel@tonic-gate bcopy(sp->usbkbm_save_keyindex.k_up,
2157c478bd9Sstevel@tonic-gate usbkbm_keyindex->k_up, USB_KEYTABLE_SIZE);
2167c478bd9Sstevel@tonic-gate
2177c478bd9Sstevel@tonic-gate kmem_free(sp->usbkbm_save_keyindex.k_normal,
2187c478bd9Sstevel@tonic-gate USB_KEYTABLE_SIZE);
2197c478bd9Sstevel@tonic-gate kmem_free(sp->usbkbm_save_keyindex.k_shifted,
2207c478bd9Sstevel@tonic-gate USB_KEYTABLE_SIZE);
2217c478bd9Sstevel@tonic-gate kmem_free(sp->usbkbm_save_keyindex.k_caps,
2227c478bd9Sstevel@tonic-gate USB_KEYTABLE_SIZE);
2237c478bd9Sstevel@tonic-gate kmem_free(sp->usbkbm_save_keyindex.k_altgraph,
2247c478bd9Sstevel@tonic-gate USB_KEYTABLE_SIZE);
2257c478bd9Sstevel@tonic-gate kmem_free(sp->usbkbm_save_keyindex.k_numlock,
2267c478bd9Sstevel@tonic-gate USB_KEYTABLE_SIZE);
2277c478bd9Sstevel@tonic-gate kmem_free(sp->usbkbm_save_keyindex.k_control,
2287c478bd9Sstevel@tonic-gate USB_KEYTABLE_SIZE);
2297c478bd9Sstevel@tonic-gate kmem_free(sp->usbkbm_save_keyindex.k_up,
2307c478bd9Sstevel@tonic-gate USB_KEYTABLE_SIZE);
2317c478bd9Sstevel@tonic-gate
2327c478bd9Sstevel@tonic-gate kmem_free(sp, sizeof (usbkbm_save_state_t));
2337c478bd9Sstevel@tonic-gate space_free("SUNW,usbkbm_state");
2347c478bd9Sstevel@tonic-gate
2357c478bd9Sstevel@tonic-gate return (0);
2367c478bd9Sstevel@tonic-gate }
2377c478bd9Sstevel@tonic-gate
2387c478bd9Sstevel@tonic-gate int
_fini(void)2397c478bd9Sstevel@tonic-gate _fini(void)
2407c478bd9Sstevel@tonic-gate {
2417c478bd9Sstevel@tonic-gate usbkbm_save_state_t *sp;
2427c478bd9Sstevel@tonic-gate int sval;
2437c478bd9Sstevel@tonic-gate int rval;
2447c478bd9Sstevel@tonic-gate
2457c478bd9Sstevel@tonic-gate sp = kmem_alloc(sizeof (usbkbm_save_state_t), KM_SLEEP);
2467c478bd9Sstevel@tonic-gate sval = space_store("SUNW,usbkbm_state", (uintptr_t)sp);
2477c478bd9Sstevel@tonic-gate
2487c478bd9Sstevel@tonic-gate /*
2497c478bd9Sstevel@tonic-gate * If it's not possible to store the state, return
2507c478bd9Sstevel@tonic-gate * EBUSY.
2517c478bd9Sstevel@tonic-gate */
2527c478bd9Sstevel@tonic-gate if (sval != 0) {
2537c478bd9Sstevel@tonic-gate kmem_free(sp, sizeof (usbkbm_save_state_t));
2547c478bd9Sstevel@tonic-gate
2557c478bd9Sstevel@tonic-gate return (EBUSY);
2567c478bd9Sstevel@tonic-gate }
2577c478bd9Sstevel@tonic-gate
2587c478bd9Sstevel@tonic-gate rval = mod_remove(&modlinkage);
2597c478bd9Sstevel@tonic-gate
2607c478bd9Sstevel@tonic-gate if (rval != 0) {
2617c478bd9Sstevel@tonic-gate kmem_free(sp, sizeof (usbkbm_save_state_t));
2627c478bd9Sstevel@tonic-gate space_free("SUNW,usbkbm_state");
2637c478bd9Sstevel@tonic-gate
2647c478bd9Sstevel@tonic-gate return (rval);
2657c478bd9Sstevel@tonic-gate }
2667c478bd9Sstevel@tonic-gate
2677c478bd9Sstevel@tonic-gate usb_free_log_hdl(usbkbm_log_handle);
2687c478bd9Sstevel@tonic-gate
2697c478bd9Sstevel@tonic-gate /* Save the LED state */
2707c478bd9Sstevel@tonic-gate sp->usbkbm_save_led = usbkbm_led_state;
2717c478bd9Sstevel@tonic-gate
2727c478bd9Sstevel@tonic-gate /* Save the layout */
273d29f5a71Szhigang lu - Sun Microsystems - Beijing China sp->usbkbm_layout = (uchar_t)usbkbm_layout;
2747c478bd9Sstevel@tonic-gate
2757c478bd9Sstevel@tonic-gate /*
2767c478bd9Sstevel@tonic-gate * Save entries of the keyboard structure that
2777c478bd9Sstevel@tonic-gate * have changed.
2787c478bd9Sstevel@tonic-gate */
2797c478bd9Sstevel@tonic-gate sp->usbkbm_save_keyindex.k_abort1 = usbkbm_keyindex->k_abort1;
2807c478bd9Sstevel@tonic-gate sp->usbkbm_save_keyindex.k_abort2 = usbkbm_keyindex->k_abort2;
2817c478bd9Sstevel@tonic-gate
282e4603304Sqz150045 sp->usbkbm_save_keyindex.k_newabort1 = usbkbm_keyindex->k_newabort1;
283e4603304Sqz150045 sp->usbkbm_save_keyindex.k_newabort2 = usbkbm_keyindex->k_newabort2;
284e4603304Sqz150045
2857c478bd9Sstevel@tonic-gate /* Allocate space for keytables to be stored */
2867c478bd9Sstevel@tonic-gate sp->usbkbm_save_keyindex.k_normal =
2877c478bd9Sstevel@tonic-gate kmem_alloc(USB_KEYTABLE_SIZE, KM_SLEEP);
2887c478bd9Sstevel@tonic-gate sp->usbkbm_save_keyindex.k_shifted =
2897c478bd9Sstevel@tonic-gate kmem_alloc(USB_KEYTABLE_SIZE, KM_SLEEP);
2907c478bd9Sstevel@tonic-gate sp->usbkbm_save_keyindex.k_caps =
2917c478bd9Sstevel@tonic-gate kmem_alloc(USB_KEYTABLE_SIZE, KM_SLEEP);
2927c478bd9Sstevel@tonic-gate sp->usbkbm_save_keyindex.k_altgraph =
2937c478bd9Sstevel@tonic-gate kmem_alloc(USB_KEYTABLE_SIZE, KM_SLEEP);
2947c478bd9Sstevel@tonic-gate sp->usbkbm_save_keyindex.k_numlock =
2957c478bd9Sstevel@tonic-gate kmem_alloc(USB_KEYTABLE_SIZE, KM_SLEEP);
2967c478bd9Sstevel@tonic-gate sp->usbkbm_save_keyindex.k_control =
2977c478bd9Sstevel@tonic-gate kmem_alloc(USB_KEYTABLE_SIZE, KM_SLEEP);
2987c478bd9Sstevel@tonic-gate sp->usbkbm_save_keyindex.k_up =
2997c478bd9Sstevel@tonic-gate kmem_alloc(USB_KEYTABLE_SIZE, KM_SLEEP);
3007c478bd9Sstevel@tonic-gate
3017c478bd9Sstevel@tonic-gate /* Copy over the keytables */
3027c478bd9Sstevel@tonic-gate bcopy(usbkbm_keyindex->k_normal,
3037c478bd9Sstevel@tonic-gate sp->usbkbm_save_keyindex.k_normal, USB_KEYTABLE_SIZE);
3047c478bd9Sstevel@tonic-gate
3057c478bd9Sstevel@tonic-gate bcopy(usbkbm_keyindex->k_shifted,
3067c478bd9Sstevel@tonic-gate sp->usbkbm_save_keyindex.k_shifted, USB_KEYTABLE_SIZE);
3077c478bd9Sstevel@tonic-gate
3087c478bd9Sstevel@tonic-gate bcopy(usbkbm_keyindex->k_caps,
3097c478bd9Sstevel@tonic-gate sp->usbkbm_save_keyindex.k_caps, USB_KEYTABLE_SIZE);
3107c478bd9Sstevel@tonic-gate
3117c478bd9Sstevel@tonic-gate bcopy(usbkbm_keyindex->k_altgraph,
3127c478bd9Sstevel@tonic-gate sp->usbkbm_save_keyindex.k_altgraph, USB_KEYTABLE_SIZE);
3137c478bd9Sstevel@tonic-gate
3147c478bd9Sstevel@tonic-gate bcopy(usbkbm_keyindex->k_numlock,
3157c478bd9Sstevel@tonic-gate sp->usbkbm_save_keyindex.k_numlock, USB_KEYTABLE_SIZE);
3167c478bd9Sstevel@tonic-gate
3177c478bd9Sstevel@tonic-gate bcopy(usbkbm_keyindex->k_control,
3187c478bd9Sstevel@tonic-gate sp->usbkbm_save_keyindex.k_control, USB_KEYTABLE_SIZE);
3197c478bd9Sstevel@tonic-gate
3207c478bd9Sstevel@tonic-gate bcopy(usbkbm_keyindex->k_up,
3217c478bd9Sstevel@tonic-gate sp->usbkbm_save_keyindex.k_up, USB_KEYTABLE_SIZE);
3227c478bd9Sstevel@tonic-gate
3237c478bd9Sstevel@tonic-gate kbtrans_usbkb_maptab_fini(&usbkbm_keyindex);
3247c478bd9Sstevel@tonic-gate
3257c478bd9Sstevel@tonic-gate return (0);
3267c478bd9Sstevel@tonic-gate }
3277c478bd9Sstevel@tonic-gate
3287c478bd9Sstevel@tonic-gate int
_info(struct modinfo * modinfop)3297c478bd9Sstevel@tonic-gate _info(struct modinfo *modinfop)
3307c478bd9Sstevel@tonic-gate {
3317c478bd9Sstevel@tonic-gate return (mod_info(&modlinkage, modinfop));
3327c478bd9Sstevel@tonic-gate }
3337c478bd9Sstevel@tonic-gate
3347c478bd9Sstevel@tonic-gate /*
3357c478bd9Sstevel@tonic-gate * Module qinit functions
3367c478bd9Sstevel@tonic-gate */
3377c478bd9Sstevel@tonic-gate
3387c478bd9Sstevel@tonic-gate static struct module_info usbkbm_minfo = {
3397c478bd9Sstevel@tonic-gate 0, /* module id number */
3407c478bd9Sstevel@tonic-gate "usbkbm", /* module name */
3417c478bd9Sstevel@tonic-gate 0, /* min packet size accepted */
3427c478bd9Sstevel@tonic-gate INFPSZ, /* max packet size accepted */
3437c478bd9Sstevel@tonic-gate 2048, /* hi-water mark */
3447c478bd9Sstevel@tonic-gate 128 /* lo-water mark */
3457c478bd9Sstevel@tonic-gate };
3467c478bd9Sstevel@tonic-gate
3477c478bd9Sstevel@tonic-gate /* read side for key data and ioctl replies */
3487c478bd9Sstevel@tonic-gate static struct qinit usbkbm_rinit = {
3493bb8546dSToomas Soome usbkbm_rput,
350*100e26fcSToomas Soome usbkbm_rsrv,
3517c478bd9Sstevel@tonic-gate usbkbm_open,
3527c478bd9Sstevel@tonic-gate usbkbm_close,
3533bb8546dSToomas Soome NULL,
3547c478bd9Sstevel@tonic-gate &usbkbm_minfo
3557c478bd9Sstevel@tonic-gate };
3567c478bd9Sstevel@tonic-gate
3577c478bd9Sstevel@tonic-gate /* write side for ioctls */
3587c478bd9Sstevel@tonic-gate static struct qinit usbkbm_winit = {
3593bb8546dSToomas Soome usbkbm_wput,
3603bb8546dSToomas Soome NULL,
3617c478bd9Sstevel@tonic-gate usbkbm_open,
3627c478bd9Sstevel@tonic-gate usbkbm_close,
3633bb8546dSToomas Soome NULL,
3647c478bd9Sstevel@tonic-gate &usbkbm_minfo
3657c478bd9Sstevel@tonic-gate };
3667c478bd9Sstevel@tonic-gate
3677c478bd9Sstevel@tonic-gate static struct streamtab usbkbm_info = {
3687c478bd9Sstevel@tonic-gate &usbkbm_rinit,
3697c478bd9Sstevel@tonic-gate &usbkbm_winit,
3707c478bd9Sstevel@tonic-gate NULL, /* for muxes */
3717c478bd9Sstevel@tonic-gate NULL, /* for muxes */
3727c478bd9Sstevel@tonic-gate };
3737c478bd9Sstevel@tonic-gate
3747c478bd9Sstevel@tonic-gate /*
3757c478bd9Sstevel@tonic-gate * usbkbm_open :
3767c478bd9Sstevel@tonic-gate * Open a keyboard
3777c478bd9Sstevel@tonic-gate */
3787c478bd9Sstevel@tonic-gate /* ARGSUSED */
3797c478bd9Sstevel@tonic-gate static int
usbkbm_open(queue_t * q,dev_t * devp,int oflag,int sflag,cred_t * crp)3807c478bd9Sstevel@tonic-gate usbkbm_open(queue_t *q, dev_t *devp, int oflag, int sflag, cred_t *crp)
3817c478bd9Sstevel@tonic-gate {
3827c478bd9Sstevel@tonic-gate usbkbm_state_t *usbkbmd;
3837c478bd9Sstevel@tonic-gate struct iocblk mctlmsg;
3847c478bd9Sstevel@tonic-gate mblk_t *mctl_ptr;
385ac9468f8Spengcheng chen - Sun Microsystems - Beijing China uintptr_t abortable = (uintptr_t)B_TRUE;
3867c478bd9Sstevel@tonic-gate int error, ret;
3877c478bd9Sstevel@tonic-gate
3887c478bd9Sstevel@tonic-gate if (q->q_ptr) {
3897c478bd9Sstevel@tonic-gate USB_DPRINTF_L3(PRINT_MASK_OPEN, usbkbm_log_handle,
3907c478bd9Sstevel@tonic-gate "usbkbm_open already opened");
3917c478bd9Sstevel@tonic-gate
3927c478bd9Sstevel@tonic-gate return (0); /* already opened */
3937c478bd9Sstevel@tonic-gate }
3947c478bd9Sstevel@tonic-gate
3957c478bd9Sstevel@tonic-gate switch (sflag) {
3967c478bd9Sstevel@tonic-gate
3977c478bd9Sstevel@tonic-gate case MODOPEN:
3987c478bd9Sstevel@tonic-gate break;
3997c478bd9Sstevel@tonic-gate
4007c478bd9Sstevel@tonic-gate case CLONEOPEN:
4017c478bd9Sstevel@tonic-gate USB_DPRINTF_L3(PRINT_MASK_OPEN, usbkbm_log_handle,
4027c478bd9Sstevel@tonic-gate "usbkbm_open: Clone open not supported");
4037c478bd9Sstevel@tonic-gate
4047c478bd9Sstevel@tonic-gate /* FALLTHRU */
4057c478bd9Sstevel@tonic-gate default:
4067c478bd9Sstevel@tonic-gate
4077c478bd9Sstevel@tonic-gate return (EINVAL);
4087c478bd9Sstevel@tonic-gate }
4097c478bd9Sstevel@tonic-gate
4107c478bd9Sstevel@tonic-gate /* allocate usb keyboard state structure */
4117c478bd9Sstevel@tonic-gate
4127c478bd9Sstevel@tonic-gate usbkbmd = kmem_zalloc(sizeof (usbkbm_state_t), KM_SLEEP);
4137c478bd9Sstevel@tonic-gate
4147c478bd9Sstevel@tonic-gate USB_DPRINTF_L3(PRINT_MASK_OPEN, usbkbm_log_handle,
4157c478bd9Sstevel@tonic-gate "usbkbm_state= %p", (void *)usbkbmd);
4167c478bd9Sstevel@tonic-gate
4177c478bd9Sstevel@tonic-gate /*
4187c478bd9Sstevel@tonic-gate * Set up private data.
4197c478bd9Sstevel@tonic-gate */
4207c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_readq = q;
4217c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_writeq = WR(q);
4227c478bd9Sstevel@tonic-gate
4237c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_vkbd_type = KB_USB;
4247c478bd9Sstevel@tonic-gate /*
4257c478bd9Sstevel@tonic-gate * Set up queue pointers, so that the "put" procedure will accept
4267c478bd9Sstevel@tonic-gate * the reply to the "ioctl" message we send down.
4277c478bd9Sstevel@tonic-gate */
4287c478bd9Sstevel@tonic-gate q->q_ptr = (caddr_t)usbkbmd;
4297c478bd9Sstevel@tonic-gate WR(q)->q_ptr = (caddr_t)usbkbmd;
4307c478bd9Sstevel@tonic-gate
431cd2135d0Spengcheng chen - Sun Microsystems - Beijing China error = kbtrans_streams_init(q, sflag,
4327c478bd9Sstevel@tonic-gate (struct kbtrans_hardware *)usbkbmd, &kbd_usb_callbacks,
4337c478bd9Sstevel@tonic-gate &usbkbmd->usbkbm_kbtrans, usbkbm_led_state, 0);
4347c478bd9Sstevel@tonic-gate
4357c478bd9Sstevel@tonic-gate if (error != 0) {
4367c478bd9Sstevel@tonic-gate USB_DPRINTF_L3(PRINT_MASK_OPEN, usbkbm_log_handle,
4377c478bd9Sstevel@tonic-gate "kbdopen: kbtrans_streams_init failed\n");
4387c478bd9Sstevel@tonic-gate kmem_free(usbkbmd, sizeof (*usbkbmd));
4397c478bd9Sstevel@tonic-gate
4407c478bd9Sstevel@tonic-gate return (error);
4417c478bd9Sstevel@tonic-gate }
4427c478bd9Sstevel@tonic-gate
4437c478bd9Sstevel@tonic-gate /*
4447c478bd9Sstevel@tonic-gate * Set the polled information in the state structure.
4457c478bd9Sstevel@tonic-gate * This information is set once, and doesn't change
4467c478bd9Sstevel@tonic-gate */
4477c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_polled_info.cons_polledio_version =
4487c478bd9Sstevel@tonic-gate CONSPOLLEDIO_V1;
4497c478bd9Sstevel@tonic-gate
4507c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_polled_info.cons_polledio_argument =
451281f0747Slt200341 (cons_polledio_arg_t)usbkbmd;
4527c478bd9Sstevel@tonic-gate
4537c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_polled_info.cons_polledio_putchar = NULL;
4547c478bd9Sstevel@tonic-gate
4557c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_polled_info.cons_polledio_getchar =
4567c478bd9Sstevel@tonic-gate usbkbm_polled_getchar;
4577c478bd9Sstevel@tonic-gate
4587c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_polled_info.cons_polledio_ischar =
4597c478bd9Sstevel@tonic-gate usbkbm_polled_ischar;
4607c478bd9Sstevel@tonic-gate
4617c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_polled_info.cons_polledio_enter =
4627c478bd9Sstevel@tonic-gate usbkbm_polled_enter;
4637c478bd9Sstevel@tonic-gate
4647c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_polled_info.cons_polledio_exit =
4657c478bd9Sstevel@tonic-gate usbkbm_polled_exit;
4667c478bd9Sstevel@tonic-gate
4677c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_polled_info.cons_polledio_setled =
468281f0747Slt200341 (void (*)(cons_polledio_arg_t, int))usbkbm_polled_setled;
4697c478bd9Sstevel@tonic-gate
4707c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_polled_info.cons_polledio_keycheck =
471281f0747Slt200341 (boolean_t (*)(cons_polledio_arg_t, int *,
4727c478bd9Sstevel@tonic-gate enum keystate *))usbkbm_polled_keycheck;
4737c478bd9Sstevel@tonic-gate /*
4747c478bd9Sstevel@tonic-gate * The head and the tail pointing at the same byte means empty or
4757c478bd9Sstevel@tonic-gate * full. usbkbm_polled_buffer_num_characters is used to
4767c478bd9Sstevel@tonic-gate * tell the difference.
4777c478bd9Sstevel@tonic-gate */
4787c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_polled_buffer_head =
4797c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_polled_scancode_buffer;
4807c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_polled_buffer_tail =
4817c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_polled_scancode_buffer;
4827c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_polled_buffer_num_characters = 0;
4837c478bd9Sstevel@tonic-gate
4847c478bd9Sstevel@tonic-gate qprocson(q);
4857c478bd9Sstevel@tonic-gate
4867c478bd9Sstevel@tonic-gate /* request hid report descriptor from HID */
4877c478bd9Sstevel@tonic-gate mctlmsg.ioc_cmd = HID_GET_PARSER_HANDLE;
4887c478bd9Sstevel@tonic-gate mctlmsg.ioc_count = 0;
4897c478bd9Sstevel@tonic-gate mctl_ptr = usba_mk_mctl(mctlmsg, NULL, 0);
4907c478bd9Sstevel@tonic-gate if (mctl_ptr == NULL) {
4917c478bd9Sstevel@tonic-gate /* failure to allocate M_CTL message */
4927c478bd9Sstevel@tonic-gate (void) kbtrans_streams_fini(usbkbmd->usbkbm_kbtrans);
4937c478bd9Sstevel@tonic-gate qprocsoff(q);
4947c478bd9Sstevel@tonic-gate kmem_free(usbkbmd, sizeof (*usbkbmd));
4957c478bd9Sstevel@tonic-gate
4967c478bd9Sstevel@tonic-gate return (ENOMEM);
4977c478bd9Sstevel@tonic-gate }
4987c478bd9Sstevel@tonic-gate
4997c478bd9Sstevel@tonic-gate /* send message to hid */
5007c478bd9Sstevel@tonic-gate putnext(usbkbmd->usbkbm_writeq, mctl_ptr);
5017c478bd9Sstevel@tonic-gate
5027c478bd9Sstevel@tonic-gate /*
5037c478bd9Sstevel@tonic-gate * Now that M_CTL has been sent, wait for report descriptor. Cleanup
5047c478bd9Sstevel@tonic-gate * if user signals in the mean time (as when this gets opened in an
5057c478bd9Sstevel@tonic-gate * inappropriate context and the user types a ^C).
5067c478bd9Sstevel@tonic-gate */
5077c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_flags |= USBKBM_QWAIT;
5087c478bd9Sstevel@tonic-gate while (usbkbmd->usbkbm_flags & USBKBM_QWAIT) {
5097c478bd9Sstevel@tonic-gate
5107c478bd9Sstevel@tonic-gate if (qwait_sig(q) == 0) {
5117c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_flags = 0;
5127c478bd9Sstevel@tonic-gate (void) kbtrans_streams_fini(usbkbmd->usbkbm_kbtrans);
5137c478bd9Sstevel@tonic-gate qprocsoff(q);
5147c478bd9Sstevel@tonic-gate kmem_free(usbkbmd, sizeof (*usbkbmd));
5157c478bd9Sstevel@tonic-gate
5167c478bd9Sstevel@tonic-gate return (EINTR);
5177c478bd9Sstevel@tonic-gate }
5187c478bd9Sstevel@tonic-gate }
5197c478bd9Sstevel@tonic-gate
5207c478bd9Sstevel@tonic-gate
5214db52957Spengcheng chen - Sun Microsystems - Beijing China /* get the input format from the hid descriptor */
5224db52957Spengcheng chen - Sun Microsystems - Beijing China if (usbkbm_get_input_format(usbkbmd) != USB_SUCCESS) {
5237c478bd9Sstevel@tonic-gate
5247c478bd9Sstevel@tonic-gate USB_DPRINTF_L3(PRINT_MASK_OPEN, usbkbm_log_handle,
5257c478bd9Sstevel@tonic-gate "usbkbm: Invalid HID Descriptor Tree."
5264db52957Spengcheng chen - Sun Microsystems - Beijing China "setting default report format");
5277c478bd9Sstevel@tonic-gate }
5287c478bd9Sstevel@tonic-gate
5296d9a41ffSqz150045 /*
5306d9a41ffSqz150045 * Although Sun Japanese type6 and type7 keyboards have the same
5316d9a41ffSqz150045 * layout number(15), they should be recognized for loading the
5326d9a41ffSqz150045 * different keytables on upper apps (e.g. X). The new layout
5336d9a41ffSqz150045 * number (271) is defined for the Sun Japanese type6 keyboards.
5346d9a41ffSqz150045 * The layout number (15) specified in HID spec is used for other
5356d9a41ffSqz150045 * Japanese keyboards. It is a workaround for the old Sun Japanese
5366d9a41ffSqz150045 * type6 keyboards defect.
5376d9a41ffSqz150045 */
5386d9a41ffSqz150045 if (usbkbmd->usbkbm_layout == SUN_JAPANESE_TYPE7) {
5396d9a41ffSqz150045
5406d9a41ffSqz150045 if ((ret = usbkbm_get_vid_pid(usbkbmd)) != 0) {
5416d9a41ffSqz150045
5426d9a41ffSqz150045 return (ret);
5436d9a41ffSqz150045 }
5446d9a41ffSqz150045
5456d9a41ffSqz150045 if ((usbkbmd->usbkbm_vid_pid.VendorId ==
5466d9a41ffSqz150045 HID_SUN_JAPANESE_TYPE6_KBD_VID) &&
5476d9a41ffSqz150045 (usbkbmd->usbkbm_vid_pid.ProductId ==
5486d9a41ffSqz150045 HID_SUN_JAPANESE_TYPE6_KBD_PID)) {
5496d9a41ffSqz150045 usbkbmd->usbkbm_layout = SUN_JAPANESE_TYPE6;
5506d9a41ffSqz150045 }
5516d9a41ffSqz150045 }
5526d9a41ffSqz150045
5537c478bd9Sstevel@tonic-gate kbtrans_streams_set_keyboard(usbkbmd->usbkbm_kbtrans, KB_USB,
5547c478bd9Sstevel@tonic-gate usbkbm_keyindex);
5557c478bd9Sstevel@tonic-gate
5567c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_flags = USBKBM_OPEN;
5577c478bd9Sstevel@tonic-gate
5587c478bd9Sstevel@tonic-gate kbtrans_streams_enable(usbkbmd->usbkbm_kbtrans);
5597c478bd9Sstevel@tonic-gate
560ac9468f8Spengcheng chen - Sun Microsystems - Beijing China /*
561ac9468f8Spengcheng chen - Sun Microsystems - Beijing China * Enable abort sequence on inital. For an internal open, conskbd
562ac9468f8Spengcheng chen - Sun Microsystems - Beijing China * will disable driver abort handling (later through M_IOCTL) and
563ac9468f8Spengcheng chen - Sun Microsystems - Beijing China * handle it by itself.
564ac9468f8Spengcheng chen - Sun Microsystems - Beijing China * For an external (aka. physical) open, this is necessary since
565ac9468f8Spengcheng chen - Sun Microsystems - Beijing China * no STREAMS module linked on top of usbkbm handles abort sequence.
566ac9468f8Spengcheng chen - Sun Microsystems - Beijing China */
567ac9468f8Spengcheng chen - Sun Microsystems - Beijing China mctlmsg.ioc_cmd = CONSSETABORTENABLE;
568ac9468f8Spengcheng chen - Sun Microsystems - Beijing China mctlmsg.ioc_count = TRANSPARENT;
569ac9468f8Spengcheng chen - Sun Microsystems - Beijing China mctl_ptr = usba_mk_mctl(mctlmsg, &abortable, sizeof (abortable));
570ac9468f8Spengcheng chen - Sun Microsystems - Beijing China if (mctl_ptr != NULL) {
571ac9468f8Spengcheng chen - Sun Microsystems - Beijing China DB_TYPE(mctl_ptr) = M_IOCTL;
572ac9468f8Spengcheng chen - Sun Microsystems - Beijing China if (kbtrans_streams_message(usbkbmd->usbkbm_kbtrans, mctl_ptr)
573ac9468f8Spengcheng chen - Sun Microsystems - Beijing China != KBTRANS_MESSAGE_HANDLED) {
574ac9468f8Spengcheng chen - Sun Microsystems - Beijing China freemsg(mctl_ptr);
575ac9468f8Spengcheng chen - Sun Microsystems - Beijing China }
576ac9468f8Spengcheng chen - Sun Microsystems - Beijing China } else {
577ac9468f8Spengcheng chen - Sun Microsystems - Beijing China USB_DPRINTF_L3(PRINT_MASK_OPEN, usbkbm_log_handle,
578ac9468f8Spengcheng chen - Sun Microsystems - Beijing China "usbkbm: enable abort sequence failed");
579ac9468f8Spengcheng chen - Sun Microsystems - Beijing China }
580ac9468f8Spengcheng chen - Sun Microsystems - Beijing China
5817c478bd9Sstevel@tonic-gate USB_DPRINTF_L3(PRINT_MASK_OPEN, usbkbm_log_handle,
5827c478bd9Sstevel@tonic-gate "usbkbm_open exiting");
5837c478bd9Sstevel@tonic-gate return (0);
5847c478bd9Sstevel@tonic-gate }
5857c478bd9Sstevel@tonic-gate
5867c478bd9Sstevel@tonic-gate
5877c478bd9Sstevel@tonic-gate /*
5887c478bd9Sstevel@tonic-gate * usbkbm_close :
5897c478bd9Sstevel@tonic-gate * Close a keyboard.
5907c478bd9Sstevel@tonic-gate */
5917c478bd9Sstevel@tonic-gate /* ARGSUSED1 */
5927c478bd9Sstevel@tonic-gate static int
usbkbm_close(register queue_t * q,int flag,cred_t * crp)5937c478bd9Sstevel@tonic-gate usbkbm_close(register queue_t *q, int flag, cred_t *crp)
5947c478bd9Sstevel@tonic-gate {
5957c478bd9Sstevel@tonic-gate usbkbm_state_t *usbkbmd = (usbkbm_state_t *)q->q_ptr;
5967c478bd9Sstevel@tonic-gate
5977c478bd9Sstevel@tonic-gate /* If a beep is in progress, stop that */
598c35aa225Smarx (void) beeper_off();
5997c478bd9Sstevel@tonic-gate
6007c478bd9Sstevel@tonic-gate (void) kbtrans_streams_fini(usbkbmd->usbkbm_kbtrans);
6017c478bd9Sstevel@tonic-gate
6027c478bd9Sstevel@tonic-gate qprocsoff(q);
6037c478bd9Sstevel@tonic-gate /*
6047c478bd9Sstevel@tonic-gate * Since we're about to destroy our private data, turn off
6057c478bd9Sstevel@tonic-gate * our open flag first, so we don't accept any more input
6067c478bd9Sstevel@tonic-gate * and try to use that data.
6077c478bd9Sstevel@tonic-gate */
6087c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_flags = 0;
6097c478bd9Sstevel@tonic-gate
6107c478bd9Sstevel@tonic-gate kmem_free(usbkbmd, sizeof (usbkbm_state_t));
6117c478bd9Sstevel@tonic-gate
6127c478bd9Sstevel@tonic-gate USB_DPRINTF_L3(PRINT_MASK_CLOSE, usbkbm_log_handle,
6137c478bd9Sstevel@tonic-gate "usbkbm_close exiting");
6147c478bd9Sstevel@tonic-gate
6157c478bd9Sstevel@tonic-gate return (0);
6167c478bd9Sstevel@tonic-gate }
6177c478bd9Sstevel@tonic-gate
6187c478bd9Sstevel@tonic-gate
6197c478bd9Sstevel@tonic-gate /*
6207c478bd9Sstevel@tonic-gate * usbkbm_wput :
6217c478bd9Sstevel@tonic-gate * usb keyboard module output queue put procedure: handles M_IOCTL
6227c478bd9Sstevel@tonic-gate * messages.
6237c478bd9Sstevel@tonic-gate */
6243bb8546dSToomas Soome static int
usbkbm_wput(register queue_t * q,register mblk_t * mp)6257c478bd9Sstevel@tonic-gate usbkbm_wput(register queue_t *q, register mblk_t *mp)
6267c478bd9Sstevel@tonic-gate {
6277c478bd9Sstevel@tonic-gate usbkbm_state_t *usbkbmd;
6287c478bd9Sstevel@tonic-gate enum kbtrans_message_response ret;
6297c478bd9Sstevel@tonic-gate
6307c478bd9Sstevel@tonic-gate USB_DPRINTF_L3(PRINT_MASK_ALL, usbkbm_log_handle,
6317c478bd9Sstevel@tonic-gate "usbkbm_wput entering");
6327c478bd9Sstevel@tonic-gate
6337c478bd9Sstevel@tonic-gate usbkbmd = (usbkbm_state_t *)q->q_ptr;
6347c478bd9Sstevel@tonic-gate
6357c478bd9Sstevel@tonic-gate /* First, see if kbtrans will handle the message */
6367c478bd9Sstevel@tonic-gate ret = kbtrans_streams_message(usbkbmd->usbkbm_kbtrans, mp);
6377c478bd9Sstevel@tonic-gate
6387c478bd9Sstevel@tonic-gate if (ret == KBTRANS_MESSAGE_HANDLED) {
6397c478bd9Sstevel@tonic-gate
6407c478bd9Sstevel@tonic-gate USB_DPRINTF_L3(PRINT_MASK_ALL, usbkbm_log_handle,
6417c478bd9Sstevel@tonic-gate "usbkbm_wput exiting:2");
6427c478bd9Sstevel@tonic-gate
6433bb8546dSToomas Soome return (0);
6447c478bd9Sstevel@tonic-gate }
6457c478bd9Sstevel@tonic-gate
6467c478bd9Sstevel@tonic-gate /* kbtrans didn't handle the message. Try to handle it here */
6477c478bd9Sstevel@tonic-gate
6487c478bd9Sstevel@tonic-gate switch (mp->b_datap->db_type) {
6497c478bd9Sstevel@tonic-gate
6507c478bd9Sstevel@tonic-gate case M_FLUSH:
6517c478bd9Sstevel@tonic-gate if (*mp->b_rptr & FLUSHW) {
6527c478bd9Sstevel@tonic-gate flushq(q, FLUSHDATA);
6537c478bd9Sstevel@tonic-gate }
6547c478bd9Sstevel@tonic-gate
6557c478bd9Sstevel@tonic-gate if (*mp->b_rptr & FLUSHR) {
6567c478bd9Sstevel@tonic-gate flushq(RD(q), FLUSHDATA);
6577c478bd9Sstevel@tonic-gate }
6587c478bd9Sstevel@tonic-gate
6597c478bd9Sstevel@tonic-gate break;
6607c478bd9Sstevel@tonic-gate
6617c478bd9Sstevel@tonic-gate case M_IOCTL:
6627c478bd9Sstevel@tonic-gate ret = usbkbm_ioctl(q, mp);
6637c478bd9Sstevel@tonic-gate
6647c478bd9Sstevel@tonic-gate if (ret == KBTRANS_MESSAGE_HANDLED) {
6657c478bd9Sstevel@tonic-gate
6667c478bd9Sstevel@tonic-gate USB_DPRINTF_L3(PRINT_MASK_ALL, usbkbm_log_handle,
6677c478bd9Sstevel@tonic-gate "usbkbm_wput exiting:1");
6687c478bd9Sstevel@tonic-gate
6693bb8546dSToomas Soome return (0);
6707c478bd9Sstevel@tonic-gate }
6717c478bd9Sstevel@tonic-gate default:
6727c478bd9Sstevel@tonic-gate break;
6737c478bd9Sstevel@tonic-gate }
6747c478bd9Sstevel@tonic-gate
6757c478bd9Sstevel@tonic-gate /*
6767c478bd9Sstevel@tonic-gate * The message has not been handled
6777c478bd9Sstevel@tonic-gate * by kbtrans or this module. Pass it down the stream
6787c478bd9Sstevel@tonic-gate */
6797c478bd9Sstevel@tonic-gate putnext(q, mp);
6807c478bd9Sstevel@tonic-gate
6817c478bd9Sstevel@tonic-gate USB_DPRINTF_L3(PRINT_MASK_ALL, usbkbm_log_handle,
6827c478bd9Sstevel@tonic-gate "usbkbm_wput exiting:3");
6833bb8546dSToomas Soome return (0);
6847c478bd9Sstevel@tonic-gate }
6857c478bd9Sstevel@tonic-gate
6867c478bd9Sstevel@tonic-gate /*
6877c478bd9Sstevel@tonic-gate * usbkbm_ioctl :
6887c478bd9Sstevel@tonic-gate * Handles the ioctls sent from upper module. Returns
6897c478bd9Sstevel@tonic-gate * ACK/NACK back.
6907c478bd9Sstevel@tonic-gate */
6917c478bd9Sstevel@tonic-gate static enum kbtrans_message_response
usbkbm_ioctl(register queue_t * q,register mblk_t * mp)6927c478bd9Sstevel@tonic-gate usbkbm_ioctl(register queue_t *q, register mblk_t *mp)
6937c478bd9Sstevel@tonic-gate {
6947c478bd9Sstevel@tonic-gate usbkbm_state_t *usbkbmd;
6957c478bd9Sstevel@tonic-gate struct iocblk mctlmsg;
6967c478bd9Sstevel@tonic-gate struct iocblk *iocp;
6977c478bd9Sstevel@tonic-gate mblk_t *datap, *mctl_ptr;
6987c478bd9Sstevel@tonic-gate size_t ioctlrespsize;
6997c478bd9Sstevel@tonic-gate int err;
7007c478bd9Sstevel@tonic-gate int tmp;
701c35aa225Smarx int cycles;
702c35aa225Smarx int frequency;
703c35aa225Smarx int msecs;
7047c478bd9Sstevel@tonic-gate char command;
7057c478bd9Sstevel@tonic-gate
7067c478bd9Sstevel@tonic-gate err = 0;
7077c478bd9Sstevel@tonic-gate
7087c478bd9Sstevel@tonic-gate usbkbmd = (usbkbm_state_t *)q->q_ptr;
7097c478bd9Sstevel@tonic-gate iocp = (struct iocblk *)mp->b_rptr;
7107c478bd9Sstevel@tonic-gate
7117c478bd9Sstevel@tonic-gate switch (iocp->ioc_cmd) {
7127c478bd9Sstevel@tonic-gate case CONSSETKBDTYPE:
7137c478bd9Sstevel@tonic-gate err = miocpullup(mp, sizeof (int));
7147c478bd9Sstevel@tonic-gate if (err != 0) {
7157c478bd9Sstevel@tonic-gate break;
7167c478bd9Sstevel@tonic-gate }
7177c478bd9Sstevel@tonic-gate tmp = *(int *)mp->b_cont->b_rptr;
7187c478bd9Sstevel@tonic-gate if (tmp != KB_PC && tmp != KB_USB) {
7197c478bd9Sstevel@tonic-gate err = EINVAL;
7207c478bd9Sstevel@tonic-gate break;
7217c478bd9Sstevel@tonic-gate }
7227c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_vkbd_type = tmp;
7237c478bd9Sstevel@tonic-gate break;
7247c478bd9Sstevel@tonic-gate case KIOCLAYOUT:
7257c478bd9Sstevel@tonic-gate
7267c478bd9Sstevel@tonic-gate datap = allocb(sizeof (int), BPRI_HI);
7277c478bd9Sstevel@tonic-gate if (datap == NULL) {
7287c478bd9Sstevel@tonic-gate ioctlrespsize = sizeof (int);
7297c478bd9Sstevel@tonic-gate
7307c478bd9Sstevel@tonic-gate goto allocfailure;
7317c478bd9Sstevel@tonic-gate }
7327c478bd9Sstevel@tonic-gate
7337c478bd9Sstevel@tonic-gate *(int *)datap->b_wptr = usbkbmd->usbkbm_layout;
7347c478bd9Sstevel@tonic-gate datap->b_wptr += sizeof (int);
7357c478bd9Sstevel@tonic-gate
7367c478bd9Sstevel@tonic-gate freemsg(mp->b_cont);
7377c478bd9Sstevel@tonic-gate
7387c478bd9Sstevel@tonic-gate mp->b_cont = datap;
7397c478bd9Sstevel@tonic-gate iocp->ioc_count = sizeof (int);
7407c478bd9Sstevel@tonic-gate break;
7417c478bd9Sstevel@tonic-gate
7427c478bd9Sstevel@tonic-gate case KIOCSLAYOUT:
7437c478bd9Sstevel@tonic-gate /*
7447c478bd9Sstevel@tonic-gate * Supply a layout if not specified by the hardware, or
7457c478bd9Sstevel@tonic-gate * override any that was specified.
7467c478bd9Sstevel@tonic-gate */
7477c478bd9Sstevel@tonic-gate if (iocp->ioc_count != TRANSPARENT) {
7487c478bd9Sstevel@tonic-gate err = EINVAL;
7497c478bd9Sstevel@tonic-gate break;
7507c478bd9Sstevel@tonic-gate }
7517c478bd9Sstevel@tonic-gate
7527c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_layout = *(intptr_t *)mp->b_cont->b_rptr;
7537c478bd9Sstevel@tonic-gate
7547c478bd9Sstevel@tonic-gate /*
7557c478bd9Sstevel@tonic-gate * Save the layout in usbkbm_layout so as to handle the
7567c478bd9Sstevel@tonic-gate * the case when the user has re-plugged in the non-self
7577c478bd9Sstevel@tonic-gate * identifying non US keyboard. In this the layout is saved
7587c478bd9Sstevel@tonic-gate * in global variable, so the user does not have to run
7597c478bd9Sstevel@tonic-gate * kdmconfig again after the X server reset
7607c478bd9Sstevel@tonic-gate */
7617c478bd9Sstevel@tonic-gate
7627c478bd9Sstevel@tonic-gate usbkbm_layout = usbkbmd->usbkbm_layout;
7637c478bd9Sstevel@tonic-gate break;
7647c478bd9Sstevel@tonic-gate
7657c478bd9Sstevel@tonic-gate case KIOCCMD:
7667c478bd9Sstevel@tonic-gate /*
7677c478bd9Sstevel@tonic-gate * Check if we have at least the subcommand field; any
7687c478bd9Sstevel@tonic-gate * other argument validation has to occur inside
7697c478bd9Sstevel@tonic-gate * usbkbm_kioccmd().
7707c478bd9Sstevel@tonic-gate */
7717c478bd9Sstevel@tonic-gate err = miocpullup(mp, sizeof (int));
7727c478bd9Sstevel@tonic-gate if (err != 0)
7737c478bd9Sstevel@tonic-gate break;
7747c478bd9Sstevel@tonic-gate
7757c478bd9Sstevel@tonic-gate /* Subcommand */
7767c478bd9Sstevel@tonic-gate command = (char)(*(int *)mp->b_cont->b_rptr);
7777c478bd9Sstevel@tonic-gate
7787c478bd9Sstevel@tonic-gate /*
7797c478bd9Sstevel@tonic-gate * Check if this ioctl is followed by a previous
7807c478bd9Sstevel@tonic-gate * KBD_CMD_SETLED command, in which case we take
7817c478bd9Sstevel@tonic-gate * the command byte as the data for setting the LED
7827c478bd9Sstevel@tonic-gate */
7837c478bd9Sstevel@tonic-gate if (usbkbmd->usbkbm_setled_second_byte) {
7847c478bd9Sstevel@tonic-gate usbkbm_streams_setled((struct kbtrans_hardware *)
7857c478bd9Sstevel@tonic-gate usbkbmd, command);
7867c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_setled_second_byte = 0;
7877c478bd9Sstevel@tonic-gate break;
7887c478bd9Sstevel@tonic-gate }
7897c478bd9Sstevel@tonic-gate
7907c478bd9Sstevel@tonic-gate /*
7917c478bd9Sstevel@tonic-gate * In case of allocb failure, this will
7927c478bd9Sstevel@tonic-gate * return the size of the allocation which
7937c478bd9Sstevel@tonic-gate * failed so that it can be allocated later
7947c478bd9Sstevel@tonic-gate * through bufcall.
7957c478bd9Sstevel@tonic-gate */
7967c478bd9Sstevel@tonic-gate ioctlrespsize = 0;
7977c478bd9Sstevel@tonic-gate
7987c478bd9Sstevel@tonic-gate err = usbkbm_kioccmd(usbkbmd, mp, command, &ioctlrespsize);
7997c478bd9Sstevel@tonic-gate
8007c478bd9Sstevel@tonic-gate if (ioctlrespsize != 0) {
8017c478bd9Sstevel@tonic-gate
8027c478bd9Sstevel@tonic-gate goto allocfailure;
8037c478bd9Sstevel@tonic-gate }
8047c478bd9Sstevel@tonic-gate
8057c478bd9Sstevel@tonic-gate break;
8067c478bd9Sstevel@tonic-gate
8077c478bd9Sstevel@tonic-gate case CONSOPENPOLLEDIO:
8087c478bd9Sstevel@tonic-gate USB_DPRINTF_L3(PRINT_MASK_ALL, usbkbm_log_handle,
8097c478bd9Sstevel@tonic-gate "usbkbm_ioctl CONSOPENPOLLEDIO");
8107c478bd9Sstevel@tonic-gate
8117c478bd9Sstevel@tonic-gate err = miocpullup(mp, sizeof (struct cons_polledio *));
8127c478bd9Sstevel@tonic-gate if (err != 0) {
8137c478bd9Sstevel@tonic-gate USB_DPRINTF_L2(PRINT_MASK_ALL, usbkbm_log_handle,
8147c478bd9Sstevel@tonic-gate "usbkbm_ioctl: malformed request");
8157c478bd9Sstevel@tonic-gate break;
8167c478bd9Sstevel@tonic-gate }
8177c478bd9Sstevel@tonic-gate
8187c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_pending_link = mp;
8197c478bd9Sstevel@tonic-gate
8207c478bd9Sstevel@tonic-gate /*
8217c478bd9Sstevel@tonic-gate * Get the polled input structure from hid
8227c478bd9Sstevel@tonic-gate */
8237c478bd9Sstevel@tonic-gate mctlmsg.ioc_cmd = HID_OPEN_POLLED_INPUT;
8247c478bd9Sstevel@tonic-gate mctlmsg.ioc_count = 0;
8257c478bd9Sstevel@tonic-gate mctl_ptr = usba_mk_mctl(mctlmsg, NULL, 0);
8267c478bd9Sstevel@tonic-gate if (mctl_ptr == NULL) {
8277c478bd9Sstevel@tonic-gate ioctlrespsize = sizeof (mctlmsg);
8287c478bd9Sstevel@tonic-gate
8297c478bd9Sstevel@tonic-gate goto allocfailure;
8307c478bd9Sstevel@tonic-gate }
8317c478bd9Sstevel@tonic-gate
8327c478bd9Sstevel@tonic-gate putnext(usbkbmd->usbkbm_writeq, mctl_ptr);
8337c478bd9Sstevel@tonic-gate
8347c478bd9Sstevel@tonic-gate /*
8357c478bd9Sstevel@tonic-gate * Do not ack or nack the message, we will wait for the
8367c478bd9Sstevel@tonic-gate * result of HID_OPEN_POLLED_INPUT
8377c478bd9Sstevel@tonic-gate */
8387c478bd9Sstevel@tonic-gate
8397c478bd9Sstevel@tonic-gate return (KBTRANS_MESSAGE_HANDLED);
8407c478bd9Sstevel@tonic-gate
8417c478bd9Sstevel@tonic-gate case CONSCLOSEPOLLEDIO:
8427c478bd9Sstevel@tonic-gate USB_DPRINTF_L3(PRINT_MASK_ALL, usbkbm_log_handle,
8437c478bd9Sstevel@tonic-gate "usbkbm_ioctl CONSCLOSEPOLLEDIO mp = 0x%p", (void *)mp);
8447c478bd9Sstevel@tonic-gate
8457c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_pending_link = mp;
8467c478bd9Sstevel@tonic-gate
8477c478bd9Sstevel@tonic-gate /*
8487c478bd9Sstevel@tonic-gate * Get the polled input structure from hid
8497c478bd9Sstevel@tonic-gate */
8507c478bd9Sstevel@tonic-gate mctlmsg.ioc_cmd = HID_CLOSE_POLLED_INPUT;
8517c478bd9Sstevel@tonic-gate mctlmsg.ioc_count = 0;
8527c478bd9Sstevel@tonic-gate mctl_ptr = usba_mk_mctl(mctlmsg, NULL, 0);
8537c478bd9Sstevel@tonic-gate if (mctl_ptr == NULL) {
8547c478bd9Sstevel@tonic-gate ioctlrespsize = sizeof (mctlmsg);
8557c478bd9Sstevel@tonic-gate
8567c478bd9Sstevel@tonic-gate goto allocfailure;
8577c478bd9Sstevel@tonic-gate }
8587c478bd9Sstevel@tonic-gate
8597c478bd9Sstevel@tonic-gate putnext(usbkbmd->usbkbm_writeq, mctl_ptr);
8607c478bd9Sstevel@tonic-gate
8617c478bd9Sstevel@tonic-gate /*
8627c478bd9Sstevel@tonic-gate * Do not ack or nack the message, we will wait for the
8637c478bd9Sstevel@tonic-gate * result of HID_CLOSE_POLLED_INPUT
8647c478bd9Sstevel@tonic-gate */
8657c478bd9Sstevel@tonic-gate
8667c478bd9Sstevel@tonic-gate return (KBTRANS_MESSAGE_HANDLED);
8677c478bd9Sstevel@tonic-gate
8687c478bd9Sstevel@tonic-gate case CONSSETABORTENABLE:
8697c478bd9Sstevel@tonic-gate /*
8707c478bd9Sstevel@tonic-gate * Nothing special to do for USB.
8717c478bd9Sstevel@tonic-gate */
8727c478bd9Sstevel@tonic-gate break;
8737c478bd9Sstevel@tonic-gate
8747c478bd9Sstevel@tonic-gate
875c35aa225Smarx case KIOCMKTONE:
876c35aa225Smarx if (iocp->ioc_count != TRANSPARENT) {
877c35aa225Smarx err = EINVAL;
878c35aa225Smarx break;
879c35aa225Smarx }
880c35aa225Smarx
881c35aa225Smarx tmp = (int)(*(intptr_t *)mp->b_cont->b_rptr);
882c35aa225Smarx cycles = tmp & 0xffff;
883c35aa225Smarx msecs = (tmp >> 16) & 0xffff;
884c35aa225Smarx
885c35aa225Smarx if (cycles == 0)
886c35aa225Smarx frequency = UINT16_MAX;
887*100e26fcSToomas Soome else if (cycles == UINT16_MAX) {
888c35aa225Smarx frequency = 0;
889*100e26fcSToomas Soome } else {
890c35aa225Smarx frequency = (PIT_HZ + cycles / 2) / cycles;
891c35aa225Smarx if (frequency > UINT16_MAX)
892c35aa225Smarx frequency = UINT16_MAX;
893c35aa225Smarx }
894c35aa225Smarx
895c35aa225Smarx err = beep_mktone(frequency, msecs);
896c35aa225Smarx break;
897c35aa225Smarx
8987c478bd9Sstevel@tonic-gate default:
8997c478bd9Sstevel@tonic-gate
9007c478bd9Sstevel@tonic-gate return (KBTRANS_MESSAGE_NOT_HANDLED);
9017c478bd9Sstevel@tonic-gate }
9027c478bd9Sstevel@tonic-gate
9037c478bd9Sstevel@tonic-gate /*
9047c478bd9Sstevel@tonic-gate * Send ACK/NACK to upper module for
9057c478bd9Sstevel@tonic-gate * the messages that have been handled.
9067c478bd9Sstevel@tonic-gate */
9077c478bd9Sstevel@tonic-gate if (err != 0) {
9087c478bd9Sstevel@tonic-gate iocp->ioc_rval = 0;
9097c478bd9Sstevel@tonic-gate iocp->ioc_error = err;
9107c478bd9Sstevel@tonic-gate mp->b_datap->db_type = M_IOCNAK;
9117c478bd9Sstevel@tonic-gate } else {
9127c478bd9Sstevel@tonic-gate iocp->ioc_rval = 0;
9137c478bd9Sstevel@tonic-gate iocp->ioc_error = 0; /* brain rot */
9147c478bd9Sstevel@tonic-gate mp->b_datap->db_type = M_IOCACK;
9157c478bd9Sstevel@tonic-gate }
9167c478bd9Sstevel@tonic-gate
9177c478bd9Sstevel@tonic-gate /* Send the response back up the stream */
9187c478bd9Sstevel@tonic-gate putnext(usbkbmd->usbkbm_readq, mp);
9197c478bd9Sstevel@tonic-gate
9207c478bd9Sstevel@tonic-gate return (KBTRANS_MESSAGE_HANDLED);
9217c478bd9Sstevel@tonic-gate
9227c478bd9Sstevel@tonic-gate allocfailure:
9237c478bd9Sstevel@tonic-gate /*
9247c478bd9Sstevel@tonic-gate * We needed to allocate something to handle this "ioctl", but
9257c478bd9Sstevel@tonic-gate * couldn't; save this "ioctl" and arrange to get called back when
9267c478bd9Sstevel@tonic-gate * it's more likely that we can get what we need.
9277c478bd9Sstevel@tonic-gate * If there's already one being saved, throw it out, since it
9287c478bd9Sstevel@tonic-gate * must have timed out.
9297c478bd9Sstevel@tonic-gate */
9307c478bd9Sstevel@tonic-gate freemsg(usbkbmd->usbkbm_streams_iocpending);
9317c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_streams_iocpending = mp;
9327c478bd9Sstevel@tonic-gate
9337c478bd9Sstevel@tonic-gate if (usbkbmd->usbkbm_streams_bufcallid) {
9347c478bd9Sstevel@tonic-gate
9357c478bd9Sstevel@tonic-gate qunbufcall(usbkbmd->usbkbm_readq,
9367c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_streams_bufcallid);
9377c478bd9Sstevel@tonic-gate }
9387c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_streams_bufcallid =
9397c478bd9Sstevel@tonic-gate qbufcall(usbkbmd->usbkbm_readq, ioctlrespsize, BPRI_HI,
9407c478bd9Sstevel@tonic-gate usbkbm_reioctl, usbkbmd);
9417c478bd9Sstevel@tonic-gate
9427c478bd9Sstevel@tonic-gate return (KBTRANS_MESSAGE_HANDLED);
9437c478bd9Sstevel@tonic-gate }
9447c478bd9Sstevel@tonic-gate
9457c478bd9Sstevel@tonic-gate /*
9467c478bd9Sstevel@tonic-gate * usbkbm_kioccmd :
9477c478bd9Sstevel@tonic-gate * Handles KIOCCMD ioctl.
9487c478bd9Sstevel@tonic-gate */
9497c478bd9Sstevel@tonic-gate static int
usbkbm_kioccmd(usbkbm_state_t * usbkbmd,register mblk_t * mp,char command,size_t * ioctlrepsize)9507c478bd9Sstevel@tonic-gate usbkbm_kioccmd(usbkbm_state_t *usbkbmd, register mblk_t *mp,
9517c478bd9Sstevel@tonic-gate char command, size_t *ioctlrepsize)
9527c478bd9Sstevel@tonic-gate {
9537c478bd9Sstevel@tonic-gate register mblk_t *datap;
9547c478bd9Sstevel@tonic-gate register struct iocblk *iocp;
9557c478bd9Sstevel@tonic-gate int err = 0;
9567c478bd9Sstevel@tonic-gate
9577c478bd9Sstevel@tonic-gate iocp = (struct iocblk *)mp->b_rptr;
9587c478bd9Sstevel@tonic-gate
9597c478bd9Sstevel@tonic-gate switch (command) {
9607c478bd9Sstevel@tonic-gate
9617c478bd9Sstevel@tonic-gate /* Keyboard layout command */
9627c478bd9Sstevel@tonic-gate case KBD_CMD_GETLAYOUT:
9637c478bd9Sstevel@tonic-gate /* layout learned at attached time. */
9647c478bd9Sstevel@tonic-gate datap = allocb(sizeof (int), BPRI_HI);
9657c478bd9Sstevel@tonic-gate
9667c478bd9Sstevel@tonic-gate /* Return error on allocation failure */
9677c478bd9Sstevel@tonic-gate if (datap == NULL) {
9687c478bd9Sstevel@tonic-gate *ioctlrepsize = sizeof (int);
9697c478bd9Sstevel@tonic-gate
9707c478bd9Sstevel@tonic-gate return (EIO);
9717c478bd9Sstevel@tonic-gate }
9727c478bd9Sstevel@tonic-gate
9737c478bd9Sstevel@tonic-gate *(int *)datap->b_wptr = usbkbmd->usbkbm_layout;
9747c478bd9Sstevel@tonic-gate datap->b_wptr += sizeof (int);
9757c478bd9Sstevel@tonic-gate freemsg(mp->b_cont);
9767c478bd9Sstevel@tonic-gate mp->b_cont = datap;
9777c478bd9Sstevel@tonic-gate iocp->ioc_count = sizeof (int);
9787c478bd9Sstevel@tonic-gate break;
9797c478bd9Sstevel@tonic-gate
9807c478bd9Sstevel@tonic-gate case KBD_CMD_SETLED:
9817c478bd9Sstevel@tonic-gate /*
9827c478bd9Sstevel@tonic-gate * Emulate type 4 keyboard :
9837c478bd9Sstevel@tonic-gate * Ignore this ioctl; the following
9847c478bd9Sstevel@tonic-gate * ioctl will specify the data byte for
9857c478bd9Sstevel@tonic-gate * setting the LEDs; setting usbkbm_setled_second_byte
9867c478bd9Sstevel@tonic-gate * will help recognizing that ioctl
9877c478bd9Sstevel@tonic-gate */
9887c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_setled_second_byte = 1;
9897c478bd9Sstevel@tonic-gate break;
9907c478bd9Sstevel@tonic-gate
9917c478bd9Sstevel@tonic-gate case KBD_CMD_RESET:
9927c478bd9Sstevel@tonic-gate break;
9937c478bd9Sstevel@tonic-gate
9947c478bd9Sstevel@tonic-gate case KBD_CMD_BELL:
9957c478bd9Sstevel@tonic-gate /*
9967c478bd9Sstevel@tonic-gate * USB keyboards do not have a beeper
9977c478bd9Sstevel@tonic-gate * in it, the generic beeper interface
9987c478bd9Sstevel@tonic-gate * is used. Turn the beeper on.
9997c478bd9Sstevel@tonic-gate */
1000c35aa225Smarx (void) beeper_on(BEEP_TYPE4);
10017c478bd9Sstevel@tonic-gate break;
10027c478bd9Sstevel@tonic-gate
10037c478bd9Sstevel@tonic-gate case KBD_CMD_NOBELL:
10047c478bd9Sstevel@tonic-gate /*
10057c478bd9Sstevel@tonic-gate * USB keyboards do not have a beeper
10067c478bd9Sstevel@tonic-gate * in it, the generic beeper interface
10077c478bd9Sstevel@tonic-gate * is used. Turn the beeper off.
10087c478bd9Sstevel@tonic-gate */
1009c35aa225Smarx (void) beeper_off();
10107c478bd9Sstevel@tonic-gate break;
10117c478bd9Sstevel@tonic-gate
10127c478bd9Sstevel@tonic-gate case KBD_CMD_CLICK:
10137c478bd9Sstevel@tonic-gate /* FALLTHRU */
10147c478bd9Sstevel@tonic-gate case KBD_CMD_NOCLICK:
10157c478bd9Sstevel@tonic-gate break;
10167c478bd9Sstevel@tonic-gate
10177c478bd9Sstevel@tonic-gate default:
10187c478bd9Sstevel@tonic-gate err = EIO;
10197c478bd9Sstevel@tonic-gate break;
10207c478bd9Sstevel@tonic-gate
10217c478bd9Sstevel@tonic-gate }
10227c478bd9Sstevel@tonic-gate
10237c478bd9Sstevel@tonic-gate return (err);
10247c478bd9Sstevel@tonic-gate }
10257c478bd9Sstevel@tonic-gate
10267c478bd9Sstevel@tonic-gate /*
10277c478bd9Sstevel@tonic-gate * usbkbm_rput :
10287c478bd9Sstevel@tonic-gate * Put procedure for input from driver end of stream (read queue).
10297c478bd9Sstevel@tonic-gate */
10303bb8546dSToomas Soome static int
usbkbm_rput(queue_t * q,mblk_t * mp)1031*100e26fcSToomas Soome usbkbm_rput(queue_t *q, mblk_t *mp)
10327c478bd9Sstevel@tonic-gate {
10337c478bd9Sstevel@tonic-gate usbkbm_state_t *usbkbmd;
10347c478bd9Sstevel@tonic-gate
10357c478bd9Sstevel@tonic-gate usbkbmd = (usbkbm_state_t *)q->q_ptr;
10367c478bd9Sstevel@tonic-gate
10377c478bd9Sstevel@tonic-gate USB_DPRINTF_L3(PRINT_MASK_ALL, usbkbm_log_handle,
10387c478bd9Sstevel@tonic-gate "usbkbm_rput");
10397c478bd9Sstevel@tonic-gate
1040*100e26fcSToomas Soome if (usbkbmd == NULL) {
10417c478bd9Sstevel@tonic-gate freemsg(mp); /* nobody's listening */
10423bb8546dSToomas Soome return (0);
10437c478bd9Sstevel@tonic-gate }
10447c478bd9Sstevel@tonic-gate
10457c478bd9Sstevel@tonic-gate switch (mp->b_datap->db_type) {
10467c478bd9Sstevel@tonic-gate
10477c478bd9Sstevel@tonic-gate case M_FLUSH:
10487c478bd9Sstevel@tonic-gate if (*mp->b_rptr & FLUSHW)
10497c478bd9Sstevel@tonic-gate flushq(WR(q), FLUSHDATA);
10507c478bd9Sstevel@tonic-gate if (*mp->b_rptr & FLUSHR)
10517c478bd9Sstevel@tonic-gate flushq(q, FLUSHDATA);
10527c478bd9Sstevel@tonic-gate
10537c478bd9Sstevel@tonic-gate freemsg(mp);
10547c478bd9Sstevel@tonic-gate
10553bb8546dSToomas Soome return (0);
10567c478bd9Sstevel@tonic-gate case M_BREAK:
10577c478bd9Sstevel@tonic-gate /*
10587c478bd9Sstevel@tonic-gate * Will get M_BREAK only if this is not the system
10597c478bd9Sstevel@tonic-gate * keyboard, otherwise serial port will eat break
10607c478bd9Sstevel@tonic-gate * and call kmdb/OBP, without passing anything up.
10617c478bd9Sstevel@tonic-gate */
10627c478bd9Sstevel@tonic-gate freemsg(mp);
10637c478bd9Sstevel@tonic-gate
10643bb8546dSToomas Soome return (0);
10657c478bd9Sstevel@tonic-gate case M_DATA:
10667c478bd9Sstevel@tonic-gate if (!(usbkbmd->usbkbm_flags & USBKBM_OPEN)) {
10677c478bd9Sstevel@tonic-gate freemsg(mp); /* not ready to listen */
10687c478bd9Sstevel@tonic-gate
10693bb8546dSToomas Soome return (0);
10707c478bd9Sstevel@tonic-gate }
10717c478bd9Sstevel@tonic-gate
10727c478bd9Sstevel@tonic-gate break;
10737c478bd9Sstevel@tonic-gate case M_CTL:
10747c478bd9Sstevel@tonic-gate usbkbm_mctl_receive(q, mp);
10757c478bd9Sstevel@tonic-gate
10763bb8546dSToomas Soome return (0);
10777c478bd9Sstevel@tonic-gate case M_ERROR:
10787c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_flags &= ~USBKBM_QWAIT;
1079ac9468f8Spengcheng chen - Sun Microsystems - Beijing China if (*mp->b_rptr == ENODEV) {
1080ac9468f8Spengcheng chen - Sun Microsystems - Beijing China putnext(q, mp);
1081ac9468f8Spengcheng chen - Sun Microsystems - Beijing China } else {
10827c478bd9Sstevel@tonic-gate freemsg(mp);
1083ac9468f8Spengcheng chen - Sun Microsystems - Beijing China }
10847c478bd9Sstevel@tonic-gate
10853bb8546dSToomas Soome return (0);
10867c478bd9Sstevel@tonic-gate case M_IOCACK:
10877c478bd9Sstevel@tonic-gate case M_IOCNAK:
10887c478bd9Sstevel@tonic-gate putnext(q, mp);
10897c478bd9Sstevel@tonic-gate
10903bb8546dSToomas Soome return (0);
10917c478bd9Sstevel@tonic-gate default:
10927c478bd9Sstevel@tonic-gate putnext(q, mp);
10937c478bd9Sstevel@tonic-gate
10943bb8546dSToomas Soome return (0);
10957c478bd9Sstevel@tonic-gate }
10967c478bd9Sstevel@tonic-gate
1097*100e26fcSToomas Soome if (putq(q, mp) == 0)
1098*100e26fcSToomas Soome freemsg(mp);
1099*100e26fcSToomas Soome return (0);
1100*100e26fcSToomas Soome }
1101*100e26fcSToomas Soome
1102*100e26fcSToomas Soome static int
usbkbm_rsrv(queue_t * q)1103*100e26fcSToomas Soome usbkbm_rsrv(queue_t *q)
1104*100e26fcSToomas Soome {
1105*100e26fcSToomas Soome usbkbm_state_t *usbkbmd;
1106*100e26fcSToomas Soome mblk_t *mp;
1107*100e26fcSToomas Soome
1108*100e26fcSToomas Soome usbkbmd = (usbkbm_state_t *)q->q_ptr;
1109*100e26fcSToomas Soome
1110*100e26fcSToomas Soome if (usbkbmd == NULL)
1111*100e26fcSToomas Soome return (0);
1112*100e26fcSToomas Soome
1113*100e26fcSToomas Soome while ((mp = getq(q)) != NULL) {
1114*100e26fcSToomas Soome /* usbkbm_rput() should have filtered anything but M_DATA. */
1115*100e26fcSToomas Soome
1116*100e26fcSToomas Soome if (mp->b_datap->db_type != M_DATA) {
1117*100e26fcSToomas Soome freemsg(mp);
1118*100e26fcSToomas Soome continue;
1119*100e26fcSToomas Soome }
1120*100e26fcSToomas Soome
11217c478bd9Sstevel@tonic-gate /*
11227c478bd9Sstevel@tonic-gate * A data message, consisting of bytes from the keyboard.
11237c478bd9Sstevel@tonic-gate * Ram them through the translator, only if there are
11247c478bd9Sstevel@tonic-gate * correct no. of bytes.
11257c478bd9Sstevel@tonic-gate */
11264db52957Spengcheng chen - Sun Microsystems - Beijing China if (MBLKL(mp) == usbkbmd->usbkbm_report_format.tlen) {
11274db52957Spengcheng chen - Sun Microsystems - Beijing China if (usbkbmd->usbkbm_report_format.keyid !=
11284db52957Spengcheng chen - Sun Microsystems - Beijing China HID_REPORT_ID_UNDEFINED) {
11294db52957Spengcheng chen - Sun Microsystems - Beijing China if (*(mp->b_rptr) !=
11304db52957Spengcheng chen - Sun Microsystems - Beijing China usbkbmd->usbkbm_report_format.keyid) {
11314db52957Spengcheng chen - Sun Microsystems - Beijing China freemsg(mp);
1132*100e26fcSToomas Soome continue;
11334db52957Spengcheng chen - Sun Microsystems - Beijing China } else {
11344db52957Spengcheng chen - Sun Microsystems - Beijing China /* We skip the report id prefix */
11354db52957Spengcheng chen - Sun Microsystems - Beijing China mp->b_rptr++;
11364db52957Spengcheng chen - Sun Microsystems - Beijing China }
11374db52957Spengcheng chen - Sun Microsystems - Beijing China }
1138*100e26fcSToomas Soome usbkbm_unpack_usb_packet(usbkbmd,
1139*100e26fcSToomas Soome usbkbm_streams_callback, mp->b_rptr);
11407c478bd9Sstevel@tonic-gate }
11417c478bd9Sstevel@tonic-gate
11427c478bd9Sstevel@tonic-gate freemsg(mp);
1143*100e26fcSToomas Soome }
11443bb8546dSToomas Soome return (0);
11457c478bd9Sstevel@tonic-gate }
11467c478bd9Sstevel@tonic-gate
11477c478bd9Sstevel@tonic-gate /*
11487c478bd9Sstevel@tonic-gate * usbkbm_mctl_receive :
11497c478bd9Sstevel@tonic-gate * Handle M_CTL messages from hid. If we don't understand
11507c478bd9Sstevel@tonic-gate * the command, send it up.
11517c478bd9Sstevel@tonic-gate */
11527c478bd9Sstevel@tonic-gate static void
usbkbm_mctl_receive(register queue_t * q,register mblk_t * mp)11537c478bd9Sstevel@tonic-gate usbkbm_mctl_receive(register queue_t *q, register mblk_t *mp)
11547c478bd9Sstevel@tonic-gate {
11557c478bd9Sstevel@tonic-gate register usbkbm_state_t *usbkbmd = (usbkbm_state_t *)q->q_ptr;
1156827f5d6bSStrony Zhang - Solaris China Team register struct iocblk *iocp;
11577c478bd9Sstevel@tonic-gate caddr_t data = NULL;
1158827f5d6bSStrony Zhang - Solaris China Team mblk_t *reply_mp;
11597c478bd9Sstevel@tonic-gate uchar_t new_buffer[USBKBM_MAXPKTSIZE];
11607c478bd9Sstevel@tonic-gate size_t size;
11617c478bd9Sstevel@tonic-gate
11627c478bd9Sstevel@tonic-gate iocp = (struct iocblk *)mp->b_rptr;
11637c478bd9Sstevel@tonic-gate if (mp->b_cont != NULL)
11647c478bd9Sstevel@tonic-gate data = (caddr_t)mp->b_cont->b_rptr;
11657c478bd9Sstevel@tonic-gate
11667c478bd9Sstevel@tonic-gate switch (iocp->ioc_cmd) {
11677c478bd9Sstevel@tonic-gate
11687c478bd9Sstevel@tonic-gate case HID_SET_REPORT:
11697c478bd9Sstevel@tonic-gate USB_DPRINTF_L3(PRINT_MASK_ALL, usbkbm_log_handle,
11707c478bd9Sstevel@tonic-gate "usbkbm_mctl_receive HID_SET mctl");
11717c478bd9Sstevel@tonic-gate freemsg(mp);
11727c478bd9Sstevel@tonic-gate /* Setting of the LED is not waiting for this message */
11737c478bd9Sstevel@tonic-gate
11747c478bd9Sstevel@tonic-gate break;
11757c478bd9Sstevel@tonic-gate case HID_GET_PARSER_HANDLE:
11767c478bd9Sstevel@tonic-gate if ((data != NULL) &&
11777c478bd9Sstevel@tonic-gate (iocp->ioc_count == sizeof (hidparser_handle_t)) &&
1178d29f5a71Szhigang lu - Sun Microsystems - Beijing China (MBLKL(mp->b_cont) == iocp->ioc_count)) {
11797c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_report_descr =
11807c478bd9Sstevel@tonic-gate *(hidparser_handle_t *)data;
11817c478bd9Sstevel@tonic-gate } else {
11827c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_report_descr = NULL;
11837c478bd9Sstevel@tonic-gate }
11847c478bd9Sstevel@tonic-gate freemsg(mp);
11857c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_flags &= ~USBKBM_QWAIT;
11867c478bd9Sstevel@tonic-gate
11877c478bd9Sstevel@tonic-gate break;
11886d9a41ffSqz150045 case HID_GET_VID_PID:
11896d9a41ffSqz150045 if ((data != NULL) &&
11906d9a41ffSqz150045 (iocp->ioc_count == sizeof (hid_vid_pid_t)) &&
1191d29f5a71Szhigang lu - Sun Microsystems - Beijing China (MBLKL(mp->b_cont) == iocp->ioc_count)) {
11926d9a41ffSqz150045 bcopy(data, &usbkbmd->usbkbm_vid_pid, iocp->ioc_count);
11936d9a41ffSqz150045 }
11946d9a41ffSqz150045 freemsg(mp);
11956d9a41ffSqz150045 usbkbmd->usbkbm_flags &= ~USBKBM_QWAIT;
11966d9a41ffSqz150045
11976d9a41ffSqz150045 break;
11987c478bd9Sstevel@tonic-gate case HID_OPEN_POLLED_INPUT:
11997c478bd9Sstevel@tonic-gate USB_DPRINTF_L3(PRINT_MASK_ALL, usbkbm_log_handle,
12007c478bd9Sstevel@tonic-gate "usbkbm_mctl_receive HID_OPEN_POLLED_INPUT");
12017c478bd9Sstevel@tonic-gate
12027c478bd9Sstevel@tonic-gate size = sizeof (hid_polled_input_callback_t);
12037c478bd9Sstevel@tonic-gate reply_mp = usbkbmd->usbkbm_pending_link;
12047c478bd9Sstevel@tonic-gate if ((data != NULL) &&
12057c478bd9Sstevel@tonic-gate (iocp->ioc_count == size) &&
1206d29f5a71Szhigang lu - Sun Microsystems - Beijing China (MBLKL(mp->b_cont) == size)) {
12077c478bd9Sstevel@tonic-gate /*
12087c478bd9Sstevel@tonic-gate * Copy the information from hid into the
12097c478bd9Sstevel@tonic-gate * state structure
12107c478bd9Sstevel@tonic-gate */
12117c478bd9Sstevel@tonic-gate bcopy(data, &usbkbmd->usbkbm_hid_callback, size);
12127c478bd9Sstevel@tonic-gate reply_mp->b_datap->db_type = M_IOCACK;
12137c478bd9Sstevel@tonic-gate
12147c478bd9Sstevel@tonic-gate /*
12157c478bd9Sstevel@tonic-gate * We are given an appropriate-sized data block,
12167c478bd9Sstevel@tonic-gate * and return a pointer to our structure in it.
12177c478bd9Sstevel@tonic-gate * The structure is saved in the states structure
12187c478bd9Sstevel@tonic-gate */
12197c478bd9Sstevel@tonic-gate *(cons_polledio_t **)reply_mp->b_cont->b_rptr =
12207c478bd9Sstevel@tonic-gate &usbkbmd->usbkbm_polled_info;
12217c478bd9Sstevel@tonic-gate
12227c478bd9Sstevel@tonic-gate } else {
12237c478bd9Sstevel@tonic-gate reply_mp->b_datap->db_type = M_IOCNAK;
12247c478bd9Sstevel@tonic-gate }
12257c478bd9Sstevel@tonic-gate freemsg(mp);
12267c478bd9Sstevel@tonic-gate
12277c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_pending_link = NULL;
12287c478bd9Sstevel@tonic-gate
12297c478bd9Sstevel@tonic-gate putnext(q, reply_mp);
12307c478bd9Sstevel@tonic-gate
12317c478bd9Sstevel@tonic-gate break;
12327c478bd9Sstevel@tonic-gate case HID_CLOSE_POLLED_INPUT:
12337c478bd9Sstevel@tonic-gate USB_DPRINTF_L3(PRINT_MASK_ALL, usbkbm_log_handle,
12347c478bd9Sstevel@tonic-gate "usbkbm_mctl_receive HID_CLOSE_POLLED_INPUT");
12357c478bd9Sstevel@tonic-gate
12367c478bd9Sstevel@tonic-gate
12377c478bd9Sstevel@tonic-gate bzero(&usbkbmd->usbkbm_hid_callback,
12387c478bd9Sstevel@tonic-gate sizeof (hid_polled_input_callback_t));
12397c478bd9Sstevel@tonic-gate
12407c478bd9Sstevel@tonic-gate freemsg(mp);
12417c478bd9Sstevel@tonic-gate
12427c478bd9Sstevel@tonic-gate reply_mp = usbkbmd->usbkbm_pending_link;
12437c478bd9Sstevel@tonic-gate
12447c478bd9Sstevel@tonic-gate iocp = (struct iocblk *)reply_mp->b_rptr;
12457c478bd9Sstevel@tonic-gate
12467c478bd9Sstevel@tonic-gate USB_DPRINTF_L3(PRINT_MASK_ALL, usbkbm_log_handle,
12477c478bd9Sstevel@tonic-gate "usbkbm_mctl_receive reply reply_mp 0x%p cmd 0x%x",
12487c478bd9Sstevel@tonic-gate (void *)reply_mp, iocp->ioc_cmd);
12497c478bd9Sstevel@tonic-gate
12507c478bd9Sstevel@tonic-gate
12517c478bd9Sstevel@tonic-gate reply_mp->b_datap->db_type = M_IOCACK;
12527c478bd9Sstevel@tonic-gate
12537c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_pending_link = NULL;
12547c478bd9Sstevel@tonic-gate
12557c478bd9Sstevel@tonic-gate putnext(q, reply_mp);
12567c478bd9Sstevel@tonic-gate
12577c478bd9Sstevel@tonic-gate break;
12587c478bd9Sstevel@tonic-gate case HID_DISCONNECT_EVENT :
12597c478bd9Sstevel@tonic-gate case HID_POWER_OFF:
12607c478bd9Sstevel@tonic-gate USB_DPRINTF_L3(PRINT_MASK_ALL, usbkbm_log_handle,
12617c478bd9Sstevel@tonic-gate "usbkbm_mctl_receive HID_DISCONNECT_EVENT/HID_POWER_OFF");
12627c478bd9Sstevel@tonic-gate
12637c478bd9Sstevel@tonic-gate /* Indicate all keys have been released */
12647c478bd9Sstevel@tonic-gate bzero(new_buffer, USBKBM_MAXPKTSIZE);
12657c478bd9Sstevel@tonic-gate usbkbm_unpack_usb_packet(usbkbmd, usbkbm_streams_callback,
12664db52957Spengcheng chen - Sun Microsystems - Beijing China new_buffer);
12677c478bd9Sstevel@tonic-gate freemsg(mp);
12687c478bd9Sstevel@tonic-gate
12697c478bd9Sstevel@tonic-gate break;
12707c478bd9Sstevel@tonic-gate case HID_CONNECT_EVENT:
12717c478bd9Sstevel@tonic-gate case HID_FULL_POWER :
12727c478bd9Sstevel@tonic-gate USB_DPRINTF_L3(PRINT_MASK_ALL, usbkbm_log_handle,
12737c478bd9Sstevel@tonic-gate "usbkbm_mctl_receive restore LEDs");
12747c478bd9Sstevel@tonic-gate
12757c478bd9Sstevel@tonic-gate /* send setled command down to restore LED states */
12767c478bd9Sstevel@tonic-gate usbkbm_streams_setled((struct kbtrans_hardware *)usbkbmd,
12777c478bd9Sstevel@tonic-gate usbkbm_led_state);
12787c478bd9Sstevel@tonic-gate
12797c478bd9Sstevel@tonic-gate freemsg(mp);
12807c478bd9Sstevel@tonic-gate
12817c478bd9Sstevel@tonic-gate break;
12827c478bd9Sstevel@tonic-gate default:
12837c478bd9Sstevel@tonic-gate putnext(q, mp);
12847c478bd9Sstevel@tonic-gate
12857c478bd9Sstevel@tonic-gate break;
12867c478bd9Sstevel@tonic-gate }
12877c478bd9Sstevel@tonic-gate }
12887c478bd9Sstevel@tonic-gate
12897c478bd9Sstevel@tonic-gate
12907c478bd9Sstevel@tonic-gate /*
12917c478bd9Sstevel@tonic-gate * usbkbm_streams_setled :
12927c478bd9Sstevel@tonic-gate * Update the keyboard LEDs to match the current keyboard state.
12937c478bd9Sstevel@tonic-gate * Send LED state downstreams to hid driver.
12947c478bd9Sstevel@tonic-gate */
12957c478bd9Sstevel@tonic-gate static void
usbkbm_streams_setled(struct kbtrans_hardware * kbtrans_hw,int state)12967c478bd9Sstevel@tonic-gate usbkbm_streams_setled(struct kbtrans_hardware *kbtrans_hw, int state)
12977c478bd9Sstevel@tonic-gate {
12987c478bd9Sstevel@tonic-gate struct iocblk mctlmsg;
129959c81845Sgc161489 mblk_t *mctl_ptr;
13007c478bd9Sstevel@tonic-gate hid_req_t *LED_report;
13017c478bd9Sstevel@tonic-gate usbkbm_state_t *usbkbmd;
13024db52957Spengcheng chen - Sun Microsystems - Beijing China uchar_t led_id, led_state;
13037c478bd9Sstevel@tonic-gate
13047c478bd9Sstevel@tonic-gate usbkbm_led_state = (uchar_t)state;
13057c478bd9Sstevel@tonic-gate
13067c478bd9Sstevel@tonic-gate usbkbmd = (usbkbm_state_t *)kbtrans_hw;
13077c478bd9Sstevel@tonic-gate
13087c478bd9Sstevel@tonic-gate LED_report = kmem_zalloc(sizeof (hid_req_t), KM_NOSLEEP);
13097c478bd9Sstevel@tonic-gate if (LED_report == NULL) {
13107c478bd9Sstevel@tonic-gate
13117c478bd9Sstevel@tonic-gate return;
13127c478bd9Sstevel@tonic-gate }
13137c478bd9Sstevel@tonic-gate
13147c478bd9Sstevel@tonic-gate /*
13157c478bd9Sstevel@tonic-gate * Send the request to the hid driver to set LED.
13167c478bd9Sstevel@tonic-gate */
13174db52957Spengcheng chen - Sun Microsystems - Beijing China led_id = usbkbmd->usbkbm_report_format.keyid;
13187c478bd9Sstevel@tonic-gate led_state = 0;
13197c478bd9Sstevel@tonic-gate
13207c478bd9Sstevel@tonic-gate /*
13217c478bd9Sstevel@tonic-gate * Set the led state based on the state that is passed in.
13227c478bd9Sstevel@tonic-gate */
13237c478bd9Sstevel@tonic-gate if (state & LED_NUM_LOCK) {
13247c478bd9Sstevel@tonic-gate led_state |= USB_LED_NUM_LOCK;
13257c478bd9Sstevel@tonic-gate }
13267c478bd9Sstevel@tonic-gate
13277c478bd9Sstevel@tonic-gate if (state & LED_COMPOSE) {
13287c478bd9Sstevel@tonic-gate led_state |= USB_LED_COMPOSE;
13297c478bd9Sstevel@tonic-gate }
13307c478bd9Sstevel@tonic-gate
13317c478bd9Sstevel@tonic-gate if (state & LED_SCROLL_LOCK) {
13327c478bd9Sstevel@tonic-gate led_state |= USB_LED_SCROLL_LOCK;
13337c478bd9Sstevel@tonic-gate }
13347c478bd9Sstevel@tonic-gate
13357c478bd9Sstevel@tonic-gate if (state & LED_CAPS_LOCK) {
13367c478bd9Sstevel@tonic-gate led_state |= USB_LED_CAPS_LOCK;
13377c478bd9Sstevel@tonic-gate }
13387c478bd9Sstevel@tonic-gate
13397c478bd9Sstevel@tonic-gate if (state & LED_KANA) {
13407c478bd9Sstevel@tonic-gate led_state |= USB_LED_KANA;
13417c478bd9Sstevel@tonic-gate }
13427c478bd9Sstevel@tonic-gate
13437c478bd9Sstevel@tonic-gate LED_report->hid_req_version_no = HID_VERSION_V_0;
13444db52957Spengcheng chen - Sun Microsystems - Beijing China LED_report->hid_req_wValue = REPORT_TYPE_OUTPUT | led_id;
13457c478bd9Sstevel@tonic-gate LED_report->hid_req_wLength = sizeof (uchar_t);
134659c81845Sgc161489 LED_report->hid_req_data[0] = led_state;
13477c478bd9Sstevel@tonic-gate
13487c478bd9Sstevel@tonic-gate mctlmsg.ioc_cmd = HID_SET_REPORT;
13497c478bd9Sstevel@tonic-gate mctlmsg.ioc_count = sizeof (LED_report);
13507c478bd9Sstevel@tonic-gate mctl_ptr = usba_mk_mctl(mctlmsg, LED_report, sizeof (hid_req_t));
13517c478bd9Sstevel@tonic-gate if (mctl_ptr != NULL) {
13527c478bd9Sstevel@tonic-gate putnext(usbkbmd->usbkbm_writeq, mctl_ptr);
13537c478bd9Sstevel@tonic-gate }
13547c478bd9Sstevel@tonic-gate
13557c478bd9Sstevel@tonic-gate /*
13567c478bd9Sstevel@tonic-gate * We are not waiting for response of HID_SET_REPORT
13577c478bd9Sstevel@tonic-gate * mctl for setting the LED.
13587c478bd9Sstevel@tonic-gate */
13597c478bd9Sstevel@tonic-gate kmem_free(LED_report, sizeof (hid_req_t));
13607c478bd9Sstevel@tonic-gate }
13617c478bd9Sstevel@tonic-gate
13627c478bd9Sstevel@tonic-gate
13637c478bd9Sstevel@tonic-gate /*
13647c478bd9Sstevel@tonic-gate * usbkbm_polled_keycheck :
13657c478bd9Sstevel@tonic-gate * This routine is called to determine if there is a scancode that
13667c478bd9Sstevel@tonic-gate * is available for input. This routine is called at poll time and
13677c478bd9Sstevel@tonic-gate * returns a key/state pair to the caller. If there are characters
13687c478bd9Sstevel@tonic-gate * buffered up, the routine returns right away with the key/state pair.
13697c478bd9Sstevel@tonic-gate * Otherwise, the routine calls down to check for characters and returns
13707c478bd9Sstevel@tonic-gate * the first key/state pair if there are any characters pending.
13717c478bd9Sstevel@tonic-gate */
13727c478bd9Sstevel@tonic-gate static boolean_t
usbkbm_polled_keycheck(struct kbtrans_hardware * hw,int * key,enum keystate * state)13737c478bd9Sstevel@tonic-gate usbkbm_polled_keycheck(struct kbtrans_hardware *hw,
13747c478bd9Sstevel@tonic-gate int *key, enum keystate *state)
13757c478bd9Sstevel@tonic-gate {
13767c478bd9Sstevel@tonic-gate usbkbm_state_t *usbkbmd;
13777c478bd9Sstevel@tonic-gate uchar_t *buffer;
13784db52957Spengcheng chen - Sun Microsystems - Beijing China unsigned size;
13797c478bd9Sstevel@tonic-gate hid_polled_handle_t hid_polled_handle;
13807c478bd9Sstevel@tonic-gate
13817c478bd9Sstevel@tonic-gate usbkbmd = (usbkbm_state_t *)hw;
13827c478bd9Sstevel@tonic-gate
13837c478bd9Sstevel@tonic-gate /*
13847c478bd9Sstevel@tonic-gate * If there are already characters buffered up, then we are done.
13857c478bd9Sstevel@tonic-gate */
13867c478bd9Sstevel@tonic-gate if (usbkbmd->usbkbm_polled_buffer_num_characters != 0) {
13877c478bd9Sstevel@tonic-gate
13887c478bd9Sstevel@tonic-gate usbkbm_get_scancode(usbkbmd, key, state);
13897c478bd9Sstevel@tonic-gate
13907c478bd9Sstevel@tonic-gate return (B_TRUE);
13917c478bd9Sstevel@tonic-gate }
13927c478bd9Sstevel@tonic-gate
13937c478bd9Sstevel@tonic-gate hid_polled_handle =
13947c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_hid_callback.hid_polled_input_handle;
13957c478bd9Sstevel@tonic-gate
13964db52957Spengcheng chen - Sun Microsystems - Beijing China size = (usbkbmd->usbkbm_hid_callback.hid_polled_read)
13977c478bd9Sstevel@tonic-gate (hid_polled_handle, &buffer);
13987c478bd9Sstevel@tonic-gate
13997c478bd9Sstevel@tonic-gate /*
14004db52957Spengcheng chen - Sun Microsystems - Beijing China * If we don't get a valid input report then indicate that,
14014db52957Spengcheng chen - Sun Microsystems - Beijing China * and we are done.
14027c478bd9Sstevel@tonic-gate */
14034db52957Spengcheng chen - Sun Microsystems - Beijing China if (size != usbkbmd->usbkbm_report_format.tlen) {
14047c478bd9Sstevel@tonic-gate return (B_FALSE);
14057c478bd9Sstevel@tonic-gate }
14067c478bd9Sstevel@tonic-gate
14077c478bd9Sstevel@tonic-gate /*
14087c478bd9Sstevel@tonic-gate * We have a usb packet, so pass this packet to
14097c478bd9Sstevel@tonic-gate * usbkbm_unpack_usb_packet so that it can be broken up into
14107c478bd9Sstevel@tonic-gate * individual key/state values.
14117c478bd9Sstevel@tonic-gate */
14124db52957Spengcheng chen - Sun Microsystems - Beijing China if (usbkbmd->usbkbm_report_format.keyid != HID_REPORT_ID_UNDEFINED) {
14134db52957Spengcheng chen - Sun Microsystems - Beijing China if (*buffer != usbkbmd->usbkbm_report_format.keyid) {
14144db52957Spengcheng chen - Sun Microsystems - Beijing China return (B_FALSE);
14154db52957Spengcheng chen - Sun Microsystems - Beijing China } else {
14164db52957Spengcheng chen - Sun Microsystems - Beijing China /* We skip the report id prefix */
14174db52957Spengcheng chen - Sun Microsystems - Beijing China buffer++;
14184db52957Spengcheng chen - Sun Microsystems - Beijing China }
14194db52957Spengcheng chen - Sun Microsystems - Beijing China }
14204db52957Spengcheng chen - Sun Microsystems - Beijing China usbkbm_unpack_usb_packet(usbkbmd, usbkbm_poll_callback, buffer);
14217c478bd9Sstevel@tonic-gate
14227c478bd9Sstevel@tonic-gate /*
14237c478bd9Sstevel@tonic-gate * If a scancode was returned as a result of this packet,
14247c478bd9Sstevel@tonic-gate * then translate the scancode.
14257c478bd9Sstevel@tonic-gate */
14267c478bd9Sstevel@tonic-gate if (usbkbmd->usbkbm_polled_buffer_num_characters != 0) {
14277c478bd9Sstevel@tonic-gate
14287c478bd9Sstevel@tonic-gate usbkbm_get_scancode(usbkbmd, key, state);
14297c478bd9Sstevel@tonic-gate
14307c478bd9Sstevel@tonic-gate return (B_TRUE);
14317c478bd9Sstevel@tonic-gate }
14327c478bd9Sstevel@tonic-gate
14337c478bd9Sstevel@tonic-gate return (B_FALSE);
14347c478bd9Sstevel@tonic-gate }
14357c478bd9Sstevel@tonic-gate
usbkbm_get_state(usbkbm_state_t * usbkbmd)14367c478bd9Sstevel@tonic-gate static ushort_t usbkbm_get_state(usbkbm_state_t *usbkbmd)
14377c478bd9Sstevel@tonic-gate {
14387c478bd9Sstevel@tonic-gate ushort_t ret;
14397c478bd9Sstevel@tonic-gate
14407c478bd9Sstevel@tonic-gate ASSERT(usbkbmd->usbkbm_vkbd_type == KB_PC ||
14417c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_vkbd_type == KB_USB);
14427c478bd9Sstevel@tonic-gate
14437c478bd9Sstevel@tonic-gate if (usbkbmd->usbkbm_vkbd_type == KB_PC)
14447c478bd9Sstevel@tonic-gate ret = INDEXTO_PC;
14457c478bd9Sstevel@tonic-gate else
14467c478bd9Sstevel@tonic-gate ret = INDEXTO_USB;
14477c478bd9Sstevel@tonic-gate
14487c478bd9Sstevel@tonic-gate return (ret);
14497c478bd9Sstevel@tonic-gate }
14507c478bd9Sstevel@tonic-gate /*
14517c478bd9Sstevel@tonic-gate * usbkbm_streams_callback :
14527c478bd9Sstevel@tonic-gate * This is the routine that is going to be called when unpacking
14537c478bd9Sstevel@tonic-gate * usb packets for normal streams-based input. We pass a pointer
14547c478bd9Sstevel@tonic-gate * to this routine to usbkbm_unpack_usb_packet. This routine will
14557c478bd9Sstevel@tonic-gate * get called with an unpacked key (scancode) and state (press/release).
14567c478bd9Sstevel@tonic-gate * We pass it to the generic keyboard module.
14577c478bd9Sstevel@tonic-gate *
14587c478bd9Sstevel@tonic-gate * 'index' and the function pointers:
14597c478bd9Sstevel@tonic-gate * Map USB scancodes to PC scancodes by lookup table.
14607c478bd9Sstevel@tonic-gate * This fix is mainly meant for x86 platforms. For SPARC systems
14617c478bd9Sstevel@tonic-gate * this fix doesn't change the way in which the scancodes are processed.
14627c478bd9Sstevel@tonic-gate */
14637c478bd9Sstevel@tonic-gate static void
usbkbm_streams_callback(usbkbm_state_t * usbkbmd,int key,enum keystate state)14647c478bd9Sstevel@tonic-gate usbkbm_streams_callback(usbkbm_state_t *usbkbmd, int key, enum keystate state)
14657c478bd9Sstevel@tonic-gate {
14667c478bd9Sstevel@tonic-gate ushort_t index = usbkbm_get_state(usbkbmd);
14677c478bd9Sstevel@tonic-gate (*usbkbm_xlate[index])(usbkbmd, key, state);
14687c478bd9Sstevel@tonic-gate }
14697c478bd9Sstevel@tonic-gate
14707c478bd9Sstevel@tonic-gate /*
14717c478bd9Sstevel@tonic-gate * Don't do any translations. Send to 'kbtrans' for processing.
14727c478bd9Sstevel@tonic-gate */
14737c478bd9Sstevel@tonic-gate static void
usbkbm_wrap_kbtrans(usbkbm_state_t * usbkbmd,int key,enum keystate state)14747c478bd9Sstevel@tonic-gate usbkbm_wrap_kbtrans(usbkbm_state_t *usbkbmd, int key, enum keystate state)
14757c478bd9Sstevel@tonic-gate {
14767c478bd9Sstevel@tonic-gate kbtrans_streams_key(usbkbmd->usbkbm_kbtrans, key, state);
14777c478bd9Sstevel@tonic-gate }
14787c478bd9Sstevel@tonic-gate
14797c478bd9Sstevel@tonic-gate /*
14807c478bd9Sstevel@tonic-gate * Translate USB scancodes to PC scancodes before sending it to 'kbtrans'
14817c478bd9Sstevel@tonic-gate */
14827c478bd9Sstevel@tonic-gate void
usbkbm_usb2pc_xlate(usbkbm_state_t * usbkbmd,int key,enum keystate state)14837c478bd9Sstevel@tonic-gate usbkbm_usb2pc_xlate(usbkbm_state_t *usbkbmd, int key, enum keystate state)
14847c478bd9Sstevel@tonic-gate {
14857c478bd9Sstevel@tonic-gate key = kbtrans_keycode_usb2pc(key);
14867c478bd9Sstevel@tonic-gate kbtrans_streams_key(usbkbmd->usbkbm_kbtrans, key, state);
14877c478bd9Sstevel@tonic-gate }
14887c478bd9Sstevel@tonic-gate
14897c478bd9Sstevel@tonic-gate /*
14907c478bd9Sstevel@tonic-gate * usbkbm_poll_callback :
14917c478bd9Sstevel@tonic-gate * This is the routine that is going to be called when unpacking
14927c478bd9Sstevel@tonic-gate * usb packets for polled input. We pass a pointer to this routine
14937c478bd9Sstevel@tonic-gate * to usbkbm_unpack_usb_packet. This routine will get called with
14947c478bd9Sstevel@tonic-gate * an unpacked key (scancode) and state (press/release). We will
14957c478bd9Sstevel@tonic-gate * store the key/state pair into a circular buffer so that it can
14967c478bd9Sstevel@tonic-gate * be translated into an ascii key later.
14977c478bd9Sstevel@tonic-gate */
14987c478bd9Sstevel@tonic-gate static void
usbkbm_poll_callback(usbkbm_state_t * usbkbmd,int key,enum keystate state)14997c478bd9Sstevel@tonic-gate usbkbm_poll_callback(usbkbm_state_t *usbkbmd, int key, enum keystate state)
15007c478bd9Sstevel@tonic-gate {
15017c478bd9Sstevel@tonic-gate /*
15027c478bd9Sstevel@tonic-gate * Check to make sure that the buffer isn't already full
15037c478bd9Sstevel@tonic-gate */
15047c478bd9Sstevel@tonic-gate if (usbkbmd->usbkbm_polled_buffer_num_characters ==
15057c478bd9Sstevel@tonic-gate USB_POLLED_BUFFER_SIZE) {
15067c478bd9Sstevel@tonic-gate
15077c478bd9Sstevel@tonic-gate /*
15087c478bd9Sstevel@tonic-gate * The buffer is full, we will drop this character.
15097c478bd9Sstevel@tonic-gate */
15107c478bd9Sstevel@tonic-gate return;
15117c478bd9Sstevel@tonic-gate }
15127c478bd9Sstevel@tonic-gate
15137c478bd9Sstevel@tonic-gate /*
15147c478bd9Sstevel@tonic-gate * Save the scancode in the buffer
15157c478bd9Sstevel@tonic-gate */
15167c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_polled_buffer_head->poll_key = key;
15177c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_polled_buffer_head->poll_state = state;
15187c478bd9Sstevel@tonic-gate
15197c478bd9Sstevel@tonic-gate /*
15207c478bd9Sstevel@tonic-gate * We have one more character in the buffer
15217c478bd9Sstevel@tonic-gate */
15227c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_polled_buffer_num_characters++;
15237c478bd9Sstevel@tonic-gate
15247c478bd9Sstevel@tonic-gate /*
15257c478bd9Sstevel@tonic-gate * Increment to the next available slot.
15267c478bd9Sstevel@tonic-gate */
15277c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_polled_buffer_head++;
15287c478bd9Sstevel@tonic-gate
15297c478bd9Sstevel@tonic-gate /*
15307c478bd9Sstevel@tonic-gate * Check to see if the tail has wrapped.
15317c478bd9Sstevel@tonic-gate */
15327c478bd9Sstevel@tonic-gate if (usbkbmd->usbkbm_polled_buffer_head -
15337c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_polled_scancode_buffer ==
15347c478bd9Sstevel@tonic-gate USB_POLLED_BUFFER_SIZE) {
15357c478bd9Sstevel@tonic-gate
15367c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_polled_buffer_head =
15377c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_polled_scancode_buffer;
15387c478bd9Sstevel@tonic-gate }
15397c478bd9Sstevel@tonic-gate }
15407c478bd9Sstevel@tonic-gate
15417c478bd9Sstevel@tonic-gate /*
15427c478bd9Sstevel@tonic-gate * usbkbm_get_scancode :
15437c478bd9Sstevel@tonic-gate * This routine retreives a key/state pair from the circular buffer.
15447c478bd9Sstevel@tonic-gate * The pair was put in the buffer by usbkbm_poll_callback when a
15457c478bd9Sstevel@tonic-gate * USB packet was translated into a key/state by usbkbm_unpack_usb_packet.
15467c478bd9Sstevel@tonic-gate */
15477c478bd9Sstevel@tonic-gate static void
usbkbm_get_scancode(usbkbm_state_t * usbkbmd,int * key,enum keystate * state)15487c478bd9Sstevel@tonic-gate usbkbm_get_scancode(usbkbm_state_t *usbkbmd, int *key, enum keystate *state)
15497c478bd9Sstevel@tonic-gate {
15507c478bd9Sstevel@tonic-gate /*
15517c478bd9Sstevel@tonic-gate * Copy the character.
15527c478bd9Sstevel@tonic-gate */
15537c478bd9Sstevel@tonic-gate *key = usbkbmd->usbkbm_polled_buffer_tail->poll_key;
15547c478bd9Sstevel@tonic-gate *state = usbkbmd->usbkbm_polled_buffer_tail->poll_state;
15557c478bd9Sstevel@tonic-gate
15567c478bd9Sstevel@tonic-gate /*
15577c478bd9Sstevel@tonic-gate * Increment to the next character to be copied from
15587c478bd9Sstevel@tonic-gate * and to.
15597c478bd9Sstevel@tonic-gate */
15607c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_polled_buffer_tail++;
15617c478bd9Sstevel@tonic-gate
15627c478bd9Sstevel@tonic-gate /*
15637c478bd9Sstevel@tonic-gate * Check to see if the tail has wrapped.
15647c478bd9Sstevel@tonic-gate */
15657c478bd9Sstevel@tonic-gate if (usbkbmd->usbkbm_polled_buffer_tail -
15667c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_polled_scancode_buffer ==
15677c478bd9Sstevel@tonic-gate USB_POLLED_BUFFER_SIZE) {
15687c478bd9Sstevel@tonic-gate
15697c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_polled_buffer_tail =
15707c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_polled_scancode_buffer;
15717c478bd9Sstevel@tonic-gate }
15727c478bd9Sstevel@tonic-gate
15737c478bd9Sstevel@tonic-gate /*
15747c478bd9Sstevel@tonic-gate * We have one less character in the buffer.
15757c478bd9Sstevel@tonic-gate */
15767c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_polled_buffer_num_characters--;
15777c478bd9Sstevel@tonic-gate }
15787c478bd9Sstevel@tonic-gate
15797c478bd9Sstevel@tonic-gate /*
15807c478bd9Sstevel@tonic-gate * usbkbm_polled_setled :
15817c478bd9Sstevel@tonic-gate * This routine is a place holder. Someday, we may want to allow led
15827c478bd9Sstevel@tonic-gate * state to be updated from within polled mode.
15837c478bd9Sstevel@tonic-gate */
15847c478bd9Sstevel@tonic-gate /* ARGSUSED */
15857c478bd9Sstevel@tonic-gate static void
usbkbm_polled_setled(struct kbtrans_hardware * hw,int led_state)15867c478bd9Sstevel@tonic-gate usbkbm_polled_setled(struct kbtrans_hardware *hw, int led_state)
15877c478bd9Sstevel@tonic-gate {
15887c478bd9Sstevel@tonic-gate /* nothing to do for now */
15897c478bd9Sstevel@tonic-gate }
15907c478bd9Sstevel@tonic-gate
15917c478bd9Sstevel@tonic-gate /*
15927c478bd9Sstevel@tonic-gate * This is a pass-thru routine to get a character at poll time.
15937c478bd9Sstevel@tonic-gate */
15947c478bd9Sstevel@tonic-gate static int
usbkbm_polled_getchar(cons_polledio_arg_t arg)1595281f0747Slt200341 usbkbm_polled_getchar(cons_polledio_arg_t arg)
15967c478bd9Sstevel@tonic-gate {
15977c478bd9Sstevel@tonic-gate usbkbm_state_t *usbkbmd;
15987c478bd9Sstevel@tonic-gate
15997c478bd9Sstevel@tonic-gate usbkbmd = (usbkbm_state_t *)arg;
16007c478bd9Sstevel@tonic-gate
16017c478bd9Sstevel@tonic-gate return (kbtrans_getchar(usbkbmd->usbkbm_kbtrans));
16027c478bd9Sstevel@tonic-gate }
16037c478bd9Sstevel@tonic-gate
16047c478bd9Sstevel@tonic-gate /*
16057c478bd9Sstevel@tonic-gate * This is a pass-thru routine to test if character is available for reading
16067c478bd9Sstevel@tonic-gate * at poll time.
16077c478bd9Sstevel@tonic-gate */
16087c478bd9Sstevel@tonic-gate static boolean_t
usbkbm_polled_ischar(cons_polledio_arg_t arg)1609281f0747Slt200341 usbkbm_polled_ischar(cons_polledio_arg_t arg)
16107c478bd9Sstevel@tonic-gate {
16117c478bd9Sstevel@tonic-gate usbkbm_state_t *usbkbmd;
16127c478bd9Sstevel@tonic-gate
16137c478bd9Sstevel@tonic-gate usbkbmd = (usbkbm_state_t *)arg;
16147c478bd9Sstevel@tonic-gate
16157c478bd9Sstevel@tonic-gate return (kbtrans_ischar(usbkbmd->usbkbm_kbtrans));
16167c478bd9Sstevel@tonic-gate }
16177c478bd9Sstevel@tonic-gate
16187c478bd9Sstevel@tonic-gate /*
16197c478bd9Sstevel@tonic-gate * usbkbm_polled_input_enter :
16207c478bd9Sstevel@tonic-gate * This is a pass-thru initialization routine for the lower layer drivers.
16217c478bd9Sstevel@tonic-gate * This routine is called at poll time to set the state for polled input.
16227c478bd9Sstevel@tonic-gate */
16237c478bd9Sstevel@tonic-gate static void
usbkbm_polled_enter(cons_polledio_arg_t arg)1624281f0747Slt200341 usbkbm_polled_enter(cons_polledio_arg_t arg)
16257c478bd9Sstevel@tonic-gate {
16264db52957Spengcheng chen - Sun Microsystems - Beijing China usbkbm_state_t *usbkbmd = (usbkbm_state_t *)arg;
16277c478bd9Sstevel@tonic-gate hid_polled_handle_t hid_polled_handle;
16284db52957Spengcheng chen - Sun Microsystems - Beijing China int kbstart, kbend, uindex;
16297c478bd9Sstevel@tonic-gate
16304db52957Spengcheng chen - Sun Microsystems - Beijing China kbstart = usbkbmd->usbkbm_report_format.kpos;
16314db52957Spengcheng chen - Sun Microsystems - Beijing China kbend = kbstart + usbkbmd->usbkbm_report_format.klen;
16327c478bd9Sstevel@tonic-gate
16337c478bd9Sstevel@tonic-gate /*
16347c478bd9Sstevel@tonic-gate * Before switching to POLLED mode, copy the contents of
16357c478bd9Sstevel@tonic-gate * usbkbm_pendingusbpacket to usbkbm_lastusbpacket since
16367c478bd9Sstevel@tonic-gate * usbkbm_pendingusbpacket field has currently processed
16377c478bd9Sstevel@tonic-gate * key events of the current OS mode usb keyboard packet.
16387c478bd9Sstevel@tonic-gate */
16394db52957Spengcheng chen - Sun Microsystems - Beijing China for (uindex = kbstart + 2; uindex < kbend; uindex++) {
16407c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_lastusbpacket[uindex] =
16417c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_pendingusbpacket[uindex];
16427c478bd9Sstevel@tonic-gate
16437c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_pendingusbpacket[uindex] = 0;
16447c478bd9Sstevel@tonic-gate }
16457c478bd9Sstevel@tonic-gate
16467c478bd9Sstevel@tonic-gate hid_polled_handle =
16477c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_hid_callback.hid_polled_input_handle;
16487c478bd9Sstevel@tonic-gate
16497c478bd9Sstevel@tonic-gate (void) (usbkbmd->usbkbm_hid_callback.hid_polled_input_enter)
16507c478bd9Sstevel@tonic-gate (hid_polled_handle);
16517c478bd9Sstevel@tonic-gate }
16527c478bd9Sstevel@tonic-gate
16537c478bd9Sstevel@tonic-gate /*
16547c478bd9Sstevel@tonic-gate * usbkbm_polled_input_exit :
16557c478bd9Sstevel@tonic-gate * This is a pass-thru restoration routine for the lower layer drivers.
16567c478bd9Sstevel@tonic-gate * This routine is called at poll time to reset the state back to streams
16577c478bd9Sstevel@tonic-gate * input.
16587c478bd9Sstevel@tonic-gate */
16597c478bd9Sstevel@tonic-gate static void
usbkbm_polled_exit(cons_polledio_arg_t arg)1660281f0747Slt200341 usbkbm_polled_exit(cons_polledio_arg_t arg)
16617c478bd9Sstevel@tonic-gate {
16624db52957Spengcheng chen - Sun Microsystems - Beijing China usbkbm_state_t *usbkbmd = (usbkbm_state_t *)arg;
16637c478bd9Sstevel@tonic-gate hid_polled_handle_t hid_polled_handle;
16644db52957Spengcheng chen - Sun Microsystems - Beijing China int kbstart, kbend, uindex;
16657c478bd9Sstevel@tonic-gate
16664db52957Spengcheng chen - Sun Microsystems - Beijing China kbstart = usbkbmd->usbkbm_report_format.kpos;
16674db52957Spengcheng chen - Sun Microsystems - Beijing China kbend = kbstart + usbkbmd->usbkbm_report_format.klen;
16687c478bd9Sstevel@tonic-gate
16697c478bd9Sstevel@tonic-gate /*
16707c478bd9Sstevel@tonic-gate * Before returning to OS mode, copy the contents of
16717c478bd9Sstevel@tonic-gate * usbkbm_lastusbpacket to usbkbm_pendingusbpacket since
16727c478bd9Sstevel@tonic-gate * usbkbm_lastusbpacket field has processed key events
16737c478bd9Sstevel@tonic-gate * of the last POLLED mode usb keyboard packet.
16747c478bd9Sstevel@tonic-gate */
16754db52957Spengcheng chen - Sun Microsystems - Beijing China for (uindex = kbstart + 2; uindex < kbend; uindex ++) {
16767c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_pendingusbpacket[uindex] =
16777c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_lastusbpacket[uindex];
16787c478bd9Sstevel@tonic-gate
16797c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_lastusbpacket[uindex] = 0;
16807c478bd9Sstevel@tonic-gate }
16817c478bd9Sstevel@tonic-gate
16827c478bd9Sstevel@tonic-gate hid_polled_handle =
16837c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_hid_callback.hid_polled_input_handle;
16847c478bd9Sstevel@tonic-gate
16857c478bd9Sstevel@tonic-gate (void) (usbkbmd->usbkbm_hid_callback.hid_polled_input_exit)
16867c478bd9Sstevel@tonic-gate (hid_polled_handle);
16877c478bd9Sstevel@tonic-gate }
16887c478bd9Sstevel@tonic-gate
16897c478bd9Sstevel@tonic-gate /*
16907c478bd9Sstevel@tonic-gate * usbkbm_unpack_usb_packet :
16912e83744eSsethg * USB key packets contain 8 bytes while in boot-protocol mode.
16927c478bd9Sstevel@tonic-gate * The first byte contains bit packed modifier key information.
16937c478bd9Sstevel@tonic-gate * Second byte is reserved. The last 6 bytes contain bytes of
16947c478bd9Sstevel@tonic-gate * currently pressed keys. If a key was not recorded on the
16957c478bd9Sstevel@tonic-gate * previous packet, but present in the current packet, then set
16967c478bd9Sstevel@tonic-gate * state to KEY_PRESSED. If a key was recorded in the previous packet,
16977c478bd9Sstevel@tonic-gate * but not present in the current packet, then state to KEY_RELEASED
16987c478bd9Sstevel@tonic-gate * Follow a similar algorithm for bit packed modifier keys.
16997c478bd9Sstevel@tonic-gate */
17007c478bd9Sstevel@tonic-gate static void
usbkbm_unpack_usb_packet(usbkbm_state_t * usbkbmd,process_key_callback_t func,uchar_t * usbpacket)17017c478bd9Sstevel@tonic-gate usbkbm_unpack_usb_packet(usbkbm_state_t *usbkbmd, process_key_callback_t func,
17024db52957Spengcheng chen - Sun Microsystems - Beijing China uchar_t *usbpacket)
17037c478bd9Sstevel@tonic-gate {
17047c478bd9Sstevel@tonic-gate uchar_t mkb;
17057c478bd9Sstevel@tonic-gate uchar_t lastmkb;
17067c478bd9Sstevel@tonic-gate uchar_t *lastusbpacket = usbkbmd->usbkbm_lastusbpacket;
17074db52957Spengcheng chen - Sun Microsystems - Beijing China int packet_size, kbstart, kbend;
17087c478bd9Sstevel@tonic-gate int uindex, lindex, rollover;
17097c478bd9Sstevel@tonic-gate
17104db52957Spengcheng chen - Sun Microsystems - Beijing China packet_size = usbkbmd->usbkbm_report_format.tlen;
17114db52957Spengcheng chen - Sun Microsystems - Beijing China kbstart = usbkbmd->usbkbm_report_format.kpos;
17124db52957Spengcheng chen - Sun Microsystems - Beijing China kbend = kbstart + usbkbmd->usbkbm_report_format.klen;
17134db52957Spengcheng chen - Sun Microsystems - Beijing China mkb = usbpacket[kbstart];
17144db52957Spengcheng chen - Sun Microsystems - Beijing China lastmkb = lastusbpacket[kbstart];
17157c478bd9Sstevel@tonic-gate
17167c478bd9Sstevel@tonic-gate for (uindex = 0; uindex < packet_size; uindex++) {
17177c478bd9Sstevel@tonic-gate
17187c478bd9Sstevel@tonic-gate USB_DPRINTF_L3(PRINT_MASK_PACKET, usbkbm_log_handle,
17197c478bd9Sstevel@tonic-gate " %x ", usbpacket[uindex]);
17207c478bd9Sstevel@tonic-gate }
17217c478bd9Sstevel@tonic-gate
17227c478bd9Sstevel@tonic-gate USB_DPRINTF_L3(PRINT_MASK_PACKET, usbkbm_log_handle,
17237c478bd9Sstevel@tonic-gate " is the usbkeypacket");
17247c478bd9Sstevel@tonic-gate
17257c478bd9Sstevel@tonic-gate /* check to see if modifier keys are different */
17267c478bd9Sstevel@tonic-gate if (mkb != lastmkb) {
17277c478bd9Sstevel@tonic-gate
17287c478bd9Sstevel@tonic-gate if ((mkb & USB_LSHIFTBIT) != (lastmkb & USB_LSHIFTBIT)) {
17297c478bd9Sstevel@tonic-gate (*func)(usbkbmd, USB_LSHIFTKEY, (mkb & USB_LSHIFTBIT) ?
17307c478bd9Sstevel@tonic-gate KEY_PRESSED : KEY_RELEASED);
17317c478bd9Sstevel@tonic-gate USB_DPRINTF_L3(PRINT_MASK_ALL, usbkbm_log_handle,
17327c478bd9Sstevel@tonic-gate "unpack: sending USB_LSHIFTKEY");
17337c478bd9Sstevel@tonic-gate }
17347c478bd9Sstevel@tonic-gate
17357c478bd9Sstevel@tonic-gate if ((mkb & USB_LCTLBIT) != (lastmkb & USB_LCTLBIT)) {
17367c478bd9Sstevel@tonic-gate (*func)(usbkbmd, USB_LCTLCKEY, mkb & USB_LCTLBIT ?
17377c478bd9Sstevel@tonic-gate KEY_PRESSED : KEY_RELEASED);
17387c478bd9Sstevel@tonic-gate }
17397c478bd9Sstevel@tonic-gate
17407c478bd9Sstevel@tonic-gate if ((mkb & USB_LALTBIT) != (lastmkb & USB_LALTBIT)) {
17417c478bd9Sstevel@tonic-gate (*func)(usbkbmd, USB_LALTKEY, mkb & USB_LALTBIT ?
17427c478bd9Sstevel@tonic-gate KEY_PRESSED : KEY_RELEASED);
17437c478bd9Sstevel@tonic-gate }
17447c478bd9Sstevel@tonic-gate
17457c478bd9Sstevel@tonic-gate if ((mkb & USB_LMETABIT) != (lastmkb & USB_LMETABIT)) {
17467c478bd9Sstevel@tonic-gate (*func)(usbkbmd, USB_LMETAKEY, mkb & USB_LMETABIT ?
17477c478bd9Sstevel@tonic-gate KEY_PRESSED : KEY_RELEASED);
17487c478bd9Sstevel@tonic-gate }
17497c478bd9Sstevel@tonic-gate
17507c478bd9Sstevel@tonic-gate if ((mkb & USB_RMETABIT) != (lastmkb & USB_RMETABIT)) {
17517c478bd9Sstevel@tonic-gate (*func)(usbkbmd, USB_RMETAKEY, mkb & USB_RMETABIT ?
17527c478bd9Sstevel@tonic-gate KEY_PRESSED : KEY_RELEASED);
17537c478bd9Sstevel@tonic-gate }
17547c478bd9Sstevel@tonic-gate
17557c478bd9Sstevel@tonic-gate if ((mkb & USB_RALTBIT) != (lastmkb & USB_RALTBIT)) {
17567c478bd9Sstevel@tonic-gate (*func)(usbkbmd, USB_RALTKEY, mkb & USB_RALTBIT ?
17577c478bd9Sstevel@tonic-gate KEY_PRESSED : KEY_RELEASED);
17587c478bd9Sstevel@tonic-gate }
17597c478bd9Sstevel@tonic-gate
17607c478bd9Sstevel@tonic-gate if ((mkb & USB_RCTLBIT) != (lastmkb & USB_RCTLBIT)) {
17617c478bd9Sstevel@tonic-gate (*func)(usbkbmd, USB_RCTLCKEY, mkb & USB_RCTLBIT ?
17627c478bd9Sstevel@tonic-gate KEY_PRESSED : KEY_RELEASED);
17637c478bd9Sstevel@tonic-gate }
17647c478bd9Sstevel@tonic-gate
17657c478bd9Sstevel@tonic-gate if ((mkb & USB_RSHIFTBIT) != (lastmkb & USB_RSHIFTBIT)) {
17667c478bd9Sstevel@tonic-gate (*func)(usbkbmd, USB_RSHIFTKEY, mkb & USB_RSHIFTBIT ?
17677c478bd9Sstevel@tonic-gate KEY_PRESSED : KEY_RELEASED);
17687c478bd9Sstevel@tonic-gate USB_DPRINTF_L3(PRINT_MASK_ALL, usbkbm_log_handle,
17697c478bd9Sstevel@tonic-gate "unpack: sending USB_RSHIFTKEY");
17707c478bd9Sstevel@tonic-gate }
17717c478bd9Sstevel@tonic-gate }
17727c478bd9Sstevel@tonic-gate
17737c478bd9Sstevel@tonic-gate /* save modifier bits */
17744db52957Spengcheng chen - Sun Microsystems - Beijing China lastusbpacket[kbstart] = usbpacket[kbstart];
17757c478bd9Sstevel@tonic-gate
17767c478bd9Sstevel@tonic-gate /* Check Keyboard rollover error. */
17774db52957Spengcheng chen - Sun Microsystems - Beijing China if (usbpacket[kbstart + 2] == USB_ERRORROLLOVER) {
17787c478bd9Sstevel@tonic-gate rollover = 1;
17794db52957Spengcheng chen - Sun Microsystems - Beijing China for (uindex = kbstart + 3; uindex < kbend;
17807c478bd9Sstevel@tonic-gate uindex++) {
17817c478bd9Sstevel@tonic-gate if (usbpacket[uindex] != USB_ERRORROLLOVER) {
17827c478bd9Sstevel@tonic-gate rollover = 0;
17837c478bd9Sstevel@tonic-gate break;
17847c478bd9Sstevel@tonic-gate }
17857c478bd9Sstevel@tonic-gate }
17867c478bd9Sstevel@tonic-gate if (rollover) {
17877c478bd9Sstevel@tonic-gate USB_DPRINTF_L3(PRINT_MASK_ALL, usbkbm_log_handle,
17887c478bd9Sstevel@tonic-gate "unpack: errorrollover");
17897c478bd9Sstevel@tonic-gate return;
17907c478bd9Sstevel@tonic-gate }
17917c478bd9Sstevel@tonic-gate }
17927c478bd9Sstevel@tonic-gate
17937c478bd9Sstevel@tonic-gate /* check for released keys */
17944db52957Spengcheng chen - Sun Microsystems - Beijing China for (lindex = kbstart + 2; lindex < kbend; lindex++) {
17957c478bd9Sstevel@tonic-gate int released = 1;
17967c478bd9Sstevel@tonic-gate
17977c478bd9Sstevel@tonic-gate if (lastusbpacket[lindex] == 0) {
17987c478bd9Sstevel@tonic-gate continue;
17997c478bd9Sstevel@tonic-gate }
18004db52957Spengcheng chen - Sun Microsystems - Beijing China for (uindex = kbstart + 2; uindex < kbend; uindex++)
18017c478bd9Sstevel@tonic-gate if (usbpacket[uindex] == lastusbpacket[lindex]) {
18027c478bd9Sstevel@tonic-gate released = 0;
18037c478bd9Sstevel@tonic-gate break;
18047c478bd9Sstevel@tonic-gate }
18057c478bd9Sstevel@tonic-gate if (released) {
18067c478bd9Sstevel@tonic-gate (*func)(usbkbmd, lastusbpacket[lindex], KEY_RELEASED);
18077c478bd9Sstevel@tonic-gate }
18087c478bd9Sstevel@tonic-gate }
18097c478bd9Sstevel@tonic-gate
18107c478bd9Sstevel@tonic-gate /* check for new presses */
18114db52957Spengcheng chen - Sun Microsystems - Beijing China for (uindex = kbstart + 2; uindex < kbend; uindex++) {
18127c478bd9Sstevel@tonic-gate int newkey = 1;
18137c478bd9Sstevel@tonic-gate
18147c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_pendingusbpacket[uindex] = usbpacket[uindex];
18157c478bd9Sstevel@tonic-gate
18167c478bd9Sstevel@tonic-gate if (usbpacket[uindex] == 0) {
18177c478bd9Sstevel@tonic-gate continue;
18187c478bd9Sstevel@tonic-gate }
18197c478bd9Sstevel@tonic-gate
18204db52957Spengcheng chen - Sun Microsystems - Beijing China for (lindex = kbstart + 2; lindex < kbend; lindex++) {
18217c478bd9Sstevel@tonic-gate if (usbpacket[uindex] == lastusbpacket[lindex]) {
18227c478bd9Sstevel@tonic-gate newkey = 0;
18237c478bd9Sstevel@tonic-gate break;
18247c478bd9Sstevel@tonic-gate }
18257c478bd9Sstevel@tonic-gate }
18267c478bd9Sstevel@tonic-gate
18277c478bd9Sstevel@tonic-gate if (newkey) {
18287c478bd9Sstevel@tonic-gate /*
18297c478bd9Sstevel@tonic-gate * Modifier keys can be present as part of both the
18307c478bd9Sstevel@tonic-gate * first byte and as separate key bytes. In the sec-
18317c478bd9Sstevel@tonic-gate * ond case ignore it.
18327c478bd9Sstevel@tonic-gate */
18337c478bd9Sstevel@tonic-gate
18347c478bd9Sstevel@tonic-gate if (!usbkbm_is_modkey(usbpacket[uindex])) {
18357c478bd9Sstevel@tonic-gate (*func)(usbkbmd, usbpacket[uindex],
18367c478bd9Sstevel@tonic-gate KEY_PRESSED);
18377c478bd9Sstevel@tonic-gate } else {
18387c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_pendingusbpacket[uindex] = 0;
18397c478bd9Sstevel@tonic-gate
18407c478bd9Sstevel@tonic-gate continue;
18417c478bd9Sstevel@tonic-gate }
18427c478bd9Sstevel@tonic-gate }
18437c478bd9Sstevel@tonic-gate }
18447c478bd9Sstevel@tonic-gate
18457c478bd9Sstevel@tonic-gate /*
18467c478bd9Sstevel@tonic-gate * Copy the processed key events of the current usb keyboard
18477c478bd9Sstevel@tonic-gate * packet, which is saved in the usbkbm_pendingusbpacket field
18487c478bd9Sstevel@tonic-gate * to the usbkbm_lastusbpacket field.
18497c478bd9Sstevel@tonic-gate */
18504db52957Spengcheng chen - Sun Microsystems - Beijing China for (uindex = kbstart + 2; uindex < kbend; uindex++) {
18517c478bd9Sstevel@tonic-gate lastusbpacket[uindex] =
18527c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_pendingusbpacket[uindex];
18537c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_pendingusbpacket[uindex] = 0;
18547c478bd9Sstevel@tonic-gate }
18557c478bd9Sstevel@tonic-gate }
18567c478bd9Sstevel@tonic-gate
18577c478bd9Sstevel@tonic-gate static boolean_t
usbkbm_is_modkey(uchar_t key)18587c478bd9Sstevel@tonic-gate usbkbm_is_modkey(uchar_t key)
18597c478bd9Sstevel@tonic-gate {
18607c478bd9Sstevel@tonic-gate
18617c478bd9Sstevel@tonic-gate switch (key) {
18627c478bd9Sstevel@tonic-gate
18637c478bd9Sstevel@tonic-gate case USB_LSHIFTKEY:
18647c478bd9Sstevel@tonic-gate case USB_LCTLCKEY:
18657c478bd9Sstevel@tonic-gate case USB_LALTKEY:
18667c478bd9Sstevel@tonic-gate case USB_LMETAKEY:
18677c478bd9Sstevel@tonic-gate case USB_RCTLCKEY:
18687c478bd9Sstevel@tonic-gate case USB_RSHIFTKEY:
18697c478bd9Sstevel@tonic-gate case USB_RMETAKEY:
18707c478bd9Sstevel@tonic-gate case USB_RALTKEY:
18717c478bd9Sstevel@tonic-gate
18727c478bd9Sstevel@tonic-gate return (B_TRUE);
18737c478bd9Sstevel@tonic-gate
18747c478bd9Sstevel@tonic-gate default:
18757c478bd9Sstevel@tonic-gate
18767c478bd9Sstevel@tonic-gate break;
18777c478bd9Sstevel@tonic-gate }
18787c478bd9Sstevel@tonic-gate
18797c478bd9Sstevel@tonic-gate return (B_FALSE);
18807c478bd9Sstevel@tonic-gate }
18817c478bd9Sstevel@tonic-gate
18827c478bd9Sstevel@tonic-gate /*
18837c478bd9Sstevel@tonic-gate * usbkbm_reioctl :
18847c478bd9Sstevel@tonic-gate * This function is set up as call-back function should an ioctl fail.
18857c478bd9Sstevel@tonic-gate * It retries the ioctl
18867c478bd9Sstevel@tonic-gate */
18877c478bd9Sstevel@tonic-gate static void
usbkbm_reioctl(void * arg)18887c478bd9Sstevel@tonic-gate usbkbm_reioctl(void *arg)
18897c478bd9Sstevel@tonic-gate {
18907c478bd9Sstevel@tonic-gate usbkbm_state_t *usbkbmd;
18917c478bd9Sstevel@tonic-gate mblk_t *mp;
18927c478bd9Sstevel@tonic-gate
18937c478bd9Sstevel@tonic-gate usbkbmd = (usbkbm_state_t *)arg;
18947c478bd9Sstevel@tonic-gate
18957c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_streams_bufcallid = 0;
18967c478bd9Sstevel@tonic-gate
18977c478bd9Sstevel@tonic-gate if ((mp = usbkbmd->usbkbm_streams_iocpending) != NULL) {
18987c478bd9Sstevel@tonic-gate
18997c478bd9Sstevel@tonic-gate /* not pending any more */
19007c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_streams_iocpending = NULL;
19017c478bd9Sstevel@tonic-gate
19027c478bd9Sstevel@tonic-gate (void) usbkbm_ioctl(usbkbmd->usbkbm_writeq, mp);
19037c478bd9Sstevel@tonic-gate }
19047c478bd9Sstevel@tonic-gate }
19057c478bd9Sstevel@tonic-gate
19066d9a41ffSqz150045 /*
19076d9a41ffSqz150045 * usbkbm_get_vid_pid
19086d9a41ffSqz150045 * Issue a M_CTL to hid to get the device info
19096d9a41ffSqz150045 */
19106d9a41ffSqz150045 static int
usbkbm_get_vid_pid(usbkbm_state_t * usbkbmd)19116d9a41ffSqz150045 usbkbm_get_vid_pid(usbkbm_state_t *usbkbmd)
19126d9a41ffSqz150045 {
19136d9a41ffSqz150045 struct iocblk mctlmsg;
19146d9a41ffSqz150045 mblk_t *mctl_ptr;
19156d9a41ffSqz150045 queue_t *q = usbkbmd->usbkbm_readq;
19166d9a41ffSqz150045
19176d9a41ffSqz150045 mctlmsg.ioc_cmd = HID_GET_VID_PID;
19186d9a41ffSqz150045 mctlmsg.ioc_count = 0;
19196d9a41ffSqz150045
19206d9a41ffSqz150045 mctl_ptr = usba_mk_mctl(mctlmsg, NULL, 0);
19216d9a41ffSqz150045 if (mctl_ptr == NULL) {
19226d9a41ffSqz150045 (void) kbtrans_streams_fini(usbkbmd->usbkbm_kbtrans);
19236d9a41ffSqz150045 qprocsoff(q);
19246d9a41ffSqz150045 kmem_free(usbkbmd, sizeof (usbkbm_state_t));
19256d9a41ffSqz150045
19266d9a41ffSqz150045 return (ENOMEM);
19276d9a41ffSqz150045 }
19286d9a41ffSqz150045
19296d9a41ffSqz150045 putnext(usbkbmd->usbkbm_writeq, mctl_ptr);
19306d9a41ffSqz150045 usbkbmd->usbkbm_flags |= USBKBM_QWAIT;
19316d9a41ffSqz150045 while (usbkbmd->usbkbm_flags & USBKBM_QWAIT) {
19326d9a41ffSqz150045 if (qwait_sig(q) == 0) {
19336d9a41ffSqz150045 usbkbmd->usbkbm_flags = 0;
19346d9a41ffSqz150045 (void) kbtrans_streams_fini(usbkbmd->usbkbm_kbtrans);
19356d9a41ffSqz150045 qprocsoff(q);
19366d9a41ffSqz150045 kmem_free(usbkbmd, sizeof (usbkbm_state_t));
19376d9a41ffSqz150045
19386d9a41ffSqz150045 return (EINTR);
19396d9a41ffSqz150045 }
19406d9a41ffSqz150045 }
19416d9a41ffSqz150045
19426d9a41ffSqz150045 return (0);
19436d9a41ffSqz150045 }
1944827f5d6bSStrony Zhang - Solaris China Team
1945827f5d6bSStrony Zhang - Solaris China Team /*
19464db52957Spengcheng chen - Sun Microsystems - Beijing China * usbkbm_get_input_format() :
19474db52957Spengcheng chen - Sun Microsystems - Beijing China * Get the input report format of keyboard
1948827f5d6bSStrony Zhang - Solaris China Team */
1949827f5d6bSStrony Zhang - Solaris China Team static int
usbkbm_get_input_format(usbkbm_state_t * usbkbmd)19504db52957Spengcheng chen - Sun Microsystems - Beijing China usbkbm_get_input_format(usbkbm_state_t *usbkbmd)
1951827f5d6bSStrony Zhang - Solaris China Team {
1952827f5d6bSStrony Zhang - Solaris China Team
19534db52957Spengcheng chen - Sun Microsystems - Beijing China hidparser_rpt_t *kb_rpt;
19544db52957Spengcheng chen - Sun Microsystems - Beijing China uint_t i, kbd_page = 0, kpos = 0, klen = 0, limit = 0;
19554db52957Spengcheng chen - Sun Microsystems - Beijing China uint32_t rptcnt, rptsz;
19564db52957Spengcheng chen - Sun Microsystems - Beijing China usbkbm_report_format_t *kbd_fmt = &usbkbmd->usbkbm_report_format;
19574db52957Spengcheng chen - Sun Microsystems - Beijing China int rptid, rval;
1958827f5d6bSStrony Zhang - Solaris China Team
19594db52957Spengcheng chen - Sun Microsystems - Beijing China /* Setup default input report format */
19604db52957Spengcheng chen - Sun Microsystems - Beijing China kbd_fmt->keyid = HID_REPORT_ID_UNDEFINED;
19614db52957Spengcheng chen - Sun Microsystems - Beijing China kbd_fmt->tlen = USB_KBD_BOOT_PROTOCOL_PACKET_SIZE;
19624db52957Spengcheng chen - Sun Microsystems - Beijing China kbd_fmt->klen = kbd_fmt->tlen;
19634db52957Spengcheng chen - Sun Microsystems - Beijing China kbd_fmt->kpos = 0;
1964827f5d6bSStrony Zhang - Solaris China Team
19654db52957Spengcheng chen - Sun Microsystems - Beijing China if (usbkbmd->usbkbm_report_descr == NULL) {
19664db52957Spengcheng chen - Sun Microsystems - Beijing China return (USB_FAILURE);
1967827f5d6bSStrony Zhang - Solaris China Team }
1968827f5d6bSStrony Zhang - Solaris China Team
19694db52957Spengcheng chen - Sun Microsystems - Beijing China /* Get keyboard layout */
19704db52957Spengcheng chen - Sun Microsystems - Beijing China if (hidparser_get_country_code(usbkbmd->usbkbm_report_descr,
19714db52957Spengcheng chen - Sun Microsystems - Beijing China (uint16_t *)&usbkbmd->usbkbm_layout) == HIDPARSER_FAILURE) {
1972827f5d6bSStrony Zhang - Solaris China Team
19734db52957Spengcheng chen - Sun Microsystems - Beijing China USB_DPRINTF_L3(PRINT_MASK_OPEN,
19744db52957Spengcheng chen - Sun Microsystems - Beijing China usbkbm_log_handle, "get_country_code failed"
19754db52957Spengcheng chen - Sun Microsystems - Beijing China "setting default layout(0)");
19764db52957Spengcheng chen - Sun Microsystems - Beijing China
19774db52957Spengcheng chen - Sun Microsystems - Beijing China usbkbmd->usbkbm_layout = usbkbm_layout;
19784db52957Spengcheng chen - Sun Microsystems - Beijing China }
19794db52957Spengcheng chen - Sun Microsystems - Beijing China
19804db52957Spengcheng chen - Sun Microsystems - Beijing China /* Get the id of the report which contains keyboard data */
19814db52957Spengcheng chen - Sun Microsystems - Beijing China if (hidparser_get_usage_attribute(
19824db52957Spengcheng chen - Sun Microsystems - Beijing China usbkbmd->usbkbm_report_descr,
19834db52957Spengcheng chen - Sun Microsystems - Beijing China 0, /* Doesn't matter */
19844db52957Spengcheng chen - Sun Microsystems - Beijing China HIDPARSER_ITEM_INPUT,
19854db52957Spengcheng chen - Sun Microsystems - Beijing China HID_KEYBOARD_KEYPAD_KEYS,
19864db52957Spengcheng chen - Sun Microsystems - Beijing China 0,
19874db52957Spengcheng chen - Sun Microsystems - Beijing China HIDPARSER_ITEM_REPORT_ID,
19884db52957Spengcheng chen - Sun Microsystems - Beijing China &rptid) == HIDPARSER_NOT_FOUND) {
19894db52957Spengcheng chen - Sun Microsystems - Beijing China
19904db52957Spengcheng chen - Sun Microsystems - Beijing China return (USB_SUCCESS);
19914db52957Spengcheng chen - Sun Microsystems - Beijing China }
19924db52957Spengcheng chen - Sun Microsystems - Beijing China
19934db52957Spengcheng chen - Sun Microsystems - Beijing China /* Allocate hidparser report structure */
19944db52957Spengcheng chen - Sun Microsystems - Beijing China kb_rpt = kmem_zalloc(sizeof (hidparser_rpt_t), KM_SLEEP);
19954db52957Spengcheng chen - Sun Microsystems - Beijing China
19964db52957Spengcheng chen - Sun Microsystems - Beijing China /*
19974db52957Spengcheng chen - Sun Microsystems - Beijing China * Check what is the total length of the keyboard packet
19984db52957Spengcheng chen - Sun Microsystems - Beijing China * and get the usages and their lengths in order
19994db52957Spengcheng chen - Sun Microsystems - Beijing China */
20004db52957Spengcheng chen - Sun Microsystems - Beijing China rval = hidparser_get_usage_list_in_order(
20014db52957Spengcheng chen - Sun Microsystems - Beijing China usbkbmd->usbkbm_report_descr,
20024db52957Spengcheng chen - Sun Microsystems - Beijing China rptid,
20034db52957Spengcheng chen - Sun Microsystems - Beijing China HIDPARSER_ITEM_INPUT,
20044db52957Spengcheng chen - Sun Microsystems - Beijing China kb_rpt);
20054db52957Spengcheng chen - Sun Microsystems - Beijing China if (rval != HIDPARSER_SUCCESS) {
20064db52957Spengcheng chen - Sun Microsystems - Beijing China
20074db52957Spengcheng chen - Sun Microsystems - Beijing China USB_DPRINTF_L3(PRINT_MASK_OPEN, usbkbm_log_handle,
20084db52957Spengcheng chen - Sun Microsystems - Beijing China "get_usage_list_in_order failed");
20094db52957Spengcheng chen - Sun Microsystems - Beijing China kmem_free(kb_rpt, sizeof (hidparser_rpt_t));
20104db52957Spengcheng chen - Sun Microsystems - Beijing China return (USB_FAILURE);
20114db52957Spengcheng chen - Sun Microsystems - Beijing China }
20124db52957Spengcheng chen - Sun Microsystems - Beijing China
20134db52957Spengcheng chen - Sun Microsystems - Beijing China for (i = 0; i < kb_rpt->no_of_usages; i++) {
20144db52957Spengcheng chen - Sun Microsystems - Beijing China rptcnt = kb_rpt->usage_descr[i].rptcnt;
20154db52957Spengcheng chen - Sun Microsystems - Beijing China rptsz = kb_rpt->usage_descr[i].rptsz;
20164db52957Spengcheng chen - Sun Microsystems - Beijing China
20174db52957Spengcheng chen - Sun Microsystems - Beijing China switch (kb_rpt->usage_descr[i].usage_page) {
20184db52957Spengcheng chen - Sun Microsystems - Beijing China case HID_KEYBOARD_KEYPAD_KEYS:
20194db52957Spengcheng chen - Sun Microsystems - Beijing China if (!kbd_page) {
20204db52957Spengcheng chen - Sun Microsystems - Beijing China kpos = limit;
20214db52957Spengcheng chen - Sun Microsystems - Beijing China kbd_page = 1;
20224db52957Spengcheng chen - Sun Microsystems - Beijing China }
20234db52957Spengcheng chen - Sun Microsystems - Beijing China klen += rptcnt * rptsz;
20244db52957Spengcheng chen - Sun Microsystems - Beijing China /*FALLTHRU*/
20254db52957Spengcheng chen - Sun Microsystems - Beijing China default:
20264db52957Spengcheng chen - Sun Microsystems - Beijing China limit += rptcnt * rptsz;
20274db52957Spengcheng chen - Sun Microsystems - Beijing China break;
2028827f5d6bSStrony Zhang - Solaris China Team }
2029827f5d6bSStrony Zhang - Solaris China Team }
2030827f5d6bSStrony Zhang - Solaris China Team
20314db52957Spengcheng chen - Sun Microsystems - Beijing China kmem_free(kb_rpt, sizeof (hidparser_rpt_t));
20324db52957Spengcheng chen - Sun Microsystems - Beijing China
20334db52957Spengcheng chen - Sun Microsystems - Beijing China /* Invalid input report format */
20344db52957Spengcheng chen - Sun Microsystems - Beijing China if (!kbd_page || limit > USBKBM_MAXPKTSIZE * 8 ||
20354db52957Spengcheng chen - Sun Microsystems - Beijing China kpos + klen > limit || (kpos % 8 != 0)) {
20364db52957Spengcheng chen - Sun Microsystems - Beijing China
20374db52957Spengcheng chen - Sun Microsystems - Beijing China USB_DPRINTF_L3(PRINT_MASK_OPEN, usbkbm_log_handle,
20384db52957Spengcheng chen - Sun Microsystems - Beijing China "Invalid input report format: kbd_page (%d), limit (%d), "
20394db52957Spengcheng chen - Sun Microsystems - Beijing China "kpos (%d), klen (%d)", kbd_page, limit, kpos, klen);
20404db52957Spengcheng chen - Sun Microsystems - Beijing China return (USB_FAILURE);
20414db52957Spengcheng chen - Sun Microsystems - Beijing China }
20424db52957Spengcheng chen - Sun Microsystems - Beijing China
20434db52957Spengcheng chen - Sun Microsystems - Beijing China /* Set report format */
20444db52957Spengcheng chen - Sun Microsystems - Beijing China kbd_fmt->keyid = (uint8_t)rptid;
20454db52957Spengcheng chen - Sun Microsystems - Beijing China kbd_fmt->tlen = limit / 8 + 1;
20464db52957Spengcheng chen - Sun Microsystems - Beijing China kbd_fmt->klen = klen / 8;
20474db52957Spengcheng chen - Sun Microsystems - Beijing China kbd_fmt->kpos = kpos / 8;
20484db52957Spengcheng chen - Sun Microsystems - Beijing China
20494db52957Spengcheng chen - Sun Microsystems - Beijing China return (USB_SUCCESS);
2050827f5d6bSStrony Zhang - Solaris China Team }
2051