Microsoft MVP성태의 닷넷 이야기
글쓴 사람
홈페이지
첨부 파일
 

Raspberry Pi Zero(OTG)를 다른 컴퓨터에 연결해 가상 마우스로 쓰는 방법 (절대 좌표)

지난 글에서,

Raspberry Pi Zero(OTG)를 다른 컴퓨터에 연결해 가상 마우스로 쓰는 방법
; https://www.sysnet.pe.kr/2/0/11355

라즈베리 파이 제로를 마우스 장치로 컴퓨터에 인식시키는 방법을 살펴봤는데요. 위의 글에서는 마우스 장치의 제어가 현재 위치를 기준으로 +/- 오프셋 위치를 지정해 움직이는 것을 구현합니다. 예를 들어, 다음과 같이 좌표를 입력하면,

50 50

화면을 기준으로 x = 50, y = 50 위치로 움직이는 것이 아니라, 현재 마우스 위치가 (100, 200)인 경우 (150, 250)으로 움직이는 역할을 합니다. 왜냐하면, report descriptors에 그렇게 움직이도록 상대 값을 지정했기 때문입니다.

05, 01          USAGE_PAGE (Generic Desktop)
09, 30          USAGE (X)
09, 31          USAGE (Y)
15, 81          LOGICAL_MINIMUM (-127)
25, 7f          LOGICAL_MAXIMUM (127)
75, 08          REPORT_SIZE (8)
95, 02          REPORT_COUNT (2)
81, 06          INPUT (Data, Var, Rel)

그럼 절댓값으로 움직이고 싶다면 어떻게 해야 할까요?

그러려면 우선, 값의 범위부터 1바이트(-127 ~ + 127)가 아닌 2바이트(0 ~ 32767) 이상으로 바꿔야 합니다. 왜냐하면 모니터의 좌표 값이 되어야 하기 때문인데, 1024 * 768 모니터만 해도 256의 범위로는 표현할 수 없기 때문입니다. 결국 값의 범위와 함께 절대 좌표로 다음과 같이 지정할 수 있습니다.

05, 01              USAGE_PAGE (Generic Desktop)
09, 30              USAGE (X)
09, 31              USAGE (Y)

15, 00,             LOGICAL_MINIMUM(0)
26, ff, 7f          LOGICAL_MAXIMUM(32767)

75, 10              REPORT_SIZE (16)
95, 02              REPORT_COUNT (2)
81, 02              INPUT (Data, Var, Abs)

이를 반영한 report descriptors를 다음과 같이 쉘 스크립트에 적용해 실행하면 절댓값 지정이 가능한 마우스로 장치가 인식됩니다.

#!/bin/bash
# From the README at https://github.com/girst/hardpass

dtoverlay dwc2
modprobe dwc2
modprobe libcomposite
cd /sys/kernel/config/usb_gadget/
mkdir -p g1
cd g1
echo 0x1d6b > idVendor # Linux Foundation
echo 0x0104 > idProduct # Multifunction Composite Gadget
echo 0x0100 > bcdDevice # v1.0.0
echo 0x0200 > bcdUSB # USB2
mkdir -p strings/0x409
echo "fedcba9876543210" > strings/0x409/serialnumber
echo "girst" > strings/0x409/manufacturer
echo "Hardpass" > strings/0x409/product
N="usb0"
mkdir -p functions/hid.$N
echo 1 > functions/hid.usb0/protocol
echo 1 > functions/hid.usb0/subclass
echo 8 > functions/hid.usb0/report_length

echo -ne \\x05\\x01\\x09\\x02\\xa1\\x01\\x09\\x01\\xa1\\x00\\x05\\x09\\x19\\x01\\x29\\x03\\x15\\x00\\x25\\x01\\x95\\x03\\x75\\x01\\x81\\x02\\x95\\x01\\x75\\x05\\x81\\x03\\x05\\x01\\x09\\x30\\x09\\x31\\x15\\x00\\x26\\xff\\x7f\\x75\\x10\\x95\\x02\\x81\\x02\\xc0\\xc0  > functions/hid.usb0/report_desc

C=1
mkdir -p configs/c.$C/strings/0x409
echo "Config $C: ECM network" > configs/c.$C/strings/0x409/configuration
echo 250 > configs/c.$C/MaxPower
ln -s functions/hid.$N configs/c.$C/
ls /sys/class/udc > UDC

물론 입력 값 구조가 바뀌었으니 driver 측의 코드도 변경해야 합니다.

Linux USB HID gadget driver
; https://www.kernel.org/doc/Documentation/usb/gadget_hid.txt

즉, 다음과 같은 바이트 구조로 장치에 write를 하면 됩니다.

#pragma pack(1)
struct mouse_report_t
{
    uint8_t buttons;
    int16_t x;
    int16_t y;
};

이때, 화면 해상도 크기가 32767 범위로 매핑이 된다는 점을 유의해야 합니다. 만약, 1920 * 1080 해상도의 모니터라면 원하는 x, y 좌표에 대해 다음의 공식에 따라 입력할 수 있습니다.

x = xpos * 32767 / 1920
y = ypos * 32767 / 1080

따라서 정중앙 위치인 (960, 540)으로 이동하고 싶다면,

x = 960 * 32767 / 1920 = 16315
y = 540 * 32767 / 1080 = 16383

(16315, 16383) 값을 입력하면 됩니다. 반면 (10, 100) 위치로 이동하고 싶다면,

x = 10 * 32767 / 1920 = 170
y = 100 * 32767 / 1080 = 3033

(170, 3033) 값이 됩니다.




웹 검색을 해보면, 마우스 절댓값 범위를 65535까지 허용하는 report descriptors를 찾아볼 수 있습니다.

05, 01              USAGE_PAGE (Generic Desktop)
09, 30              USAGE (X)
09, 31              USAGE (Y)

15, 00,             LOGICAL_MINIMUM(0)
27, ff, ff, 00, 00  LOGICAL_MAXIMUM(65535)

75, 10              REPORT_SIZE (16)
95, 02              REPORT_COUNT (2)
81, 02              INPUT (Data, Var, Abs)

echo -ne \\x05\\x01\\x09\\x02\\xa1\\x01\\x09\\x01\\xa1\\x00\\x05\\x09\\x19\\x01\\x29\\x03\\x15\\x00\\x25\\x01\\x95\\x03\\x75\\x01\\x81\\x02\\x95\\x01\\x75\\x05\\x81\\x03\\x05\\x01\\x09\\x30\\x09\\x31\\x15\\x00\\x27\\xff\\xff\\x00\\x00\\x75\\x10\\x95\\x02\\x81\\x02\\xc0\\xc0  > functions/hid.usb0/report_desc

실제로 해보면, 제 경우에는 65535가 아닌 32767로 매핑이 되었습니다. 혹시 이에 대한 이유를 아시는 분은 덧글 부탁드립니다. ^^




참고로, 장치를 등록한 것을 다시 삭제하고 싶다면 다음의 스크립트를 실행하면 됩니다.

$ sudo rm -r /sys/kernel/config/usb_gadget/g1/configs/c.1/



윈도우즈 사용자를 위한 라즈베리 파이 제로 W 모델을 설정하는 방법
; https://www.sysnet.pe.kr/2/0/11372

Raspberry Pi Zero(OTG)를 다른 컴퓨터에 연결해 가상 이더넷 카드로 쓰는 방법
; https://www.sysnet.pe.kr/2/0/11353

Raspberry Pi Zero(OTG)를 다른 컴퓨터에 연결해 가상 키보드로 쓰는 방법
; https://www.sysnet.pe.kr/2/0/11354

Raspberry Pi Zero(OTG)를 다른 컴퓨터에 연결해 가상 마우스로 쓰는 방법
; https://www.sysnet.pe.kr/2/0/11355

Raspberry Pi Zero(OTG)를 다른 컴퓨터에 연결해 가상 마우스 + 키보드로 쓰는 방법
; https://www.sysnet.pe.kr/2/0/11356

Raspberry Pi Zero(OTG)를 다른 컴퓨터에 연결해 가상 마우스로 쓰는 방법 (절대 좌표)
; https://www.sysnet.pe.kr/2/0/11364

Raspberry Pi Zero(OTG)를 다른 컴퓨터에 연결해 가상 키보드 및 마우스로 쓰는 방법 (절대 좌표, 상대 좌표, 휠)
; https://www.sysnet.pe.kr/2/0/11369

라즈베리 파이 용 C++ 프로젝트에 SSL Socket 적용
; https://www.sysnet.pe.kr/2/0/11411

Raspberry Pi/Windows 다중 플랫폼 지원 컴파일 관련 오류 기록
; https://www.sysnet.pe.kr/2/0/11373

Linux 3: 라즈베리 파이 - (윈도우의 NT 서비스처럼) 부팅 시 시작하는 프로그램 설정
; https://www.sysnet.pe.kr/2/0/11374


[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]

[연관 글]





[최초 등록일: ]
[최종 수정일: 8/9/2018 ]

Creative Commons License
이 저작물은 크리에이티브 커먼즈 코리아 저작자표시-비영리-변경금지 2.0 대한민국 라이센스에 따라 이용하실 수 있습니다.
by SeongTae Jeong, mailto:techsharer@outlook.com

비밀번호

댓글 쓴 사람
 



2019-06-13 06시48분
[박승태] 유익한 글 감사합니다. 프로그래밍 초보라서 잘 모르는 부분이 많은데, driver 측의 코드를 어떻게 바꿔야 하는건가요? 어느 부분을 바꿔야하는지 감이 안오네요ㅜㅜ
[손님]
2019-06-13 09시17분
죄종 소스 코드를 다음의 github에 올려두었습니다.

stjeong/rasp_vusb
; https://github.com/stjeong/rasp_vusb

질문하신 부분에 대한 소스 코드는 다음에 있습니다.

https://github.com/stjeong/rasp_vusb/blob/master/rasp_vusb_server/MouseDevice.cpp
정성태

[1]  2  3  4  5  6  7  8  9  10  11  12  13  14  15  ...
NoWriterDateCnt.TitleFile(s)
12207정성태4/2/202071스크립트: 19. Windows PowerShell의 NonInteractive 모드
12206정성태4/2/202044오류 유형: 613. 파일 잠금이 바로 안 풀린다면? - The process cannot access the file '...' because it is being used by another process.
12205정성태4/2/202040스크립트: 18. Powershell에서는 cmd.exe의 명령어를 지원하진 않습니다.
12204정성태4/1/202029스크립트: 17. Powershell 명령어에 ';' (semi-colon) 문자가 포함된 경우
12203정성태3/18/202084오류 유형: 612. warning: 'C:\ProgramData/Git/config' has a dubious owner: '...'.
12202정성태3/18/2020119개발 환경 구성: 486. .NET Framework 프로젝트를 위한 GitLab CI/CD Runner 구성
12201정성태3/18/202047오류 유형: 611. git-credential-manager.exe: Using credentials for username "Personal Access Token".
12200정성태3/18/2020170VS.NET IDE: 145. NuGet + Github 라이브러리 디버깅 관련 옵션 3가지 - "Enable Just My Code" / "Enable Source Link support" / "Suppress JIT optimization on module load (Managed only)"
12199정성태3/17/202048오류 유형: 610. C# - CodeDomProvider 사용 시 Unhandled Exception: System.IO.DirectoryNotFoundException: Could not find a part of the path '...\f2_6uod0.tmp'.
12198정성태3/17/202041오류 유형: 609. SQL 서버 접속 시 "Cannot open user default database. Login failed."
12197정성태3/17/2020139VS.NET IDE: 144. .NET Core 콘솔 응용 프로그램을 배포(publish) 시 docker image 자동 생성 - 두 번째 이야기
12196정성태3/17/202082오류 유형: 608. The ServicedComponent being invoked is not correctly configured (Use regsvcs to re-register).
12195정성태3/17/2020185.NET Framework: 902. C# - 프로세스의 모든 핸들을 열람 - 세 번째 이야기
12194정성태3/16/202063오류 유형: 607. PostgreSQL - Npgsql.NpgsqlException: sorry, too many clients already
12193정성태3/16/202095개발 환경 구성: 485. docker - SAP Adaptive Server Enterprise 컨테이너 실행
12192정성태3/14/2020102개발 환경 구성: 484. docker - Sybase Anywhere 16 컨테이너 실행
12191정성태3/14/2020148개발 환경 구성: 483. docker - OracleXE 컨테이너 실행
12190정성태3/14/202055오류 유형: 606. Docker Desktop 업그레이드 시 "The process cannot access the file 'C:\Program Files\Docker\Docker\resources\dockerd.exe' because it is being used by another process."
12189정성태3/13/2020100개발 환경 구성: 482. Facebook OAuth 처리 시 상태 정보 전달 방법과 "유효한 OAuth 리디렉션 URI" 설정 규칙
12188정성태3/14/202060Windows: 167. 부팅 시점에 실행되는 chkdsk 결과를 확인하는 방법
12187정성태3/12/202045오류 유형: 605. NtpClient was unable to set a manual peer to use as a time source because of duplicate error on '...'.
12186정성태3/12/202063오류 유형: 604. The SysVol Permissions for one or more GPOs on this domain controller and not in sync with the permissions for the GPOs on the Baseline domain controller.
12185정성태3/11/202062오류 유형: 603. The browser service was unable to retrieve a list of servers from the browser master...
12184정성태3/11/202069오류 유형: 602. Automatic certificate enrollment for local system failed (0x800706ba) The RPC server is unavailable.
12183정성태3/12/202072오류 유형: 601. Warning: DsGetDcName returned information for \\[...], when we were trying to reach [...].
[1]  2  3  4  5  6  7  8  9  10  11  12  13  14  15  ...