1 /* $NetBSD: btnmgr.c,v 1.1 2001/02/22 18:37:54 uch Exp $ */ 2 3 /*- 4 * Copyright (c) 1999 5 * Shin Takemura and PocketBSD Project. 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 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by the PocketBSD project 18 * and its contributors. 19 * 4. Neither the name of the project nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 * 35 */ 36 #define BTNMGRDEBUG 37 38 #include <sys/param.h> 39 #include <sys/systm.h> 40 #include <sys/ioctl.h> 41 #include <sys/conf.h> 42 #include <sys/device.h> 43 #include <sys/malloc.h> 44 #include <sys/kernel.h> 45 46 #include "opt_wsdisplay_compat.h" 47 #include <dev/wscons/wsconsio.h> 48 #include <dev/wscons/wskbdvar.h> 49 #include <dev/wscons/wsksymdef.h> 50 #ifdef WSDISPLAY_COMPAT_RAWKBD 51 #include <dev/hpc/pckbd_encode.h> 52 #endif 53 54 #include <machine/bus.h> 55 #include <machine/autoconf.h> 56 #include <machine/config_hook.h> 57 58 #ifdef BTNMGRDEBUG 59 #ifndef BTNMGRDEBUG_CONF 60 #define BTNMGRDEBUG_CONF 0 61 #endif 62 int btnmgr_debug = BTNMGRDEBUG_CONF; 63 #define DPRINTF(arg) if (btnmgr_debug) printf arg; 64 #define DPRINTFN(n, arg) if (btnmgr_debug > (n)) printf arg; 65 #else 66 #define DPRINTF(arg) 67 #define DPRINTFN(n, arg) 68 #endif 69 70 cdev_decl(btnmgr); 71 72 struct btnmgr_softc { 73 struct device sc_dev; 74 config_hook_tag sc_hook_tag; 75 int sc_enabled; 76 struct device *sc_wskbddev; 77 #ifdef WSDISPLAY_COMPAT_RAWKBD 78 int sc_rawkbd; 79 #endif 80 }; 81 82 /* 83 static struct btnmgr_softc *the_btnmgr_sc; 84 */ 85 86 /* 87 void btnmgrattach __P((int)); 88 */ 89 int btnmgrmatch __P((struct device *, struct cfdata *, void *)); 90 void btnmgrattach __P((struct device *, struct device *, void *)); 91 char* btnmgr_name __P((long)); 92 static int btnmgr_hook __P((void *, int, long, void *)); 93 94 95 /* 96 * global/static data 97 */ 98 struct cfattach btnmgr_ca = { 99 sizeof(struct btnmgr_softc), btnmgrmatch, btnmgrattach 100 }; 101 102 /* wskbd accessopts */ 103 int btnmgr_wskbd_enable __P((void *, int)); 104 void btnmgr_wskbd_set_leds __P((void *, int)); 105 int btnmgr_wskbd_ioctl __P((void *, u_long, caddr_t, int, struct proc *)); 106 107 const struct wskbd_accessops btnmgr_wskbd_accessops = { 108 btnmgr_wskbd_enable, 109 btnmgr_wskbd_set_leds, 110 btnmgr_wskbd_ioctl, 111 }; 112 113 /* button config: index by buttun event id */ 114 static const struct { 115 int kevent; 116 int keycode; 117 char *name; 118 } button_config[] = { 119 /* id kevent keycode name */ 120 [CONFIG_HOOK_BUTTONEVENT_POWER] = { 0, 0, "Power" }, 121 [CONFIG_HOOK_BUTTONEVENT_OK] = { 1, 28, "OK" }, 122 [CONFIG_HOOK_BUTTONEVENT_CANCEL] = { 1, 1, "Cancel" }, 123 [CONFIG_HOOK_BUTTONEVENT_UP] = { 1, 72, "Up" }, 124 [CONFIG_HOOK_BUTTONEVENT_DOWN] = { 1, 80, "Down" }, 125 [CONFIG_HOOK_BUTTONEVENT_REC] = { 0, 0, "Rec" }, 126 [CONFIG_HOOK_BUTTONEVENT_COVER] = { 0, 0, "Cover" }, 127 [CONFIG_HOOK_BUTTONEVENT_LIGHT] = { 1, 57, "Light" }, 128 [CONFIG_HOOK_BUTTONEVENT_CONTRAST] = { 0, 0, "Contrast" }, 129 [CONFIG_HOOK_BUTTONEVENT_APP0] = { 1, 67, "Application 0" }, 130 [CONFIG_HOOK_BUTTONEVENT_APP1] = { 1, 68, "Application 1" }, 131 [CONFIG_HOOK_BUTTONEVENT_APP2] = { 1, 87, "Application 2" }, 132 [CONFIG_HOOK_BUTTONEVENT_APP3] = { 1, 88, "Application 3" }, 133 }; 134 static const int n_button_config = 135 sizeof(button_config) / sizeof(*button_config); 136 137 #define KC(n) KS_KEYCODE(n) 138 static const keysym_t btnmgr_keydesc_default[] = { 139 /* pos normal shifted */ 140 KC(1), KS_Escape, 141 KC(28), KS_Return, 142 KC(57), KS_Cmd, KS_Cmd_BacklightToggle, 143 KC(67), KS_f9, 144 KC(68), KS_f10, 145 KC(72), KS_KP_Up, 146 KC(80), KS_KP_Down, 147 KC(87), KS_f11, 148 KC(88), KS_f12, 149 }; 150 #undef KC 151 #define KBD_MAP(name, base, map) \ 152 { name, base, sizeof(map)/sizeof(keysym_t), map } 153 const struct wscons_keydesc btnmgr_keydesctab[] = { 154 KBD_MAP(KB_US, 0, btnmgr_keydesc_default), 155 {0, 0, 0, 0} 156 }; 157 #undef KBD_MAP 158 159 struct wskbd_mapdata btnmgr_keymapdata = { 160 btnmgr_keydesctab, 161 KB_US, /* XXX, This is bad idea... */ 162 }; 163 164 /* 165 * function bodies 166 */ 167 int 168 btnmgrmatch(parent, match, aux) 169 struct device *parent; 170 struct cfdata *match; 171 void *aux; 172 { 173 struct mainbus_attach_args *ma = aux; 174 175 if (strcmp(ma->ma_name, match->cf_driver->cd_name)) 176 return 0; 177 178 return (1); 179 } 180 181 void 182 btnmgrattach(parent, self, aux) 183 struct device *parent, *self; 184 void *aux; 185 { 186 int id; 187 struct btnmgr_softc *sc = (struct btnmgr_softc *)self; 188 struct wskbddev_attach_args wa; 189 190 printf("\n"); 191 192 /* 193 * install button event listener 194 */ 195 for (id = 0; id <= CONFIG_HOOK_MAX_ID; id++) 196 if (button_config[id].name != NULL) 197 sc->sc_hook_tag = config_hook(CONFIG_HOOK_BUTTONEVENT, 198 id, CONFIG_HOOK_SHARE, 199 btnmgr_hook, sc); 200 201 /* 202 * attach wskbd 203 */ 204 wa.console = 0; 205 wa.keymap = &btnmgr_keymapdata; 206 wa.accessops = &btnmgr_wskbd_accessops; 207 wa.accesscookie = sc; 208 209 sc->sc_wskbddev = config_found(self, &wa, wskbddevprint); 210 } 211 212 static int 213 btnmgr_hook(ctx, type, id, msg) 214 void *ctx; 215 int type; 216 long id; 217 void *msg; 218 { 219 struct btnmgr_softc *sc = ctx; 220 221 DPRINTF(("%s button: %s\n", btnmgr_name(id), msg ? "ON" : "OFF")); 222 223 if (button_config[id].kevent) { 224 u_int evtype; 225 evtype = msg ? WSCONS_EVENT_KEY_DOWN : WSCONS_EVENT_KEY_UP; 226 #ifdef WSDISPLAY_COMPAT_RAWKBD 227 if (sc->sc_rawkbd) { 228 int n; 229 u_char data[16]; 230 n = pckbd_encode(evtype, button_config[id].keycode, 231 data); 232 wskbd_rawinput(sc->sc_wskbddev, data, n); 233 } else 234 #endif 235 wskbd_input(sc->sc_wskbddev, evtype, 236 button_config[id].keycode); 237 } 238 239 if (id == CONFIG_HOOK_BUTTONEVENT_POWER && msg) 240 config_hook_call(CONFIG_HOOK_PMEVENT, 241 CONFIG_HOOK_PMEVENT_SUSPENDREQ, NULL); 242 243 244 return (0); 245 } 246 247 char* 248 btnmgr_name(id) 249 long id; 250 { 251 if (id < n_button_config) 252 return button_config[id].name; 253 return ("unknown"); 254 } 255 256 int 257 btnmgr_wskbd_enable(scx, on) 258 void *scx; 259 int on; 260 { 261 struct btnmgr_softc *sc = scx; 262 263 if (on) { 264 if (sc->sc_enabled) 265 return (EBUSY); 266 sc->sc_enabled = 1; 267 } else { 268 sc->sc_enabled = 0; 269 } 270 271 return (0); 272 } 273 274 void 275 btnmgr_wskbd_set_leds(scx, leds) 276 void *scx; 277 int leds; 278 { 279 /* 280 * We have nothing to do. 281 */ 282 } 283 284 int 285 btnmgr_wskbd_ioctl(scx, cmd, data, flag, p) 286 void *scx; 287 u_long cmd; 288 caddr_t data; 289 int flag; 290 struct proc *p; 291 { 292 #ifdef WSDISPLAY_COMPAT_RAWKBD 293 struct btnmgr_softc *sc = scx; 294 #endif 295 switch (cmd) { 296 case WSKBDIO_GTYPE: 297 *(int *)data = WSKBD_TYPE_HPC_BTN; 298 return 0; 299 case WSKBDIO_SETLEDS: 300 DPRINTF(("%s(%d): no LED\n", __FILE__, __LINE__)); 301 return 0; 302 case WSKBDIO_GETLEDS: 303 DPRINTF(("%s(%d): no LED\n", __FILE__, __LINE__)); 304 *(int *)data = 0; 305 return (0); 306 #ifdef WSDISPLAY_COMPAT_RAWKBD 307 case WSKBDIO_SETMODE: 308 sc->sc_rawkbd = (*(int *)data == WSKBD_RAW); 309 DPRINTF(("%s(%d): rawkbd is %s\n", __FILE__, __LINE__, 310 sc->sc_rawkbd ? "on" : "off")); 311 return (0); 312 #endif 313 } 314 return (-1); 315 } 316 317 #ifdef notyet 318 int 319 btnmgropen(dev, flag, mode, p) 320 dev_t dev; 321 int flag, mode; 322 struct proc *p; 323 { 324 return (EINVAL); 325 } 326 327 int 328 btnmgrclose(dev, flag, mode, p) 329 dev_t dev; 330 int flag, mode; 331 struct proc *p; 332 { 333 return (EINVAL); 334 } 335 336 int 337 btnmgrread(dev, uio, flag) 338 dev_t dev; 339 struct uio *uio; 340 int flag; 341 { 342 return (EINVAL); 343 } 344 345 int 346 btnmgrwrite(dev, uio, flag) 347 dev_t dev; 348 struct uio *uio; 349 int flag; 350 { 351 return (EINVAL); 352 } 353 354 int 355 btnmgrioctl(dev, cmd, data, flag, p) 356 dev_t dev; 357 u_long cmd; 358 caddr_t data; 359 int flag; 360 struct proc *p; 361 { 362 return (EINVAL); 363 } 364 #endif /* notyet */ 365