Root/tools/atrf-gpio/atusb.c

1/*
2 * atrf-gpio/atusb.c - ATUSB-specific GPIO driver
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
17#include <usb.h>
18
19#include "atusb/ep0.h"
20#include "atrf.h"
21
22#include "atrf-gpio.h"
23
24
25#define FROM_DEV ATUSB_FROM_DEV(0)
26#define TO_DEV ATUSB_TO_DEV(0)
27
28
29static const char *name[24] = {
30    "PB0", "PB1/P16", "PB2/P15", "PB3/P14",
31    "PB4/SLP_TR", "PB5", "PB6/LED", "PB7",
32    "PC0", "PC1/P13", "PC2", "PC3(NC)",
33    "PC4", "PC5", "PC6", "PC7/nRST_RF",
34    "PD0/IRQ_RF", "PD1/nSS", "PD2/MISO", "PD3/MOSI",
35    "PD4", "PD5/SCLK", "PD6", "PD7"
36};
37
38
39static struct atrf_dsc *orig_dsc;
40static uint8_t orig_data[3], orig_dir[3];
41
42
43static void dump_port(int port, uint8_t data, uint8_t dir, uint8_t mask)
44{
45    int i;
46
47    fprintf(stderr, "name\t\tcfg\n");
48    for (i = 0; i != 8; i++) {
49        int bit = 1 << (i & 7);
50
51        fprintf(stderr, "%-16s%c\n", name[port*8+i],
52            mask & bit ? dir & bit ? data & bit ? '1' : '0' :
53            data & bit ? 'R' : 'Z' : 'x');
54    }
55}
56
57
58static uint8_t gpio(struct atrf_dsc *dsc,
59    uint8_t port, uint8_t *data, uint8_t *dir, uint8_t mask)
60{
61    uint8_t buf[3];
62    int res;
63
64    res = usb_control_msg(atrf_usb_handle(dsc),
65            FROM_DEV, ATUSB_GPIO, *dir << 8 | *data, mask << 8 | port,
66        (void *) buf, sizeof(buf), 1000);
67    if (res < 0) {
68        dump_port(port-1, *data, *dir, mask);
69        fprintf(stderr, "ATUSB_GPIO: %s\n", usb_strerror());
70        _exit(1);
71    }
72    if (res != 3) {
73        fprintf(stderr, "ATUSB_GPIO: expected 3 bytes, got %d\n", res);
74        _exit(1);
75    }
76    *data = buf[1];
77    *dir = buf[2];
78    return buf[0];
79}
80
81
82static void dump(const uint8_t *data, const uint8_t *dir,
83    const uint8_t *expect, const uint8_t *got, const uint8_t *read)
84{
85    int i;
86
87    fprintf(stderr, "name\t\tcfg exp got\n");
88    for (i = 0; i != 24; i++) {
89        int port = i >> 3;
90        int bit = 1 << (i & 7);
91
92        fprintf(stderr, "%-16s%c %c %d", name[i],
93            dir[port] & bit ? data[port] & bit ? '1' : '0' :
94            data[port] & bit ? 'R' : 'Z',
95            read[port] & bit ? expect[port] & bit ? '1' : '0' : '-',
96            !!(got[port] & bit));
97        if ((expect[port] ^ got[port]) & read[port] & bit)
98            fprintf(stderr, "\t***");
99        fputc('\n', stderr);
100    }
101}
102
103
104/* ----- Decode and apply pattern ------------------------------------------ */
105
106
107static void restore_gpios(void)
108{
109    int i, res;
110
111    for (i = 0; i != 3; i++)
112        gpio(orig_dsc, i+1, orig_data+i, orig_dir+i, 0xff);
113
114    res = usb_control_msg(atrf_usb_handle(orig_dsc),
115        TO_DEV, ATUSB_GPIO_CLEANUP, 0, 0, NULL, 0, 1000);
116    if (res < 0) {
117        fprintf(stderr, "ATUSB_GPIO_CLEANUP: %s\n", usb_strerror());
118        _exit(1);
119    }
120}
121
122
123void do_atusb(struct atrf_dsc *dsc, const char *pattern, const char *next)
124{
125    static int first = 1;
126    const char *p;
127    int i, pin = 0;
128    uint8_t data[3], dir[3], mask[3], read[3], expect[3], got[3];
129    uint8_t bit;
130    int port;
131
132    data[0] = data[1] = data[2] = 0;
133    dir[0] = dir[1] = dir[2] = 0;
134    mask[0] = mask[1] = mask[2] = 0;
135    read[0] = read[1] = read[2] = 0;
136    expect[0] = expect[1] = expect[2] = 0;
137
138    if (first) {
139        orig_dsc = dsc;
140        for (i = 0; i != 3; i++)
141            gpio(dsc, i+1, orig_data+i, orig_dir+i, 0);
142        atexit(restore_gpios);
143        first = 0;
144    }
145
146    for (p = pattern; *p; p++) {
147        bit = 1 << (pin & 7);
148        port = pin >> 3;
149        switch (*p) {
150        case '1':
151            data[port] |= bit;
152            /* fall through */
153        case '0':
154            dir[port] |= bit;
155            mask[port] |= bit;
156            break;
157        case 'H':
158            expect[port] |= bit;
159            /* fall through */
160        case 'L':
161            read[port] |= bit;
162            /* fall through */
163        case 'Z':
164            data[port] |= bit;
165            mask[port] |= bit;
166            break;
167        case 'h':
168            expect[port] |= bit;
169            /* fall through */
170        case 'l':
171        case 'o':
172            read[port] |= bit;
173            /* fall through */
174        case 'z':
175            mask[port] |= bit;
176            break;
177        case 'x':
178            pin++;
179            continue;
180        default:
181            continue;
182        }
183        pin++;
184    }
185
186    for (i = 0; i <= port; i++)
187        got[i] = gpio(dsc, i+1, data+i, dir+i, mask[i]);
188    for (i = 0; i <= port; i++)
189        if ((got[i] & read[i]) != expect[i]) {
190            dump(data, dir, expect, got, read);
191            fprintf(stderr, "at \"%s\", next \"%s\"\n", pattern,
192                next);
193            exit(1);
194        }
195}
196

Archive Download this file



interactive