Root/atusb/fw/atusb/ep0.c

Source at commit 96b6a50b3a1f9f889e1a59631bc17836511aaf06 created 8 years 11 months ago.
By Werner Almesberger, The Great ATSPI Renaming, part 2: rename ATSPI_* identifiers to ATUSB_*
1/*
2 * atspi/ep0.c - EP0 extension protocol
3 *
4 * Written 2008-2010 by Werner Almesberger
5 * Copyright 2008-2010 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 <stdint.h>
15
16#ifndef NULL
17#define NULL 0
18#endif
19
20#include "regs.h"
21//#include "uart.h"
22#include "usb.h"
23#include "atusb/ep0.h"
24#include "at86rf230.h"
25#include "version.h"
26
27
28extern void reset_rf(void);
29extern void test_mode(void);
30
31
32#define debug(...)
33#define error(...)
34
35
36/*
37 * SDCC 2.8.0 had a number of code generation bugs that appeared in the big
38 * switch statement of my_setup. SDCC_FORCE_UPDATE forced the value of the
39 * "size" variable to be written to memory. This work-around doesn't seem
40 * to be necessary with 2.9.0, but we keep it around, just in case.
41 *
42 * Unfortunately, the setup->bRequest garbling bug is still with us. Without
43 * the evaluation forced with SDCC_FORCE_EVAL, sdcc gets confused about the
44 * value of setup->bRequest and then rejects all SETUP requests.
45 */
46
47#define SDCC_FORCE_EVAL(type, value) \
48    do { \
49    static volatile type foo; \
50    foo = value; \
51    } while (0)
52
53#define SDCC_FORCE_UPDATE(type, var) \
54    do { \
55    volatile type foo; \
56    foo = var; \
57    var = foo; \
58    } while (0)
59
60
61static const uint8_t id[] = { EP0ATUSB_MAJOR, EP0ATUSB_MINOR, HW_TYPE };
62static __xdata uint8_t buf[MAX_PSDU+3]; /* command, PHDR, and LQI */
63static uint8_t size;
64
65
66static void spi_send(uint8_t v)
67{
68    uint8_t mask;
69
70    for (mask = 0x80; mask; mask >>= 1) {
71        MOSI = !!(v & mask);
72        SCLK = 1;
73        SCLK = 0;
74    }
75}
76
77
78static uint8_t spi_recv(void)
79{
80    uint8_t res = 0;
81    uint8_t i;
82
83    for (i = 0; i != 8; i++) {
84        res = (res << 1) | MISO;
85        SCLK = 1;
86        SCLK = 0;
87    }
88    return res;
89}
90
91
92static void do_buf_write(void *user)
93{
94    uint8_t i;
95
96    user; /* suppress warning */
97    nSS = 0;
98    for (i = 0; i != size; i++)
99        spi_send(buf[i]);
100    nSS = 1;
101}
102
103
104#define BUILD_OFFSET 7 /* '#' plus "65535" plus ' ' */
105
106
107static __bit my_setup(struct setup_request *setup) __reentrant
108{
109    unsigned tmp;
110    uint8_t i;
111
112    switch (setup->bmRequestType | setup->bRequest << 8) {
113    case ATUSB_FROM_DEV(ATUSB_ID):
114        debug("ATUSB_ID\n");
115        if (setup->wLength > 3)
116            return 0;
117        usb_send(&ep0, id, setup->wLength, NULL, NULL);
118        return 1;
119    case ATUSB_FROM_DEV(ATUSB_BUILD):
120        debug("ATUSB_BUILD\n");
121        tmp = build_number;
122        for (i = BUILD_OFFSET-2; tmp; i--) {
123            buf[i] = (tmp % 10)+'0';
124            tmp /= 10;
125        }
126        buf[i] = '#';
127        buf[BUILD_OFFSET-1] = ' ';
128        for (size = 0; build_date[size]; size++)
129            buf[BUILD_OFFSET+size] = build_date[size];
130        size += BUILD_OFFSET-i;
131        SDCC_FORCE_EVAL(uint8_t, setup->bRequest);
132        if (size > setup->wLength)
133            return 0;
134        usb_send(&ep0, buf+i, size, NULL, NULL);
135        return 1;
136
137    case ATUSB_TO_DEV(ATUSB_RESET):
138        debug("ATUSB_RESET\n");
139        RSTSRC = SWRSF;
140        while (1);
141
142    case ATUSB_TO_DEV(ATUSB_RF_RESET):
143        debug("ATUSB_RF_RESET\n");
144        reset_rf();
145        return 1;
146
147    case ATUSB_FROM_DEV(ATUSB_POLL_INT):
148        debug("ATUSB_POLL_INT\n");
149        if (setup->wLength < 1)
150            return 0;
151        *buf = IRQ_RF;
152        usb_send(&ep0, buf, 1, NULL, NULL);
153        return 1;
154
155    case ATUSB_TO_DEV(ATUSB_TEST):
156        debug("ATUSB_TEST\n");
157        test_mode();
158        return 1;
159
160    case ATUSB_TO_DEV(ATUSB_REG_WRITE):
161        debug("ATUSB_REG_WRITE\n");
162        nSS = 0;
163        spi_send(AT86RF230_REG_WRITE | setup->wIndex);
164        spi_send(setup->wValue);
165        nSS = 1;
166        return 1;
167    case ATUSB_FROM_DEV(ATUSB_REG_READ):
168        debug("ATUSB_REG_READ\n");
169        nSS = 0;
170        spi_send(AT86RF230_REG_READ | setup->wIndex);
171        *buf = spi_recv();
172        nSS = 1;
173        usb_send(&ep0, buf, 1, NULL, NULL);
174        return 1;
175
176    case ATUSB_TO_DEV(ATUSB_BUF_WRITE):
177        debug("ATUSB_BUF_WRITE\n");
178        if (setup->wLength < 1)
179            return 0;
180        if (setup->wLength > MAX_PSDU)
181            return 0;
182        buf[0] = AT86RF230_BUF_WRITE;
183        buf[1] = setup->wLength;
184        size = setup->wLength+2;
185        usb_recv(&ep0, buf+2, setup->wLength, do_buf_write, NULL);
186        return 1;
187    case ATUSB_FROM_DEV(ATUSB_BUF_READ):
188        debug("ATUSB_BUF_READ\n");
189        if (setup->wLength < 2) /* PHR+LQI */
190            return 0;
191        if (setup->wLength > MAX_PSDU+2) /* PHR+PSDU+LQI */
192            return 0;
193        nSS = 0;
194        spi_send(AT86RF230_BUF_READ);
195        size = spi_recv();
196        if (size >= setup->wLength)
197            size = setup->wLength-1;
198        for (i = 0; i != size+1; i++)
199            buf[i] = spi_recv();
200        nSS = 1;
201        usb_send(&ep0, buf, size+1, NULL, NULL);
202        return 1;
203
204    case ATUSB_TO_DEV(ATUSB_SRAM_WRITE):
205        debug("ATUSB_SRAM_WRITE\n");
206        if (setup->wIndex > SRAM_SIZE)
207            return 0;
208        if (setup->wIndex+setup->wLength > SRAM_SIZE)
209            return 0;
210        buf[0] = AT86RF230_SRAM_WRITE;
211        buf[1] = setup->wIndex;
212        size = setup->wLength+2;
213        usb_recv(&ep0, buf+2, setup->wLength, do_buf_write, NULL);
214        return 1;
215    case ATUSB_TO_DEV(ATUSB_SRAM_READ):
216        debug("ATUSB_SRAM_READ\n");
217        if (setup->wIndex > SRAM_SIZE)
218            return 0;
219        if (setup->wIndex+setup->wLength > SRAM_SIZE)
220            return 0;
221        nSS = 0;
222        spi_send(AT86RF230_SRAM_READ);
223        spi_send(setup->wIndex);
224        for (i = 0; i != size; i++)
225            buf[i] = spi_recv();
226        nSS = 1;
227        usb_send(&ep0, buf, size, NULL, NULL);
228        return 1;
229
230    default:
231        error("Unrecognized SETUP: 0x%02x 0x%02x ...\n",
232            setup->bmRequestType, setup->bRequest);
233        return 0;
234    }
235}
236
237
238void ep0_init(void)
239{
240    user_setup = my_setup;
241}
242

Archive Download this file



interactive