Root/tools/atrf-proxy/atrf-proxy.c

Source at commit 2961482cac72ca292ad95a4e6bf53500014279b4 created 8 years 11 months ago.
By Werner Almesberger, tools: atrf-id option -s to retrieve driver spec, with necessary infrastructure
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
27
28#define DEFAULT_PORT 0x1540 /* 5440 */
29
30
31static int verbose = 0;
32
33
34static int get_num(struct netio *netio, int last, int *ret)
35{
36    char buf[10];
37    ssize_t got;
38    unsigned long n;
39    char *end;
40
41    got = netio_read_until(netio,
42        last ? "\n" : " ", buf, sizeof(buf), NULL);
43    if (got < 0) {
44        *ret = -1;
45        return -1;
46    }
47    buf[got] = 0;
48    n = strtoul(buf, &end, 0);
49    if (*end) {
50        *ret = netio_printf(netio, "-bad number\n");
51        return -1;
52    }
53    /* @@@ check against INT_MAX */
54    return n;
55}
56
57
58static int cmd_two(struct atrf_dsc *dsc, struct netio *netio, const char *cmd)
59{
60    int n, ret;
61
62    n = get_num(netio, 0, &ret);
63    if (n < 0)
64        return ret;
65    if (n > 255)
66        return netio_printf(netio, "-bad argument\n");
67
68    if (!strcasecmp(cmd, "set")) {
69        int val;
70
71        val = get_num(netio, 1, &ret);
72        if (val < 0)
73            return ret;
74        if (val > 255)
75            return netio_printf(netio, "-bad argument\n");
76        atrf_reg_write(dsc, n, val);
77        if (atrf_error(dsc))
78            return netio_printf(netio, "-I/O error\n");
79        return netio_printf(netio, "+\n");
80    }
81    if (!strcasecmp(cmd, "write")) {
82        uint8_t *tmp;
83        ssize_t got;
84
85        if (n > 128)
86            return netio_printf(netio, "-bad argument\n");
87        tmp = malloc(n+1);
88        if (!tmp)
89            return netio_printf(netio, "-out of memory\n");
90        got = netio_read(netio, tmp, n+1);
91        if (got != n+1) {
92            free(tmp);
93            return -1;
94        }
95        if (tmp[n] != '\n') {
96            free(tmp);
97            return netio_printf(netio, "-unterminated command\n");
98        }
99        atrf_buf_write(dsc, tmp, n);
100        free(tmp);
101        if (atrf_error(dsc))
102            return netio_printf(netio, "-I/O error\n");
103        return netio_printf(netio, "+\n");
104    }
105    abort();
106}
107
108
109static int cmd_more(struct atrf_dsc *dsc, struct netio *netio, const char *cmd)
110{
111    int n, ret;
112
113    if (!strcasecmp(cmd, "set"))
114        return cmd_two(dsc, netio, cmd);
115    if (!strcasecmp(cmd, "write"))
116        return cmd_two(dsc, netio, cmd);
117
118    n = get_num(netio, 1, &ret);
119    if (n < 0)
120        return ret;
121
122    if (!strcasecmp(cmd, "slp_tr")) {
123        if (n > 1)
124            return netio_printf(netio, "-bad argument\n");
125        if (atrf_slp_tr(dsc, n) < 0)
126            return netio_printf(netio, "-I/O error\n");
127        return netio_printf(netio, "+\n");
128    }
129    if (!strcasecmp(cmd, "clkm")) {
130        if (n > 16)
131            return netio_printf(netio, "-bad argument\n");
132        if (atrf_set_clkm(dsc, n) < 0)
133            return netio_printf(netio, "-error\n");
134        return netio_printf(netio, "+\n");
135    }
136    if (!strcasecmp(cmd, "get")) {
137        uint8_t res;
138
139        if (n > 255)
140            return netio_printf(netio, "-bad argument\n");
141        res = atrf_reg_read(dsc, n);
142        if (atrf_error(dsc))
143            return netio_printf(netio, "-I/O error\n");
144        return netio_printf(netio, "+0x%02x\n", res);
145    }
146    return netio_printf(netio, "-unrecognized command\n");
147}
148
149
150static int cmd_zero(struct atrf_dsc *dsc, struct netio *netio, const char *cmd)
151{
152    int res;
153
154    if (!strcasecmp(cmd, "spec")) {
155        const char *spec = atrf_driver_spec(dsc, 1);
156
157        if (spec)
158            return netio_printf(netio, "+%s\n", spec);
159        else
160            return netio_printf(netio,
161                "-can't obtain specification\n");
162    }
163    if (!strcasecmp(cmd, "reset")) {
164        atrf_reset(dsc);
165        return netio_printf(netio, "+\n");
166    }
167    if (!strcasecmp(cmd, "reset_rf")) {
168        atrf_reset_rf(dsc);
169        return netio_printf(netio, "+\n");
170    }
171    if (!strcasecmp(cmd, "test")) {
172        atrf_test_mode(dsc);
173        return netio_printf(netio, "+\n");
174    }
175    if (!strcasecmp(cmd, "read")) {
176        uint8_t buf[128+1]; /* one more for the trailing \n */
177        int got;
178
179        got = atrf_buf_read(dsc, buf, sizeof(buf));
180        if (got < 0)
181            return netio_printf(netio, "-I/O error\n");
182        if (netio_printf(netio, "+%d ", got) < 0)
183            return -1;
184        buf[got] = '\n';
185        return netio_write(netio, buf, got+1);
186    }
187    if (!strcasecmp(cmd, "poll")) {
188        res = atrf_interrupt(dsc);
189        if (res < 0)
190            return netio_printf(netio, "-I/O error\n");
191        if (!res)
192            usleep(100*1000);
193        return netio_printf(netio, "+%d\n", res);
194    }
195    return netio_printf(netio, "-unrecognized command\n");
196}
197
198
199static void session(const char *driver, struct netio *netio)
200{
201    struct atrf_dsc *dsc;
202
203    dsc = atrf_open(driver);
204    if (!dsc) {
205        netio_printf(netio, "-unable to open driver\n");
206        return;
207    }
208
209    if (netio_printf(netio,
210        "+connected to %s\n", driver ? driver : "default") < 0)
211        goto done;
212
213    while (1) {
214        char buf[100];
215        ssize_t got;
216        char last;
217
218        got = netio_read_until(netio, " \n", buf, sizeof(buf), &last);
219        if (got < 0)
220            break;
221        if (!got && last) {
222            netio_printf(netio, "-empty input\n");
223            continue;
224        }
225        buf[got] = 0;
226        switch (last) {
227        case ' ':
228            if (cmd_more(dsc, netio, buf) < 0)
229                goto done;
230            break;
231        case '\n':
232            if (cmd_zero(dsc, netio, buf) < 0)
233                goto done;
234            break;
235        case 0:
236            goto done;
237        default:
238            abort();
239        }
240    }
241    
242done:
243    atrf_close(dsc);
244}
245
246
247static void loop(const char *driver, int port)
248{
249    struct sockaddr_in addr;
250    int s;
251    int one = 1;
252
253    s = socket(PF_INET, SOCK_STREAM, 0);
254    if (s < 0) {
255        perror("socket");
256        exit(1);
257    }
258
259    if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)) < 0) {
260        perror("setsockopt");
261        exit(1);
262    }
263
264    memset(&addr, 0, sizeof(addr));
265    addr.sin_family = AF_INET;
266    addr.sin_port = htons(port);
267    if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
268        perror("bind");
269        exit(1);
270    }
271
272    if (listen(s, 0) < 0) {
273        perror("listen");
274        exit(1);
275    }
276
277    while (1) {
278        socklen_t len = sizeof(addr);
279        int s2;
280        struct netio *netio;
281
282        s2 = accept(s, (struct sockaddr *) &addr, &len);
283        if (s2 < 0) {
284            perror("accept");
285            continue;
286        }
287
288        if (verbose)
289            fprintf(stderr, "%s:%u\n", inet_ntoa(addr.sin_addr),
290              ntohs(addr.sin_port));
291
292        netio = netio_open(s2);
293        if (netio) {
294            session(driver, netio);
295            netio_close(netio);
296        } else {
297            if (close(s2) < 0)
298                perror("close");
299        }
300    }
301}
302
303
304static void usage(const char *name)
305{
306    fprintf(stderr, "usage: %s [-d driver[:arg]] [-v ...] [port]\n", name);
307    exit(1);
308}
309
310
311int main(int argc, char **argv)
312{
313    unsigned long port = DEFAULT_PORT;
314    const char *driver = NULL;
315    char *end;
316    int c;
317
318    while ((c = getopt(argc, argv, "d:v")) != EOF)
319        switch (c) {
320        case 'd':
321            driver = optarg;
322            break;
323        case 'v':
324            verbose++;
325            netio_verbose++;
326            break;
327        default:
328            usage(*argv);
329        }
330    
331    switch (argc-optind) {
332    case 0:
333        break;
334    case 1:
335        port = strtoul(argv[optind], &end, 0);
336        if (*end || !port || port > 0xffff)
337            usage(*argv);
338        break;
339    default:
340        usage(*argv);
341    }
342
343    loop(driver, port);
344
345    return 0;
346}
347

Archive Download this file



interactive