mpx on serial port

2009. 5. 31. 04:22 from 컴퓨터/Linux
멀티포인트 프로젝트를 시작한지 벌써 두달이..

다시 되새겨보면, 임베디드 보드에서 멀티 좌표 정보를 보내주고, USB를 통해 리눅스 디바이스 드라이버를 만드는 것이 최종 목적이다.
하지만 현재 임베디드 보드 상에서 멀티 좌표 정보를 보내줄 수 있는 형편이 아니다. 문제로는 보드 상에서 영상처리를 위해 제공되는 라이브러리나 드라이버 등을 고려해서 제한적인 웹캠만 가능하기 때문이다... ln2440의 r1.4 lcd를 이용해서 임베디드 리눅스를 탑재해서 하려고 했으나, 결국 해당 lcd에 대한 리눅스 디바이스 드라이버가 존재하지 않아서 포기! (제조사에서 제공을 안해줌).
그리고, smdk2440 보드에서 임베디드 리눅스를 포팅하고 하고 있는데, 웹캠 드라이버가 적재되었지만, 해당 qt 버전과 gcc 컴파일러 버전이 너무 낮아서 현재 설치된 서버용 리눅스에서 가동이 안된다는 점.. 아무튼 어려움이 많았다.

그런 상황에서 일단, ln2440 보드에 winCE를 탑재하고나서 로지텍Pro5000 웹캠을 기다리는 중이다... 일단은 winCE에서 lcd에 터치를 하면, 그 좌표 정보를 서버용 리눅스에 전송하게 하였고(강세욱 담당), 전송받은 데이터를 리눅스 드라이버단에서 처리하여 터치스크린 이벤트로 전달하여 mpx기반의 X-window에서 두개 이상의 좌표로 인식하게 하는 것으로 마무리를 지었다. 영상처리를 추가해야 진짜 멀티 포인트인데...

암튼 현 상황은 아래와 같다.



뭐니뭐니해도 임베디드 보드에서 보내는 시리얼 데이터를 가동되는 리눅스 상에서 인터럽트로 처리하는 것이 중요하다. 물론, 터치 스크린 드라이버는 기존 리눅스에 있는 시리얼 기반의 터치 스크린 드라이버를 참조해서, 최대한 비슷하게 구현하였다. (0x80의 의미는 몇년이 지나도 잊혀지지 않을 만큼 나에게 충격을 주었다.. 시리얼 기반이라 0x00이 전송이 불가능하다는 거.. 이걸 어찌 알고 0x80으로 미리 선수를 썼는지..암튼.. 존경스러운 전세계 해커들..)

실행 방법을 까먹을 듯하여 정리해본다.

1) 터치 스크린용 이벤트 드라이버를 생성하는 시리얼 디바이스 드라이버 적재

# insmod uv_mtd.ko
# ./inputattach --uv_mtd /dev/ttyS0 &
# dmesg
May 31 11:20:22 mola_server uv_mtd_init
May 31 11:20:27 mola_server serio: Serial port ttyS0
May 31 11:20:27 mola_server uv_mtd_connect
May 31 11:20:27 mola_server uv_mtd[0] ttyS0/serio0/input0
May 31 11:20:27 mola_server uv_mtd[1] ttyS0/serio0/input1
May 31 11:20:27 mola_server input: UV Serial Multi-TouchScreen #1 as /class/input/input8
May 31 11:20:27 mola_server input: UV Serial Multi-TouchScreen #2 as /class/input/input9


2) 임베디드 보드에서 시리얼로 좌표값을 보내는 프로그램 실행 후 터치 테스트

# dmesg
uv_mtd->count = 2
uv_mtd->length = 13
0 input_report_abs(uv_mtd->dev, ABS_X, 543)
0 input_report_abs(uv_mtd->dev, ABS_Y, 176)
0 input_report_key(uv_mtd->dev, BTN_TOUCH, 0)
1 input_report_abs(uv_mtd->dev, ABS_X, 553)
1 input_report_abs(uv_mtd->dev, ABS_Y, 176)
1 input_report_key(uv_mtd->dev, BTN_TOUCH, 0)

3) X-server 가동

ssh1# ./start_xserver
ssh2# ./start_xclient
ssh3# ./start_mpwm
ssh4# xterm &
ssh4# xinput --list --short
"Virtual core pointer"  id=0    [XPointer]
"Virtual core keyboard" id=1    [XKeyboard]
"Virtual core Xtst pointer"     id=2    [XExtensionPointer]
"Virtual core Xtst keyboard"    id=3    [XExtensionKeyboard]
"Mouse0"        id=4    [XExtensionPointer]
"Mouse1"        id=5    [XExtensionPointer]
"Keyboard0"     id=6    [XExtensionKeyboard]
"<default pointer>"     id=7    [XExtensionPointer]
# xinput --create-master "foobar1"
# xinput --reattach "Mouse0" "foobar1 pointer"
# xinput --create-master "foobar2"
# xinput --reattach "Mouse1" "foobar2 pointer"
# xinput --list --short
"Virtual core pointer"  id=0    [XPointer]
"Virtual core keyboard" id=1    [XKeyboard]
"Virtual core Xtst pointer"     id=2    [XExtensionPointer]
"Virtual core Xtst keyboard"    id=3    [XExtensionKeyboard]
"Mouse0"        id=4    [XExtensionPointer]
"Mouse1"        id=5    [XExtensionPointer]
"Keyboard0"     id=6    [XExtensionKeyboard]
"<default pointer>"     id=7    [XExtensionPointer]
"foobar1 pointer"       id=8    [XPointer]
"foobar1 keyboard"      id=9    [XKeyboard]
"foobar1 Xtst pointer"  id=10   [XExtensionPointer]
"foobar1 Xtst keyboard" id=11   [XExtensionKeyboard]
"foobar2 pointer"       id=12   [XPointer]
"foobar2 keyboard"      id=13   [XKeyboard]
"foobar2 Xtst pointer"  id=14   [XExtensionPointer]
"foobar2 Xtst keyboard" id=15   [XExtensionKeyboard]

4) 추가적인 설정 사항 (Xorg.conf)

Section "ServerLayout"
        Identifier     "X.org Configured"
        Screen      0  "Screen0" 0 0
        InputDevice    "Mouse0" "SendCoreEvents"     <- 중요
        InputDevice    "Mouse1" "SendCoreEvents"     <- 중요
        InputDevice    "Keyboard0" "CoreKeyboard"
        Option         "AllowEmptyInput" "off"
        Option         "AutoAddDevices" "off"
EndSection
...........중략..........
Section "InputDevice"
        Identifier  "Mouse0"
        Driver      "evdev"
        Option      "Protocol" "usb"
        Option      "Device" "/dev/input/event6"       <- 위에 적재된 모듈에 의해 생성된 event 파일 #1
        Option      "ZAxisMapping" "4 5"
EndSection
Section "InputDevice"
        Identifier  "Mouse1"
        Driver      "evdev"
        Option      "Protocol" "usb"
        Option      "Device" "/dev/input/event7"       <- 위에 적재된 모듈에 의해 생성된 event 파일 #2
        Option      "ZAxisMapping" "4 5"
EndSection



p.s. 시리얼 디바이스 드라이버를 개인적으로 꼭 정리하고 싶다. 너무나 고생한 걸 생각하면... ㅡ.ㅜ
Posted by wbhacker :



너무나 돌아온 느낌이다. 시리얼 통신으로 터치스크린 이벤트 좌표값을 가져오기 위해서 구현하는 것인데... 원래는 USB로 할 예정이지만, 그 전에 시리얼로 한번 해보는 것이다. 특별한 설정 없이도 되는 줄 알고.. 하지만, 시리얼 디바이스 드라이버 구현보다는, 연결에 어려움이 꽤 있었다.

우선 kernel의 driver/input/touchscreen/mtouch.c 파일의 내용을 수정해서 새로운 uv_mtd 장치에 대한 시리얼 디바이스 드라이버를 작성하였다.

static int __init mtouch_init(void)
{
        return serio_register_driver(&mtouch_drv);
}

static void __exit mtouch_exit(void)
{
        serio_unregister_driver(&mtouch_drv);
}

module_init(mtouch_init);
module_exit(mtouch_exit);




위 소스는 모듈의 등록과 해제를 담당하는 루틴으로, 보면 insmod 해당모듈.ko를 하게 되면, 그냥 serio_register_driver이 호출되고, 드라이버가 새로이 등록되버린 상태로 가만히 있게 된다.

static irqreturn_t mtouch_interrupt(struct serio *serio,
                unsigned char data, unsigned int flags)
{
        struct mtouch* mtouch = serio_get_drvdata(serio);

        mtouch->data[mtouch->idx] = data;

        if (MTOUCH_FORMAT_TABLET_STATUS_BIT & mtouch->data[0])
                mtouch_process_format_tablet(mtouch);
        else if (MTOUCH_RESPONSE_BEGIN_BYTE == mtouch->data[0])
                mtouch_process_response(mtouch);
        else
                printk(KERN_DEBUG "mtouch.c: unknown/unsynchronized data from device, byte %x\n",mtouch->data[0]);

        return IRQ_HANDLED;
}



위 루틴은 해당 드라이버의 인터럽트 처리 부분이다. 즉, 시리얼 포트(ttyS0)를 통해 데이터가 들어오면, 위 루틴에서 처리를 담당하는 것이다. 이 말은, 데이터가 들어오게 되면 무조건 인터럽트가 걸리게 된다는 것으로, 이 함수에 들어와야 정상이다.. 하지만, 단순히 모듈을 적재하는 것으로 인터럽트를 연결하진 못했다. 이 전에 인터럽트 자체가 등록이 되지 않은 상황이었다. ㅡ.ㅜ

static int mtouch_connect(struct serio *serio, struct serio_driver *drv)
{
        struct mtouch *mtouch;
        struct input_dev *input_dev;
        int err;

        mtouch = kzalloc(sizeof(struct mtouch), GFP_KERNEL);
        input_dev = input_allocate_device();
        if (!mtouch || !input_dev) {
                err = -ENOMEM;
                goto fail1;
        }

        mtouch->serio = serio;
        mtouch->dev = input_dev;
        snprintf(mtouch->phys, sizeof(mtouch->phys), "%s/input0", serio->phys);

        input_dev->name = "MicroTouch Serial TouchScreen";
        input_dev->phys = mtouch->phys;
        input_dev->id.bustype = BUS_RS232;
        input_dev->id.vendor = SERIO_MICROTOUCH;
        input_dev->id.product = 0;
        input_dev->id.version = 0x0100;
        input_dev->dev.parent = &serio->dev;
        input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
        input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
        input_set_abs_params(mtouch->dev, ABS_X, MTOUCH_MIN_XC, MTOUCH_MAX_XC, 0, 0);
        input_set_abs_params(mtouch->dev, ABS_Y, MTOUCH_MIN_YC, MTOUCH_MAX_YC, 0, 0);

        serio_set_drvdata(serio, mtouch);

        err = serio_open(serio, drv);
        if (err)
                goto fail2;

        err = input_register_device(mtouch->dev);
        if (err)
                goto fail3;

        return 0;

 fail3: serio_close(serio);
 fail2: serio_set_drvdata(serio, NULL);
 fail1: input_free_device(input_dev);
        kfree(mtouch);
        return err;
}



우선 인터럽트를 등록하는 위 connect 함수가 호출되어야 한다. 하지만, 이 함수 역시 모듈 적재만으론 되지 않았다. 솔직히 이 문제를 해결하기 위해 약 3일간 밤낮없이 고생한 것 같다. 구글에 검색을 해봐도 이 문제에 봉착한 경우만 있지, 해결 방법에 대해선 별다른 말이 없었기 때문이다. 그 과정에서 알게 된 것이 setserial과 inputattach 프로그램 뿐이었고, 이것에 대한 자세한 설명도 없는 상황이었다.

/*
 * The serio driver structure.
 */

static struct serio_device_id mtouch_serio_ids[] = {
        {
                .type   = SERIO_RS232,
                .proto  = SERIO_MICROTOUCH,
                .id     = SERIO_ANY,
                .extra  = SERIO_ANY,
        },
        { 0 }
};

MODULE_DEVICE_TABLE(serio, mtouch_serio_ids);

static struct serio_driver mtouch_drv = {
        .driver         = {
                .name   = "mtouch",
        },
        .description    = DRIVER_DESC,
        .id_table       = mtouch_serio_ids,
        .interrupt      = mtouch_interrupt,
        .connect        = mtouch_connect,
        .disconnect     = mtouch_disconnect,
};



위 소스와 같이 mtouch_drv는 mtouch_init 함수에 의해서 시리얼 디바이스 드라이버로 등록이 되지만, 실제로 .connect로 정의된 mtouch_connect 함수는 호출이 되지 않는 문제...

결국은, 구글 검색의 힘(해커들의 질의응답... 검색어는 "lagacy serial driver .connect")으로 해결할 수 있었다.

- 참고사이트1 : http://kerneltrap.org/mailarchive/linux-kernel-mentors/2007/12/5/477437
- 참고사이트2 : http://lkml.org/lkml/2007/6/19/254 - Writing a driver for a legacy serial device
- 참고사이트3 : http://lkml.indiana.edu/hypermail/linux/kernel/0706.2/1755.html

The problem is that taos_connect is never called. I suppose that I need
different values for .type, .proto or .id, except that I just don't
know what to put there. I tried a few random values without success.
What's the trick?


참고로 위 질문에서 나의 문제와 똑같다는 것을 느끼게 되었다. 이 never called라는 메시지가 정말 반가웠다 ㅡ.ㅜ
해당 글의 쓰레드를 조금 추적해서 들어가면 inputattach.c 소스를 구할 수 있고(http://linuxconsole.cvs.sourceforge.net/viewvc/*checkout*/linuxconsole/ruby/utils/inputattach.c), 이 프로그램에 새로운 시리얼 디바이스의 속성을 지정하고, 실행하면 해당 시리얼 디바이스 드라이버와 연결된다는 것을 알게 되었다.
inputattach를 실제 실행하면, 키보드 입력을 받게 되어 있어서 어떻게 사용하는지 조금 난해했었다.

kernel/Documentation/input/joystick.txt 문서에서 inputattach -xxx /dev/tts/X & 를 보고, 이렇게 하니 잘 되었다;;

May 30 09:55:29 mola_server uv_mtd_init
May 30 09:55:59 mola_server serio: Serial port ttyS0
May 30 09:55:59 mola_server uv_mtd_connect
May 30 09:55:59 mola_server uv_mtd ttyS0/serio0/input0
May 30 09:55:59 mola_server input: UV Serial Multi-TouchScreen as /class/input/input13
May 30 09:56:12 mola_server uv_mtd_interrupt
May 30 09:56:12 mola_server uv_mtd unknown/unsynchronized data from device, byte 53
May 30 09:56:12 mola_server uv_mtd_interrupt
May 30 09:56:12 mola_server uv_mtd unknown/unsynchronized data from device, byte 63
May 30 09:56:12 mola_server uv_mtd_interrupt
May 30 09:56:12 mola_server uv_mtd unknown/unsynchronized data from device, byte 72



위 메시지는 커널의 메시지이며, insmod uv_mtd.ko를 하고 ./inputattach --uv_mtd /dev/ttyS0 & 를 한 후, 시리얼을 통해 데이터를 보낸 상태이다. 아직 인터럽트에서 제대로 처리를 하지 않아 위 메시지가 나왔지만, 인터럽트 내에 제대로 진입한 것을 볼 수 있다.;;

p.s.#1 이거 안되면 드라이버단에서 sys_open( /dev/ttyS0 )을 해서 처리하려고 했었다..
         장치에서 값이 들어오든 안들어오든 무조건 blocking된 상태에서 말이다.;;; 그래도 다행이다. 드라이버 단에서 되서~
p.s.#2 앞으로는 이벤트 드라이버와 연결해서 시리얼에서 온 데이터를 이벤트화 하면 된다.
         (이벤트 드라이버는 이미 테스트 종료 상태 ^^;;)

Posted by wbhacker :
포인터만 두개였지, 포커스는 하나만 되었었다. 아마도 윈도 매니저에서 지원을 하지 않았나보다. (bhbuild를 할 경우) 기본적으로 twm을 띄우게 된다. 앞서 포스팅 했던 글이 twm 기반이다.

어렴풋이 mpwm을 혹시 몰라 받았던 기억이 났다. mpx 공식 홈페이지(http://wearables.unisa.edu.au/mpx/)에서 좀 뒤적거리면 mpwm의 git 주소를 찾을 수 있을 것이다.



설치 순서는 아래와 같다. (이미 mpx가 설치되어 있다고 가정한다)

# git clone git://people.freedesktop.org/~whot/mpwm - mpwm의 다운로드
# cd mpwm
# ./autogen.sh --prefix=/root/xorg-test - 나는 /root/xorg에 mpx 지원하는 x-server를 설치했었는데, 혹시나 방해가 될까봐서 -test를 붙였다.
# vim src/Makefile
INCLUDES = -I/root/xorg/include <- 기존내용 앞에 쓴다.
LDFLAGS = -L/root/xorg/lib <- 값이 비어있을 것이다. 채워적으면 된다.

# make && make install

# ls -l /root/xorg-test/bin
total 1076
-rwxr-xr-x 1 root root 1095270 Apr 30 02:59 mpwm

그러면 /root/xorg-test/bin 에 mpwm이 설치된 것을 볼 수 있다.

/root/xorg/bin/startx 를 살펴보면, /root/xorg/lib/X11/xinit/xinitrc 파일을 참조하는 것을 볼 수 있는데, 이 파일을 열어서 twm 호출부분을 수정하면 된다.

# vim /root/xorg/lib/X11/xinit/xinitrc
#twm &
/root/xorg-test/bin/mpwm &

# startx
 
mpwm을 윈도 매니저로 사용하는 x-window가 띄워진 상태에서도 마찬가지로 xinput으로 설정해주어야 두개의 포인터, 두개의 포커스를 사용할 수 있다.

# xinput --create-master "foobar"
# xinput --reattach "Mouse1" "foobar pointer"

실제 동영상 처럼, 두개의 포커스를 처리할 수 있는 app를 따로 제작해야 그림판 같은 시연이 가능할 것으로 보인다.
Posted by wbhacker :
원래 이건데 ㅡ.ㅜ; 왜 나는 동시에 이벤트가 안먹지. gimp에서는 원래 안되는 것인가??



 얼른 xf86 용이든, 커널용이든 드라이버를 제작해야하는데, 어디서부터 손을 대야하는지 원...
Posted by wbhacker :

MPX 설치 완료 +_+

2009. 4. 29. 05:17 from 컴퓨터/Linux
멀티터치스크린 디바이스 드라이버 제작한다고 선언(?)한 후, 꼬박 한달여 기간이 지났다.

드라이버의 테스트를 위해선 X-window 내에서 두개의 포인터가 필요했다. 그래야 동시에 두좌표 이상이 되는지 확인할 수 있기 때문이다.;; 너무나 당연하다.

검색을 해보니, 새로운 윈도우 버전에서나 볼 수 있는 두개의 포인터 기술이 리눅스에선 이미 있었다.(역시!)
MPX(Multi-Pointer X server)라는 기술인데, Peter Hutterer라는 X input hacker가 개발한 것이 있었다.
그리고, 데모 동영상도 꽤 있었다. 하지만, 실제 구현하는 순서 같은 것은 거의 없었다 ㅡ.ㅡ^

최신 버전의 X-window를 설치하느라 꽤 삽질을 했었다. git, tar, jhbuild, deb 파일, apt-get, emerge 등....
결국은 jhbuild에서도 컴파일 에러를 수정해가면서 되게 했다.



위 동영상과 같이 두 개의 USB 마우스에서 두 개의 포인터는 나오게 했지만, 결국 두 개의 이벤트를 동시에 보여주는 프로그램이 없는 관계로 이정도로... 위 과정이 되기에도 꽤 많은 삽질이 있어서 아래에 기록해본다.

- http://www.x.org/wiki/JhBuildInstructions 페이지를 참고하여 jhbuild를 이용해서 빌드를 시작했다.
   # jhbuild -f modular-jhbuildrc build xserver xf86-video-nv xf86-input-keyboard
                                xf86-input-mouse
xorg-drivers xorg-libs xorg-apps

- 컴파일 과정에서 xf86Version.h 파일이 없다는 메시지가 자주 나와서, 그냥 /usr/include/xorg/xf86Version.h으로 지정해버렸다. 같은 디렉토리에 있는 어떤 파일들도 잘 참조가 되지 않아, 어찌어찌 통과하는 방향으로 했다. 중간에 asm/@!@!@.h 파일은 그냥 무시하고,..

- 기본 디렉토리(prefix)는 /root/xorg로 잡혀있으며, 해당 디렉토리/bin 에 startx 가 있는지 확인해야 하며, 없으면 다시 컴파일 시도한다.;;

- xorg.conf 파일의 작성... 여기서 실제로 많이 막혔다. 그래서 다시 컴파일하여 mouse와 keyboard 드라이버를 재로딩했다.

Section "ServerLayout"
        Identifier     "X.org Configured"
        Screen      0  "Screen0" 0 0
        #InputDevice    "Mouse0" "CorePointer"
        InputDevice    "Mouse0" "SendCoreEvents"
        InputDevice    "Mouse1" "SendCoreEvents"
        InputDevice    "Keyboard0" "CoreKeyboard"
        #InputDevice    "Keyboard0" "SendCoreEvents"
        Option         "AllowEmptyInput" "off"
        Option         "AutoAddDevices" "off"
EndSection

Section "Files"
        ModulePath   "/root/xorg/lib/xorg/modules"
        FontPath     "/usr/share/fonts/misc/"
        FontPath     "/usr/share/fonts/TTF/"
        FontPath     "/usr/share/fonts/OTF"
        FontPath     "/usr/share/fonts/Type1/"
        FontPath     "/usr/share/fonts/100dpi/"
        FontPath     "/usr/share/fonts/75dpi/"
EndSection

Section "Module"
        Load  "dbe"
        Load  "dri"
        Load  "record"
        Load  "extmod"
        Load  "xtrap"
        Load  "glx"
EndSection

Section "InputDevice"
        Identifier  "Keyboard0"
        Driver      "kbd"
        Option      "XkbRules" "xorg"
        Option      "XkbModel" "pc105"
        Option      "XkbLayout" "us"
EndSection

Section "InputDevice"
        Identifier  "Mouse0"
        Driver      "mouse"
        #Option     "Protocol" "PS/2"
        Option      "Protocol" "auto"
        #Option     "Protocol" "ExplorerPS/2"
        #Option     "Protocol" "IMPS/2"
        Option      "Device" "/dev/input/mouse1"
        #Option     "Device" "/dev/input/mice"
        #Option      "Device" "/dev/input/by-path/pci-0000:00:1d.0-usb-0:1:1.0-e
vent-mouse"
        #Option      "Device" "/dev/input/event2"

        Option      "ZAxisMapping" "4 5"
        #Option     "ZAxisMapping" "4 5 6 7"
        #Option      "Emulate3Buttons" "no"
EndSection

Section "InputDevice"
        Identifier  "Mouse1"
        Driver      "mouse"
        Option      "Protocol" "auto"
        #Option     "Protocol" "ExplorerPS/2"
        Option      "Device" "/dev/input/mouse2"
        Option      "ZAxisMapping" "4 5"
EndSection

Section "Monitor"
        #DisplaySize      380   300     # mm
        Identifier   "Monitor0"
        VendorName   "SAM"
        ModelName    "SyncMaster"
        HorizSync    30.0 - 81.0
        VertRefresh  56.0 - 75.0
        Option      "DPMS"
EndSection

Section "Device"
        ### Available Driver options are:-
        ### Values: <i>: integer, <f>: float, <bool>: "True"/"False",
        ### <string>: "String", <freq>: "<f> Hz/kHz/MHz"
        ### [arg]: arg optional
        #Option     "SWcursor"                  # [<bool>]
        #Option     "HWcursor"                  # [<bool>]
        #Option     "NoAccel"                   # [<bool>]
        #Option     "ShadowFB"                  # [<bool>]
        #Option     "UseFBDev"                  # [<bool>]
        #Option     "Rotate"                    # [<str>]
        #Option     "VideoKey"                  # <i>
        #Option     "FlatPanel"                 # [<bool>]
        #Option     "FPDither"                  # [<bool>]
        #Option     "CrtcNumber"                # <i>
        #Option     "FPScale"                   # [<bool>]
        #Option     "FPTweak"                   # <i>
        #Option     "DualHead"                  # [<bool>]
        #Option     "ShadowFB"                  # [<bool>]
        #Option     "UseFBDev"                  # [<bool>]
        #Option     "Rotate"                    # [<str>]
        #Option     "VideoKey"                  # <i>
        #Option     "FlatPanel"                 # [<bool>]
        #Option     "FPDither"                  # [<bool>]
        #Option     "CrtcNumber"                # <i>
        #Option     "FPScale"                   # [<bool>]
        #Option     "FPTweak"                   # <i>
        #Option     "DualHead"                  # [<bool>]
        Identifier  "Card0"
        Driver      "nv"
        VendorName  "nVidia Corporation"
        BoardName   "NV18 [GeForce4 MX 440 AGP 8x]"
        BusID       "PCI:1:0:0"
EndSection

Section "Screen"
        Identifier "Screen0"
        Device     "Card0"
        Monitor    "Monitor0"
        SubSection "Display"
                Viewport   0 0
                Depth     1
        EndSubSection
        SubSection "Display"
                Viewport   0 0
                Depth     4
        EndSubSection
        SubSection "Display"
                Viewport   0 0
                Depth     8
        EndSubSection
        SubSection "Display"
                Viewport   0 0
                Depth     15
        EndSubSection
        SubSection "Display"
                Viewport   0 0
                Depth     16
        EndSubSection
        SubSection "Display"
                Viewport   0 0
                Depth     24
        EndSubSection
EndSection


위에 살펴보면 알겠지만,
 1. Option "AllowEmptyInput" "off" 이 없으면 시작할 때 에러가 발생했다. (최신 버전에만 그러는 듯)
 2. ModulePath "/root/xorg/lib/xorg/modules" 도 꽤나 중요하다.
     나는 /root/xorg에 설치했기 때문에, 모든 모듈들이 해당 디렉토리 내에 존재했었다.
 3. InputDevice "Mouse0" "SendCoreEvents" 는 마우스 두개가 될 경우, 이벤트를 따로 발생하라는 의미이다.
     원래 하나의 포인터로 사용할 때에는 "CorePointer" 값이다.

- 위 설정대로 x-window가 실행되는지 해봐야 한다. (/root/xorg/bin 내에 있는 startx 나 xinit가 실행되도록 유도해야 한다.)
  # export PATH=/root/xorg/bin:$PATH
  # export LD_LIBRARY_PATH=/root/xorg/lib
  # startx -- -verbose 6

- 나오는 메시지를 잘 살펴보고, 에러가 있으면 나름대로 해결해야 한다. 나에게는 xcb 관련 에러가 발생했는데, 이미 gentoo 패키지 시스템인 emerge를 이용해서 x-window를 /usr에 설치된 상황이기 때문에 이곳에 있는 xcb 자료를 복사해서 사용했다.
  # cp -ap /usr/share/X11/xkb/* /root/xorg/share/X11/xkb/

- 마우스 관련 에러도 많이 나왔었다. 이것은 실제로 /dev/input/mouse1에 접근해보는 것으로 실제 동작하는 지 알 수 있다.
  # cat /dev/input/mouse1  (실행한 상태에서 마우스를 움직이거나 클릭해본 후, 이상한 쓰레기 값이 나오면 동작하는 것이다)
   물론, 두번째 마우스는 /dev/input/mouse2 가 될 것이다. 여기서 동작하는 값으로 xorg.conf 에 설정해주어야 하는 것은 당연하다.
   (원래 보통 /dev/input/mice로 되어 있을 것이다.)

- 이제 에러를 해결했으면, x-window가 정상적으로 뜰 것이다. 아직 포인터가 하나 뿐일 것이다.
   xinput를 통해 설정을 해주어야 하기 때문이다. (x-window 내 xterm이 띄워져 있을 것이다. 그 안에서 실행해야 한다.)
  # xinput --list --short
  "Virtual core pointer"  id=0    [XPointer]
  "Virtual core keyboard" id=1    [XKeyboard]
  "Virtual core Xtst pointer"     id=2    [XExtensionPointer]
  "Virtual core Xtst keyboard"    id=3    [XExtensionKeyboard]
  "Mouse0"        id=4    [XExtensionPointer]
  "Mouse1"        id=5    [XExtensionPointer]
  "Keyboard0"     id=6    [XExtensionKeyboard]
  "Mouse0"        id=7    [XExtensionPointer]
  # xinput --create-master "foobar"
  # xinput --reattach "Mouse1" "foobar pointer"
    (foobar pointer로 방향을 바꾸는 것으로 따로 동작이 가능해진다)

- 아래와 같이 포인터 두 개가 나오면 성공한 것이다.

포인터 두개 모습

I 포인터 두개의 모습



포인터 두개 모습

X 포인터 두개의 모습



동작이 제대로 되는지 확인하기 위해 나는 emerge gimp로 gimp를 설치하였다. 하지만, 아직, 한 쪽 마우스가 클릭한 상태에서 다른 마우스 클릭이 제대로 먹히지 않는데, 아마도 /dev/input/mice와 같이 중첩사용되는 장치 이벤트만 처리하나 보다. 아직 모르겠다.

- 마지막으로 이 xinput를 개발한 사람 블로그(?)에 샘플 소스가 있어서 컴파일을 해보았다.
  * 사이트 : http://wearables.unisa.edu.au/mpx/?q=xi2_sample
  # gcc -o xi2_sample xi2_sample.c `pkg-config --cflags --libs xi`
    -I/root/xorg/include -L/root/xorg/lib


참고 사이트 정보 :
1. http://live.gnome.org/Metacity/MpxHowto - How to install MPX and Metacity
2. http://wearables.unisa.edu.au/mpx/ - MPX 공식 홈페이지
3. http://www.x.org/wiki/JhBuildInstructions - JhBuildInstructions 설치방법

p.s. 이젠 멀티터치 디바이스 드라이버를 제작하기만 하면 된다 ㅡ.ㅜ
Posted by wbhacker :