2 * fw/ep0.c - EP0 extension protocol
4 * Written 2008-2011, 2013 by Werner Almesberger
5 * Copyright 2008-2011, 2013 Werner Almesberger
6 * Copyright 2015-2016 Stefan Schmidt
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
20 #include <avr/eeprom.h>
22 #define F_CPU 8000000UL
23 #include <util/delay.h>
32 #include "at86rf230.h"
33 #include "atusb/ep0.h"
41 #define HW_TYPE ATUSB_HW_TYPE_110131
45 #define HW_TYPE ATUSB_HW_TYPE_RZUSB
49 #define HW_TYPE ATUSB_HW_TYPE_HULUSB
55 #define debug(FORMAT,args...) printf(FORMAT,##args)
56 #define error(FORMAT,args...) printf(FORMAT,##args)
63 static const uint8_t id[] = { EP0ATUSB_MAJOR, EP0ATUSB_MINOR, HW_TYPE };
64 static uint8_t buf[MAX_PSDU+3]; /* command, PHDR, and LQI */
68 static void do_eeprom_write(void *user)
72 for (i = 0; i < size; i++)
73 eeprom_update_byte((uint8_t*)i, buf[i]);
76 static void do_buf_write(void *user)
81 for (i = 0; i != size; i++)
87 #define BUILD_OFFSET 7 /* '#' plus "65535" plus ' ' */
90 static bool my_setup(const struct setup_request *setup)
92 uint16_t req = setup->bmRequestType | setup->bRequest << 8;
98 case ATUSB_FROM_DEV(ATUSB_ID):
100 if (setup->wLength > 3)
102 usb_send(&eps[0], id, setup->wLength, NULL, NULL);
104 case ATUSB_FROM_DEV(ATUSB_BUILD):
105 debug("ATUSB_BUILD\n");
107 for (i = BUILD_OFFSET-2; tmp; i--) {
108 buf[i] = (tmp % 10)+'0';
112 buf[BUILD_OFFSET-1] = ' ';
113 for (size = 0; build_date[size]; size++)
114 buf[BUILD_OFFSET+size] = build_date[size];
115 size += BUILD_OFFSET-i;
116 if (size > setup->wLength)
118 usb_send(&eps[0], buf+i, size, NULL, NULL);
121 case ATUSB_TO_DEV(ATUSB_RESET):
122 debug("ATUSB_RESET\n");
126 case ATUSB_TO_DEV(ATUSB_RF_RESET):
127 debug("ATUSB_RF_RESET\n");
130 //ep_send_zlp(EP_CTRL);
133 case ATUSB_FROM_DEV(ATUSB_POLL_INT):
134 debug("ATUSB_POLL_INT\n");
135 if (setup->wLength < 1)
138 usb_send(&eps[0], buf, 1, NULL, NULL);
141 case ATUSB_FROM_DEV(ATUSB_TIMER):
142 debug("ATUSB_TIMER\n");
143 size = setup->wLength;
144 if (size > sizeof(tmp64))
145 size = sizeof(tmp64);
146 tmp64 = timer_read();
147 memcpy(buf, &tmp64, sizeof(tmp64));
148 usb_send(&eps[0], buf, size, NULL, NULL);
151 case ATUSB_FROM_DEV(ATUSB_GPIO):
152 debug("ATUSB_GPIO\n");
153 if (setup->wLength < 3)
155 if (!gpio(setup->wIndex, setup->wValue, setup->wValue >> 8,
156 setup->wIndex >> 8, buf))
158 usb_send(&eps[0], buf, 3, NULL, NULL);
160 case ATUSB_TO_DEV(ATUSB_GPIO_CLEANUP):
164 case ATUSB_TO_DEV(ATUSB_SLP_TR):
165 debug("ATUSB_SLP_TR\n");
169 case ATUSB_TO_DEV(ATUSB_REG_WRITE):
170 debug("ATUSB_REG_WRITE\n");
172 spi_send(AT86RF230_REG_WRITE | setup->wIndex);
173 spi_send(setup->wValue);
175 //ep_send_zlp(EP_CTRL);
177 case ATUSB_FROM_DEV(ATUSB_REG_READ):
178 debug("ATUSB_REG_READ\n");
180 spi_send(AT86RF230_REG_READ | setup->wIndex);
183 usb_send(&eps[0], buf, 1, NULL, NULL);
186 case ATUSB_TO_DEV(ATUSB_BUF_WRITE):
187 debug("ATUSB_BUF_WRITE\n");
188 if (setup->wLength < 1)
190 if (setup->wLength > MAX_PSDU)
192 buf[0] = AT86RF230_BUF_WRITE;
193 buf[1] = setup->wLength;
194 size = setup->wLength+2;
195 usb_recv(&eps[0], buf+2, setup->wLength, do_buf_write, NULL);
197 case ATUSB_FROM_DEV(ATUSB_BUF_READ):
198 debug("ATUSB_BUF_READ\n");
199 if (setup->wLength < 2) /* PHR+LQI */
201 if (setup->wLength > MAX_PSDU+2) /* PHR+PSDU+LQI */
204 spi_send(AT86RF230_BUF_READ);
206 if (size >= setup->wLength)
207 size = setup->wLength-1;
208 for (i = 0; i != size+1; i++)
211 usb_send(&eps[0], buf, size+1, NULL, NULL);
214 case ATUSB_TO_DEV(ATUSB_SRAM_WRITE):
215 debug("ATUSB_SRAM_WRITE\n");
216 if (setup->wIndex > SRAM_SIZE)
218 if (setup->wIndex+setup->wLength > SRAM_SIZE)
220 buf[0] = AT86RF230_SRAM_WRITE;
221 buf[1] = setup->wIndex;
222 size = setup->wLength+2;
223 usb_recv(&eps[0], buf+2, setup->wLength, do_buf_write, NULL);
225 case ATUSB_FROM_DEV(ATUSB_SRAM_READ):
226 debug("ATUSB_SRAM_READ\n");
227 if (setup->wIndex > SRAM_SIZE)
229 if (setup->wIndex+setup->wLength > SRAM_SIZE)
232 spi_send(AT86RF230_SRAM_READ);
233 spi_send(setup->wIndex);
234 for (i = 0; i != setup->wLength; i++)
237 usb_send(&eps[0], buf, setup->wLength, NULL, NULL);
240 case ATUSB_TO_DEV(ATUSB_SPI_WRITE):
241 size = setup->wLength+2;
242 if (size > sizeof(buf))
244 buf[0] = setup->wValue;
245 buf[1] = setup->wIndex;
247 usb_recv(&eps[0], buf+2, setup->wLength,
252 case ATUSB_FROM_DEV(ATUSB_SPI_WRITE2_SYNC):
254 spi_send(setup->wValue);
255 spi_send(setup->wIndex);
259 usb_send(&eps[0], buf, 1, NULL, NULL);
262 case ATUSB_FROM_DEV(ATUSB_SPI_READ1):
263 case ATUSB_FROM_DEV(ATUSB_SPI_READ2):
265 spi_send(setup->wValue);
266 if (req == ATUSB_FROM_DEV(ATUSB_SPI_READ2))
267 spi_send(setup->wIndex);
268 for (i = 0; i != setup->wLength; i++)
271 usb_send(&eps[0], buf, setup->wLength, NULL, NULL);
274 case ATUSB_TO_DEV(ATUSB_RX_MODE):
275 return mac_rx(setup->wValue);
276 case ATUSB_TO_DEV(ATUSB_TX):
277 return mac_tx(setup->wValue, setup->wIndex, setup->wLength);
278 case ATUSB_TO_DEV(ATUSB_EUI64_WRITE):
279 debug("ATUSB_EUI64_WRITE\n");
280 usb_recv(&eps[0], buf, setup->wLength, do_eeprom_write, NULL);
285 case ATUSB_FROM_DEV(ATUSB_EUI64_READ):
286 debug("ATUSB_EUI64_READ\n");
287 eeprom_read_block(buf, (const void*)0, 8);
288 usb_send(&eps[0], buf, 8, NULL, NULL);
292 error("Unrecognized SETUP: 0x%02x 0x%02x ...\n",
293 setup->bmRequestType, setup->bRequest);
299 static bool my_dfu_setup(const struct setup_request *setup)
301 switch (setup->bmRequestType | setup->bRequest << 8) {
302 case DFU_TO_DEV(DFU_DETACH):
303 /* @@@ should use wTimeout */
304 dfu.state = appDETACH;
307 return dfu_setup_common(setup);
312 static void my_set_interface(int nth)
315 user_setup = my_dfu_setup;
316 user_get_descriptor = dfu_my_descr;
319 user_setup = my_setup;
320 user_get_descriptor = sernum_get_descr;
325 static void my_reset(void)
327 if (dfu.state == appDETACH)
334 user_setup = my_setup;
335 user_set_interface = my_set_interface;
337 user_reset = my_reset;