2015年1月5日 星期一

ioctl command EVIOCGRAB of linux input layer.

     最近這一週都在處理有關 Linux input 問題,詳細就不說了,主要這次對 /dev/input/eventX 做了稍微詳細的測試一下.

     有關取 key 的方式就是open & read ,這也是一般方式,問題是open 兩次得到兩個handle id 分別對這兩個去讀取會得到啥呢?一個按鍵的值會給哪一個呢? 結果是兩者都會收到 , 並且先 open 先收到 , 這樣說可能不是很清楚 , 舉個例子說明吧. 
    先利用  open  開啟 input device , 並且不要關閉(close) ,然後輸入 A,B,C,D & E , 接著再open input device 一次 , 然後 輸入 F,G,H,U,J & K , 接著讀取兩個 handle file ID . 第一個 open 的會讀取到 A,B,C,D,E,F,G,H,I,J & K  , 第二次 open 的會讀取到 F,G,H,I,J & K . 這樣應該了解我說的先 open 先讀到的意思了吧 !  想一想, 這樣的邏輯也對 , open 一次就是新的一個 file , 之前已經過去的 key ( open 之前) 當然收不到 . 
  
    問題又來了 , 這樣會導致兩個 task 都收到 key , 這樣的情況下 ,  我能只限定某個 task 收到 , 另外一個不要收到嗎 ?? 這就是今天的主題了.

    可以利用今天說的主題 EVIOCGRAB ioctl command 來進行這樣的控制 , 對於想要 "獨佔" 的 device file 下 EVIOCGRAB command , 就可以確保只有它收到 , 其它有 open 的 device 不會收到. 如果兩者都下 EVIOCGRAB command , 就看誰先了, 先的就 "獨占" .

    下面就是我測試的  sample code (部份), 會發現只有第二次 open 的會讀到輸入值.

    devfd_1 = open(key_dev, O_RDONLY | O_NONBLOCK);
    devfd = open(key_dev, O_RDONLY | O_NONBLOCK);

    ioctl(devfd, EVIOCGRAB,1);
    ioctl(devfd_1, EVIOCGRAB,1);

    for ( i = 0 ; i < 20 ; i ++ )
    {
        readlen = read(devfd,&inputdata,sizeof(struct input_event));
        if ( readlen == sizeof(struct input_event)  && (inputdata.type == EV_KEY) )
        {
            printf("Keypad code:%d",inputdata.code);

            if (inputdata.value == 1)
                printf(" Down!\n");
            else if (inputdata.value == 0)
               printf(" Up!\n");
            else if (inputdata.value == 2 )
                printf(" PRESSED !\n");
           
        }

        readlen = read(devfd_1,&inputdata,sizeof(struct input_event));
        if ( readlen == sizeof(struct input_event)  && (inputdata.type == EV_KEY) )
        {
            printf("2 Keypad code:%d",inputdata.code);
            if (inputdata.value == 1)
                printf(" Down!\n");
            else if (inputdata.value == 0)
                printf(" Up!\n");
            else if (inputdata.value == 2 )
                printf(" PRESSED !\n");
         }

    }

    close(devfd);
    close(devfd_1);