android_HAL_input.hwp

Similar documents
PowerPoint 프레젠테이션

Microsoft Word doc

비긴쿡-자바 00앞부속

임베디드시스템설계강의자료 6 system call 2/2 (2014 년도 1 학기 ) 김영진 아주대학교전자공학과

Chapter #01 Subject

JAVA 프로그래밍실습 실습 1) 실습목표 - 메소드개념이해하기 - 매개변수이해하기 - 새메소드만들기 - Math 클래스의기존메소드이용하기 ( ) 문제 - 직사각형모양의땅이있다. 이땅의둘레, 면적과대각

PowerPoint 프레젠테이션

Microsoft PowerPoint - lab14.pptx

PowerPoint 프레젠테이션

Microsoft PowerPoint - chap02-C프로그램시작하기.pptx

슬라이드 1

<4D F736F F F696E74202D20C1A63038C0E520C5ACB7A1BDBABFCD20B0B4C3BC4928B0ADC0C729205BC8A3C8AF20B8F0B5E55D>

제11장 프로세스와 쓰레드

A Hierarchical Approach to Interactive Motion Editing for Human-like Figures

<4D F736F F F696E74202D20C1A63034B0AD202D20C7C1B7B9C0D3B8AEBDBAB3CABFCD20B9ABB9F6C6DBC0D4B7C2>

UI TASK & KEY EVENT

PowerPoint 프레젠테이션

JUNIT 실습및발표

untitled

gnu-lee-oop-kor-lec06-3-chap7

PowerPoint Template

chap 5: Trees

K&R2 Reference Manual 번역본

PowerPoint Presentation

Microsoft PowerPoint - Java7.pptx

API 매뉴얼

<4D F736F F F696E74202D20B8AEB4AABDBA20BFC0B7F920C3B3B8AEC7CFB1E22E BC8A3C8AF20B8F0B5E55D>

KEY 디바이스 드라이버

PowerPoint 프레젠테이션


PowerPoint 프레젠테이션

Design Issues

Microsoft PowerPoint - Chapter 6.ppt

PowerPoint Presentation

JAVA PROGRAMMING 실습 08.다형성

어댑터뷰

Microsoft PowerPoint - chap10-함수의활용.pptx

PowerPoint 프레젠테이션

PowerPoint Presentation

교육지원 IT시스템 선진화

10.

4장.문장

PowerPoint 프레젠테이션

PowerPoint 프레젠테이션

쉽게 풀어쓴 C 프로그래밍

adfasdfasfdasfasfadf

프로그램을 학교 등지에서 조금이라도 배운 사람들을 위한 프로그래밍 노트 입니다. 저 역시 그 사람들 중 하나 입니다. 중고등학교 시절 학교 도서관, 새로 생긴 시립 도서관 등을 다니며 책을 보 고 정리하며 어느정도 독학으르 공부하긴 했지만, 자주 안하다 보면 금방 잊어

PowerPoint Presentation

PowerPoint 프레젠테이션

UI TASK & KEY EVENT

슬라이드 1

[ 마이크로프로세서 1] 2 주차 3 차시. 포인터와구조체 2 주차 3 차시포인터와구조체 학습목표 1. C 언어에서가장어려운포인터와구조체를설명할수있다. 2. Call By Value 와 Call By Reference 를구분할수있다. 학습내용 1 : 함수 (Functi

Microsoft PowerPoint - chap03-변수와데이터형.pptx

C# Programming Guide - Types

Secure Programming Lecture1 : Introduction

파일로입출력하기II - 파일출력클래스중에는데이터를일정한형태로출력하는기능을가지고있다. - PrintWriter와 PrintStream을사용해서원하는형태로출력할수있다. - PrintStream은구버전으로가능하면 PrintWriter 클래스를사용한다. PrintWriter

Microsoft PowerPoint - polling.pptx

gnu-lee-oop-kor-lec10-1-chap10

슬라이드 1

PowerPoint 프레젠테이션

UI TASK & KEY EVENT

q 이장에서다룰내용 1 객체지향프로그래밍의이해 2 객체지향언어 : 자바 2

Microsoft PowerPoint - [2009] 02.pptx

Microsoft PowerPoint - 06-Pointer and Memory.pptx

Microsoft PowerPoint - ch09 - 연결형리스트, Stack, Queue와 응용 pm0100

금오공대 컴퓨터공학전공 강의자료

untitled

지난시간에... 우리는 kernel compile을위하여 cross compile 환경을구축했음. UBUNTU 12.04에서 arm-2009q3를사용하여 간단한 c source를빌드함. 한번은 intel CPU를위한 gcc로, 한번은 ARM CPU를위한 gcc로. AR

PowerPoint Template

Microsoft PowerPoint - java1-lab5-ImageProcessorTestOOP.pptx

PowerPoint 프레젠테이션

Microsoft PowerPoint - 06-Chapter09-Event.ppt

PowerPoint Presentation

슬라이드 1

다른 JSP 페이지호출 forward() 메서드 - 하나의 JSP 페이지실행이끝나고다른 JSP 페이지를호출할때사용한다. 예 ) <% RequestDispatcher dispatcher = request.getrequestdispatcher(" 실행할페이지.jsp");

Adding a New Dev file

Embeddedsystem(8).PDF

OCW_C언어 기초

PowerPoint 프레젠테이션

KNK_C_05_Pointers_Arrays_structures_summary_v02

슬라이드 1

11장 포인터

Spring Boot/JDBC JdbcTemplate/CRUD 예제

02 C h a p t e r Java


(Microsoft Word - \301\337\260\243\260\355\273\347.docx)

PowerPoint Presentation

Microsoft PowerPoint - additional06.ppt [호환 모드]

슬라이드 1

Microsoft PowerPoint - additional01.ppt [호환 모드]

<4D F736F F F696E74202D2036C0CFC2B05FB0B4C3BCC1F6C7E2C7C1B7CEB1D7B7A1B9D62E707074>

Microsoft PowerPoint - CSharp-10-예외처리

컴파일러

Microsoft Word - LKP-RTD 사용자 설명서

untitled

슬라이드 1

API 매뉴얼

Microsoft PowerPoint - chap06-5 [호환 모드]

11장 포인터

<443A5C4C C4B48555C B3E25C32C7D0B1E25CBCB3B0E8C7C1B7CEC1A7C6AE425CC0E7B0EDB0FCB8AE5C53746F636B5F4D616E D656E74732E637070>

Transcription:

Android HAL input 1. 안드로이드 Input 시스템개요 안드로이드의 Input 시스템은최하위 Kernel 단에서부터최상위어플리케이션단까지많은단계가존재한다. 이렇게단계가많은이유는 java 가디바이스에접근하기위해서 jni 를사용하였기때문이다. 그럼먼저사용자가입력을한데이터가어플리케이션에전달되는과정을대략적으로알아보도록하자 (1) 사용자입력이일어남 (2) Kernel 에짜여진 input_device_driver 에의해 input_event 가발생함 (3) EventHub.cpp에서 /dev/input/ 의디바이스드라이버파일을읽어서발생한 input_event를읽어냄 (4) jni를통해 KeyInputQueue.java 로 input_event를넘김 (5) KeyInputQueue 에서는무한루프를돌면서 input_event 가 jni를통해넘어오는지를계속감시하다가넘어온다면 QueueEvent 리스트의 tail 에붙임.( 내부스레드로처리 ) (6) 만약상위단에서현재의 Key 값을필요로하면 QueueEvent 리스트의 head를넘겨주고삭제함. (KeyInputQueue.getEvent() 함수 ) (7) WindowManagerService에서무한루프로 KeyInputQueue.getEvent() 함수를계속호출하면서큐에이벤트가추가되면바로원하는어플리케이션으로 dispatch 해줌안드로이드 Input 시스템을공부하는이유는궁극적으로 Input 디바이스를추가하거나변경하기위해서일것이다. 그러기위해서위의모든단계를손봐줄필요는없고 Input Device Driver 만안드로이드 Input 시스템에맞춰서잘짜주면된다. 2. Input device driver 인풋디바이스드라이버는커널에포함되어있다. 그래서커널소스를수정해야하는데인풋디바이스관련소스는커널루트에서 drivers/input/keyboard/ 디렉토리에있다. 인풋디바이스드라이버의코드는아래와같은형태로짜여져있다. static void timer_callback(unsigned long data) // 하드웨어값을읽어냄 s3c_gpio_getpin() // 읽어낸값을보고함 input_report_switch(); input_report_key(); input_report_abs(); input_sync(); static int devinit driver_probe(struct platform_device *pdev) // input 디바이스생성 input_dev = input_allocate_device()

// input 디바이스초기화 // input 디바이스등록 input_register_device(input_dev) // 하드웨어초기화 s3c_set_gpio_func() set_bit() // timer 초기화및등록 init_timer() add_timer() static int devexit driver_remove(struct platform_device *pdev) // 자원해제코드 input_unregister_device(input_dev); del_timer(); static void release_device(struct device *dev) struct platform_device mep6410_joybut_device_t =.name = DRV_NAME,.id = 0,.num_resources = 0,.dev =.release = release_device,, ; static struct platform_driver driver_t =.probe = driver_probe,.remove = driver_remove,.driver =.name = DRV_NAME,.owner = THIS_MODULE,, ; int init driver_init() res = platform_device_register(&device_t); res = platform_driver_register(&driver_t); void exit driver_exit() platform_device_unregister(&device_t); platform_driver_unregister(&driver_t); module_init(driver_init); module_exit(driver_exit); MODULE_LICENSE("GPL"); 안드로이드인풋디바이스드라이버는커널디바이스모델을따라작성해줘야한다. 결국커널디바이스모델의개념을이해하고있어야하는데이에대한자세한내용은이책의범위를벗어나기때문에설명하지않는다. 위의소스는결과적으로 input_report_xxx() 함수에의해서하드웨어에서읽혀진값이올라가도록되어있는구조이다. 이렇게올라가는값은 input_event 라는커널상의구조체형식으로올라가는데이구조체

는아래와같은형태로 linux/input.h 파일에선언되어있다. struct input_event struct timval time; unsigned short type; unsigned short code; unsigned int value; ; 이구조체의각필드는다음과같은역할을한다. 필드설명 time 입력이벤트가발생한시간정보다양한입력장치에의해입력된정보를구분하는타입을나타낸다. 이것을구분하는이유는각각의장치의형태가다르기때문이다. type 예를들어터치는값이정해져있기때문에절대값위치정보 (EV_ABS) 를제공하고마우스는상대적이기때문에변화량을위한위치정보 (EV_REL) 를제공한다. 또한키보드는위치가없기때문에키에관한정보 (EV_KEY) 를제공한다. 이필드는입력한정보를세분화하는필드이다. 예를들어마우스는 X 좌표와 Y 좌표를각각따로따로전송한다. 결국이를 code 구분하기위한구분자가필요한데이필드가그러한역할을한다. 또한키입력에서는이필드가 keycode 가된다. 이값은세분화된필드의데이터를저장하는역할을한다. value 이값역시입력장치마다쓰임세가다른데마우스에서는 X,Y 좌표를입력받고키에서는키가눌리어있는지를확인할때쓰인다. 결국안드로이드시스템에서는커널에서넘겨주는 input_event 형태의값만파싱해서쓰면되는것이다. 3. 안드로이드에서의 input 시스템 가. 안드로이드 native 단에서 input 값읽어내기 커널에서 input_event를얻어오기위해서는디바이스파일을읽어내야한다. 디바이스파일경로는 /dev/input/* 형태로되어있다. 여기서 "/dev/input" 이라는디렉토리는마우스나키보드, 트랙볼등인풋에관련된디바이스를모아놓은부분이다. 안드로이드에서이를읽어내서처리하는부분을담당하는파일은 frameworks/base/libs/ui/eventhub.cpp" 이다. struct pollfd *mfds; bool EventHub::getEvent() if (!mopened) merror = openplatforminput()? NO_ERROR : UNKNOWN_ERROR; // "/dev/input/*" 디바이스읽어내기

mopened = true; while(1) release_wake_lock(wake_lock_id); pollres = poll(mfds, mfdcount, -1); acquire_wake_lock(partial_wake_lock, WAKE_LOCK_ID); for(i = 1; i < mfdcount; i++) if(mfds[i].revents) if(mfds[i].revents & POLLIN) res = read(mfds[i].fd, &iev, sizeof(iev)); if (res == sizeof(iev)) [ 읽어낸값파라메터로넘겨주기 ] return true; <EventHub.cpp : getevent()> 가장먼저 openplatforminput() 함수가보이는데이부분에 input 디바이스를 open 하는부분이들어있다. 이렇게 open 된인풋디바이스 fd 들에게서 POLLIN 이벤트가일어나게되면넘어온 input_event 의내용을파라메터로넘겨주게된다. 넘겨준값을어떻게처리하는지는다음장에서알아보기로하고이번장에서는제목과마찬가지로디바이스를여는데초점을맞추기로하겠다. static const char *device_path = "/dev/input"; bool EventHub::openPlatformInput(void) res = scan_dir(device_path); if(res < 0) LOGE("scan dir failed for %s n", device_path); return true; <EventHub.cpp : openplatforminput()> device_path 변수가 /dev/input" 로잡혀있다. 이것은 input 관련된 device 가모여있는디렉토리이다. 즉 scan_dir() 함수는이러한디렉토리를열어서모든디바이스파일을오픈하도록해주는기능을한다.

int EventHub::scan_dir(const char *dirname) dir = opendir(dirname); while((de = readdir(dir))) // devname= 열린파일절대경로 open_device(devname); closedir(dir); return 0; <EventHub.cpp : scan_dir()> 이와같이디렉토리자체를열어서 readdir 로순회하면서각파일마다 open_device() 함수를호출하게되어있다. 이러한내용으로미루어볼때 open_device() 함수에 open() 시스템콜이들어가있을확률이높다. 그럼확인해보도록하자. struct pollfd *mfds; int mfdcount; int EventHub::open_device(const char *devicename) fd = open(devicename, O_RDWR); new_mfds = (pollfd*)realloc(mfds, sizeof(mfds[0]) * (mfdcount + 1)); mfds = new_mfds; mfds[mfdcount].fd = fd; mfds[mfdcount].events = POLLIN; mfdcount++; return 0; <EventHub.cpp : open_device()> 사실이함수의내용은상당히길다. 거기서중요한기능을간추리면위와같다. 가장먼저 open() 시스템콜로디바이스를오픈하고전역변수 mfds를 realloc() 으로늘려준다음내용을채운다. 마지막으로 mfdcount 변수를증가시키고리턴하게된다. 이로서 mfds 변수에는모든 input 디바이스의 fd 가들어가게되고이를 getevent() 함수에서 poll 하여서사용할수있는것이다. 나. 안드로이드 framework 에서 input 값읽어내기 사실 framework 와 native 사이에는 jni 가존재하지만이것은그저데이터의이동통로

만을정의해줄뿐새로운기능을하는것은아니다. 그래서이부분은설명하지않도록하겠다. 그럼먼저 getevent() 함수가어떤특징이있는지간략하게알아보고 Framework에서어떤식으로처리하는지알아보도록하자. struct pollfd *mfds; bool EventHub::getEvent() while(1) for(i = 1; i < mfdcount; i++) if(mfds[i].revents) if(mfds[i].revents & POLLIN) res = read(mfds[i].fd, &iev, sizeof(iev)); if (res == sizeof(iev)) [ 읽어낸값파라메터로넘겨주기 ] return true; <EventHub.cpp : getevent()> EventHub.cpp 의 getevent() 함수를다시한번보게되면무한루프를돌고있는것을알수있다. 이것으로 getevent() 함수가계속 input 디바이스를감시하고있는것으로오해하기쉽다. 그러나여기서는제대로읽어내기만하면 true를리턴해서바로무한루프를끝내준다. 즉 getevent() 는제대로읽어내기전까지는무한루프 (block) 이고제대로읽어낸다면리턴이되게된다. 이 getevent() 함수와 JNI를통해연결되어진 java 메소드는 KeyInputQueue 클래스의 readevent() 메소드이다. 그럼이메소드를사용하는방법에대해서알아보도록하자. package com.android.server; public abstract class KeyInputQueue private static native boolean readevent(rawinputevent outevent); Thread mthread = new Thread("InputDeviceReader") public void run() RawInputEvent ev = new RawInputEvent(); while(true) readevent(ev);

[input 이벤트처리 ] ; KeyInputQueue() mthread.start(); <KeyInputQueue.java> readevent() 메소드는 native 함수로등록되어있고이는 JNI 와통신하여 EventHub.cpp 의 getevent() 함수를부르게된다. readevent() 메소드의파라메터로 RawInputEvent 라는클래스가있는데이것은 getevent() 함수에서넘어온데이터를한군데모아놓은일종의구조체라고보면된다. 즉 JNI 에서는 getevent() 함수를호출해서데이터를받은다음이것을가지고 RawInputEvent 라는클래스를구성해서 readevent() 메소드로돌려주게된다. getevent() 함수는 block 함수이기때문에이를호출하는 readevent() 함수역시 block 함수가된다. java에서이를처리하기위해위처럼 thread를사용하였다. 먼저무한루프를돌면서 readevent() 메소드를호출하여처리하는 mthread를만들고이를 KeyInputQueue 클래스가생성될때시작되도록하였다. 여기서 KeyInputQueue 클래스는 abstract 클래스이기때문에이를상속한어떤클래스가생성되면이스레드가실행되게되는것이다. 다. input 이벤트처리하기 KeyInputQueue 에서는무한루프를돌면서 readevent() 를호출하면서 input 이벤트를가지고온다. 이렇게가져온이벤트의처리방식은서로연결된 QueuedEvent List를유지하면서새로운이벤트가일어나면 List tail 에추가하고어플리케이션에서이벤트를사용하면 head에서삭제하면서처리한다. 이와같은형태로사용되게되며 getevent() 함수는유지하고있는 List에서 head 에있는 Event를리턴하고삭제하는기능을한다. 또한 addlocked() 는유지하고있는 List 의 tail 에다가 Event를추가하는기능을한다. 결국어플리케이션에서는 getevent() 함수만호출해서사용하면된다.

라. 안드로이드에서키값매핑 안드로이드는키이벤트가일어나면이를안드로이드의키로맵핑을해주는데이를설정하는파일이 "build/target/board/generic/xxx.kl" 이다. 이를열어보면아래와같은형태로되어있다. key 399 GRAVE key 2 1 key 3 2 key 158 BACK WAKE_DROPPED key 230 SOFT_RIGHT WAKE key 60 SOFT_RIGHT WAKE key 107 ENDCALL WAKE_DROPPED key 62 ENDCALL WAKE_DROPPED key 229 MENU WAKE_DROPPED key 102 HOME WAKE key 105 DPAD_LEFT WAKE_DROPPED key 106 DPAD_RIGHT WAKE_DROPPED key 115 VOLUME_UP key 114 VOLUME_DOWN key 116 POWER WAKE key 212 CAMERA 가장처음숫자는 input_event에서넘어오는키코드에비례하고그옆의문자는안드로이드에서어떤키에맵핑될지를나타낸다. 이렇게얻어낸키이벤트는캐릭터코드로맵핑되는데이를처리하는파일은 "build/target/board/generic/xxx.kcm" 이다. 이파일은아래와같은형태로되어있다. [type=qwerty] # keycode display number base caps fn caps_fn A 'A' '%' 'a' 'A' '%' 0x00 B 'B' '=' 'b' 'B' '=' 0x00 C 'C' '8' 'c' 'C' '8' 0x00E7 D 'D' '5' 'd' 'D' '5' 0x00 E 'E' '2' 'e' 'E' '2' 0x0301 Y 'Y' '!' 'y' 'Y' '!' 0x00A1 Z 'Z' '#' 'z' 'Z' '#' 0x00 AT '@' '0' '@' '0' '0' 0x2022 SLASH '/' '/' '/' '?' '?' ' ' SPACE 0x20 0x20 0x20 0x20 0xEF01 0xEF01 ENTER 0xa 0xa 0xa 0xa 0xa 0xa

이 KCM 파일은처리속도를높이기위해서컴파일시 "xxx.kcm.bin" 과같은바이너리형태로바뀌게된다. 이렇게안드로이드에서는최하위디바이스드라이버와 kl,kcm 파일만시스템에맞게수정해주면쉽게포팅가능하다.