웹캠의 입력 이벤트를 키보드의 키로 다시 매핑

웹캠의 입력 이벤트를 키보드의 키로 다시 매핑

저는 애플리케이션이 특정 작업을 수행하도록 지시하기 위해 웹캠의 트리거에서 입력을 읽어야 하는 애플리케이션을 개발 중입니다.

이 프로젝트에는 QT 지원으로 구축된 OpenCV가 포함되어 있으며 이 트리거를 적용하면 무작위 충돌이 발생합니다(ASSERT: qasciikey.cpp 파일의 'false', 495행).

그래서 더 간단하고 안정적인 방법은 외부 트리거를 키(특히 스페이스바)에 매핑하는 것이라고 생각합니다. 하고 싶지 않다씌우다스페이스바를 누르면 방아쇠가 스페이스바를 누른 것처럼 보이게 됩니다.

지금까지 evtest를 사용하여 장치를 선택했습니다.

/dev/input/event13: See3CAM_CU51

카메라를 실행하면 다음이 표시되는 것을 볼 수 있습니다.

Event: time 1507757166.472300, type 1 (EV_KEY), code 212 (KEY_CAMERA), value 1
Event: time 1507757166.472300, -------------- SYN_REPORT ------------
Event: time 1507757167.147649, type 1 (EV_KEY), code 212 (KEY_CAMERA), value 0
Event: time 1507757167.147649, -------------- SYN_REPORT ------------

"값 1"은 핀이 높게 당겨진 경우(트리거된 경우), "값 0"은 핀이 분리된 경우입니다. 그래서 KEY_CAMERA를 스페이스바에 다시 매핑하면 될 것 같지만 Ubuntu 16.04에서 이 작업을 수행하는 가장 깔끔한 방법은 잘 모르겠습니다.

키보드 장치를 선택할 때:

/dev/input/event4: AT Translated Set 2 keyboard

스페이스바를 누르면 다음과 같은 결과가 출력됩니다.

Event: time 1507757327.011812, -------------- SYN_REPORT ------------
Event: time 1507757328.818177, type 4 (EV_MSC), code 4 (MSC_SCAN), value 39
Event: time 1507757328.818177, type 1 (EV_KEY), code 57 (KEY_SPACE), value 1
Event: time 1507757328.818177, -------------- SYN_REPORT ------------
Event: time 1507757328.896970, type 4 (EV_MSC), code 4 (MSC_SCAN), value 39
Event: time 1507757328.896970, type 1 (EV_KEY), code 57 (KEY_SPACE), value 0

나는 hwdb udev 파일 작성에 대해 읽었지만 한 장치에서 다른 장치로 입력을 매핑하는 방법을 찾지 못했습니다. 가능합니까? 이를 달성하는 가장 쉬운 방법은 무엇입니까?

미리 감사드립니다.

답변1

정답은 아마도 [hwdb] 파일을 작성 하여 KEY_CAMERA.KEY_SPACE이것예시처럼 보이지만 디테일이 좀 부족하네요.

파일 형식은 주로 파일 머리 부분 /usr/lib/udev/hwdb.d/60-keyboard.hwdb(내 시스템의 경우)에 있는 주석에 설명되어 있습니다.아키텍처Linux이에 대한 토론. 이 형식은 systemd 버전에 따라 다르므로 자신의 파일을 확인하세요. 입력 장치를 다음 3가지 모드 중 하나에 맞출 수 있습니다.

  • 범용 입력 장치 일치:

      evdev:입력:bZZZZvYYYYpXXXXeWWWW-VVVV

    이는 입력 장치의 커널 모달 별칭과 일치합니다. 기본적으로 ZZZZ는 버스 ID(/usr/include/linux/input.h BUS_* 참조)이고 YYYY, XXXX 및 WWW는 4자리 16진수 대문자 공급자, 제품 및 버전 ID 및 VVVV는 장치 기능을 설명하는 임의 길이의 입력 양식입니다.

  • AT 키보드 DMI 데이터 매칭:

      evdev:atkbd:dmi:bvn*:bvr*:bd*:svn행상인:pn제품:개인 영상*

    Vendor 및 Product는 커널 DMI 모달에서 내보낸 펌웨어에서 제공하는 문자열입니다.

  • 일치하는 드라이버 장치 이름과 DMI 데이터를 입력하세요.

      evdev:이름:장치 이름을 입력하세요:dmi:bvn*:bvr*:bd*:svn행상인:pn*

    입력 장치 이름은 드라이버가 지정한 장치 이름이고, 공급업체는 커널 DMI 모달리아에서 내보낸 펌웨어에서 제공하는 문자열입니다.

또 다른 가능성은 evtest처럼 웹캠 이벤트 스트림을 읽고 키가 표시되면 KEY_SPACE다른 이벤트 스트림에 삽입하는 작은 프로그램을 작성하는 것입니다. 이에 대한 더 많은 문서와 이와 같은 Python 예제가 많이 있는 것 같습니다.지도 시간이벤트 주입을 위한 조각입니다.

답변2

hwdb 사용에 관한 @meuh의 답변에 추가하여 hwdb 작동 방식에 대해 배운 몇 가지 사항은 다음과 같습니다. 이것은 주로 hwdb에 대한 키보드 스캔 코드 매핑에 관한 것이지만, 많은 부분이 다른 hwdb 정보에도 유용합니다.

원천:

여기에서 수집된 정보를 처리하는 방법에 대한 실제적인 예는 다음을 참조하세요.이 게시물"에코버튼"의 용도 변경과 관련하여, 눌렀을 때 일련의 키 입력을 보내는 단일 버튼 "키보드"입니다.

hwdb에는 어떤 식별자가 사용됩니까?

실제로 어떤 hwdb 식별자가 사용되고 있는지 확인하려면 다음을 사용할 수 있습니다 udevadm.

$ sudo udevadm test /sys/class/input/event256 |& grep builtin.command..hwdb
event256: /usr/lib/udev/rules.d/60-evdev.rules:8 Importing properties from results of builtin command 'hwdb --subsystem=input --lookup-prefix=evdev:'
event256: /usr/lib/udev/rules.d/60-evdev.rules:18 Importing properties from results of builtin command 'hwdb 'evdev:name:HID 3412:7856:phys:usb-0000:00:14.0-1.1.2.4/input0:ev:120013:dmi:bvnINSYDECorp.:bvr03.17:bd10/27/2022:br3.17:svnFramework:pnLaptop:pvrAB:rvnFramework:rnFRANBMCP0B:rvrAB:cvnFramework:ct10:cvrAB:skuFRANBMCP0B:''
event256: /usr/lib/udev/rules.d/60-evdev.rules:23 Importing properties from results of builtin command 'hwdb 'evdev:name:HID 3412:7856:dmi:bvnINSYDECorp.:bvr03.17:bd10/27/2022:br3.17:svnFramework:pnLaptop:pvrAB:rvnFramework:rnFRANBMCP0B:rvrAB:cvnFramework:ct10:cvrAB:skuFRANBMCP0B:''
event256: /usr/lib/udev/rules.d/60-input-id.rules:6 Importing properties from results of builtin command 'hwdb --subsystem=input --lookup-prefix=id-input:modalias:'
event256: /usr/lib/udev/rules.d/65-libwacom.rules:19 Importing properties from results of builtin command 'hwdb --subsystem=input '--lookup-prefix=libwacom:name:HID 3412:7856:''

이는 위의 udev 규칙에 표시된 4개의 hwdb 명령 중 3개를 시도한다는 점에 유의하십시오. 여기서 evdev:atkbd 명령은 이 USB 키보드에만 적용되고 DRIVERS=="atkbd"이 USB 키보드에는 적용되지 않습니다.

예를 들어 위 출력에는 다음이 포함됩니다.

event256: /usr/lib/udev/rules.d/60-evdev.rules:18 Importing properties from results of builtin command 'hwdb 'evdev:name:HID 3412:7856:phys:usb-0000:00:14.0-1.1.2.4/input0:ev:120013:dmi:bvnINSYDECorp.:bvr03.17:bd10/27/2022:br3.17:svnFramework:pnLaptop:pvrAB:rvnFramework:rnFRANBMCP0B:rvrAB:cvnFramework:ct10:cvrAB:skuFRANBMCP0B:''

여기에는 내가 연결한 USB 키보드가 아닌 내 노트북과 관련된 식별자가 많이 포함되어 있는 것 같습니다. 하지만 USB vidpid(3412:7856)가 처음에 포함되어 있으며 다음과 같이 일치할 수 있습니다.

evdev:name:HID 3412:7856:*
  KEYBOARD_KEY_70028=backspace

또는 evdev 출력에 다음 내용도 포함됩니다(두 번째 줄은 grep으로 인해 위에 표시되지 않지만 전체 출력에는 표시됩니다).

event256: /usr/lib/udev/rules.d/60-evdev.rules:8 Importing properties from results of builtin command 'hwdb --subsystem=input --lookup-prefix=evdev:'
event256: hwdb modalias key: "input:b0003v3412p7856e0100-e0,1,4,11,14,k74,75,77,7D,7E,7F,B7,ram4,l0,1,2,3,4,sfw"

이 hwdb 호출은 후속 호출처럼 지정된 전체 일치 키를 얻지 못하는 것으로 보이지만 hwdb에 의해 자동으로 생성된 접두사 및 모달리어스 키로 구성됩니다. 따라서 위의 결과는 완전한 핵심입니다.

evdev:input:b0003v3412p7856e0100-e0,1,4,11,14,k74,75,77,7D,7E,7F,B7,ram4,l0,1,2,3,4,sfw

이는 USB vid/pid와 일치하며 다음과 같이 사용할 수 있습니다.

evdev:input:b????v3412p7856e*
  KEYBOARD_KEY_70028=backspace

?이는 다른 USB 버스/포트를 연결할 때 여전히 일치하도록 버스 번호를 일치시키기 위해 와일드카드를 사용합니다 . 또한 *버전 번호와 그 뒤의 기타 모달 콘텐츠에 와일드카드를 사용하는데, 이는 여기서는 관련이 없을 수 있습니다.

어떤 스캔 코드를 사용해야 합니까?

올바른 스캔 코드를 얻는 가장 안정적인 방법은 evtest를 사용하는 것 같습니다. 실행하고 버튼을 누르면 다음과 같은 결과가 나타납니다.

sudo evtest --grab /dev/input/event256 
[ snip debug output]
Event: time 1675505630.859393, -------------- SYN_REPORT ------------
Event: time 1675505630.867333, type 4 (EV_MSC), code 4 (MSC_SCAN), value 70028
Event: time 1675505630.867333, type 1 (EV_KEY), code 28 (KEY_ENTER), value 0

여기에 70028스캔 코드가 있습니다(실제로는 16진수이지만 KEYBOARD_KEY_xx예상되는 내용입니다(예 KEYBOARD_KEY_70028=backspace: ).) USB 키보드는 700xx 스캔 코드를 사용하는 것처럼 보이지만 이전 AT 키보드는 더 낮은 스캔 코드를 사용하는 것 같으므로 더 좋습니다. 온라인에서 코드를 찾는 대신 키보드로 테스트해 보세요.

또한 이러한 스캔 코드는 16진수(0x 접두어는 모든 곳에서 생략됨)로 작성된 것으로 나타나는 반면, 키코드는 10진수로 작성 및 분석되지만 100% 확실하지는 않습니다.

당신은 또한 볼 수 있습니다이 페이지

어떤 키코드를 사용해야 합니까?

이러한 키코드의 정식 소스는 다음과 같습니다.이벤트 코드를 입력하세요커널에서는 모든 KEY_xxx 상수입니다.

숫자값, KEY_xxx, xxx 값은 모두 허용되는 것 같습니다. 예를 들어, 다음은 Enter 키를 매핑하여 백스페이스 키를 생성하는 것과 동일합니다.

 KEYBOARD_KEY_70028=14
 KEYBOARD_KEY_70028=key_backspace
 KEYBOARD_KEY_70028=backspace

evtest시작 시 출력(지원되는 EV_KEY 이벤트 코드), evtest키를 눌렀을 때( EV_KEY이벤트 코드) 동일한 키 코드가 표시되는 것으로 나타남

당신은 또한 볼 수 있습니다이 페이지

입력 장치에 대한 현재 스캔 코드 매핑을 어떻게 볼 수 있나요?

입력 장치와 일부 ioctl을 사용하여 쿼리하는 것이 가능해야 한다고 가정하지만 이 작업을 수행할 수 있는 기존 명령줄 도구가 있는지는 확실하지 않습니다. 찾으시면 댓글 남겨주세요.

시작 시 인쇄되는 지원되는 EV_KEY 목록은 힌트를 제공하는 것 같습니다 evtest. 목록에는 일부 스캔 코드가 매핑된 키 코드만 포함되어 있는 것 같습니다.

hwdb 파일에 변경 사항을 적용하는 방법은 무엇입니까?

다음 명령을 사용하여 hwdb 파일을 /etc/udev/hwdb.bin으로 다시 컴파일해야 합니다.

$ sudo systemd-hwdb update

USB 장치를 다시 연결하거나 다음을 사용하여 udev가 규칙을 다시 실행하도록 강제합니다.

$ sudo udevadm trigger /sys/class/input/event256

hwdb는 어디에서 호출됩니까?

hwdb의 키와 값은 udev에 하드코딩되지 않고 규칙 파일에 의해 결정됩니다. 예를 들어 /usr/lib/udev/rules.d/60-evdev.rules는 입력/키보드 규칙을 처리합니다.

IMPORT{builtin}="hwdb --subsystem=input --lookup-prefix=evdev:", \
  IMPORT{builtin}="keyboard", GOTO="evdev_end"

# AT keyboard matching by the machine's DMI data
DRIVERS=="atkbd", \
  IMPORT{builtin}="hwdb 'evdev:atkbd:$attr{[dmi/id]modalias}'", \
  IMPORT{builtin}="keyboard", GOTO="evdev_end"

# device matching the input device name + properties + the machine's DMI data
KERNELS=="input*", \
  IMPORT{builtin}="hwdb 'evdev:name:$attr{name}:phys:$attr{phys}:ev:$attr{capabilities/ev}:$attr{[dmi/id]modalias}'", \
  IMPORT{builtin}="keyboard", GOTO="evdev_end"

# device matching the input device name and the machine's DMI data
KERNELS=="input*", \
  IMPORT{builtin}="hwdb 'evdev:name:$attr{name}:$attr{[dmi/id]modalias}'", \
  IMPORT{builtin}="keyboard", GOTO="evdev_end"

따라서 위의 규칙은 hwdb 식별자가 어떻게 구성되는지 정확하게 보여줍니다. 또한 60-evdev.rules와 60-keyboard.hwdb는 서로 관련되어 있지만 이는 단지 관례일 뿐입니다. 모든 hwdb 항목은 단일 데이터베이스에 저장되고 올바른 식별자를 제공하는 모든 udev 규칙과 일치될 수 있습니다.

hwdb 속성은 어떻게 처리됩니까?

이 행이 하는 일은 IMPORT{builtin}="hwdb ..."hwdb를 조회하고 거기에 나열된 모든 속성을 일반 udev 장치 속성으로 표시하는 것입니다(즉, 를 사용하여 쿼리할 수 있습니다 udevadm info).

또한 위의 규칙에는 IMPORT{builtin}="keyboard"udev 내장 유틸리티를 호출하여 KEYBOARD_*속성을 처리하고 이를 사용하여 커널에서 키코드 매핑에 대한 스캔코드를 구성하는 데 사용되는 가 포함되어 있습니다( EVIOCSKEYCODE입력 장치에서 ioctl 사용, 참조).원천).

다시 말하지만, udevadmin info위에 표시된 대로 사용하면 내장된 결정이 적용되는 키맵이 무엇이든 표시되므로 여기서도 도움이 됩니다.

$ sudo udevadm test /sys/class/input/event256 |& grep mapping
event256: keyboard: mapping scan code 18 (0x12) to key code 0 (0x0)
event256: keyboard: mapping scan code 458770 (0x70012) to key code 0 (0x0)
event256: keyboard: mapping scan code 36 (0x24) to key code 0 (0x0)

( udevadm test실제로는 이렇게 실행됩니다.하다문서에는 한 번만 수행해야 한다고 나와 있지만 이러한 키맵을 직접 적용하십시오. "내장" 메커니즘이 원래 변경 사항을 적용하지 않고 정보만 수집하도록 설계된 것으로 의심되므로 이는 버그일 수 있습니다.)

udev 규칙에서 hwdb/KEYBOARD 속성 설정

Hwdb 항목은 본질적으로 udev 규칙이 직접 수행할 수 있는 것과 마찬가지로 장치 속성을 설정하는 것뿐입니다(그러나 hwdb는 매우 상세한 udev 규칙이 필요 없이 여러 속성을 간결하게 설정하는 것을 더 쉽게 만들기 위해 발명된 것 같습니다). 그러나 이는 더 복잡한 hwdb 대신 udev 규칙만 사용하여 이 키 재매핑을 수행하는 것이 가능해야 함을 의미합니다. 예를 들면 다음과 같습니다.

SUBSYSTEM=="input", KERNEL=="event3", ENV{KEYBOARD_KEY_01}="capslock", ENV{KEYBOARD_KEY_3a}="esc"
SUBSYSTEM=="input", KERNEL=="event3", IMPORT{builtin}="keyboard"

"키보드" 플러그인을 실행하는 udev 규칙은 60-evdev.rules내장된 hwdb 규칙과 동일합니다. 나는 이것이 hwdb 내장 함수가 정보를 찾은 경우에만 "키보드" 규칙이 실행된다는 것을 의미한다고 믿습니다.

hwdb 규칙이 이 특정 장치와 일치하지 않으면 내장된 "키보드"가 실행되지 않을 수 있으므로 이를 실행하기 위해 위에 명시적인 규칙을 추가했습니다(같은 규칙에 있을 때 이것은 별도의 규칙이어야 합니다. ENV항목은 내장 기능이 실행된 후에만 적용되며 이전에는 적용되지 않습니다.

hwdb 규칙이 있는 경우하다60-evdev.rules이 특정 장치와 일치시키려면 위의 두 번째 규칙을 생략하고 내장 키보드를 실행 하면 됩니다 (그러나 위의 udev 규칙은 실행 중인 규칙 파일에 있어야 합니다).앞으로 60-evdev.rules, 그 이후는 아닙니다. udev/eudev의 이전 버전은 RUN내장 키보드를 호출하는 대신 사용 IMPORT하고 이러한 순서 제약이 없는 것 같습니다 .

이 정보의 일부 출처는 다음과 같습니다.이 문제.

udev 내장 함수는 어디에 문서화되어 있나요?

갈 곳이 없을 것 같습니다. 바라보다이 답변이러한 내장 함수의 소스 코드에 대한 일부 포인터입니다.

관련 정보