summaryrefslogtreecommitdiff
path: root/sys/dev/usb
diff options
context:
space:
mode:
authorMiod Vallat <miod@cvs.openbsd.org>2006-06-26 22:14:13 +0000
committerMiod Vallat <miod@cvs.openbsd.org>2006-06-26 22:14:13 +0000
commit676709553639f24690a62a929c32a72e9f2d96cd (patch)
treef2cda84a1cf6f50bee654b3e58039a10fb44ac14 /sys/dev/usb
parent426c4ad780e17f4fbd290e087423955663f32731 (diff)
When attaching an USB keyboard, check the HID interface for its country code
id, and if it is non-zero, try to select the appropriate layout. Of course, Sun USB keyboards still use the Sun layout encoding, which is completely different, so we have to check for them. Tested on a variety of keyboards by krw@ matthieu@ and I.
Diffstat (limited to 'sys/dev/usb')
-rw-r--r--sys/dev/usb/ukbd.c125
-rw-r--r--sys/dev/usb/usbhid.h6
2 files changed, 118 insertions, 13 deletions
diff --git a/sys/dev/usb/ukbd.c b/sys/dev/usb/ukbd.c
index d710e49038f..eef711f1f7d 100644
--- a/sys/dev/usb/ukbd.c
+++ b/sys/dev/usb/ukbd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ukbd.c,v 1.24 2006/06/23 06:27:11 miod Exp $ */
+/* $OpenBSD: ukbd.c,v 1.25 2006/06/26 22:14:12 miod Exp $ */
/* $NetBSD: ukbd.c,v 1.85 2003/03/11 16:44:00 augustss Exp $ */
/*
@@ -145,6 +145,80 @@ Static const u_int8_t ukbd_trtab[256] = {
};
#endif /* defined(WSDISPLAY_COMPAT_RAWKBD) */
+const kbd_t ukbd_countrylayout[HCC_MAX] = {
+ (kbd_t)-1,
+ (kbd_t)-1, /* arabic */
+ KB_BE, /* belgian */
+ (kbd_t)-1, /* canadian bilingual */
+ KB_CF, /* canadian french */
+ (kbd_t)-1, /* czech */
+ KB_DK, /* danish */
+ (kbd_t)-1, /* finnish */
+ KB_FR, /* french */
+ KB_DE, /* german */
+ (kbd_t)-1, /* greek */
+ (kbd_t)-1, /* hebrew */
+ KB_HU, /* hungary */
+ (kbd_t)-1, /* international (iso) */
+ KB_IT, /* italian */
+ KB_JP, /* japanese (katakana) */
+ (kbd_t)-1, /* korean */
+ KB_LA, /* latin american */
+ (kbd_t)-1, /* netherlands/dutch */
+ KB_NO, /* norwegian */
+ (kbd_t)-1, /* persian (farsi) */
+ KB_PL, /* polish */
+ KB_PT, /* portuguese */
+ KB_RU, /* russian */
+ (kbd_t)-1, /* slovakia */
+ KB_ES, /* spanish */
+ KB_SF, /* swiss french */
+ KB_SG, /* swiss german */
+ (kbd_t)-1, /* switzerland */
+ (kbd_t)-1, /* taiwan */
+ KB_TR, /* turkish Q */
+ KB_UK, /* uk */
+ KB_US, /* us */
+ (kbd_t)-1, /* yugoslavia */
+ (kbd_t)-1 /* turkish F */
+};
+
+#define SUN_HCC_MIN 0x21
+#define SUN_HCC_MAX 0x3f
+const kbd_t ukbd_sunlayout[1 + SUN_HCC_MAX - SUN_HCC_MIN] = {
+ KB_US, /* 021 USA */
+ KB_US, /* 022 UNIX */
+ KB_FR, /* 023 France */
+ KB_DK, /* 024 Denmark */
+ KB_DE, /* 025 Germany */
+ KB_IT, /* 026 Italy */
+ KB_NL, /* 027 The Netherlands */
+ KB_NO, /* 028 Norway */
+ KB_PT, /* 029 Portugal */
+ KB_ES, /* 02a Spain */
+ KB_SV, /* 02b Sweden */
+ KB_SF, /* 02c Switzerland/French */
+ KB_SG, /* 02d Switzerland/German */
+ KB_UK, /* 02e Great Britain */
+ -1, /* 02f Korea */
+ -1, /* 030 Taiwan */
+ KB_JP, /* 031 Japan */
+ -1, /* 032 Canada/French */
+ -1, /* 033 Hungary */
+ -1, /* 034 Poland */
+ -1, /* 035 Czech */
+ -1, /* 036 Russia */
+ -1, /* 037 Latvia */
+ -1, /* 038 Turkey-Q5 */
+ -1, /* 039 Greece */
+ -1, /* 03a Arabic */
+ -1, /* 03b Lithuania */
+ -1, /* 03c Belgium */
+ -1, /* 03d unaffected */
+ -1, /* 03e Turkey-F5 */
+ -1, /* 03f Canada/French */
+};
+
#define KEY_ERROR 0x01
#define MAXKEYS (MAXMOD+2*MAXKEYCODE)
@@ -259,13 +333,8 @@ const struct wskbd_accessops ukbd_accessops = {
extern const struct wscons_keydesc ukbd_keydesctab[];
-const struct wskbd_mapdata ukbd_keymapdata = {
- ukbd_keydesctab,
-#ifdef UKBD_LAYOUT
- UKBD_LAYOUT,
-#else
- KB_US,
-#endif
+struct wskbd_mapdata ukbd_keymapdata = {
+ ukbd_keydesctab
};
USB_DECLARE_DRIVER(ukbd);
@@ -289,8 +358,10 @@ USB_ATTACH(ukbd)
{
USB_ATTACH_START(ukbd, sc, uaa);
struct uhidev_attach_arg *uha = (struct uhidev_attach_arg *)uaa;
+ usb_hid_descriptor_t *hid;
u_int32_t qflags;
const char *parseerr;
+ kbd_t layout = (kbd_t)-1;
struct wskbddev_attach_args a;
sc->sc_hdev.sc_intr = ukbd_intr;
@@ -304,12 +375,12 @@ USB_ATTACH(ukbd)
USB_ATTACH_ERROR_RETURN;
}
+ hid = usbd_get_hid_descriptor(uha->uaa->iface);
+
#ifdef DIAGNOSTIC
- printf(": %d modifier keys, %d key codes", sc->sc_nmod,
- sc->sc_nkeycode);
+ printf(": %d modifier keys, %d key codes",
+ sc->sc_nmod, sc->sc_nkeycode);
#endif
- printf("\n");
-
qflags = usbd_get_quirks(uha->parent->sc_udev)->uq_flags;
sc->sc_debounce = (qflags & UQ_SPUR_BUT_UP) != 0;
@@ -325,6 +396,36 @@ USB_ATTACH(ukbd)
ukbd_is_console = 0;
}
+ if (uha->uaa->vendor == USB_VENDOR_SUN &&
+ (uha->uaa->product == USB_PRODUCT_SUN_KEYBOARD6 ||
+ uha->uaa->product == USB_PRODUCT_SUN_KEYBOARD7)) {
+ /* Sun keyboard use Sun-style layout codes */
+ if (hid->bCountryCode >= SUN_HCC_MIN &&
+ hid->bCountryCode <= SUN_HCC_MAX)
+ layout = ukbd_sunlayout[hid->bCountryCode - SUN_HCC_MIN];
+#ifdef DIAGNOSTIC
+ if (hid->bCountryCode != 0)
+ printf(", layout %d", hid->bCountryCode);
+#endif
+ } else {
+ if (hid->bCountryCode <= HCC_MAX)
+ layout = ukbd_countrylayout[hid->bCountryCode];
+#ifdef DIAGNOSTIC
+ if (hid->bCountryCode != 0)
+ printf(", country code %d", hid->bCountryCode);
+#endif
+ }
+ if (layout == (kbd_t)-1) {
+#ifdef UKBD_LAYOUT
+ layout = UKBD_LAYOUT;
+#else
+ layout = KB_US;
+#endif
+ }
+ ukbd_keymapdata.layout = layout;
+
+ printf("\n");
+
if (sc->sc_console_keyboard) {
DPRINTF(("ukbd_attach: console keyboard sc=%p\n", sc));
wskbd_cnattach(&ukbd_consops, sc, &ukbd_keymapdata);
diff --git a/sys/dev/usb/usbhid.h b/sys/dev/usb/usbhid.h
index d88c6d375ee..b49f740b5a1 100644
--- a/sys/dev/usb/usbhid.h
+++ b/sys/dev/usb/usbhid.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: usbhid.h,v 1.7 2002/05/09 15:06:29 nate Exp $ */
+/* $OpenBSD: usbhid.h,v 1.8 2006/06/26 22:14:12 miod Exp $ */
/* $NetBSD: usbhid.h,v 1.11 2001/12/28 00:20:24 augustss Exp $ */
/* $FreeBSD: src/sys/dev/usb/usbhid.h,v 1.7 1999/11/17 22:33:51 n_hibma Exp $ */
@@ -195,4 +195,8 @@ typedef struct usb_hid_descriptor {
#define HIO_VOLATILE 0x080
#define HIO_BUFBYTES 0x100
+/* Valid values for the country codes */
+#define HCC_UNDEFINED 0x00
+#define HCC_MAX 0x23
+
#endif /* _USBHID_H_ */