1/* $NetBSD: lk201_ws.c,v 1.7 2005/12/11 12:21:20 christos Exp $ */ 2 3/* 4 * Copyright (c) 1998 5 * Matthias Drochner. 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 AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 * 27 */ 28 29#include <sys/cdefs.h> 30__KERNEL_RCSID(0, "$NetBSD: lk201_ws.c,v 1.7 2005/12/11 12:21:20 christos Exp $"); 31 32#include <sys/param.h> 33#include <sys/systm.h> 34 35#include <dev/wscons/wsconsio.h> 36 37#include <dev/dec/lk201reg.h> 38#include <dev/dec/lk201var.h> 39#include <dev/dec/wskbdmap_lk201.h> /* for {MIN,MAX}_LK201_KEY */ 40 41#define send(lks, c) ((*((lks)->attmt.sendchar))((lks)->attmt.cookie, c)) 42 43int 44lk201_init(struct lk201_state *lks) 45{ 46 int i; 47 48 send(lks, LK_LED_ENABLE); 49 send(lks, LK_LED_ALL); 50 51 /* 52 * set all keys to updown mode; autorepeat is 53 * done by wskbd software 54 */ 55 for (i = 1; i <= 14; i++) 56 send(lks, LK_CMD_MODE(LK_UPDOWN, i)); 57 58 send(lks, LK_CL_ENABLE); 59 send(lks, LK_PARAM_VOLUME(3)); 60 lks->kcvol = (8 - 3) * 100 / 8; 61 62 lks->bellvol = -1; /* not yet set */ 63 64 for (i = 0; i < LK_KLL; i++) 65 lks->down_keys_list[i] = -1; 66 send(lks, LK_KBD_ENABLE); 67 68 send(lks, LK_LED_DISABLE); 69 send(lks, LK_LED_ALL); 70 lks->leds_state = 0; 71 72 return (0); 73} 74 75int 76lk201_decode(struct lk201_state *lks, int datain, u_int *type, int *dataout) 77{ 78 int i, freeslot; 79 80 switch (datain) { 81 case LK_KEY_UP: 82 for (i = 0; i < LK_KLL; i++) 83 lks->down_keys_list[i] = -1; 84 *type = WSCONS_EVENT_ALL_KEYS_UP; 85 return (1); 86 case LK_POWER_UP: 87 printf("lk201_decode: powerup detected\n"); 88 lk201_init(lks); 89 return (0); 90 case LK_KDOWN_ERROR: 91 case LK_POWER_ERROR: 92 case LK_OUTPUT_ERROR: 93 case LK_INPUT_ERROR: 94 printf("lk201_decode: error %x\n", datain); 95 /* FALLTHRU */ 96 case LK_KEY_REPEAT: /* autorepeat handled by wskbd */ 97 case LK_MODE_CHANGE: /* ignore silently */ 98 return (0); 99 } 100 101 if (datain < MIN_LK201_KEY || datain > MAX_LK201_KEY) { 102 printf("lk201_decode: %x\n", datain); 103 return (0); 104 } 105 106 *dataout = datain - MIN_LK201_KEY; 107 108 freeslot = -1; 109 for (i = 0; i < LK_KLL; i++) { 110 if (lks->down_keys_list[i] == datain) { 111 *type = WSCONS_EVENT_KEY_UP; 112 lks->down_keys_list[i] = -1; 113 return (1); 114 } 115 if (lks->down_keys_list[i] == -1 && freeslot == -1) 116 freeslot = i; 117 } 118 119 if (freeslot == -1) { 120 printf("lk201_decode: down(%d) no free slot\n", datain); 121 return (0); 122 } 123 124 *type = WSCONS_EVENT_KEY_DOWN; 125 lks->down_keys_list[freeslot] = datain; 126 return (1); 127} 128 129void 130lk201_bell(struct lk201_state *lks, struct wskbd_bell_data *bell) 131{ 132 unsigned int vol; 133 134 if (bell->which & WSKBD_BELL_DOVOLUME) { 135 vol = 8 - bell->volume * 8 / 100; 136 if (vol > 7) 137 vol = 7; 138 } else 139 vol = 3; 140 141 if (vol != lks->bellvol) { 142 send(lks, LK_BELL_ENABLE); 143 send(lks, LK_PARAM_VOLUME(vol)); 144 lks->bellvol = vol; 145 } 146 send(lks, LK_RING_BELL); 147} 148 149void 150lk201_set_leds(struct lk201_state *lks, int leds) 151{ 152 int newleds; 153 154 newleds = 0; 155 if (leds & WSKBD_LED_SCROLL) 156 newleds |= LK_LED_WAIT; 157 if (leds & WSKBD_LED_CAPS) 158 newleds |= LK_LED_LOCK; 159 160 send(lks, LK_LED_DISABLE); 161 send(lks, (0x80 | (~newleds & 0x0f))); 162 163 send(lks, LK_LED_ENABLE); 164 send(lks, (0x80 | (newleds & 0x0f))); 165 166 lks->leds_state = leds; 167} 168 169void 170lk201_set_keyclick(struct lk201_state *lks, int vol) 171{ 172 unsigned int newvol; 173 174 if (vol == 0) 175 send(lks, LK_CL_DISABLE); 176 else { 177 newvol = 8 - vol * 8 / 100; 178 if (newvol > 7) 179 newvol = 7; 180 181 send(lks, LK_CL_ENABLE); 182 send(lks, LK_PARAM_VOLUME(newvol)); 183 } 184 185 lks->kcvol = vol; 186} 187