xref: /netbsd-src/sys/dev/dec/lk201_ws.c (revision daf6c4152fcddc27c445489775ed1f66ab4ea9a9)
1 /* $NetBSD: lk201_ws.c,v 1.8 2009/03/14 15:36:17 dsl 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.8 2009/03/14 15:36:17 dsl 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 
43 int
44 lk201_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 
75 int
76 lk201_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 
129 void
130 lk201_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 
149 void
150 lk201_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 
169 void
170 lk201_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