input 테스트
usb로 들어오는 버튼 입력을 테스트 했다. LED를 켜는 출력과 비슷하게 진행된다. 역시 출력을 보는 작업이 제일 어려웠다.
- 입력 디바이스 할당: input_allocate_device();
- urb 할당
- usb_alloc_coherent
- usb_alloc_urb
- 인터럽트로 urb 설정: usb_rcvintpipe, usb_fill_int_urb
- input device 주소 변경?: input_set_drvdata
- open, close 함수 오버로드
- input_dev->open = xpad_open
- input_dev->close = xpad_close
- usb_submit_urb call back 함수 설정
input_dev->close에 usb_kill_urb로 urb를 해제하지 않으면 다시 입력 디이스를 열었을 때 사용할 수 없다.
xpad.c 드라이버는 인터럽트 실행될 때 완료 함수를 등록했다. 그 함수 안에있는 work queue가 input_report_key, input_sync로 입력 키를 이벤트로 OS에 전달한다.
버튼이 눌렸을 경우 이벤트가 0, 1 값으로 전달되어야 한다. urb로 들어오는 data 패킷 중 2번, 3번 주소에 mask를 씌워 EV_KEY 값 상태를 확인한다.
- 인터럽트 발생 확인.
- urb data 값 수신.
- 해당하는 주소에 mask를 씌워 특정 이벤트를 OS에 전달.
리눅스 시스템 내에서 사용할 수 있는 이벤트가 이미 정해져 있어 사용자 맘대로 설정할 수 없다. 그 말은 조이스틱 이동을 마우스 이동 키로 할당하면 마우스 대신 조이스틱을 사용할 수 있단 말이다. 조이스틱을 눌렀을 때 어느 데이터가 켜지는지는 기기마다 다르기 때문에 몇 번 테스트를 해야 한다.
static void xpad360_process_packet(struct usb_xpad *xpad, struct input_dev *dev, u16 cmd, unsigned char *data) { if (data[0] != 0x00) return; /* buttons A,B,X,Y,TL,TR and MODE */ input_report_key(dev, BTN_A, data[3] & 0x10); input_report_key(dev, BTN_B, data[3] & 0x20); input_sync(dev); }
아날로그 버튼이라면 얼마나 눌렸는지 값을 전달할 수 있다. 콘솔에서 실행 가능한 evtest로 입력값을 확인할 수 있다.
xpad.c를 직접 해 보면서 다음을 학습했다. The Linux Kernel 에는 너무 간단한 예가 있다. 내가 무엇을 알고 있고, 모르는 지를 정확하게 확인되지 않고는 위 문서를 제대로 이해할 수 없다. 적절한 삽질로 정확하게 이해할 수 있다.
- usb 등록, 해제
- urb packet 사용 방법
- input device 등록, 해제
- input device 사용
참조 사이트