Bug Summary

File:dev/wscons/wskbd.c
Warning:line 1818, column 30
Access to field 'sc_audiocookie' results in a dereference of a null pointer (loaded from variable 'sc')

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.4 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name wskbd.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model static -mframe-pointer=all -relaxed-aliasing -ffp-contract=on -fno-rounding-math -mconstructor-aliases -ffreestanding -mcmodel=kernel -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -target-feature -sse2 -target-feature -sse -target-feature -3dnow -target-feature -mmx -target-feature +save-args -target-feature +retpoline-external-thunk -disable-red-zone -no-implicit-float -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -nostdsysteminc -nobuiltininc -resource-dir /usr/local/llvm16/lib/clang/16 -I /usr/src/sys -I /usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -I /usr/src/sys/arch -I /usr/src/sys/dev/pci/drm/include -I /usr/src/sys/dev/pci/drm/include/uapi -I /usr/src/sys/dev/pci/drm/amd/include/asic_reg -I /usr/src/sys/dev/pci/drm/amd/include -I /usr/src/sys/dev/pci/drm/amd/amdgpu -I /usr/src/sys/dev/pci/drm/amd/display -I /usr/src/sys/dev/pci/drm/amd/display/include -I /usr/src/sys/dev/pci/drm/amd/display/dc -I /usr/src/sys/dev/pci/drm/amd/display/amdgpu_dm -I /usr/src/sys/dev/pci/drm/amd/pm/inc -I /usr/src/sys/dev/pci/drm/amd/pm/legacy-dpm -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/inc -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu11 -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu12 -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu13 -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/inc -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/hwmgr -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/smumgr -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/inc -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/inc/pmfw_if -I /usr/src/sys/dev/pci/drm/amd/display/dc/inc -I /usr/src/sys/dev/pci/drm/amd/display/dc/inc/hw -I /usr/src/sys/dev/pci/drm/amd/display/dc/clk_mgr -I /usr/src/sys/dev/pci/drm/amd/display/modules/inc -I /usr/src/sys/dev/pci/drm/amd/display/modules/hdcp -I /usr/src/sys/dev/pci/drm/amd/display/dmub/inc -I /usr/src/sys/dev/pci/drm/i915 -D DDB -D DIAGNOSTIC -D KTRACE -D ACCOUNTING -D KMEMSTATS -D PTRACE -D POOL_DEBUG -D CRYPTO -D SYSVMSG -D SYSVSEM -D SYSVSHM -D UVM_SWAP_ENCRYPT -D FFS -D FFS2 -D FFS_SOFTUPDATES -D UFS_DIRHASH -D QUOTA -D EXT2FS -D MFS -D NFSCLIENT -D NFSSERVER -D CD9660 -D UDF -D MSDOSFS -D FIFO -D FUSE -D SOCKET_SPLICE -D TCP_ECN -D TCP_SIGNATURE -D INET6 -D IPSEC -D PPP_BSDCOMP -D PPP_DEFLATE -D PIPEX -D MROUTING -D MPLS -D BOOT_CONFIG -D USER_PCICONF -D APERTURE -D MTRR -D NTFS -D SUSPEND -D HIBERNATE -D PCIVERBOSE -D USBVERBOSE -D WSDISPLAY_COMPAT_USL -D WSDISPLAY_COMPAT_RAWKBD -D WSDISPLAY_DEFAULTSCREENS=6 -D X86EMU -D ONEWIREVERBOSE -D MULTIPROCESSOR -D MAXUSERS=80 -D _KERNEL -O2 -Wno-pointer-sign -Wno-address-of-packed-member -Wno-constant-conversion -Wno-unused-but-set-variable -Wno-gnu-folding-constant -fdebug-compilation-dir=/usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fcf-protection=branch -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -o /home/ben/Projects/scan/2024-01-11-110808-61670-1 -x c /usr/src/sys/dev/wscons/wskbd.c
1/* $OpenBSD: wskbd.c,v 1.117 2023/11/23 15:02:57 deraadt Exp $ */
2/* $NetBSD: wskbd.c,v 1.80 2005/05/04 01:52:16 augustss Exp $ */
3
4/*
5 * Copyright (c) 1996, 1997 Christopher G. Demetriou. All rights reserved.
6 *
7 * Keysym translator:
8 * Contributed to The NetBSD Foundation by Juergen Hannken-Illjes.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by Christopher G. Demetriou
21 * for the NetBSD Project.
22 * 4. The name of the author may not be used to endorse or promote products
23 * derived from this software without specific prior written permission
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
26 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
27 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
28 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
29 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
30 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
31 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
32 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
33 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
34 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 */
36
37/*
38 * Copyright (c) 1992, 1993
39 * The Regents of the University of California. All rights reserved.
40 *
41 * This software was developed by the Computer Systems Engineering group
42 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
43 * contributed to Berkeley.
44 *
45 * All advertising materials mentioning features or use of this software
46 * must display the following acknowledgement:
47 * This product includes software developed by the University of
48 * California, Lawrence Berkeley Laboratory.
49 *
50 * Redistribution and use in source and binary forms, with or without
51 * modification, are permitted provided that the following conditions
52 * are met:
53 * 1. Redistributions of source code must retain the above copyright
54 * notice, this list of conditions and the following disclaimer.
55 * 2. Redistributions in binary form must reproduce the above copyright
56 * notice, this list of conditions and the following disclaimer in the
57 * documentation and/or other materials provided with the distribution.
58 * 3. Neither the name of the University nor the names of its contributors
59 * may be used to endorse or promote products derived from this software
60 * without specific prior written permission.
61 *
62 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
63 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
64 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
65 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
66 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
67 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
68 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
69 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
70 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
71 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
72 * SUCH DAMAGE.
73 *
74 * @(#)kbd.c 8.2 (Berkeley) 10/30/93
75 */
76
77/*
78 * Keyboard driver (/dev/wskbd*). Translates incoming bytes to ASCII or
79 * to `wscons_events' and passes them up to the appropriate reader.
80 */
81
82#include <sys/param.h>
83#include <sys/conf.h>
84#include <sys/device.h>
85#include <sys/ioctl.h>
86#include <sys/kernel.h>
87#include <sys/proc.h>
88#include <sys/syslog.h>
89#include <sys/systm.h>
90#include <sys/timeout.h>
91#include <sys/malloc.h>
92#include <sys/tty.h>
93#include <sys/signalvar.h>
94#include <sys/errno.h>
95#include <sys/fcntl.h>
96#include <sys/vnode.h>
97#include <sys/task.h>
98
99#include <ddb/db_var.h>
100
101#include <dev/wscons/wscons_features.h>
102#include <dev/wscons/wsconsio.h>
103#include <dev/wscons/wskbdvar.h>
104#include <dev/wscons/wsksymdef.h>
105#include <dev/wscons/wsksymvar.h>
106#include <dev/wscons/wsdisplayvar.h>
107#include <dev/wscons/wseventvar.h>
108#include <dev/wscons/wscons_callbacks.h>
109
110#include "audio.h" /* NAUDIO (mixer tuning) */
111#include "wsdisplay.h"
112#include "wskbd.h"
113#include "wsmux.h"
114
115#if NWSDISPLAY1 > 0
116#include <sys/atomic.h>
117#endif
118
119#ifdef WSKBD_DEBUG
120#define DPRINTF(x) if (wskbddebug) printf x
121int wskbddebug = 0;
122#else
123#define DPRINTF(x)
124#endif
125
126#include <dev/wscons/wsmuxvar.h>
127
128struct wskbd_internal {
129 const struct wskbd_consops *t_consops;
130 void *t_consaccesscookie;
131
132 int t_modifiers;
133 int t_composelen; /* remaining entries in t_composebuf */
134 keysym_t t_composebuf[2];
135
136 int t_flags;
137#define WSKFL_METAESC1 1
138
139#define MAXKEYSYMSPERKEY2 2 /* ESC <key> at max */
140 keysym_t t_symbols[MAXKEYSYMSPERKEY2];
141
142 struct wskbd_softc *t_sc; /* back pointer */
143
144 struct wskbd_mapdata t_keymap; /* translation map table and
145 current layout */
146};
147
148struct wskbd_softc {
149 struct wsevsrc sc_base;
150
151 struct wskbd_internal *id;
152
153 const struct wskbd_accessops *sc_accessops;
154 void *sc_accesscookie;
155
156 int sc_ledstate;
157
158 int sc_isconsole;
159
160 struct wskbd_bell_data sc_bell_data;
161 struct wskbd_keyrepeat_data sc_keyrepeat_data;
162
163 int sc_repeating; /* we've called timeout() */
164 int sc_repkey;
165 struct timeout sc_repeat_ch;
166 u_int sc_repeat_type;
167 int sc_repeat_value;
168
169 int sc_translating; /* xlate to chars for emulation */
170
171 int sc_maplen; /* number of entries in sc_map */
172 struct wscons_keymap *sc_map; /* current translation map */
173
174 int sc_refcnt;
175 u_char sc_dying; /* device is being detached */
176
177#if NAUDIO1 > 0
178 void *sc_audiocookie;
179#endif
180 struct task sc_kbd_backlight_task;
181 u_int sc_kbd_backlight_cmd;
182#if NWSDISPLAY1 > 0
183 struct task sc_brightness_task;
184 int sc_brightness_steps;
185#endif
186};
187
188enum wskbd_kbd_backlight_cmds {
189 KBD_BACKLIGHT_NONE,
190 KBD_BACKLIGHT_UP,
191 KBD_BACKLIGHT_DOWN,
192 KBD_BACKLIGHT_TOGGLE,
193};
194
195#define MOD_SHIFT_L(1 << 0) (1 << 0)
196#define MOD_SHIFT_R(1 << 1) (1 << 1)
197#define MOD_SHIFTLOCK(1 << 2) (1 << 2)
198#define MOD_CAPSLOCK(1 << 3) (1 << 3)
199#define MOD_CONTROL_L(1 << 4) (1 << 4)
200#define MOD_CONTROL_R(1 << 5) (1 << 5)
201#define MOD_META_L(1 << 6) (1 << 6)
202#define MOD_META_R(1 << 7) (1 << 7)
203#define MOD_MODESHIFT(1 << 8) (1 << 8)
204#define MOD_NUMLOCK(1 << 9) (1 << 9)
205#define MOD_COMPOSE(1 << 10) (1 << 10)
206#define MOD_HOLDSCREEN(1 << 11) (1 << 11)
207#define MOD_COMMAND(1 << 12) (1 << 12)
208#define MOD_COMMAND1(1 << 13) (1 << 13)
209#define MOD_COMMAND2(1 << 14) (1 << 14)
210#define MOD_MODELOCK(1 << 15) (1 << 15)
211
212#define MOD_ANYSHIFT((1 << 0) | (1 << 1) | (1 << 2)) (MOD_SHIFT_L(1 << 0) | MOD_SHIFT_R(1 << 1) | MOD_SHIFTLOCK(1 << 2))
213#define MOD_ANYCONTROL((1 << 4) | (1 << 5)) (MOD_CONTROL_L(1 << 4) | MOD_CONTROL_R(1 << 5))
214#define MOD_ANYMETA((1 << 6) | (1 << 7)) (MOD_META_L(1 << 6) | MOD_META_R(1 << 7))
215#define MOD_ANYLED((1 << 2) | (1 << 3) | (1 << 9) | (1 <<
10) | (1 << 11))
(MOD_SHIFTLOCK(1 << 2) | MOD_CAPSLOCK(1 << 3) | MOD_NUMLOCK(1 << 9) | \
216 MOD_COMPOSE(1 << 10) | MOD_HOLDSCREEN(1 << 11))
217
218#define MOD_ONESET(id, mask)(((id)->t_modifiers & (mask)) != 0) (((id)->t_modifiers & (mask)) != 0)
219#define MOD_ALLSET(id, mask)(((id)->t_modifiers & (mask)) == (mask)) (((id)->t_modifiers & (mask)) == (mask))
220
221keysym_t ksym_upcase(keysym_t);
222
223int wskbd_match(struct device *, void *, void *);
224void wskbd_attach(struct device *, struct device *, void *);
225int wskbd_detach(struct device *, int);
226int wskbd_activate(struct device *, int);
227
228int wskbd_displayioctl(struct device *, u_long, caddr_t, int, struct proc *);
229int wskbd_displayioctl_sc(struct wskbd_softc *, u_long, caddr_t, int,
230 struct proc *, int);
231
232void update_leds(struct wskbd_internal *);
233void update_modifier(struct wskbd_internal *, u_int, int, int);
234int internal_command(struct wskbd_softc *, u_int *, keysym_t, keysym_t);
235int wskbd_translate(struct wskbd_internal *, u_int, int);
236int wskbd_enable(struct wskbd_softc *, int);
237void wskbd_debugger(struct wskbd_softc *);
238#if NWSDISPLAY1 > 0
239void change_displayparam(struct wskbd_softc *, int, int, int);
240#endif
241
242int wskbd_do_ioctl_sc(struct wskbd_softc *, u_long, caddr_t, int,
243 struct proc *, int);
244void wskbd_deliver_event(struct wskbd_softc *sc, u_int type, int value);
245
246#if NWSMUX1 > 0
247int wskbd_mux_open(struct wsevsrc *, struct wseventvar *);
248int wskbd_mux_close(struct wsevsrc *);
249#else
250#define wskbd_mux_open NULL((void *)0)
251#define wskbd_mux_close NULL((void *)0)
252#endif
253
254int wskbd_do_open(struct wskbd_softc *, struct wseventvar *);
255int wskbd_do_ioctl(struct device *, u_long, caddr_t, int, struct proc *);
256
257void wskbd_set_keymap(struct wskbd_softc *, struct wscons_keymap *, int);
258
259int (*wskbd_get_backlight)(struct wskbd_backlight *);
260int (*wskbd_set_backlight)(struct wskbd_backlight *);
261
262void wskbd_kbd_backlight_task(void *);
263#if NWSDISPLAY1 > 0
264void wskbd_brightness_task(void *);
265#endif
266
267struct cfdriver wskbd_cd = {
268 NULL((void *)0), "wskbd", DV_TTY
269};
270
271const struct cfattach wskbd_ca = {
272 sizeof (struct wskbd_softc), wskbd_match, wskbd_attach,
273 wskbd_detach, wskbd_activate
274};
275
276#if defined(__i386__) || defined(__amd64__1)
277extern int kbd_reset;
278#endif
279
280#ifndef WSKBD_DEFAULT_BELL_PITCH400
281#define WSKBD_DEFAULT_BELL_PITCH400 400 /* 400Hz */
282#endif
283#ifndef WSKBD_DEFAULT_BELL_PERIOD100
284#define WSKBD_DEFAULT_BELL_PERIOD100 100 /* 100ms */
285#endif
286#ifndef WSKBD_DEFAULT_BELL_VOLUME50
287#define WSKBD_DEFAULT_BELL_VOLUME50 50 /* 50% volume */
288#endif
289
290struct wskbd_bell_data wskbd_default_bell_data = {
291 WSKBD_BELL_DOALL0x7,
292 WSKBD_DEFAULT_BELL_PITCH400,
293 WSKBD_DEFAULT_BELL_PERIOD100,
294 WSKBD_DEFAULT_BELL_VOLUME50,
295};
296
297#ifndef WSKBD_DEFAULT_KEYREPEAT_DEL1400
298#define WSKBD_DEFAULT_KEYREPEAT_DEL1400 400 /* 400ms to start repeating */
299#endif
300#ifndef WSKBD_DEFAULT_KEYREPEAT_DELN100
301#define WSKBD_DEFAULT_KEYREPEAT_DELN100 100 /* 100ms to between repeats */
302#endif
303
304struct wskbd_keyrepeat_data wskbd_default_keyrepeat_data = {
305 WSKBD_KEYREPEAT_DOALL0x3,
306 WSKBD_DEFAULT_KEYREPEAT_DEL1400,
307 WSKBD_DEFAULT_KEYREPEAT_DELN100,
308};
309
310#if NWSMUX1 > 0 || NWSDISPLAY1 > 0
311struct wssrcops wskbd_srcops = {
312 .type = WSMUX_KBD2,
313 .dopen = wskbd_mux_open,
314 .dclose = wskbd_mux_close,
315 .dioctl = wskbd_do_ioctl,
316 .ddispioctl = wskbd_displayioctl,
317#if NWSDISPLAY1 > 0
318 .dsetdisplay = wskbd_set_display,
319#else
320 .dsetdisplay = NULL((void *)0),
321#endif
322};
323#endif
324
325#if NWSDISPLAY1 > 0
326void wskbd_repeat(void *v);
327#endif
328
329static int wskbd_console_initted;
330static struct wskbd_softc *wskbd_console_device;
331static struct wskbd_internal wskbd_console_data;
332
333void wskbd_update_layout(struct wskbd_internal *, kbd_t);
334
335#if NAUDIO1 > 0
336extern int wskbd_set_mixervolume_dev(void *, long, long);
337#endif
338
339void
340wskbd_update_layout(struct wskbd_internal *id, kbd_t enc)
341{
342 if (enc & KB_METAESC0x00000020)
343 id->t_flags |= WSKFL_METAESC1;
344 else
345 id->t_flags &= ~WSKFL_METAESC1;
346
347 id->t_keymap.layout = enc;
348}
349
350/*
351 * Print function (for parent devices).
352 */
353int
354wskbddevprint(void *aux, const char *pnp)
355{
356#if 0
357 struct wskbddev_attach_args *ap = aux;
358#endif
359
360 if (pnp)
361 printf("wskbd at %s", pnp);
362#if 0
363 printf(" console %d", ap->console);
364#endif
365
366 return (UNCONF1);
367}
368
369int
370wskbd_match(struct device *parent, void *match, void *aux)
371{
372 struct cfdata *cf = match;
373 struct wskbddev_attach_args *ap = aux;
374
375 if (cf->wskbddevcf_consolecf_loc[0] != WSKBDDEVCF_CONSOLE_UNK-1) {
376 /*
377 * If console-ness of device specified, either match
378 * exactly (at high priority), or fail.
379 */
380 if (cf->wskbddevcf_consolecf_loc[0] != 0 && ap->console != 0)
381 return (10);
382 else
383 return (0);
384 }
385
386 /* If console-ness unspecified, it wins. */
387 return (1);
388}
389
390void
391wskbd_attach(struct device *parent, struct device *self, void *aux)
392{
393 struct wskbd_softc *sc = (struct wskbd_softc *)self;
394 struct wskbddev_attach_args *ap = aux;
395 kbd_t layout;
396#if NWSMUX1 > 0
397 struct wsmux_softc *wsmux_sc = NULL((void *)0);
398 int mux, error;
399#endif
400
401 sc->sc_isconsole = ap->console;
402
403#if NWSMUX1 > 0 || NWSDISPLAY1 > 0
404 sc->sc_base.me_ops = &wskbd_srcops;
405#endif
406#if NWSMUX1 > 0
407 mux = sc->sc_base.me_dv.dv_cfdata->wskbddevcf_muxcf_loc[1];
408 if (mux >= 0)
409 wsmux_sc = wsmux_getmux(mux);
410#endif /* NWSMUX > 0 */
411
412 if (ap->console) {
413 sc->id = &wskbd_console_data;
414 } else {
415 sc->id = malloc(sizeof(struct wskbd_internal),
416 M_DEVBUF2, M_WAITOK0x0001 | M_ZERO0x0008);
417 bcopy(ap->keymap, &sc->id->t_keymap, sizeof(sc->id->t_keymap));
418 }
419
420 task_set(&sc->sc_kbd_backlight_task, wskbd_kbd_backlight_task, sc);
421#if NWSDISPLAY1 > 0
422 timeout_set(&sc->sc_repeat_ch, wskbd_repeat, sc);
423 task_set(&sc->sc_brightness_task, wskbd_brightness_task, sc);
424#endif
425
426#if NAUDIO1 > 0
427 sc->sc_audiocookie = ap->audiocookie;
428#endif
429
430 sc->id->t_sc = sc;
431
432 sc->sc_accessops = ap->accessops;
433 sc->sc_accesscookie = ap->accesscookie;
434 sc->sc_repeating = 0;
435 sc->sc_translating = 1;
436 sc->sc_ledstate = -1; /* force update */
437
438 /*
439 * If this layout is the default choice of the driver (i.e. the
440 * driver doesn't know better), pick the existing layout of the
441 * current mux, if any.
442 */
443 layout = sc->id->t_keymap.layout;
444#if NWSMUX1 > 0
445 if (layout & KB_DEFAULT0x80000000) {
446 if (wsmux_sc != NULL((void *)0) && wsmux_get_layout(wsmux_sc) != KB_NONE0x0000)
447 layout = wsmux_get_layout(wsmux_sc);
448 }
449#endif
450 for (;;) {
451 struct wscons_keymap *map;
452 int maplen;
453
454 if (wskbd_load_keymap(&sc->id->t_keymap, layout, &map,
455 &maplen) == 0) {
456 wskbd_set_keymap(sc, map, maplen);
457 break;
458 }
459#if NWSMUX1 > 0
460 if (layout == sc->id->t_keymap.layout)
461 panic("cannot load keymap");
462 if (wsmux_sc != NULL((void *)0) && wsmux_get_layout(wsmux_sc) != KB_NONE0x0000) {
463 printf("\n%s: cannot load keymap, "
464 "falling back to default\n%s",
465 sc->sc_base.me_dv.dv_xname,
466 sc->sc_base.me_dv.dv_xname);
467 layout = wsmux_get_layout(wsmux_sc);
468 } else
469#endif
470 panic("cannot load keymap");
471 }
472 wskbd_update_layout(sc->id, layout);
473
474 /* set default bell and key repeat data */
475 sc->sc_bell_data = wskbd_default_bell_data;
476 sc->sc_keyrepeat_data = wskbd_default_keyrepeat_data;
477
478 if (ap->console) {
479 KASSERT(wskbd_console_initted)((wskbd_console_initted) ? (void)0 : __assert("diagnostic ", "/usr/src/sys/dev/wscons/wskbd.c"
, 479, "wskbd_console_initted"))
;
480 KASSERT(wskbd_console_device == NULL)((wskbd_console_device == ((void *)0)) ? (void)0 : __assert("diagnostic "
, "/usr/src/sys/dev/wscons/wskbd.c", 480, "wskbd_console_device == NULL"
))
;
481
482 wskbd_console_device = sc;
483
484 printf(": console keyboard");
485
486#if NWSDISPLAY1 > 0
487 wsdisplay_set_console_kbd(&sc->sc_base); /* sets sc_displaydv */
488 if (sc->sc_displaydvsc_base.me_dispdv != NULL((void *)0))
489 printf(", using %s", sc->sc_displaydvsc_base.me_dispdv->dv_xname);
490#endif
491 }
492
493#if NWSMUX1 > 0
494 /* Ignore mux for console; it always goes to the console mux. */
495 if (wsmux_sc != NULL((void *)0) && ap->console == 0) {
496 printf(" mux %d\n", mux);
497 error = wsmux_attach_sc(wsmux_sc, &sc->sc_base);
498 if (error)
499 printf("%s: attach error=%d\n",
500 sc->sc_base.me_dv.dv_xname, error);
501
502 /*
503 * Try and set this encoding as the mux default if it
504 * hasn't any yet, and if this is not a driver default
505 * layout (i.e. parent driver pretends to know better).
506 * Note that wsmux_set_layout() rejects layouts with
507 * KB_DEFAULT set.
508 */
509 if (wsmux_get_layout(wsmux_sc) == KB_NONE0x0000)
510 wsmux_set_layout(wsmux_sc, layout);
511 } else
512#endif
513 printf("\n");
514
515#if NWSDISPLAY1 > 0 && NWSMUX1 == 0
516 if (ap->console == 0) {
517 /*
518 * In the non-wsmux world, always connect wskbd0 and wsdisplay0
519 * together.
520 */
521 extern struct cfdriver wsdisplay_cd;
522
523 if (wsdisplay_cd.cd_ndevs != 0 && self->dv_unit == 0) {
524 if (wskbd_set_display(self,
525 wsdisplay_cd.cd_devs[0]) == 0)
526 wsdisplay_set_kbd(wsdisplay_cd.cd_devs[0],
527 (struct wsevsrc *)sc);
528 }
529 }
530#endif
531}
532
533void
534wskbd_cnattach(const struct wskbd_consops *consops, void *conscookie,
535 const struct wskbd_mapdata *mapdata)
536{
537
538 KASSERT(!wskbd_console_initted)((!wskbd_console_initted) ? (void)0 : __assert("diagnostic ",
"/usr/src/sys/dev/wscons/wskbd.c", 538, "!wskbd_console_initted"
))
;
539
540 bcopy(mapdata, &wskbd_console_data.t_keymap, sizeof(*mapdata));
541 wskbd_update_layout(&wskbd_console_data, mapdata->layout);
542
543 wskbd_console_data.t_consops = consops;
544 wskbd_console_data.t_consaccesscookie = conscookie;
545
546#if NWSDISPLAY1 > 0
547 wsdisplay_set_cons_kbd(wskbd_cngetc, wskbd_cnpollc, wskbd_cnbell);
548#endif
549
550 wskbd_console_initted = 1;
551}
552
553void
554wskbd_cndetach(void)
555{
556 KASSERT(wskbd_console_initted)((wskbd_console_initted) ? (void)0 : __assert("diagnostic ", "/usr/src/sys/dev/wscons/wskbd.c"
, 556, "wskbd_console_initted"))
;
557
558 wskbd_console_data.t_keymap.keydesc = NULL((void *)0);
559 wskbd_console_data.t_keymap.layout = KB_NONE0x0000;
560
561 wskbd_console_data.t_consops = NULL((void *)0);
562 wskbd_console_data.t_consaccesscookie = NULL((void *)0);
563
564#if NWSDISPLAY1 > 0
565 wsdisplay_unset_cons_kbd();
566#endif
567
568 wskbd_console_device = NULL((void *)0);
569 wskbd_console_initted = 0;
570}
571
572#if NWSDISPLAY1 > 0
573void
574wskbd_repeat(void *v)
575{
576 struct wskbd_softc *sc = (struct wskbd_softc *)v;
577 int s = spltty()splraise(0x9);
578
579 if (sc->sc_repeating == 0) {
580 /*
581 * race condition: a "key up" event came in when wskbd_repeat()
582 * was already called but not yet spltty()'d
583 */
584 splx(s)spllower(s);
585 return;
586 }
587 if (sc->sc_translating) {
588 /* deliver keys */
589 if (sc->sc_displaydvsc_base.me_dispdv != NULL((void *)0))
590 wsdisplay_kbdinput(sc->sc_displaydvsc_base.me_dispdv,
591 sc->id->t_keymap.layout,
592 sc->id->t_symbols, sc->sc_repeating);
593 } else {
594 /* queue event */
595 wskbd_deliver_event(sc, sc->sc_repeat_type,
596 sc->sc_repeat_value);
597 }
598 if (sc->sc_keyrepeat_data.delN != 0)
599 timeout_add_msec(&sc->sc_repeat_ch, sc->sc_keyrepeat_data.delN);
600 splx(s)spllower(s);
601}
602#endif
603
604int
605wskbd_activate(struct device *self, int act)
606{
607 struct wskbd_softc *sc = (struct wskbd_softc *)self;
608
609 if (act == DVACT_DEACTIVATE1)
610 sc->sc_dying = 1;
611 return (0);
612}
613
614/*
615 * Detach a keyboard. To keep track of users of the softc we keep
616 * a reference count that's incremented while inside, e.g., read.
617 * If the keyboard is active and the reference count is > 0 (0 is the
618 * normal state) we post an event and then wait for the process
619 * that had the reference to wake us up again. Then we blow away the
620 * vnode and return (which will deallocate the softc).
621 */
622int
623wskbd_detach(struct device *self, int flags)
624{
625 struct wskbd_softc *sc = (struct wskbd_softc *)self;
626 struct wseventvar *evar;
627 int maj, mn;
628 int s;
629
630#if NWSMUX1 > 0
631 /* Tell parent mux we're leaving. */
632 if (sc->sc_base.me_parent != NULL((void *)0))
633 wsmux_detach_sc(&sc->sc_base);
634#endif
635
636#if NWSDISPLAY1 > 0
637 if (sc->sc_repeating) {
638 sc->sc_repeating = 0;
639 timeout_del(&sc->sc_repeat_ch);
640 }
641#endif
642
643 if (sc->sc_isconsole) {
644 KASSERT(wskbd_console_device == sc)((wskbd_console_device == sc) ? (void)0 : __assert("diagnostic "
, "/usr/src/sys/dev/wscons/wskbd.c", 644, "wskbd_console_device == sc"
))
;
645 wskbd_cndetach();
646 }
647
648 evar = sc->sc_base.me_evp;
649 if (evar != NULL((void *)0)) {
650 s = spltty()splraise(0x9);
651 if (--sc->sc_refcnt >= 0) {
652 /* Wake everyone by generating a dummy event. */
653 if (++evar->put >= WSEVENT_QSIZE256)
654 evar->put = 0;
655 WSEVENT_WAKEUP(evar){ selwakeup(&(evar)->sel); if ((evar)->wanted) { (evar
)->wanted = 0; wakeup((caddr_t)(evar)); } if ((evar)->async
) pgsigio(&(evar)->sigio, 23, 0); }
;
656 /* Wait for processes to go away. */
657 if (tsleep_nsec(sc, PZERO22, "wskdet", SEC_TO_NSEC(60)))
658 printf("wskbd_detach: %s didn't detach\n",
659 sc->sc_base.me_dv.dv_xname);
660 }
661 splx(s)spllower(s);
662 }
663
664 free(sc->sc_map, M_DEVBUF2,
665 sc->sc_maplen * sizeof(struct wscons_keymap));
666
667 /* locate the major number */
668 for (maj = 0; maj < nchrdev; maj++)
669 if (cdevsw[maj].d_open == wskbdopen)
670 break;
671
672 /* Nuke the vnodes for any open instances. */
673 mn = self->dv_unit;
674 vdevgone(maj, mn, mn, VCHR);
675
676 return (0);
677}
678
679void
680wskbd_input(struct device *dev, u_int type, int value)
681{
682 struct wskbd_softc *sc = (struct wskbd_softc *)dev;
683#if NWSDISPLAY1 > 0
684 int num;
685#endif
686
687#if NWSDISPLAY1 > 0
688 if (sc->sc_repeating) {
689 sc->sc_repeating = 0;
690 timeout_del(&sc->sc_repeat_ch);
691 }
692
693 /*
694 * If /dev/wskbdN is not connected in event mode translate and
695 * send upstream.
696 */
697 if (sc->sc_translating) {
698#ifdef HAVE_BURNER_SUPPORT
699 if (type == WSCONS_EVENT_KEY_DOWN2 && sc->sc_displaydvsc_base.me_dispdv != NULL((void *)0))
700 wsdisplay_burn(sc->sc_displaydvsc_base.me_dispdv, WSDISPLAY_BURN_KBD0x0002);
701#endif
702 num = wskbd_translate(sc->id, type, value);
703 if (num > 0) {
704 if (sc->sc_displaydvsc_base.me_dispdv != NULL((void *)0)) {
705#ifdef HAVE_SCROLLBACK_SUPPORT
706 /* XXX - Shift_R+PGUP(release) emits PrtSc */
707 if (sc->id->t_symbols[0] != KS_Print_Screen0xf3c2) {
708 wsscrollback(sc->sc_displaydvsc_base.me_dispdv,
709 WSDISPLAY_SCROLL_RESET2);
710 }
711#endif
712 wsdisplay_kbdinput(sc->sc_displaydvsc_base.me_dispdv,
713 sc->id->t_keymap.layout,
714 sc->id->t_symbols, num);
715 }
716
717 if (sc->sc_keyrepeat_data.del1 != 0) {
718 sc->sc_repeating = num;
719 timeout_add_msec(&sc->sc_repeat_ch,
720 sc->sc_keyrepeat_data.del1);
721 }
722 }
723 return;
724 }
725#endif
726
727 wskbd_deliver_event(sc, type, value);
728
729#if NWSDISPLAY1 > 0
730 /* Repeat key presses if enabled. */
731 if (type == WSCONS_EVENT_KEY_DOWN2 && sc->sc_keyrepeat_data.del1 != 0) {
732 sc->sc_repeat_type = type;
733 sc->sc_repeat_value = value;
734 sc->sc_repeating = 1;
735 timeout_add_msec(&sc->sc_repeat_ch, sc->sc_keyrepeat_data.del1);
736 }
737#endif
738}
739
740/*
741 * Keyboard is generating events. Turn this keystroke into an
742 * event and put it in the queue. If the queue is full, the
743 * keystroke is lost (sorry!).
744 */
745void
746wskbd_deliver_event(struct wskbd_softc *sc, u_int type, int value)
747{
748 struct wseventvar *evar;
749 struct wscons_event *ev;
750 int put;
751
752 evar = sc->sc_base.me_evp;
753
754 if (evar == NULL((void *)0)) {
755 DPRINTF(("%s: not open\n", __func__));
756 return;
757 }
758
759#ifdef DIAGNOSTIC1
760 if (evar->q == NULL((void *)0)) {
761 printf("wskbd_input: evar->q=NULL\n");
762 return;
763 }
764#endif
765
766 put = evar->put;
767 ev = &evar->q[put];
768 put = (put + 1) % WSEVENT_QSIZE256;
769 if (put == evar->get) {
770 log(LOG_WARNING4, "%s: event queue overflow\n",
771 sc->sc_base.me_dv.dv_xname);
772 return;
773 }
774 ev->type = type;
775 ev->value = value;
776 nanotime(&ev->time);
777 evar->put = put;
778 WSEVENT_WAKEUP(evar){ selwakeup(&(evar)->sel); if ((evar)->wanted) { (evar
)->wanted = 0; wakeup((caddr_t)(evar)); } if ((evar)->async
) pgsigio(&(evar)->sigio, 23, 0); }
;
779}
780
781#ifdef WSDISPLAY_COMPAT_RAWKBD1
782void
783wskbd_rawinput(struct device *dev, u_char *buf, int len)
784{
785#if NWSDISPLAY1 > 0
786 struct wskbd_softc *sc = (struct wskbd_softc *)dev;
787
788 if (sc->sc_displaydvsc_base.me_dispdv != NULL((void *)0))
789 wsdisplay_rawkbdinput(sc->sc_displaydvsc_base.me_dispdv, buf, len);
790#endif
791}
792#endif /* WSDISPLAY_COMPAT_RAWKBD */
793
794int
795wskbd_enable(struct wskbd_softc *sc, int on)
796{
797 int error;
798
799#if NWSDISPLAY1 > 0
800 if (sc->sc_displaydvsc_base.me_dispdv != NULL((void *)0))
801 return (0);
802
803 /* Always cancel auto repeat when fiddling with the kbd. */
804 if (sc->sc_repeating) {
805 sc->sc_repeating = 0;
806 timeout_del(&sc->sc_repeat_ch);
807 }
808#endif
809
810 error = (*sc->sc_accessops->enable)(sc->sc_accesscookie, on);
811 DPRINTF(("%s: sc=%p on=%d res=%d\n", __func__, sc, on, error));
812 return (error);
813}
814
815#if NWSMUX1 > 0
816int
817wskbd_mux_open(struct wsevsrc *me, struct wseventvar *evp)
818{
819 struct wskbd_softc *sc = (struct wskbd_softc *)me;
820
821 if (sc->sc_dying)
822 return (EIO5);
823
824 return (wskbd_do_open(sc, evp));
825}
826#endif
827
828int
829wskbdopen(dev_t dev, int flags, int mode, struct proc *p)
830{
831 struct wskbd_softc *sc;
832 struct wseventvar *evar;
833 int unit, error;
834
835 unit = minor(dev)((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8))
;
836 if (unit >= wskbd_cd.cd_ndevs || /* make sure it was attached */
837 (sc = wskbd_cd.cd_devs[unit]) == NULL((void *)0))
838 return (ENXIO6);
839
840#if NWSMUX1 > 0
841 DPRINTF(("%s: %s mux=%p\n", __func__, sc->sc_base.me_dv.dv_xname,
842 sc->sc_base.me_parent));
843#endif
844
845 if (sc->sc_dying)
846 return (EIO5);
847
848 if ((flags & (FREAD0x0001 | FWRITE0x0002)) == FWRITE0x0002) {
849 /* Not opening for read, only ioctl is available. */
850 return (0);
851 }
852
853#if NWSMUX1 > 0
854 if (sc->sc_base.me_parent != NULL((void *)0)) {
855 /* Grab the keyboard out of the greedy hands of the mux. */
856 DPRINTF(("%s: detach\n", __func__));
857 wsmux_detach_sc(&sc->sc_base);
858 }
859#endif
860
861 if (sc->sc_base.me_evp != NULL((void *)0))
862 return (EBUSY16);
863
864 evar = &sc->sc_base.me_evar;
865 if (wsevent_init(evar))
866 return (EBUSY16);
867
868 error = wskbd_do_open(sc, evar);
869 if (error)
870 wsevent_fini(evar);
871 return (error);
872}
873
874int
875wskbd_do_open(struct wskbd_softc *sc, struct wseventvar *evp)
876{
877 int error;
878
879 /* The device could already be attached to a mux. */
880 if (sc->sc_base.me_evp != NULL((void *)0))
881 return (EBUSY16);
882
883 sc->sc_base.me_evp = evp;
884 sc->sc_translating = 0;
885
886 error = wskbd_enable(sc, 1);
887 if (error)
888 sc->sc_base.me_evp = NULL((void *)0);
889 return (error);
890}
891
892int
893wskbdclose(dev_t dev, int flags, int mode, struct proc *p)
894{
895 struct wskbd_softc *sc =
896 (struct wskbd_softc *)wskbd_cd.cd_devs[minor(dev)((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8))
];
897 struct wseventvar *evar = sc->sc_base.me_evp;
898
899 if ((flags & (FREAD0x0001 | FWRITE0x0002)) == FWRITE0x0002) {
900 /* not open for read */
901 return (0);
902 }
903
904 sc->sc_base.me_evp = NULL((void *)0);
905 sc->sc_translating = 1;
906 (void)wskbd_enable(sc, 0);
907 wsevent_fini(evar);
908
909#if NWSMUX1 > 0
910 if (sc->sc_base.me_parent == NULL((void *)0)) {
911 int mux, error;
912
913 DPRINTF(("%s: attach\n", __func__));
914 mux = sc->sc_base.me_dv.dv_cfdata->wskbddevcf_muxcf_loc[1];
915 if (mux >= 0) {
916 error = wsmux_attach_sc(wsmux_getmux(mux), &sc->sc_base);
917 if (error)
918 printf("%s: can't attach mux (error=%d)\n",
919 sc->sc_base.me_dv.dv_xname, error);
920 }
921 }
922#endif
923
924 return (0);
925}
926
927#if NWSMUX1 > 0
928int
929wskbd_mux_close(struct wsevsrc *me)
930{
931 struct wskbd_softc *sc = (struct wskbd_softc *)me;
932
933 (void)wskbd_enable(sc, 0);
934 sc->sc_translating = 1;
935 sc->sc_base.me_evp = NULL((void *)0);
936
937 return (0);
938}
939#endif
940
941int
942wskbdread(dev_t dev, struct uio *uio, int flags)
943{
944 struct wskbd_softc *sc = wskbd_cd.cd_devs[minor(dev)((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8))
];
945 int error;
946
947 if (sc->sc_dying)
948 return (EIO5);
949
950#ifdef DIAGNOSTIC1
951 if (sc->sc_base.me_evp == NULL((void *)0)) {
952 printf("wskbdread: evp == NULL\n");
953 return (EINVAL22);
954 }
955#endif
956
957 sc->sc_refcnt++;
958 error = wsevent_read(&sc->sc_base.me_evar, uio, flags);
959 if (--sc->sc_refcnt < 0) {
960 wakeup(sc);
961 error = EIO5;
962 }
963 return (error);
964}
965
966int
967wskbdioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
968{
969 struct wskbd_softc *sc = wskbd_cd.cd_devs[minor(dev)((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8))
];
970 int error;
971
972 sc->sc_refcnt++;
973 error = wskbd_do_ioctl_sc(sc, cmd, data, flag, p, 0);
974 if (--sc->sc_refcnt < 0)
975 wakeup(sc);
976 return (error);
977}
978
979/* A wrapper around the ioctl() workhorse to make reference counting easy. */
980int
981wskbd_do_ioctl(struct device *dv, u_long cmd, caddr_t data, int flag,
982 struct proc *p)
983{
984 struct wskbd_softc *sc = (struct wskbd_softc *)dv;
985 int error;
986
987 sc->sc_refcnt++;
988 error = wskbd_do_ioctl_sc(sc, cmd, data, flag, p, 1);
989 if (--sc->sc_refcnt < 0)
990 wakeup(sc);
991 return (error);
992}
993
994int
995wskbd_do_ioctl_sc(struct wskbd_softc *sc, u_long cmd, caddr_t data, int flag,
996 struct proc *p, int evsrc)
997{
998 struct wseventvar *evar;
999 int error;
1000
1001 /*
1002 * Try the generic ioctls that the wskbd interface supports.
1003 */
1004 switch (cmd) {
1005 case FIONBIO((unsigned long)0x80000000 | ((sizeof(int) & 0x1fff) <<
16) | ((('f')) << 8) | ((126)))
: /* we will remove this someday (soon???) */
1006 return (0);
1007
1008 case FIOASYNC((unsigned long)0x80000000 | ((sizeof(int) & 0x1fff) <<
16) | ((('f')) << 8) | ((125)))
:
1009 if (sc->sc_base.me_evp == NULL((void *)0))
1010 return (EINVAL22);
1011 sc->sc_base.me_evp->async = *(int *)data != 0;
1012 return (0);
1013
1014 case FIOGETOWN((unsigned long)0x40000000 | ((sizeof(int) & 0x1fff) <<
16) | ((('f')) << 8) | ((123)))
:
1015 case TIOCGPGRP((unsigned long)0x40000000 | ((sizeof(int) & 0x1fff) <<
16) | ((('t')) << 8) | ((119)))
:
1016 evar = sc->sc_base.me_evp;
1017 if (evar == NULL((void *)0))
1018 return (EINVAL22);
1019 sigio_getown(&evar->sigio, cmd, data);
1020 return (0);
1021
1022 case FIOSETOWN((unsigned long)0x80000000 | ((sizeof(int) & 0x1fff) <<
16) | ((('f')) << 8) | ((124)))
:
1023 case TIOCSPGRP((unsigned long)0x80000000 | ((sizeof(int) & 0x1fff) <<
16) | ((('t')) << 8) | ((118)))
:
1024 evar = sc->sc_base.me_evp;
1025 if (evar == NULL((void *)0))
1026 return (EINVAL22);
1027 return (sigio_setown(&evar->sigio, cmd, data));
1028 }
1029
1030 /*
1031 * Try the keyboard driver for WSKBDIO ioctls. It returns -1
1032 * if it didn't recognize the request.
1033 */
1034 error = wskbd_displayioctl_sc(sc, cmd, data, flag, p, evsrc);
1035 return (error != -1 ? error : ENOTTY25);
1036}
1037
1038/*
1039 * WSKBDIO ioctls, handled in both emulation mode and in ``raw'' mode.
1040 * Some of these have no real effect in raw mode, however.
1041 */
1042int
1043wskbd_displayioctl(struct device *dv, u_long cmd, caddr_t data, int flag,
1044 struct proc *p)
1045{
1046 struct wskbd_softc *sc = (struct wskbd_softc *)dv;
1047
1048 return (wskbd_displayioctl_sc(sc, cmd, data, flag, p, 1));
1049}
1050
1051int
1052wskbd_displayioctl_sc(struct wskbd_softc *sc, u_long cmd, caddr_t data,
1053 int flag, struct proc *p, int evsrc)
1054{
1055 struct wskbd_bell_data *ubdp, *kbdp;
1056 struct wskbd_keyrepeat_data *ukdp, *kkdp;
1057 struct wskbd_map_data *umdp;
1058 struct wskbd_encoding_data *uedp;
1059 kbd_t enc;
1060 void *buf;
1061 int len, error;
1062 int count, i;
1063
1064 switch (cmd) {
1065 case WSKBDIO_BELL((unsigned long)0x20000000 | ((0 & 0x1fff) << 16) |
((('W')) << 8) | ((1)))
:
1066 case WSKBDIO_COMPLEXBELL((unsigned long)0x80000000 | ((sizeof(struct wskbd_bell_data)
& 0x1fff) << 16) | ((('W')) << 8) | ((2)))
:
1067 case WSKBDIO_SETBELL((unsigned long)0x80000000 | ((sizeof(struct wskbd_bell_data)
& 0x1fff) << 16) | ((('W')) << 8) | ((3)))
:
1068 case WSKBDIO_SETKEYREPEAT((unsigned long)0x80000000 | ((sizeof(struct wskbd_keyrepeat_data
) & 0x1fff) << 16) | ((('W')) << 8) | ((7)))
:
1069 case WSKBDIO_SETDEFAULTKEYREPEAT((unsigned long)0x80000000 | ((sizeof(struct wskbd_keyrepeat_data
) & 0x1fff) << 16) | ((('W')) << 8) | ((9)))
:
1070 case WSKBDIO_SETMAP((unsigned long)0x80000000 | ((sizeof(struct wskbd_map_data) &
0x1fff) << 16) | ((('W')) << 8) | ((14)))
:
1071 case WSKBDIO_SETENCODING((unsigned long)0x80000000 | ((sizeof(kbd_t) & 0x1fff) <<
16) | ((('W')) << 8) | ((16)))
:
1072 case WSKBDIO_SETBACKLIGHT((unsigned long)0x80000000 | ((sizeof(struct wskbd_backlight)
& 0x1fff) << 16) | ((('W')) << 8) | ((18)))
:
1073 if ((flag & FWRITE0x0002) == 0)
1074 return (EACCES13);
1075 }
1076
1077 switch (cmd) {
1078#define SETBELL(dstp, srcp, dfltp) \
1079 do { \
1080 (dstp)->pitch = ((srcp)->which & WSKBD_BELL_DOPITCH0x1) ? \
1081 (srcp)->pitch : (dfltp)->pitch; \
1082 (dstp)->period = ((srcp)->which & WSKBD_BELL_DOPERIOD0x2) ? \
1083 (srcp)->period : (dfltp)->period; \
1084 (dstp)->volume = ((srcp)->which & WSKBD_BELL_DOVOLUME0x4) ? \
1085 (srcp)->volume : (dfltp)->volume; \
1086 (dstp)->which = WSKBD_BELL_DOALL0x7; \
1087 } while (0)
1088
1089 case WSKBDIO_BELL((unsigned long)0x20000000 | ((0 & 0x1fff) << 16) |
((('W')) << 8) | ((1)))
:
1090 return ((*sc->sc_accessops->ioctl)(sc->sc_accesscookie,
1091 WSKBDIO_COMPLEXBELL((unsigned long)0x80000000 | ((sizeof(struct wskbd_bell_data)
& 0x1fff) << 16) | ((('W')) << 8) | ((2)))
, (caddr_t)&sc->sc_bell_data, flag, p));
1092
1093 case WSKBDIO_COMPLEXBELL((unsigned long)0x80000000 | ((sizeof(struct wskbd_bell_data)
& 0x1fff) << 16) | ((('W')) << 8) | ((2)))
:
1094 ubdp = (struct wskbd_bell_data *)data;
1095 SETBELL(ubdp, ubdp, &sc->sc_bell_data);
1096 return ((*sc->sc_accessops->ioctl)(sc->sc_accesscookie,
1097 WSKBDIO_COMPLEXBELL((unsigned long)0x80000000 | ((sizeof(struct wskbd_bell_data)
& 0x1fff) << 16) | ((('W')) << 8) | ((2)))
, (caddr_t)ubdp, flag, p));
1098
1099 case WSKBDIO_SETBELL((unsigned long)0x80000000 | ((sizeof(struct wskbd_bell_data)
& 0x1fff) << 16) | ((('W')) << 8) | ((3)))
:
1100 kbdp = &sc->sc_bell_data;
1101setbell:
1102 ubdp = (struct wskbd_bell_data *)data;
1103 SETBELL(kbdp, ubdp, kbdp);
1104 return (0);
1105
1106 case WSKBDIO_GETBELL((unsigned long)0x40000000 | ((sizeof(struct wskbd_bell_data)
& 0x1fff) << 16) | ((('W')) << 8) | ((4)))
:
1107 kbdp = &sc->sc_bell_data;
1108getbell:
1109 ubdp = (struct wskbd_bell_data *)data;
1110 SETBELL(ubdp, kbdp, kbdp);
1111 return (0);
1112
1113 case WSKBDIO_SETDEFAULTBELL((unsigned long)0x80000000 | ((sizeof(struct wskbd_bell_data)
& 0x1fff) << 16) | ((('W')) << 8) | ((5)))
:
1114 if ((error = suser(p)) != 0)
1115 return (error);
1116 kbdp = &wskbd_default_bell_data;
1117 goto setbell;
1118
1119
1120 case WSKBDIO_GETDEFAULTBELL((unsigned long)0x40000000 | ((sizeof(struct wskbd_bell_data)
& 0x1fff) << 16) | ((('W')) << 8) | ((6)))
:
1121 kbdp = &wskbd_default_bell_data;
1122 goto getbell;
1123
1124#undef SETBELL
1125
1126#define SETKEYREPEAT(dstp, srcp, dfltp) \
1127 do { \
1128 (dstp)->del1 = ((srcp)->which & WSKBD_KEYREPEAT_DODEL10x1) ? \
1129 (srcp)->del1 : (dfltp)->del1; \
1130 (dstp)->delN = ((srcp)->which & WSKBD_KEYREPEAT_DODELN0x2) ? \
1131 (srcp)->delN : (dfltp)->delN; \
1132 (dstp)->which = WSKBD_KEYREPEAT_DOALL0x3; \
1133 } while (0)
1134
1135 case WSKBDIO_SETKEYREPEAT((unsigned long)0x80000000 | ((sizeof(struct wskbd_keyrepeat_data
) & 0x1fff) << 16) | ((('W')) << 8) | ((7)))
:
1136 kkdp = &sc->sc_keyrepeat_data;
1137setkeyrepeat:
1138 ukdp = (struct wskbd_keyrepeat_data *)data;
1139 SETKEYREPEAT(kkdp, ukdp, kkdp);
1140 return (0);
1141
1142 case WSKBDIO_GETKEYREPEAT((unsigned long)0x40000000 | ((sizeof(struct wskbd_keyrepeat_data
) & 0x1fff) << 16) | ((('W')) << 8) | ((8)))
:
1143 kkdp = &sc->sc_keyrepeat_data;
1144getkeyrepeat:
1145 ukdp = (struct wskbd_keyrepeat_data *)data;
1146 SETKEYREPEAT(ukdp, kkdp, kkdp);
1147 return (0);
1148
1149 case WSKBDIO_SETDEFAULTKEYREPEAT((unsigned long)0x80000000 | ((sizeof(struct wskbd_keyrepeat_data
) & 0x1fff) << 16) | ((('W')) << 8) | ((9)))
:
1150 if ((error = suser(p)) != 0)
1151 return (error);
1152 kkdp = &wskbd_default_keyrepeat_data;
1153 goto setkeyrepeat;
1154
1155
1156 case WSKBDIO_GETDEFAULTKEYREPEAT((unsigned long)0x40000000 | ((sizeof(struct wskbd_keyrepeat_data
) & 0x1fff) << 16) | ((('W')) << 8) | ((10)))
:
1157 kkdp = &wskbd_default_keyrepeat_data;
1158 goto getkeyrepeat;
1159
1160#undef SETKEYREPEAT
1161
1162 case WSKBDIO_SETMAP((unsigned long)0x80000000 | ((sizeof(struct wskbd_map_data) &
0x1fff) << 16) | ((('W')) << 8) | ((14)))
:
1163 umdp = (struct wskbd_map_data *)data;
1164 if (umdp->maplen > WSKBDIO_MAXMAPLEN65536)
1165 return (EINVAL22);
1166
1167 buf = mallocarray(umdp->maplen, sizeof(struct wscons_keymap),
1168 M_TEMP127, M_WAITOK0x0001);
1169 len = umdp->maplen * sizeof(struct wscons_keymap);
1170
1171 error = copyin(umdp->map, buf, len);
1172 if (error == 0) {
1173 struct wscons_keymap *map;
1174
1175 map = wskbd_init_keymap(umdp->maplen);
1176 memcpy(map, buf, len)__builtin_memcpy((map), (buf), (len));
1177 wskbd_set_keymap(sc, map, umdp->maplen);
1178 /* drop the variant bits handled by the map */
1179 enc = KB_USER0x0100 | (KB_VARIANT(sc->id->t_keymap.layout)((sc->id->t_keymap.layout) & 0xffff00ff) &
1180 KB_HANDLEDBYWSKBD(0x00000020 | 0x80000000 | 0x00000080));
1181 wskbd_update_layout(sc->id, enc);
1182 }
1183 free(buf, M_TEMP127, len);
1184 return(error);
1185
1186 case WSKBDIO_GETMAP(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct wskbd_map_data) & 0x1fff) << 16) | ((('W'))
<< 8) | ((13)))
:
1187 umdp = (struct wskbd_map_data *)data;
1188 if (umdp->maplen > sc->sc_maplen)
1189 umdp->maplen = sc->sc_maplen;
1190 error = copyout(sc->sc_map, umdp->map,
1191 umdp->maplen*sizeof(struct wscons_keymap));
1192 return(error);
1193
1194 case WSKBDIO_GETENCODING((unsigned long)0x40000000 | ((sizeof(kbd_t) & 0x1fff) <<
16) | ((('W')) << 8) | ((15)))
:
1195 /* Do not advertise encoding to the parent mux. */
1196 if (evsrc && (sc->id->t_keymap.layout & KB_NOENCODING0x00000080))
1197 return (ENOTTY25);
1198 *((kbd_t *)data) = sc->id->t_keymap.layout & ~KB_DEFAULT0x80000000;
1199 return(0);
1200
1201 case WSKBDIO_SETENCODING((unsigned long)0x80000000 | ((sizeof(kbd_t) & 0x1fff) <<
16) | ((('W')) << 8) | ((16)))
:
1202 enc = *((kbd_t *)data);
1203 if (KB_ENCODING(enc)((enc) & 0x0000ff00) == KB_USER0x0100) {
1204 /* user map must already be loaded */
1205 if (KB_ENCODING(sc->id->t_keymap.layout)((sc->id->t_keymap.layout) & 0x0000ff00) != KB_USER0x0100)
1206 return (EINVAL22);
1207 /* map variants make no sense */
1208 if (KB_VARIANT(enc)((enc) & 0xffff00ff) & ~KB_HANDLEDBYWSKBD(0x00000020 | 0x80000000 | 0x00000080))
1209 return (EINVAL22);
1210 } else if (sc->id->t_keymap.layout & KB_NOENCODING0x00000080) {
1211 return (0);
1212 } else {
1213 struct wscons_keymap *map;
1214 int maplen;
1215
1216 error = wskbd_load_keymap(&sc->id->t_keymap, enc,
1217 &map, &maplen);
1218 if (error)
1219 return (error);
1220 wskbd_set_keymap(sc, map, maplen);
1221 }
1222 wskbd_update_layout(sc->id, enc);
1223#if NWSMUX1 > 0
1224 /* Update mux default layout */
1225 if (sc->sc_base.me_parent != NULL((void *)0))
1226 wsmux_set_layout(sc->sc_base.me_parent, enc);
1227#endif
1228 return (0);
1229
1230 case WSKBDIO_GETENCODINGS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct wskbd_encoding_data) & 0x1fff) << 16) | (((
'W')) << 8) | ((21)))
:
1231 uedp = (struct wskbd_encoding_data *)data;
1232 for (count = 0; sc->id->t_keymap.keydesc[count].name; count++)
1233 ;
1234 if (uedp->nencodings > count)
1235 uedp->nencodings = count;
1236 for (i = 0; i < uedp->nencodings; i++) {
1237 error = copyout(&sc->id->t_keymap.keydesc[i].name,
1238 &uedp->encodings[i], sizeof(kbd_t));
1239 if (error)
1240 return (error);
1241 }
1242 return (0);
1243
1244 case WSKBDIO_GETBACKLIGHT((unsigned long)0x40000000 | ((sizeof(struct wskbd_backlight)
& 0x1fff) << 16) | ((('W')) << 8) | ((17)))
:
1245 if (wskbd_get_backlight != NULL((void *)0))
1246 return (*wskbd_get_backlight)((struct wskbd_backlight *)data);
1247 break;
1248
1249 case WSKBDIO_SETBACKLIGHT((unsigned long)0x80000000 | ((sizeof(struct wskbd_backlight)
& 0x1fff) << 16) | ((('W')) << 8) | ((18)))
:
1250 if (wskbd_set_backlight != NULL((void *)0))
1251 return (*wskbd_set_backlight)((struct wskbd_backlight *)data);
1252 break;
1253 }
1254
1255 /*
1256 * Try the keyboard driver for WSKBDIO ioctls. It returns -1
1257 * if it didn't recognize the request, and in turn we return
1258 * -1 if we didn't recognize the request.
1259 */
1260/* printf("kbdaccess\n"); */
1261 error = (*sc->sc_accessops->ioctl)(sc->sc_accesscookie, cmd, data,
1262 flag, p);
1263#ifdef WSDISPLAY_COMPAT_RAWKBD1
1264 if (!error && cmd == WSKBDIO_SETMODE((unsigned long)0x80000000 | ((sizeof(int) & 0x1fff) <<
16) | ((('W')) << 8) | ((19)))
&& *(int *)data == WSKBD_RAW1) {
1265 int s = spltty()splraise(0x9);
1266 sc->id->t_modifiers &= ~(MOD_SHIFT_L(1 << 0) | MOD_SHIFT_R(1 << 1)
1267 | MOD_CONTROL_L(1 << 4) | MOD_CONTROL_R(1 << 5)
1268 | MOD_META_L(1 << 6) | MOD_META_R(1 << 7)
1269 | MOD_COMMAND(1 << 12)
1270 | MOD_COMMAND1(1 << 13) | MOD_COMMAND2(1 << 14));
1271#if NWSDISPLAY1 > 0
1272 if (sc->sc_repeating) {
1273 sc->sc_repeating = 0;
1274 timeout_del(&sc->sc_repeat_ch);
1275 }
1276#endif
1277 splx(s)spllower(s);
1278 }
1279#endif
1280 return (error);
1281}
1282
1283int
1284wskbdkqfilter(dev_t dev, struct knote *kn)
1285{
1286 struct wskbd_softc *sc = wskbd_cd.cd_devs[minor(dev)((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8))
];
1287
1288 if (sc->sc_base.me_evp == NULL((void *)0))
1289 return (ENXIO6);
1290 return (wsevent_kqfilter(sc->sc_base.me_evp, kn));
1291}
1292
1293#if NWSDISPLAY1 > 0
1294
1295int
1296wskbd_pickfree(void)
1297{
1298 int i;
1299 struct wskbd_softc *sc;
1300
1301 for (i = 0; i < wskbd_cd.cd_ndevs; i++) {
1302 if ((sc = wskbd_cd.cd_devs[i]) == NULL((void *)0))
1303 continue;
1304 if (sc->sc_displaydvsc_base.me_dispdv == NULL((void *)0))
1305 return (i);
1306 }
1307 return (-1);
1308}
1309
1310struct wsevsrc *
1311wskbd_set_console_display(struct device *displaydv, struct wsevsrc *me)
1312{
1313 struct wskbd_softc *sc = wskbd_console_device;
1314
1315 if (sc == NULL((void *)0))
1316 return (NULL((void *)0));
1317 sc->sc_displaydvsc_base.me_dispdv = displaydv;
1318#if NWSMUX1 > 0
1319 (void)wsmux_attach_sc((struct wsmux_softc *)me, &sc->sc_base);
1320#endif
1321 return (&sc->sc_base);
1322}
1323
1324int
1325wskbd_set_display(struct device *dv, struct device *displaydv)
1326{
1327 struct wskbd_softc *sc = (struct wskbd_softc *)dv;
1328 struct device *odisplaydv;
1329 int error;
1330
1331 DPRINTF(("%s: %s odisp=%p disp=%p cons=%d\n", __func__,
1332 dv->dv_xname, sc->sc_displaydv, displaydv,
1333 sc->sc_isconsole));
1334
1335 if (sc->sc_isconsole)
1336 return (EBUSY16);
1337
1338 if (displaydv != NULL((void *)0)) {
1339 if (sc->sc_displaydvsc_base.me_dispdv != NULL((void *)0))
1340 return (EBUSY16);
1341 } else {
1342 if (sc->sc_displaydvsc_base.me_dispdv == NULL((void *)0))
1343 return (ENXIO6);
1344 }
1345
1346 odisplaydv = sc->sc_displaydvsc_base.me_dispdv;
1347 sc->sc_displaydvsc_base.me_dispdv = NULL((void *)0);
1348 error = wskbd_enable(sc, displaydv != NULL((void *)0));
1349 sc->sc_displaydvsc_base.me_dispdv = displaydv;
1350 if (error) {
1351 sc->sc_displaydvsc_base.me_dispdv = odisplaydv;
1352 return (error);
1353 }
1354
1355 if (displaydv)
1356 printf("%s: connecting to %s\n",
1357 sc->sc_base.me_dv.dv_xname, displaydv->dv_xname);
1358 else
1359 printf("%s: disconnecting from %s\n",
1360 sc->sc_base.me_dv.dv_xname, odisplaydv->dv_xname);
1361
1362 return (0);
1363}
1364
1365#endif /* NWSDISPLAY > 0 */
1366
1367#if NWSMUX1 > 0
1368int
1369wskbd_add_mux(int unit, struct wsmux_softc *muxsc)
1370{
1371 struct wskbd_softc *sc;
1372
1373 if (unit < 0 || unit >= wskbd_cd.cd_ndevs ||
1374 (sc = wskbd_cd.cd_devs[unit]) == NULL((void *)0))
1375 return (ENXIO6);
1376
1377 if (sc->sc_base.me_parent != NULL((void *)0) || sc->sc_base.me_evp != NULL((void *)0))
1378 return (EBUSY16);
1379
1380 return (wsmux_attach_sc(muxsc, &sc->sc_base));
1381}
1382#endif
1383
1384/*
1385 * Console interface.
1386 */
1387int
1388wskbd_cngetc(dev_t dev)
1389{
1390 static int num = 0;
1391 static int pos;
1392 u_int type;
1393 int data;
1394 keysym_t ks;
1395
1396 if (!wskbd_console_initted)
1397 return 0;
1398
1399 if (wskbd_console_device != NULL((void *)0) &&
1400 !wskbd_console_device->sc_translating)
1401 return 0;
1402
1403 for(;;) {
1404 if (num-- > 0) {
1405 ks = wskbd_console_data.t_symbols[pos++];
1406 if (KS_GROUP(ks)((ks) >= 0x0300 && (ks) < 0x0370 ? 0xf801 : (((
ks) & 0xf000) == 0xe000 ? 0xf803 : (((ks) & 0xf800) ==
0xf000 ? ((ks) & 0xff00) : 0xf802)))
== KS_GROUP_Ascii0xf802)
1407 return (KS_VALUE(ks)(((ks) & 0xf000) == 0xe000 ? ((ks) & 0x0fff) : (((ks)
& 0xf800) == 0xf000 ? ((ks) & 0x00ff) : (ks)))
);
1408 } else {
1409 (*wskbd_console_data.t_consops->getc)
1410 (wskbd_console_data.t_consaccesscookie,
1411 &type, &data);
1412 num = wskbd_translate(&wskbd_console_data, type, data);
1413 pos = 0;
1414 }
1415 }
1416}
1417
1418void
1419wskbd_cnpollc(dev_t dev, int poll)
1420{
1421 if (!wskbd_console_initted)
1422 return;
1423
1424 if (wskbd_console_device != NULL((void *)0) &&
1425 !wskbd_console_device->sc_translating)
1426 return;
1427
1428 (*wskbd_console_data.t_consops->pollc)
1429 (wskbd_console_data.t_consaccesscookie, poll);
1430}
1431
1432void
1433wskbd_cnbell(dev_t dev, u_int pitch, u_int period, u_int volume)
1434{
1435 if (!wskbd_console_initted)
1436 return;
1437
1438 if (wskbd_console_data.t_consops->bell != NULL((void *)0))
1439 (*wskbd_console_data.t_consops->bell)
1440 (wskbd_console_data.t_consaccesscookie, pitch, period,
1441 volume);
1442}
1443
1444void
1445update_leds(struct wskbd_internal *id)
1446{
1447 int new_state;
1448
1449 new_state = 0;
1450 if (id->t_modifiers & (MOD_SHIFTLOCK(1 << 2) | MOD_CAPSLOCK(1 << 3)))
1451 new_state |= WSKBD_LED_CAPS0x01;
1452 if (id->t_modifiers & MOD_NUMLOCK(1 << 9))
1453 new_state |= WSKBD_LED_NUM0x02;
1454 if (id->t_modifiers & MOD_COMPOSE(1 << 10))
1455 new_state |= WSKBD_LED_COMPOSE0x08;
1456 if (id->t_modifiers & MOD_HOLDSCREEN(1 << 11))
1457 new_state |= WSKBD_LED_SCROLL0x04;
1458
1459 if (id->t_sc && new_state != id->t_sc->sc_ledstate) {
1460 (*id->t_sc->sc_accessops->set_leds)
1461 (id->t_sc->sc_accesscookie, new_state);
1462 id->t_sc->sc_ledstate = new_state;
1463 }
1464}
1465
1466void
1467update_modifier(struct wskbd_internal *id, u_int type, int toggle, int mask)
1468{
1469 if (toggle) {
1470 if (type == WSCONS_EVENT_KEY_DOWN2)
1471 id->t_modifiers ^= mask;
1472 } else {
1473 if (type == WSCONS_EVENT_KEY_DOWN2)
1474 id->t_modifiers |= mask;
1475 else
1476 id->t_modifiers &= ~mask;
1477 }
1478 if (mask & MOD_ANYLED((1 << 2) | (1 << 3) | (1 << 9) | (1 <<
10) | (1 << 11))
)
1479 update_leds(id);
1480}
1481
1482#if NWSDISPLAY1 > 0
1483void
1484change_displayparam(struct wskbd_softc *sc, int param, int updown,
1485 int wraparound)
1486{
1487 int res;
1488 struct wsdisplay_param dp;
1489
1490 dp.param = param;
1491 res = wsdisplay_param(sc->sc_displaydvsc_base.me_dispdv, WSDISPLAYIO_GETPARAM(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct wsdisplay_param) & 0x1fff) << 16) | ((('W')
) << 8) | ((89)))
, &dp);
1492
1493 if (res == EINVAL22)
1494 return; /* no such parameter */
1495
1496 dp.curval += updown;
1497 if (dp.max < dp.curval)
1498 dp.curval = wraparound ? dp.min : dp.max;
1499 else
1500 if (dp.curval < dp.min)
1501 dp.curval = wraparound ? dp.max : dp.min;
1502 wsdisplay_param(sc->sc_displaydvsc_base.me_dispdv, WSDISPLAYIO_SETPARAM(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct wsdisplay_param) & 0x1fff) << 16) | ((('W')
) << 8) | ((90)))
, &dp);
1503}
1504#endif
1505
1506int
1507internal_command(struct wskbd_softc *sc, u_int *type, keysym_t ksym,
1508 keysym_t ksym2)
1509{
1510 switch (ksym) {
1511 case KS_Cmd0xf10d:
1512 update_modifier(sc->id, *type, 0, MOD_COMMAND(1 << 12));
1513 ksym = ksym2;
1514 break;
1515
1516 case KS_Cmd10xf10e:
1517 update_modifier(sc->id, *type, 0, MOD_COMMAND1(1 << 13));
1518 break;
1519
1520 case KS_Cmd20xf10f:
1521 update_modifier(sc->id, *type, 0, MOD_COMMAND2(1 << 14));
1522 break;
1523 }
1524
1525 if (*type != WSCONS_EVENT_KEY_DOWN2)
1526 return (0);
1527
1528#ifdef SUSPEND1
1529 if (ksym == KS_Cmd_Sleep0xf42f) {
1530 request_sleep(SLEEP_SUSPEND0x01);
1531 return (1);
1532 }
1533#endif
1534
1535#ifdef HAVE_SCROLLBACK_SUPPORT
1536#if NWSDISPLAY1 > 0
1537 switch (ksym) {
1538 case KS_Cmd_ScrollBack0xf42c:
1539 if (MOD_ONESET(sc->id, MOD_ANYSHIFT)(((sc->id)->t_modifiers & (((1 << 0) | (1 <<
1) | (1 << 2)))) != 0)
) {
1540 if (sc->sc_displaydvsc_base.me_dispdv != NULL((void *)0))
1541 wsscrollback(sc->sc_displaydvsc_base.me_dispdv,
1542 WSDISPLAY_SCROLL_BACKWARD0);
1543 return (1);
1544 }
1545 break;
1546
1547 case KS_Cmd_ScrollFwd0xf42d:
1548 if (MOD_ONESET(sc->id, MOD_ANYSHIFT)(((sc->id)->t_modifiers & (((1 << 0) | (1 <<
1) | (1 << 2)))) != 0)
) {
1549 if (sc->sc_displaydvsc_base.me_dispdv != NULL((void *)0))
1550 wsscrollback(sc->sc_displaydvsc_base.me_dispdv,
1551 WSDISPLAY_SCROLL_FORWARD1);
1552 return (1);
1553 }
1554 break;
1555 }
1556#endif
1557#endif
1558
1559 switch (ksym) {
1560 case KS_Cmd_KbdBacklightUp0xf431:
1561 atomic_store_int(&sc->sc_kbd_backlight_cmd, KBD_BACKLIGHT_UP);
1562 task_add(systq, &sc->sc_kbd_backlight_task);
1563 return (1);
1564 case KS_Cmd_KbdBacklightDown0xf432:
1565 atomic_store_int(&sc->sc_kbd_backlight_cmd, KBD_BACKLIGHT_DOWN);
1566 task_add(systq, &sc->sc_kbd_backlight_task);
1567 return (1);
1568 case KS_Cmd_KbdBacklightToggle0xf430:
1569 atomic_store_int(&sc->sc_kbd_backlight_cmd, KBD_BACKLIGHT_TOGGLE);
1570 task_add(systq, &sc->sc_kbd_backlight_task);
1571 return (1);
1572 }
1573
1574#if NWSDISPLAY1 > 0
1575 switch(ksym) {
1576 case KS_Cmd_BrightnessUp0xf426:
1577 atomic_add_int(&sc->sc_brightness_steps, 1)_atomic_add_int(&sc->sc_brightness_steps, 1);
1578 task_add(systq, &sc->sc_brightness_task);
1579 return (1);
1580 case KS_Cmd_BrightnessDown0xf427:
1581 atomic_sub_int(&sc->sc_brightness_steps, 1)_atomic_sub_int(&sc->sc_brightness_steps, 1);
1582 task_add(systq, &sc->sc_brightness_task);
1583 return (1);
1584 case KS_Cmd_BrightnessRotate0xf428:
1585 wsdisplay_brightness_cycle(sc->sc_displaydvsc_base.me_dispdv);
1586 return (1);
1587 }
1588#endif
1589
1590 if (!MOD_ONESET(sc->id, MOD_COMMAND)(((sc->id)->t_modifiers & ((1 << 12))) != 0) &&
1591 !MOD_ALLSET(sc->id, MOD_COMMAND1 | MOD_COMMAND2)(((sc->id)->t_modifiers & ((1 << 13) | (1 <<
14))) == ((1 << 13) | (1 << 14)))
)
1592 return (0);
1593
1594#ifdef DDB1
1595 if (ksym == KS_Cmd_Debugger0xf420) {
1596 wskbd_debugger(sc);
1597 /* discard this key (ddb discarded command modifiers) */
1598 *type = WSCONS_EVENT_KEY_UP1;
1599 return (1);
1600 }
1601#endif
1602
1603#if NWSDISPLAY1 > 0
1604 if (sc->sc_displaydvsc_base.me_dispdv == NULL((void *)0))
1605 return (0);
1606
1607 switch (ksym) {
1608 case KS_Cmd_Screen00xf400:
1609 case KS_Cmd_Screen10xf401:
1610 case KS_Cmd_Screen20xf402:
1611 case KS_Cmd_Screen30xf403:
1612 case KS_Cmd_Screen40xf404:
1613 case KS_Cmd_Screen50xf405:
1614 case KS_Cmd_Screen60xf406:
1615 case KS_Cmd_Screen70xf407:
1616 case KS_Cmd_Screen80xf408:
1617 case KS_Cmd_Screen90xf409:
1618 case KS_Cmd_Screen100xf40a:
1619 case KS_Cmd_Screen110xf40b:
1620 wsdisplay_switch(sc->sc_displaydvsc_base.me_dispdv, ksym - KS_Cmd_Screen00xf400, 0);
1621 return (1);
1622 case KS_Cmd_ResetEmul0xf421:
1623 wsdisplay_reset(sc->sc_displaydvsc_base.me_dispdv, WSDISPLAY_RESETEMUL);
1624 return (1);
1625 case KS_Cmd_ResetClose0xf422:
1626 wsdisplay_reset(sc->sc_displaydvsc_base.me_dispdv, WSDISPLAY_RESETCLOSE);
1627 return (1);
1628#if defined(__i386__) || defined(__amd64__1)
1629 case KS_Cmd_KbdReset0xf42e:
1630 switch (kbd_reset) {
1631#ifdef DDB1
1632 case 2:
1633 wskbd_debugger(sc);
1634 /* discard this key (ddb discarded command modifiers) */
1635 *type = WSCONS_EVENT_KEY_UP1;
1636 break;
1637#endif
1638 case 1:
1639 kbd_reset = 0;
1640 prsignal(initprocess, SIGUSR1)ptsignal((initprocess)->ps_mainproc, (30), SPROCESS);
1641 break;
1642 default:
1643 break;
1644 }
1645 return (1);
1646#endif
1647 case KS_Cmd_BacklightOn0xf423:
1648 case KS_Cmd_BacklightOff0xf424:
1649 case KS_Cmd_BacklightToggle0xf425:
1650 change_displayparam(sc, WSDISPLAYIO_PARAM_BACKLIGHT1,
1651 ksym == KS_Cmd_BacklightOff0xf424 ? -1 : 1,
1652 ksym == KS_Cmd_BacklightToggle0xf425 ? 1 : 0);
1653 return (1);
1654 case KS_Cmd_ContrastUp0xf429:
1655 case KS_Cmd_ContrastDown0xf42a:
1656 case KS_Cmd_ContrastRotate0xf42b:
1657 change_displayparam(sc, WSDISPLAYIO_PARAM_CONTRAST3,
1658 ksym == KS_Cmd_ContrastDown0xf42a ? -1 : 1,
1659 ksym == KS_Cmd_ContrastRotate0xf42b ? 1 : 0);
1660 return (1);
1661 }
1662#endif
1663 return (0);
1664}
1665
1666int
1667wskbd_translate(struct wskbd_internal *id, u_int type, int value)
1668{
1669 struct wskbd_softc *sc = id->t_sc;
1
'sc' initialized here
1670 keysym_t ksym, res, *group;
1671 struct wscons_keymap kpbuf, *kp;
1672 int gindex, iscommand = 0;
1673
1674 if (type == WSCONS_EVENT_ALL_KEYS_UP3) {
2
Assuming 'type' is not equal to WSCONS_EVENT_ALL_KEYS_UP
3
Taking false branch
1675#if NWSDISPLAY1 > 0
1676 if (sc != NULL((void *)0) && sc->sc_repeating) {
1677 sc->sc_repeating = 0;
1678 timeout_del(&sc->sc_repeat_ch);
1679 }
1680#endif
1681 id->t_modifiers &= ~(MOD_SHIFT_L(1 << 0) | MOD_SHIFT_R(1 << 1) |
1682 MOD_CONTROL_L(1 << 4) | MOD_CONTROL_R(1 << 5) |
1683 MOD_META_L(1 << 6) | MOD_META_R(1 << 7) |
1684 MOD_MODESHIFT(1 << 8) | MOD_MODELOCK(1 << 15) |
1685 MOD_COMMAND(1 << 12) | MOD_COMMAND1(1 << 13) | MOD_COMMAND2(1 << 14));
1686 return (0);
1687 }
1688
1689 if (sc != NULL((void *)0)) {
4
Assuming 'sc' is equal to NULL
5
Taking false branch
1690 if (value < 0 || value >= sc->sc_maplen) {
1691#ifdef DEBUG
1692 printf("wskbd_translate: keycode %d out of range\n",
1693 value);
1694#endif
1695 return (0);
1696 }
1697 kp = sc->sc_map + value;
1698 } else {
1699 kp = &kpbuf;
1700 wskbd_get_mapentry(&id->t_keymap, value, kp);
1701 }
1702
1703 /* if this key has a command, process it first */
1704 if (sc
5.1
'sc' is equal to NULL
!= NULL((void *)0) && kp->command != KS_voidSymbol0xf500)
1705 iscommand = internal_command(sc, &type, kp->command,
1706 kp->group1[0]);
1707
1708 /* Now update modifiers */
1709 switch (kp->group1[0]) {
6
Control jumps to the 'default' case at line 1764
1710 case KS_Shift_L0xf101:
1711 update_modifier(id, type, 0, MOD_SHIFT_L(1 << 0));
1712 break;
1713
1714 case KS_Shift_R0xf102:
1715 update_modifier(id, type, 0, MOD_SHIFT_R(1 << 1));
1716 break;
1717
1718 case KS_Shift_Lock0xf106:
1719 update_modifier(id, type, 1, MOD_SHIFTLOCK(1 << 2));
1720 break;
1721
1722 case KS_Caps_Lock0xf105:
1723 update_modifier(id, type, 1, MOD_CAPSLOCK(1 << 3));
1724 break;
1725
1726 case KS_Control_L0xf103:
1727 update_modifier(id, type, 0, MOD_CONTROL_L(1 << 4));
1728 break;
1729
1730 case KS_Control_R0xf104:
1731 update_modifier(id, type, 0, MOD_CONTROL_R(1 << 5));
1732 break;
1733
1734 case KS_Alt_L0xf107:
1735 update_modifier(id, type, 0, MOD_META_L(1 << 6));
1736 break;
1737
1738 case KS_Alt_R0xf108:
1739 update_modifier(id, type, 0, MOD_META_R(1 << 7));
1740 break;
1741
1742 case KS_Mode_switch0xf10a:
1743 update_modifier(id, type, 0, MOD_MODESHIFT(1 << 8));
1744 break;
1745
1746 case KS_Mode_Lock0xf117:
1747 update_modifier(id, type, 1, MOD_MODELOCK(1 << 15));
1748 break;
1749
1750 case KS_Num_Lock0xf10b:
1751 update_modifier(id, type, 1, MOD_NUMLOCK(1 << 9));
1752 break;
1753
1754#if NWSDISPLAY1 > 0
1755 case KS_Hold_Screen0xf10c:
1756 if (sc != NULL((void *)0)) {
1757 update_modifier(id, type, 1, MOD_HOLDSCREEN(1 << 11));
1758 if (sc->sc_displaydvsc_base.me_dispdv != NULL((void *)0))
1759 wsdisplay_kbdholdscreen(sc->sc_displaydvsc_base.me_dispdv,
1760 id->t_modifiers & MOD_HOLDSCREEN(1 << 11));
1761 }
1762 break;
1763
1764 default:
1765 if (sc
6.1
'sc' is equal to NULL
!= NULL((void *)0) && sc->sc_repeating &&
1766 ((type == WSCONS_EVENT_KEY_UP1 && value != sc->sc_repkey) ||
1767 (type == WSCONS_EVENT_KEY_DOWN2 && value == sc->sc_repkey)))
1768 return (0);
1769 break;
1770#endif
1771 }
1772
1773#if NWSDISPLAY1 > 0
1774 if (sc
7.1
'sc' is equal to NULL
!= NULL((void *)0)) {
7
Execution continues on line 1774
1775 if (sc->sc_repeating) {
1776 sc->sc_repeating = 0;
1777 timeout_del(&sc->sc_repeat_ch);
1778 }
1779 sc->sc_repkey = value;
1780 }
1781#endif
1782
1783 /* If this is a key release or we are in command mode, we are done */
1784 if (type != WSCONS_EVENT_KEY_DOWN2 || iscommand
8.1
'iscommand' is 0
)
8
Assuming 'type' is equal to WSCONS_EVENT_KEY_DOWN
1785 return (0);
1786
1787 /* Get the keysym */
1788 if (id->t_modifiers & (MOD_MODESHIFT(1 << 8)|MOD_MODELOCK(1 << 15)) &&
9
Assuming the condition is false
1789 !MOD_ONESET(id, MOD_ANYCONTROL)(((id)->t_modifiers & (((1 << 4) | (1 << 5
)))) != 0)
)
1790 group = & kp->group2[0];
1791 else
1792 group = & kp->group1[0];
1793
1794 if ((id->t_modifiers & MOD_NUMLOCK(1 << 9)) &&
10
Assuming the condition is false
1795 KS_GROUP(group[1])((group[1]) >= 0x0300 && (group[1]) < 0x0370 ? 0xf801
: (((group[1]) & 0xf000) == 0xe000 ? 0xf803 : (((group[1
]) & 0xf800) == 0xf000 ? ((group[1]) & 0xff00) : 0xf802
)))
== KS_GROUP_Keypad0xf200) {
1796 gindex = !MOD_ONESET(id, MOD_ANYSHIFT)(((id)->t_modifiers & (((1 << 0) | (1 << 1
) | (1 << 2)))) != 0)
;
1797 ksym = group[gindex];
1798 } else {
1799 /* CAPS alone should only affect letter keys */
1800 if ((id->t_modifiers & (MOD_CAPSLOCK(1 << 3) | MOD_ANYSHIFT((1 << 0) | (1 << 1) | (1 << 2)))) ==
11
Assuming the condition is true
12
Taking true branch
1801 MOD_CAPSLOCK(1 << 3)) {
1802 gindex = 0;
1803 ksym = ksym_upcase(group[0]);
1804 } else {
1805 gindex = MOD_ONESET(id, MOD_ANYSHIFT)(((id)->t_modifiers & (((1 << 0) | (1 << 1
) | (1 << 2)))) != 0)
;
1806 ksym = group[gindex];
1807 }
1808 }
1809
1810 /* Submit Audio keys for hotkey processing */
1811 if (KS_GROUP(ksym)((ksym) >= 0x0300 && (ksym) < 0x0370 ? 0xf801 :
(((ksym) & 0xf000) == 0xe000 ? 0xf803 : (((ksym) & 0xf800
) == 0xf000 ? ((ksym) & 0xff00) : 0xf802)))
== KS_GROUP_Function0xf300
) {
13
Assuming 'ksym' is >= 768
14
Assuming 'ksym' is >= 880
15
'?' condition is false
16
Assuming the condition is false
17
'?' condition is false
18
Assuming the condition is true
19
'?' condition is true
20
Assuming the condition is true
21
Taking true branch
1812 switch (ksym) {
22
Control jumps to 'case 62418:' at line 1817
1813#if NAUDIO1 > 0
1814 case KS_AudioMute0xf3d1:
1815 wskbd_set_mixervolume_dev(sc->sc_audiocookie, 0, 1);
1816 return (0);
1817 case KS_AudioLower0xf3d2:
1818 wskbd_set_mixervolume_dev(sc->sc_audiocookie, -1, 1);
23
Access to field 'sc_audiocookie' results in a dereference of a null pointer (loaded from variable 'sc')
1819 return (0);
1820 case KS_AudioRaise0xf3d3:
1821 wskbd_set_mixervolume_dev(sc->sc_audiocookie, 1, 1);
1822 return (0);
1823#endif
1824 default:
1825 break;
1826 }
1827 }
1828
1829 /* Process compose sequence and dead accents */
1830 res = KS_voidSymbol0xf500;
1831
1832 switch (KS_GROUP(ksym)((ksym) >= 0x0300 && (ksym) < 0x0370 ? 0xf801 :
(((ksym) & 0xf000) == 0xe000 ? 0xf803 : (((ksym) & 0xf800
) == 0xf000 ? ((ksym) & 0xff00) : 0xf802)))
) {
1833 case KS_GROUP_Ascii0xf802:
1834 case KS_GROUP_Keypad0xf200:
1835 case KS_GROUP_Function0xf300:
1836 res = ksym;
1837 break;
1838
1839 case KS_GROUP_Mod0xf100:
1840 if (ksym == KS_Multi_key0xf109) {
1841 update_modifier(id, 1, 0, MOD_COMPOSE(1 << 10));
1842 id->t_composelen = 2;
1843 }
1844 break;
1845
1846 case KS_GROUP_Dead0xf801:
1847 if (id->t_composelen == 0) {
1848 update_modifier(id, 1, 0, MOD_COMPOSE(1 << 10));
1849 id->t_composelen = 1;
1850 id->t_composebuf[0] = ksym;
1851 } else
1852 res = ksym;
1853 break;
1854 }
1855
1856 if (res == KS_voidSymbol0xf500)
1857 return (0);
1858
1859 if (id->t_composelen > 0) {
1860 /*
1861 * If the compose key also serves as AltGr (i.e. set to both
1862 * KS_Multi_key and KS_Mode_switch), and would provide a valid,
1863 * distinct combination as AltGr, leave compose mode.
1864 */
1865 if (id->t_composelen == 2 && group == &kp->group2[0]) {
1866 if (kp->group1[gindex] != kp->group2[gindex])
1867 id->t_composelen = 0;
1868 }
1869
1870 if (id->t_composelen != 0) {
1871 id->t_composebuf[2 - id->t_composelen] = res;
1872 if (--id->t_composelen == 0) {
1873 res = wskbd_compose_value(id->t_composebuf);
1874 update_modifier(id, 0, 0, MOD_COMPOSE(1 << 10));
1875 } else {
1876 return (0);
1877 }
1878 }
1879 }
1880
1881 /* We are done, return the symbol */
1882 if (KS_GROUP(res)((res) >= 0x0300 && (res) < 0x0370 ? 0xf801 : (
((res) & 0xf000) == 0xe000 ? 0xf803 : (((res) & 0xf800
) == 0xf000 ? ((res) & 0xff00) : 0xf802)))
== KS_GROUP_Ascii0xf802) {
1883 if (MOD_ONESET(id, MOD_ANYCONTROL)(((id)->t_modifiers & (((1 << 4) | (1 << 5
)))) != 0)
) {
1884 if ((res >= KS_at0x40 && res <= KS_z0x7a) || res == KS_space0x20)
1885 res = res & 0x1f;
1886 else if (res == KS_20x32)
1887 res = 0x00;
1888 else if (res >= KS_30x33 && res <= KS_70x37)
1889 res = KS_Escape0x1b + (res - KS_30x33);
1890 else if (res == KS_80x38)
1891 res = KS_Delete0x7f;
1892 }
1893 if (MOD_ONESET(id, MOD_ANYMETA)(((id)->t_modifiers & (((1 << 6) | (1 << 7
)))) != 0)
) {
1894 if (id->t_flags & WSKFL_METAESC1) {
1895 id->t_symbols[0] = KS_Escape0x1b;
1896 id->t_symbols[1] = res;
1897 return (2);
1898 } else
1899 res |= 0x80;
1900 }
1901 }
1902
1903 id->t_symbols[0] = res;
1904 return (1);
1905}
1906
1907void
1908wskbd_debugger(struct wskbd_softc *sc)
1909{
1910#ifdef DDB1
1911 if (sc->sc_isconsole && db_console) {
1912 if (sc->id->t_consops->debugger != NULL((void *)0)) {
1913 (*sc->id->t_consops->debugger)
1914 (sc->id->t_consaccesscookie);
1915 } else
1916 db_enter();
1917 }
1918#endif
1919}
1920
1921void
1922wskbd_set_keymap(struct wskbd_softc *sc, struct wscons_keymap *map, int maplen)
1923{
1924 free(sc->sc_map, M_DEVBUF2, sc->sc_maplen * sizeof(*sc->sc_map));
1925 sc->sc_map = map;
1926 sc->sc_maplen = maplen;
1927}
1928
1929void
1930wskbd_kbd_backlight_task(void *arg)
1931{
1932 struct wskbd_softc *sc = arg;
1933 struct wskbd_backlight data;
1934 int step, val;
1935 u_int cmd;
1936
1937 if (wskbd_get_backlight == NULL((void *)0) || wskbd_set_backlight == NULL((void *)0))
1938 return;
1939
1940 cmd = atomic_swap_uint(&sc->sc_kbd_backlight_cmd, 0)_atomic_swap_uint((&sc->sc_kbd_backlight_cmd), (0));
1941 if (cmd != KBD_BACKLIGHT_UP &&
1942 cmd != KBD_BACKLIGHT_DOWN &&
1943 cmd != KBD_BACKLIGHT_TOGGLE)
1944 return;
1945
1946 (*wskbd_get_backlight)(&data);
1947 step = (data.max - data.min + 1) / 8;
1948 val = (cmd == KBD_BACKLIGHT_UP) ? data.curval + step :
1949 (cmd == KBD_BACKLIGHT_DOWN) ? data.curval - step :
1950 (data.curval) ? 0 : (data.max - data.min + 1) / 2;
1951 data.curval = (val > 0xff) ? 0xff : (val < 0) ? 0 : val;
1952 (*wskbd_set_backlight)(&data);
1953}
1954
1955#if NWSDISPLAY1 > 0
1956void
1957wskbd_brightness_task(void *arg)
1958{
1959 struct wskbd_softc *sc = arg;
1960 int steps = atomic_swap_uint(&sc->sc_brightness_steps, 0)_atomic_swap_uint((&sc->sc_brightness_steps), (0));
1961 int dir = 1;
1962
1963 if (steps < 0) {
1964 steps = -steps;
1965 dir = -1;
1966 }
1967 while (steps--)
1968 wsdisplay_brightness_step(NULL((void *)0), dir);
1969}
1970#endif