# HG changeset patch # User John Tsiombikas # Date 1410383303 -10800 # Node ID a32b151fb3c6c7404bfd3e50e33ee110c422bbed # Parent a1784a4290c2e3a93132523c58349ce832ec00c5 moving along slowly diff -r a1784a4290c2 -r a32b151fb3c6 .clang_complete --- a/.clang_complete Mon Sep 01 05:59:31 2014 +0300 +++ b/.clang_complete Thu Sep 11 00:08:23 2014 +0300 @@ -1,1 +1,2 @@ +-std=c++11 -Iinclude diff -r a1784a4290c2 -r a32b151fb3c6 Makefile --- a/Makefile Mon Sep 01 05:59:31 2014 +0300 +++ b/Makefile Thu Sep 11 00:08:23 2014 +0300 @@ -6,7 +6,7 @@ inc = -Iinclude CFLAGS = -pedantic -Wall -g $(inc) `pkg-config --cflags sdl2` -CXXFLAGS = $(CFLAGS) +CXXFLAGS = -std=c++11 $(CFLAGS) LDFLAGS = $(libgl) `pkg-config --libs sdl2` ifeq ($(shell uname -s), Darwin) diff -r a1784a4290c2 -r a32b151fb3c6 include/proto.h --- a/include/proto.h Mon Sep 01 05:59:31 2014 +0300 +++ b/include/proto.h Thu Sep 11 00:08:23 2014 +0300 @@ -11,12 +11,24 @@ /* responses */ #define RSP_OK 0 #define RSP_ERR 255 +/* events */ +#define EV_STATE MAGIC +#define EV_MOTION 16 +#define EV_BUTTON 17 +struct msg_ev_data { + float x, y, z; + unsigned int bnmask; +}; struct message { int magic; int type; - char data[24]; + + union { + char raw[24]; + struct msg_ev_data event; + } data; }; diff -r a1784a4290c2 -r a32b151fb3c6 inptools/test/.clang_complete --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/inptools/test/.clang_complete Thu Sep 11 00:08:23 2014 +0300 @@ -0,0 +1,1 @@ +-I../../include diff -r a1784a4290c2 -r a32b151fb3c6 inptools/test/src/main.c --- a/inptools/test/src/main.c Mon Sep 01 05:59:31 2014 +0300 +++ b/inptools/test/src/main.c Thu Sep 11 00:08:23 2014 +0300 @@ -1,5 +1,174 @@ #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "proto.h" + +struct client { + int s; + struct sockaddr_in addr; + struct client *next; +}; + +int open_js(const char *jspath); +int handle_js(int fd); +int start_srv(int port); +int handle_net(int s); + +static int opt_dport = DEF_PORT; +static const char *opt_jspath = "/dev/input/js0"; + +static struct client *clients; + +static int js_num_axes; +static float *js_axis_state; +static unsigned int js_bn_state; + int main(int argc, char **argv) { + int js, sock; + int maxfd; + + if((js = open_js(opt_jspath)) == -1) { + return 1; + } + if((sock = start_srv(opt_dport)) == -1) { + return 1; + } + maxfd = js > sock ? js : sock; + + for(;;) { + fd_set rdset; + + FD_ZERO(&rdset); + FD_SET(js, &rdset); + FD_SET(sock, &rdset); + + while(select(maxfd + 1, &rdset, 0, 0, 0) == -1 && errno == EINTR); + + if(FD_ISSET(js, &rdset)) { + handle_js(js); + } + if(FD_ISSET(sock, &rdset)) { + handle_net(sock); + } + } + + close(js); + close(sock); + return 0; } + +int open_js(const char *jspath) +{ + int fd; + char buf[256]; + int axes; + + if((fd = open(jspath, O_RDONLY)) == -1) { + fprintf(stderr, "failed to open js device: %s: %s\n", jspath, strerror(errno)); + return -1; + } + fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK); + + if(ioctl(fd, JSIOCGAXES, &axes) == -1) { + fprintf(stderr, "failed to get number of joystick axes\n"); + return -1; + } + if(ioctl(fd, JSIOCGNAME(sizeof buf), buf) == -1) { + strcpy(buf, "unknown"); + } + printf("opened joystick: %s: %s (%d axes)\n", jspath, buf, axes); + + js_axis_state = malloc(axes * sizeof *js_axis_state); + assert(js_axis_state); + js_num_axes = axes; + + return fd; +} + +int handle_js(int fd) +{ + int evtype; + struct js_event ev; + struct client *c; + + if(read(fd, &ev, sizeof ev) <= 0) { + return -1; + } + + switch(ev.type) { + case JS_EVENT_AXIS: + js_axis_state[ev.number] = (float)ev.value / (float)SHRT_MAX; + evtype = EV_MOTION; + break; + + case JS_EVENT_BUTTON: + if(ev.value) { + js_bn_state |= 1 << ev.number; + } else { + js_bn_state &= ~(1 << ev.number); + } + evtype = EV_BUTTON; + break; + + default: + break; + } + + /* send client events */ + c = clients; + while(c) { + struct message m; + + m.magic = MAGIC; + m.type = evtype; + m.data.event.x = js_axis_state[0]; + m.data.event.y = js_num_axes > 1 ? js_axis_state[1] : 0; + m.data.event.z = js_num_axes > 2 ? js_axis_state[2] : 0; + + sendto(c->s, &m, sizeof m, 0, (struct sockaddr*)&c->addr, sizeof c->addr); + c = c->next; + } + return 0; +} + +int start_srv(int port) +{ + int s; + struct sockaddr_in sa; + + if((s = socket(PF_INET, SOCK_DGRAM, 0)) == -1) { + perror("failed to create socket"); + return -1; + } + + memset(&sa, 0, sizeof sa); + sa.sin_family = AF_INET; + sa.sin_addr.s_addr = htonl(INADDR_ANY); + sa.sin_port = htons(opt_dport); + + if(bind(s, (struct sockaddr*)&sa, sizeof sa) == -1) { + perror("failed to bind socket"); + close(s); + return -1; + } + + return s; +} + +int handle_net(int s) +{ + return 0; +} diff -r a1784a4290c2 -r a32b151fb3c6 src/inpclient.cc --- a/src/inpclient.cc Mon Sep 01 05:59:31 2014 +0300 +++ b/src/inpclient.cc Thu Sep 11 00:08:23 2014 +0300 @@ -15,7 +15,7 @@ static int send_request(int s, struct message *msg, long timeout); static int opt_dport = DEF_PORT; /* discover broadcast port */ -static long opt_timeout = 5000; /* 10 sec discovery timeout */ +static long opt_timeout = 5000; /* 10 sec discovery timeout */ static int sock = -1; @@ -40,7 +40,10 @@ memset(&msg, 0, sizeof msg); msg.magic = MAGIC; msg.type = REQ_START; - return send_request(sock, &msg, opt_timeout); + if(send_request(sock, &msg, opt_timeout) == -1) { + return -1; + } + return msg.magic == MAGIC && msg.type == RSP_OK ? 0 : -1; } int netinp_stop() @@ -54,10 +57,14 @@ memset(&msg, 0, sizeof msg); msg.magic = MAGIC; msg.type = REQ_STOP; - return send_request(sock, &msg, opt_timeout); + + if(send_request(sock, &msg, opt_timeout) == -1) { + return -1; + } + return msg.magic == MAGIC && msg.type == RSP_OK ? 0 : -1; } -int netinp_read(float *pos) +int netinp_read(float *pos, unsigned int *bnmask) { struct message msg; @@ -70,15 +77,34 @@ return -1; } - pos[0] = ((float*)msg.data)[0]; - pos[1] = ((float*)msg.data)[1]; - pos[2] = ((float*)msg.data)[3]; + if(msg.magic != MAGIC || msg.type != MAGIC) { + fprintf(stderr, "not enough magic in the message\n"); + return -1; + } + + pos[0] = msg.data.event.x; + pos[1] = msg.data.event.y; + pos[2] = msg.data.event.z; + *bnmask = msg.data.event.bnmask; return 0; } int netinp_reset() { - return -1; // TODO + struct message msg; + + if(sock == -1) { + return -1; + } + + memset(&msg, 0, sizeof msg); + msg.magic = MAGIC; + msg.type = REQ_STOP; + + if(send_request(sock, &msg, opt_timeout) == -1) { + return -1; + } + return msg.magic == MAGIC && msg.type == RSP_OK ? 0 : -1; } static int discover(struct sockaddr_in *srv_sa) @@ -142,7 +168,7 @@ perror("failed to receive datagram\n"); } if(msg.magic == MAGIC && msg.type == RSP_OK) { - printf("found input server \"%s\" at: %s:%d\n", msg.data, + printf("found input server \"%s\" at: %s:%d\n", msg.data.raw, inet_ntoa(srv_sa->sin_addr), ntohs(srv_sa->sin_port)); return s; } diff -r a1784a4290c2 -r a32b151fb3c6 src/inpclient.h --- a/src/inpclient.h Mon Sep 01 05:59:31 2014 +0300 +++ b/src/inpclient.h Thu Sep 11 00:08:23 2014 +0300 @@ -4,7 +4,7 @@ int netinp_start(); int netinp_stop(); -int netinp_read(float *pos); +int netinp_read(float *pos, unsigned int *bnmask); int netinp_reset(); #endif // INPCLIENT_H_ diff -r a1784a4290c2 -r a32b151fb3c6 src/main.cc --- a/src/main.cc Mon Sep 01 05:59:31 2014 +0300 +++ b/src/main.cc Thu Sep 11 00:08:23 2014 +0300 @@ -1,8 +1,16 @@ #include #include +#include +#include +#include #include +#include +#include +#include +#include #include "opengl.h" #include "vport.h" +#include "inpclient.h" #define ANYPOS SDL_WINDOWPOS_UNDEFINED @@ -10,10 +18,17 @@ bool handle_event(SDL_Event *ev); bool handle_key(int key, bool pressed); void reshape(int x, int y); +void inp_thread_func(); static SDL_Window *win; static SDL_GLContext ctx; +// network input stuff +static std::thread inp_thread; +static std::mutex inp_mutex; +static float inp_pos[3]; +static unsigned int inp_bn; + int main(int argc, char **argv) { if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER) == -1) { @@ -32,6 +47,8 @@ return 1; } + inp_thread = std::thread(inp_thread_func); + for(;;) { SDL_Event ev; SDL_WaitEvent(&ev); @@ -46,6 +63,7 @@ } done: + inp_thread.join(); SDL_Quit(); return 0; } @@ -99,3 +117,33 @@ } return true; } + +void inp_thread_func() +{ + int s = netinp_start(); + if(s == -1) { + return; + } + + for(;;) { + fd_set rdset; + + FD_ZERO(&rdset); + FD_SET(s, &rdset); + + struct timeval tv; + tv.tv_sec = 5; + tv.tv_usec = 0; + + while(select(s + 1, &rdset, 0, 0, &tv) == -1 && errno == EINTR); + + if(FD_ISSET(s, &rdset)) { + inp_mutex.lock(); + netinp_read(inp_pos, &inp_bn); + inp_mutex.unlock(); + } + } + + netinp_stop(); + close(s); +}