Root/tools/lib/atrf.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 * lib/atrf.c - ATRF access functions library
3 *
4 * Written 2010-2011 by Werner Almesberger
5 * Copyright 2010-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 <string.h>
17
18#include "at86rf230.h"
19
20#include "driver.h"
21#include "atrf.h"
22
23
24struct atrf_dsc {
25    const struct atrf_driver *driver;
26    void *handle;
27    char *spec;
28    enum atrf_chip_id chip_id;
29};
30
31
32static const struct atrf_driver *drivers[] = {
33#ifdef HAVE_BEN
34    &atben_driver,
35#endif
36#ifdef HAVE_USB
37    &atusb_driver,
38#endif
39    &atnet_driver,
40    NULL
41};
42
43
44void *atrf_usb_handle(struct atrf_dsc *dsc)
45{
46#ifdef HAVE_USB
47    if (dsc->driver == &atusb_driver)
48        return atusb_dev_handle(dsc->handle);
49#endif
50    return NULL;
51}
52
53
54void *atrf_ben_regs(struct atrf_dsc *dsc)
55{
56#ifdef HAVE_BEN
57    if (dsc->driver == &atben_driver)
58        return atben_regs(dsc->handle);
59#endif
60    return NULL;
61}
62
63
64int atrf_error(struct atrf_dsc *dsc)
65{
66    return dsc->driver->error ? dsc->driver->error(dsc->handle) : 0;
67}
68
69
70int atrf_clear_error(struct atrf_dsc *dsc)
71{
72    return dsc->driver->clear_error ?
73        dsc->driver->clear_error(dsc->handle) : 0;
74}
75
76
77static enum atrf_chip_id identify(struct atrf_dsc *dsc)
78{
79    uint8_t part, version;
80
81    part = atrf_reg_read(dsc, REG_PART_NUM);
82    version = atrf_reg_read(dsc, REG_VERSION_NUM);
83    switch (part) {
84    case 2: /* AT86RF230 */
85        switch (version) {
86        case 1: /* rev A */
87        case 2: /* rev B */
88            return artf_at86rf230;
89        default:
90            return atrf_unknown_chip;
91        }
92        break;
93    case 3: /* AT86RF231 */
94        switch (version) {
95        case 2: /* rev A */
96            return artf_at86rf231;
97        default:
98            return atrf_unknown_chip;
99        }
100        break;
101    default:
102        return atrf_unknown_chip;
103    }
104    return atrf_unknown_chip;
105}
106
107
108const char *atrf_default_driver_name(void)
109{
110    return drivers[0] ? drivers[0]->name : "none";
111}
112
113
114static const struct atrf_driver *select_driver(const char *spec,
115    const char **opt)
116{
117    const struct atrf_driver **drv;
118    const char *end;
119    size_t len;
120
121    if (!*drivers) {
122        fprintf(stderr, "no drivers defined\n");
123        return NULL;
124    }
125
126    *opt = NULL;
127    if (!spec || !strcmp(spec, "default"))
128        return *drivers;
129    
130    end = strchr(spec, ':');
131    if (!end)
132        end = strchr(spec, 0);
133    len = end-spec;
134    for (drv = drivers; *drv; drv++)
135        if (!strncmp((*drv)->name, spec, len) &&
136            strlen((*drv)->name) == len)
137            break;
138    if (!*drv) {
139        fprintf(stderr, "no driver \"%.*s\" found\n", (int) len, spec);
140        return NULL;
141    }
142    if (*end)
143        *opt = end+1;
144    return *drv;
145}
146
147
148struct atrf_dsc *atrf_open(const char *spec)
149{
150    struct atrf_dsc *dsc;
151    const struct atrf_driver *driver;
152    const char *opt;
153    void *handle;
154
155    driver = select_driver(spec, &opt);
156    if (!driver)
157        return NULL;
158    handle = driver->open(opt);
159    if (!handle)
160        return NULL;
161    dsc = malloc(sizeof(*dsc));
162    if (!dsc) {
163        perror("malloc");
164        exit(1);
165    }
166    dsc->driver = driver;
167    dsc->handle = handle;
168    if (spec) {
169        dsc->spec = strdup(spec);
170        if (!dsc->spec) {
171            perror("strdup");
172            exit(1);
173        }
174    } else {
175        dsc->spec= NULL;
176    }
177    dsc->chip_id = identify(dsc);
178    return dsc;
179}
180
181
182void atrf_close(struct atrf_dsc *dsc)
183{
184    if (dsc->driver->close)
185        dsc->driver->close(dsc->handle);
186    free(dsc->spec);
187    free(dsc);
188}
189
190
191const char *atrf_driver_spec(struct atrf_dsc *dsc, int last)
192{
193    if (!dsc->spec)
194        return dsc->driver->name;
195    if (!last || !dsc->driver->driver_spec)
196        return dsc->spec;
197    return dsc->driver->driver_spec(dsc->handle);
198}
199
200
201void atrf_reset(struct atrf_dsc *dsc)
202{
203    if (dsc->driver->reset)
204        dsc->driver->reset(dsc->handle);
205}
206
207
208void atrf_reset_rf(struct atrf_dsc *dsc)
209{
210    dsc->driver->reset_rf(dsc->handle);
211}
212
213
214enum atrf_chip_id atrf_identify(struct atrf_dsc *dsc)
215{
216    return dsc->chip_id;
217}
218
219
220int atrf_test_mode(struct atrf_dsc *dsc)
221{
222    if (!dsc->driver->test_mode)
223        return 0;
224    dsc->driver->test_mode(dsc->handle);
225    return 1;
226}
227
228
229int atrf_slp_tr(struct atrf_dsc *dsc, int on)
230{
231    if (!dsc->driver->slp_tr)
232        return 0;
233    dsc->driver->slp_tr(dsc->handle, on);
234    return 1;
235}
236
237
238int atrf_set_clkm_generic(
239    void (*reg_write)(void *dsc, uint8_t reg, uint8_t value),
240    void *handle, int mhz)
241{
242    uint8_t clkm;
243
244    if (!mhz) {
245        reg_write(handle, REG_TRX_CTRL_0, 0); /* disable CLKM */
246        return 1;
247    }
248    switch (mhz) {
249    case 1:
250        clkm = CLKM_CTRL_1MHz;
251        break;
252    case 2:
253        clkm = CLKM_CTRL_2MHz;
254        break;
255    case 4:
256        clkm = CLKM_CTRL_4MHz;
257        break;
258    case 8:
259        clkm = CLKM_CTRL_8MHz;
260        break;
261    case 16:
262        clkm = CLKM_CTRL_16MHz;
263        break;
264    default:
265        fprintf(stderr, "unsupported CLKM frequency %d MHz\n", mhz);
266        return 0;
267    }
268    reg_write(handle, REG_TRX_CTRL_0,
269        (PAD_IO_8mA << PAD_IO_CLKM_SHIFT) | clkm);
270    return 1;
271}
272
273
274int atrf_set_clkm(struct atrf_dsc *dsc, int mhz)
275{
276    if (dsc->driver->set_clkm)
277        return dsc->driver->set_clkm(dsc->handle, mhz);
278    else
279        return atrf_set_clkm_generic(dsc->driver->reg_write,
280            dsc->handle, mhz);
281}
282
283
284void atrf_reg_write(struct atrf_dsc *dsc, uint8_t reg, uint8_t value)
285{
286    dsc->driver->reg_write(dsc->handle, reg, value);
287}
288
289
290uint8_t atrf_reg_read(struct atrf_dsc *dsc, uint8_t reg)
291{
292    return dsc->driver->reg_read(dsc->handle, reg);
293}
294
295
296void atrf_buf_write(struct atrf_dsc *dsc, const void *buf, int size)
297{
298    dsc->driver->buf_write(dsc->handle, buf, size);
299}
300
301
302int atrf_buf_read(struct atrf_dsc *dsc, void *buf, int size)
303{
304    return dsc->driver->buf_read(dsc->handle, buf, size);
305}
306
307
308int atrf_interrupt(struct atrf_dsc *dsc)
309{
310    return
311        dsc->driver->interrupt ? dsc->driver->interrupt(dsc->handle) : 1;
312}
313

Archive Download this file



interactive