Se você estiver lendo em stdin , leia a manpage de tcsetattr e, especificamente, a seção sobre "Modo canônico e não canônico" ( ICANON ). A menos que você desative ICANON on stdin , a entrada é orientada por linha (você não obtém nada até que Enter seja pressionado). Esse é o caso mesmo para O_NONBLOCK .
Em caso de dúvida, strace -v stty raw >&log; stty sane; grep TCSETSW log e veja o que acontece com stdin . Você pode usar a mesma chamada de sistema com parâmetros idênticos para desbloquear o terminal. Tenha cuidado, a menos que você restaure as configurações na saída, o terminal será inútil após o término do seu programa. (é por isso que eu fiz stty sane após stty raw )
O uso de hardware bruto de E / S é provavelmente uma idéia muito muito ruim, a menos que você esteja absolutamente certo sobre o hardware de destino e / ou deseje antecipar cada tipo de teclado existe.
Ah, apesar de ser "cru", você ainda está lendo alguma informação do teclado: você não obterá scancodes, você obterá ASCII (ou UTF-8, provavelmente). Então Escape é decimal 27, não 1 (como no teclado IBM PC original).
Sugestão alternativa que requer acesso de superusuário: leia os dispositivos de evento, abra o caminho certo e leia as estruturas de evento do Linux a partir dele. Este método retorna eventos e press raw key / key (eles são os códigos de chave internos do kernel, não scancodes de hardware). Confira /usr/include/linux/input.h para os detalhes. Encontrar o dispositivo eventX correto para abrir em 256 bytes de código é outra coisa, claro.