Root/tools/lib/atnet.c

Source at commit 49e7c83796bc04941e9dbcec69bc0751563ff4d4 created 2 years 4 months ago.
By Werner Almesberger, atusb/: use ""VDD" symbol from kicad-libs
1/*
2 * lib/atnet.c - Access functions library for 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 <stdarg.h>
15#include <stdlib.h>
16#include <stdio.h>
17#include <string.h>
18#include <assert.h>
19#include <sys/types.h>
20#include <sys/socket.h>
21#include <netdb.h>
22
23#include "netio.h"
24
25#include "driver.h"
26
27
28#define DEFAULT_PORT "5440"
29
30
31struct atnet_dsc {
32    struct netio *netio;
33    int error;
34    char *spec;
35    char reply[1000];
36};
37
38
39static int dialog_vsend(struct atnet_dsc *dsc, const char *fmt, va_list ap)
40{
41    va_list ap2;
42    char *buf;
43    int n, res;
44
45    va_copy(ap2, ap);
46    n = vsnprintf(NULL, 0, fmt, ap2);
47
48    buf = malloc(n+1);
49    if (!buf) {
50        perror("malloc");
51        return -1;
52    }
53
54    vsprintf(buf, fmt, ap);
55
56    buf[n] = '\n';
57    res = netio_write(dsc->netio, buf, n+1);
58    free(buf);
59
60    return res < 0 ? -1 : 0;
61}
62
63
64static int dialog_send(struct atnet_dsc *dsc, const char *fmt, ...)
65{
66    va_list ap;
67    int res;
68
69    va_start(ap, fmt);
70    res = dialog_vsend(dsc, fmt, ap);
71    va_end(ap);
72    return res;
73}
74
75
76static int dialog_recv(struct atnet_dsc *dsc)
77{
78    int n;
79
80    n = netio_read_until(dsc->netio,
81        "\n", dsc->reply, sizeof(dsc->reply)-1, NULL);
82    if (n < 0)
83        return -1;
84    dsc->reply[n] = 0;
85
86    return dsc->reply[0] == '+' ? 0 : -1;
87}
88
89
90static int dialog(struct atnet_dsc *dsc, const char *fmt, ...)
91{
92    va_list ap;
93    int res;
94
95    va_start(ap, fmt);
96    res = dialog_vsend(dsc, fmt, ap);
97    va_end(ap);
98    if (res < 0)
99        return res;
100
101    return dialog_recv(dsc);
102}
103
104
105/* ----- error handling ---------------------------------------------------- */
106
107
108static int atnet_error(void *handle)
109{
110    struct atnet_dsc *dsc = handle;
111
112    return dsc->error;
113}
114
115
116static int atnet_clear_error(void *handle)
117{
118    struct atnet_dsc *dsc = handle;
119    int ret;
120
121    ret = dsc->error;
122    dsc->error = 0;
123    return ret;
124}
125
126
127/* ----- open/close -------------------------------------------------------- */
128
129
130static void *atnet_open(const char *arg)
131{
132    char *host = NULL, *comma;
133    const char *port = DEFAULT_PORT;
134    struct addrinfo *addrs;
135    const struct addrinfo *addr;
136    static struct addrinfo hint = { .ai_socktype = SOCK_STREAM };
137    int res, s;
138    struct atnet_dsc *dsc;
139
140    if (arg) {
141        host = strdup(arg);
142        if (!host) {
143            perror("strdup");
144            return NULL;
145        }
146        comma = strchr(host, ',');
147        if (comma) {
148            *comma = 0;
149            port = comma+1;
150        }
151    }
152    res = getaddrinfo(arg && *host ? host : NULL, port, &hint, &addrs);
153    if (res < 0) {
154        fprintf(stderr, "%s: %s\n", arg, gai_strerror(res));
155        free(host);
156        return NULL;
157    }
158    free(host);
159
160    for (addr = addrs; addr; addr = addr->ai_next) {
161        s = socket(addr->ai_family, addr->ai_socktype,
162            addr->ai_protocol);
163        if (s < 0)
164            continue;
165        if (connect(s, addr->ai_addr, addr->ai_addrlen) >= 0)
166            break;
167        close(s);
168    }
169    if (!addr) {
170        perror(arg);
171        freeaddrinfo(addrs);
172        return NULL;
173    }
174
175    freeaddrinfo(addrs);
176
177    dsc = malloc(sizeof(*dsc));
178    if (!dsc) {
179        perror("malloc");
180        exit(1);
181    }
182
183    dsc->netio = netio_open(s);
184    if (!dsc->netio) {
185        free(dsc);
186        return NULL;
187    }
188
189    if (dialog_recv(dsc) < 0) {
190        netio_close(dsc->netio);
191        free(dsc);
192        return NULL;
193    }
194
195    dsc->error = 0;
196    dsc->spec = NULL;
197    *dsc->reply = 0;
198
199    return dsc;
200}
201
202
203static void atnet_close(void *handle)
204{
205    struct atnet_dsc *dsc = handle;
206
207    netio_close(dsc->netio);
208    free(dsc->spec);
209}
210
211
212/* ----- driver specification ---------------------------------------------- */
213
214
215static const char *atnet_driver_spec(void *handle)
216{
217    struct atnet_dsc *dsc = handle;
218
219    if (dialog(dsc, "SPEC") < 0) {
220        dsc->error = 1;
221        return NULL;
222    }
223    free(dsc->spec);
224    dsc->spec = strdup(dsc->reply+1);
225    if (!dsc->spec) {
226        perror("strdup");
227        exit(1);
228    }
229    return dsc->spec;
230}
231
232
233/* ----- device mode ------------------------------------------------------- */
234
235
236static void atnet_reset(void *handle)
237{
238    struct atnet_dsc *dsc = handle;
239
240    if (dsc->error)
241        return;
242    if (dialog(dsc, "RESET") < 0)
243        dsc->error = 1;
244}
245
246
247static void atnet_reset_rf(void *handle)
248{
249    struct atnet_dsc *dsc = handle;
250
251    if (dsc->error)
252        return;
253    if (dialog(dsc, "RESET_RF") < 0)
254        dsc->error = 1;
255}
256
257
258static void atnet_test_mode(void *handle)
259{
260    struct atnet_dsc *dsc = handle;
261
262    if (dsc->error)
263        return;
264    if (dialog(dsc, "TEST") < 0)
265        dsc->error = 1;
266}
267
268
269static void atnet_slp_tr(void *handle, int on, int pulse)
270{
271    struct atnet_dsc *dsc = handle;
272
273    if (dsc->error)
274        return;
275    if (dialog(dsc, "SLP_TR %d %d", on, pulse) < 0)
276        dsc->error = 1;
277}
278
279
280/* ----- register access --------------------------------------------------- */
281
282
283static void atnet_reg_write(void *handle, uint8_t reg, uint8_t value)
284{
285    struct atnet_dsc *dsc = handle;
286
287    if (dsc->error)
288        return;
289    if (dialog(dsc, "SET 0x%02x 0x%02x", reg, value) < 0)
290        dsc->error = 1;
291}
292
293
294static uint8_t atnet_reg_read(void *handle, uint8_t reg)
295{
296    struct atnet_dsc *dsc = handle;
297    unsigned long value;
298    char *end;
299
300    if (dsc->error)
301        return;
302    if (dialog(dsc, "GET 0x%02x", reg) < 0) {
303        dsc->error = 1;
304        return 0;
305    }
306    value = strtoul(dsc->reply+1, &end, 0);
307    if (*end || value > 255) {
308        fprintf(stderr, "invalid response \"%s\"\n", dsc->reply+1);
309        dsc->error = 1;
310        return 0;
311    }
312    return value;
313}
314
315
316/* ----- frame buffer access ----------------------------------------------- */
317
318
319static void atnet_buf_write(void *handle, const void *buf, int size)
320{
321    struct atnet_dsc *dsc = handle;
322    char tmp[20];
323    int n;
324
325    if (dsc->error)
326        return;
327
328    n = snprintf(tmp, sizeof(tmp), "WRITE %d ", size);
329    assert(n < sizeof(tmp));
330    if (netio_write(dsc->netio, tmp, n) < 0) {
331        dsc->error = 1;
332                return;
333    }
334
335    if (netio_write(dsc->netio, buf, size) < 0) {
336        dsc->error = 1;
337                return;
338    }
339
340    if (netio_write(dsc->netio, "\n", 1) < 0) {
341        dsc->error = 1;
342                return;
343    }
344
345    if (dialog_recv(dsc) < 0)
346        dsc->error = 1;
347}
348
349
350static int atnet_buf_read(void *handle, void *buf, int size)
351{
352    struct atnet_dsc *dsc = handle;
353    uint8_t tmp[200];
354    int n, got = 0;
355    unsigned long len = 0;
356    char *end;
357
358    if (dsc->error)
359        return -1;
360
361    if (dialog_send(dsc, "READ") < 0)
362        goto fail;
363
364    n = netio_read_until(dsc->netio, " ", tmp, sizeof(tmp)-1, NULL);
365    if (n < 0)
366        goto fail;
367    tmp[n] = 0;
368    if (*tmp == '-') {
369        fprintf(stderr, "%s ", tmp+1);
370        n = netio_read_until(dsc->netio,
371            "\n", tmp, sizeof(tmp)-1, NULL);
372        if (n >= 0) {
373            tmp[n] = 0;
374            fprintf(stderr, "%s\n", tmp);
375        }
376        goto fail;
377    }
378    if (*tmp != '+' || n < 2) /* +0<spc> */
379        goto invalid;
380    len = strtoul(tmp+1, &end, 0);
381    if (*end)
382        goto invalid;
383    if (len > size) {
384        fprintf(stderr, "buffer overflow\n");
385        goto fail;
386    }
387
388    got = netio_read(dsc->netio, buf, len);
389    if (got < 0)
390        goto fail;
391
392    if (netio_getc(dsc->netio, tmp) < 0)
393        goto fail;
394    if (*tmp == '\n')
395        return len;
396
397invalid:
398    fprintf(stderr, "invalid reponse\n");
399fail:
400    dsc->error = 1;
401    return -1;
402}
403
404
405/* ----- SRAM access ------------------------------------------------------- */
406
407
408static void atnet_sram_write(void *handle, uint8_t addr, uint8_t value)
409{
410    struct atnet_dsc *dsc = handle;
411
412    if (dsc->error)
413        return;
414    if (dialog(dsc, "SETRAM 0x%02x 0x%02x", addr, value) < 0)
415        dsc->error = 1;
416}
417
418
419static uint8_t atnet_sram_read(void *handle, uint8_t addr)
420{
421    struct atnet_dsc *dsc = handle;
422    unsigned long value;
423    char *end;
424
425    if (dsc->error)
426        return;
427    if (dialog(dsc, "GETRAM 0x%02x", addr) < 0) {
428        dsc->error = 1;
429        return 0;
430    }
431    value = strtoul(dsc->reply+1, &end, 0);
432    if (*end || value > 255) {
433        fprintf(stderr, "invalid response \"%s\"\n", dsc->reply+1);
434        dsc->error = 1;
435        return 0;
436    }
437    return value;
438}
439
440
441/* ----- RF interrupt ------------------------------------------------------ */
442
443
444int atnet_interrupt_wait(void *handle, int timeout_ms)
445{
446    struct atnet_dsc *dsc = handle;
447    unsigned long value;
448    char *end;
449
450    if (dsc->error)
451        return 0;
452    if (dialog(dsc, "WAIT %d", timeout_ms) < 0)
453        return 0;
454    value = strtoul(dsc->reply+1, &end, 0);
455    if (*end || value > 0xff) {
456        fprintf(stderr, "invalid response \"%s\"\n", dsc->reply+1);
457        dsc->error = 1;
458        return 0;
459    }
460    return value;
461}
462
463
464/* ----- CLKM handling ----------------------------------------------------- */
465
466
467static int atnet_set_clkm(void *handle, int mhz)
468{
469    struct atnet_dsc *dsc = handle;
470
471    return dialog(dsc, "CLKM %d", mhz) == 0;
472}
473
474
475/* ----- driver interface -------------------------------------------------- */
476
477
478struct atrf_driver atnet_driver = {
479    .name = "net",
480    .open = atnet_open,
481    .close = atnet_close,
482    .driver_spec = atnet_driver_spec,
483    .error = atnet_error,
484    .clear_error = atnet_clear_error,
485    .reset = atnet_reset,
486    .reset_rf = atnet_reset_rf,
487    .test_mode = atnet_test_mode,
488    .slp_tr = atnet_slp_tr,
489    .set_clkm = atnet_set_clkm,
490    .reg_write = atnet_reg_write,
491    .reg_read = atnet_reg_read,
492    .buf_write = atnet_buf_write,
493    .buf_read = atnet_buf_read,
494    .sram_write = atnet_sram_write,
495    .sram_read = atnet_sram_read,
496    .interrupt_wait = atnet_interrupt_wait,
497};
498

Archive Download this file



interactive