Root/ubbctl/ubbctl.c

1/*
2 * ubbctl.c - Set and query UBB signals
3 *
4 * Written 2013-2014 by Werner Almesberger
5 * Copyright 2013-2014 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#include <stddef.h>
14#include <stdint.h>
15#include <stdlib.h>
16#include <stdio.h>
17#include <unistd.h>
18#include <string.h>
19#include <strings.h> /* for strcasecmp, strncasecmp */
20
21#include <ubb/ubb.h>
22
23
24static struct pin {
25    const char *name;
26    uint32_t mask;
27} pins[] = {
28    { "nPWR", UBB_nPWR },
29    { "DAT2", UBB_DAT2 },
30    { "DAT3", UBB_DAT3 },
31    { "CMD", UBB_CMD },
32    { "CLK", UBB_CLK },
33    { "DAT0", UBB_DAT0 },
34    { "DAT1", UBB_DAT1 },
35    { NULL }
36};
37
38
39static void show_pins(void)
40{
41    const struct pin *p;
42    int pin, set;
43
44    for (p = pins; p->name; p++) {
45        printf("%s%s=", p == pins ? "" : " ", p->name);
46        pin = PIN(p->mask);
47        if (PDFUN & p->mask) {
48            putchar('F');
49            if (PDSEL & p->mask)
50                putchar('b');
51        } else if (PDSEL & p->mask) {
52            putchar('I');
53            if (PDTRG & p->mask) {
54                if (PDDIR & p->mask)
55                    putchar('r');
56                else
57                    putchar('f');
58            } else {
59                if (PDDIR & p->mask)
60                    putchar('h');
61                else
62                    putchar('l');
63            }
64            if (!(PDPULL & p->mask))
65                putchar('R');
66        } else if (PDDIR & p->mask) {
67            set = !!(PDDAT & p->mask);
68            if (pin != set)
69                printf("%d!", set);
70            
71        } else {
72            putchar(PDPULL & p->mask ? 'Z' : 'R');
73        }
74        printf("%d", pin);
75    }
76}
77
78
79/*
80 * The order of the IO operations below is important to avoid glitches.
81 */
82
83static int setup_pin(const char *s, int doit)
84{
85    static const char trigger[] = "lhfrLHFR";
86    const struct pin *p;
87    const char *eq, *t;
88    uint8_t trig;
89
90    if (!strcasecmp(s, "on"))
91        s = "nPWR=0";
92    else if (!strcasecmp(s, "off"))
93        s = "nPWR=1";
94
95    eq = strchr(s, '=');
96    if (!eq)
97        return 0;
98
99    for (p = pins; p->name; p++)
100        if (strlen(p->name) == eq-s && !strncasecmp(p->name, s, eq-s))
101            break;
102    if (!p->name)
103        return 0;
104
105    if (!strcasecmp(eq+1, "f") || !strcasecmp(eq+1, "fa")) {
106        if (doit) {
107            PDFUNS = p->mask;
108            PDSELC = p->mask;
109        }
110        return 1;
111    }
112    if (!strcasecmp(eq+1, "fb")) {
113        if (doit) {
114            PDFUNS = p->mask;
115            PDSELS = p->mask;
116        }
117        return 1;
118    }
119    if (!strcmp(eq+1, "0")) {
120        if (doit) {
121            PDDATC = p->mask;
122            PDDIRS = p->mask;
123            PDFUNC = p->mask;
124        }
125        return 1;
126    }
127    if (!strcmp(eq+1, "1")) {
128        if (doit) {
129            PDDATS = p->mask;
130            PDDIRS = p->mask;
131            PDFUNC = p->mask;
132        }
133        return 1;
134    }
135    if (!strcasecmp(eq+1, "r")) {
136        if (doit) {
137            PDPULLC = p->mask;
138            PDDIRC = p->mask;
139            PDFUNC = p->mask;
140            PDSELC = p->mask;
141        }
142        return 1;
143    }
144    if (!strcasecmp(eq+1, "z")) {
145        if (doit) {
146            PDPULLS = p->mask;
147            PDDIRC = p->mask;
148            PDFUNC = p->mask;
149            PDSELC = p->mask;
150        }
151        return 1;
152    }
153    if (eq[1] != 'i' && eq[1] != 'I')
154        return 0;
155
156    t = strchr(trigger, eq[2]);
157    if (!t || !*t)
158        return 0;
159
160    if (!eq[3] || eq[3] == 'z' || eq[3] == 'Z') {
161        if (doit)
162            PDPULLS = p->mask;
163    } else if (eq[3] == 'r' || eq[3] == 'R') {
164        if (doit)
165            PDPULLC = p->mask;
166    } else {
167        return 0;
168    }
169
170    if (!doit)
171        return 1;
172
173    PDFUNC = p->mask;
174    PDSELS = p->mask;
175    trig = (t-trigger) & 3;
176    if (trig & 1)
177        PDDIRS = p->mask;
178    else
179        PDDIRC = p->mask;
180    if (trig & 2)
181        PDTRGS = p->mask;
182    else
183        PDTRGC = p->mask;
184
185    return 1;
186}
187
188
189static void usage(const char *name)
190{
191        fprintf(stderr,
192"usage: %s [-c]\n"
193" %s name=value|action ...\n\n"
194" -c continously update the pin status (until user interrupts)\n\n"
195"Names: nPWR, CMD, CLK, DAT0, DAT1, DAT2, DAT3\n"
196"Values: F, Fa, Fb, 0, 1, Z, R, Ir[R|Z], If[R|Z], Ih[R|Z], Il[R|Z]\n"
197"Actions: ON, OFF\n"
198    , name, name);
199    exit(1);
200}
201
202
203int main(int argc, char **argv)
204{
205    int continuous = 0;
206    int c, i;
207
208    while ((c = getopt(argc, argv, "c")) != EOF)
209        switch (c) {
210        case 'c':
211            continuous = 1;
212            break;
213        default:
214            usage(*argv);
215        }
216
217    if (argc != optind && continuous)
218        usage(*argv);
219
220    for (i = optind; i != argc; i++)
221        if (!setup_pin(argv[i], 0))
222            usage(*argv);
223
224    ubb_open(UBB_ALL);
225    if (argc == optind) {
226        if (continuous) {
227            while (1) {
228                show_pins();
229                printf("%*s\r", sizeof(pins)/sizeof(*pins)*2,
230                    "");
231                fflush(stdout);
232                usleep(200*1000);
233            }
234        } else {
235            show_pins();
236            putchar('\n');
237        }
238    } else {
239        for (i = optind; i != argc; i++)
240            setup_pin(argv[i], 1);
241    }
242    return 0;
243}
244

Archive Download this file

Branches:
master



interactive