rev |
line source |
nuclear@0
|
1 #include <stdio.h>
|
nuclear@4
|
2 #include <stdlib.h>
|
nuclear@4
|
3 #include <string.h>
|
nuclear@4
|
4 #include <limits.h>
|
nuclear@4
|
5 #include <errno.h>
|
nuclear@4
|
6 #include <assert.h>
|
nuclear@4
|
7 #include <unistd.h>
|
nuclear@4
|
8 #include <fcntl.h>
|
nuclear@4
|
9 #include <sys/socket.h>
|
nuclear@4
|
10 #include <arpa/inet.h>
|
nuclear@4
|
11 #include <sys/select.h>
|
nuclear@4
|
12 #include <sys/time.h>
|
nuclear@4
|
13 #include <sys/types.h>
|
nuclear@4
|
14 #include <linux/joystick.h>
|
nuclear@4
|
15 #include "proto.h"
|
nuclear@4
|
16
|
nuclear@4
|
17 struct client {
|
nuclear@5
|
18 int active;
|
nuclear@4
|
19 struct sockaddr_in addr;
|
nuclear@4
|
20 struct client *next;
|
nuclear@4
|
21 };
|
nuclear@4
|
22
|
nuclear@4
|
23 int open_js(const char *jspath);
|
nuclear@4
|
24 int handle_js(int fd);
|
nuclear@4
|
25 int start_srv(int port);
|
nuclear@4
|
26 int handle_net(int s);
|
nuclear@5
|
27 int respond(int s, int rsp, struct sockaddr_in *sa);
|
nuclear@5
|
28 int respond_msg(int s, struct message *msg, struct sockaddr_in *sa);
|
nuclear@5
|
29 struct client *add_client(struct sockaddr_in *addr);
|
nuclear@5
|
30 struct client *find_client(struct sockaddr_in *addr);
|
nuclear@4
|
31
|
nuclear@4
|
32 static int opt_dport = DEF_PORT;
|
nuclear@4
|
33 static const char *opt_jspath = "/dev/input/js0";
|
nuclear@4
|
34
|
nuclear@5
|
35 static int sock = -1;
|
nuclear@4
|
36 static struct client *clients;
|
nuclear@4
|
37
|
nuclear@4
|
38 static int js_num_axes;
|
nuclear@4
|
39 static float *js_axis_state;
|
nuclear@4
|
40 static unsigned int js_bn_state;
|
nuclear@4
|
41
|
nuclear@0
|
42
|
nuclear@0
|
43 int main(int argc, char **argv)
|
nuclear@0
|
44 {
|
nuclear@5
|
45 int js;
|
nuclear@4
|
46 int maxfd;
|
nuclear@4
|
47
|
nuclear@4
|
48 if((js = open_js(opt_jspath)) == -1) {
|
nuclear@4
|
49 return 1;
|
nuclear@4
|
50 }
|
nuclear@4
|
51 if((sock = start_srv(opt_dport)) == -1) {
|
nuclear@4
|
52 return 1;
|
nuclear@4
|
53 }
|
nuclear@4
|
54 maxfd = js > sock ? js : sock;
|
nuclear@4
|
55
|
nuclear@4
|
56 for(;;) {
|
nuclear@4
|
57 fd_set rdset;
|
nuclear@4
|
58
|
nuclear@4
|
59 FD_ZERO(&rdset);
|
nuclear@4
|
60 FD_SET(js, &rdset);
|
nuclear@4
|
61 FD_SET(sock, &rdset);
|
nuclear@4
|
62
|
nuclear@4
|
63 while(select(maxfd + 1, &rdset, 0, 0, 0) == -1 && errno == EINTR);
|
nuclear@4
|
64
|
nuclear@4
|
65 if(FD_ISSET(js, &rdset)) {
|
nuclear@4
|
66 handle_js(js);
|
nuclear@4
|
67 }
|
nuclear@4
|
68 if(FD_ISSET(sock, &rdset)) {
|
nuclear@4
|
69 handle_net(sock);
|
nuclear@4
|
70 }
|
nuclear@4
|
71 }
|
nuclear@4
|
72
|
nuclear@4
|
73 close(js);
|
nuclear@4
|
74 close(sock);
|
nuclear@4
|
75 return 0;
|
nuclear@0
|
76 }
|
nuclear@4
|
77
|
nuclear@4
|
78 int open_js(const char *jspath)
|
nuclear@4
|
79 {
|
nuclear@4
|
80 int fd;
|
nuclear@4
|
81 char buf[256];
|
nuclear@4
|
82 int axes;
|
nuclear@4
|
83
|
nuclear@4
|
84 if((fd = open(jspath, O_RDONLY)) == -1) {
|
nuclear@4
|
85 fprintf(stderr, "failed to open js device: %s: %s\n", jspath, strerror(errno));
|
nuclear@4
|
86 return -1;
|
nuclear@4
|
87 }
|
nuclear@5
|
88 /*fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK);*/
|
nuclear@4
|
89
|
nuclear@4
|
90 if(ioctl(fd, JSIOCGAXES, &axes) == -1) {
|
nuclear@4
|
91 fprintf(stderr, "failed to get number of joystick axes\n");
|
nuclear@4
|
92 return -1;
|
nuclear@4
|
93 }
|
nuclear@4
|
94 if(ioctl(fd, JSIOCGNAME(sizeof buf), buf) == -1) {
|
nuclear@4
|
95 strcpy(buf, "unknown");
|
nuclear@4
|
96 }
|
nuclear@4
|
97 printf("opened joystick: %s: %s (%d axes)\n", jspath, buf, axes);
|
nuclear@4
|
98
|
nuclear@4
|
99 js_axis_state = malloc(axes * sizeof *js_axis_state);
|
nuclear@4
|
100 assert(js_axis_state);
|
nuclear@4
|
101 js_num_axes = axes;
|
nuclear@4
|
102
|
nuclear@4
|
103 return fd;
|
nuclear@4
|
104 }
|
nuclear@4
|
105
|
nuclear@4
|
106 int handle_js(int fd)
|
nuclear@4
|
107 {
|
nuclear@4
|
108 int evtype;
|
nuclear@4
|
109 struct js_event ev;
|
nuclear@4
|
110 struct client *c;
|
nuclear@4
|
111
|
nuclear@4
|
112 if(read(fd, &ev, sizeof ev) <= 0) {
|
nuclear@4
|
113 return -1;
|
nuclear@4
|
114 }
|
nuclear@4
|
115
|
nuclear@4
|
116 switch(ev.type) {
|
nuclear@4
|
117 case JS_EVENT_AXIS:
|
nuclear@4
|
118 js_axis_state[ev.number] = (float)ev.value / (float)SHRT_MAX;
|
nuclear@4
|
119 evtype = EV_MOTION;
|
nuclear@4
|
120 break;
|
nuclear@4
|
121
|
nuclear@4
|
122 case JS_EVENT_BUTTON:
|
nuclear@4
|
123 if(ev.value) {
|
nuclear@4
|
124 js_bn_state |= 1 << ev.number;
|
nuclear@4
|
125 } else {
|
nuclear@4
|
126 js_bn_state &= ~(1 << ev.number);
|
nuclear@4
|
127 }
|
nuclear@4
|
128 evtype = EV_BUTTON;
|
nuclear@4
|
129 break;
|
nuclear@4
|
130
|
nuclear@4
|
131 default:
|
nuclear@4
|
132 break;
|
nuclear@4
|
133 }
|
nuclear@4
|
134
|
nuclear@4
|
135 /* send client events */
|
nuclear@4
|
136 c = clients;
|
nuclear@4
|
137 while(c) {
|
nuclear@4
|
138 struct message m;
|
nuclear@4
|
139
|
nuclear@4
|
140 m.magic = MAGIC;
|
nuclear@4
|
141 m.type = evtype;
|
nuclear@4
|
142 m.data.event.x = js_axis_state[0];
|
nuclear@4
|
143 m.data.event.y = js_num_axes > 1 ? js_axis_state[1] : 0;
|
nuclear@4
|
144 m.data.event.z = js_num_axes > 2 ? js_axis_state[2] : 0;
|
nuclear@5
|
145 m.data.event.bnmask = js_bn_state;
|
nuclear@4
|
146
|
nuclear@5
|
147 sendto(sock, &m, sizeof m, 0, (struct sockaddr*)&c->addr, sizeof c->addr);
|
nuclear@4
|
148 c = c->next;
|
nuclear@4
|
149 }
|
nuclear@4
|
150 return 0;
|
nuclear@4
|
151 }
|
nuclear@4
|
152
|
nuclear@4
|
153 int start_srv(int port)
|
nuclear@4
|
154 {
|
nuclear@4
|
155 int s;
|
nuclear@4
|
156 struct sockaddr_in sa;
|
nuclear@4
|
157
|
nuclear@4
|
158 if((s = socket(PF_INET, SOCK_DGRAM, 0)) == -1) {
|
nuclear@4
|
159 perror("failed to create socket");
|
nuclear@4
|
160 return -1;
|
nuclear@4
|
161 }
|
nuclear@4
|
162
|
nuclear@4
|
163 memset(&sa, 0, sizeof sa);
|
nuclear@4
|
164 sa.sin_family = AF_INET;
|
nuclear@4
|
165 sa.sin_addr.s_addr = htonl(INADDR_ANY);
|
nuclear@4
|
166 sa.sin_port = htons(opt_dport);
|
nuclear@4
|
167
|
nuclear@4
|
168 if(bind(s, (struct sockaddr*)&sa, sizeof sa) == -1) {
|
nuclear@4
|
169 perror("failed to bind socket");
|
nuclear@4
|
170 close(s);
|
nuclear@4
|
171 return -1;
|
nuclear@4
|
172 }
|
nuclear@4
|
173
|
nuclear@4
|
174 return s;
|
nuclear@4
|
175 }
|
nuclear@4
|
176
|
nuclear@5
|
177
|
nuclear@4
|
178 int handle_net(int s)
|
nuclear@4
|
179 {
|
nuclear@5
|
180 struct message msg;
|
nuclear@5
|
181 struct sockaddr_in addr;
|
nuclear@5
|
182 socklen_t addrlen = sizeof addr;
|
nuclear@5
|
183 struct client *c;
|
nuclear@5
|
184
|
nuclear@5
|
185 if(recvfrom(s, &msg, sizeof msg, 0, (struct sockaddr*)&addr, &addrlen) < sizeof addr) {
|
nuclear@5
|
186 perror("failed to recieve message");
|
nuclear@5
|
187 return -1;
|
nuclear@5
|
188 }
|
nuclear@5
|
189 if(msg.magic != MAGIC) {
|
nuclear@5
|
190 fprintf(stderr, "received magic is not good\n");
|
nuclear@5
|
191 return -1;
|
nuclear@5
|
192 }
|
nuclear@5
|
193
|
nuclear@5
|
194 c = find_client(&addr);
|
nuclear@5
|
195
|
nuclear@5
|
196 switch(msg.type) {
|
nuclear@5
|
197 case REQ_DISCOVER:
|
nuclear@5
|
198 /* a client is looking for us */
|
nuclear@5
|
199 msg.type = RSP_OK;
|
nuclear@5
|
200 strcat(msg.data.raw, "test-input");
|
nuclear@5
|
201 if(respond_msg(s, &msg, &addr) == -1) {
|
nuclear@5
|
202 return -1;
|
nuclear@5
|
203 }
|
nuclear@5
|
204 break;
|
nuclear@5
|
205
|
nuclear@5
|
206 case REQ_START:
|
nuclear@5
|
207 if(!c) {
|
nuclear@5
|
208 if(!(c = add_client(&addr))) {
|
nuclear@5
|
209 respond(s, RSP_ERR, &addr);
|
nuclear@5
|
210 return -1;
|
nuclear@5
|
211 }
|
nuclear@5
|
212 }
|
nuclear@5
|
213 c->active = 1;
|
nuclear@5
|
214 if(respond(s, RSP_OK, &addr) == -1) {
|
nuclear@5
|
215 return -1;
|
nuclear@5
|
216 }
|
nuclear@5
|
217 break;
|
nuclear@5
|
218
|
nuclear@5
|
219 case REQ_STOP:
|
nuclear@5
|
220 if(c) {
|
nuclear@5
|
221 c->active = 0;
|
nuclear@5
|
222 }
|
nuclear@5
|
223 if(respond(s, RSP_OK, &addr) == -1) {
|
nuclear@5
|
224 return -1;
|
nuclear@5
|
225 }
|
nuclear@5
|
226 break;
|
nuclear@5
|
227
|
nuclear@5
|
228 default:
|
nuclear@5
|
229 break;
|
nuclear@5
|
230 }
|
nuclear@5
|
231
|
nuclear@4
|
232 return 0;
|
nuclear@4
|
233 }
|
nuclear@5
|
234
|
nuclear@5
|
235 int respond(int s, int rsp, struct sockaddr_in *sa)
|
nuclear@5
|
236 {
|
nuclear@5
|
237 struct message m;
|
nuclear@5
|
238 memset(&m, 0, sizeof m);
|
nuclear@5
|
239 m.magic = MAGIC;
|
nuclear@5
|
240 m.type = rsp;
|
nuclear@5
|
241
|
nuclear@5
|
242 return respond_msg(s, &m, sa);
|
nuclear@5
|
243 }
|
nuclear@5
|
244
|
nuclear@5
|
245 int respond_msg(int s, struct message *msg, struct sockaddr_in *sa)
|
nuclear@5
|
246 {
|
nuclear@5
|
247 if(sendto(s, &msg, sizeof msg, 0, (struct sockaddr*)sa, sizeof *sa) == -1) {
|
nuclear@5
|
248 perror("failed to send response");
|
nuclear@5
|
249 return -1;
|
nuclear@5
|
250 }
|
nuclear@5
|
251 return 0;
|
nuclear@5
|
252 }
|
nuclear@5
|
253
|
nuclear@5
|
254 struct client *add_client(struct sockaddr_in *addr)
|
nuclear@5
|
255 {
|
nuclear@5
|
256 struct client *c;
|
nuclear@5
|
257
|
nuclear@5
|
258 if(!(c = calloc(1, sizeof *c))) {
|
nuclear@5
|
259 perror("failed to add client");
|
nuclear@5
|
260 return 0;
|
nuclear@5
|
261 }
|
nuclear@5
|
262 c->addr = *addr;
|
nuclear@5
|
263 c->next = clients;
|
nuclear@5
|
264 clients = c;
|
nuclear@5
|
265 return c;
|
nuclear@5
|
266 }
|
nuclear@5
|
267
|
nuclear@5
|
268 struct client *find_client(struct sockaddr_in *addr)
|
nuclear@5
|
269 {
|
nuclear@5
|
270 struct client *c = clients;
|
nuclear@5
|
271 while(c) {
|
nuclear@5
|
272 if(c->addr.sin_addr.s_addr == addr->sin_addr.s_addr &&
|
nuclear@5
|
273 c->addr.sin_port == addr->sin_port) {
|
nuclear@5
|
274 return c;
|
nuclear@5
|
275 }
|
nuclear@5
|
276 c = c->next;
|
nuclear@5
|
277 }
|
nuclear@5
|
278 return 0;
|
nuclear@5
|
279 }
|