2013-04-11 2 views
3

У меня есть USB-считыватель карт RFID, который эмулирует клавиатуру. Итак, когда я кладу карту, я вижу строку в терминальном окне -i.e. "0684a24bc1"Чтение с/dev/input

Но я хотел бы прочитать его в моей программе на C. Нет проблем при использовании: scanf("%s",buff);

Но когда я использую код ниже, я получил много (около 500 байт) не распознанных данных. Почему? Я хотел бы иметь неблокирующее чтение.

#include <stdio.h> 
#include <string.h> 
#include <unistd.h> 
#include <fcntl.h> 
#include <errno.h> 
#include <termios.h> 

int main(int argc, char ** argv) { 
    int fd; 
    char buf[256]; 

    fd = open("/dev/input/event3", O_RDWR | O_NOCTTY | O_NDELAY); 
    if (fd == -1) { 
    perror("open_port: Unable to open /dev/ttyAMA0 - "); 
    return(-1); 
    } 

    // Turn off blocking for reads, use (fd, F_SETFL, FNDELAY) if you want that 
    fcntl(fd, F_SETFL, 0); 


    } 

while(1){ 
    n = read(fd, (void*)buf, 255); 
    if (n < 0) { 
    perror("Read failed - "); 
    return -1; 
    } else if (n == 0) printf("No data on port\n"); 
    else { 
    buf[n] = '\0'; 
    printf("%i bytes read : %s", n, buf); 
    } 
sleep(1); 
printf("i'm still doing something"); 

} 
    close(fd); 
    return 0; 
} 
+0

Разве вы не устанавливаете флаг 'O_NONBLOCK', чтобы сделать дескриптор неблокирующим? –

+0

Кроме того, при чтении непосредственно с устройства вы читаете данные _raw_ до того, как они преобразуются в символы, которые вы можете читать с терминала. –

+0

Я просто хочу добавить, что это отвратительная реализация драйвера RFID. он должен быть реализован как символьное устройство. – stdcall

ответ

8

В соответствии с Linux input documentation, разделом 5,/DEV/вход/eventX устройство возвращает данные следующим образом:

Вы можете использовать блокирование и неблокирующее чтение, также выбрать() на /dev/input/eventX, и вы всегда получите целое число событий ввода при чтении. Их планировка:

struct input_event { 
     struct timeval time; 
     unsigned short type; 
     unsigned short code; 
     unsigned int value; }; 

«время» является отметкой о времени, она возвращает время, когда событие произошло . Тип - например EV_REL для относительного момента, EV_KEY для нажатия клавиши . Дополнительные типы определены в include/linux/input.h.

«код» - это код события, например REL_X или KEY_BACKSPACE, снова полный список находится в include/linux/input.h.

«значение» - это значение, которое несет событие. Либо относительное изменение для EV_REL, абсолютное новое значение для EV_ABS (джойстики ...), либо 0 для EV_KEY для выпуска, 1 для нажатия клавиш и 2 для автоповтора.

0

Ваш код явно ошибочен при открытии устройства событий под номером /dev/input/. Даже ваше сообщение об ошибке противоречит выбору:

perror("open_port: Unable to open /dev/ttyAMA0 - "); 

Считывает из /dev/input/eventN файлов возврат двоичных данных с описаниями событий (например, указатель движения или нажатия кнопок), а не текст. Возможно, вы захотите открыть какое-то устройство последовательной эмуляции.

+1

Судя по названию, он действительно хочет читать что-то под '/ dev/input', а не'/dev/ttyAMA0'. Сообщение об ошибке неверно. – Hasturkun