IEEE 802.15.4 subsystem
Sign in or create your account | Project List | Help
IEEE 802.15.4 subsystem Git Source Tree
Root/
Source at commit 6969e7d6890c0b73b0100bcff775750f5d5b73c3 created 13 years 1 month ago. By Werner Almesberger, atusb/fw2/ep0.c: make commands needed for sending work | |
---|---|
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 | #include <avr/io.h> |
17 | //#ifndef NULL |
18 | //#define NULL 0 |
19 | //#endif |
20 | |
21 | //#include "regs.h" |
22 | //#include "uart.h" |
23 | //#include "usb.h" |
24 | |
25 | #include "freakusb.h" |
26 | |
27 | #include "at86rf230.h" |
28 | #include "atusb/ep0.h" |
29 | //#include "version.h" |
30 | #include "io.h" |
31 | #include "spi.h" |
32 | |
33 | |
34 | #define HW_TYPE 2 /* @@@ needs more work */ |
35 | static const char *build_date = "today"; |
36 | static unsigned build_number = 42; |
37 | |
38 | extern void reset_rf(void); |
39 | |
40 | |
41 | #define debug(...) |
42 | #define error(...) |
43 | |
44 | |
45 | static const uint8_t id[] = { EP0ATUSB_MAJOR, EP0ATUSB_MINOR, HW_TYPE }; |
46 | static uint8_t buf[MAX_PSDU+3]; /* command, PHDR, and LQI */ |
47 | static uint8_t size; |
48 | |
49 | |
50 | static void do_buf_write(void *user) |
51 | { |
52 | uint8_t i; |
53 | |
54 | spi_begin(); |
55 | for (i = 0; i != size; i++) |
56 | spi_send(buf[i]); |
57 | spi_end(); |
58 | } |
59 | |
60 | |
61 | static void do_usb_send(const uint8_t *data, int len) |
62 | { |
63 | int i; |
64 | |
65 | for (i = 0; i++ != len; data++) { |
66 | usb_buf_write(EP_CTRL, *data); |
67 | if (!(i % MAX_BUF_SZ)) |
68 | ep_write(EP_CTRL); |
69 | } |
70 | ep_write(EP_CTRL); |
71 | } |
72 | |
73 | |
74 | static void do_usb_recv(uint8_t *data, int len, void (*fn)(void *user), |
75 | void *user) |
76 | { |
77 | volatile usb_pcb_t *pcb = usb_pcb_get(); |
78 | uint8_t got; |
79 | |
80 | /* FreakUSB likes to do things this way. Looks dangerous ... */ |
81 | while (len) { |
82 | for (got = pcb->fifo[EP_CTRL].len; got; got--) { |
83 | *data++ = usb_buf_read(EP_CTRL); |
84 | len--; |
85 | } |
86 | } |
87 | pcb->flags &= ~(1 << SETUP_DATA_AVAIL); |
88 | fn(user); |
89 | ep_send_zlp(EP_CTRL); |
90 | } |
91 | |
92 | |
93 | #define usb_send(ep, buf, len, arg1, arg2) do_usb_send(buf, len) |
94 | #define usb_recv(ep, buf, len, fn, user) do_usb_recv(buf, len, fn, user) |
95 | |
96 | |
97 | #define BUILD_OFFSET 7 /* '#' plus "65535" plus ' ' */ |
98 | |
99 | |
100 | /* keep things as similar to the original as possible for now */ |
101 | #define setup_request req_t |
102 | #define setup req |
103 | #define bmRequestType type |
104 | #define bRequest req |
105 | #define wValue val |
106 | #define wLength len |
107 | #define wIndex idx |
108 | #define __reentrant |
109 | |
110 | |
111 | static int my_setup(struct setup_request *setup) __reentrant |
112 | { |
113 | unsigned tmp; |
114 | uint8_t i; |
115 | |
116 | switch (setup->bmRequestType | setup->bRequest << 8) { |
117 | case ATUSB_FROM_DEV(ATUSB_ID): |
118 | debug("ATUSB_ID\n"); |
119 | if (setup->wLength > 3) |
120 | return 0; |
121 | usb_send(&ep0, id, setup->wLength, NULL, NULL); |
122 | return 1; |
123 | case ATUSB_FROM_DEV(ATUSB_BUILD): |
124 | debug("ATUSB_BUILD\n"); |
125 | tmp = build_number; |
126 | for (i = BUILD_OFFSET-2; tmp; i--) { |
127 | buf[i] = (tmp % 10)+'0'; |
128 | tmp /= 10; |
129 | } |
130 | buf[i] = '#'; |
131 | buf[BUILD_OFFSET-1] = ' '; |
132 | for (size = 0; build_date[size]; size++) |
133 | buf[BUILD_OFFSET+size] = build_date[size]; |
134 | size += BUILD_OFFSET-i; |
135 | if (size > setup->wLength) |
136 | return 0; |
137 | usb_send(&ep0, buf+i, size, NULL, NULL); |
138 | return 1; |
139 | |
140 | #ifdef NOTYET |
141 | case ATUSB_TO_DEV(ATUSB_RESET): |
142 | debug("ATUSB_RESET\n"); |
143 | RSTSRC = SWRSF; |
144 | while (1); |
145 | #endif |
146 | |
147 | case ATUSB_TO_DEV(ATUSB_RF_RESET): |
148 | debug("ATUSB_RF_RESET\n"); |
149 | reset_rf(); |
150 | ep_send_zlp(EP_CTRL); |
151 | return 1; |
152 | |
153 | case ATUSB_FROM_DEV(ATUSB_POLL_INT): |
154 | debug("ATUSB_POLL_INT\n"); |
155 | if (setup->wLength < 1) |
156 | return 0; |
157 | *buf = 0;//IRQ_RF; |
158 | usb_send(&ep0, buf, 1, NULL, NULL); |
159 | return 1; |
160 | |
161 | case ATUSB_TO_DEV(ATUSB_REG_WRITE): |
162 | debug("ATUSB_REG_WRITE\n"); |
163 | spi_begin(); |
164 | spi_send(AT86RF230_REG_WRITE | setup->wIndex); |
165 | spi_send(setup->wValue); |
166 | spi_end(); |
167 | ep_send_zlp(EP_CTRL); |
168 | return 1; |
169 | case ATUSB_FROM_DEV(ATUSB_REG_READ): |
170 | debug("ATUSB_REG_READ\n"); |
171 | spi_begin(); |
172 | spi_send(AT86RF230_REG_READ | setup->wIndex); |
173 | *buf = spi_recv(); |
174 | spi_end(); |
175 | usb_send(&ep0, buf, 1, NULL, NULL); |
176 | return 1; |
177 | |
178 | case ATUSB_TO_DEV(ATUSB_BUF_WRITE): |
179 | debug("ATUSB_BUF_WRITE\n"); |
180 | if (setup->wLength < 1) |
181 | return 0; |
182 | if (setup->wLength > MAX_PSDU) |
183 | return 0; |
184 | buf[0] = AT86RF230_BUF_WRITE; |
185 | buf[1] = setup->wLength; |
186 | size = setup->wLength+2; |
187 | usb_recv(&ep0, buf+2, setup->wLength, do_buf_write, NULL); |
188 | return 1; |
189 | case ATUSB_FROM_DEV(ATUSB_BUF_READ): |
190 | debug("ATUSB_BUF_READ\n"); |
191 | if (setup->wLength < 2) /* PHR+LQI */ |
192 | return 0; |
193 | if (setup->wLength > MAX_PSDU+2) /* PHR+PSDU+LQI */ |
194 | return 0; |
195 | spi_begin(); |
196 | spi_send(AT86RF230_BUF_READ); |
197 | size = spi_recv(); |
198 | if (size >= setup->wLength) |
199 | size = setup->wLength-1; |
200 | for (i = 0; i != size+1; i++) |
201 | buf[i] = spi_recv(); |
202 | spi_end(); |
203 | usb_send(&ep0, buf, size+1, NULL, NULL); |
204 | return 1; |
205 | |
206 | case ATUSB_TO_DEV(ATUSB_SRAM_WRITE): |
207 | debug("ATUSB_SRAM_WRITE\n"); |
208 | if (setup->wIndex > SRAM_SIZE) |
209 | return 0; |
210 | if (setup->wIndex+setup->wLength > SRAM_SIZE) |
211 | return 0; |
212 | buf[0] = AT86RF230_SRAM_WRITE; |
213 | buf[1] = setup->wIndex; |
214 | size = setup->wLength+2; |
215 | usb_recv(&ep0, buf+2, setup->wLength, do_buf_write, NULL); |
216 | return 1; |
217 | case ATUSB_TO_DEV(ATUSB_SRAM_READ): |
218 | debug("ATUSB_SRAM_READ\n"); |
219 | if (setup->wIndex > SRAM_SIZE) |
220 | return 0; |
221 | if (setup->wIndex+setup->wLength > SRAM_SIZE) |
222 | return 0; |
223 | spi_begin(); |
224 | spi_send(AT86RF230_SRAM_READ); |
225 | spi_send(setup->wIndex); |
226 | for (i = 0; i != size; i++) |
227 | buf[i] = spi_recv(); |
228 | spi_end(); |
229 | usb_send(&ep0, buf, size, NULL, NULL); |
230 | return 1; |
231 | |
232 | default: |
233 | error("Unrecognized SETUP: 0x%02x 0x%02x ...\n", |
234 | setup->bmRequestType, setup->bRequest); |
235 | return 0; |
236 | } |
237 | } |
238 | |
239 | |
240 | static void class_init(void) |
241 | { |
242 | } |
243 | |
244 | |
245 | static void req_handler(req_t *req) |
246 | { |
247 | if (!my_setup(req)) |
248 | ep_set_stall(EP_CTRL); |
249 | } |
250 | |
251 | |
252 | static void rx_handler(void) |
253 | { |
254 | } |
255 | |
256 | |
257 | void ep0_init(void) |
258 | { |
259 | usb_reg_class_drvr(class_init, req_handler, rx_handler); |
260 | } |
261 |