1 /* $NetBSD: adb_bt.c,v 1.4 2008/04/29 06:53:02 martin Exp $ */ 2 3 /*- 4 * Copyright (c) 2006 Michael Lorenz 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 #include <sys/cdefs.h> 30 __KERNEL_RCSID(0, "$NetBSD: adb_bt.c,v 1.4 2008/04/29 06:53:02 martin Exp $"); 31 32 #include <sys/param.h> 33 #include <sys/systm.h> 34 #include <sys/kernel.h> 35 #include <sys/device.h> 36 #include <sys/proc.h> 37 38 #include <dev/wscons/wsconsio.h> 39 #include <dev/wscons/wskbdvar.h> 40 #include <dev/wscons/wsksymdef.h> 41 #include <dev/wscons/wsksymvar.h> 42 #include <dev/wscons/wsmousevar.h> 43 44 #include <dev/sysmon/sysmonvar.h> 45 #include <dev/sysmon/sysmon_taskq.h> 46 47 #include <machine/autoconf.h> 48 #include <machine/keyboard.h> 49 #include <machine/adbsys.h> 50 51 #include <dev/adb/adbvar.h> 52 #include <dev/adb/adb_keymap.h> 53 54 #include "opt_wsdisplay_compat.h" 55 #include "adbdebug.h" 56 57 #ifdef ADBBT_DEBUG 58 #define DPRINTF printf 59 #else 60 #define DPRINTF while (0) printf 61 #endif 62 63 #define BT_VOL_UP 0x06 64 #define BT_VOL_DOWN 0x07 65 #define BT_VOL_MUTE 0x08 66 #define BT_BRT_UP 0x09 67 #define BT_BRT_DOWN 0x0a 68 #define BT_EJECT 0x0b 69 #define BT_F7 0x0c 70 #define BT_NUMLOCK 0x7f 71 72 static int adbbt_match(device_t, cfdata_t, void *); 73 static void adbbt_attach(device_t, device_t, void *); 74 75 struct adbbt_softc { 76 device_t sc_dev; 77 struct adb_device *sc_adbdev; 78 struct adb_bus_accessops *sc_ops; 79 device_t sc_wskbddev; 80 int sc_msg_len; 81 int sc_event; 82 int sc_poll; 83 int sc_polled_chars; 84 int sc_rawkbd; 85 uint8_t sc_buffer[16]; 86 uint8_t sc_pollbuf[16]; 87 uint8_t sc_trans[16]; 88 uint8_t sc_us; 89 }; 90 91 /* Driver definition. */ 92 CFATTACH_DECL_NEW(adbbt, sizeof(struct adbbt_softc), 93 adbbt_match, adbbt_attach, NULL, NULL); 94 95 extern struct cfdriver adbbt_cd; 96 97 static int adbbt_enable(void *, int); 98 static void adbbt_set_leds(void *, int); 99 static int adbbt_ioctl(void *, u_long, void *, int, struct lwp *); 100 static void adbbt_handler(void *, int, uint8_t *); 101 102 struct wskbd_accessops adbbt_accessops = { 103 adbbt_enable, 104 adbbt_set_leds, 105 adbbt_ioctl, 106 }; 107 108 struct wskbd_mapdata adbbt_keymapdata = { 109 akbd_keydesctab, 110 #ifdef AKBD_LAYOUT 111 AKBD_LAYOUT, 112 #else 113 KB_US, 114 #endif 115 }; 116 117 static int 118 adbbt_match(device_t parent, cfdata_t cf, void *aux) 119 { 120 struct adb_attach_args *aaa = aux; 121 122 if ((aaa->dev->original_addr == ADBADDR_MISC) && 123 (aaa->dev->handler_id == 0x1f)) 124 return 100; 125 else 126 return 0; 127 } 128 129 static void 130 adbbt_attach(device_t parent, device_t self, void *aux) 131 { 132 struct adbbt_softc *sc = device_private(self); 133 struct adb_attach_args *aaa = aux; 134 struct wskbddev_attach_args a; 135 136 sc->sc_dev = self; 137 sc->sc_ops = aaa->ops; 138 sc->sc_adbdev = aaa->dev; 139 sc->sc_adbdev->cookie = sc; 140 sc->sc_adbdev->handler = adbbt_handler; 141 sc->sc_us = ADBTALK(sc->sc_adbdev->current_addr, 0); 142 143 sc->sc_msg_len = 0; 144 sc->sc_rawkbd = 0; 145 sc->sc_trans[6] = 96; /* F5 */ 146 sc->sc_trans[7] = 118; /* F4 */ 147 sc->sc_trans[8] = 99; /* F3 */ 148 sc->sc_trans[9] = 120; /* F2 */ 149 sc->sc_trans[10] = 122; /* F1 */ 150 sc->sc_trans[11] = 111; /* F12 */ 151 152 printf(" addr %d: button device\n", sc->sc_adbdev->current_addr); 153 154 a.console = 0; 155 a.keymap = &adbbt_keymapdata; 156 a.accessops = &adbbt_accessops; 157 a.accesscookie = sc; 158 159 sc->sc_wskbddev = config_found_ia(self, "wskbddev", &a, wskbddevprint); 160 } 161 162 static void 163 adbbt_handler(void *cookie, int len, uint8_t *data) 164 { 165 struct adbbt_softc *sc = cookie; 166 int type; 167 uint8_t k, keyval, scancode; 168 169 #ifdef ADBBT_DEBUG 170 int i; 171 printf("%s: %02x - ", device_xname(&sc->sc_dev), sc->sc_us); 172 for (i = 0; i < len; i++) { 173 printf(" %02x", data[i]); 174 } 175 printf("\n"); 176 #endif 177 k = data[2]; 178 keyval = ADBK_KEYVAL(k); 179 if ((keyval < 6) || (keyval > 0x0c)) 180 return; 181 scancode = sc->sc_trans[keyval]; 182 183 #ifdef WSDISPLAY_COMPAT_RAWKBD 184 if (sc->sc_rawkbd) { 185 char cbuf[2]; 186 int s; 187 188 cbuf[0] = scancode | (k & 0x80); 189 190 s = spltty(); 191 wskbd_rawinput(sc->sc_wskbddev, cbuf, 1); 192 splx(s); 193 } else { 194 #endif 195 196 /* normal event */ 197 type = ADBK_PRESS(k) ? 198 WSCONS_EVENT_KEY_DOWN : WSCONS_EVENT_KEY_UP; 199 wskbd_input(sc->sc_wskbddev, type, scancode); 200 #ifdef WSDISPLAY_COMPAT_RAWKBD 201 } 202 #endif 203 } 204 205 static void 206 adbbt_set_leds(void *cookie, int leds) 207 { 208 /* we have no LEDs */ 209 } 210 211 static int 212 adbbt_enable(void *v, int on) 213 { 214 return 0; 215 } 216 217 static int 218 adbbt_ioctl(void *v, u_long cmd, void *data, int flag, struct lwp *l) 219 { 220 #ifdef WSDISPLAY_COMPAT_RAWKBD 221 struct adbbt_softc *sc = (struct adbbt_softc *) v; 222 #endif 223 224 switch (cmd) { 225 226 case WSKBDIO_GTYPE: 227 *(int *)data = WSKBD_TYPE_ADB; 228 return 0; 229 #ifdef WSDISPLAY_COMPAT_RAWKBD 230 case WSKBDIO_SETMODE: 231 sc->sc_rawkbd = *(int *)data == WSKBD_RAW; 232 return 0; 233 #endif 234 } 235 236 return EPASSTHROUGH; 237 } 238