BY: cashimor DATE: 2004-Apr-23 06:25 SUBJECT: SPS2 keyboard inputFor the past week I have been trying to get keyboard input under SPS2. Unfortunately STDIN_FILENO is not working as an fd and anything typed does not go to this. I tried various approaches, and eventually digged into sps2util.c and discovered that it opens a new virtual terminal, to avoid disrupting the existing virtual terminals. It stores the terminal fd in mscr_tty_fd. Talking with Sauce, it seems that this is the fd to use. As the sps2util library is in C, you can get this fd easily by putting:
extern int mscr_tty_fd;
in front of your program. If you want to make your code proper, you can then clone your own fd from this by doing:
fd = fcntl(mscr_tty_fd, F_DUPFD, 0);
but you can of course also happily use the original fd. I tested it, and keys typed indeed do go to this terminal.
Now for the next bit, which is not related to SPS2, but might still be useful to some people.
Obviously, under SPS2 you don't want to do a blocking read() on this fd, because then your fps would be gone. You might just want to make the fd unblocking:
ret = fcntl(fd, F_SETFL, O_NONBLOCK);
But as there is a virtual terminal around it, you would only get response to the read() after the user hits the Enter key. You could solve this by making the terminal raw (stty raw) but this would cause CTRL-C to cease working, making it more difficult for you to stop your application.
A solution is to change the terminal settings only for the duration that you get a key. Here is some sample code:
#include <termio.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
int getch() {
char ch;
int error;
static struct termios old,new;
tcgetattr(keyfd,&old);
new=old;
new.c_iflag=0;
new.c_oflag=0;
new.c_lflag&=~ICANON;
new.c_lflag&=~ECHO;
new.c_cc[VMIN]=0;
new.c_cc[VTIME]=0;
tcsetattr(keyfd,TCSANOW,&new);
error=read(keyfd,&ch,1);
tcsetattr(keyfd,TCSANOW,&old);
if(error!=1) return -1;
return ch;
}
I hope this helps people. |