| @@ -1,488 +1,489 @@ | | | @@ -1,488 +1,489 @@ |
1 | /* $NetBSD: hpckbd.c,v 1.28 2009/05/12 14:22:39 cegger Exp $ */ | | 1 | /* $NetBSD: hpckbd.c,v 1.29 2011/06/11 16:34:36 nonaka Exp $ */ |
2 | | | 2 | |
3 | /*- | | 3 | /*- |
4 | * Copyright (c) 1999-2001 The NetBSD Foundation, Inc. | | 4 | * Copyright (c) 1999-2001 The NetBSD Foundation, Inc. |
5 | * All rights reserved. | | 5 | * All rights reserved. |
6 | * | | 6 | * |
7 | * This code is derived from software contributed to The NetBSD Foundation | | 7 | * This code is derived from software contributed to The NetBSD Foundation |
8 | * by UCHIYAMA Yasushi. | | 8 | * by UCHIYAMA Yasushi. |
9 | * | | 9 | * |
10 | * Redistribution and use in source and binary forms, with or without | | 10 | * Redistribution and use in source and binary forms, with or without |
11 | * modification, are permitted provided that the following conditions | | 11 | * modification, are permitted provided that the following conditions |
12 | * are met: | | 12 | * are met: |
13 | * 1. Redistributions of source code must retain the above copyright | | 13 | * 1. Redistributions of source code must retain the above copyright |
14 | * notice, this list of conditions and the following disclaimer. | | 14 | * notice, this list of conditions and the following disclaimer. |
15 | * 2. Redistributions in binary form must reproduce the above copyright | | 15 | * 2. Redistributions in binary form must reproduce the above copyright |
16 | * notice, this list of conditions and the following disclaimer in the | | 16 | * notice, this list of conditions and the following disclaimer in the |
17 | * documentation and/or other materials provided with the distribution. | | 17 | * documentation and/or other materials provided with the distribution. |
18 | * | | 18 | * |
19 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | | 19 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS |
20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | | 20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | | 21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | | 22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS |
23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | | 23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | | 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | | 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | | 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | | 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | | 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
29 | * POSSIBILITY OF SUCH DAMAGE. | | 29 | * POSSIBILITY OF SUCH DAMAGE. |
30 | */ | | 30 | */ |
31 | | | 31 | |
32 | #include <sys/cdefs.h> | | 32 | #include <sys/cdefs.h> |
33 | __KERNEL_RCSID(0, "$NetBSD: hpckbd.c,v 1.28 2009/05/12 14:22:39 cegger Exp $"); | | 33 | __KERNEL_RCSID(0, "$NetBSD: hpckbd.c,v 1.29 2011/06/11 16:34:36 nonaka Exp $"); |
34 | | | 34 | |
35 | #include <sys/param.h> | | 35 | #include <sys/param.h> |
36 | #include <sys/systm.h> | | 36 | #include <sys/systm.h> |
37 | #include <sys/device.h> | | 37 | #include <sys/device.h> |
38 | | | 38 | |
39 | #include <sys/tty.h> | | 39 | #include <sys/tty.h> |
40 | | | 40 | |
41 | #include <sys/bus.h> | | 41 | #include <sys/bus.h> |
42 | #include <sys/intr.h> | | 42 | #include <sys/intr.h> |
43 | | | 43 | |
44 | #include <machine/config_hook.h> | | 44 | #include <machine/config_hook.h> |
45 | #include <machine/platid.h> | | 45 | #include <machine/platid.h> |
46 | #include <machine/platid_mask.h> | | 46 | #include <machine/platid_mask.h> |
47 | | | 47 | |
48 | #include "opt_wsdisplay_compat.h" | | 48 | #include "opt_wsdisplay_compat.h" |
49 | #include "opt_pckbd_layout.h" | | 49 | #include "opt_pckbd_layout.h" |
50 | #include <dev/wscons/wsksymdef.h> | | 50 | #include <dev/wscons/wsksymdef.h> |
51 | #include <dev/wscons/wsconsio.h> | | 51 | #include <dev/wscons/wsconsio.h> |
52 | #include <dev/wscons/wskbdvar.h> | | 52 | #include <dev/wscons/wskbdvar.h> |
53 | #include <dev/wscons/wsksymvar.h> | | 53 | #include <dev/wscons/wsksymvar.h> |
54 | #include <dev/pckbport/wskbdmap_mfii.h> | | 54 | #include <dev/pckbport/wskbdmap_mfii.h> |
55 | #ifdef WSDISPLAY_COMPAT_RAWKBD | | 55 | #ifdef WSDISPLAY_COMPAT_RAWKBD |
56 | #include <dev/hpc/pckbd_encode.h> | | 56 | #include <dev/hpc/pckbd_encode.h> |
57 | #endif | | 57 | #endif |
58 | | | 58 | |
59 | #include <dev/hpc/hpckbdvar.h> | | 59 | #include <dev/hpc/hpckbdvar.h> |
60 | #include <dev/hpc/hpckbdkeymap.h> | | 60 | #include <dev/hpc/hpckbdkeymap.h> |
61 | | | 61 | |
62 | struct hpckbd_softc; | | 62 | struct hpckbd_softc; |
63 | | | 63 | |
64 | #define NEVENTQ 32 | | 64 | #define NEVENTQ 32 |
65 | struct hpckbd_eventq { | | 65 | struct hpckbd_eventq { |
66 | u_int hq_type; | | 66 | u_int hq_type; |
67 | int hq_data; | | 67 | int hq_data; |
68 | }; | | 68 | }; |
69 | | | 69 | |
70 | struct hpckbd_core { | | 70 | struct hpckbd_core { |
71 | struct hpckbd_if hc_if; | | 71 | struct hpckbd_if hc_if; |
72 | struct hpckbd_ic_if *hc_ic; | | 72 | struct hpckbd_ic_if *hc_ic; |
73 | const uint8_t *hc_keymap; | | 73 | const uint8_t *hc_keymap; |
74 | const int *hc_special; | | 74 | const int *hc_special; |
75 | int hc_polling; | | 75 | int hc_polling; |
76 | int hc_console; | | 76 | int hc_console; |
77 | #define NEVENTQ 32 | | 77 | #define NEVENTQ 32 |
78 | struct hpckbd_eventq hc_eventq[NEVENTQ]; | | 78 | struct hpckbd_eventq hc_eventq[NEVENTQ]; |
79 | struct hpckbd_eventq *hc_head, *hc_tail; | | 79 | struct hpckbd_eventq *hc_head, *hc_tail; |
80 | int hc_nevents; | | 80 | int hc_nevents; |
81 | int hc_enabled; | | 81 | int hc_enabled; |
82 | struct device *hc_wskbddev; | | 82 | struct device *hc_wskbddev; |
83 | struct hpckbd_softc* hc_sc; /* back link */ | | 83 | struct hpckbd_softc* hc_sc; /* back link */ |
84 | #ifdef WSDISPLAY_COMPAT_RAWKBD | | 84 | #ifdef WSDISPLAY_COMPAT_RAWKBD |
85 | int hc_rawkbd; | | 85 | int hc_rawkbd; |
86 | #endif | | 86 | #endif |
87 | }; | | 87 | }; |
88 | | | 88 | |
89 | struct hpckbd_softc { | | 89 | struct hpckbd_softc { |
90 | struct device sc_dev; | | 90 | device_t sc_dev; |
91 | struct hpckbd_core *sc_core; | | 91 | struct hpckbd_core *sc_core; |
92 | struct hpckbd_core sc_coredata; | | 92 | struct hpckbd_core sc_coredata; |
93 | }; | | 93 | }; |
94 | | | 94 | |
95 | int hpckbd_match(device_t, cfdata_t, void *); | | 95 | int hpckbd_match(device_t, cfdata_t, void *); |
96 | void hpckbd_attach(device_t, device_t, void *); | | 96 | void hpckbd_attach(device_t, device_t, void *); |
97 | | | 97 | |
98 | void hpckbd_initcore(struct hpckbd_core *, struct hpckbd_ic_if *, int); | | 98 | void hpckbd_initcore(struct hpckbd_core *, struct hpckbd_ic_if *, int); |
99 | void hpckbd_initif(struct hpckbd_core *); | | 99 | void hpckbd_initif(struct hpckbd_core *); |
100 | int hpckbd_getevent(struct hpckbd_core *, u_int *, int *); | | 100 | int hpckbd_getevent(struct hpckbd_core *, u_int *, int *); |
101 | int hpckbd_putevent(struct hpckbd_core *, u_int, int); | | 101 | int hpckbd_putevent(struct hpckbd_core *, u_int, int); |
102 | void hpckbd_keymap_lookup(struct hpckbd_core*); | | 102 | void hpckbd_keymap_lookup(struct hpckbd_core*); |
103 | void hpckbd_keymap_setup(struct hpckbd_core *, const keysym_t *, int); | | 103 | void hpckbd_keymap_setup(struct hpckbd_core *, const keysym_t *, int); |
104 | int __hpckbd_input(void *, int, int); | | 104 | int __hpckbd_input(void *, int, int); |
105 | void __hpckbd_input_hook(void *); | | 105 | void __hpckbd_input_hook(void *); |
106 | | | 106 | |
107 | CFATTACH_DECL(hpckbd, sizeof(struct hpckbd_softc), | | 107 | CFATTACH_DECL_NEW(hpckbd, sizeof(struct hpckbd_softc), |
108 | hpckbd_match, hpckbd_attach, NULL, NULL); | | 108 | hpckbd_match, hpckbd_attach, NULL, NULL); |
109 | | | 109 | |
110 | /* wskbd accessopts */ | | 110 | /* wskbd accessopts */ |
111 | int hpckbd_enable(void *, int); | | 111 | int hpckbd_enable(void *, int); |
112 | void hpckbd_set_leds(void *, int); | | 112 | void hpckbd_set_leds(void *, int); |
113 | int hpckbd_ioctl(void *, u_long, void *, int, struct lwp *); | | 113 | int hpckbd_ioctl(void *, u_long, void *, int, struct lwp *); |
114 | | | 114 | |
115 | /* consopts */ | | 115 | /* consopts */ |
116 | struct hpckbd_core hpckbd_consdata; | | 116 | struct hpckbd_core hpckbd_consdata; |
117 | void hpckbd_cngetc(void *, u_int *, int*); | | 117 | void hpckbd_cngetc(void *, u_int *, int*); |
118 | void hpckbd_cnpollc(void *, int); | | 118 | void hpckbd_cnpollc(void *, int); |
119 | | | 119 | |
120 | const struct wskbd_accessops hpckbd_accessops = { | | 120 | const struct wskbd_accessops hpckbd_accessops = { |
121 | hpckbd_enable, | | 121 | hpckbd_enable, |
122 | hpckbd_set_leds, | | 122 | hpckbd_set_leds, |
123 | hpckbd_ioctl, | | 123 | hpckbd_ioctl, |
124 | }; | | 124 | }; |
125 | | | 125 | |
126 | const struct wskbd_consops hpckbd_consops = { | | 126 | const struct wskbd_consops hpckbd_consops = { |
127 | hpckbd_cngetc, | | 127 | hpckbd_cngetc, |
128 | hpckbd_cnpollc, | | 128 | hpckbd_cnpollc, |
129 | NULL, | | 129 | NULL, |
130 | }; | | 130 | }; |
131 | | | 131 | |
132 | struct wskbd_mapdata hpckbd_keymapdata = { | | 132 | struct wskbd_mapdata hpckbd_keymapdata = { |
133 | pckbd_keydesctab, | | 133 | pckbd_keydesctab, |
134 | #ifdef PCKBD_LAYOUT | | 134 | #ifdef PCKBD_LAYOUT |
135 | PCKBD_LAYOUT | | 135 | PCKBD_LAYOUT |
136 | #else | | 136 | #else |
137 | KB_US | | 137 | KB_US |
138 | #endif | | 138 | #endif |
139 | }; | | 139 | }; |
140 | | | 140 | |
141 | int | | 141 | int |
142 | hpckbd_match(device_t parent, | | 142 | hpckbd_match(device_t parent, cfdata_t cf, void *aux) |
143 | cfdata_t cf, void *aux) | | | |
144 | { | | 143 | { |
145 | return (1); | | 144 | return (1); |
146 | } | | 145 | } |
147 | | | 146 | |
148 | void | | 147 | void |
149 | hpckbd_attach(device_t parent, device_t self, void *aux) | | 148 | hpckbd_attach(device_t parent, device_t self, void *aux) |
150 | { | | 149 | { |
151 | struct hpckbd_attach_args *haa = aux; | | 150 | struct hpckbd_attach_args *haa = aux; |
152 | struct hpckbd_softc *sc = device_private(self); | | 151 | struct hpckbd_softc *sc = device_private(self); |
153 | struct hpckbd_ic_if *ic = haa->haa_ic; | | 152 | struct hpckbd_ic_if *ic = haa->haa_ic; |
154 | struct wskbddev_attach_args wa; | | 153 | struct wskbddev_attach_args wa; |
155 | | | 154 | |
| | | 155 | sc->sc_dev = self; |
| | | 156 | |
156 | /* | | 157 | /* |
157 | * Initialize core if it isn't console | | 158 | * Initialize core if it isn't console |
158 | */ | | 159 | */ |
159 | if (hpckbd_consdata.hc_ic == ic) { | | 160 | if (hpckbd_consdata.hc_ic == ic) { |
160 | sc->sc_core = &hpckbd_consdata; | | 161 | sc->sc_core = &hpckbd_consdata; |
161 | /* The core has been initialized in hpckbd_cnattach. */ | | 162 | /* The core has been initialized in hpckbd_cnattach. */ |
162 | } else { | | 163 | } else { |
163 | sc->sc_core = &sc->sc_coredata; | | 164 | sc->sc_core = &sc->sc_coredata; |
164 | hpckbd_initcore(sc->sc_core, ic, 0 /* not console */); | | 165 | hpckbd_initcore(sc->sc_core, ic, 0 /* not console */); |
165 | } | | 166 | } |
166 | | | 167 | |
167 | if (sc->sc_core->hc_keymap == default_keymap) | | 168 | if (sc->sc_core->hc_keymap == default_keymap) |
168 | printf(": no keymap."); | | 169 | printf(": no keymap."); |
169 | | | 170 | |
170 | printf("\n"); | | 171 | printf("\n"); |
171 | | | 172 | |
172 | /* | | 173 | /* |
173 | * setup hpckbd public interface for parent controller. | | 174 | * setup hpckbd public interface for parent controller. |
174 | */ | | 175 | */ |
175 | hpckbd_initif(sc->sc_core); | | 176 | hpckbd_initif(sc->sc_core); |
176 | | | 177 | |
177 | /* | | 178 | /* |
178 | * attach wskbd | | 179 | * attach wskbd |
179 | */ | | 180 | */ |
180 | wa.console = sc->sc_core->hc_console; | | 181 | wa.console = sc->sc_core->hc_console; |
181 | wa.keymap = &hpckbd_keymapdata; | | 182 | wa.keymap = &hpckbd_keymapdata; |
182 | wa.accessops = &hpckbd_accessops; | | 183 | wa.accessops = &hpckbd_accessops; |
183 | wa.accesscookie = sc->sc_core; | | 184 | wa.accesscookie = sc->sc_core; |
184 | sc->sc_core->hc_wskbddev = config_found(self, &wa, wskbddevprint); | | 185 | sc->sc_core->hc_wskbddev = config_found(self, &wa, wskbddevprint); |
185 | | | 186 | |
186 | if (!pmf_device_register(self, NULL, NULL)) | | 187 | if (!pmf_device_register(self, NULL, NULL)) |
187 | aprint_error_dev(self, "unable to establish power handler\n"); | | 188 | aprint_error_dev(self, "unable to establish power handler\n"); |
188 | } | | 189 | } |
189 | | | 190 | |
190 | int | | 191 | int |
191 | hpckbd_print(void *aux, const char *pnp) | | 192 | hpckbd_print(void *aux, const char *pnp) |
192 | { | | 193 | { |
193 | return (pnp ? QUIET : UNCONF); | | 194 | return (pnp ? QUIET : UNCONF); |
194 | } | | 195 | } |
195 | | | 196 | |
196 | void | | 197 | void |
197 | hpckbd_initcore(struct hpckbd_core *hc, struct hpckbd_ic_if *ic, int console) | | 198 | hpckbd_initcore(struct hpckbd_core *hc, struct hpckbd_ic_if *ic, int console) |
198 | { | | 199 | { |
199 | hc->hc_polling = 0; | | 200 | hc->hc_polling = 0; |
200 | hc->hc_console = console; | | 201 | hc->hc_console = console; |
201 | hc->hc_ic = ic; | | 202 | hc->hc_ic = ic; |
202 | | | 203 | |
203 | /* setup event queue */ | | 204 | /* setup event queue */ |
204 | hc->hc_head = hc->hc_tail = hc->hc_eventq; | | 205 | hc->hc_head = hc->hc_tail = hc->hc_eventq; |
205 | hc->hc_nevents = 0; | | 206 | hc->hc_nevents = 0; |
206 | | | 207 | |
207 | hpckbd_keymap_lookup(hc); | | 208 | hpckbd_keymap_lookup(hc); |
208 | } | | 209 | } |
209 | | | 210 | |
210 | void | | 211 | void |
211 | hpckbd_initif(struct hpckbd_core *hc) | | 212 | hpckbd_initif(struct hpckbd_core *hc) |
212 | { | | 213 | { |
213 | struct hpckbd_if *kbdif = &hc->hc_if; | | 214 | struct hpckbd_if *kbdif = &hc->hc_if; |
214 | | | 215 | |
215 | kbdif->hi_ctx = hc; | | 216 | kbdif->hi_ctx = hc; |
216 | kbdif->hi_input = __hpckbd_input; | | 217 | kbdif->hi_input = __hpckbd_input; |
217 | kbdif->hi_input_hook = __hpckbd_input_hook; | | 218 | kbdif->hi_input_hook = __hpckbd_input_hook; |
218 | hpckbd_ic_establish(hc->hc_ic, &hc->hc_if); | | 219 | hpckbd_ic_establish(hc->hc_ic, &hc->hc_if); |
219 | } | | 220 | } |
220 | | | 221 | |
221 | int | | 222 | int |
222 | hpckbd_putevent(struct hpckbd_core* hc, u_int type, int data) | | 223 | hpckbd_putevent(struct hpckbd_core* hc, u_int type, int data) |
223 | { | | 224 | { |
224 | int s = spltty(); | | 225 | int s = spltty(); |
225 | | | 226 | |
226 | if (hc->hc_nevents == NEVENTQ) { | | 227 | if (hc->hc_nevents == NEVENTQ) { |
227 | splx(s); | | 228 | splx(s); |
228 | return (0); /* queue is full */ | | 229 | return (0); /* queue is full */ |
229 | } | | 230 | } |
230 | | | 231 | |
231 | hc->hc_nevents++; | | 232 | hc->hc_nevents++; |
232 | hc->hc_tail->hq_type = type; | | 233 | hc->hc_tail->hq_type = type; |
233 | hc->hc_tail->hq_data = data; | | 234 | hc->hc_tail->hq_data = data; |
234 | if (&hc->hc_eventq[NEVENTQ] <= ++hc->hc_tail) | | 235 | if (&hc->hc_eventq[NEVENTQ] <= ++hc->hc_tail) |
235 | hc->hc_tail = hc->hc_eventq; | | 236 | hc->hc_tail = hc->hc_eventq; |
236 | splx(s); | | 237 | splx(s); |
237 | | | 238 | |
238 | return (1); | | 239 | return (1); |
239 | } | | 240 | } |
240 | | | 241 | |
241 | int | | 242 | int |
242 | hpckbd_getevent(struct hpckbd_core* hc, u_int *type, int *data) | | 243 | hpckbd_getevent(struct hpckbd_core* hc, u_int *type, int *data) |
243 | { | | 244 | { |
244 | int s = spltty(); | | 245 | int s = spltty(); |
245 | | | 246 | |
246 | if (hc->hc_nevents == 0) { | | 247 | if (hc->hc_nevents == 0) { |
247 | splx(s); | | 248 | splx(s); |
248 | return (0); /* queue is empty */ | | 249 | return (0); /* queue is empty */ |
249 | } | | 250 | } |
250 | | | 251 | |
251 | *type = hc->hc_head->hq_type; | | 252 | *type = hc->hc_head->hq_type; |
252 | *data = hc->hc_head->hq_data; | | 253 | *data = hc->hc_head->hq_data; |
253 | hc->hc_nevents--; | | 254 | hc->hc_nevents--; |
254 | if (&hc->hc_eventq[NEVENTQ] <= ++hc->hc_head) | | 255 | if (&hc->hc_eventq[NEVENTQ] <= ++hc->hc_head) |
255 | hc->hc_head = hc->hc_eventq; | | 256 | hc->hc_head = hc->hc_eventq; |
256 | splx(s); | | 257 | splx(s); |
257 | | | 258 | |
258 | return (1); | | 259 | return (1); |
259 | } | | 260 | } |
260 | | | 261 | |
261 | void | | 262 | void |
262 | hpckbd_keymap_setup(struct hpckbd_core *hc, | | 263 | hpckbd_keymap_setup(struct hpckbd_core *hc, |
263 | const keysym_t *map, int mapsize) | | 264 | const keysym_t *map, int mapsize) |
264 | { | | 265 | { |
265 | int i; | | 266 | int i; |
266 | struct wscons_keydesc *desc; | | 267 | struct wscons_keydesc *desc; |
267 | | | 268 | |
268 | /* fix keydesc table */ | | 269 | /* fix keydesc table */ |
269 | /* | | 270 | /* |
270 | * XXX The way this is done is really wrong. The __UNCONST() | | 271 | * XXX The way this is done is really wrong. The __UNCONST() |
271 | * is a hint as to what is wrong. This actually ends up modifying | | 272 | * is a hint as to what is wrong. This actually ends up modifying |
272 | * initialized data which is marked "const". | | 273 | * initialized data which is marked "const". |
273 | * The reason we get away with it here is apparently that text | | 274 | * The reason we get away with it here is apparently that text |
274 | * and read-only data gets mapped read/write on the platforms | | 275 | * and read-only data gets mapped read/write on the platforms |
275 | * using this code. | | 276 | * using this code. |
276 | */ | | 277 | */ |
277 | desc = (struct wscons_keydesc *)__UNCONST(hpckbd_keymapdata.keydesc); | | 278 | desc = (struct wscons_keydesc *)__UNCONST(hpckbd_keymapdata.keydesc); |
278 | for (i = 0; desc[i].name != 0; i++) { | | 279 | for (i = 0; desc[i].name != 0; i++) { |
279 | if ((desc[i].name & KB_MACHDEP) && desc[i].map == NULL) { | | 280 | if ((desc[i].name & KB_MACHDEP) && desc[i].map == NULL) { |
280 | desc[i].map = map; | | 281 | desc[i].map = map; |
281 | desc[i].map_size = mapsize; | | 282 | desc[i].map_size = mapsize; |
282 | } | | 283 | } |
283 | } | | 284 | } |
284 | | | 285 | |
285 | return; | | 286 | return; |
286 | } | | 287 | } |
287 | | | 288 | |
288 | void | | 289 | void |
289 | hpckbd_keymap_lookup(struct hpckbd_core *hc) | | 290 | hpckbd_keymap_lookup(struct hpckbd_core *hc) |
290 | { | | 291 | { |
291 | const struct hpckbd_keymap_table *tab; | | 292 | const struct hpckbd_keymap_table *tab; |
292 | platid_mask_t mask; | | 293 | platid_mask_t mask; |
293 | | | 294 | |
294 | for (tab = hpckbd_keymap_table; tab->ht_platform != NULL; tab++) { | | 295 | for (tab = hpckbd_keymap_table; tab->ht_platform != NULL; tab++) { |
295 | | | 296 | |
296 | mask = PLATID_DEREF(tab->ht_platform); | | 297 | mask = PLATID_DEREF(tab->ht_platform); |
297 | | | 298 | |
298 | if (platid_match(&platid, &mask)) { | | 299 | if (platid_match(&platid, &mask)) { |
299 | hc->hc_keymap = tab->ht_keymap; | | 300 | hc->hc_keymap = tab->ht_keymap; |
300 | hc->hc_special = tab->ht_special; | | 301 | hc->hc_special = tab->ht_special; |
301 | #if !defined(PCKBD_LAYOUT) | | 302 | #if !defined(PCKBD_LAYOUT) |
302 | hpckbd_keymapdata.layout = tab->ht_layout; | | 303 | hpckbd_keymapdata.layout = tab->ht_layout; |
303 | #endif | | 304 | #endif |
304 | if (tab->ht_cmdmap.map) { | | 305 | if (tab->ht_cmdmap.map) { |
305 | hpckbd_keymap_setup(hc, tab->ht_cmdmap.map, | | 306 | hpckbd_keymap_setup(hc, tab->ht_cmdmap.map, |
306 | tab->ht_cmdmap.size); | | 307 | tab->ht_cmdmap.size); |
307 | #if !defined(PCKBD_LAYOUT) | | 308 | #if !defined(PCKBD_LAYOUT) |
308 | hpckbd_keymapdata.layout |= KB_MACHDEP; | | 309 | hpckbd_keymapdata.layout |= KB_MACHDEP; |
309 | #endif | | 310 | #endif |
310 | } else { | | 311 | } else { |
311 | hpckbd_keymapdata.layout &= ~KB_MACHDEP; | | 312 | hpckbd_keymapdata.layout &= ~KB_MACHDEP; |
312 | } | | 313 | } |
313 | return; | | 314 | return; |
314 | } | | 315 | } |
315 | } | | 316 | } |
316 | | | 317 | |
317 | /* no keymap. use default. */ | | 318 | /* no keymap. use default. */ |
318 | hc->hc_keymap = default_keymap; | | 319 | hc->hc_keymap = default_keymap; |
319 | hc->hc_special = default_special_keymap; | | 320 | hc->hc_special = default_special_keymap; |
320 | #if !defined(PCKBD_LAYOUT) | | 321 | #if !defined(PCKBD_LAYOUT) |
321 | hpckbd_keymapdata.layout = KB_US; | | 322 | hpckbd_keymapdata.layout = KB_US; |
322 | #endif | | 323 | #endif |
323 | } | | 324 | } |
324 | | | 325 | |
325 | void | | 326 | void |
326 | __hpckbd_input_hook(void *arg) | | 327 | __hpckbd_input_hook(void *arg) |
327 | { | | 328 | { |
328 | #if 0 | | 329 | #if 0 |
329 | struct hpckbd_core *hc = arg; | | 330 | struct hpckbd_core *hc = arg; |
330 | | | 331 | |
331 | if (hc->hc_polling) { | | 332 | if (hc->hc_polling) { |
332 | hc->hc_type = WSCONS_EVENT_ALL_KEYS_UP; | | 333 | hc->hc_type = WSCONS_EVENT_ALL_KEYS_UP; |
333 | } | | 334 | } |
334 | #endif | | 335 | #endif |
335 | } | | 336 | } |
336 | | | 337 | |
337 | int | | 338 | int |
338 | __hpckbd_input(void *arg, int flag, int scancode) | | 339 | __hpckbd_input(void *arg, int flag, int scancode) |
339 | { | | 340 | { |
340 | struct hpckbd_core *hc = arg; | | 341 | struct hpckbd_core *hc = arg; |
341 | int type, key; | | 342 | int type, key; |
342 | | | 343 | |
343 | if (flag) { | | 344 | if (flag) { |
344 | type = WSCONS_EVENT_KEY_DOWN; | | 345 | type = WSCONS_EVENT_KEY_DOWN; |
345 | } else { | | 346 | } else { |
346 | type = WSCONS_EVENT_KEY_UP; | | 347 | type = WSCONS_EVENT_KEY_UP; |
347 | } | | 348 | } |
348 | | | 349 | |
349 | key = hc->hc_keymap[scancode]; | | 350 | key = hc->hc_keymap[scancode]; |
350 | if (key == UNK) { | | 351 | if (key == UNK) { |
351 | #ifdef DEBUG | | 352 | #ifdef DEBUG |
352 | printf("hpckbd: unknown scan code %#x (%d, %d)\n", | | 353 | printf("hpckbd: unknown scan code %#x (%d, %d)\n", |
353 | scancode, scancode >> 3, | | 354 | scancode, scancode >> 3, |
354 | scancode - ((scancode >> 3) << 3)); | | 355 | scancode - ((scancode >> 3) << 3)); |
355 | #endif /* DEBUG */ | | 356 | #endif /* DEBUG */ |
356 | return (0); | | 357 | return (0); |
357 | } | | 358 | } |
358 | | | 359 | |
359 | if (key == IGN) { | | 360 | if (key == IGN) { |
360 | return (0); | | 361 | return (0); |
361 | } | | 362 | } |
362 | | | 363 | |
363 | if (key == SPL) { | | 364 | if (key == SPL) { |
364 | if (!flag) | | 365 | if (!flag) |
365 | return (0); | | 366 | return (0); |
366 | | | 367 | |
367 | if (scancode == hc->hc_special[KEY_SPECIAL_OFF]) { | | 368 | if (scancode == hc->hc_special[KEY_SPECIAL_OFF]) { |
368 | config_hook_call(CONFIG_HOOK_BUTTONEVENT, | | 369 | config_hook_call(CONFIG_HOOK_BUTTONEVENT, |
369 | CONFIG_HOOK_BUTTONEVENT_POWER, (void *)1 /* on */); | | 370 | CONFIG_HOOK_BUTTONEVENT_POWER, (void *)1 /* on */); |
370 | } else if (scancode == hc->hc_special[KEY_SPECIAL_LIGHT]) { | | 371 | } else if (scancode == hc->hc_special[KEY_SPECIAL_LIGHT]) { |
371 | static int onoff; /* XXX -uch */ | | 372 | static int onoff; /* XXX -uch */ |
372 | config_hook_call(CONFIG_HOOK_BUTTONEVENT, | | 373 | config_hook_call(CONFIG_HOOK_BUTTONEVENT, |
373 | CONFIG_HOOK_BUTTONEVENT_LIGHT, | | 374 | CONFIG_HOOK_BUTTONEVENT_LIGHT, |
374 | (void *)(onoff ^= 1)); | | 375 | (void *)(onoff ^= 1)); |
375 | } else { | | 376 | } else { |
376 | #ifdef DEBUG | | 377 | #ifdef DEBUG |
377 | printf("unknown special key %d\n", scancode); | | 378 | printf("unknown special key %d\n", scancode); |
378 | #endif | | 379 | #endif |
379 | } | | 380 | } |
380 | | | 381 | |
381 | return (0); | | 382 | return (0); |
382 | } | | 383 | } |
383 | | | 384 | |
384 | if (hc->hc_polling) { | | 385 | if (hc->hc_polling) { |
385 | if (hpckbd_putevent(hc, type, key) == 0) | | 386 | if (hpckbd_putevent(hc, type, key) == 0) |
386 | printf("hpckbd: queue over flow\n"); | | 387 | printf("hpckbd: queue over flow\n"); |
387 | } else { | | 388 | } else { |
388 | #ifdef WSDISPLAY_COMPAT_RAWKBD | | 389 | #ifdef WSDISPLAY_COMPAT_RAWKBD |
389 | if (hc->hc_rawkbd) { | | 390 | if (hc->hc_rawkbd) { |
390 | int n; | | 391 | int n; |
391 | u_char data[16]; | | 392 | u_char data[16]; |
392 | n = pckbd_encode(type, key, data); | | 393 | n = pckbd_encode(type, key, data); |
393 | wskbd_rawinput(hc->hc_wskbddev, data, n); | | 394 | wskbd_rawinput(hc->hc_wskbddev, data, n); |
394 | } else | | 395 | } else |
395 | #endif | | 396 | #endif |
396 | wskbd_input(hc->hc_wskbddev, type, key); | | 397 | wskbd_input(hc->hc_wskbddev, type, key); |
397 | } | | 398 | } |
398 | | | 399 | |
399 | return (0); | | 400 | return (0); |
400 | } | | 401 | } |
401 | | | 402 | |
402 | /* | | 403 | /* |
403 | * console support routines | | 404 | * console support routines |
404 | */ | | 405 | */ |
405 | int | | 406 | int |
406 | hpckbd_cnattach(struct hpckbd_ic_if *ic) | | 407 | hpckbd_cnattach(struct hpckbd_ic_if *ic) |
407 | { | | 408 | { |
408 | struct hpckbd_core *hc = &hpckbd_consdata; | | 409 | struct hpckbd_core *hc = &hpckbd_consdata; |
409 | | | 410 | |
410 | hpckbd_initcore(hc, ic, 1 /* console */); | | 411 | hpckbd_initcore(hc, ic, 1 /* console */); |
411 | | | 412 | |
412 | /* attach controller */ | | 413 | /* attach controller */ |
413 | hpckbd_initif(hc); | | 414 | hpckbd_initif(hc); |
414 | | | 415 | |
415 | /* attach wskbd */ | | 416 | /* attach wskbd */ |
416 | wskbd_cnattach(&hpckbd_consops, hc, &hpckbd_keymapdata); | | 417 | wskbd_cnattach(&hpckbd_consops, hc, &hpckbd_keymapdata); |
417 | | | 418 | |
418 | return (0); | | 419 | return (0); |
419 | } | | 420 | } |
420 | | | 421 | |
421 | void | | 422 | void |
422 | hpckbd_cngetc(void *arg, u_int *type, int *data) | | 423 | hpckbd_cngetc(void *arg, u_int *type, int *data) |
423 | { | | 424 | { |
424 | struct hpckbd_core *hc = arg; | | 425 | struct hpckbd_core *hc = arg; |
425 | | | 426 | |
426 | if (!hc->hc_console || !hc->hc_polling || !hc->hc_ic) | | 427 | if (!hc->hc_console || !hc->hc_polling || !hc->hc_ic) |
427 | return; | | 428 | return; |
428 | | | 429 | |
429 | while (hpckbd_getevent(hc, type, data) == 0) /* busy loop */ | | 430 | while (hpckbd_getevent(hc, type, data) == 0) /* busy loop */ |
430 | hpckbd_ic_poll(hc->hc_ic); | | 431 | hpckbd_ic_poll(hc->hc_ic); |
431 | } | | 432 | } |
432 | | | 433 | |
433 | void | | 434 | void |
434 | hpckbd_cnpollc(void *arg, int on) | | 435 | hpckbd_cnpollc(void *arg, int on) |
435 | { | | 436 | { |
436 | struct hpckbd_core *hc = arg; | | 437 | struct hpckbd_core *hc = arg; |
437 | | | 438 | |
438 | hc->hc_polling = on; | | 439 | hc->hc_polling = on; |
439 | } | | 440 | } |
440 | | | 441 | |
441 | int | | 442 | int |
442 | hpckbd_enable(void *arg, int on) | | 443 | hpckbd_enable(void *arg, int on) |
443 | { | | 444 | { |
444 | struct hpckbd_core *hc = arg; | | 445 | struct hpckbd_core *hc = arg; |
445 | | | 446 | |
446 | if (on) { | | 447 | if (on) { |
447 | if (hc->hc_enabled) | | 448 | if (hc->hc_enabled) |
448 | return (EBUSY); | | 449 | return (EBUSY); |
449 | hc->hc_enabled = 1; | | 450 | hc->hc_enabled = 1; |
450 | } else { | | 451 | } else { |
451 | if (hc->hc_console) | | 452 | if (hc->hc_console) |
452 | return (EBUSY); | | 453 | return (EBUSY); |
453 | hc->hc_enabled = 0; | | 454 | hc->hc_enabled = 0; |
454 | } | | 455 | } |
455 | | | 456 | |
456 | return (0); | | 457 | return (0); |
457 | } | | 458 | } |
458 | | | 459 | |
459 | void | | 460 | void |
460 | hpckbd_set_leds(void *arg, int leds) | | 461 | hpckbd_set_leds(void *arg, int leds) |
461 | { | | 462 | { |
462 | /* Can you find any LED which tells you about keyboard? */ | | 463 | /* Can you find any LED which tells you about keyboard? */ |
463 | } | | 464 | } |
464 | | | 465 | |
465 | int | | 466 | int |
466 | hpckbd_ioctl(void *arg, u_long cmd, void *data, int flag, | | 467 | hpckbd_ioctl(void *arg, u_long cmd, void *data, int flag, |
467 | struct lwp *l) | | 468 | struct lwp *l) |
468 | { | | 469 | { |
469 | #ifdef WSDISPLAY_COMPAT_RAWKBD | | 470 | #ifdef WSDISPLAY_COMPAT_RAWKBD |
470 | struct hpckbd_core *hc = arg; | | 471 | struct hpckbd_core *hc = arg; |
471 | #endif | | 472 | #endif |
472 | switch (cmd) { | | 473 | switch (cmd) { |
473 | case WSKBDIO_GTYPE: | | 474 | case WSKBDIO_GTYPE: |
474 | *(int *)data = WSKBD_TYPE_HPC_KBD; | | 475 | *(int *)data = WSKBD_TYPE_HPC_KBD; |
475 | return (0); | | 476 | return (0); |
476 | case WSKBDIO_SETLEDS: | | 477 | case WSKBDIO_SETLEDS: |
477 | return 0; | | 478 | return 0; |
478 | case WSKBDIO_GETLEDS: | | 479 | case WSKBDIO_GETLEDS: |
479 | *(int *)data = 0; /* dummy for wsconsctl(8) */ | | 480 | *(int *)data = 0; /* dummy for wsconsctl(8) */ |
480 | return (0); | | 481 | return (0); |
481 | #ifdef WSDISPLAY_COMPAT_RAWKBD | | 482 | #ifdef WSDISPLAY_COMPAT_RAWKBD |
482 | case WSKBDIO_SETMODE: | | 483 | case WSKBDIO_SETMODE: |
483 | hc->hc_rawkbd = (*(int *)data == WSKBD_RAW); | | 484 | hc->hc_rawkbd = (*(int *)data == WSKBD_RAW); |
484 | return (0); | | 485 | return (0); |
485 | #endif | | 486 | #endif |
486 | } | | 487 | } |
487 | return (EPASSTHROUGH); | | 488 | return (EPASSTHROUGH); |
488 | } | | 489 | } |