#include #include #include #include #include #include // XXX Linux botch #include #include extern const char *__progname; static int fd; static int state; static int downp; static int buttons; static int dx; static int dy; static int prevbuttons; static const int keys[] = { #define FOO(x) KEY_##x, #include "keys" #undef FOO }; /* * We want to initialize unused elements to -1. If we don't mention * them at all, C initializes them to 0. As it happens, no KEY_* is * zero, but we don't want to depend on that (though I am willing to * depend on none of them being -1...hmm, maybe I should fix that). * * But C does promise that, if we initialize a given element more than * once, the last value is the one that sticks. So we initialize the * whole array to -1, then (re)initialize the elements we want to be * other than -1. */ #define R4(n) n, n, n, n #define R16(n) R4(n), R4(n), R4(n), R4(n) #define R64(n) R16(n), R16(n), R16(n), R16(n) static const signed short int map_sun[128] = { [0] = R64(-1), R64(-1), [0x05] = KEY_F1, // F1 [0x06] = KEY_F2, // F2 [0x08] = KEY_F3, // F3 [0x0a] = KEY_F4, // F4 [0x0c] = KEY_F5, // F5 [0x0e] = KEY_F6, // F6 [0x10] = KEY_F7, // F7 [0x11] = KEY_F8, // F8 [0x12] = KEY_F9, // F9 [0x15] = KEY_F10, // R1 [0x16] = KEY_F11, // R2 [0x17] = KEY_F12, // R3 [0x1d] = KEY_ESC, // ESC [0x1e] = KEY_1, // 1! [0x1f] = KEY_2, // 2@ [0x20] = KEY_3, // 3# [0x21] = KEY_4, // 4$ [0x22] = KEY_5, // 5% [0x23] = KEY_6, // 6^ [0x24] = KEY_7, // 7& [0x25] = KEY_8, // 8* [0x26] = KEY_9, // 9( [0x27] = KEY_0, // 0) [0x28] = KEY_MINUS, // -_ [0x29] = KEY_EQUAL, // =+ [0x58] = KEY_BACKSLASH, // \| [0x2a] = KEY_GRAVE, // `~ [0x2b] = KEY_DELETE, // BackSpace [0x35] = KEY_TAB, // Tab [0x36] = KEY_Q, // Q [0x37] = KEY_W, // W [0x38] = KEY_E, // E [0x39] = KEY_R, // R [0x3a] = KEY_T, // T [0x3b] = KEY_Y, // Y [0x3c] = KEY_U, // U [0x3d] = KEY_I, // I [0x3e] = KEY_O, // O [0x3f] = KEY_P, // P [0x40] = KEY_LEFTBRACE, // [{ [0x41] = KEY_RIGHTBRACE, // ]} [0x45] = KEY_UP, // R8/up [0x4c] = KEY_LEFTCTRL, // Control [0x4d] = KEY_A, // A [0x4e] = KEY_S, // S [0x4f] = KEY_D, // D [0x50] = KEY_F, // F [0x51] = KEY_G, // G [0x52] = KEY_H, // H [0x53] = KEY_J, // J [0x54] = KEY_K, // K [0x55] = KEY_L, // L [0x56] = KEY_SEMICOLON, // ;: [0x57] = KEY_APOSTROPHE, // '" [0x59] = KEY_ENTER, // Return [0x5b] = KEY_LEFT, // R10/left [0x5d] = KEY_RIGHT, // R12/right [0x63] = KEY_LEFTSHIFT, // LShift [0x64] = KEY_Z, // Z [0x65] = KEY_X, // X [0x66] = KEY_C, // C [0x67] = KEY_V, // Vl [0x68] = KEY_B, // B [0x69] = KEY_N, // N [0x6a] = KEY_M, // M [0x6b] = KEY_COMMA, // ,< [0x6c] = KEY_DOT, // .> [0x6d] = KEY_SLASH, // /? [0x6e] = KEY_RIGHTSHIFT, // RShift [0x6f] = KEY_BACKSPACE, // LineFeed [0x71] = KEY_DOWN, // R14/down [0x79] = KEY_SPACE // space }; #undef R4 #undef R16 #undef R64 #include static void dlog(const char *, ...) __attribute__((__format__(__printf__,1,2))); static void dlog(const char *fmt, ...) { va_list ap; static int dfd = -1; static FILE *df; switch (dfd) { case -1: dfd = open("LOG.dbg",O_WRONLY|O_APPEND,0); if (dfd < 0) { dfd = -2; case -2: return; } df = fdopen(dfd,"a"); break; } va_start(ap,fmt); vfprintf(df,fmt,ap); va_end(ap); fflush(df); } static void setup(void) { struct uinput_setup setup; int i; fd = open("/dev/uinput",O_WRONLY|O_NONBLOCK,0); if (fd < 0) { fprintf(stderr,"%s: can't open /dev/uinput: %s\n",__progname,strerror(errno)); exit(1); } ioctl(fd,UI_SET_EVBIT,EV_KEY); ioctl(fd,UI_SET_KEYBIT,BTN_LEFT); ioctl(fd,UI_SET_KEYBIT,BTN_MIDDLE); ioctl(fd,UI_SET_KEYBIT,BTN_RIGHT); for (i=(sizeof(keys)/sizeof(keys[i]))-1;i>=0;i--) ioctl(fd,UI_SET_KEYBIT,keys[i]); ioctl(fd,UI_SET_EVBIT,EV_REL); ioctl(fd,UI_SET_RELBIT,REL_X); ioctl(fd,UI_SET_RELBIT,REL_Y); bzero(&setup,sizeof(setup)); setup.id.bustype = BUS_USB; setup.id.vendor = 0x0000; setup.id.product = 0x0000; strncpy(&setup.name[0],"None",sizeof(setup.name)); ioctl(fd,UI_DEV_SETUP,&setup); ioctl(fd,UI_DEV_CREATE); prevbuttons = 0; } static void gen(int type, int code, int val) { struct input_event ie; ie.type = type; ie.code = code; ie.value = val; ie.time.tv_sec = 0; ie.time.tv_usec = 0; write(fd,&ie,sizeof(ie)); } static void down(int key) { dlog("key %d down\n",key); gen(EV_KEY,key,1); gen(EV_SYN,SYN_REPORT,0); } static void up(int key) { dlog("key %d up\n",key); gen(EV_KEY,key,0); gen(EV_SYN,SYN_REPORT,0); } static void mouse_event(void) { int any; dlog("buttons %d->%d (%d,%d)\n",buttons,prevbuttons,dx,dy); any = 0; if (buttons != prevbuttons) { if ((buttons ^ prevbuttons) & 1) gen(EV_KEY,BTN_LEFT,(buttons&1)?1:0); if ((buttons ^ prevbuttons) & 2) gen(EV_KEY,BTN_MIDDLE,(buttons&2)?1:0); if ((buttons ^ prevbuttons) & 4) gen(EV_KEY,BTN_RIGHT,(buttons&4)?1:0); prevbuttons = buttons; any = 1; } if (dx) { gen(EV_REL,REL_X,dx); any = 1; } if (dy) { gen(EV_REL,REL_Y,dy); any = 1; } if (any) gen(EV_SYN,SYN_REPORT,0); } static void teardown(void) { ioctl(fd,UI_DEV_DESTROY,0); close(fd); } static int sun_to_evkey(int sunkey) { if ((sunkey < 0) || (sunkey > 127)) return(-1); return(map_sun[sunkey]); } static int signed7(unsigned char v) { v &= 0x7f; if (v & 0x40) return(((int)v)-(int)0x80); else return(v); } int main(void); int main(void) { int ch; int ikey; setup(); sleep(1); while (1) { ch = getchar(); dlog("i %d\n",ch); if (ch == EOF) break; switch (state) { case 0: switch (ch) { case 0x80 ... 0x87: buttons = ch & 7; state = 1; break; case 0x88: downp = 1; state = 3; break; case 0x89: downp = 0; state = 3; break; case 0x8a: break; } break; case 1: if (ch & 0x80) { state = 0; break; } dx = signed7(ch); state = 2; break; case 2: if (ch & 0x80) { state = 0; break; } // Linux dy is reverse of Sun mice dy = - signed7(ch); mouse_event(); state = 0; break; case 3: if (ch & 0x80) { state = 0; break; } ikey = sun_to_evkey(ch); if (ikey >= 0) { if (downp) down(ikey); else up(ikey); } state = 0; break; } } sleep(1); teardown(); return(0); }