1 /* $NetBSD: hpf1275a_tty.c,v 1.24 2009/05/12 12:13:49 cegger Exp $ */
4 * Copyright (c) 2004 Valeriy E. Ushakov
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 #include <sys/cdefs.h>
31 __KERNEL_RCSID(0, "$NetBSD: hpf1275a_tty.c,v 1.24 2009/05/12 12:13:49 cegger Exp $");
33 #include "opt_wsdisplay_compat.h"
35 #include <sys/param.h>
36 #include <sys/kernel.h>
38 #include <sys/device.h>
40 #include <sys/fcntl.h>
42 #include <sys/systm.h>
43 #include <sys/kauth.h>
45 #include <dev/wscons/wsconsio.h>
46 #include <dev/wscons/wskbdvar.h>
47 #include <dev/wscons/wsksymdef.h>
48 #include <dev/wscons/wsksymvar.h>
50 #include <dev/pckbport/wskbdmap_mfii.h>
51 #ifdef WSDISPLAY_COMPAT_RAWKBD
52 #include <dev/hpc/pckbd_encode.h>
56 extern struct cfdriver hpf1275a_cd
;
58 struct hpf1275a_softc
{
61 struct tty
*sc_tp
; /* back reference to the tty */
62 device_t sc_wskbd
; /* wskbd child */
64 #ifdef WSDISPLAY_COMPAT_RAWKBD
70 /* pseudo-device initialization */
71 extern void hpf1275aattach(int);
73 /* line discipline methods */
74 static int hpf1275a_open(dev_t
, struct tty
*);
75 static int hpf1275a_close(struct tty
*, int);
76 static int hpf1275a_input(int, struct tty
*);
78 /* autoconf(9) methods */
79 static int hpf1275a_match(device_t
, cfdata_t
, void *);
80 static void hpf1275a_attach(device_t
, device_t
, void *);
81 static int hpf1275a_detach(device_t
, int);
83 /* wskbd(4) accessops */
84 static int hpf1275a_wskbd_enable(void *, int);
85 static void hpf1275a_wskbd_set_leds(void *, int);
86 static int hpf1275a_wskbd_ioctl(void *, u_long
, void *, int,
91 * It doesn't need to be exported, as only hpf1275aattach() uses it,
92 * but there's no "official" way to make it static.
94 CFATTACH_DECL(hpf1275a
, sizeof(struct hpf1275a_softc
),
95 hpf1275a_match
, hpf1275a_attach
, hpf1275a_detach
, NULL
);
98 static struct linesw hpf1275a_disc
= {
100 .l_open
= hpf1275a_open
,
101 .l_close
= hpf1275a_close
,
104 .l_ioctl
= ttynullioctl
,
105 .l_rint
= hpf1275a_input
,
107 .l_modem
= nullmodem
,
112 static const struct wskbd_accessops hpf1275a_wskbd_accessops
= {
113 hpf1275a_wskbd_enable
,
114 hpf1275a_wskbd_set_leds
,
119 static const struct wskbd_mapdata hpf1275a_wskbd_keymapdata
= {
120 pckbd_keydesctab
, KB_US
124 /* F1275A scancodes -> XT scancodes so that we can use pckbd_keydesctab. */
125 static const uint8_t hpf1275a_to_xtscan
[128] = {
164 [0x28] = 28, /* Enter */
166 [0x29] = 1, /* ESC */
167 [0x2a] = 14, /* Backspace */
168 [0x2b] = 15, /* Tab */
169 [0x2c] = 57, /* Space */
184 [0x3a] = 59, /* F1 */
185 [0x3b] = 60, /* F2 */
186 [0x3c] = 61, /* F3 */
187 [0x3d] = 62, /* F4 */
188 [0x3e] = 63, /* F5 */
189 [0x3f] = 64, /* F6 */
190 [0x40] = 65, /* F7 */
191 [0x41] = 66, /* F8 */
193 [0x42] = 68, /* "OK" -> F10 */
194 [0x43] = 87, /* "Cancel" -> F11 */
196 [0x4c] = 211, /* Del */
198 [0x4f] = 205, /* Right */
199 [0x50] = 203, /* Left */
200 [0x51] = 208, /* Down */
201 [0x52] = 200, /* Up */
203 [0x53] = 67, /* "task switch" -> F9 */
205 [0x65] = 221, /* windows */
206 [0x66] = 88, /* "keyboard" -> F12 */
208 [0x74] = 42, /* Shift (left) */
209 [0x75] = 54, /* Shift (right) */
210 [0x76] = 56, /* Alt (left) */
211 [0x77] = 184, /* Fn -> AltGr == Mode Switch */
212 [0x78] = 29, /* Control (left) */
217 * Pseudo-device initialization routine called from main().
220 hpf1275aattach(int n
)
224 error
= ttyldisc_attach(&hpf1275a_disc
);
226 printf("%s: unable to register line discipline, error = %d\n",
227 hpf1275a_cd
.cd_name
, error
);
231 error
= config_cfattach_attach(hpf1275a_cd
.cd_name
, &hpf1275a_ca
);
233 printf("%s: unable to register cfattach, error = %d\n",
234 hpf1275a_cd
.cd_name
, error
);
235 config_cfdriver_detach(&hpf1275a_cd
);
236 (void) ttyldisc_detach(&hpf1275a_disc
);
242 * Autoconf match routine.
244 * XXX: unused: config_attach_pseudo(9) does not call ca_match.
247 hpf1275a_match(device_t self
,
248 cfdata_t cfdata
, void *arg
)
251 /* pseudo-device; always present */
257 * Autoconf attach routine. Called by config_attach_pseudo(9) when we
258 * open the line discipline.
261 hpf1275a_attach(device_t parent
,
262 device_t self
, void *aux
)
264 struct hpf1275a_softc
*sc
= device_private(self
);
265 struct wskbddev_attach_args wska
;
268 wska
.keymap
= &hpf1275a_wskbd_keymapdata
;
269 wska
.accessops
= &hpf1275a_wskbd_accessops
;
270 wska
.accesscookie
= sc
;
273 #ifdef WSDISPLAY_COMPAT_RAWKBD
276 sc
->sc_wskbd
= config_found(self
, &wska
, wskbddevprint
);
281 * Autoconf detach routine. Called when we close the line discipline.
284 hpf1275a_detach(device_t self
, int flags
)
286 struct hpf1275a_softc
*sc
= device_private(self
);
289 if (sc
->sc_wskbd
== NULL
)
292 error
= config_detach(sc
->sc_wskbd
, 0);
299 * Line discipline open routine.
302 hpf1275a_open(dev_t dev
, struct tty
*tp
)
304 static struct cfdata hpf1275a_cfdata
= {
305 .cf_name
= "hpf1275a",
306 .cf_atname
= "hpf1275a",
308 .cf_fstate
= FSTATE_STAR
,
310 struct lwp
*l
= curlwp
; /* XXX */
311 struct hpf1275a_softc
*sc
;
314 if ((error
= kauth_authorize_device_tty(l
->l_cred
,
315 KAUTH_DEVICE_TTY_OPEN
, tp
)))
320 if (tp
->t_linesw
== &hpf1275a_disc
) {
325 sc
= (struct hpf1275a_softc
*)config_attach_pseudo(&hpf1275a_cfdata
);
340 * Line discipline close routine.
343 hpf1275a_close(struct tty
*tp
, int flag
)
345 struct hpf1275a_softc
*sc
= tp
->t_sc
;
349 mutex_spin_enter(&tty_lock
);
350 ttyflush(tp
, FREAD
| FWRITE
);
351 mutex_spin_exit(&tty_lock
); /* XXX */
352 ttyldisc_release(tp
->t_linesw
);
353 tp
->t_linesw
= ttyldisc_default();
357 config_detach(&sc
->sc_dev
, 0);
365 * Feed input from the keyboard to wskbd(4).
368 hpf1275a_input(int c
, struct tty
*tp
)
370 struct hpf1275a_softc
*sc
= tp
->t_sc
;
378 if (c
& TTY_ERRORMASK
)
379 return (0); /* TODO? */
381 code
= c
& TTY_CHARMASK
;
383 type
= WSCONS_EVENT_KEY_UP
;
386 type
= WSCONS_EVENT_KEY_DOWN
;
388 xtscan
= hpf1275a_to_xtscan
[code
];
390 aprint_error_dev(&sc
->sc_dev
, "unknown code 0x%x\n", code
);
394 KASSERT(sc
->sc_wskbd
!= NULL
);
396 #ifdef WSDISPLAY_COMPAT_RAWKBD
401 n
= pckbd_encode(type
, xtscan
, data
);
402 wskbd_rawinput(sc
->sc_wskbd
, data
, n
);
405 wskbd_input(sc
->sc_wskbd
, type
, xtscan
);
412 hpf1275a_wskbd_enable(void *self
, int on
)
414 struct hpf1275a_softc
*sc
= self
;
423 hpf1275a_wskbd_set_leds(void *self
, int leds
)
426 /* this keyboard has no leds; nothing to do */
432 hpf1275a_wskbd_ioctl(void *self
, u_long cmd
, void *data
, int flag
,
435 #ifdef WSDISPLAY_COMPAT_RAWKBD
436 struct hpf1275a_softc
*sc
= self
;
441 *(int *)data
= WSKBD_TYPE_HPC_KBD
; /* may be use new type? */
444 case WSKBDIO_GETLEDS
:
445 *(int *)data
= 0; /* this keyboard has no leds */
448 #ifdef WSDISPLAY_COMPAT_RAWKBD
449 case WSKBDIO_SETMODE
:
450 sc
->sc_rawkbd
= (*(int *)data
== WSKBD_RAW
);
455 return (EPASSTHROUGH
);