--- kbd.c 2005-01-02 23:20:06.717348720 +1300 +++ kbd.c 2005-01-03 00:38:28.629549416 +1300 @@ -21,12 +21,15 @@ #include #include #include +#include #include #include #include #include #include #include +#include +#include #include "keyboards.h" #include "dev_uinput.h" @@ -37,6 +40,7 @@ char debug=0; int uindev=0; +static int reinit=0; char TTY_PORT[PATH_MAX]; int open_serial(char *port, speed_t baud) @@ -122,6 +126,160 @@ return 0; } +int select_read(int fd, int timeout_sec, int timeout_us) { + fd_set fds; + struct timeval tv; + + FD_ZERO(&fds); + FD_SET(fd, &fds); + tv.tv_sec = timeout_sec; + tv.tv_usec = timeout_us; + return select(fd+1, &fds, NULL, NULL, &tv); +} + +int stowaway_init(int fd) +{ +int status; +unsigned char buf[16]; + + ioctl(fd, TIOCMGET, &status); + status |= TIOCM_DTR; /* Set DTR */ + status &= ~TIOCM_RTS; /* Clear RTS */ + ioctl(fd, TIOCMSET, &status); + + /* Unfortunately, DCD seems to be high all of the time on H3900, so the following can't be used */ + /* ioctl(fd, TIOCMIWAIT, TIOCM_CAR */ + /* So we just wait instead */ + usleep(1000000); + + ioctl(fd, TIOCMGET, &status); + status |= TIOCM_RTS; /* Set RTS */ + ioctl(fd, TIOCMSET, &status); + /* Stowaway will send back 0xFA 0xFD indicating successful init */ + if(select_read(fd, 2, 0)) { + read(fd, buf, 2); + if((buf[0] = 0xFA) && (buf[0] = 0xFD)) + if (debug) fprintf(stderr, "keyboard initialised\n"); + } + + return 0; +} + +int open_apm(void) { + int fd; + + fd = open( "/dev/apm_bios", O_RDONLY | O_NONBLOCK ); + if(fd <= 0) + return -1; + + return fd; +} + +int check_apm_resume(int fd) { + apm_event_t ev; + int resumed; + + resumed = 0; + while(read(fd, &ev, sizeof(apm_event_t)) > 0) { + if(ev == APM_NORMAL_RESUME) + resumed = 1; + } + return resumed; +} + +void stowaway_sig(int sig) { + reinit = 1; +} + +int stowaway(void) +{ +int fd, apm_fd; +unsigned char buf[16]; +char fn=0; +struct sigaction act; +int rc; + + fd = open_serial(TTY_PORT, B9600); + if (fd <= 0) + return (-1); + + /* Make SIGHUP cause a reinit of the keyboard */ + act.sa_handler = stowaway_sig; + sigemptyset(&act.sa_mask); + act.sa_flags = 0; + sigaction(SIGHUP, &act, NULL); + + /* Open APM so we can listen for resume events */ + apm_fd = open_apm(); + + while (fd > 0) { + + stowaway_init(fd); + + while (fd > 0) { + rc = select_read(fd, 0, 100000); + if(rc == -1) { + if(reinit) { + reinit = 0; + break; + } + else { + perror("select"); + return 1; + } + } + else if(rc == 0) { + /* Timeout expired with nothing read, do APM resume check */ + if((apm_fd > 0) && (check_apm_resume(apm_fd))) + break; + continue; + } + + rc = read (fd, buf, 1); + if(rc == -1) { + if(reinit) { + reinit = 0; + break; + } + else { + perror("read"); + return 1; + } + } + + if ( ((unsigned char)buf[0] & (unsigned char)0x80) == 0 ) { + if (debug) fprintf(stderr, "press: %d\n", buf[0]); + if (buf[0] == 0x08) { + fn=1; + continue; + } + if (fn) + buf[0]=stowaway_function[buf[0]]; + else + buf[0]=stowaway_normal[buf[0]]; + if (debug) fprintf(stderr,"= 0x%02x\n", buf[0]); + if (buf[0] > 0) + dev_uinput_key(uindev, (unsigned short)buf[0], KEY_PRESSED); + } else { + if (debug) fprintf(stderr, "rel. : %d\n", buf[0] & ~0x80); + if ((buf[0] & ~0x80) == 0x08) { + fn = 0; + continue; + } + if (fn) + buf[0]=stowaway_function[(unsigned char)buf[0] & (unsigned char)~0x80]; + else + buf[0]=stowaway_normal[(unsigned char)buf[0] & (unsigned char)~0x80]; + if (debug) fprintf(stderr,"= 0x%02x\n", buf[0]); + if (buf[0] > 0) + dev_uinput_key(uindev, (unsigned short)buf[0], KEY_RELEASED); + } + } + } + +return 0; +} + int snapntype(void) { @@ -177,6 +335,7 @@ fprintf (stderr, "-t \n"); fprintf (stderr, "\tspecify the serial keyboard type, supported are:\n"); fprintf (stderr, "\tfoldable - Compaq/HP foldable keyboard\n"); + fprintf (stderr, "\tstowaway - Targus Stowaway keyboard\n"); fprintf (stderr, "\tsnapntype- Snap'n'Type\n\n"); fprintf (stderr, "Example:\n\t%s -t foldable\n", arg0); } @@ -184,6 +343,7 @@ #define KBD_TYPE_NONE 0 #define KBD_TYPE_FOLDABLE 1 #define KBD_TYPE_SNAPNTYPE 2 +#define KBD_TYPE_STOWAWAY 3 int main(int argc, char **argv) { @@ -204,7 +364,11 @@ kbdtype = KBD_TYPE_FOLDABLE; } else if (strncmp("snapntype", optarg, 9) == 0) { kbdtype = KBD_TYPE_SNAPNTYPE; + } else if (strncmp("stowaway", optarg, 8) == 0) { + kbdtype = KBD_TYPE_STOWAWAY; } + else + fprintf(stderr, "unrecognised keyboard type %s\n", optarg); break; case 'p': strcpy(TTY_PORT, optarg); @@ -226,6 +390,8 @@ compaq_foldable(); else if (kbdtype == KBD_TYPE_SNAPNTYPE) snapntype(); + else if (kbdtype == KBD_TYPE_STOWAWAY) + stowaway(); return 0; } --- keyboards.h 2005-01-02 23:20:20.240292920 +1300 +++ keyboards.h 2005-01-02 23:22:32.584173592 +1300 @@ -139,6 +139,51 @@ 108, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; +/*********************************************************************************** + * Targus Stowaway keyboard + * + * 9600 baud, 8N1 + * + * Initialisation: raise DTR and drop RTS, wait for DCD pulse, then raise RTS + * keyboard will then send back 0xFA 0xFD + * + * Key down sends one byte + * Key up sends one byte & 0x80, and if the key up is the last key up (ie, no more + * keys held down), then the key code & 0x80 is repeated + ***********************************************************************************/ + +static unsigned char stowaway_normal[128] = { + /* 0, 001, 002, 003, 004, 005, 006, 007, 008, 009 */ +/*000*/ 2, 3, 4, 44, 5, 6, 7, 8, 0, 16, +/*010*/ 17, 18, 19, 20, 21, 41, 45, 30, 31, 32, +/*020*/ 33, 34, 35, 57, 58, 15, 29, 0, 0, 0, +/*030*/ 0, 0, 0, 0, 0, 56, 0, 0, 0, 0, +/*040*/ 0, 0, 0, 0, 46, 47, 48, 49, 12, 13, +/*050*/ 14, 87, 9, 10, 11, 57, 26, 27, 43, 220, +/*060*/ 22, 23, 24, 25, 40, 28, 219, 0, 36, 37, +/*070*/ 38, 39, 53, 144, 183, 0, 50, 51, 52, 0, +/*080*/ 111, 146, 155, 151, 0, 0, 0, 0, 42, 54, +/*090*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/*100*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/*110*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/*120*/ 0, 0, 0, 0, 0, 0, 0, 0, }; + +static unsigned char stowaway_function[128] = { + /* 0, 001, 002, 003, 004, 005, 006, 007, 008, 009 */ +/*000*/ 59, 60, 61, 0, 62, 63, 64, 65, 0, 0, +/*010*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/*020*/ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, +/*030*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/*040*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/*050*/ 92, 0, 66, 67, 68, 0, 0, 0, 0, 0, +/*060*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/*070*/ 0, 0, 0, 104, 0, 0, 0, 0, 0, 0, +/*080*/ 0, 102, 109, 107, 0, 0, 0, 0, 0, 0, +/*090*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/*100*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/*110*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/*120*/ 0, 0, 0, 0, 0, 0, 0, 0, }; + /*********************************************************************************** * HP foldable keyboard