void fs_ml_input_init() { list_input_devices(); // http://msdn.microsoft.com/en-us/library/windows/desktop/dd375731(v=VS.85).aspx g_key_mapping[VK_BACK] = FS_ML_KEY_BACKSPACE; g_key_mapping[VK_TAB] = FS_ML_KEY_TAB; g_key_mapping[VK_CLEAR] = FS_ML_KEY_CLEAR; g_key_mapping[VK_RETURN] = FS_ML_KEY_RETURN; // FIXME: RSHIFT g_key_mapping[VK_SHIFT] = FS_ML_KEY_LSHIFT; g_key_mapping[VK_CONTROL] = FS_ML_KEY_LCTRL; g_key_mapping[E0 + VK_CONTROL] = FS_ML_KEY_RCTRL; g_key_mapping[VK_MENU] = FS_ML_KEY_LALT; g_key_mapping[VK_PAUSE] = FS_ML_KEY_PAUSE; // ... FIXME ... g_key_mapping[E0 + VK_LEFT] = FS_ML_KEY_LEFT; g_key_mapping[E0 + VK_UP] = FS_ML_KEY_UP; g_key_mapping[E0 + VK_RIGHT] = FS_ML_KEY_RIGHT; g_key_mapping[E0 + VK_DOWN] = FS_ML_KEY_DOWN; // ... FIXME ... g_key_mapping[VK_F1] = FS_ML_KEY_F1; g_key_mapping[VK_F2] = FS_ML_KEY_F2; g_key_mapping[VK_F3] = FS_ML_KEY_F3; g_key_mapping[VK_F4] = FS_ML_KEY_F4; g_key_mapping[VK_F5] = FS_ML_KEY_F5; g_key_mapping[VK_F6] = FS_ML_KEY_F6; g_key_mapping[VK_F7] = FS_ML_KEY_F7; g_key_mapping[VK_F8] = FS_ML_KEY_F8; g_key_mapping[VK_F9] = FS_ML_KEY_F9; g_key_mapping[VK_F10] = FS_ML_KEY_F10; g_key_mapping[VK_F11] = FS_ML_KEY_F11; g_key_mapping[VK_F12] = FS_ML_KEY_F12; }
int main ( int argc, char ** argv ) { int i, j; int sockint, sockctl; // For the listening sockets struct sockaddr_l2 l2a; socklen_t alen=sizeof(l2a); int sint, sctl; // For the one-session-only // socket descriptor handles char badr[40]; fd_set fds; // fds for listening sockets fd_set efds; // dev-event file descriptors int maxevdevfileno; char skipsdp = 0; // On request, disable SDPreg struct timeval tv; // Used for "select" int evdevmask = 0;// If restricted to using only one evdev int mutex11 = 0; // try to "mute" in x11? char *fifoname = NULL; // Filename for fifo, if applicable // Parse command line for ( i = 1; i < argc; ++i ) { if ( ( 0 == strcmp ( argv[i], "-h" ) ) || ( 0 == strcmp ( argv[i], "-?" ) ) || ( 0 == strcmp ( argv[i], "--help" ) ) ) { showhelp(); return 0; } else if ( ( 0 == strcmp ( argv[i], "-s" ) ) || ( 0 == strcmp ( argv[i], "--skipsdp" ) ) ) { skipsdp = 1; } else if ( 0 == strncmp ( argv[i], "-e", 2 ) ) { evdevmask |= 1 << atoi(argv[i]+2); } else if ( 0 == strcmp ( argv[i], "-l" ) ) { return list_input_devices(); } else if ( 0 == strcmp ( argv[i], "-d" ) ) { debugevents = 0xffff; } else if ( 0 == strcmp ( argv[i], "-x" ) ) { mutex11 = 1; } else if ( 0 == strncmp ( argv[i], "-f", 2 ) ) { fifoname = argv[i] + 2; } else { fprintf ( stderr, "Invalid argument: \'%s\'\n", argv[i]); return 1; } } if ( ! skipsdp ) { if ( dosdpregistration() ) { fprintf(stderr,"Failed to register with SDP server\n"); return 1; } } if ( NULL == fifoname ) { if ( 1 > initevents (evdevmask, mutex11) ) { fprintf ( stderr, "Failed to open event interface files\n" ); return 2; } } else { if ( 1 > initfifo ( fifoname ) ) { fprintf ( stderr, "Failed to create/open fifo [%s]\n", fifoname ); return 2; } } maxevdevfileno = add_filedescriptors ( &efds ); if ( maxevdevfileno <= 0 ) { fprintf ( stderr, "Failed to organize event input.\n" ); return 13; } sockint = socket ( AF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP ); sockctl = socket ( AF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP ); if ( ( 0 > sockint ) || ( 0 > sockctl ) ) { fprintf ( stderr, "Failed to generate bluetooth sockets\n" ); return 2; } if ( btbind ( sockint, PSMHIDINT ) || btbind ( sockctl, PSMHIDCTL )) { fprintf ( stderr, "Failed to bind sockets (%d/%d) " "to PSM (%d/%d)\n", sockctl, sockint, PSMHIDCTL, PSMHIDINT ); return 3; } if ( listen ( sockint, 1 ) || listen ( sockctl, 1 ) ) { fprintf ( stderr, "Failed to listen on int/ctl BT socket\n" ); close ( sockint ); close ( sockctl ); return 4; } // Add handlers to catch signals: // All do the same, terminate the program safely // Ctrl+C will be ignored though (SIGINT) while a connection is active signal ( SIGHUP, &onsignal ); signal ( SIGTERM, &onsignal ); signal ( SIGINT, &onsignal ); fprintf ( stdout, "The HID-Client is now ready to accept connections " "from another machine\n" ); //i = system ( "stty -echo" ); // Disable key echo to the console while ( 0 == prepareshutdown ) { // Wait for any shutdown-event to occur sint = sctl = 0; add_filedescriptors ( &efds ); tv.tv_sec = 0; tv.tv_usec = 0; while ( 0 < (j = select(maxevdevfileno+1,&efds,NULL,NULL,&tv))) { // Collect and discard input data as long as available if ( -1 > ( j = parse_events ( &efds, 0 ) ) ) { // LCtrl-LAlt-PAUSE - terminate program prepareshutdown = 1; break; } add_filedescriptors ( &efds ); tv.tv_sec = 0; tv.tv_usec = 500; // minimal delay } if ( prepareshutdown ) break; connectionok = 0; tv.tv_sec = 1; tv.tv_usec = 0; FD_ZERO ( &fds ); FD_SET ( sockctl, &fds ); j = select ( sockctl + 1, &fds, NULL, NULL, &tv ); if ( j < 0 ) { if ( errno == EINTR ) { // Ctrl+C ? - handle that elsewhere continue; } fprintf ( stderr, "select() error on BT socket: %s! " "Aborting.\n", strerror ( errno ) ); return 11; } if ( j == 0 ) { // Nothing happened, check for shutdown req and retry if ( debugevents & 0x2 ) fprintf ( stdout, "," ); continue; } sctl = accept ( sockctl, (struct sockaddr *)&l2a, &alen ); if ( sctl < 0 ) { if ( errno == EAGAIN ) { continue; } fprintf ( stderr, "Failed to get a control connection:" " %s\n", strerror ( errno ) ); continue; } tv.tv_sec = 3; tv.tv_usec = 0; FD_ZERO ( &fds ); FD_SET ( sockint, &fds ); j = select ( sockint + 1, &fds, NULL, NULL, &tv ); if ( j < 0 ) { if ( errno == EINTR ) { // Might have been Ctrl+C close ( sctl ); continue; } fprintf ( stderr, "select() error on BT socket: %s! " "Aborting.\n", strerror ( errno ) ); return 12; } if ( j == 0 ) { fprintf ( stderr, "Interrupt connection failed to " "establish (control connection already" " there), timeout!\n" ); close ( sctl ); continue; } sint = accept ( sockint, (struct sockaddr *)&l2a, &alen ); if ( sint < 0 ) { close ( sctl ); if ( errno == EAGAIN ) continue; fprintf ( stderr, "Failed to get an interrupt " "connection: %s\n", strerror(errno)); continue; } ba2str ( &l2a.l2_bdaddr, badr ); badr[39] = 0; fprintf ( stdout, "Incoming connection from node [%s] " "accepted and established.\n", badr ); tv.tv_sec = 0; tv.tv_usec = 0; j = -1; add_filedescriptors ( &efds ); while ( 0 < (j = select(maxevdevfileno+1,&efds,NULL,NULL,&tv))) { // This loop removes all input garbage that might be // already in the queue if ( -1 > ( j = parse_events ( &efds, 0 ) ) ) { // LCtrl-LAlt-PAUSE - terminate program prepareshutdown = 1; break; } add_filedescriptors ( &efds ); tv.tv_sec = 0; tv.tv_usec = 0; } if ( prepareshutdown ) break; connectionok = 1; memset ( pressedkey, 0, 8 ); modifierkeys = 0; mousebuttons = 0; while ( connectionok ) { add_filedescriptors ( &efds ); tv.tv_sec = 1; tv.tv_usec = 0; while ( 0 < ( j = select ( maxevdevfileno + 1, &efds, NULL, NULL, &tv ) ) ) { if ( 0 > ( j = parse_events ( &efds, sint ) ) ) { // PAUSE pressed - close connection connectionok = 0; if ( j < -1 ) { // LCtrl-LAlt-PAUSE - terminate close ( sint ); close ( sctl ); prepareshutdown = 1; } break; } add_filedescriptors ( &efds ); tv.tv_sec = 1; tv.tv_usec = 0; } } connectionok = 0; close ( sint ); close ( sctl ); sint = sctl = 0; fprintf ( stderr, "Connection closed\n" ); usleep ( 500000 ); // Sleep 0.5 secs between connections // to not be flooded } //i = system ( "stty echo" ); // Set console back to normal close ( sockint ); close ( sockctl ); if ( ! skipsdp ) { sdpunregister ( sdphandle ); // Remove HID info from SDP server } if ( NULL == fifoname ) { closeevents (); } else { closefifo (); } cleanup_stdin (); // And remove the input queue from stdin fprintf ( stderr, "Stopped hidclient.\n" ); return 0; }