리눅스(Raspberry Pi OS Bullseye) 기반 터치패널을 사용해 제품을 개발하는데, 이 패널을 세로모드로 세워서 쓰다보니 양산용으로 셋업하는 것이 여간 번거로운 것이 아니다. 터치패널의 Calibration 값이 터치패널 내부에 저장되기 때문에 리눅스 이미지나 패키지 배포로 일괄 적용할 수 없기 때문이다.
최후의 수단으로 터치패널의 컨트롤러(Microchips AR1100)를 직접 제어하기로 하고 좀 더 쉬운 방법이 있는지 찾아 보았다.
라즈베리파이 OS는 커널 파라미터를 설정하는 cmdline.txt파일과 디바이스 드라이버 파라미터를 설정하는 config.txt파일을 제공한다. 가장 간편한 방법은 이 2개의 파일에 설정을 추가하거나 변경하는 것이다.
아쉽게도 bullseye 버전부터는 cmdline.txt에서 부팅화면의 디스플레이 방향을 설정하는 것만 가능하고 config.txt에서 가능했던 데스크탑 화면의 디스플레이 설정은 더이상 동작하지 않는다.
cmdline.txt 파일에 다음 내용을 추가하는 것으로 디스플레이에 방향을 설정하고 이 설정값을 기준으로 데스트탑화면과 터치패널의 화면을 자동으로 변경하도록 한다.
# cmdline.txt의 설정은 모두 한줄에 작성되어야 한다.
$ cat /boot/cmdline.txt
... video=HDMI-A-1:800x480@60,rotate=270 ...
cmdline.txt에 설정할 video display의 이름을 모르는 경우 다음 명령으로 확인할 수 있다.
$ kmsprint -m
Connector 0 (32) HDMI-A-1 (connected)
0 800x480@60.06 33.300 800/210/46/0/- 480/22/23/0/- 60 (60.06) P|D
1 800x480@58.91 29.217 800/24/72/96/- 480/3/10/7/+ 59 (58.91) U
디스플레이 해상도와 주파수, rotate 값을 입력한다. 디스플레이를 회전시킬 각도를 시계방향(clockwise)로 설정한다.
Bullseye 버전부터는 GTK+2가 GTK+3으로 업그레이되고 Video Core도 Fake KMS(Kernel Mode Setting)대신 KMS를 그대로 사용하면서 X-Window 스크린 회전은 Screen Configuration Application(arandr)를 통해 설정한다.
사용 중인 터치패널이 이 Application과 호환된다면 터치 회전도 함께 설정할 수 있다.
CLI에서 직접 설정하는 것도 가능하다. 여기서는 회전 각도 대신에 방향(left, right)을 사용한다.
xrandr --output HDMI-1 --primary --mode 800x480 --pos 0x0 --rotate right
디스플레이 서버를 기존 X11대신 Wayland/Wayfire 조합을 사용한다면 더 쉽게 설정할 수 있다.
# .config/wayfire.ini
[output:HDMI-A-1]
mode = 800x480@60
transform = 270
현재 사용 중인 디스플레이 서버 방식은 다음 명령으로 확인할 수 있다.
loginctl show-session $(loginctl | grep $(whoami) | awk '{print $1}') -p Type
사용중인 터치패널이 Raspberry Pi에서 제공하는 공식 제품이라면 운이 좋다. config.txt에서 터치 디바이스 드라이버를 아래와 같이 설정해주면 끝이다.
dtoverlay=vc4-kms-dsi-7inch,sizex=480,sizey=800,swapxy,invx,invy
아쉽게도 내가 사용중인 AR1100 디바이스는 위와 같은 설정 파라미터를 제공하지 않는다.
사용 중이 AR1100 드라이버 로딩 정보는 다음 명령으로 확인할 수 있다.
$ dmesg | grep AR1100
[...] usb 1-1.2: New USB device found, idVendor=04d8, idProduct=0c02, bcdDevice= 1.04
[...] usb 1-1.2: New USB device strings: Mfr=1, Product=3, SerialNumber=0
[...] usb 1-1.2: Product: AR1100 HID-MOUSE
[...] usb 1-1.2: Manufacturer: Microchip Technology Inc.
[...] input: Microchip Technology Inc. AR1100 HID-MOUSE as /devices/platform/soc/fe980000.usb/usb1/1-1/1-1.2/1-1.2:1.0/0003:04D8:0C02.0001/input/input1
[...] hid-generic 0003:04D8:0C02.0001: input,hidraw0: USB HID v1.11 Mouse [Microchip Technology Inc. AR1100 HID-MOUSE] on usb-fe980000.usb-1.2/input0
위 정보는 디바이스 파일로도 확인할 수 있다.
$ ls /dev/input
by-id by-path event0 event1 mice mouse0
$ ls -al /dev/input/by-id
usb-Microchip_Technology_Inc._AR1100_HID-MOUSE-event-mouse -> ../event1
usb-Microchip_Technology_Inc._AR1100_HID-MOUSE-mouse -> ../mouse0
고맙게도 X-Window는 마우스/디지타이저/터치패널 같은 입력장치에 대해 여러가지 설정 파라미터를 제공한다. 먼저 설정할 터치 디바이스의 id를 확인한다.
$ export DISPLAY=:0 # for SSH
$ xinput list
Virtual core pointer id=2 [master pointer (3)]
↳ Virtual core XTEST pointer id=4 [slave pointer (2)]
↳ vc4-hdmi-0 id=7 [slave pointer (2)]
↳ Microchip Technology Inc. AR1100 HID-MOUSE id=6 [slave pointer (2)]
이제 디바이스의 설정값들을 살펴보고 터치입력 회전을 위해 좌표변환 Matrix를 설정한다.
$ xinput list-props 6 # for AR1100 id=6
$ xinput set-prop 6 "Coordinate Transformation Matrix" 0 -1 1 1 0 0 0 0 1 # for rotating 270 degrees
이제 부팅 화면의 스크린 방향 설정하기, X-Window와 터치패널의 회전 방법을 확인했으므로 다음 스크립트를 예시로 삼아서 자신의 환경에 맞게 작성하면 된다.
# read booting display rotation
disp_rotate=$(awk /rotate/ /boot/cmdline.txt | awk -F'rotate=' '{print $2}' | awk '{print $1}')
if [ -z "$disp_rotate" ]; then
echo "console rotate is not set in cmdline.txt"
disp_rotate="0"
fi
echo "console rotate=$disp_rotate"
# set rotation on X-Windows
# read X-Windows rotation
xrandr_r=$(xrandr | awk /connected/ | awk '{print $5}')
echo "xrandr rotation=$xrandr_r"
# set xrandr roatation by $disp_rotate
if [[ "$disp_rotate" == "270" && "$xrandr_r" != "right" ]]; then
xrandr --output HDMI-1 --primary --mode 800x480 --pos 0x0 --rotate right
echo "set display rotate=right"
elif [[ "$disp_rotate" == "0" && "$xrandr_r" != "normal" ]]; then
xrandr --output HDMI-1 --primary --mode 800x480 --pos 0x0 --rotate normal
echo "set display rotate=normal"
fi
# set rotation on touch-panel
touch_id=$(xinput list | awk /AR1100/ | awk -F'id=' '{print $2}' | awk '{print $1}')
echo "touch xinput id=$touch_id"
# Normal (0 degrees): [1 0 0, 0 1 0, 0 0 1]
# 90 degrees clockwise: [0 1 0, -1 0 1, 0 0 1]
# 180 degrees: [-1 0 1, 0 -1 1, 0 0 1]
# 270 degrees clockwise: [0 -1 1, 1 0 0, 0 0 1]
if [ "$disp_rotate" == "270" ]; then
# right = set 90
xinput set-prop $touch_id "Coordinate Transformation Matrix" 0 1 0 -1 0 1 0 0 1
echo "set touch coordinate transform=90"
elif [ "$disp_rotate" == "0" ]; then
xinput set-prop $touch_id "Coordinate Transformation Matrix" 1 0 0 0 1 0 0 0 1
echo "set touch coordinate transform=0"
fi