Bug 265260 - HANGEUL and HANJA on Korean keyboards do not work.
Summary: HANGEUL and HANJA on Korean keyboards do not work.
Status: Closed FIXED
Alias: None
Product: Base System
Classification: Unclassified
Component: kern (show other bugs)
Version: 13.1-RELEASE
Hardware: Any Any
: --- Affects Some People
Assignee: freebsd-bugs (Nobody)
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2022-07-17 07:23 UTC by warioburn
Modified: 2022-07-20 03:05 UTC (History)
0 users

See Also:


Attachments
korean keyboard patch (1.09 KB, patch)
2022-07-19 01:21 UTC, warioburn
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description warioburn 2022-07-17 07:23:32 UTC
Korean keyboard have Hanyoung key (sometimes called Hanguel key) witch toggle Korean/English input mode and a Hanja key witch covert korean letter to chinese letter.

Unlike before, x11's keycode conversion is done by evdev. That's why I'm reporting here.
When tested with evtest, they are not recognized.


in /sys/dev/atkbdc/atkbd.c

There are several mode. Especially, K_CODE, K_RAW,K_ASCII, EVDEV.

Hanyoung and Hanja key is not recognized in all modes, but I will report mainly EVDEV part because it's most relevant.

First, the Hanyoung key is 0xF1 and the Hanja key is 0xF2.
Hanyoung/Hanja keys are generally greater than 0x80, which is genarlly considered a release key. And it does not repeat or generate a release key.

Reference:https://www.win.tue.nl/~aeb/linux/kbd/scancodes-9.html



#ifdef EVDEV_SUPPORT
/* push evdev event */

if (evdev_rcpt_mask & EVDEV_RCPT_HW_KBD && state->ks_evdev != NULL) {
keycode = evdev_scancode2key(&state->ks_evdev_state,
scancode);

if (keycode != KEY_RESERVED) {
	evdev_push_event(state->ks_evdev, EV_KEY,
	(uint16_t)keycode, scancode & 0x80 ? 0 : 1);
	evdev_sync(state->ks_evdev);
	}
}
#endif


After digging with atkbd driver source, it looks like this part is related.
There seems to be no problem that returning the keycode from evdev_scancode2key and the definition is already in place with KEY_HANGEUL, KEY_HANJA.

evdev_push_event(state->ks_evdev, EV_KEY,
(uint16_t)keycode, scancode & 0x80 ? 0 : 1);

But here, if the scan code is greater than 0x80,
evdev_push_event -> evdev_send_event ->evdev_sparse_event
through these codes, EV_SKIP_EVENT is returned, it will be ignored.

So, wouldn't special processing for Hangul keys be necessary somewhere?







Notes on other parts.
K_CODE also has a similar problem, but even if it's not fixed, There is no big problem. because, without ime, Hanyoung/Hanja key is meaningless. 
But it's pretty much the same problem, so it shouldn't be difficult to fix.

For previously used xorg-xf86-input-keyboard package(This is how it worked before,), receives the scan code through K_RAW and converts it to an X11 key code.
I guess adding Hanyoung keys in the wsXtMap of bsd_KbdMap.c table, make it  work, but I can't make it sucess.
Comment 1 warioburn 2022-07-18 19:50:09 UTC
Oops, There was a mistake.
Chinese key is 0xF1, hanyoung key is 0xf2, as opposed to usb.

Anyway, I found a workaround about xorg-xf86-input-keyboard.

static int
isKoreankey(unsigned char c)
{
	return c == 0xF1 || c== 0xF2;
}

static void
stdReadInput(InputInfoPtr pInfo)
{
    KbdDevPtr pKbd = (KbdDevPtr) pInfo->private;
    unsigned char rBuf[64];
    int nBytes, i;
    if ((nBytes = read( pInfo->fd, (char *)rBuf, sizeof(rBuf))) > 0) {
       for (i = 0; i < nBytes; i++)
		if(isKoreankey(rBuf[i])){
		  pKbd->PostEvent(pInfo, rBuf[i], TRUE);
		  pKbd->PostEvent(pInfo, rBuf[i], FALSE);
		 }else{
			pKbd->PostEvent(pInfo, rBuf[i] & 0x7f,
			rBuf[i] & 0x80 ? FALSE : TRUE);
		}
       }
}

It's not pretty code, but it seems to work. If there is no problem, I'll make a bug report about it later.


It's not ideal, but I think there is no choice but to take the same approach for evdev .

if (keycode != KEY_RESERVED) {
 if(Korean key){
  evdev_push_event(state->ks_evdev, EV_KEY,(uint16_t)keycode, 1);
  evdev_push_event(state->ks_evdev, EV_KEY,(uint16_t)keycode, 0);
  evdev_sync(state->ks_evdev);
 
 }else{
 
  //do like before

 }

}

K_CODE mode also similar code.

/* keycode to key action */

action = genkbd_keyaction(kbd, keycode, scancode & 0x80,

&state->ks_state, &state->ks_accents);

The workaround will be similar.
Comment 2 warioburn 2022-07-18 20:28:50 UTC
I just tested it with a usb keyboard.
USB keyboard works without any special patch.
Comment 3 warioburn 2022-07-19 01:21:15 UTC
Created attachment 235342 [details]
korean keyboard patch

After applying the patch suggested by Vladimir Kondratyev, it seems to work fine.
Also I swapped key order at evdev_at_set1_scancodes in evdev_utils.c.
Comment 4 commit-hook freebsd_committer freebsd_triage 2022-07-19 22:08:39 UTC
A commit in branch main references this bug:

URL: https://cgit.FreeBSD.org/src/commit/?id=6a26c99f827ffa9da5e23d466eeb17131fc75238

commit 6a26c99f827ffa9da5e23d466eeb17131fc75238
Author:     Vladimir Kondratyev <wulf@FreeBSD.org>
AuthorDate: 2022-07-19 21:06:22 +0000
Commit:     Vladimir Kondratyev <wulf@FreeBSD.org>
CommitDate: 2022-07-19 21:36:20 +0000

    atkbd(4): Fix "hancha" and "han/yong" korean keys handling.

    The Korean keyboard has two keys, the Korean/Chinese and the
    Korean/English toggles, that generate scancodes 0xF1 and 0xF2
    (respectively) when pressed, and nothing when released. They do not
    repeat.
    As Hanyong/Hancha keys are generally greater than 0x80, which is
    generally considered a release key, add extra preceding press key event
    to generate press/release pair.
    Swap Hanyong/Hancha key codes to match reality.

    Reported by:    Warioburn <warioburn@yahoo.co.jp>
    PR:             265260
    MFC after:      1 week

 sys/dev/atkbdc/atkbd.c      | 10 ++++++++++
 sys/dev/evdev/evdev_utils.c |  2 +-
 2 files changed, 11 insertions(+), 1 deletion(-)
Comment 5 warioburn 2022-07-20 03:05:26 UTC
I think i can close it. thanks.