알리에서 VR-PARK 라는 BT 콘트롤러를 샀다.
(그리 필요하진 않지만) 이북 리더에서 페이지 넘기는건 괜찮은것 같은데
그걸 제외하면 볼륨조절 이외에는 별로 쓸모가 없어 보인다.
그래서 PC 의 미디어 리모콘용으로 키를 변경해 봤다.
기본적으로는 디바이스별 키맵 변경을 참고 했다
테스트 환경 - ubuntu 22.04
* 우선 모드별 키 매핑은 다음과 같다. (기본은 모드 D)
모드 A
A - 마우스 버튼 1
B - 마우스 버튼 8
C - 키코드 123 XF86AudioRaiseVolume
D - 키코드 122 XF86AudioLowerVolume
상 - 여러 번의 마우스 커서 이동
하 - 여러 번의 마우스 커서 이동
좌 - 여러 번의 마우스 커서 이동
우 - 여러 번의 마우스 커서 이동
전면 위, 아래 - 각각 A, B 와 동일
|
모드 B
A - 키코드172 XF86AudioPlay
B - 키코드180 XF86HomePage
C - 키코드123 XF86AudioRaiseVolume
D - 키코드122 XF86AudioLowerVolume
상 - 키코드173 XF86AudioPrev
하 - 키코드171 XF86AudioNext
좌 - 키코드173 XF86AudioPrev
우 - 키코드171 XF86AudioNext
전면 위, 아래 - 각각 A, B 와 동일
|
모드 C
A - 마우스 버튼 41
B - 마우스 버튼 37
C - 마우스 버튼 40
D - 마우스 버튼 38
상 - 없음
하 - 없음
좌 - 없음
우 - 없음
전면 위, 아래 - 각각 B, A 와 동일
|
모드 D
A - 마우스 버튼 1
B - 마우스 버튼 8
C - 키코드 123 XF86AudioRaiseVolume
D - 키코드 122 XF86AudioLowerVolume
상 - 마우스 커서
하 - 마우스 커서
좌 - 마우스 커서
우 - 마우스 커서
전면 위, 아래 - 각각 A, B 와 동일매 |
* 키 매핑 조사
xev 를 띄우고, 창에 마우스 커서를 놓고, 버튼 및 조이스틱을 동작 시켜 터미널 출력을 확인
일부 버튼(볼륨)은 키코드를 얻을 수 없고 KeymapNotify 등이 발생했는데 xev 로 Fn+F1-F12 키코드 조사에 따른면 다른 키 바인딩 앱이 동작 중이라 그렇다고 한다.
xlsclients 를 실행하니 gsd-media-keys 라는 이름이 보였다.
killall gsd-media-keys 로 삭제 후 모든 매핑을 조사할 수 있었다.
변경할 키의 심볼은 xkbcomp.dump 에서 또는 다음 명령어로 확인한다.
최종적으로는 키보드로만 구성된 모드 B 에서 다음과 같이 동작하게 하기로 했다.
$ cat vrpark.sh
#! /bin/bash
XKB_ROOT="/tmp/$USER/xkb"
# 매핑 생성
# @B 모드
# 위/왼쪽 - 소리 크게
# 아래/오른쪽 - 소리 작게
# C - 재생/일시정지
# D - 전체화면 (f)
# A - 오른쪽
# B - 왼쪽
mkdir -p $XKB_ROOT/symbols
cat << EOF > $XKB_ROOT/symbols/custom
xkb_symbols "media" {
key <I171> { [ XF86AudioLowerVolume ] };
key <I172> { [ Right ] };
key <I173> { [ XF86AudioRaiseVolume ] };
key <I180> { [ Left ] };
key <VOL+> { [ XF86AudioPlay, XF86AudioPause ] };
key <VOL-> { type="ALPHABETIC", symbols[Group1]=[ f, F ] };
};
EOF
kbd_id=$(xinput list | sed -n 's/.*VR-PARK.*id=\([0-9]*\).*keyboard.*/\1/p')
[ "$kbd_id" ] &&
setxkbmap -device $kbd_id -print |
sed 's/\(xkb_symbols.*\)"/\1+custom(youtube)"/' |
xkbcomp -I$XKB_ROOT -i $kbd_id -synch - $DISPLAY 2>/dev/null
|
연결되면 기본으로 모드 D 가 되어 모드 B 로 변경해야 하지만, 꽤 만족스럽다.
다만 몇 가지 문제는
1. 유튜브의 경우 오른쪽 왼쪽을 누르면 5초씩 이동하는데 VLC player의 경우 10초씩 이동한다.
2. 미디어 콘트롤러로는 키가 부족하다. 최소 이전파일/다음파일의 두 개가 더 필요하다.
3. 유튜브 중간 중간 나오는 광고 건너뛰기는 처리가 안된다. 배너 광고 삭제도 안된다.
모드D 로 바꿔서 할 수 있기는 있는데 정확히 맞추기가 너무 힘들다
4. 디바이스가 연결될 때마다 이 스크립트를 실행해야 한다. (절전을 위해 자주 꺼진다)
1 에 대해서는 VLC player 의 설정을 변경한다.
도구 > 환경설정 > (왼쪽 아래의) 설정보기에서 전체 선택 > 인터페이스 > 단축키 설정 > 이동 시간: 짧게 에서 5로 변경 > 저장
2 는 디바이스 쪽에서 제어가 되어야 할 것 같다. 전면 버튼 두 개와 조이스틱의 방향 2개가 남지만 보내는 곳에서 같은 값으로 보내면 받는 곳에서는 할 수 있는게 없다.
3 은 이 방법에 익숙해 지거나, 마우스를 사용하거나, 디바이스 쪽에서 제어가 되어야 할 것 같다.
4 는 udev 를 설정해서 해결하기로 한다.
* udev 설정
udevadm 을 실행하고 디바이스를 연결하여 표시되는 메시지를 확인한다.
$ udevadm monitor --udev
monitor will print the received events for:
UDEV - the event which udev sends out after rule processing
UDEV [9025.790074] add /devices/pci0000:00/0000:00:14.0/usb1/1-10/1-10:1.0/bluetooth/hci0/hci0:3585 (bluetooth)
UDEV [9025.800014] add /devices/virtual/misc/uhid/0005:05AC:022C.0014 (hid)
UDEV [9025.806226] add /devices/virtual/misc/uhid/0005:05AC:022C.0014/input/input40 (input)
UDEV [9025.810143] add /devices/virtual/misc/uhid/0005:05AC:022C.0014/hidraw/hidraw3 (hidraw)
UDEV [9025.811948] add /devices/virtual/misc/uhid/0005:05AC:022C.0014/input/input40/mouse3 (input)
UDEV [9025.814807] add /devices/virtual/misc/uhid/0005:05AC:022C.0014/input/input40/js0 (input)
UDEV [9025.926914] add /devices/virtual/misc/uhid/0005:05AC:022C.0014/input/input40/event22 (input)
UDEV [9026.992700] bind /devices/virtual/misc/uhid/0005:05AC:022C.0014 (hid)
$ udevadm monitor --environment --udev
. . .
UDEV [8397.519158] add /devices/virtual/misc/uhid/0005:05AC:022C.0012/input/input38/event22 (input)
ACTION=add
DEVPATH=/devices/virtual/misc/uhid/0005:05AC:022C.0012/input/input38/event22
SUBSYSTEM=input
DEVNAME=/dev/input/event22
. . .
$ udevadm info -a /dev/input/event22
|
몇 가지 테스트를 해보니
1. udevadm info -a <디바이스> 의 결과에 나오는 ATTR 또는 ATTRS 등을 그대로 써야한다.
예로 많은 문서에서 vender id 를 참조할 때 ATTRS{idVendor} 를 사용하지만 이 디바이스는 ATTRS{id/vendor} 를 사용해야 동작했다.
2. 스크립트를 한 번만 실행되게 하려면 룰이 정확히 한 번만 일치되게 작성해야 한다.
예로 SUBSYSTEM=="input" ACTION="add" ATTRS{id/vendor}=="05ac" ATTRS{id/product}=="022c" 는 mouse3, js0, event22 에 모두 일치해서 세번 실행된다.
간단히 하기 위해 한 번만 발생하는 bind 이벤트를 사용하기로 했다.
$ cat /etc/udev/rules.d/80-vrpark.rules
ACTION=="bind", SUBSYSTEM=="hid", ENV{HID_NAME}=="VR-PARK", RUN+="/tmp/vrpark.sh"
|
* 합체 후 문제
위 룰로 vrpark.sh 가 시작하기는 하는데 매핑 변경은 이루어지지 않았다.
udev 가 스크립트의 xinput 을 실행하지 않음 에 따르면 xinput 이 동작하려면 DISPLAY와 XAUTHORITY 환경변수가 필요하다고 한다.
파일 하나로 관리하고 싶은 마음도 있고 해서 최종 파일은 다음과 같다.
vrpark.sh
참고
* xkb 로 리눅스 키보드 해킹
* 디바이스별 키맵 변경
* xev 로 Fn+F1-F12 키코드 조사
* xkbcomp.dump
* Linux에서 장치 검색 및 관리를 위해 Udev 사용 방법