Root/atusb/fw/ep0.c

Source at commit 0db361d49da04eef1f4dd77996450d54e900e083 created 9 years 3 months ago.
By Werner Almesberger, atusb/fw/Makefile (dfu): pass transfer size to hide DFU non-compliance
1/*
2 * fw/ep0.c - EP0 extension protocol
3 *
4 * Written 2008-2011 by Werner Almesberger
5 * Copyright 2008-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 <stdint.h>
15
16#include <avr/io.h>
17
18#ifndef NULL
19#define NULL 0
20#endif
21
22#include "usb.h"
23
24#include "at86rf230.h"
25#include "atusb/ep0.h"
26#include "version.h"
27#include "board.h"
28#include "spi.h"
29
30
31#define HW_TYPE HW_TYPE_110131
32
33#define debug(...)
34#define error(...)
35
36
37static const uint8_t id[] = { EP0ATUSB_MAJOR, EP0ATUSB_MINOR, HW_TYPE };
38static uint8_t buf[MAX_PSDU+3]; /* command, PHDR, and LQI */
39static uint8_t size;
40
41
42static void do_buf_write(void *user)
43{
44    uint8_t i;
45
46    spi_begin();
47    for (i = 0; i != size; i++)
48        spi_send(buf[i]);
49    spi_end();
50}
51
52
53#define BUILD_OFFSET 7 /* '#' plus "65535" plus ' ' */
54
55
56static int my_setup(const struct setup_request *setup)
57{
58    unsigned tmp;
59    uint8_t i;
60
61    switch (setup->bmRequestType | setup->bRequest << 8) {
62    case ATUSB_FROM_DEV(ATUSB_ID):
63        debug("ATUSB_ID\n");
64        if (setup->wLength > 3)
65            return 0;
66        usb_send(&eps[0], id, setup->wLength, NULL, NULL);
67        return 1;
68    case ATUSB_FROM_DEV(ATUSB_BUILD):
69        debug("ATUSB_BUILD\n");
70        tmp = build_number;
71        for (i = BUILD_OFFSET-2; tmp; i--) {
72            buf[i] = (tmp % 10)+'0';
73            tmp /= 10;
74        }
75        buf[i] = '#';
76        buf[BUILD_OFFSET-1] = ' ';
77        for (size = 0; build_date[size]; size++)
78            buf[BUILD_OFFSET+size] = build_date[size];
79        size += BUILD_OFFSET-i;
80        if (size > setup->wLength)
81            return 0;
82        usb_send(&eps[0], buf+i, size, NULL, NULL);
83        return 1;
84
85#ifdef NOTYET
86    case ATUSB_TO_DEV(ATUSB_RESET):
87        debug("ATUSB_RESET\n");
88        RSTSRC = SWRSF;
89        while (1);
90#endif
91
92    case ATUSB_TO_DEV(ATUSB_RF_RESET):
93        debug("ATUSB_RF_RESET\n");
94        reset_rf();
95        //ep_send_zlp(EP_CTRL);
96        return 1;
97
98    case ATUSB_FROM_DEV(ATUSB_POLL_INT):
99        debug("ATUSB_POLL_INT\n");
100        if (setup->wLength < 1)
101            return 0;
102        *buf = read_irq();
103        usb_send(&eps[0], buf, 1, NULL, NULL);
104        return 1;
105
106    case ATUSB_TO_DEV(ATUSB_REG_WRITE):
107        debug("ATUSB_REG_WRITE\n");
108        spi_begin();
109        spi_send(AT86RF230_REG_WRITE | setup->wIndex);
110        spi_send(setup->wValue);
111        spi_end();
112        //ep_send_zlp(EP_CTRL);
113        return 1;
114    case ATUSB_FROM_DEV(ATUSB_REG_READ):
115        debug("ATUSB_REG_READ\n");
116        spi_begin();
117        spi_send(AT86RF230_REG_READ | setup->wIndex);
118        *buf = spi_recv();
119        spi_end();
120        usb_send(&eps[0], buf, 1, NULL, NULL);
121        return 1;
122
123    case ATUSB_TO_DEV(ATUSB_BUF_WRITE):
124        debug("ATUSB_BUF_WRITE\n");
125        if (setup->wLength < 1)
126            return 0;
127        if (setup->wLength > MAX_PSDU)
128            return 0;
129        buf[0] = AT86RF230_BUF_WRITE;
130        buf[1] = setup->wLength;
131        size = setup->wLength+2;
132        usb_recv(&eps[0], buf+2, setup->wLength, do_buf_write, NULL);
133        return 1;
134    case ATUSB_FROM_DEV(ATUSB_BUF_READ):
135        debug("ATUSB_BUF_READ\n");
136        if (setup->wLength < 2) /* PHR+LQI */
137            return 0;
138        if (setup->wLength > MAX_PSDU+2) /* PHR+PSDU+LQI */
139            return 0;
140        spi_begin();
141        spi_send(AT86RF230_BUF_READ);
142        size = spi_recv();
143        if (size >= setup->wLength)
144            size = setup->wLength-1;
145        for (i = 0; i != size+1; i++)
146            buf[i] = spi_recv();
147        spi_end();
148        usb_send(&eps[0], buf, size+1, NULL, NULL);
149        return 1;
150
151    case ATUSB_TO_DEV(ATUSB_SRAM_WRITE):
152        debug("ATUSB_SRAM_WRITE\n");
153        if (setup->wIndex > SRAM_SIZE)
154            return 0;
155        if (setup->wIndex+setup->wLength > SRAM_SIZE)
156            return 0;
157        buf[0] = AT86RF230_SRAM_WRITE;
158        buf[1] = setup->wIndex;
159        size = setup->wLength+2;
160        usb_recv(&eps[0], buf+2, setup->wLength, do_buf_write, NULL);
161        return 1;
162    case ATUSB_TO_DEV(ATUSB_SRAM_READ):
163        debug("ATUSB_SRAM_READ\n");
164        if (setup->wIndex > SRAM_SIZE)
165            return 0;
166        if (setup->wIndex+setup->wLength > SRAM_SIZE)
167            return 0;
168        spi_begin();
169        spi_send(AT86RF230_SRAM_READ);
170        spi_send(setup->wIndex);
171        for (i = 0; i != size; i++)
172            buf[i] = spi_recv();
173        spi_end();
174        usb_send(&eps[0], buf, size, NULL, NULL);
175        return 1;
176
177    default:
178        error("Unrecognized SETUP: 0x%02x 0x%02x ...\n",
179            setup->bmRequestType, setup->bRequest);
180        return 0;
181    }
182}
183
184
185void ep0_init(void)
186{
187    user_setup = my_setup;
188}
189

Archive Download this file



interactive