IEEE 802.15.4 subsystem
Sign in or create your account | Project List | Help
IEEE 802.15.4 subsystem Git Source Tree
Root/
Source at commit d0fb1a8992d1cf83c558c87ae4dedfae063ddc8f created 12 years 9 months ago. By Werner Almesberger, tools/: the great removal of atrf_interrupt | |
---|---|
1 | /* |
2 | * atrf-proxy/atrf-proxy.c - ATRF network proxy |
3 | * |
4 | * Written 2011 by Werner Almesberger |
5 | * Copyright 2011 Werner Almesberger |
6 | * |
7 | * This program is free software; you can redistribute it and/or modify |
8 | * it under the terms of the GNU General Public License as published by |
9 | * the Free Software Foundation; either version 2 of the License, or |
10 | * (at your option) any later version. |
11 | */ |
12 | |
13 | |
14 | #include <stdlib.h> |
15 | #include <stdio.h> |
16 | #include <unistd.h> |
17 | #include <string.h> |
18 | #include <strings.h> /* for strcasecmp */ |
19 | #include <sys/types.h> |
20 | #include <sys/socket.h> |
21 | #include <netinet/in.h> |
22 | #include <arpa/inet.h> |
23 | |
24 | #include "atrf.h" |
25 | #include "netio.h" |
26 | #include "daemon.h" |
27 | |
28 | |
29 | #define DEFAULT_PORT 0x1540 /* 5440 */ |
30 | |
31 | |
32 | static int verbose = 0; |
33 | |
34 | |
35 | static int get_num(struct netio *netio, int last, int *ret) |
36 | { |
37 | char buf[10]; |
38 | ssize_t got; |
39 | unsigned long n; |
40 | char *end; |
41 | |
42 | got = netio_read_until(netio, |
43 | last ? "\n" : " ", buf, sizeof(buf), NULL); |
44 | if (got < 0) { |
45 | *ret = -1; |
46 | return -1; |
47 | } |
48 | buf[got] = 0; |
49 | n = strtoul(buf, &end, 0); |
50 | if (*end) { |
51 | *ret = netio_printf(netio, "-bad number\n"); |
52 | return -1; |
53 | } |
54 | /* @@@ check against INT_MAX */ |
55 | return n; |
56 | } |
57 | |
58 | |
59 | static int cmd_two(struct atrf_dsc *dsc, struct netio *netio, const char *cmd) |
60 | { |
61 | int n, ret; |
62 | |
63 | n = get_num(netio, 0, &ret); |
64 | if (n < 0) |
65 | return ret; |
66 | if (n > 255) |
67 | return netio_printf(netio, "-bad argument\n"); |
68 | |
69 | if (!strcasecmp(cmd, "set")) { |
70 | int val; |
71 | |
72 | val = get_num(netio, 1, &ret); |
73 | if (val < 0) |
74 | return ret; |
75 | if (val > 255) |
76 | return netio_printf(netio, "-bad argument\n"); |
77 | atrf_reg_write(dsc, n, val); |
78 | if (atrf_error(dsc)) |
79 | return netio_printf(netio, "-I/O error\n"); |
80 | return netio_printf(netio, "+\n"); |
81 | } |
82 | if (!strcasecmp(cmd, "write")) { |
83 | uint8_t *tmp; |
84 | ssize_t got; |
85 | |
86 | if (n > 128) |
87 | return netio_printf(netio, "-bad argument\n"); |
88 | tmp = malloc(n+1); |
89 | if (!tmp) |
90 | return netio_printf(netio, "-out of memory\n"); |
91 | got = netio_read(netio, tmp, n+1); |
92 | if (got != n+1) { |
93 | free(tmp); |
94 | return -1; |
95 | } |
96 | if (tmp[n] != '\n') { |
97 | free(tmp); |
98 | return netio_printf(netio, "-unterminated command\n"); |
99 | } |
100 | atrf_buf_write(dsc, tmp, n); |
101 | free(tmp); |
102 | if (atrf_error(dsc)) |
103 | return netio_printf(netio, "-I/O error\n"); |
104 | return netio_printf(netio, "+\n"); |
105 | } |
106 | if (!strcasecmp(cmd, "setram")) { |
107 | int val; |
108 | |
109 | val = get_num(netio, 1, &ret); |
110 | if (val < 0) |
111 | return ret; |
112 | if (val > 255) |
113 | return netio_printf(netio, "-bad argument\n"); |
114 | atrf_sram_write(dsc, n, val); |
115 | if (atrf_error(dsc)) |
116 | return netio_printf(netio, "-I/O error\n"); |
117 | return netio_printf(netio, "+\n"); |
118 | } |
119 | if (!strcasecmp(cmd, "slp_tr")) { |
120 | int val; |
121 | |
122 | if (n > 1) |
123 | return netio_printf(netio, "-bad argument\n"); |
124 | val = get_num(netio, 1, &ret); |
125 | if (val < 0) |
126 | return ret; |
127 | if (val > 1) |
128 | return netio_printf(netio, "-bad argument\n"); |
129 | if (atrf_slp_tr(dsc, n, val) < 0) |
130 | return netio_printf(netio, "-I/O error\n"); |
131 | return netio_printf(netio, "+\n"); |
132 | } |
133 | abort(); |
134 | } |
135 | |
136 | |
137 | static int cmd_more(struct atrf_dsc *dsc, struct netio *netio, const char *cmd) |
138 | { |
139 | int n, ret; |
140 | |
141 | if (!strcasecmp(cmd, "set")) |
142 | return cmd_two(dsc, netio, cmd); |
143 | if (!strcasecmp(cmd, "setram")) |
144 | return cmd_two(dsc, netio, cmd); |
145 | if (!strcasecmp(cmd, "write")) |
146 | return cmd_two(dsc, netio, cmd); |
147 | if (!strcasecmp(cmd, "slp_tr")) |
148 | return cmd_two(dsc, netio, cmd); |
149 | |
150 | n = get_num(netio, 1, &ret); |
151 | if (n < 0) |
152 | return ret; |
153 | |
154 | if (!strcasecmp(cmd, "clkm")) { |
155 | if (n > 16) |
156 | return netio_printf(netio, "-bad argument\n"); |
157 | if (atrf_set_clkm(dsc, n) < 0) |
158 | return netio_printf(netio, "-error\n"); |
159 | return netio_printf(netio, "+\n"); |
160 | } |
161 | if (!strcasecmp(cmd, "get")) { |
162 | uint8_t res; |
163 | |
164 | if (n > 255) |
165 | return netio_printf(netio, "-bad argument\n"); |
166 | res = atrf_reg_read(dsc, n); |
167 | if (atrf_error(dsc)) |
168 | return netio_printf(netio, "-I/O error\n"); |
169 | return netio_printf(netio, "+0x%02x\n", res); |
170 | } |
171 | if (!strcasecmp(cmd, "wait")) { |
172 | int res; |
173 | |
174 | if (!n) |
175 | n = 1; |
176 | res = atrf_interrupt_wait(dsc, n); |
177 | if (atrf_error(dsc)) |
178 | return netio_printf(netio, "-I/O error\n"); |
179 | if (res < 0) |
180 | return netio_printf(netio, "-not supported\n"); |
181 | return netio_printf(netio, "+0x%02x\n", res); |
182 | } |
183 | if (!strcasecmp(cmd, "getram")) { |
184 | uint8_t res; |
185 | |
186 | if (n > 255) |
187 | return netio_printf(netio, "-bad argument\n"); |
188 | res = atrf_sram_read(dsc, n); |
189 | if (atrf_error(dsc)) |
190 | return netio_printf(netio, "-I/O error\n"); |
191 | return netio_printf(netio, "+0x%02x\n", res); |
192 | } |
193 | return netio_printf(netio, "-unrecognized command\n"); |
194 | } |
195 | |
196 | |
197 | static int cmd_zero(struct atrf_dsc *dsc, struct netio *netio, const char *cmd) |
198 | { |
199 | if (!strcasecmp(cmd, "spec")) { |
200 | const char *spec = atrf_driver_spec(dsc, 1); |
201 | |
202 | if (spec) |
203 | return netio_printf(netio, "+%s\n", spec); |
204 | else |
205 | return netio_printf(netio, |
206 | "-can't obtain specification\n"); |
207 | } |
208 | if (!strcasecmp(cmd, "reset")) { |
209 | atrf_reset(dsc); |
210 | return netio_printf(netio, "+\n"); |
211 | } |
212 | if (!strcasecmp(cmd, "reset_rf")) { |
213 | atrf_reset_rf(dsc); |
214 | return netio_printf(netio, "+\n"); |
215 | } |
216 | if (!strcasecmp(cmd, "test")) { |
217 | atrf_test_mode(dsc); |
218 | return netio_printf(netio, "+\n"); |
219 | } |
220 | if (!strcasecmp(cmd, "read")) { |
221 | uint8_t buf[128+1]; /* one more for the trailing \n */ |
222 | int got; |
223 | |
224 | got = atrf_buf_read(dsc, buf, sizeof(buf)); |
225 | if (got < 0) |
226 | return netio_printf(netio, "-I/O error\n"); |
227 | if (netio_printf(netio, "+%d ", got) < 0) |
228 | return -1; |
229 | buf[got] = '\n'; |
230 | return netio_write(netio, buf, got+1); |
231 | } |
232 | return netio_printf(netio, "-unrecognized command\n"); |
233 | } |
234 | |
235 | |
236 | static void session(const char *driver, struct netio *netio) |
237 | { |
238 | struct atrf_dsc *dsc; |
239 | |
240 | dsc = atrf_open(driver); |
241 | if (!dsc) { |
242 | netio_printf(netio, "-unable to open driver\n"); |
243 | return; |
244 | } |
245 | |
246 | if (netio_printf(netio, |
247 | "+connected to %s\n", driver ? driver : "default") < 0) |
248 | goto done; |
249 | |
250 | while (1) { |
251 | char buf[100]; |
252 | ssize_t got; |
253 | char last; |
254 | |
255 | got = netio_read_until(netio, " \n", buf, sizeof(buf), &last); |
256 | if (got < 0) |
257 | break; |
258 | if (!got && last) { |
259 | netio_printf(netio, "-empty input\n"); |
260 | continue; |
261 | } |
262 | buf[got] = 0; |
263 | switch (last) { |
264 | case ' ': |
265 | if (cmd_more(dsc, netio, buf) < 0) |
266 | goto done; |
267 | break; |
268 | case '\n': |
269 | if (cmd_zero(dsc, netio, buf) < 0) |
270 | goto done; |
271 | break; |
272 | case 0: |
273 | goto done; |
274 | default: |
275 | abort(); |
276 | } |
277 | } |
278 | |
279 | done: |
280 | atrf_close(dsc); |
281 | } |
282 | |
283 | |
284 | static void loop(const char *driver, int port) |
285 | { |
286 | struct sockaddr_in addr; |
287 | int s; |
288 | int one = 1; |
289 | |
290 | s = socket(PF_INET, SOCK_STREAM, 0); |
291 | if (s < 0) { |
292 | perror("socket"); |
293 | exit(1); |
294 | } |
295 | |
296 | if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)) < 0) { |
297 | perror("setsockopt"); |
298 | exit(1); |
299 | } |
300 | |
301 | memset(&addr, 0, sizeof(addr)); |
302 | addr.sin_family = AF_INET; |
303 | addr.sin_port = htons(port); |
304 | if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) { |
305 | perror("bind"); |
306 | exit(1); |
307 | } |
308 | |
309 | if (listen(s, 0) < 0) { |
310 | perror("listen"); |
311 | exit(1); |
312 | } |
313 | |
314 | while (1) { |
315 | socklen_t len = sizeof(addr); |
316 | int s2; |
317 | struct netio *netio; |
318 | |
319 | s2 = accept(s, (struct sockaddr *) &addr, &len); |
320 | if (s2 < 0) { |
321 | perror("accept"); |
322 | continue; |
323 | } |
324 | |
325 | if (verbose) |
326 | fprintf(stderr, "%s:%u\n", inet_ntoa(addr.sin_addr), |
327 | ntohs(addr.sin_port)); |
328 | |
329 | netio = netio_open(s2); |
330 | if (netio) { |
331 | session(driver, netio); |
332 | netio_close(netio); |
333 | } else { |
334 | if (close(s2) < 0) |
335 | perror("close"); |
336 | } |
337 | } |
338 | } |
339 | |
340 | |
341 | static void usage(const char *name) |
342 | { |
343 | fprintf(stderr, |
344 | "usage: %s [-b] [-d driver[:arg]] [-v ...] [port]\n\n" |
345 | " port listen on the specified port (default: %d)\n\n" |
346 | " -b background the process after initialization\n" |
347 | " -d driver[:arg] use the specified driver (default: %s)\n" |
348 | " -v ... increase verbosity level\n" |
349 | , name, DEFAULT_PORT, atrf_default_driver_name()); |
350 | exit(1); |
351 | } |
352 | |
353 | |
354 | int main(int argc, char **argv) |
355 | { |
356 | unsigned long port = DEFAULT_PORT; |
357 | const char *driver = NULL; |
358 | int foreground = 1; |
359 | char *end; |
360 | int c; |
361 | |
362 | while ((c = getopt(argc, argv, "bd:v")) != EOF) |
363 | switch (c) { |
364 | case 'b': |
365 | foreground = 0; |
366 | break; |
367 | case 'd': |
368 | driver = optarg; |
369 | break; |
370 | case 'v': |
371 | verbose++; |
372 | netio_verbose++; |
373 | break; |
374 | default: |
375 | usage(*argv); |
376 | } |
377 | |
378 | switch (argc-optind) { |
379 | case 0: |
380 | break; |
381 | case 1: |
382 | port = strtoul(argv[optind], &end, 0); |
383 | if (*end || !port || port > 0xffff) |
384 | usage(*argv); |
385 | break; |
386 | default: |
387 | usage(*argv); |
388 | } |
389 | |
390 | if (foreground || !daemonize()) |
391 | loop(driver, port); |
392 | |
393 | return 0; |
394 | } |
395 |