tslib 터치스크린 라이브러리 심층 분석 및 멀티터치 거리 계산 구현

tslib 프레임워크 구조

tslib은 터치스크린 입력 데이터를 처리하기 위한 라이브러리로, 모듈 기반의 파이프라인 구조를 사용합니다. 각 모듈은 데이터를 가공하거나 필터링하는 역할을 담당합니다.

핵심 데이터 구조: tsdev

struct tsdev {
    struct tslib_module_info *list;      // 처리 모듈 연결 리스트
    struct tslib_module_info *list_raw;  // 원시 데이터 모듈 (변경되지 않음)
    // ... 기타 필드
};

설정 파일 처리 방식

ts.conf 파일의 각 라인은 순차적으로 읽혀지며, ts_setup() 호출 시 내부에서 linked list로 변환됩니다. 각 모듈은 info->dev 필드를 통해 자신이 속한 장치 정보를 참조할 수 있습니다.

모듈 연결 과정 (head insertion 방식):

  1. 첫 번째 input 모듈 추가: module_raw 타입이므로 __ts_attach_raw() 호출. ts->list가 NULL일 경우, 이 모듈이 ts->listts->list_raw 모두에 설정됩니다.
  2. 두 번째 pthres pmin=1 모듈 추가: __ts_attach() 호출. 새 모듈이 ts->list의 헤드가 되고, 기존 ts->list는 다음 노드로 연결됩니다.

이 방식으로 모든 모듈이 연결되며, ts->list_raw는 항상 첫 번째 module_raw 모듈을 가리킵니다.

크로스 컴파일 설정

크로스 컴파일러를 사용하여 tslib을 타겟 플랫폼용으로 빌드할 수 있습니다. 일반적으로 configure 스크립트에 --host 옵션으로 타겟 아키텍처를 지정합니다.

./configure --host=arm-linux-gnueabihf --prefix=/usr/local/tslib
make
make install

실전 예제: 두 터치 포인트 간 유클리드 거리 계산

구현 단계

  1. 장치 초기화
    ts_setup(NULL, 0)을 호출하여 자동으로 터치스크린 장치를 찾고 연결합니다. 두 번째 인자는 블로킹 모드를 제어하며, 0은 블로킹(데이터가 없으면 대기), 1은 논블로킹(즉시 반환)을 의미합니다.
  2. 멀티터치 지원 확인
    ioctl(ts_fd(ts), EVIOCGABS(ABS_MT_SLOT), &slot)으로 장치의 절대 축 정보를 얻습니다. slot.maximumslot.minimum을 통해 최대 지원 터치 포인트 수를 계산합니다:
    max_slots = slot.maximum + 1 - slot.minimum;
    
  3. 데이터 버퍼 준비
    struct ts_sample_mt **samp_mt는 이차원 포인터로, 두 개의 버퍼를 관리합니다:
    • samp_mt[0]: 이전 프레임의 터치 데이터
    • samp_mt[1]: 현재 프레임의 터치 데이터
    각 버퍼는 calloc을 통해 max_slots 개의 struct ts_sample_mt 구조체를 저장할 공간을 할당받습니다.
  4. 데이터 읽기 및 거리 계산
    ts_read_mt(ts, &samp_mt[1], max_slots, 1)로 현재 터치 데이터를 읽고, valid 필드가 1인 활성 포인트를 식별합니다. 두 개의 활성 포인트가 발견되면 유클리드 거리를 계산합니다.

전체 코드

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <linux/input.h>
#include <sys/ioctl.h>
#include <tslib.h>

int max_slots;
struct ts_sample_mt **samp_mt;

int compute_distance(struct ts_sample_mt *points)
{
    int active_indices[2] = {0};
    int count = 0;
    
    for (int i = 0; i < max_slots; i++) {
        if (points[i].valid == 1 && points[i].tracking_id != -1) {
            if (count < 2)
                active_indices[count++] = i;
        }
    }
    
    int dx = points[active_indices[1]].x - points[active_indices[0]].x;
    int dy = points[active_indices[1]].y - points[active_indices[0]].y;
    return dx * dx + dy * dy;
}

int main(int argc, char *argv[])
{
    struct tsdev *ts;
    struct input_absinfo slot;
    int ret;
    int active_count = 0;
    int touch_ids[20];
    
    ts = ts_setup(NULL, 0);
    if (!ts) {
        fprintf(stderr, "ts_setup failed\n");
        return -1;
    }
    
    if (ioctl(ts_fd(ts), EVIOCGABS(ABS_MT_SLOT), &slot) < 0) {
        perror("ioctl EVIOCGABS");
        ts_close(ts);
        return errno;
    }
    
    max_slots = slot.maximum + 1 - slot.minimum;
    
    samp_mt = malloc(sizeof(struct ts_sample_mt *));
    samp_mt[0] = calloc(max_slots, sizeof(struct ts_sample_mt));
    if (!samp_mt || !samp_mt[0]) {
        ts_close(ts);
        return -ENOMEM;
    }
    
    samp_mt = realloc(samp_mt, 2 * sizeof(struct ts_sample_mt *));
    samp_mt[1] = calloc(max_slots, sizeof(struct ts_sample_mt));
    if (!samp_mt[1]) {
        free(samp_mt[0]);
        free(samp_mt);
        ts_close(ts);
        return -ENOMEM;
    }
    
    for (int i = 0; i < max_slots; i++)
        samp_mt[0][i].valid = 0;
    
    while (1) {
        ret = ts_read_mt(ts, &samp_mt[1], max_slots, 1);
        if (ret < 0) {
            fprintf(stderr, "ts_read_mt error\n");
            break;
        }
        
        memcpy(samp_mt[0], samp_mt[1], max_slots * sizeof(struct ts_sample_mt));
        
        active_count = 0;
        for (int i = 0; i < max_slots; i++) {
            if (samp_mt[0][i].valid == 1 && samp_mt[0][i].tracking_id != -1)
                touch_ids[active_count++] = i;
        }
        
        if (active_count == 2) {
            int dist = compute_distance(samp_mt[0]);
            printf("Distance squared: %08d\n", dist);
        }
        
        usleep(10000); // 10ms delay
    }
    
    free(samp_mt[0]);
    free(samp_mt[1]);
    free(samp_mt);
    ts_close(ts);
    return 0;
}

태그: tslib 터치스크린 linux 멀티터치 임베디드시스템

6월 27일 21:27에 게시됨