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 57c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 67c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 77c478bd9Sstevel@tonic-gate * with the License. 87c478bd9Sstevel@tonic-gate * 97c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 107c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 117c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 127c478bd9Sstevel@tonic-gate * and limitations under the License. 137c478bd9Sstevel@tonic-gate * 147c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 157c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 167c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 177c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 187c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 197c478bd9Sstevel@tonic-gate * 207c478bd9Sstevel@tonic-gate * CDDL HEADER END 217c478bd9Sstevel@tonic-gate */ 227c478bd9Sstevel@tonic-gate /* 237c478bd9Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 247c478bd9Sstevel@tonic-gate * Use is subject to license terms. 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate 277c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 287c478bd9Sstevel@tonic-gate 297c478bd9Sstevel@tonic-gate /* 307c478bd9Sstevel@tonic-gate * USB keyboard input streams module - processes USB keypacket 317c478bd9Sstevel@tonic-gate * received from HID driver below to either ASCII or event 327c478bd9Sstevel@tonic-gate * format for windowing system. 337c478bd9Sstevel@tonic-gate */ 347c478bd9Sstevel@tonic-gate #include <sys/usb/usba/usbai_version.h> 357c478bd9Sstevel@tonic-gate 367c478bd9Sstevel@tonic-gate #define KEYMAP_SIZE_VARIABLE 377c478bd9Sstevel@tonic-gate #include <sys/usb/usba.h> 387c478bd9Sstevel@tonic-gate #include <sys/usb/clients/hid/hid.h> 397c478bd9Sstevel@tonic-gate #include <sys/usb/clients/hid/hid_polled.h> 407c478bd9Sstevel@tonic-gate #include <sys/usb/clients/hidparser/hidparser.h> 417c478bd9Sstevel@tonic-gate #include <sys/stropts.h> 427c478bd9Sstevel@tonic-gate #include <sys/stream.h> 437c478bd9Sstevel@tonic-gate #include <sys/strsun.h> 447c478bd9Sstevel@tonic-gate #include <sys/kbio.h> 457c478bd9Sstevel@tonic-gate #include <sys/vuid_event.h> 467c478bd9Sstevel@tonic-gate #include <sys/kbd.h> 477c478bd9Sstevel@tonic-gate #include <sys/consdev.h> 487c478bd9Sstevel@tonic-gate #include <sys/kbtrans.h> 497c478bd9Sstevel@tonic-gate #include <sys/usb/clients/usbkbm/usbkbm.h> 507c478bd9Sstevel@tonic-gate #include <sys/beep.h> 517c478bd9Sstevel@tonic-gate #include <sys/policy.h> 527c478bd9Sstevel@tonic-gate 537c478bd9Sstevel@tonic-gate /* debugging information */ 544610e4a0Sfrits uint_t usbkbm_errmask = (uint_t)PRINT_MASK_ALL; 554610e4a0Sfrits uint_t usbkbm_errlevel = USB_LOG_L2; 567c478bd9Sstevel@tonic-gate static usb_log_handle_t usbkbm_log_handle; 577c478bd9Sstevel@tonic-gate 587c478bd9Sstevel@tonic-gate typedef void (*process_key_callback_t)(usbkbm_state_t *, int, enum keystate); 597c478bd9Sstevel@tonic-gate 607c478bd9Sstevel@tonic-gate /* 617c478bd9Sstevel@tonic-gate * Internal Function Prototypes 627c478bd9Sstevel@tonic-gate */ 637c478bd9Sstevel@tonic-gate static void usbkbm_streams_setled(struct kbtrans_hardware *, int); 647c478bd9Sstevel@tonic-gate static void usbkbm_polled_setled(struct kbtrans_hardware *, int); 657c478bd9Sstevel@tonic-gate static boolean_t usbkbm_polled_keycheck(struct kbtrans_hardware *, 667c478bd9Sstevel@tonic-gate int *, enum keystate *); 677c478bd9Sstevel@tonic-gate static void usbkbm_poll_callback(usbkbm_state_t *, int, enum keystate); 687c478bd9Sstevel@tonic-gate static void usbkbm_streams_callback(usbkbm_state_t *, int, enum keystate); 697c478bd9Sstevel@tonic-gate static void usbkbm_unpack_usb_packet(usbkbm_state_t *, process_key_callback_t, 707c478bd9Sstevel@tonic-gate uchar_t *, int); 717c478bd9Sstevel@tonic-gate static boolean_t usbkbm_is_modkey(uchar_t); 727c478bd9Sstevel@tonic-gate static void usbkbm_reioctl(void *); 737c478bd9Sstevel@tonic-gate static int usbkbm_polled_getchar(struct cons_polledio_arg *); 747c478bd9Sstevel@tonic-gate static boolean_t usbkbm_polled_ischar(struct cons_polledio_arg *); 757c478bd9Sstevel@tonic-gate static void usbkbm_polled_enter(struct cons_polledio_arg *); 767c478bd9Sstevel@tonic-gate static void usbkbm_polled_exit(struct cons_polledio_arg *); 777c478bd9Sstevel@tonic-gate static void usbkbm_mctl_receive(queue_t *, mblk_t *); 787c478bd9Sstevel@tonic-gate static enum kbtrans_message_response usbkbm_ioctl(queue_t *, mblk_t *); 797c478bd9Sstevel@tonic-gate static int usbkbm_kioccmd(usbkbm_state_t *, mblk_t *, char, size_t *); 807c478bd9Sstevel@tonic-gate static void usbkbm_usb2pc_xlate(usbkbm_state_t *, int, enum keystate); 817c478bd9Sstevel@tonic-gate static void usbkbm_wrap_kbtrans(usbkbm_state_t *, int, enum keystate); 827c478bd9Sstevel@tonic-gate static int usbkbm_set_protocol(usbkbm_state_t *, uint16_t); 83*6d9a41ffSqz150045 static int usbkbm_get_vid_pid(usbkbm_state_t *); 847c478bd9Sstevel@tonic-gate 857c478bd9Sstevel@tonic-gate /* stream qinit functions defined here */ 867c478bd9Sstevel@tonic-gate static int usbkbm_open(queue_t *, dev_t *, int, int, cred_t *); 877c478bd9Sstevel@tonic-gate static int usbkbm_close(queue_t *, int, cred_t *); 887c478bd9Sstevel@tonic-gate static void usbkbm_wput(queue_t *, mblk_t *); 897c478bd9Sstevel@tonic-gate static void usbkbm_rput(queue_t *, mblk_t *); 907c478bd9Sstevel@tonic-gate static ushort_t usbkbm_get_state(usbkbm_state_t *); 917c478bd9Sstevel@tonic-gate static void usbkbm_get_scancode(usbkbm_state_t *, int *, enum keystate *); 927c478bd9Sstevel@tonic-gate 937c478bd9Sstevel@tonic-gate static struct keyboard *usbkbm_keyindex; 947c478bd9Sstevel@tonic-gate 957c478bd9Sstevel@tonic-gate /* External Functions */ 967c478bd9Sstevel@tonic-gate extern void space_free(char *); 977c478bd9Sstevel@tonic-gate extern uintptr_t space_fetch(char *); 987c478bd9Sstevel@tonic-gate extern int space_store(char *, uintptr_t); 997c478bd9Sstevel@tonic-gate extern struct keyboard *kbtrans_usbkb_maptab_init(void); 1007c478bd9Sstevel@tonic-gate extern void kbtrans_usbkb_maptab_fini(struct keyboard **); 1017c478bd9Sstevel@tonic-gate extern keymap_entry_t kbtrans_keycode_usb2pc(int); 1027c478bd9Sstevel@tonic-gate 1037c478bd9Sstevel@tonic-gate /* 1047c478bd9Sstevel@tonic-gate * Structure to setup callbacks 1057c478bd9Sstevel@tonic-gate */ 1067c478bd9Sstevel@tonic-gate struct kbtrans_callbacks kbd_usb_callbacks = { 1077c478bd9Sstevel@tonic-gate usbkbm_streams_setled, 1087c478bd9Sstevel@tonic-gate usbkbm_polled_setled, 1097c478bd9Sstevel@tonic-gate usbkbm_polled_keycheck, 1107c478bd9Sstevel@tonic-gate }; 1117c478bd9Sstevel@tonic-gate 1127c478bd9Sstevel@tonic-gate /* 1137c478bd9Sstevel@tonic-gate * Global Variables 1147c478bd9Sstevel@tonic-gate */ 1157c478bd9Sstevel@tonic-gate 1167c478bd9Sstevel@tonic-gate /* This variable saves the LED state across hotplugging. */ 1177c478bd9Sstevel@tonic-gate static uchar_t usbkbm_led_state = 0; 1187c478bd9Sstevel@tonic-gate 1197c478bd9Sstevel@tonic-gate /* This variable saves the layout state */ 120*6d9a41ffSqz150045 static uint16_t usbkbm_layout = 0; 1217c478bd9Sstevel@tonic-gate 1227c478bd9Sstevel@tonic-gate /* 1237c478bd9Sstevel@tonic-gate * Function pointer array for mapping of scancodes. 1247c478bd9Sstevel@tonic-gate */ 1257c478bd9Sstevel@tonic-gate void (*usbkbm_xlate[2])(usbkbm_state_t *, int, enum keystate) = { 1267c478bd9Sstevel@tonic-gate usbkbm_wrap_kbtrans, 1277c478bd9Sstevel@tonic-gate usbkbm_usb2pc_xlate 1287c478bd9Sstevel@tonic-gate }; 1297c478bd9Sstevel@tonic-gate 1307c478bd9Sstevel@tonic-gate static struct streamtab usbkbm_info; 1317c478bd9Sstevel@tonic-gate static struct fmodsw fsw = { 1327c478bd9Sstevel@tonic-gate "usbkbm", 1337c478bd9Sstevel@tonic-gate &usbkbm_info, 1347c478bd9Sstevel@tonic-gate D_MP | D_MTPERMOD 1357c478bd9Sstevel@tonic-gate }; 1367c478bd9Sstevel@tonic-gate 1377c478bd9Sstevel@tonic-gate 1387c478bd9Sstevel@tonic-gate /* 1397c478bd9Sstevel@tonic-gate * Module linkage information for the kernel. 1407c478bd9Sstevel@tonic-gate */ 1417c478bd9Sstevel@tonic-gate static struct modlstrmod modlstrmod = { 1427c478bd9Sstevel@tonic-gate &mod_strmodops, 1437c478bd9Sstevel@tonic-gate "USB keyboard streams %I%", 1447c478bd9Sstevel@tonic-gate &fsw 1457c478bd9Sstevel@tonic-gate }; 1467c478bd9Sstevel@tonic-gate 1477c478bd9Sstevel@tonic-gate static struct modlinkage modlinkage = { 1487c478bd9Sstevel@tonic-gate MODREV_1, 1497c478bd9Sstevel@tonic-gate (void *)&modlstrmod, 1507c478bd9Sstevel@tonic-gate NULL 1517c478bd9Sstevel@tonic-gate }; 1527c478bd9Sstevel@tonic-gate 1537c478bd9Sstevel@tonic-gate 1547c478bd9Sstevel@tonic-gate int 1557c478bd9Sstevel@tonic-gate _init(void) 1567c478bd9Sstevel@tonic-gate { 1577c478bd9Sstevel@tonic-gate int rval = mod_install(&modlinkage); 1587c478bd9Sstevel@tonic-gate usbkbm_save_state_t *sp; 1597c478bd9Sstevel@tonic-gate 1607c478bd9Sstevel@tonic-gate if (rval != 0) { 1617c478bd9Sstevel@tonic-gate 1627c478bd9Sstevel@tonic-gate return (rval); 1637c478bd9Sstevel@tonic-gate } 1647c478bd9Sstevel@tonic-gate 1657c478bd9Sstevel@tonic-gate usbkbm_keyindex = kbtrans_usbkb_maptab_init(); 1667c478bd9Sstevel@tonic-gate 1677c478bd9Sstevel@tonic-gate usbkbm_log_handle = usb_alloc_log_hdl(NULL, "usbkbm", 1687c478bd9Sstevel@tonic-gate &usbkbm_errlevel, &usbkbm_errmask, NULL, 0); 1697c478bd9Sstevel@tonic-gate 1707c478bd9Sstevel@tonic-gate sp = (usbkbm_save_state_t *)space_fetch("SUNW,usbkbm_state"); 1717c478bd9Sstevel@tonic-gate 1727c478bd9Sstevel@tonic-gate if (sp == NULL) { 1737c478bd9Sstevel@tonic-gate 1747c478bd9Sstevel@tonic-gate return (0); 1757c478bd9Sstevel@tonic-gate } 1767c478bd9Sstevel@tonic-gate 1777c478bd9Sstevel@tonic-gate /* Restore LED information */ 1787c478bd9Sstevel@tonic-gate usbkbm_led_state = sp->usbkbm_save_led; 1797c478bd9Sstevel@tonic-gate 1807c478bd9Sstevel@tonic-gate /* Restore the Layout */ 1817c478bd9Sstevel@tonic-gate usbkbm_layout = sp->usbkbm_layout; 1827c478bd9Sstevel@tonic-gate 1837c478bd9Sstevel@tonic-gate /* Restore abort information */ 1847c478bd9Sstevel@tonic-gate usbkbm_keyindex->k_abort1 = 1857c478bd9Sstevel@tonic-gate sp->usbkbm_save_keyindex.k_abort1; 1867c478bd9Sstevel@tonic-gate 1877c478bd9Sstevel@tonic-gate usbkbm_keyindex->k_abort2 = 1887c478bd9Sstevel@tonic-gate sp->usbkbm_save_keyindex.k_abort2; 1897c478bd9Sstevel@tonic-gate 1907c478bd9Sstevel@tonic-gate /* Restore keytables */ 1917c478bd9Sstevel@tonic-gate bcopy(sp->usbkbm_save_keyindex.k_normal, 1927c478bd9Sstevel@tonic-gate usbkbm_keyindex->k_normal, USB_KEYTABLE_SIZE); 1937c478bd9Sstevel@tonic-gate 1947c478bd9Sstevel@tonic-gate bcopy(sp->usbkbm_save_keyindex.k_shifted, 1957c478bd9Sstevel@tonic-gate usbkbm_keyindex->k_shifted, USB_KEYTABLE_SIZE); 1967c478bd9Sstevel@tonic-gate 1977c478bd9Sstevel@tonic-gate bcopy(sp->usbkbm_save_keyindex.k_caps, 1987c478bd9Sstevel@tonic-gate usbkbm_keyindex->k_caps, USB_KEYTABLE_SIZE); 1997c478bd9Sstevel@tonic-gate 2007c478bd9Sstevel@tonic-gate bcopy(sp->usbkbm_save_keyindex.k_altgraph, 2017c478bd9Sstevel@tonic-gate usbkbm_keyindex->k_altgraph, USB_KEYTABLE_SIZE); 2027c478bd9Sstevel@tonic-gate 2037c478bd9Sstevel@tonic-gate bcopy(sp->usbkbm_save_keyindex.k_numlock, 2047c478bd9Sstevel@tonic-gate usbkbm_keyindex->k_numlock, USB_KEYTABLE_SIZE); 2057c478bd9Sstevel@tonic-gate 2067c478bd9Sstevel@tonic-gate bcopy(sp->usbkbm_save_keyindex.k_control, 2077c478bd9Sstevel@tonic-gate usbkbm_keyindex->k_control, USB_KEYTABLE_SIZE); 2087c478bd9Sstevel@tonic-gate 2097c478bd9Sstevel@tonic-gate bcopy(sp->usbkbm_save_keyindex.k_up, 2107c478bd9Sstevel@tonic-gate usbkbm_keyindex->k_up, USB_KEYTABLE_SIZE); 2117c478bd9Sstevel@tonic-gate 2127c478bd9Sstevel@tonic-gate kmem_free(sp->usbkbm_save_keyindex.k_normal, 2137c478bd9Sstevel@tonic-gate USB_KEYTABLE_SIZE); 2147c478bd9Sstevel@tonic-gate kmem_free(sp->usbkbm_save_keyindex.k_shifted, 2157c478bd9Sstevel@tonic-gate USB_KEYTABLE_SIZE); 2167c478bd9Sstevel@tonic-gate kmem_free(sp->usbkbm_save_keyindex.k_caps, 2177c478bd9Sstevel@tonic-gate USB_KEYTABLE_SIZE); 2187c478bd9Sstevel@tonic-gate kmem_free(sp->usbkbm_save_keyindex.k_altgraph, 2197c478bd9Sstevel@tonic-gate USB_KEYTABLE_SIZE); 2207c478bd9Sstevel@tonic-gate kmem_free(sp->usbkbm_save_keyindex.k_numlock, 2217c478bd9Sstevel@tonic-gate USB_KEYTABLE_SIZE); 2227c478bd9Sstevel@tonic-gate kmem_free(sp->usbkbm_save_keyindex.k_control, 2237c478bd9Sstevel@tonic-gate USB_KEYTABLE_SIZE); 2247c478bd9Sstevel@tonic-gate kmem_free(sp->usbkbm_save_keyindex.k_up, 2257c478bd9Sstevel@tonic-gate USB_KEYTABLE_SIZE); 2267c478bd9Sstevel@tonic-gate 2277c478bd9Sstevel@tonic-gate kmem_free(sp, sizeof (usbkbm_save_state_t)); 2287c478bd9Sstevel@tonic-gate space_free("SUNW,usbkbm_state"); 2297c478bd9Sstevel@tonic-gate 2307c478bd9Sstevel@tonic-gate return (0); 2317c478bd9Sstevel@tonic-gate } 2327c478bd9Sstevel@tonic-gate 2337c478bd9Sstevel@tonic-gate int 2347c478bd9Sstevel@tonic-gate _fini(void) 2357c478bd9Sstevel@tonic-gate { 2367c478bd9Sstevel@tonic-gate usbkbm_save_state_t *sp; 2377c478bd9Sstevel@tonic-gate int sval; 2387c478bd9Sstevel@tonic-gate int rval; 2397c478bd9Sstevel@tonic-gate 2407c478bd9Sstevel@tonic-gate sp = kmem_alloc(sizeof (usbkbm_save_state_t), KM_SLEEP); 2417c478bd9Sstevel@tonic-gate sval = space_store("SUNW,usbkbm_state", (uintptr_t)sp); 2427c478bd9Sstevel@tonic-gate 2437c478bd9Sstevel@tonic-gate /* 2447c478bd9Sstevel@tonic-gate * If it's not possible to store the state, return 2457c478bd9Sstevel@tonic-gate * EBUSY. 2467c478bd9Sstevel@tonic-gate */ 2477c478bd9Sstevel@tonic-gate if (sval != 0) { 2487c478bd9Sstevel@tonic-gate kmem_free(sp, sizeof (usbkbm_save_state_t)); 2497c478bd9Sstevel@tonic-gate 2507c478bd9Sstevel@tonic-gate return (EBUSY); 2517c478bd9Sstevel@tonic-gate } 2527c478bd9Sstevel@tonic-gate 2537c478bd9Sstevel@tonic-gate rval = mod_remove(&modlinkage); 2547c478bd9Sstevel@tonic-gate 2557c478bd9Sstevel@tonic-gate if (rval != 0) { 2567c478bd9Sstevel@tonic-gate kmem_free(sp, sizeof (usbkbm_save_state_t)); 2577c478bd9Sstevel@tonic-gate space_free("SUNW,usbkbm_state"); 2587c478bd9Sstevel@tonic-gate 2597c478bd9Sstevel@tonic-gate return (rval); 2607c478bd9Sstevel@tonic-gate } 2617c478bd9Sstevel@tonic-gate 2627c478bd9Sstevel@tonic-gate usb_free_log_hdl(usbkbm_log_handle); 2637c478bd9Sstevel@tonic-gate 2647c478bd9Sstevel@tonic-gate /* Save the LED state */ 2657c478bd9Sstevel@tonic-gate sp->usbkbm_save_led = usbkbm_led_state; 2667c478bd9Sstevel@tonic-gate 2677c478bd9Sstevel@tonic-gate /* Save the layout */ 2687c478bd9Sstevel@tonic-gate sp->usbkbm_layout = usbkbm_layout; 2697c478bd9Sstevel@tonic-gate 2707c478bd9Sstevel@tonic-gate /* 2717c478bd9Sstevel@tonic-gate * Save entries of the keyboard structure that 2727c478bd9Sstevel@tonic-gate * have changed. 2737c478bd9Sstevel@tonic-gate */ 2747c478bd9Sstevel@tonic-gate sp->usbkbm_save_keyindex.k_abort1 = usbkbm_keyindex->k_abort1; 2757c478bd9Sstevel@tonic-gate sp->usbkbm_save_keyindex.k_abort2 = usbkbm_keyindex->k_abort2; 2767c478bd9Sstevel@tonic-gate 2777c478bd9Sstevel@tonic-gate /* Allocate space for keytables to be stored */ 2787c478bd9Sstevel@tonic-gate sp->usbkbm_save_keyindex.k_normal = 2797c478bd9Sstevel@tonic-gate kmem_alloc(USB_KEYTABLE_SIZE, KM_SLEEP); 2807c478bd9Sstevel@tonic-gate sp->usbkbm_save_keyindex.k_shifted = 2817c478bd9Sstevel@tonic-gate kmem_alloc(USB_KEYTABLE_SIZE, KM_SLEEP); 2827c478bd9Sstevel@tonic-gate sp->usbkbm_save_keyindex.k_caps = 2837c478bd9Sstevel@tonic-gate kmem_alloc(USB_KEYTABLE_SIZE, KM_SLEEP); 2847c478bd9Sstevel@tonic-gate sp->usbkbm_save_keyindex.k_altgraph = 2857c478bd9Sstevel@tonic-gate kmem_alloc(USB_KEYTABLE_SIZE, KM_SLEEP); 2867c478bd9Sstevel@tonic-gate sp->usbkbm_save_keyindex.k_numlock = 2877c478bd9Sstevel@tonic-gate kmem_alloc(USB_KEYTABLE_SIZE, KM_SLEEP); 2887c478bd9Sstevel@tonic-gate sp->usbkbm_save_keyindex.k_control = 2897c478bd9Sstevel@tonic-gate kmem_alloc(USB_KEYTABLE_SIZE, KM_SLEEP); 2907c478bd9Sstevel@tonic-gate sp->usbkbm_save_keyindex.k_up = 2917c478bd9Sstevel@tonic-gate kmem_alloc(USB_KEYTABLE_SIZE, KM_SLEEP); 2927c478bd9Sstevel@tonic-gate 2937c478bd9Sstevel@tonic-gate /* Copy over the keytables */ 2947c478bd9Sstevel@tonic-gate bcopy(usbkbm_keyindex->k_normal, 2957c478bd9Sstevel@tonic-gate sp->usbkbm_save_keyindex.k_normal, USB_KEYTABLE_SIZE); 2967c478bd9Sstevel@tonic-gate 2977c478bd9Sstevel@tonic-gate bcopy(usbkbm_keyindex->k_shifted, 2987c478bd9Sstevel@tonic-gate sp->usbkbm_save_keyindex.k_shifted, USB_KEYTABLE_SIZE); 2997c478bd9Sstevel@tonic-gate 3007c478bd9Sstevel@tonic-gate bcopy(usbkbm_keyindex->k_caps, 3017c478bd9Sstevel@tonic-gate sp->usbkbm_save_keyindex.k_caps, USB_KEYTABLE_SIZE); 3027c478bd9Sstevel@tonic-gate 3037c478bd9Sstevel@tonic-gate bcopy(usbkbm_keyindex->k_altgraph, 3047c478bd9Sstevel@tonic-gate sp->usbkbm_save_keyindex.k_altgraph, USB_KEYTABLE_SIZE); 3057c478bd9Sstevel@tonic-gate 3067c478bd9Sstevel@tonic-gate bcopy(usbkbm_keyindex->k_numlock, 3077c478bd9Sstevel@tonic-gate sp->usbkbm_save_keyindex.k_numlock, USB_KEYTABLE_SIZE); 3087c478bd9Sstevel@tonic-gate 3097c478bd9Sstevel@tonic-gate bcopy(usbkbm_keyindex->k_control, 3107c478bd9Sstevel@tonic-gate sp->usbkbm_save_keyindex.k_control, USB_KEYTABLE_SIZE); 3117c478bd9Sstevel@tonic-gate 3127c478bd9Sstevel@tonic-gate bcopy(usbkbm_keyindex->k_up, 3137c478bd9Sstevel@tonic-gate sp->usbkbm_save_keyindex.k_up, USB_KEYTABLE_SIZE); 3147c478bd9Sstevel@tonic-gate 3157c478bd9Sstevel@tonic-gate kbtrans_usbkb_maptab_fini(&usbkbm_keyindex); 3167c478bd9Sstevel@tonic-gate 3177c478bd9Sstevel@tonic-gate return (0); 3187c478bd9Sstevel@tonic-gate } 3197c478bd9Sstevel@tonic-gate 3207c478bd9Sstevel@tonic-gate int 3217c478bd9Sstevel@tonic-gate _info(struct modinfo *modinfop) 3227c478bd9Sstevel@tonic-gate { 3237c478bd9Sstevel@tonic-gate return (mod_info(&modlinkage, modinfop)); 3247c478bd9Sstevel@tonic-gate } 3257c478bd9Sstevel@tonic-gate 3267c478bd9Sstevel@tonic-gate /* 3277c478bd9Sstevel@tonic-gate * Module qinit functions 3287c478bd9Sstevel@tonic-gate */ 3297c478bd9Sstevel@tonic-gate 3307c478bd9Sstevel@tonic-gate static struct module_info usbkbm_minfo = { 3317c478bd9Sstevel@tonic-gate 0, /* module id number */ 3327c478bd9Sstevel@tonic-gate "usbkbm", /* module name */ 3337c478bd9Sstevel@tonic-gate 0, /* min packet size accepted */ 3347c478bd9Sstevel@tonic-gate INFPSZ, /* max packet size accepted */ 3357c478bd9Sstevel@tonic-gate 2048, /* hi-water mark */ 3367c478bd9Sstevel@tonic-gate 128 /* lo-water mark */ 3377c478bd9Sstevel@tonic-gate }; 3387c478bd9Sstevel@tonic-gate 3397c478bd9Sstevel@tonic-gate /* read side for key data and ioctl replies */ 3407c478bd9Sstevel@tonic-gate static struct qinit usbkbm_rinit = { 3417c478bd9Sstevel@tonic-gate (int (*)())usbkbm_rput, 3427c478bd9Sstevel@tonic-gate (int (*)())NULL, /* service not used */ 3437c478bd9Sstevel@tonic-gate usbkbm_open, 3447c478bd9Sstevel@tonic-gate usbkbm_close, 3457c478bd9Sstevel@tonic-gate (int (*)())NULL, 3467c478bd9Sstevel@tonic-gate &usbkbm_minfo 3477c478bd9Sstevel@tonic-gate }; 3487c478bd9Sstevel@tonic-gate 3497c478bd9Sstevel@tonic-gate /* write side for ioctls */ 3507c478bd9Sstevel@tonic-gate static struct qinit usbkbm_winit = { 3517c478bd9Sstevel@tonic-gate (int (*)())usbkbm_wput, 3527c478bd9Sstevel@tonic-gate (int (*)())NULL, 3537c478bd9Sstevel@tonic-gate usbkbm_open, 3547c478bd9Sstevel@tonic-gate usbkbm_close, 3557c478bd9Sstevel@tonic-gate (int (*)())NULL, 3567c478bd9Sstevel@tonic-gate &usbkbm_minfo 3577c478bd9Sstevel@tonic-gate }; 3587c478bd9Sstevel@tonic-gate 3597c478bd9Sstevel@tonic-gate static struct streamtab usbkbm_info = { 3607c478bd9Sstevel@tonic-gate &usbkbm_rinit, 3617c478bd9Sstevel@tonic-gate &usbkbm_winit, 3627c478bd9Sstevel@tonic-gate NULL, /* for muxes */ 3637c478bd9Sstevel@tonic-gate NULL, /* for muxes */ 3647c478bd9Sstevel@tonic-gate }; 3657c478bd9Sstevel@tonic-gate 3667c478bd9Sstevel@tonic-gate /* 3677c478bd9Sstevel@tonic-gate * usbkbm_open : 3687c478bd9Sstevel@tonic-gate * Open a keyboard 3697c478bd9Sstevel@tonic-gate */ 3707c478bd9Sstevel@tonic-gate /* ARGSUSED */ 3717c478bd9Sstevel@tonic-gate static int 3727c478bd9Sstevel@tonic-gate usbkbm_open(queue_t *q, dev_t *devp, int oflag, int sflag, cred_t *crp) 3737c478bd9Sstevel@tonic-gate { 3747c478bd9Sstevel@tonic-gate usbkbm_state_t *usbkbmd; 3757c478bd9Sstevel@tonic-gate struct iocblk mctlmsg; 3767c478bd9Sstevel@tonic-gate uint32_t packet_size; 3777c478bd9Sstevel@tonic-gate mblk_t *mctl_ptr; 3787c478bd9Sstevel@tonic-gate int error, ret; 3797c478bd9Sstevel@tonic-gate 3807c478bd9Sstevel@tonic-gate packet_size = 0; 3817c478bd9Sstevel@tonic-gate 3827c478bd9Sstevel@tonic-gate if (q->q_ptr) { 3837c478bd9Sstevel@tonic-gate USB_DPRINTF_L3(PRINT_MASK_OPEN, usbkbm_log_handle, 3847c478bd9Sstevel@tonic-gate "usbkbm_open already opened"); 3857c478bd9Sstevel@tonic-gate 3867c478bd9Sstevel@tonic-gate return (0); /* already opened */ 3877c478bd9Sstevel@tonic-gate } 3887c478bd9Sstevel@tonic-gate 3897c478bd9Sstevel@tonic-gate /* 3907c478bd9Sstevel@tonic-gate * Only allow open requests to succeed for privileged users. This 3917c478bd9Sstevel@tonic-gate * necessary to prevent users from pushing the "usbkbm" module again 3927c478bd9Sstevel@tonic-gate * on the stream associated with /dev/kbd. 3937c478bd9Sstevel@tonic-gate */ 3947c478bd9Sstevel@tonic-gate if (secpolicy_console(crp) != 0) 3957c478bd9Sstevel@tonic-gate return (EPERM); 3967c478bd9Sstevel@tonic-gate 3977c478bd9Sstevel@tonic-gate switch (sflag) { 3987c478bd9Sstevel@tonic-gate 3997c478bd9Sstevel@tonic-gate case MODOPEN: 4007c478bd9Sstevel@tonic-gate break; 4017c478bd9Sstevel@tonic-gate 4027c478bd9Sstevel@tonic-gate case CLONEOPEN: 4037c478bd9Sstevel@tonic-gate USB_DPRINTF_L3(PRINT_MASK_OPEN, usbkbm_log_handle, 4047c478bd9Sstevel@tonic-gate "usbkbm_open: Clone open not supported"); 4057c478bd9Sstevel@tonic-gate 4067c478bd9Sstevel@tonic-gate /* FALLTHRU */ 4077c478bd9Sstevel@tonic-gate default: 4087c478bd9Sstevel@tonic-gate 4097c478bd9Sstevel@tonic-gate return (EINVAL); 4107c478bd9Sstevel@tonic-gate } 4117c478bd9Sstevel@tonic-gate 4127c478bd9Sstevel@tonic-gate /* allocate usb keyboard state structure */ 4137c478bd9Sstevel@tonic-gate 4147c478bd9Sstevel@tonic-gate usbkbmd = kmem_zalloc(sizeof (usbkbm_state_t), KM_SLEEP); 4157c478bd9Sstevel@tonic-gate 4167c478bd9Sstevel@tonic-gate USB_DPRINTF_L3(PRINT_MASK_OPEN, usbkbm_log_handle, 4177c478bd9Sstevel@tonic-gate "usbkbm_state= %p", (void *)usbkbmd); 4187c478bd9Sstevel@tonic-gate 4197c478bd9Sstevel@tonic-gate /* 4207c478bd9Sstevel@tonic-gate * Set up private data. 4217c478bd9Sstevel@tonic-gate */ 4227c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_readq = q; 4237c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_writeq = WR(q); 4247c478bd9Sstevel@tonic-gate 4257c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_vkbd_type = KB_USB; 4267c478bd9Sstevel@tonic-gate /* 4277c478bd9Sstevel@tonic-gate * Set up queue pointers, so that the "put" procedure will accept 4287c478bd9Sstevel@tonic-gate * the reply to the "ioctl" message we send down. 4297c478bd9Sstevel@tonic-gate */ 4307c478bd9Sstevel@tonic-gate q->q_ptr = (caddr_t)usbkbmd; 4317c478bd9Sstevel@tonic-gate WR(q)->q_ptr = (caddr_t)usbkbmd; 4327c478bd9Sstevel@tonic-gate 4337c478bd9Sstevel@tonic-gate error = kbtrans_streams_init(q, sflag, crp, 4347c478bd9Sstevel@tonic-gate (struct kbtrans_hardware *)usbkbmd, &kbd_usb_callbacks, 4357c478bd9Sstevel@tonic-gate &usbkbmd->usbkbm_kbtrans, usbkbm_led_state, 0); 4367c478bd9Sstevel@tonic-gate 4377c478bd9Sstevel@tonic-gate if (error != 0) { 4387c478bd9Sstevel@tonic-gate USB_DPRINTF_L3(PRINT_MASK_OPEN, usbkbm_log_handle, 4397c478bd9Sstevel@tonic-gate "kbdopen: kbtrans_streams_init failed\n"); 4407c478bd9Sstevel@tonic-gate kmem_free(usbkbmd, sizeof (*usbkbmd)); 4417c478bd9Sstevel@tonic-gate 4427c478bd9Sstevel@tonic-gate return (error); 4437c478bd9Sstevel@tonic-gate } 4447c478bd9Sstevel@tonic-gate 4457c478bd9Sstevel@tonic-gate /* 4467c478bd9Sstevel@tonic-gate * Set the polled information in the state structure. 4477c478bd9Sstevel@tonic-gate * This information is set once, and doesn't change 4487c478bd9Sstevel@tonic-gate */ 4497c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_polled_info.cons_polledio_version = 4507c478bd9Sstevel@tonic-gate CONSPOLLEDIO_V1; 4517c478bd9Sstevel@tonic-gate 4527c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_polled_info.cons_polledio_argument = 4537c478bd9Sstevel@tonic-gate (struct cons_polledio_arg *)usbkbmd; 4547c478bd9Sstevel@tonic-gate 4557c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_polled_info.cons_polledio_putchar = NULL; 4567c478bd9Sstevel@tonic-gate 4577c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_polled_info.cons_polledio_getchar = 4587c478bd9Sstevel@tonic-gate usbkbm_polled_getchar; 4597c478bd9Sstevel@tonic-gate 4607c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_polled_info.cons_polledio_ischar = 4617c478bd9Sstevel@tonic-gate usbkbm_polled_ischar; 4627c478bd9Sstevel@tonic-gate 4637c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_polled_info.cons_polledio_enter = 4647c478bd9Sstevel@tonic-gate usbkbm_polled_enter; 4657c478bd9Sstevel@tonic-gate 4667c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_polled_info.cons_polledio_exit = 4677c478bd9Sstevel@tonic-gate usbkbm_polled_exit; 4687c478bd9Sstevel@tonic-gate 4697c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_polled_info.cons_polledio_setled = 4707c478bd9Sstevel@tonic-gate (void (*)(struct cons_polledio_arg *, int))usbkbm_polled_setled; 4717c478bd9Sstevel@tonic-gate 4727c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_polled_info.cons_polledio_keycheck = 4737c478bd9Sstevel@tonic-gate (boolean_t (*)(struct cons_polledio_arg *, int *, 4747c478bd9Sstevel@tonic-gate enum keystate *))usbkbm_polled_keycheck; 4757c478bd9Sstevel@tonic-gate /* 4767c478bd9Sstevel@tonic-gate * The head and the tail pointing at the same byte means empty or 4777c478bd9Sstevel@tonic-gate * full. usbkbm_polled_buffer_num_characters is used to 4787c478bd9Sstevel@tonic-gate * tell the difference. 4797c478bd9Sstevel@tonic-gate */ 4807c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_polled_buffer_head = 4817c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_polled_scancode_buffer; 4827c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_polled_buffer_tail = 4837c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_polled_scancode_buffer; 4847c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_polled_buffer_num_characters = 0; 4857c478bd9Sstevel@tonic-gate 4867c478bd9Sstevel@tonic-gate qprocson(q); 4877c478bd9Sstevel@tonic-gate 4887c478bd9Sstevel@tonic-gate if (ret = usbkbm_set_protocol(usbkbmd, SET_BOOT_PROTOCOL)) { 4897c478bd9Sstevel@tonic-gate 4907c478bd9Sstevel@tonic-gate return (ret); 4917c478bd9Sstevel@tonic-gate } 4927c478bd9Sstevel@tonic-gate 4937c478bd9Sstevel@tonic-gate /* request hid report descriptor from HID */ 4947c478bd9Sstevel@tonic-gate mctlmsg.ioc_cmd = HID_GET_PARSER_HANDLE; 4957c478bd9Sstevel@tonic-gate mctlmsg.ioc_count = 0; 4967c478bd9Sstevel@tonic-gate mctl_ptr = usba_mk_mctl(mctlmsg, NULL, 0); 4977c478bd9Sstevel@tonic-gate if (mctl_ptr == NULL) { 4987c478bd9Sstevel@tonic-gate /* failure to allocate M_CTL message */ 4997c478bd9Sstevel@tonic-gate (void) kbtrans_streams_fini(usbkbmd->usbkbm_kbtrans); 5007c478bd9Sstevel@tonic-gate qprocsoff(q); 5017c478bd9Sstevel@tonic-gate kmem_free(usbkbmd, sizeof (*usbkbmd)); 5027c478bd9Sstevel@tonic-gate 5037c478bd9Sstevel@tonic-gate return (ENOMEM); 5047c478bd9Sstevel@tonic-gate } 5057c478bd9Sstevel@tonic-gate 5067c478bd9Sstevel@tonic-gate /* send message to hid */ 5077c478bd9Sstevel@tonic-gate putnext(usbkbmd->usbkbm_writeq, mctl_ptr); 5087c478bd9Sstevel@tonic-gate 5097c478bd9Sstevel@tonic-gate /* 5107c478bd9Sstevel@tonic-gate * Now that M_CTL has been sent, wait for report descriptor. Cleanup 5117c478bd9Sstevel@tonic-gate * if user signals in the mean time (as when this gets opened in an 5127c478bd9Sstevel@tonic-gate * inappropriate context and the user types a ^C). 5137c478bd9Sstevel@tonic-gate */ 5147c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_flags |= USBKBM_QWAIT; 5157c478bd9Sstevel@tonic-gate while (usbkbmd->usbkbm_flags & USBKBM_QWAIT) { 5167c478bd9Sstevel@tonic-gate 5177c478bd9Sstevel@tonic-gate if (qwait_sig(q) == 0) { 5187c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_flags = 0; 5197c478bd9Sstevel@tonic-gate (void) kbtrans_streams_fini(usbkbmd->usbkbm_kbtrans); 5207c478bd9Sstevel@tonic-gate qprocsoff(q); 5217c478bd9Sstevel@tonic-gate kmem_free(usbkbmd, sizeof (*usbkbmd)); 5227c478bd9Sstevel@tonic-gate 5237c478bd9Sstevel@tonic-gate return (EINTR); 5247c478bd9Sstevel@tonic-gate } 5257c478bd9Sstevel@tonic-gate } 5267c478bd9Sstevel@tonic-gate 5277c478bd9Sstevel@tonic-gate /* 5287c478bd9Sstevel@tonic-gate * In case of non-self identifying keyboards the country code 5297c478bd9Sstevel@tonic-gate * has value 0. In this case we will set the layout to default US 5307c478bd9Sstevel@tonic-gate * if the usbkbm_layout is 0. 5317c478bd9Sstevel@tonic-gate */ 5327c478bd9Sstevel@tonic-gate if (usbkbmd->usbkbm_report_descr != NULL) { 5337c478bd9Sstevel@tonic-gate if ((hidparser_get_country_code(usbkbmd->usbkbm_report_descr, 5347c478bd9Sstevel@tonic-gate (uint16_t *)&usbkbmd->usbkbm_layout) == 5357c478bd9Sstevel@tonic-gate HIDPARSER_FAILURE) || (usbkbmd->usbkbm_layout == 0)) { 5367c478bd9Sstevel@tonic-gate 5377c478bd9Sstevel@tonic-gate if (!usbkbm_layout) { 5387c478bd9Sstevel@tonic-gate USB_DPRINTF_L3(PRINT_MASK_OPEN, 5397c478bd9Sstevel@tonic-gate usbkbm_log_handle, "get_country_code failed" 5407c478bd9Sstevel@tonic-gate "setting default layout(0x21)"); 5417c478bd9Sstevel@tonic-gate 5427c478bd9Sstevel@tonic-gate /* Setting to default layout = US */ 5437c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_layout = 0x21; 5447c478bd9Sstevel@tonic-gate } else 5457c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_layout = usbkbm_layout; 5467c478bd9Sstevel@tonic-gate } 5477c478bd9Sstevel@tonic-gate 5487c478bd9Sstevel@tonic-gate if (hidparser_get_packet_size(usbkbmd->usbkbm_report_descr, 5497c478bd9Sstevel@tonic-gate 0, HIDPARSER_ITEM_INPUT, (uint32_t *)&packet_size) == 5507c478bd9Sstevel@tonic-gate HIDPARSER_FAILURE) { 5517c478bd9Sstevel@tonic-gate 5527c478bd9Sstevel@tonic-gate USB_DPRINTF_L3(PRINT_MASK_OPEN, 5537c478bd9Sstevel@tonic-gate usbkbm_log_handle, "get_packet_size failed" 5547c478bd9Sstevel@tonic-gate "setting default packet size(8)"); 5557c478bd9Sstevel@tonic-gate 5567c478bd9Sstevel@tonic-gate /* Setting to default packet size = 8 */ 5577c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_packet_size = 5587c478bd9Sstevel@tonic-gate USB_KBD_DEFAULT_PACKET_SIZE; 5597c478bd9Sstevel@tonic-gate } else { 5607c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_packet_size = packet_size/8; 5617c478bd9Sstevel@tonic-gate } 5627c478bd9Sstevel@tonic-gate } else { 5637c478bd9Sstevel@tonic-gate USB_DPRINTF_L3(PRINT_MASK_OPEN, usbkbm_log_handle, 5647c478bd9Sstevel@tonic-gate "usbkbm: Invalid HID Descriptor Tree." 5657c478bd9Sstevel@tonic-gate "setting default layout(0x21) & packet_size(8)"); 5667c478bd9Sstevel@tonic-gate 5677c478bd9Sstevel@tonic-gate if (!usbkbm_layout) { 5687c478bd9Sstevel@tonic-gate /* Setting to default = US */ 5697c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_layout = 0x21; 5707c478bd9Sstevel@tonic-gate } else 5717c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_layout = usbkbm_layout; 5727c478bd9Sstevel@tonic-gate 5737c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_packet_size = 5747c478bd9Sstevel@tonic-gate USB_KBD_DEFAULT_PACKET_SIZE; 5757c478bd9Sstevel@tonic-gate } 5767c478bd9Sstevel@tonic-gate 577*6d9a41ffSqz150045 /* 578*6d9a41ffSqz150045 * Although Sun Japanese type6 and type7 keyboards have the same 579*6d9a41ffSqz150045 * layout number(15), they should be recognized for loading the 580*6d9a41ffSqz150045 * different keytables on upper apps (e.g. X). The new layout 581*6d9a41ffSqz150045 * number (271) is defined for the Sun Japanese type6 keyboards. 582*6d9a41ffSqz150045 * The layout number (15) specified in HID spec is used for other 583*6d9a41ffSqz150045 * Japanese keyboards. It is a workaround for the old Sun Japanese 584*6d9a41ffSqz150045 * type6 keyboards defect. 585*6d9a41ffSqz150045 */ 586*6d9a41ffSqz150045 if (usbkbmd->usbkbm_layout == SUN_JAPANESE_TYPE7) { 587*6d9a41ffSqz150045 588*6d9a41ffSqz150045 if ((ret = usbkbm_get_vid_pid(usbkbmd)) != 0) { 589*6d9a41ffSqz150045 590*6d9a41ffSqz150045 return (ret); 591*6d9a41ffSqz150045 } 592*6d9a41ffSqz150045 593*6d9a41ffSqz150045 if ((usbkbmd->usbkbm_vid_pid.VendorId == 594*6d9a41ffSqz150045 HID_SUN_JAPANESE_TYPE6_KBD_VID) && 595*6d9a41ffSqz150045 (usbkbmd->usbkbm_vid_pid.ProductId == 596*6d9a41ffSqz150045 HID_SUN_JAPANESE_TYPE6_KBD_PID)) { 597*6d9a41ffSqz150045 usbkbmd->usbkbm_layout = SUN_JAPANESE_TYPE6; 598*6d9a41ffSqz150045 } 599*6d9a41ffSqz150045 } 600*6d9a41ffSqz150045 6017c478bd9Sstevel@tonic-gate kbtrans_streams_set_keyboard(usbkbmd->usbkbm_kbtrans, KB_USB, 6027c478bd9Sstevel@tonic-gate usbkbm_keyindex); 6037c478bd9Sstevel@tonic-gate 6047c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_flags = USBKBM_OPEN; 6057c478bd9Sstevel@tonic-gate 6067c478bd9Sstevel@tonic-gate kbtrans_streams_enable(usbkbmd->usbkbm_kbtrans); 6077c478bd9Sstevel@tonic-gate 6087c478bd9Sstevel@tonic-gate USB_DPRINTF_L3(PRINT_MASK_OPEN, usbkbm_log_handle, 6097c478bd9Sstevel@tonic-gate "usbkbm_open exiting"); 6107c478bd9Sstevel@tonic-gate return (0); 6117c478bd9Sstevel@tonic-gate } 6127c478bd9Sstevel@tonic-gate 6137c478bd9Sstevel@tonic-gate 6147c478bd9Sstevel@tonic-gate /* 6157c478bd9Sstevel@tonic-gate * usbkbm_close : 6167c478bd9Sstevel@tonic-gate * Close a keyboard. 6177c478bd9Sstevel@tonic-gate */ 6187c478bd9Sstevel@tonic-gate /* ARGSUSED1 */ 6197c478bd9Sstevel@tonic-gate static int 6207c478bd9Sstevel@tonic-gate usbkbm_close(register queue_t *q, int flag, cred_t *crp) 6217c478bd9Sstevel@tonic-gate { 6227c478bd9Sstevel@tonic-gate usbkbm_state_t *usbkbmd = (usbkbm_state_t *)q->q_ptr; 6237c478bd9Sstevel@tonic-gate 6247c478bd9Sstevel@tonic-gate /* If a beep is in progress, stop that */ 6257c478bd9Sstevel@tonic-gate beeper_off(); 6267c478bd9Sstevel@tonic-gate 6277c478bd9Sstevel@tonic-gate (void) kbtrans_streams_fini(usbkbmd->usbkbm_kbtrans); 6287c478bd9Sstevel@tonic-gate 6297c478bd9Sstevel@tonic-gate qprocsoff(q); 6307c478bd9Sstevel@tonic-gate /* 6317c478bd9Sstevel@tonic-gate * Since we're about to destroy our private data, turn off 6327c478bd9Sstevel@tonic-gate * our open flag first, so we don't accept any more input 6337c478bd9Sstevel@tonic-gate * and try to use that data. 6347c478bd9Sstevel@tonic-gate */ 6357c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_flags = 0; 6367c478bd9Sstevel@tonic-gate 6377c478bd9Sstevel@tonic-gate kmem_free(usbkbmd, sizeof (usbkbm_state_t)); 6387c478bd9Sstevel@tonic-gate 6397c478bd9Sstevel@tonic-gate USB_DPRINTF_L3(PRINT_MASK_CLOSE, usbkbm_log_handle, 6407c478bd9Sstevel@tonic-gate "usbkbm_close exiting"); 6417c478bd9Sstevel@tonic-gate 6427c478bd9Sstevel@tonic-gate return (0); 6437c478bd9Sstevel@tonic-gate } 6447c478bd9Sstevel@tonic-gate 6457c478bd9Sstevel@tonic-gate 6467c478bd9Sstevel@tonic-gate /* 6477c478bd9Sstevel@tonic-gate * usbkbm_wput : 6487c478bd9Sstevel@tonic-gate * usb keyboard module output queue put procedure: handles M_IOCTL 6497c478bd9Sstevel@tonic-gate * messages. 6507c478bd9Sstevel@tonic-gate */ 6517c478bd9Sstevel@tonic-gate static void 6527c478bd9Sstevel@tonic-gate usbkbm_wput(register queue_t *q, register mblk_t *mp) 6537c478bd9Sstevel@tonic-gate { 6547c478bd9Sstevel@tonic-gate usbkbm_state_t *usbkbmd; 6557c478bd9Sstevel@tonic-gate enum kbtrans_message_response ret; 6567c478bd9Sstevel@tonic-gate 6577c478bd9Sstevel@tonic-gate USB_DPRINTF_L3(PRINT_MASK_ALL, usbkbm_log_handle, 6587c478bd9Sstevel@tonic-gate "usbkbm_wput entering"); 6597c478bd9Sstevel@tonic-gate 6607c478bd9Sstevel@tonic-gate usbkbmd = (usbkbm_state_t *)q->q_ptr; 6617c478bd9Sstevel@tonic-gate 6627c478bd9Sstevel@tonic-gate /* First, see if kbtrans will handle the message */ 6637c478bd9Sstevel@tonic-gate ret = kbtrans_streams_message(usbkbmd->usbkbm_kbtrans, mp); 6647c478bd9Sstevel@tonic-gate 6657c478bd9Sstevel@tonic-gate if (ret == KBTRANS_MESSAGE_HANDLED) { 6667c478bd9Sstevel@tonic-gate 6677c478bd9Sstevel@tonic-gate USB_DPRINTF_L3(PRINT_MASK_ALL, usbkbm_log_handle, 6687c478bd9Sstevel@tonic-gate "usbkbm_wput exiting:2"); 6697c478bd9Sstevel@tonic-gate 6707c478bd9Sstevel@tonic-gate return; 6717c478bd9Sstevel@tonic-gate } 6727c478bd9Sstevel@tonic-gate 6737c478bd9Sstevel@tonic-gate /* kbtrans didn't handle the message. Try to handle it here */ 6747c478bd9Sstevel@tonic-gate 6757c478bd9Sstevel@tonic-gate switch (mp->b_datap->db_type) { 6767c478bd9Sstevel@tonic-gate 6777c478bd9Sstevel@tonic-gate case M_FLUSH: 6787c478bd9Sstevel@tonic-gate if (*mp->b_rptr & FLUSHW) { 6797c478bd9Sstevel@tonic-gate flushq(q, FLUSHDATA); 6807c478bd9Sstevel@tonic-gate } 6817c478bd9Sstevel@tonic-gate 6827c478bd9Sstevel@tonic-gate if (*mp->b_rptr & FLUSHR) { 6837c478bd9Sstevel@tonic-gate flushq(RD(q), FLUSHDATA); 6847c478bd9Sstevel@tonic-gate } 6857c478bd9Sstevel@tonic-gate 6867c478bd9Sstevel@tonic-gate break; 6877c478bd9Sstevel@tonic-gate 6887c478bd9Sstevel@tonic-gate case M_IOCTL: 6897c478bd9Sstevel@tonic-gate ret = usbkbm_ioctl(q, mp); 6907c478bd9Sstevel@tonic-gate 6917c478bd9Sstevel@tonic-gate if (ret == KBTRANS_MESSAGE_HANDLED) { 6927c478bd9Sstevel@tonic-gate 6937c478bd9Sstevel@tonic-gate USB_DPRINTF_L3(PRINT_MASK_ALL, usbkbm_log_handle, 6947c478bd9Sstevel@tonic-gate "usbkbm_wput exiting:1"); 6957c478bd9Sstevel@tonic-gate 6967c478bd9Sstevel@tonic-gate return; 6977c478bd9Sstevel@tonic-gate } 6987c478bd9Sstevel@tonic-gate default: 6997c478bd9Sstevel@tonic-gate break; 7007c478bd9Sstevel@tonic-gate } 7017c478bd9Sstevel@tonic-gate 7027c478bd9Sstevel@tonic-gate /* 7037c478bd9Sstevel@tonic-gate * The message has not been handled 7047c478bd9Sstevel@tonic-gate * by kbtrans or this module. Pass it down the stream 7057c478bd9Sstevel@tonic-gate */ 7067c478bd9Sstevel@tonic-gate putnext(q, mp); 7077c478bd9Sstevel@tonic-gate 7087c478bd9Sstevel@tonic-gate USB_DPRINTF_L3(PRINT_MASK_ALL, usbkbm_log_handle, 7097c478bd9Sstevel@tonic-gate "usbkbm_wput exiting:3"); 7107c478bd9Sstevel@tonic-gate } 7117c478bd9Sstevel@tonic-gate 7127c478bd9Sstevel@tonic-gate /* 7137c478bd9Sstevel@tonic-gate * usbkbm_ioctl : 7147c478bd9Sstevel@tonic-gate * Handles the ioctls sent from upper module. Returns 7157c478bd9Sstevel@tonic-gate * ACK/NACK back. 7167c478bd9Sstevel@tonic-gate */ 7177c478bd9Sstevel@tonic-gate static enum kbtrans_message_response 7187c478bd9Sstevel@tonic-gate usbkbm_ioctl(register queue_t *q, register mblk_t *mp) 7197c478bd9Sstevel@tonic-gate { 7207c478bd9Sstevel@tonic-gate usbkbm_state_t *usbkbmd; 7217c478bd9Sstevel@tonic-gate struct iocblk mctlmsg; 7227c478bd9Sstevel@tonic-gate struct iocblk *iocp; 7237c478bd9Sstevel@tonic-gate mblk_t *datap, *mctl_ptr; 7247c478bd9Sstevel@tonic-gate size_t ioctlrespsize; 7257c478bd9Sstevel@tonic-gate int err; 7267c478bd9Sstevel@tonic-gate int tmp; 7277c478bd9Sstevel@tonic-gate char command; 7287c478bd9Sstevel@tonic-gate 7297c478bd9Sstevel@tonic-gate err = 0; 7307c478bd9Sstevel@tonic-gate 7317c478bd9Sstevel@tonic-gate usbkbmd = (usbkbm_state_t *)q->q_ptr; 7327c478bd9Sstevel@tonic-gate iocp = (struct iocblk *)mp->b_rptr; 7337c478bd9Sstevel@tonic-gate 7347c478bd9Sstevel@tonic-gate switch (iocp->ioc_cmd) { 7357c478bd9Sstevel@tonic-gate case CONSSETKBDTYPE: 7367c478bd9Sstevel@tonic-gate err = miocpullup(mp, sizeof (int)); 7377c478bd9Sstevel@tonic-gate if (err != 0) { 7387c478bd9Sstevel@tonic-gate break; 7397c478bd9Sstevel@tonic-gate } 7407c478bd9Sstevel@tonic-gate tmp = *(int *)mp->b_cont->b_rptr; 7417c478bd9Sstevel@tonic-gate if (tmp != KB_PC && tmp != KB_USB) { 7427c478bd9Sstevel@tonic-gate err = EINVAL; 7437c478bd9Sstevel@tonic-gate break; 7447c478bd9Sstevel@tonic-gate } 7457c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_vkbd_type = tmp; 7467c478bd9Sstevel@tonic-gate break; 7477c478bd9Sstevel@tonic-gate case KIOCLAYOUT: 7487c478bd9Sstevel@tonic-gate 7497c478bd9Sstevel@tonic-gate datap = allocb(sizeof (int), BPRI_HI); 7507c478bd9Sstevel@tonic-gate if (datap == NULL) { 7517c478bd9Sstevel@tonic-gate ioctlrespsize = sizeof (int); 7527c478bd9Sstevel@tonic-gate 7537c478bd9Sstevel@tonic-gate goto allocfailure; 7547c478bd9Sstevel@tonic-gate } 7557c478bd9Sstevel@tonic-gate 7567c478bd9Sstevel@tonic-gate *(int *)datap->b_wptr = usbkbmd->usbkbm_layout; 7577c478bd9Sstevel@tonic-gate datap->b_wptr += sizeof (int); 7587c478bd9Sstevel@tonic-gate 7597c478bd9Sstevel@tonic-gate freemsg(mp->b_cont); 7607c478bd9Sstevel@tonic-gate 7617c478bd9Sstevel@tonic-gate mp->b_cont = datap; 7627c478bd9Sstevel@tonic-gate iocp->ioc_count = sizeof (int); 7637c478bd9Sstevel@tonic-gate break; 7647c478bd9Sstevel@tonic-gate 7657c478bd9Sstevel@tonic-gate case KIOCSLAYOUT: 7667c478bd9Sstevel@tonic-gate /* 7677c478bd9Sstevel@tonic-gate * Supply a layout if not specified by the hardware, or 7687c478bd9Sstevel@tonic-gate * override any that was specified. 7697c478bd9Sstevel@tonic-gate */ 7707c478bd9Sstevel@tonic-gate if (iocp->ioc_count != TRANSPARENT) { 7717c478bd9Sstevel@tonic-gate err = EINVAL; 7727c478bd9Sstevel@tonic-gate break; 7737c478bd9Sstevel@tonic-gate } 7747c478bd9Sstevel@tonic-gate 7757c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_layout = *(intptr_t *)mp->b_cont->b_rptr; 7767c478bd9Sstevel@tonic-gate 7777c478bd9Sstevel@tonic-gate /* 7787c478bd9Sstevel@tonic-gate * Save the layout in usbkbm_layout so as to handle the 7797c478bd9Sstevel@tonic-gate * the case when the user has re-plugged in the non-self 7807c478bd9Sstevel@tonic-gate * identifying non US keyboard. In this the layout is saved 7817c478bd9Sstevel@tonic-gate * in global variable, so the user does not have to run 7827c478bd9Sstevel@tonic-gate * kdmconfig again after the X server reset 7837c478bd9Sstevel@tonic-gate */ 7847c478bd9Sstevel@tonic-gate 7857c478bd9Sstevel@tonic-gate usbkbm_layout = usbkbmd->usbkbm_layout; 7867c478bd9Sstevel@tonic-gate break; 7877c478bd9Sstevel@tonic-gate 7887c478bd9Sstevel@tonic-gate case KIOCCMD: 7897c478bd9Sstevel@tonic-gate /* 7907c478bd9Sstevel@tonic-gate * Check if we have at least the subcommand field; any 7917c478bd9Sstevel@tonic-gate * other argument validation has to occur inside 7927c478bd9Sstevel@tonic-gate * usbkbm_kioccmd(). 7937c478bd9Sstevel@tonic-gate */ 7947c478bd9Sstevel@tonic-gate err = miocpullup(mp, sizeof (int)); 7957c478bd9Sstevel@tonic-gate if (err != 0) 7967c478bd9Sstevel@tonic-gate break; 7977c478bd9Sstevel@tonic-gate 7987c478bd9Sstevel@tonic-gate /* Subcommand */ 7997c478bd9Sstevel@tonic-gate command = (char)(*(int *)mp->b_cont->b_rptr); 8007c478bd9Sstevel@tonic-gate 8017c478bd9Sstevel@tonic-gate /* 8027c478bd9Sstevel@tonic-gate * Check if this ioctl is followed by a previous 8037c478bd9Sstevel@tonic-gate * KBD_CMD_SETLED command, in which case we take 8047c478bd9Sstevel@tonic-gate * the command byte as the data for setting the LED 8057c478bd9Sstevel@tonic-gate */ 8067c478bd9Sstevel@tonic-gate if (usbkbmd->usbkbm_setled_second_byte) { 8077c478bd9Sstevel@tonic-gate usbkbm_streams_setled((struct kbtrans_hardware *) 8087c478bd9Sstevel@tonic-gate usbkbmd, command); 8097c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_setled_second_byte = 0; 8107c478bd9Sstevel@tonic-gate break; 8117c478bd9Sstevel@tonic-gate } 8127c478bd9Sstevel@tonic-gate 8137c478bd9Sstevel@tonic-gate /* 8147c478bd9Sstevel@tonic-gate * In case of allocb failure, this will 8157c478bd9Sstevel@tonic-gate * return the size of the allocation which 8167c478bd9Sstevel@tonic-gate * failed so that it can be allocated later 8177c478bd9Sstevel@tonic-gate * through bufcall. 8187c478bd9Sstevel@tonic-gate */ 8197c478bd9Sstevel@tonic-gate ioctlrespsize = 0; 8207c478bd9Sstevel@tonic-gate 8217c478bd9Sstevel@tonic-gate err = usbkbm_kioccmd(usbkbmd, mp, command, &ioctlrespsize); 8227c478bd9Sstevel@tonic-gate 8237c478bd9Sstevel@tonic-gate if (ioctlrespsize != 0) { 8247c478bd9Sstevel@tonic-gate 8257c478bd9Sstevel@tonic-gate goto allocfailure; 8267c478bd9Sstevel@tonic-gate } 8277c478bd9Sstevel@tonic-gate 8287c478bd9Sstevel@tonic-gate break; 8297c478bd9Sstevel@tonic-gate 8307c478bd9Sstevel@tonic-gate case CONSOPENPOLLEDIO: 8317c478bd9Sstevel@tonic-gate USB_DPRINTF_L3(PRINT_MASK_ALL, usbkbm_log_handle, 8327c478bd9Sstevel@tonic-gate "usbkbm_ioctl CONSOPENPOLLEDIO"); 8337c478bd9Sstevel@tonic-gate 8347c478bd9Sstevel@tonic-gate err = miocpullup(mp, sizeof (struct cons_polledio *)); 8357c478bd9Sstevel@tonic-gate if (err != 0) { 8367c478bd9Sstevel@tonic-gate USB_DPRINTF_L2(PRINT_MASK_ALL, usbkbm_log_handle, 8377c478bd9Sstevel@tonic-gate "usbkbm_ioctl: malformed request"); 8387c478bd9Sstevel@tonic-gate break; 8397c478bd9Sstevel@tonic-gate } 8407c478bd9Sstevel@tonic-gate 8417c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_pending_link = mp; 8427c478bd9Sstevel@tonic-gate 8437c478bd9Sstevel@tonic-gate /* 8447c478bd9Sstevel@tonic-gate * Get the polled input structure from hid 8457c478bd9Sstevel@tonic-gate */ 8467c478bd9Sstevel@tonic-gate mctlmsg.ioc_cmd = HID_OPEN_POLLED_INPUT; 8477c478bd9Sstevel@tonic-gate mctlmsg.ioc_count = 0; 8487c478bd9Sstevel@tonic-gate mctl_ptr = usba_mk_mctl(mctlmsg, NULL, 0); 8497c478bd9Sstevel@tonic-gate if (mctl_ptr == NULL) { 8507c478bd9Sstevel@tonic-gate ioctlrespsize = sizeof (mctlmsg); 8517c478bd9Sstevel@tonic-gate 8527c478bd9Sstevel@tonic-gate goto allocfailure; 8537c478bd9Sstevel@tonic-gate } 8547c478bd9Sstevel@tonic-gate 8557c478bd9Sstevel@tonic-gate putnext(usbkbmd->usbkbm_writeq, mctl_ptr); 8567c478bd9Sstevel@tonic-gate 8577c478bd9Sstevel@tonic-gate /* 8587c478bd9Sstevel@tonic-gate * Do not ack or nack the message, we will wait for the 8597c478bd9Sstevel@tonic-gate * result of HID_OPEN_POLLED_INPUT 8607c478bd9Sstevel@tonic-gate */ 8617c478bd9Sstevel@tonic-gate 8627c478bd9Sstevel@tonic-gate return (KBTRANS_MESSAGE_HANDLED); 8637c478bd9Sstevel@tonic-gate 8647c478bd9Sstevel@tonic-gate case CONSCLOSEPOLLEDIO: 8657c478bd9Sstevel@tonic-gate USB_DPRINTF_L3(PRINT_MASK_ALL, usbkbm_log_handle, 8667c478bd9Sstevel@tonic-gate "usbkbm_ioctl CONSCLOSEPOLLEDIO mp = 0x%p", (void *)mp); 8677c478bd9Sstevel@tonic-gate 8687c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_pending_link = mp; 8697c478bd9Sstevel@tonic-gate 8707c478bd9Sstevel@tonic-gate /* 8717c478bd9Sstevel@tonic-gate * Get the polled input structure from hid 8727c478bd9Sstevel@tonic-gate */ 8737c478bd9Sstevel@tonic-gate mctlmsg.ioc_cmd = HID_CLOSE_POLLED_INPUT; 8747c478bd9Sstevel@tonic-gate mctlmsg.ioc_count = 0; 8757c478bd9Sstevel@tonic-gate mctl_ptr = usba_mk_mctl(mctlmsg, NULL, 0); 8767c478bd9Sstevel@tonic-gate if (mctl_ptr == NULL) { 8777c478bd9Sstevel@tonic-gate ioctlrespsize = sizeof (mctlmsg); 8787c478bd9Sstevel@tonic-gate 8797c478bd9Sstevel@tonic-gate goto allocfailure; 8807c478bd9Sstevel@tonic-gate } 8817c478bd9Sstevel@tonic-gate 8827c478bd9Sstevel@tonic-gate putnext(usbkbmd->usbkbm_writeq, mctl_ptr); 8837c478bd9Sstevel@tonic-gate 8847c478bd9Sstevel@tonic-gate /* 8857c478bd9Sstevel@tonic-gate * Do not ack or nack the message, we will wait for the 8867c478bd9Sstevel@tonic-gate * result of HID_CLOSE_POLLED_INPUT 8877c478bd9Sstevel@tonic-gate */ 8887c478bd9Sstevel@tonic-gate 8897c478bd9Sstevel@tonic-gate return (KBTRANS_MESSAGE_HANDLED); 8907c478bd9Sstevel@tonic-gate 8917c478bd9Sstevel@tonic-gate case CONSSETABORTENABLE: 8927c478bd9Sstevel@tonic-gate /* 8937c478bd9Sstevel@tonic-gate * Nothing special to do for USB. 8947c478bd9Sstevel@tonic-gate */ 8957c478bd9Sstevel@tonic-gate break; 8967c478bd9Sstevel@tonic-gate 8977c478bd9Sstevel@tonic-gate 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 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 */ 10007c478bd9Sstevel@tonic-gate 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 */ 10097c478bd9Sstevel@tonic-gate 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 /* 10287c478bd9Sstevel@tonic-gate * usbkbm_rput : 10297c478bd9Sstevel@tonic-gate * Put procedure for input from driver end of stream (read queue). 10307c478bd9Sstevel@tonic-gate */ 10317c478bd9Sstevel@tonic-gate static void 10327c478bd9Sstevel@tonic-gate usbkbm_rput(register queue_t *q, register mblk_t *mp) 10337c478bd9Sstevel@tonic-gate { 10347c478bd9Sstevel@tonic-gate usbkbm_state_t *usbkbmd; 10357c478bd9Sstevel@tonic-gate 10367c478bd9Sstevel@tonic-gate usbkbmd = (usbkbm_state_t *)q->q_ptr; 10377c478bd9Sstevel@tonic-gate 10387c478bd9Sstevel@tonic-gate USB_DPRINTF_L3(PRINT_MASK_ALL, usbkbm_log_handle, 10397c478bd9Sstevel@tonic-gate "usbkbm_rput"); 10407c478bd9Sstevel@tonic-gate 10417c478bd9Sstevel@tonic-gate if (usbkbmd == 0) { 10427c478bd9Sstevel@tonic-gate freemsg(mp); /* nobody's listening */ 10437c478bd9Sstevel@tonic-gate 10447c478bd9Sstevel@tonic-gate return; 10457c478bd9Sstevel@tonic-gate } 10467c478bd9Sstevel@tonic-gate 10477c478bd9Sstevel@tonic-gate switch (mp->b_datap->db_type) { 10487c478bd9Sstevel@tonic-gate 10497c478bd9Sstevel@tonic-gate case M_FLUSH: 10507c478bd9Sstevel@tonic-gate if (*mp->b_rptr & FLUSHW) 10517c478bd9Sstevel@tonic-gate flushq(WR(q), FLUSHDATA); 10527c478bd9Sstevel@tonic-gate if (*mp->b_rptr & FLUSHR) 10537c478bd9Sstevel@tonic-gate flushq(q, FLUSHDATA); 10547c478bd9Sstevel@tonic-gate 10557c478bd9Sstevel@tonic-gate freemsg(mp); 10567c478bd9Sstevel@tonic-gate 10577c478bd9Sstevel@tonic-gate return; 10587c478bd9Sstevel@tonic-gate case M_BREAK: 10597c478bd9Sstevel@tonic-gate /* 10607c478bd9Sstevel@tonic-gate * Will get M_BREAK only if this is not the system 10617c478bd9Sstevel@tonic-gate * keyboard, otherwise serial port will eat break 10627c478bd9Sstevel@tonic-gate * and call kmdb/OBP, without passing anything up. 10637c478bd9Sstevel@tonic-gate */ 10647c478bd9Sstevel@tonic-gate freemsg(mp); 10657c478bd9Sstevel@tonic-gate 10667c478bd9Sstevel@tonic-gate return; 10677c478bd9Sstevel@tonic-gate case M_DATA: 10687c478bd9Sstevel@tonic-gate if (!(usbkbmd->usbkbm_flags & USBKBM_OPEN)) { 10697c478bd9Sstevel@tonic-gate freemsg(mp); /* not ready to listen */ 10707c478bd9Sstevel@tonic-gate 10717c478bd9Sstevel@tonic-gate return; 10727c478bd9Sstevel@tonic-gate } 10737c478bd9Sstevel@tonic-gate 10747c478bd9Sstevel@tonic-gate break; 10757c478bd9Sstevel@tonic-gate case M_CTL: 10767c478bd9Sstevel@tonic-gate usbkbm_mctl_receive(q, mp); 10777c478bd9Sstevel@tonic-gate 10787c478bd9Sstevel@tonic-gate return; 10797c478bd9Sstevel@tonic-gate case M_ERROR: 10807c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_flags &= ~USBKBM_QWAIT; 10817c478bd9Sstevel@tonic-gate freemsg(mp); 10827c478bd9Sstevel@tonic-gate 10837c478bd9Sstevel@tonic-gate return; 10847c478bd9Sstevel@tonic-gate case M_IOCACK: 10857c478bd9Sstevel@tonic-gate case M_IOCNAK: 10867c478bd9Sstevel@tonic-gate putnext(q, mp); 10877c478bd9Sstevel@tonic-gate 10887c478bd9Sstevel@tonic-gate return; 10897c478bd9Sstevel@tonic-gate default: 10907c478bd9Sstevel@tonic-gate putnext(q, mp); 10917c478bd9Sstevel@tonic-gate 10927c478bd9Sstevel@tonic-gate return; 10937c478bd9Sstevel@tonic-gate } 10947c478bd9Sstevel@tonic-gate 10957c478bd9Sstevel@tonic-gate /* 10967c478bd9Sstevel@tonic-gate * A data message, consisting of bytes from the keyboard. 10977c478bd9Sstevel@tonic-gate * Ram them through the translator, only if there are 10987c478bd9Sstevel@tonic-gate * correct no. of bytes. 10997c478bd9Sstevel@tonic-gate */ 11007c478bd9Sstevel@tonic-gate if ((mp->b_wptr - mp->b_rptr) == usbkbmd->usbkbm_packet_size) { 11017c478bd9Sstevel@tonic-gate usbkbm_unpack_usb_packet(usbkbmd, usbkbm_streams_callback, 11027c478bd9Sstevel@tonic-gate (uchar_t *)mp->b_rptr, usbkbmd->usbkbm_packet_size); 11037c478bd9Sstevel@tonic-gate } 11047c478bd9Sstevel@tonic-gate 11057c478bd9Sstevel@tonic-gate freemsg(mp); 11067c478bd9Sstevel@tonic-gate } 11077c478bd9Sstevel@tonic-gate 11087c478bd9Sstevel@tonic-gate /* 11097c478bd9Sstevel@tonic-gate * usbkbm_mctl_receive : 11107c478bd9Sstevel@tonic-gate * Handle M_CTL messages from hid. If we don't understand 11117c478bd9Sstevel@tonic-gate * the command, send it up. 11127c478bd9Sstevel@tonic-gate */ 11137c478bd9Sstevel@tonic-gate static void 11147c478bd9Sstevel@tonic-gate usbkbm_mctl_receive(register queue_t *q, register mblk_t *mp) 11157c478bd9Sstevel@tonic-gate { 11167c478bd9Sstevel@tonic-gate register usbkbm_state_t *usbkbmd = (usbkbm_state_t *)q->q_ptr; 11177c478bd9Sstevel@tonic-gate register struct iocblk *iocp, mctlmsg; 11187c478bd9Sstevel@tonic-gate caddr_t data = NULL; 11197c478bd9Sstevel@tonic-gate mblk_t *reply_mp, *mctl_ptr; 11207c478bd9Sstevel@tonic-gate uchar_t new_buffer[USBKBM_MAXPKTSIZE]; 11217c478bd9Sstevel@tonic-gate size_t size; 11227c478bd9Sstevel@tonic-gate hid_req_t buf; 11237c478bd9Sstevel@tonic-gate size_t len = sizeof (buf); 11247c478bd9Sstevel@tonic-gate 11257c478bd9Sstevel@tonic-gate 11267c478bd9Sstevel@tonic-gate 11277c478bd9Sstevel@tonic-gate iocp = (struct iocblk *)mp->b_rptr; 11287c478bd9Sstevel@tonic-gate if (mp->b_cont != NULL) 11297c478bd9Sstevel@tonic-gate data = (caddr_t)mp->b_cont->b_rptr; 11307c478bd9Sstevel@tonic-gate 11317c478bd9Sstevel@tonic-gate switch (iocp->ioc_cmd) { 11327c478bd9Sstevel@tonic-gate 11337c478bd9Sstevel@tonic-gate case HID_SET_REPORT: 11347c478bd9Sstevel@tonic-gate USB_DPRINTF_L3(PRINT_MASK_ALL, usbkbm_log_handle, 11357c478bd9Sstevel@tonic-gate "usbkbm_mctl_receive HID_SET mctl"); 11367c478bd9Sstevel@tonic-gate freemsg(mp); 11377c478bd9Sstevel@tonic-gate /* Setting of the LED is not waiting for this message */ 11387c478bd9Sstevel@tonic-gate 11397c478bd9Sstevel@tonic-gate break; 11407c478bd9Sstevel@tonic-gate case HID_SET_PROTOCOL: 11417c478bd9Sstevel@tonic-gate freemsg(mp); 11427c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_flags &= ~USBKBM_QWAIT; 11437c478bd9Sstevel@tonic-gate 11447c478bd9Sstevel@tonic-gate break; 11457c478bd9Sstevel@tonic-gate case HID_GET_PARSER_HANDLE: 11467c478bd9Sstevel@tonic-gate if ((data != NULL) && 11477c478bd9Sstevel@tonic-gate (iocp->ioc_count == sizeof (hidparser_handle_t)) && 11487c478bd9Sstevel@tonic-gate ((mp->b_cont->b_wptr - mp->b_cont->b_rptr) == 11497c478bd9Sstevel@tonic-gate iocp->ioc_count)) { 11507c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_report_descr = 11517c478bd9Sstevel@tonic-gate *(hidparser_handle_t *)data; 11527c478bd9Sstevel@tonic-gate } else { 11537c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_report_descr = NULL; 11547c478bd9Sstevel@tonic-gate } 11557c478bd9Sstevel@tonic-gate freemsg(mp); 11567c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_flags &= ~USBKBM_QWAIT; 11577c478bd9Sstevel@tonic-gate 11587c478bd9Sstevel@tonic-gate break; 1159*6d9a41ffSqz150045 case HID_GET_VID_PID: 1160*6d9a41ffSqz150045 if ((data != NULL) && 1161*6d9a41ffSqz150045 (iocp->ioc_count == sizeof (hid_vid_pid_t)) && 1162*6d9a41ffSqz150045 ((mp->b_cont->b_wptr - mp->b_cont->b_rptr) == 1163*6d9a41ffSqz150045 iocp->ioc_count)) { 1164*6d9a41ffSqz150045 bcopy(data, &usbkbmd->usbkbm_vid_pid, iocp->ioc_count); 1165*6d9a41ffSqz150045 } 1166*6d9a41ffSqz150045 freemsg(mp); 1167*6d9a41ffSqz150045 usbkbmd->usbkbm_flags &= ~USBKBM_QWAIT; 1168*6d9a41ffSqz150045 1169*6d9a41ffSqz150045 break; 11707c478bd9Sstevel@tonic-gate case HID_OPEN_POLLED_INPUT: 11717c478bd9Sstevel@tonic-gate USB_DPRINTF_L3(PRINT_MASK_ALL, usbkbm_log_handle, 11727c478bd9Sstevel@tonic-gate "usbkbm_mctl_receive HID_OPEN_POLLED_INPUT"); 11737c478bd9Sstevel@tonic-gate 11747c478bd9Sstevel@tonic-gate size = sizeof (hid_polled_input_callback_t); 11757c478bd9Sstevel@tonic-gate reply_mp = usbkbmd->usbkbm_pending_link; 11767c478bd9Sstevel@tonic-gate if ((data != NULL) && 11777c478bd9Sstevel@tonic-gate (iocp->ioc_count == size) && 11787c478bd9Sstevel@tonic-gate ((mp->b_cont->b_wptr - mp->b_cont->b_rptr) == size)) { 11797c478bd9Sstevel@tonic-gate /* 11807c478bd9Sstevel@tonic-gate * Copy the information from hid into the 11817c478bd9Sstevel@tonic-gate * state structure 11827c478bd9Sstevel@tonic-gate */ 11837c478bd9Sstevel@tonic-gate bcopy(data, &usbkbmd->usbkbm_hid_callback, size); 11847c478bd9Sstevel@tonic-gate reply_mp->b_datap->db_type = M_IOCACK; 11857c478bd9Sstevel@tonic-gate 11867c478bd9Sstevel@tonic-gate /* 11877c478bd9Sstevel@tonic-gate * We are given an appropriate-sized data block, 11887c478bd9Sstevel@tonic-gate * and return a pointer to our structure in it. 11897c478bd9Sstevel@tonic-gate * The structure is saved in the states structure 11907c478bd9Sstevel@tonic-gate */ 11917c478bd9Sstevel@tonic-gate *(cons_polledio_t **)reply_mp->b_cont->b_rptr = 11927c478bd9Sstevel@tonic-gate &usbkbmd->usbkbm_polled_info; 11937c478bd9Sstevel@tonic-gate 11947c478bd9Sstevel@tonic-gate } else { 11957c478bd9Sstevel@tonic-gate reply_mp->b_datap->db_type = M_IOCNAK; 11967c478bd9Sstevel@tonic-gate } 11977c478bd9Sstevel@tonic-gate freemsg(mp); 11987c478bd9Sstevel@tonic-gate 11997c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_pending_link = NULL; 12007c478bd9Sstevel@tonic-gate 12017c478bd9Sstevel@tonic-gate putnext(q, reply_mp); 12027c478bd9Sstevel@tonic-gate 12037c478bd9Sstevel@tonic-gate break; 12047c478bd9Sstevel@tonic-gate case HID_CLOSE_POLLED_INPUT: 12057c478bd9Sstevel@tonic-gate USB_DPRINTF_L3(PRINT_MASK_ALL, usbkbm_log_handle, 12067c478bd9Sstevel@tonic-gate "usbkbm_mctl_receive HID_CLOSE_POLLED_INPUT"); 12077c478bd9Sstevel@tonic-gate 12087c478bd9Sstevel@tonic-gate 12097c478bd9Sstevel@tonic-gate bzero(&usbkbmd->usbkbm_hid_callback, 12107c478bd9Sstevel@tonic-gate sizeof (hid_polled_input_callback_t)); 12117c478bd9Sstevel@tonic-gate 12127c478bd9Sstevel@tonic-gate freemsg(mp); 12137c478bd9Sstevel@tonic-gate 12147c478bd9Sstevel@tonic-gate reply_mp = usbkbmd->usbkbm_pending_link; 12157c478bd9Sstevel@tonic-gate 12167c478bd9Sstevel@tonic-gate iocp = (struct iocblk *)reply_mp->b_rptr; 12177c478bd9Sstevel@tonic-gate 12187c478bd9Sstevel@tonic-gate USB_DPRINTF_L3(PRINT_MASK_ALL, usbkbm_log_handle, 12197c478bd9Sstevel@tonic-gate "usbkbm_mctl_receive reply reply_mp 0x%p cmd 0x%x", 12207c478bd9Sstevel@tonic-gate (void *)reply_mp, iocp->ioc_cmd); 12217c478bd9Sstevel@tonic-gate 12227c478bd9Sstevel@tonic-gate 12237c478bd9Sstevel@tonic-gate reply_mp->b_datap->db_type = M_IOCACK; 12247c478bd9Sstevel@tonic-gate 12257c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_pending_link = NULL; 12267c478bd9Sstevel@tonic-gate 12277c478bd9Sstevel@tonic-gate putnext(q, reply_mp); 12287c478bd9Sstevel@tonic-gate 12297c478bd9Sstevel@tonic-gate break; 12307c478bd9Sstevel@tonic-gate case HID_DISCONNECT_EVENT : 12317c478bd9Sstevel@tonic-gate case HID_POWER_OFF: 12327c478bd9Sstevel@tonic-gate USB_DPRINTF_L3(PRINT_MASK_ALL, usbkbm_log_handle, 12337c478bd9Sstevel@tonic-gate "usbkbm_mctl_receive HID_DISCONNECT_EVENT/HID_POWER_OFF"); 12347c478bd9Sstevel@tonic-gate 12357c478bd9Sstevel@tonic-gate /* Indicate all keys have been released */ 12367c478bd9Sstevel@tonic-gate bzero(new_buffer, USBKBM_MAXPKTSIZE); 12377c478bd9Sstevel@tonic-gate usbkbm_unpack_usb_packet(usbkbmd, usbkbm_streams_callback, 12387c478bd9Sstevel@tonic-gate new_buffer, usbkbmd->usbkbm_packet_size); 12397c478bd9Sstevel@tonic-gate 12407c478bd9Sstevel@tonic-gate freemsg(mp); 12417c478bd9Sstevel@tonic-gate 12427c478bd9Sstevel@tonic-gate break; 12437c478bd9Sstevel@tonic-gate case HID_CONNECT_EVENT: 12447c478bd9Sstevel@tonic-gate mctlmsg.ioc_cmd = HID_SET_PROTOCOL; 12457c478bd9Sstevel@tonic-gate mctlmsg.ioc_count = 0; 12467c478bd9Sstevel@tonic-gate buf.hid_req_version_no = HID_VERSION_V_0; 12477c478bd9Sstevel@tonic-gate buf.hid_req_wValue = SET_BOOT_PROTOCOL; 12487c478bd9Sstevel@tonic-gate buf.hid_req_wLength = 0; 12497c478bd9Sstevel@tonic-gate buf.hid_req_data = NULL; 12507c478bd9Sstevel@tonic-gate mctl_ptr = usba_mk_mctl(mctlmsg, &buf, len); 12517c478bd9Sstevel@tonic-gate if (mctl_ptr == NULL) { 12527c478bd9Sstevel@tonic-gate USB_DPRINTF_L2(PRINT_MASK_ALL, usbkbm_log_handle, 12537c478bd9Sstevel@tonic-gate "usbkbm_mctl_receive HID_CONNECT_EVENT: " 12547c478bd9Sstevel@tonic-gate "Set protocol failed"); 12557c478bd9Sstevel@tonic-gate } else { 12567c478bd9Sstevel@tonic-gate putnext(usbkbmd->usbkbm_writeq, mctl_ptr); 12577c478bd9Sstevel@tonic-gate } 12587c478bd9Sstevel@tonic-gate 12597c478bd9Sstevel@tonic-gate /* FALLTHRU */ 12607c478bd9Sstevel@tonic-gate case HID_FULL_POWER : 12617c478bd9Sstevel@tonic-gate USB_DPRINTF_L3(PRINT_MASK_ALL, usbkbm_log_handle, 12627c478bd9Sstevel@tonic-gate "usbkbm_mctl_receive restore LEDs"); 12637c478bd9Sstevel@tonic-gate 12647c478bd9Sstevel@tonic-gate /* send setled command down to restore LED states */ 12657c478bd9Sstevel@tonic-gate usbkbm_streams_setled((struct kbtrans_hardware *)usbkbmd, 12667c478bd9Sstevel@tonic-gate usbkbm_led_state); 12677c478bd9Sstevel@tonic-gate 12687c478bd9Sstevel@tonic-gate freemsg(mp); 12697c478bd9Sstevel@tonic-gate 12707c478bd9Sstevel@tonic-gate break; 12717c478bd9Sstevel@tonic-gate default: 12727c478bd9Sstevel@tonic-gate putnext(q, mp); 12737c478bd9Sstevel@tonic-gate 12747c478bd9Sstevel@tonic-gate break; 12757c478bd9Sstevel@tonic-gate } 12767c478bd9Sstevel@tonic-gate } 12777c478bd9Sstevel@tonic-gate 12787c478bd9Sstevel@tonic-gate 12797c478bd9Sstevel@tonic-gate /* 12807c478bd9Sstevel@tonic-gate * usbkbm_streams_setled : 12817c478bd9Sstevel@tonic-gate * Update the keyboard LEDs to match the current keyboard state. 12827c478bd9Sstevel@tonic-gate * Send LED state downstreams to hid driver. 12837c478bd9Sstevel@tonic-gate */ 12847c478bd9Sstevel@tonic-gate static void 12857c478bd9Sstevel@tonic-gate usbkbm_streams_setled(struct kbtrans_hardware *kbtrans_hw, int state) 12867c478bd9Sstevel@tonic-gate { 12877c478bd9Sstevel@tonic-gate struct iocblk mctlmsg; 12887c478bd9Sstevel@tonic-gate mblk_t *LED_message, *mctl_ptr; 12897c478bd9Sstevel@tonic-gate hid_req_t *LED_report; 12907c478bd9Sstevel@tonic-gate usbkbm_state_t *usbkbmd; 12917c478bd9Sstevel@tonic-gate uchar_t led_state; 12927c478bd9Sstevel@tonic-gate 12937c478bd9Sstevel@tonic-gate usbkbm_led_state = (uchar_t)state; 12947c478bd9Sstevel@tonic-gate 12957c478bd9Sstevel@tonic-gate usbkbmd = (usbkbm_state_t *)kbtrans_hw; 12967c478bd9Sstevel@tonic-gate 12977c478bd9Sstevel@tonic-gate LED_report = kmem_zalloc(sizeof (hid_req_t), KM_NOSLEEP); 12987c478bd9Sstevel@tonic-gate if (LED_report == NULL) { 12997c478bd9Sstevel@tonic-gate 13007c478bd9Sstevel@tonic-gate return; 13017c478bd9Sstevel@tonic-gate } 13027c478bd9Sstevel@tonic-gate 13037c478bd9Sstevel@tonic-gate /* 13047c478bd9Sstevel@tonic-gate * Send the request to the hid driver to set LED. 13057c478bd9Sstevel@tonic-gate */ 13067c478bd9Sstevel@tonic-gate 13077c478bd9Sstevel@tonic-gate /* Create an mblk_t */ 13087c478bd9Sstevel@tonic-gate LED_message = allocb(sizeof (uchar_t), BPRI_HI); 13097c478bd9Sstevel@tonic-gate if (LED_message == NULL) { 13107c478bd9Sstevel@tonic-gate kmem_free(LED_report, sizeof (hid_req_t)); 13117c478bd9Sstevel@tonic-gate 13127c478bd9Sstevel@tonic-gate return; 13137c478bd9Sstevel@tonic-gate } 13147c478bd9Sstevel@tonic-gate 13157c478bd9Sstevel@tonic-gate led_state = 0; 13167c478bd9Sstevel@tonic-gate 13177c478bd9Sstevel@tonic-gate /* 13187c478bd9Sstevel@tonic-gate * Set the led state based on the state that is passed in. 13197c478bd9Sstevel@tonic-gate */ 13207c478bd9Sstevel@tonic-gate if (state & LED_NUM_LOCK) { 13217c478bd9Sstevel@tonic-gate led_state |= USB_LED_NUM_LOCK; 13227c478bd9Sstevel@tonic-gate } 13237c478bd9Sstevel@tonic-gate 13247c478bd9Sstevel@tonic-gate if (state & LED_COMPOSE) { 13257c478bd9Sstevel@tonic-gate led_state |= USB_LED_COMPOSE; 13267c478bd9Sstevel@tonic-gate } 13277c478bd9Sstevel@tonic-gate 13287c478bd9Sstevel@tonic-gate if (state & LED_SCROLL_LOCK) { 13297c478bd9Sstevel@tonic-gate led_state |= USB_LED_SCROLL_LOCK; 13307c478bd9Sstevel@tonic-gate } 13317c478bd9Sstevel@tonic-gate 13327c478bd9Sstevel@tonic-gate if (state & LED_CAPS_LOCK) { 13337c478bd9Sstevel@tonic-gate led_state |= USB_LED_CAPS_LOCK; 13347c478bd9Sstevel@tonic-gate } 13357c478bd9Sstevel@tonic-gate 13367c478bd9Sstevel@tonic-gate if (state & LED_KANA) { 13377c478bd9Sstevel@tonic-gate led_state |= USB_LED_KANA; 13387c478bd9Sstevel@tonic-gate } 13397c478bd9Sstevel@tonic-gate 13407c478bd9Sstevel@tonic-gate bcopy((void *)&led_state, (void *)LED_message->b_wptr, 1); 13417c478bd9Sstevel@tonic-gate 13427c478bd9Sstevel@tonic-gate LED_message->b_wptr = LED_message->b_wptr + 1; 13437c478bd9Sstevel@tonic-gate 13447c478bd9Sstevel@tonic-gate USB_DPRINTF_L3(PRINT_MASK_ALL, usbkbm_log_handle, 13457c478bd9Sstevel@tonic-gate "usbkbm: Send Ctrl Request. Data is 0x%x", 13467c478bd9Sstevel@tonic-gate (uchar_t)*LED_message->b_rptr); 13477c478bd9Sstevel@tonic-gate 13487c478bd9Sstevel@tonic-gate LED_report->hid_req_version_no = HID_VERSION_V_0; 13497c478bd9Sstevel@tonic-gate LED_report->hid_req_wValue = REPORT_TYPE_OUTPUT; 13507c478bd9Sstevel@tonic-gate LED_report->hid_req_wLength = sizeof (uchar_t); 13517c478bd9Sstevel@tonic-gate LED_report->hid_req_data = LED_message; 13527c478bd9Sstevel@tonic-gate 13537c478bd9Sstevel@tonic-gate mctlmsg.ioc_cmd = HID_SET_REPORT; 13547c478bd9Sstevel@tonic-gate mctlmsg.ioc_count = sizeof (LED_report); 13557c478bd9Sstevel@tonic-gate mctl_ptr = usba_mk_mctl(mctlmsg, LED_report, sizeof (hid_req_t)); 13567c478bd9Sstevel@tonic-gate if (mctl_ptr != NULL) { 13577c478bd9Sstevel@tonic-gate putnext(usbkbmd->usbkbm_writeq, mctl_ptr); 13587c478bd9Sstevel@tonic-gate } else { 13597c478bd9Sstevel@tonic-gate freemsg(LED_message); 13607c478bd9Sstevel@tonic-gate } 13617c478bd9Sstevel@tonic-gate 13627c478bd9Sstevel@tonic-gate /* 13637c478bd9Sstevel@tonic-gate * We are not waiting for response of HID_SET_REPORT 13647c478bd9Sstevel@tonic-gate * mctl for setting the LED. 13657c478bd9Sstevel@tonic-gate */ 13667c478bd9Sstevel@tonic-gate kmem_free(LED_report, sizeof (hid_req_t)); 13677c478bd9Sstevel@tonic-gate } 13687c478bd9Sstevel@tonic-gate 13697c478bd9Sstevel@tonic-gate 13707c478bd9Sstevel@tonic-gate /* 13717c478bd9Sstevel@tonic-gate * usbkbm_polled_keycheck : 13727c478bd9Sstevel@tonic-gate * This routine is called to determine if there is a scancode that 13737c478bd9Sstevel@tonic-gate * is available for input. This routine is called at poll time and 13747c478bd9Sstevel@tonic-gate * returns a key/state pair to the caller. If there are characters 13757c478bd9Sstevel@tonic-gate * buffered up, the routine returns right away with the key/state pair. 13767c478bd9Sstevel@tonic-gate * Otherwise, the routine calls down to check for characters and returns 13777c478bd9Sstevel@tonic-gate * the first key/state pair if there are any characters pending. 13787c478bd9Sstevel@tonic-gate */ 13797c478bd9Sstevel@tonic-gate static boolean_t 13807c478bd9Sstevel@tonic-gate usbkbm_polled_keycheck(struct kbtrans_hardware *hw, 13817c478bd9Sstevel@tonic-gate int *key, enum keystate *state) 13827c478bd9Sstevel@tonic-gate { 13837c478bd9Sstevel@tonic-gate usbkbm_state_t *usbkbmd; 13847c478bd9Sstevel@tonic-gate uchar_t *buffer; 13857c478bd9Sstevel@tonic-gate unsigned num_keys; 13867c478bd9Sstevel@tonic-gate hid_polled_handle_t hid_polled_handle; 13877c478bd9Sstevel@tonic-gate 13887c478bd9Sstevel@tonic-gate usbkbmd = (usbkbm_state_t *)hw; 13897c478bd9Sstevel@tonic-gate 13907c478bd9Sstevel@tonic-gate /* 13917c478bd9Sstevel@tonic-gate * If there are already characters buffered up, then we are done. 13927c478bd9Sstevel@tonic-gate */ 13937c478bd9Sstevel@tonic-gate if (usbkbmd->usbkbm_polled_buffer_num_characters != 0) { 13947c478bd9Sstevel@tonic-gate 13957c478bd9Sstevel@tonic-gate usbkbm_get_scancode(usbkbmd, key, state); 13967c478bd9Sstevel@tonic-gate 13977c478bd9Sstevel@tonic-gate return (B_TRUE); 13987c478bd9Sstevel@tonic-gate } 13997c478bd9Sstevel@tonic-gate 14007c478bd9Sstevel@tonic-gate hid_polled_handle = 14017c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_hid_callback.hid_polled_input_handle; 14027c478bd9Sstevel@tonic-gate 14037c478bd9Sstevel@tonic-gate num_keys = (usbkbmd->usbkbm_hid_callback.hid_polled_read) 14047c478bd9Sstevel@tonic-gate (hid_polled_handle, &buffer); 14057c478bd9Sstevel@tonic-gate 14067c478bd9Sstevel@tonic-gate /* 14077c478bd9Sstevel@tonic-gate * If we don't get any characters back then indicate that, and we 14087c478bd9Sstevel@tonic-gate * are done. 14097c478bd9Sstevel@tonic-gate */ 14107c478bd9Sstevel@tonic-gate if (num_keys == 0) { 14117c478bd9Sstevel@tonic-gate 14127c478bd9Sstevel@tonic-gate return (B_FALSE); 14137c478bd9Sstevel@tonic-gate } 14147c478bd9Sstevel@tonic-gate 14157c478bd9Sstevel@tonic-gate /* 14167c478bd9Sstevel@tonic-gate * We have a usb packet, so pass this packet to 14177c478bd9Sstevel@tonic-gate * usbkbm_unpack_usb_packet so that it can be broken up into 14187c478bd9Sstevel@tonic-gate * individual key/state values. 14197c478bd9Sstevel@tonic-gate */ 14207c478bd9Sstevel@tonic-gate usbkbm_unpack_usb_packet(usbkbmd, usbkbm_poll_callback, 14217c478bd9Sstevel@tonic-gate buffer, num_keys); 14227c478bd9Sstevel@tonic-gate 14237c478bd9Sstevel@tonic-gate /* 14247c478bd9Sstevel@tonic-gate * If a scancode was returned as a result of this packet, 14257c478bd9Sstevel@tonic-gate * then translate the scancode. 14267c478bd9Sstevel@tonic-gate */ 14277c478bd9Sstevel@tonic-gate if (usbkbmd->usbkbm_polled_buffer_num_characters != 0) { 14287c478bd9Sstevel@tonic-gate 14297c478bd9Sstevel@tonic-gate usbkbm_get_scancode(usbkbmd, key, state); 14307c478bd9Sstevel@tonic-gate 14317c478bd9Sstevel@tonic-gate return (B_TRUE); 14327c478bd9Sstevel@tonic-gate } 14337c478bd9Sstevel@tonic-gate 14347c478bd9Sstevel@tonic-gate return (B_FALSE); 14357c478bd9Sstevel@tonic-gate } 14367c478bd9Sstevel@tonic-gate 14377c478bd9Sstevel@tonic-gate static ushort_t usbkbm_get_state(usbkbm_state_t *usbkbmd) 14387c478bd9Sstevel@tonic-gate { 14397c478bd9Sstevel@tonic-gate ushort_t ret; 14407c478bd9Sstevel@tonic-gate 14417c478bd9Sstevel@tonic-gate ASSERT(usbkbmd->usbkbm_vkbd_type == KB_PC || 14427c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_vkbd_type == KB_USB); 14437c478bd9Sstevel@tonic-gate 14447c478bd9Sstevel@tonic-gate if (usbkbmd->usbkbm_vkbd_type == KB_PC) 14457c478bd9Sstevel@tonic-gate ret = INDEXTO_PC; 14467c478bd9Sstevel@tonic-gate else 14477c478bd9Sstevel@tonic-gate ret = INDEXTO_USB; 14487c478bd9Sstevel@tonic-gate 14497c478bd9Sstevel@tonic-gate return (ret); 14507c478bd9Sstevel@tonic-gate } 14517c478bd9Sstevel@tonic-gate /* 14527c478bd9Sstevel@tonic-gate * usbkbm_streams_callback : 14537c478bd9Sstevel@tonic-gate * This is the routine that is going to be called when unpacking 14547c478bd9Sstevel@tonic-gate * usb packets for normal streams-based input. We pass a pointer 14557c478bd9Sstevel@tonic-gate * to this routine to usbkbm_unpack_usb_packet. This routine will 14567c478bd9Sstevel@tonic-gate * get called with an unpacked key (scancode) and state (press/release). 14577c478bd9Sstevel@tonic-gate * We pass it to the generic keyboard module. 14587c478bd9Sstevel@tonic-gate * 14597c478bd9Sstevel@tonic-gate * 'index' and the function pointers: 14607c478bd9Sstevel@tonic-gate * Map USB scancodes to PC scancodes by lookup table. 14617c478bd9Sstevel@tonic-gate * This fix is mainly meant for x86 platforms. For SPARC systems 14627c478bd9Sstevel@tonic-gate * this fix doesn't change the way in which the scancodes are processed. 14637c478bd9Sstevel@tonic-gate */ 14647c478bd9Sstevel@tonic-gate static void 14657c478bd9Sstevel@tonic-gate usbkbm_streams_callback(usbkbm_state_t *usbkbmd, int key, enum keystate state) 14667c478bd9Sstevel@tonic-gate { 14677c478bd9Sstevel@tonic-gate ushort_t index = usbkbm_get_state(usbkbmd); 14687c478bd9Sstevel@tonic-gate (*usbkbm_xlate[index])(usbkbmd, key, state); 14697c478bd9Sstevel@tonic-gate } 14707c478bd9Sstevel@tonic-gate 14717c478bd9Sstevel@tonic-gate /* 14727c478bd9Sstevel@tonic-gate * Don't do any translations. Send to 'kbtrans' for processing. 14737c478bd9Sstevel@tonic-gate */ 14747c478bd9Sstevel@tonic-gate static void 14757c478bd9Sstevel@tonic-gate usbkbm_wrap_kbtrans(usbkbm_state_t *usbkbmd, int key, enum keystate state) 14767c478bd9Sstevel@tonic-gate { 14777c478bd9Sstevel@tonic-gate kbtrans_streams_key(usbkbmd->usbkbm_kbtrans, key, state); 14787c478bd9Sstevel@tonic-gate } 14797c478bd9Sstevel@tonic-gate 14807c478bd9Sstevel@tonic-gate /* 14817c478bd9Sstevel@tonic-gate * Translate USB scancodes to PC scancodes before sending it to 'kbtrans' 14827c478bd9Sstevel@tonic-gate */ 14837c478bd9Sstevel@tonic-gate void 14847c478bd9Sstevel@tonic-gate usbkbm_usb2pc_xlate(usbkbm_state_t *usbkbmd, int key, enum keystate state) 14857c478bd9Sstevel@tonic-gate { 14867c478bd9Sstevel@tonic-gate key = kbtrans_keycode_usb2pc(key); 14877c478bd9Sstevel@tonic-gate kbtrans_streams_key(usbkbmd->usbkbm_kbtrans, key, state); 14887c478bd9Sstevel@tonic-gate } 14897c478bd9Sstevel@tonic-gate 14907c478bd9Sstevel@tonic-gate /* 14917c478bd9Sstevel@tonic-gate * usbkbm_poll_callback : 14927c478bd9Sstevel@tonic-gate * This is the routine that is going to be called when unpacking 14937c478bd9Sstevel@tonic-gate * usb packets for polled input. We pass a pointer to this routine 14947c478bd9Sstevel@tonic-gate * to usbkbm_unpack_usb_packet. This routine will get called with 14957c478bd9Sstevel@tonic-gate * an unpacked key (scancode) and state (press/release). We will 14967c478bd9Sstevel@tonic-gate * store the key/state pair into a circular buffer so that it can 14977c478bd9Sstevel@tonic-gate * be translated into an ascii key later. 14987c478bd9Sstevel@tonic-gate */ 14997c478bd9Sstevel@tonic-gate static void 15007c478bd9Sstevel@tonic-gate usbkbm_poll_callback(usbkbm_state_t *usbkbmd, int key, enum keystate state) 15017c478bd9Sstevel@tonic-gate { 15027c478bd9Sstevel@tonic-gate /* 15037c478bd9Sstevel@tonic-gate * Check to make sure that the buffer isn't already full 15047c478bd9Sstevel@tonic-gate */ 15057c478bd9Sstevel@tonic-gate if (usbkbmd->usbkbm_polled_buffer_num_characters == 15067c478bd9Sstevel@tonic-gate USB_POLLED_BUFFER_SIZE) { 15077c478bd9Sstevel@tonic-gate 15087c478bd9Sstevel@tonic-gate /* 15097c478bd9Sstevel@tonic-gate * The buffer is full, we will drop this character. 15107c478bd9Sstevel@tonic-gate */ 15117c478bd9Sstevel@tonic-gate return; 15127c478bd9Sstevel@tonic-gate } 15137c478bd9Sstevel@tonic-gate 15147c478bd9Sstevel@tonic-gate /* 15157c478bd9Sstevel@tonic-gate * Save the scancode in the buffer 15167c478bd9Sstevel@tonic-gate */ 15177c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_polled_buffer_head->poll_key = key; 15187c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_polled_buffer_head->poll_state = state; 15197c478bd9Sstevel@tonic-gate 15207c478bd9Sstevel@tonic-gate /* 15217c478bd9Sstevel@tonic-gate * We have one more character in the buffer 15227c478bd9Sstevel@tonic-gate */ 15237c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_polled_buffer_num_characters++; 15247c478bd9Sstevel@tonic-gate 15257c478bd9Sstevel@tonic-gate /* 15267c478bd9Sstevel@tonic-gate * Increment to the next available slot. 15277c478bd9Sstevel@tonic-gate */ 15287c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_polled_buffer_head++; 15297c478bd9Sstevel@tonic-gate 15307c478bd9Sstevel@tonic-gate /* 15317c478bd9Sstevel@tonic-gate * Check to see if the tail has wrapped. 15327c478bd9Sstevel@tonic-gate */ 15337c478bd9Sstevel@tonic-gate if (usbkbmd->usbkbm_polled_buffer_head - 15347c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_polled_scancode_buffer == 15357c478bd9Sstevel@tonic-gate USB_POLLED_BUFFER_SIZE) { 15367c478bd9Sstevel@tonic-gate 15377c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_polled_buffer_head = 15387c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_polled_scancode_buffer; 15397c478bd9Sstevel@tonic-gate } 15407c478bd9Sstevel@tonic-gate } 15417c478bd9Sstevel@tonic-gate 15427c478bd9Sstevel@tonic-gate /* 15437c478bd9Sstevel@tonic-gate * usbkbm_get_scancode : 15447c478bd9Sstevel@tonic-gate * This routine retreives a key/state pair from the circular buffer. 15457c478bd9Sstevel@tonic-gate * The pair was put in the buffer by usbkbm_poll_callback when a 15467c478bd9Sstevel@tonic-gate * USB packet was translated into a key/state by usbkbm_unpack_usb_packet. 15477c478bd9Sstevel@tonic-gate */ 15487c478bd9Sstevel@tonic-gate static void 15497c478bd9Sstevel@tonic-gate usbkbm_get_scancode(usbkbm_state_t *usbkbmd, int *key, enum keystate *state) 15507c478bd9Sstevel@tonic-gate { 15517c478bd9Sstevel@tonic-gate /* 15527c478bd9Sstevel@tonic-gate * Copy the character. 15537c478bd9Sstevel@tonic-gate */ 15547c478bd9Sstevel@tonic-gate *key = usbkbmd->usbkbm_polled_buffer_tail->poll_key; 15557c478bd9Sstevel@tonic-gate *state = usbkbmd->usbkbm_polled_buffer_tail->poll_state; 15567c478bd9Sstevel@tonic-gate 15577c478bd9Sstevel@tonic-gate /* 15587c478bd9Sstevel@tonic-gate * Increment to the next character to be copied from 15597c478bd9Sstevel@tonic-gate * and to. 15607c478bd9Sstevel@tonic-gate */ 15617c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_polled_buffer_tail++; 15627c478bd9Sstevel@tonic-gate 15637c478bd9Sstevel@tonic-gate /* 15647c478bd9Sstevel@tonic-gate * Check to see if the tail has wrapped. 15657c478bd9Sstevel@tonic-gate */ 15667c478bd9Sstevel@tonic-gate if (usbkbmd->usbkbm_polled_buffer_tail - 15677c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_polled_scancode_buffer == 15687c478bd9Sstevel@tonic-gate USB_POLLED_BUFFER_SIZE) { 15697c478bd9Sstevel@tonic-gate 15707c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_polled_buffer_tail = 15717c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_polled_scancode_buffer; 15727c478bd9Sstevel@tonic-gate } 15737c478bd9Sstevel@tonic-gate 15747c478bd9Sstevel@tonic-gate /* 15757c478bd9Sstevel@tonic-gate * We have one less character in the buffer. 15767c478bd9Sstevel@tonic-gate */ 15777c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_polled_buffer_num_characters--; 15787c478bd9Sstevel@tonic-gate } 15797c478bd9Sstevel@tonic-gate 15807c478bd9Sstevel@tonic-gate /* 15817c478bd9Sstevel@tonic-gate * usbkbm_polled_setled : 15827c478bd9Sstevel@tonic-gate * This routine is a place holder. Someday, we may want to allow led 15837c478bd9Sstevel@tonic-gate * state to be updated from within polled mode. 15847c478bd9Sstevel@tonic-gate */ 15857c478bd9Sstevel@tonic-gate /* ARGSUSED */ 15867c478bd9Sstevel@tonic-gate static void 15877c478bd9Sstevel@tonic-gate usbkbm_polled_setled(struct kbtrans_hardware *hw, int led_state) 15887c478bd9Sstevel@tonic-gate { 15897c478bd9Sstevel@tonic-gate /* nothing to do for now */ 15907c478bd9Sstevel@tonic-gate } 15917c478bd9Sstevel@tonic-gate 15927c478bd9Sstevel@tonic-gate /* 15937c478bd9Sstevel@tonic-gate * This is a pass-thru routine to get a character at poll time. 15947c478bd9Sstevel@tonic-gate */ 15957c478bd9Sstevel@tonic-gate static int 15967c478bd9Sstevel@tonic-gate usbkbm_polled_getchar(struct cons_polledio_arg *arg) 15977c478bd9Sstevel@tonic-gate { 15987c478bd9Sstevel@tonic-gate usbkbm_state_t *usbkbmd; 15997c478bd9Sstevel@tonic-gate 16007c478bd9Sstevel@tonic-gate usbkbmd = (usbkbm_state_t *)arg; 16017c478bd9Sstevel@tonic-gate 16027c478bd9Sstevel@tonic-gate return (kbtrans_getchar(usbkbmd->usbkbm_kbtrans)); 16037c478bd9Sstevel@tonic-gate } 16047c478bd9Sstevel@tonic-gate 16057c478bd9Sstevel@tonic-gate /* 16067c478bd9Sstevel@tonic-gate * This is a pass-thru routine to test if character is available for reading 16077c478bd9Sstevel@tonic-gate * at poll time. 16087c478bd9Sstevel@tonic-gate */ 16097c478bd9Sstevel@tonic-gate static boolean_t 16107c478bd9Sstevel@tonic-gate usbkbm_polled_ischar(struct cons_polledio_arg *arg) 16117c478bd9Sstevel@tonic-gate { 16127c478bd9Sstevel@tonic-gate usbkbm_state_t *usbkbmd; 16137c478bd9Sstevel@tonic-gate 16147c478bd9Sstevel@tonic-gate usbkbmd = (usbkbm_state_t *)arg; 16157c478bd9Sstevel@tonic-gate 16167c478bd9Sstevel@tonic-gate return (kbtrans_ischar(usbkbmd->usbkbm_kbtrans)); 16177c478bd9Sstevel@tonic-gate } 16187c478bd9Sstevel@tonic-gate 16197c478bd9Sstevel@tonic-gate /* 16207c478bd9Sstevel@tonic-gate * usbkbm_polled_input_enter : 16217c478bd9Sstevel@tonic-gate * This is a pass-thru initialization routine for the lower layer drivers. 16227c478bd9Sstevel@tonic-gate * This routine is called at poll time to set the state for polled input. 16237c478bd9Sstevel@tonic-gate */ 16247c478bd9Sstevel@tonic-gate static void 16257c478bd9Sstevel@tonic-gate usbkbm_polled_enter(struct cons_polledio_arg *arg) 16267c478bd9Sstevel@tonic-gate { 16277c478bd9Sstevel@tonic-gate usbkbm_state_t *usbkbmd; 16287c478bd9Sstevel@tonic-gate hid_polled_handle_t hid_polled_handle; 16297c478bd9Sstevel@tonic-gate uint_t uindex; 16307c478bd9Sstevel@tonic-gate 16317c478bd9Sstevel@tonic-gate usbkbmd = (usbkbm_state_t *)arg; 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 */ 16397c478bd9Sstevel@tonic-gate for (uindex = 2; uindex < USBKBM_MAXPKTSIZE; 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 16607c478bd9Sstevel@tonic-gate usbkbm_polled_exit(struct cons_polledio_arg *arg) 16617c478bd9Sstevel@tonic-gate { 16627c478bd9Sstevel@tonic-gate usbkbm_state_t *usbkbmd; 16637c478bd9Sstevel@tonic-gate hid_polled_handle_t hid_polled_handle; 16647c478bd9Sstevel@tonic-gate uint_t uindex; 16657c478bd9Sstevel@tonic-gate 16667c478bd9Sstevel@tonic-gate usbkbmd = (usbkbm_state_t *)arg; 16677c478bd9Sstevel@tonic-gate 16687c478bd9Sstevel@tonic-gate /* 16697c478bd9Sstevel@tonic-gate * Before returning to OS mode, copy the contents of 16707c478bd9Sstevel@tonic-gate * usbkbm_lastusbpacket to usbkbm_pendingusbpacket since 16717c478bd9Sstevel@tonic-gate * usbkbm_lastusbpacket field has processed key events 16727c478bd9Sstevel@tonic-gate * of the last POLLED mode usb keyboard packet. 16737c478bd9Sstevel@tonic-gate */ 16747c478bd9Sstevel@tonic-gate for (uindex = 2; uindex < USBKBM_MAXPKTSIZE; uindex ++) { 16757c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_pendingusbpacket[uindex] = 16767c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_lastusbpacket[uindex]; 16777c478bd9Sstevel@tonic-gate 16787c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_lastusbpacket[uindex] = 0; 16797c478bd9Sstevel@tonic-gate } 16807c478bd9Sstevel@tonic-gate 16817c478bd9Sstevel@tonic-gate hid_polled_handle = 16827c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_hid_callback.hid_polled_input_handle; 16837c478bd9Sstevel@tonic-gate 16847c478bd9Sstevel@tonic-gate (void) (usbkbmd->usbkbm_hid_callback.hid_polled_input_exit) 16857c478bd9Sstevel@tonic-gate (hid_polled_handle); 16867c478bd9Sstevel@tonic-gate } 16877c478bd9Sstevel@tonic-gate 16887c478bd9Sstevel@tonic-gate /* 16897c478bd9Sstevel@tonic-gate * usbkbm_unpack_usb_packet : 16907c478bd9Sstevel@tonic-gate * USB key packets contain 8 bytes while in boot protocol mode. 16917c478bd9Sstevel@tonic-gate * The first byte contains bit packed modifier key information. 16927c478bd9Sstevel@tonic-gate * Second byte is reserved. The last 6 bytes contain bytes of 16937c478bd9Sstevel@tonic-gate * currently pressed keys. If a key was not recorded on the 16947c478bd9Sstevel@tonic-gate * previous packet, but present in the current packet, then set 16957c478bd9Sstevel@tonic-gate * state to KEY_PRESSED. If a key was recorded in the previous packet, 16967c478bd9Sstevel@tonic-gate * but not present in the current packet, then state to KEY_RELEASED 16977c478bd9Sstevel@tonic-gate * Follow a similar algorithm for bit packed modifier keys. 16987c478bd9Sstevel@tonic-gate */ 16997c478bd9Sstevel@tonic-gate static void 17007c478bd9Sstevel@tonic-gate usbkbm_unpack_usb_packet(usbkbm_state_t *usbkbmd, process_key_callback_t func, 17017c478bd9Sstevel@tonic-gate uchar_t *usbpacket, int packet_size) 17027c478bd9Sstevel@tonic-gate { 17037c478bd9Sstevel@tonic-gate uchar_t mkb; 17047c478bd9Sstevel@tonic-gate uchar_t lastmkb; 17057c478bd9Sstevel@tonic-gate uchar_t *lastusbpacket = usbkbmd->usbkbm_lastusbpacket; 17067c478bd9Sstevel@tonic-gate int uindex, lindex, rollover; 17077c478bd9Sstevel@tonic-gate 17087c478bd9Sstevel@tonic-gate mkb = usbpacket[0]; 17097c478bd9Sstevel@tonic-gate 17107c478bd9Sstevel@tonic-gate lastmkb = lastusbpacket[0]; 17117c478bd9Sstevel@tonic-gate 17127c478bd9Sstevel@tonic-gate for (uindex = 0; uindex < packet_size; uindex++) { 17137c478bd9Sstevel@tonic-gate 17147c478bd9Sstevel@tonic-gate USB_DPRINTF_L3(PRINT_MASK_PACKET, usbkbm_log_handle, 17157c478bd9Sstevel@tonic-gate " %x ", usbpacket[uindex]); 17167c478bd9Sstevel@tonic-gate } 17177c478bd9Sstevel@tonic-gate 17187c478bd9Sstevel@tonic-gate USB_DPRINTF_L3(PRINT_MASK_PACKET, usbkbm_log_handle, 17197c478bd9Sstevel@tonic-gate " is the usbkeypacket"); 17207c478bd9Sstevel@tonic-gate 17217c478bd9Sstevel@tonic-gate /* check to see if modifier keys are different */ 17227c478bd9Sstevel@tonic-gate if (mkb != lastmkb) { 17237c478bd9Sstevel@tonic-gate 17247c478bd9Sstevel@tonic-gate if ((mkb & USB_LSHIFTBIT) != (lastmkb & USB_LSHIFTBIT)) { 17257c478bd9Sstevel@tonic-gate (*func)(usbkbmd, USB_LSHIFTKEY, (mkb&USB_LSHIFTBIT) ? 17267c478bd9Sstevel@tonic-gate KEY_PRESSED : KEY_RELEASED); 17277c478bd9Sstevel@tonic-gate USB_DPRINTF_L3(PRINT_MASK_ALL, usbkbm_log_handle, 17287c478bd9Sstevel@tonic-gate "unpack: sending USB_LSHIFTKEY"); 17297c478bd9Sstevel@tonic-gate } 17307c478bd9Sstevel@tonic-gate 17317c478bd9Sstevel@tonic-gate if ((mkb & USB_LCTLBIT) != (lastmkb & USB_LCTLBIT)) { 17327c478bd9Sstevel@tonic-gate (*func)(usbkbmd, USB_LCTLCKEY, mkb&USB_LCTLBIT ? 17337c478bd9Sstevel@tonic-gate KEY_PRESSED : KEY_RELEASED); 17347c478bd9Sstevel@tonic-gate } 17357c478bd9Sstevel@tonic-gate 17367c478bd9Sstevel@tonic-gate if ((mkb & USB_LALTBIT) != (lastmkb & USB_LALTBIT)) { 17377c478bd9Sstevel@tonic-gate (*func)(usbkbmd, USB_LALTKEY, mkb&USB_LALTBIT ? 17387c478bd9Sstevel@tonic-gate KEY_PRESSED : KEY_RELEASED); 17397c478bd9Sstevel@tonic-gate } 17407c478bd9Sstevel@tonic-gate 17417c478bd9Sstevel@tonic-gate if ((mkb & USB_LMETABIT) != (lastmkb & USB_LMETABIT)) { 17427c478bd9Sstevel@tonic-gate (*func)(usbkbmd, USB_LMETAKEY, mkb&USB_LMETABIT ? 17437c478bd9Sstevel@tonic-gate KEY_PRESSED : KEY_RELEASED); 17447c478bd9Sstevel@tonic-gate } 17457c478bd9Sstevel@tonic-gate 17467c478bd9Sstevel@tonic-gate if ((mkb & USB_RMETABIT) != (lastmkb & USB_RMETABIT)) { 17477c478bd9Sstevel@tonic-gate (*func)(usbkbmd, USB_RMETAKEY, mkb&USB_RMETABIT ? 17487c478bd9Sstevel@tonic-gate KEY_PRESSED : KEY_RELEASED); 17497c478bd9Sstevel@tonic-gate } 17507c478bd9Sstevel@tonic-gate 17517c478bd9Sstevel@tonic-gate if ((mkb & USB_RALTBIT) != (lastmkb & USB_RALTBIT)) { 17527c478bd9Sstevel@tonic-gate (*func)(usbkbmd, USB_RALTKEY, mkb&USB_RALTBIT ? 17537c478bd9Sstevel@tonic-gate KEY_PRESSED : KEY_RELEASED); 17547c478bd9Sstevel@tonic-gate } 17557c478bd9Sstevel@tonic-gate 17567c478bd9Sstevel@tonic-gate if ((mkb & USB_RCTLBIT) != (lastmkb & USB_RCTLBIT)) { 17577c478bd9Sstevel@tonic-gate (*func)(usbkbmd, USB_RCTLCKEY, mkb&USB_RCTLBIT ? 17587c478bd9Sstevel@tonic-gate KEY_PRESSED : KEY_RELEASED); 17597c478bd9Sstevel@tonic-gate } 17607c478bd9Sstevel@tonic-gate 17617c478bd9Sstevel@tonic-gate if ((mkb & USB_RSHIFTBIT) != (lastmkb & USB_RSHIFTBIT)) { 17627c478bd9Sstevel@tonic-gate (*func)(usbkbmd, USB_RSHIFTKEY, mkb&USB_RSHIFTBIT ? 17637c478bd9Sstevel@tonic-gate KEY_PRESSED : KEY_RELEASED); 17647c478bd9Sstevel@tonic-gate USB_DPRINTF_L3(PRINT_MASK_ALL, usbkbm_log_handle, 17657c478bd9Sstevel@tonic-gate "unpack: sending USB_RSHIFTKEY"); 17667c478bd9Sstevel@tonic-gate } 17677c478bd9Sstevel@tonic-gate } 17687c478bd9Sstevel@tonic-gate 17697c478bd9Sstevel@tonic-gate /* save modifier bits */ 17707c478bd9Sstevel@tonic-gate lastusbpacket[0] = usbpacket[0]; 17717c478bd9Sstevel@tonic-gate 17727c478bd9Sstevel@tonic-gate /* Check Keyboard rollover error. */ 17737c478bd9Sstevel@tonic-gate if (usbpacket[2] == USB_ERRORROLLOVER) { 17747c478bd9Sstevel@tonic-gate rollover = 1; 17757c478bd9Sstevel@tonic-gate for (uindex = 3; uindex < packet_size; 17767c478bd9Sstevel@tonic-gate uindex++) { 17777c478bd9Sstevel@tonic-gate if (usbpacket[uindex] != USB_ERRORROLLOVER) { 17787c478bd9Sstevel@tonic-gate rollover = 0; 17797c478bd9Sstevel@tonic-gate break; 17807c478bd9Sstevel@tonic-gate } 17817c478bd9Sstevel@tonic-gate } 17827c478bd9Sstevel@tonic-gate if (rollover) { 17837c478bd9Sstevel@tonic-gate USB_DPRINTF_L3(PRINT_MASK_ALL, usbkbm_log_handle, 17847c478bd9Sstevel@tonic-gate "unpack: errorrollover"); 17857c478bd9Sstevel@tonic-gate return; 17867c478bd9Sstevel@tonic-gate } 17877c478bd9Sstevel@tonic-gate } 17887c478bd9Sstevel@tonic-gate 17897c478bd9Sstevel@tonic-gate /* check for released keys */ 17907c478bd9Sstevel@tonic-gate for (lindex = 2; lindex < packet_size; lindex++) { 17917c478bd9Sstevel@tonic-gate int released = 1; 17927c478bd9Sstevel@tonic-gate 17937c478bd9Sstevel@tonic-gate if (lastusbpacket[lindex] == 0) { 17947c478bd9Sstevel@tonic-gate continue; 17957c478bd9Sstevel@tonic-gate } 17967c478bd9Sstevel@tonic-gate for (uindex = 2; uindex < packet_size; uindex++) 17977c478bd9Sstevel@tonic-gate if (usbpacket[uindex] == lastusbpacket[lindex]) { 17987c478bd9Sstevel@tonic-gate released = 0; 17997c478bd9Sstevel@tonic-gate break; 18007c478bd9Sstevel@tonic-gate } 18017c478bd9Sstevel@tonic-gate if (released) { 18027c478bd9Sstevel@tonic-gate (*func)(usbkbmd, lastusbpacket[lindex], KEY_RELEASED); 18037c478bd9Sstevel@tonic-gate } 18047c478bd9Sstevel@tonic-gate } 18057c478bd9Sstevel@tonic-gate 18067c478bd9Sstevel@tonic-gate /* check for new presses */ 18077c478bd9Sstevel@tonic-gate for (uindex = 2; uindex < packet_size; uindex++) { 18087c478bd9Sstevel@tonic-gate int newkey = 1; 18097c478bd9Sstevel@tonic-gate 18107c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_pendingusbpacket[uindex] = usbpacket[uindex]; 18117c478bd9Sstevel@tonic-gate 18127c478bd9Sstevel@tonic-gate if (usbpacket[uindex] == 0) { 18137c478bd9Sstevel@tonic-gate continue; 18147c478bd9Sstevel@tonic-gate } 18157c478bd9Sstevel@tonic-gate 18167c478bd9Sstevel@tonic-gate for (lindex = 2; lindex < packet_size; lindex++) { 18177c478bd9Sstevel@tonic-gate if (usbpacket[uindex] == lastusbpacket[lindex]) { 18187c478bd9Sstevel@tonic-gate newkey = 0; 18197c478bd9Sstevel@tonic-gate break; 18207c478bd9Sstevel@tonic-gate } 18217c478bd9Sstevel@tonic-gate } 18227c478bd9Sstevel@tonic-gate 18237c478bd9Sstevel@tonic-gate if (newkey) { 18247c478bd9Sstevel@tonic-gate /* 18257c478bd9Sstevel@tonic-gate * Modifier keys can be present as part of both the 18267c478bd9Sstevel@tonic-gate * first byte and as separate key bytes. In the sec- 18277c478bd9Sstevel@tonic-gate * ond case ignore it. 18287c478bd9Sstevel@tonic-gate */ 18297c478bd9Sstevel@tonic-gate 18307c478bd9Sstevel@tonic-gate if (!usbkbm_is_modkey(usbpacket[uindex])) { 18317c478bd9Sstevel@tonic-gate (*func)(usbkbmd, usbpacket[uindex], 18327c478bd9Sstevel@tonic-gate KEY_PRESSED); 18337c478bd9Sstevel@tonic-gate } else { 18347c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_pendingusbpacket[uindex] = 0; 18357c478bd9Sstevel@tonic-gate 18367c478bd9Sstevel@tonic-gate continue; 18377c478bd9Sstevel@tonic-gate } 18387c478bd9Sstevel@tonic-gate } 18397c478bd9Sstevel@tonic-gate } 18407c478bd9Sstevel@tonic-gate 18417c478bd9Sstevel@tonic-gate /* 18427c478bd9Sstevel@tonic-gate * Copy the processed key events of the current usb keyboard 18437c478bd9Sstevel@tonic-gate * packet, which is saved in the usbkbm_pendingusbpacket field 18447c478bd9Sstevel@tonic-gate * to the usbkbm_lastusbpacket field. 18457c478bd9Sstevel@tonic-gate */ 18467c478bd9Sstevel@tonic-gate for (uindex = 2; uindex < USBKBM_MAXPKTSIZE; uindex++) { 18477c478bd9Sstevel@tonic-gate lastusbpacket[uindex] = 18487c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_pendingusbpacket[uindex]; 18497c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_pendingusbpacket[uindex] = 0; 18507c478bd9Sstevel@tonic-gate } 18517c478bd9Sstevel@tonic-gate } 18527c478bd9Sstevel@tonic-gate 18537c478bd9Sstevel@tonic-gate static boolean_t 18547c478bd9Sstevel@tonic-gate usbkbm_is_modkey(uchar_t key) 18557c478bd9Sstevel@tonic-gate { 18567c478bd9Sstevel@tonic-gate 18577c478bd9Sstevel@tonic-gate switch (key) { 18587c478bd9Sstevel@tonic-gate 18597c478bd9Sstevel@tonic-gate case USB_LSHIFTKEY: 18607c478bd9Sstevel@tonic-gate case USB_LCTLCKEY: 18617c478bd9Sstevel@tonic-gate case USB_LALTKEY: 18627c478bd9Sstevel@tonic-gate case USB_LMETAKEY: 18637c478bd9Sstevel@tonic-gate case USB_RCTLCKEY: 18647c478bd9Sstevel@tonic-gate case USB_RSHIFTKEY: 18657c478bd9Sstevel@tonic-gate case USB_RMETAKEY: 18667c478bd9Sstevel@tonic-gate case USB_RALTKEY: 18677c478bd9Sstevel@tonic-gate 18687c478bd9Sstevel@tonic-gate return (B_TRUE); 18697c478bd9Sstevel@tonic-gate 18707c478bd9Sstevel@tonic-gate default: 18717c478bd9Sstevel@tonic-gate 18727c478bd9Sstevel@tonic-gate break; 18737c478bd9Sstevel@tonic-gate } 18747c478bd9Sstevel@tonic-gate 18757c478bd9Sstevel@tonic-gate return (B_FALSE); 18767c478bd9Sstevel@tonic-gate } 18777c478bd9Sstevel@tonic-gate 18787c478bd9Sstevel@tonic-gate /* 18797c478bd9Sstevel@tonic-gate * usbkbm_reioctl : 18807c478bd9Sstevel@tonic-gate * This function is set up as call-back function should an ioctl fail. 18817c478bd9Sstevel@tonic-gate * It retries the ioctl 18827c478bd9Sstevel@tonic-gate */ 18837c478bd9Sstevel@tonic-gate static void 18847c478bd9Sstevel@tonic-gate usbkbm_reioctl(void *arg) 18857c478bd9Sstevel@tonic-gate { 18867c478bd9Sstevel@tonic-gate usbkbm_state_t *usbkbmd; 18877c478bd9Sstevel@tonic-gate mblk_t *mp; 18887c478bd9Sstevel@tonic-gate 18897c478bd9Sstevel@tonic-gate usbkbmd = (usbkbm_state_t *)arg; 18907c478bd9Sstevel@tonic-gate 18917c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_streams_bufcallid = 0; 18927c478bd9Sstevel@tonic-gate 18937c478bd9Sstevel@tonic-gate if ((mp = usbkbmd->usbkbm_streams_iocpending) != NULL) { 18947c478bd9Sstevel@tonic-gate 18957c478bd9Sstevel@tonic-gate /* not pending any more */ 18967c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_streams_iocpending = NULL; 18977c478bd9Sstevel@tonic-gate 18987c478bd9Sstevel@tonic-gate (void) usbkbm_ioctl(usbkbmd->usbkbm_writeq, mp); 18997c478bd9Sstevel@tonic-gate } 19007c478bd9Sstevel@tonic-gate } 19017c478bd9Sstevel@tonic-gate 19027c478bd9Sstevel@tonic-gate 19037c478bd9Sstevel@tonic-gate /* 19047c478bd9Sstevel@tonic-gate * usbkbm_set_protocol 19057c478bd9Sstevel@tonic-gate * Issue an M_CTL to hid to set the desired protocol 19067c478bd9Sstevel@tonic-gate */ 19077c478bd9Sstevel@tonic-gate static int 19087c478bd9Sstevel@tonic-gate usbkbm_set_protocol(usbkbm_state_t *usbkbmd, uint16_t protocol) 19097c478bd9Sstevel@tonic-gate { 19107c478bd9Sstevel@tonic-gate struct iocblk mctlmsg; 19117c478bd9Sstevel@tonic-gate hid_req_t buf; 19127c478bd9Sstevel@tonic-gate mblk_t *mctl_ptr; 19137c478bd9Sstevel@tonic-gate size_t len = sizeof (buf); 19147c478bd9Sstevel@tonic-gate queue_t *q = usbkbmd->usbkbm_readq; 19157c478bd9Sstevel@tonic-gate 19167c478bd9Sstevel@tonic-gate mctlmsg.ioc_cmd = HID_SET_PROTOCOL; 19177c478bd9Sstevel@tonic-gate mctlmsg.ioc_count = 0; 19187c478bd9Sstevel@tonic-gate buf.hid_req_version_no = HID_VERSION_V_0; 19197c478bd9Sstevel@tonic-gate buf.hid_req_wValue = protocol; 19207c478bd9Sstevel@tonic-gate buf.hid_req_wLength = 0; 19217c478bd9Sstevel@tonic-gate buf.hid_req_data = NULL; 19227c478bd9Sstevel@tonic-gate mctl_ptr = usba_mk_mctl(mctlmsg, &buf, len); 19237c478bd9Sstevel@tonic-gate if (mctl_ptr == NULL) { 19247c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_flags = 0; 19257c478bd9Sstevel@tonic-gate (void) kbtrans_streams_fini(usbkbmd->usbkbm_kbtrans); 19267c478bd9Sstevel@tonic-gate qprocsoff(q); 19277c478bd9Sstevel@tonic-gate kmem_free(usbkbmd, sizeof (usbkbm_state_t)); 19287c478bd9Sstevel@tonic-gate 19297c478bd9Sstevel@tonic-gate return (ENOMEM); 19307c478bd9Sstevel@tonic-gate } 19317c478bd9Sstevel@tonic-gate 19327c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_flags |= USBKBM_QWAIT; 19337c478bd9Sstevel@tonic-gate putnext(usbkbmd->usbkbm_writeq, mctl_ptr); 19347c478bd9Sstevel@tonic-gate 19357c478bd9Sstevel@tonic-gate while (usbkbmd->usbkbm_flags & USBKBM_QWAIT) { 19367c478bd9Sstevel@tonic-gate if (qwait_sig(q) == 0) { 19377c478bd9Sstevel@tonic-gate usbkbmd->usbkbm_flags = 0; 19387c478bd9Sstevel@tonic-gate (void) kbtrans_streams_fini(usbkbmd->usbkbm_kbtrans); 19397c478bd9Sstevel@tonic-gate qprocsoff(q); 19407c478bd9Sstevel@tonic-gate kmem_free(usbkbmd, sizeof (usbkbm_state_t)); 19417c478bd9Sstevel@tonic-gate 19427c478bd9Sstevel@tonic-gate return (EINTR); 19437c478bd9Sstevel@tonic-gate } 19447c478bd9Sstevel@tonic-gate } 19457c478bd9Sstevel@tonic-gate 19467c478bd9Sstevel@tonic-gate return (0); 19477c478bd9Sstevel@tonic-gate } 1948*6d9a41ffSqz150045 1949*6d9a41ffSqz150045 1950*6d9a41ffSqz150045 /* 1951*6d9a41ffSqz150045 * usbkbm_get_vid_pid 1952*6d9a41ffSqz150045 * Issue a M_CTL to hid to get the device info 1953*6d9a41ffSqz150045 */ 1954*6d9a41ffSqz150045 static int 1955*6d9a41ffSqz150045 usbkbm_get_vid_pid(usbkbm_state_t *usbkbmd) 1956*6d9a41ffSqz150045 { 1957*6d9a41ffSqz150045 struct iocblk mctlmsg; 1958*6d9a41ffSqz150045 mblk_t *mctl_ptr; 1959*6d9a41ffSqz150045 queue_t *q = usbkbmd->usbkbm_readq; 1960*6d9a41ffSqz150045 1961*6d9a41ffSqz150045 mctlmsg.ioc_cmd = HID_GET_VID_PID; 1962*6d9a41ffSqz150045 mctlmsg.ioc_count = 0; 1963*6d9a41ffSqz150045 1964*6d9a41ffSqz150045 mctl_ptr = usba_mk_mctl(mctlmsg, NULL, 0); 1965*6d9a41ffSqz150045 if (mctl_ptr == NULL) { 1966*6d9a41ffSqz150045 (void) kbtrans_streams_fini(usbkbmd->usbkbm_kbtrans); 1967*6d9a41ffSqz150045 qprocsoff(q); 1968*6d9a41ffSqz150045 kmem_free(usbkbmd, sizeof (usbkbm_state_t)); 1969*6d9a41ffSqz150045 1970*6d9a41ffSqz150045 return (ENOMEM); 1971*6d9a41ffSqz150045 } 1972*6d9a41ffSqz150045 1973*6d9a41ffSqz150045 putnext(usbkbmd->usbkbm_writeq, mctl_ptr); 1974*6d9a41ffSqz150045 usbkbmd->usbkbm_flags |= USBKBM_QWAIT; 1975*6d9a41ffSqz150045 while (usbkbmd->usbkbm_flags & USBKBM_QWAIT) { 1976*6d9a41ffSqz150045 if (qwait_sig(q) == 0) { 1977*6d9a41ffSqz150045 usbkbmd->usbkbm_flags = 0; 1978*6d9a41ffSqz150045 (void) kbtrans_streams_fini(usbkbmd->usbkbm_kbtrans); 1979*6d9a41ffSqz150045 qprocsoff(q); 1980*6d9a41ffSqz150045 kmem_free(usbkbmd, sizeof (usbkbm_state_t)); 1981*6d9a41ffSqz150045 1982*6d9a41ffSqz150045 return (EINTR); 1983*6d9a41ffSqz150045 } 1984*6d9a41ffSqz150045 } 1985*6d9a41ffSqz150045 1986*6d9a41ffSqz150045 return (0); 1987*6d9a41ffSqz150045 } 1988