blob: 9c93cff5e2fa4a5adc51d52f8366b20f779f2628 [file] [log] [blame]
Brian Silverman099196d2017-06-21 23:26:02 -07001/* Teensyduino Core Library
2 * http://www.pjrc.com/teensy/
3 * Copyright (c) 2017 PJRC.COM, LLC.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining
6 * a copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sublicense, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
12 *
13 * 1. The above copyright notice and this permission notice shall be
14 * included in all copies or substantial portions of the Software.
15 *
16 * 2. If the Software is incorporated into a build system that allows
17 * selection among a list of target devices, then similar target
18 * devices manufactured by PJRC.COM must be included in the list of
19 * target devices and selectable in the same manner.
20 *
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
25 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
26 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
27 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28 * SOFTWARE.
29 *
30 * Trying to understand this rather complex code?
31 *
32 * Kevin Cuzner wrote a simpler version, and a great blog article:
33 * http://kevincuzner.com/2014/12/12/teensy-3-1-bare-metal-writing-a-usb-driver/
34 * https://github.com/kcuzner/teensy-oscilloscope/blob/master/scope-teensy/src/usb.c
35 *
36 * Andy Payne wrote another relatively simple USB example for Freescale Kinetis
37 * https://github.com/payne92/bare-metal-arm
38 */
39
Brian Silvermanb79af7c2017-06-21 23:48:02 -070040#include "motors/usb/usb_dev.h"
Brian Silverman099196d2017-06-21 23:26:02 -070041#if F_CPU >= 20000000 && defined(NUM_ENDPOINTS)
42
Brian Silvermanb79af7c2017-06-21 23:48:02 -070043#include "motors/core/kinetis.h"
44#include "motors/usb/usb_mem.h"
Brian Silverman099196d2017-06-21 23:26:02 -070045#include <string.h> // for memset
46
Brian Silvermanb79af7c2017-06-21 23:48:02 -070047#ifdef CDC_DATA_INTERFACE
48extern uint32_t usb_cdc_line_coding[2];
49extern volatile uint32_t usb_cdc_line_rtsdtr_millis;
50extern volatile uint32_t systick_millis_count;
51extern volatile uint8_t usb_cdc_line_rtsdtr;
52extern volatile uint8_t *usb_cdc_transmit_flush_timer;
53extern void usb_serial_flush_callback(int);
54#endif
55#ifdef CDC2_DATA_INTERFACE
56extern volatile uint8_t *usb_cdc2_transmit_flush_timer;
57#endif
58
Brian Silverman099196d2017-06-21 23:26:02 -070059// buffer descriptor table
60
61typedef struct {
62 uint32_t desc;
Brian Silvermanb79af7c2017-06-21 23:48:02 -070063 const void * addr;
Brian Silverman099196d2017-06-21 23:26:02 -070064} bdt_t;
65
Brian Silvermanf1ad1bc2017-09-23 13:08:36 -040066__attribute__((aligned(512), used)) static bdt_t table[(NUM_ENDPOINTS + 1) * 4];
Brian Silverman099196d2017-06-21 23:26:02 -070067
68static usb_packet_t *rx_first[NUM_ENDPOINTS];
69static usb_packet_t *rx_last[NUM_ENDPOINTS];
70static usb_packet_t *tx_first[NUM_ENDPOINTS];
71static usb_packet_t *tx_last[NUM_ENDPOINTS];
72uint16_t usb_rx_byte_count_data[NUM_ENDPOINTS];
73
74static uint8_t tx_state[NUM_ENDPOINTS];
75#define TX_STATE_BOTH_FREE_EVEN_FIRST 0
76#define TX_STATE_BOTH_FREE_ODD_FIRST 1
77#define TX_STATE_EVEN_FREE 2
78#define TX_STATE_ODD_FREE 3
79#define TX_STATE_NONE_FREE_EVEN_FIRST 4
80#define TX_STATE_NONE_FREE_ODD_FIRST 5
81
82#define BDT_OWN 0x80
83#define BDT_DATA1 0x40
84#define BDT_DATA0 0x00
85#define BDT_DTS 0x08
86#define BDT_STALL 0x04
87#define BDT_PID(n) (((n) >> 2) & 15)
88
89#define BDT_DESC(count, data) (BDT_OWN | BDT_DTS \
90 | ((data) ? BDT_DATA1 : BDT_DATA0) \
91 | ((count) << 16))
92
93#define TX 1
94#define RX 0
95#define ODD 1
96#define EVEN 0
97#define DATA0 0
98#define DATA1 1
99#define index(endpoint, tx, odd) (((endpoint) << 2) | ((tx) << 1) | (odd))
100#define stat2bufferdescriptor(stat) (table + ((stat) >> 2))
101
102
103static union {
104 struct {
105 union {
106 struct {
107 uint8_t bmRequestType;
108 uint8_t bRequest;
109 };
110 uint16_t wRequestAndType;
111 };
112 uint16_t wValue;
113 uint16_t wIndex;
114 uint16_t wLength;
115 };
116 struct {
117 uint32_t word1;
118 uint32_t word2;
119 };
120} setup;
121
122
123#define GET_STATUS 0
124#define CLEAR_FEATURE 1
125#define SET_FEATURE 3
126#define SET_ADDRESS 5
127#define GET_DESCRIPTOR 6
128#define SET_DESCRIPTOR 7
129#define GET_CONFIGURATION 8
130#define SET_CONFIGURATION 9
131#define GET_INTERFACE 10
132#define SET_INTERFACE 11
133#define SYNCH_FRAME 12
134
135// SETUP always uses a DATA0 PID for the data field of the SETUP transaction.
136// transactions in the data phase start with DATA1 and toggle (figure 8-12, USB1.1)
137// Status stage uses a DATA1 PID.
138
139static uint8_t ep0_rx0_buf[EP0_SIZE] __attribute__ ((aligned (4)));
140static uint8_t ep0_rx1_buf[EP0_SIZE] __attribute__ ((aligned (4)));
141static const uint8_t *ep0_tx_ptr = NULL;
142static uint16_t ep0_tx_len;
143static uint8_t ep0_tx_bdt_bank = 0;
144static uint8_t ep0_tx_data_toggle = 0;
145uint8_t usb_rx_memory_needed = 0;
146
147volatile uint8_t usb_configuration = 0;
148volatile uint8_t usb_reboot_timer = 0;
149
150
151static void endpoint0_stall(void)
152{
153 USB0_ENDPT0 = USB_ENDPT_EPSTALL | USB_ENDPT_EPRXEN | USB_ENDPT_EPTXEN | USB_ENDPT_EPHSHK;
154}
155
156
157static void endpoint0_transmit(const void *data, uint32_t len)
158{
Brian Silvermanb79af7c2017-06-21 23:48:02 -0700159 table[index(0, TX, ep0_tx_bdt_bank)].addr = (const void *)data;
Brian Silverman099196d2017-06-21 23:26:02 -0700160 table[index(0, TX, ep0_tx_bdt_bank)].desc = BDT_DESC(len, ep0_tx_data_toggle);
161 ep0_tx_data_toggle ^= 1;
162 ep0_tx_bdt_bank ^= 1;
163}
164
165static uint8_t reply_buffer[8];
166
167static void usb_setup(void)
168{
169 const uint8_t *data = NULL;
170 uint32_t datalen = 0;
171 const usb_descriptor_list_t *list;
172 uint32_t size;
173 volatile uint8_t *reg;
174 uint8_t epconf;
175 const uint8_t *cfg;
176 int i;
177
178 switch (setup.wRequestAndType) {
179 case 0x0500: // SET_ADDRESS
180 break;
181 case 0x0900: // SET_CONFIGURATION
Brian Silverman099196d2017-06-21 23:26:02 -0700182 usb_configuration = setup.wValue;
183 reg = &USB0_ENDPT1;
184 cfg = usb_endpoint_config_table;
185 // clear all BDT entries, free any allocated memory...
186 for (i=4; i < (NUM_ENDPOINTS+1)*4; i++) {
187 if (table[i].desc & BDT_OWN) {
Brian Silvermanb79af7c2017-06-21 23:48:02 -0700188 usb_free((const usb_packet_t *)((const uint8_t *)(table[i].addr) - 8));
Brian Silverman099196d2017-06-21 23:26:02 -0700189 }
190 }
191 // free all queued packets
192 for (i=0; i < NUM_ENDPOINTS; i++) {
193 usb_packet_t *p, *n;
194 p = rx_first[i];
195 while (p) {
196 n = p->next;
197 usb_free(p);
198 p = n;
199 }
200 rx_first[i] = NULL;
201 rx_last[i] = NULL;
202 p = tx_first[i];
203 while (p) {
204 n = p->next;
205 usb_free(p);
206 p = n;
207 }
208 tx_first[i] = NULL;
209 tx_last[i] = NULL;
210 usb_rx_byte_count_data[i] = 0;
211 switch (tx_state[i]) {
212 case TX_STATE_EVEN_FREE:
213 case TX_STATE_NONE_FREE_EVEN_FIRST:
214 tx_state[i] = TX_STATE_BOTH_FREE_EVEN_FIRST;
215 break;
216 case TX_STATE_ODD_FREE:
217 case TX_STATE_NONE_FREE_ODD_FIRST:
218 tx_state[i] = TX_STATE_BOTH_FREE_ODD_FIRST;
219 break;
220 default:
221 break;
222 }
223 }
224 usb_rx_memory_needed = 0;
225 for (i=1; i <= NUM_ENDPOINTS; i++) {
226 epconf = *cfg++;
227 *reg = epconf;
228 reg += 4;
229#ifdef AUDIO_INTERFACE
230 if (i == AUDIO_RX_ENDPOINT) {
231 table[index(i, RX, EVEN)].addr = usb_audio_receive_buffer;
232 table[index(i, RX, EVEN)].desc = (AUDIO_RX_SIZE<<16) | BDT_OWN;
233 table[index(i, RX, ODD)].addr = usb_audio_receive_buffer;
234 table[index(i, RX, ODD)].desc = (AUDIO_RX_SIZE<<16) | BDT_OWN;
235 } else
236#endif
237 if (epconf & USB_ENDPT_EPRXEN) {
238 usb_packet_t *p;
239 p = usb_malloc();
240 if (p) {
241 table[index(i, RX, EVEN)].addr = p->buf;
242 table[index(i, RX, EVEN)].desc = BDT_DESC(64, 0);
243 } else {
244 table[index(i, RX, EVEN)].desc = 0;
245 usb_rx_memory_needed++;
246 }
247 p = usb_malloc();
248 if (p) {
249 table[index(i, RX, ODD)].addr = p->buf;
250 table[index(i, RX, ODD)].desc = BDT_DESC(64, 1);
251 } else {
252 table[index(i, RX, ODD)].desc = 0;
253 usb_rx_memory_needed++;
254 }
255 }
256 table[index(i, TX, EVEN)].desc = 0;
257 table[index(i, TX, ODD)].desc = 0;
258#ifdef AUDIO_INTERFACE
259 if (i == AUDIO_SYNC_ENDPOINT) {
260 table[index(i, TX, EVEN)].addr = &usb_audio_sync_feedback;
261 table[index(i, TX, EVEN)].desc = (3<<16) | BDT_OWN;
262 }
263#endif
264 }
265 break;
266 case 0x0880: // GET_CONFIGURATION
267 reply_buffer[0] = usb_configuration;
268 datalen = 1;
269 data = reply_buffer;
270 break;
271 case 0x0080: // GET_STATUS (device)
272 reply_buffer[0] = 0;
273 reply_buffer[1] = 0;
274 datalen = 2;
275 data = reply_buffer;
276 break;
277 case 0x0082: // GET_STATUS (endpoint)
278 i = setup.wIndex & 0x7F;
279 if (i > NUM_ENDPOINTS) {
280 // TODO: do we need to handle IN vs OUT here?
281 endpoint0_stall();
282 return;
283 }
284 reply_buffer[0] = 0;
285 reply_buffer[1] = 0;
Brian Silvermanb79af7c2017-06-21 23:48:02 -0700286 if (*(volatile uint8_t *)(&USB0_ENDPT0 + i * 4) & 0x02) {
287 reply_buffer[0] = 1;
288 }
Brian Silverman099196d2017-06-21 23:26:02 -0700289 data = reply_buffer;
290 datalen = 2;
291 break;
292 case 0x0102: // CLEAR_FEATURE (endpoint)
293 i = setup.wIndex & 0x7F;
294 if (i > NUM_ENDPOINTS || setup.wValue != 0) {
295 // TODO: do we need to handle IN vs OUT here?
296 endpoint0_stall();
297 return;
298 }
Brian Silvermanb79af7c2017-06-21 23:48:02 -0700299 (*(volatile uint8_t *)(&USB0_ENDPT0 + i * 4)) &= ~0x02;
Brian Silverman099196d2017-06-21 23:26:02 -0700300 // TODO: do we need to clear the data toggle here?
301 break;
302 case 0x0302: // SET_FEATURE (endpoint)
303 i = setup.wIndex & 0x7F;
304 if (i > NUM_ENDPOINTS || setup.wValue != 0) {
305 // TODO: do we need to handle IN vs OUT here?
306 endpoint0_stall();
307 return;
308 }
Brian Silvermanb79af7c2017-06-21 23:48:02 -0700309 (*(volatile uint8_t *)(&USB0_ENDPT0 + i * 4)) |= 0x02;
Brian Silverman099196d2017-06-21 23:26:02 -0700310 // TODO: do we need to clear the data toggle here?
311 break;
312 case 0x0680: // GET_DESCRIPTOR
313 case 0x0681:
Brian Silverman099196d2017-06-21 23:26:02 -0700314 for (list = usb_descriptor_list; 1; list++) {
315 if (list->addr == NULL) break;
Brian Silverman099196d2017-06-21 23:26:02 -0700316 if (setup.wValue == list->wValue && setup.wIndex == list->wIndex) {
317 data = list->addr;
318 if ((setup.wValue >> 8) == 3) {
319 // for string descriptors, use the descriptor's
320 // length field, allowing runtime configured
321 // length.
322 datalen = *(list->addr);
323 } else {
324 datalen = list->length;
325 }
Brian Silverman099196d2017-06-21 23:26:02 -0700326 goto send;
327 }
328 }
Brian Silverman099196d2017-06-21 23:26:02 -0700329 endpoint0_stall();
330 return;
331#if defined(CDC_STATUS_INTERFACE)
332 case 0x2221: // CDC_SET_CONTROL_LINE_STATE
Brian Silvermanb79af7c2017-06-21 23:48:02 -0700333 // TODO(Brian): wIndex is the interface number this is directed at. Pay
334 // attention to that.
Brian Silverman099196d2017-06-21 23:26:02 -0700335 usb_cdc_line_rtsdtr_millis = systick_millis_count;
336 usb_cdc_line_rtsdtr = setup.wValue;
Brian Silverman099196d2017-06-21 23:26:02 -0700337 break;
338 case 0x2321: // CDC_SEND_BREAK
339 break;
340 case 0x2021: // CDC_SET_LINE_CODING
Brian Silverman099196d2017-06-21 23:26:02 -0700341 return;
342#endif
343
344#if defined(MTP_INTERFACE)
345 case 0x64A1: // Cancel Request (PTP spec, 5.2.1, page 8)
346 // TODO: required by PTP spec
347 endpoint0_stall();
348 return;
349 case 0x66A1: // Device Reset (PTP spec, 5.2.3, page 10)
350 // TODO: required by PTP spec
351 endpoint0_stall();
352 return;
353 case 0x67A1: // Get Device Statis (PTP spec, 5.2.4, page 10)
354 // For now, always respond with status ok.
355 reply_buffer[0] = 0x4;
356 reply_buffer[1] = 0;
357 reply_buffer[2] = 0x01;
358 reply_buffer[3] = 0x20;
359 data = reply_buffer;
360 datalen = 4;
361 break;
362#endif
363
364// TODO: this does not work... why?
365#if defined(SEREMU_INTERFACE) || defined(KEYBOARD_INTERFACE)
366 case 0x0921: // HID SET_REPORT
Brian Silverman099196d2017-06-21 23:26:02 -0700367 return;
368 case 0x0A21: // HID SET_IDLE
369 break;
370 // case 0xC940:
371#endif
372
373#if defined(AUDIO_INTERFACE)
374 case 0x0B01: // SET_INTERFACE (alternate setting)
375 if (setup.wIndex == AUDIO_INTERFACE+1) {
376 usb_audio_transmit_setting = setup.wValue;
377 if (usb_audio_transmit_setting > 0) {
378 bdt_t *b = &table[index(AUDIO_TX_ENDPOINT, TX, EVEN)];
379 uint8_t state = tx_state[AUDIO_TX_ENDPOINT-1];
380 if (state) b++;
381 if (!(b->desc & BDT_OWN)) {
382 memset(usb_audio_transmit_buffer, 0, 176);
383 b->addr = usb_audio_transmit_buffer;
384 b->desc = (176 << 16) | BDT_OWN;
385 tx_state[AUDIO_TX_ENDPOINT-1] = state ^ 1;
386 }
387 }
388 } else if (setup.wIndex == AUDIO_INTERFACE+2) {
389 usb_audio_receive_setting = setup.wValue;
390 } else {
391 endpoint0_stall();
392 return;
393 }
394 break;
395 case 0x0A81: // GET_INTERFACE (alternate setting)
396 datalen = 1;
397 data = reply_buffer;
398 if (setup.wIndex == AUDIO_INTERFACE+1) {
399 reply_buffer[0] = usb_audio_transmit_setting;
400 } else if (setup.wIndex == AUDIO_INTERFACE+2) {
401 reply_buffer[0] = usb_audio_receive_setting;
402 } else {
403 endpoint0_stall();
404 return;
405 }
406 break;
407 case 0x0121: // SET FEATURE
408 case 0x0221:
409 case 0x0321:
410 case 0x0421:
411 // handle these on the next packet. See usb_audio_set_feature()
412 return;
413 case 0x81A1: // GET FEATURE
414 case 0x82A1:
415 case 0x83A1:
416 case 0x84A1:
417 if (usb_audio_get_feature(&setup, reply_buffer, &datalen)) {
418 data = reply_buffer;
419 }
420 else {
421 endpoint0_stall();
422 return;
423 }
424 break;
425
426 case 0x81A2: // GET_CUR (wValue=0, wIndex=interface, wLength=len)
427 if (setup.wLength >= 3) {
428 reply_buffer[0] = 44100 & 255;
429 reply_buffer[1] = 44100 >> 8;
430 reply_buffer[2] = 0;
431 datalen = 3;
432 data = reply_buffer;
433 } else {
434 endpoint0_stall();
435 return;
436 }
437 break;
438#endif
439
440#if defined(MULTITOUCH_INTERFACE)
441 case 0x01A1:
442 if (setup.wValue == 0x0300 && setup.wIndex == MULTITOUCH_INTERFACE) {
443 reply_buffer[0] = MULTITOUCH_FINGERS;
444 data = reply_buffer;
445 datalen = 1;
446 } else {
447 endpoint0_stall();
448 return;
449 }
450 break;
451#endif
452 default:
453 endpoint0_stall();
454 return;
455 }
456 send:
Brian Silverman099196d2017-06-21 23:26:02 -0700457
458 if (datalen > setup.wLength) datalen = setup.wLength;
459 size = datalen;
460 if (size > EP0_SIZE) size = EP0_SIZE;
461 endpoint0_transmit(data, size);
462 data += size;
463 datalen -= size;
464 if (datalen == 0 && size < EP0_SIZE) return;
465
466 size = datalen;
467 if (size > EP0_SIZE) size = EP0_SIZE;
468 endpoint0_transmit(data, size);
469 data += size;
470 datalen -= size;
471 if (datalen == 0 && size < EP0_SIZE) return;
472
473 ep0_tx_ptr = data;
474 ep0_tx_len = datalen;
475}
476
477
478
479//A bulk endpoint's toggle sequence is initialized to DATA0 when the endpoint
480//experiences any configuration event (configuration events are explained in
481//Sections 9.1.1.5 and 9.4.5).
482
483//Configuring a device or changing an alternate setting causes all of the status
484//and configuration values associated with endpoints in the affected interfaces
485//to be set to their default values. This includes setting the data toggle of
486//any endpoint using data toggles to the value DATA0.
487
488//For endpoints using data toggle, regardless of whether an endpoint has the
489//Halt feature set, a ClearFeature(ENDPOINT_HALT) request always results in the
490//data toggle being reinitialized to DATA0.
491
492
493
494// #define stat2bufferdescriptor(stat) (table + ((stat) >> 2))
495
496static void usb_control(uint32_t stat)
497{
498 bdt_t *b;
499 uint32_t pid, size;
Brian Silvermanb79af7c2017-06-21 23:48:02 -0700500 const uint8_t *buf;
Brian Silverman099196d2017-06-21 23:26:02 -0700501 const uint8_t *data;
502
503 b = stat2bufferdescriptor(stat);
504 pid = BDT_PID(b->desc);
Brian Silverman099196d2017-06-21 23:26:02 -0700505 buf = b->addr;
Brian Silverman099196d2017-06-21 23:26:02 -0700506
507 switch (pid) {
508 case 0x0D: // Setup received from host
Brian Silverman099196d2017-06-21 23:26:02 -0700509 // grab the 8 byte setup info
Brian Silvermanb79af7c2017-06-21 23:48:02 -0700510 setup.word1 = *(const uint32_t *)(buf);
511 setup.word2 = *(const uint32_t *)(buf + 4);
Brian Silverman099196d2017-06-21 23:26:02 -0700512
513 // give the buffer back
514 b->desc = BDT_DESC(EP0_SIZE, DATA1);
Brian Silverman099196d2017-06-21 23:26:02 -0700515
516 // clear any leftover pending IN transactions
517 ep0_tx_ptr = NULL;
518 if (ep0_tx_data_toggle) {
519 }
Brian Silverman099196d2017-06-21 23:26:02 -0700520 table[index(0, TX, EVEN)].desc = 0;
521 table[index(0, TX, ODD)].desc = 0;
522 // first IN after Setup is always DATA1
523 ep0_tx_data_toggle = 1;
524
Brian Silverman099196d2017-06-21 23:26:02 -0700525 // actually "do" the setup request
526 usb_setup();
527 // unfreeze the USB, now that we're ready
528 USB0_CTL = USB_CTL_USBENSOFEN; // clear TXSUSPENDTOKENBUSY bit
529 break;
530 case 0x01: // OUT transaction received from host
531 case 0x02:
Brian Silverman099196d2017-06-21 23:26:02 -0700532#ifdef CDC_STATUS_INTERFACE
Brian Silvermanb79af7c2017-06-21 23:48:02 -0700533 // TODO(Brian): wIndex is the interface number this is directed at. Pay
534 // attention to that.
Brian Silverman099196d2017-06-21 23:26:02 -0700535 if (setup.wRequestAndType == 0x2021 /*CDC_SET_LINE_CODING*/) {
536 int i;
537 uint8_t *dst = (uint8_t *)usb_cdc_line_coding;
Brian Silverman099196d2017-06-21 23:26:02 -0700538 for (i=0; i<7; i++) {
Brian Silverman099196d2017-06-21 23:26:02 -0700539 *dst++ = *buf++;
540 }
Brian Silverman099196d2017-06-21 23:26:02 -0700541 if (usb_cdc_line_coding[0] == 134) usb_reboot_timer = 15;
542 endpoint0_transmit(NULL, 0);
543 }
544#endif
545#ifdef KEYBOARD_INTERFACE
546 if (setup.word1 == 0x02000921 && setup.word2 == ((1<<16)|KEYBOARD_INTERFACE)) {
547 keyboard_leds = buf[0];
548 endpoint0_transmit(NULL, 0);
549 }
550#endif
551#ifdef SEREMU_INTERFACE
552 if (setup.word1 == 0x03000921 && setup.word2 == ((4<<16)|SEREMU_INTERFACE)
553 && buf[0] == 0xA9 && buf[1] == 0x45 && buf[2] == 0xC2 && buf[3] == 0x6B) {
554 usb_reboot_timer = 5;
555 endpoint0_transmit(NULL, 0);
556 }
557#endif
558#ifdef AUDIO_INTERFACE
559 if (usb_audio_set_feature(&setup, buf)) {
560 endpoint0_transmit(NULL, 0);
561 }
562#endif
563 // give the buffer back
564 b->desc = BDT_DESC(EP0_SIZE, DATA1);
565 break;
566
567 case 0x09: // IN transaction completed to host
Brian Silverman099196d2017-06-21 23:26:02 -0700568
569 // send remaining data, if any...
570 data = ep0_tx_ptr;
571 if (data) {
572 size = ep0_tx_len;
573 if (size > EP0_SIZE) size = EP0_SIZE;
574 endpoint0_transmit(data, size);
575 data += size;
576 ep0_tx_len -= size;
577 ep0_tx_ptr = (ep0_tx_len > 0 || size == EP0_SIZE) ? data : NULL;
578 }
579
580 if (setup.bRequest == 5 && setup.bmRequestType == 0) {
581 setup.bRequest = 0;
Brian Silverman099196d2017-06-21 23:26:02 -0700582 USB0_ADDR = setup.wValue;
583 }
584
585 break;
Brian Silverman099196d2017-06-21 23:26:02 -0700586 }
587 USB0_CTL = USB_CTL_USBENSOFEN; // clear TXSUSPENDTOKENBUSY bit
588}
589
590
591
592
593
594
595usb_packet_t *usb_rx(uint32_t endpoint)
596{
597 usb_packet_t *ret;
598 endpoint--;
599 if (endpoint >= NUM_ENDPOINTS) return NULL;
600 __disable_irq();
601 ret = rx_first[endpoint];
602 if (ret) {
603 rx_first[endpoint] = ret->next;
604 usb_rx_byte_count_data[endpoint] -= ret->len;
605 }
606 __enable_irq();
Brian Silverman099196d2017-06-21 23:26:02 -0700607 return ret;
608}
609
610static uint32_t usb_queue_byte_count(const usb_packet_t *p)
611{
612 uint32_t count=0;
613
614 __disable_irq();
615 for ( ; p; p = p->next) {
616 count += p->len;
617 }
618 __enable_irq();
619 return count;
620}
621
Brian Silverman099196d2017-06-21 23:26:02 -0700622uint32_t usb_tx_byte_count(uint32_t endpoint)
623{
624 endpoint--;
625 if (endpoint >= NUM_ENDPOINTS) return 0;
626 return usb_queue_byte_count(tx_first[endpoint]);
627}
628
629uint32_t usb_tx_packet_count(uint32_t endpoint)
630{
631 const usb_packet_t *p;
632 uint32_t count=0;
633
634 endpoint--;
635 if (endpoint >= NUM_ENDPOINTS) return 0;
636 __disable_irq();
637 for (p = tx_first[endpoint]; p; p = p->next) count++;
638 __enable_irq();
639 return count;
640}
641
642
643// Called from usb_free, but only when usb_rx_memory_needed > 0, indicating
644// receive endpoints are starving for memory. The intention is to give
645// endpoints needing receive memory priority over the user's code, which is
646// likely calling usb_malloc to obtain memory for transmitting. When the
647// user is creating data very quickly, their consumption could starve reception
648// without this prioritization. The packet buffer (input) is assigned to the
649// first endpoint needing memory.
650//
Brian Silvermanb79af7c2017-06-21 23:48:02 -0700651void usb_rx_memory(const usb_packet_t *packet)
Brian Silverman099196d2017-06-21 23:26:02 -0700652{
653 unsigned int i;
654 const uint8_t *cfg;
655
656 cfg = usb_endpoint_config_table;
Brian Silverman099196d2017-06-21 23:26:02 -0700657 __disable_irq();
658 for (i=1; i <= NUM_ENDPOINTS; i++) {
659#ifdef AUDIO_INTERFACE
660 if (i == AUDIO_RX_ENDPOINT) continue;
661#endif
662 if (*cfg++ & USB_ENDPT_EPRXEN) {
663 if (table[index(i, RX, EVEN)].desc == 0) {
664 table[index(i, RX, EVEN)].addr = packet->buf;
665 table[index(i, RX, EVEN)].desc = BDT_DESC(64, 0);
666 usb_rx_memory_needed--;
667 __enable_irq();
Brian Silverman099196d2017-06-21 23:26:02 -0700668 return;
669 }
670 if (table[index(i, RX, ODD)].desc == 0) {
671 table[index(i, RX, ODD)].addr = packet->buf;
672 table[index(i, RX, ODD)].desc = BDT_DESC(64, 1);
673 usb_rx_memory_needed--;
674 __enable_irq();
Brian Silverman099196d2017-06-21 23:26:02 -0700675 return;
676 }
677 }
678 }
679 __enable_irq();
680 // we should never reach this point. If we get here, it means
681 // usb_rx_memory_needed was set greater than zero, but no memory
682 // was actually needed.
683 usb_rx_memory_needed = 0;
684 usb_free(packet);
685 return;
686}
687
688//#define index(endpoint, tx, odd) (((endpoint) << 2) | ((tx) << 1) | (odd))
689//#define stat2bufferdescriptor(stat) (table + ((stat) >> 2))
690
691void usb_tx(uint32_t endpoint, usb_packet_t *packet)
692{
693 bdt_t *b = &table[index(endpoint, TX, EVEN)];
694 uint8_t next;
695
696 endpoint--;
697 if (endpoint >= NUM_ENDPOINTS) return;
698 __disable_irq();
Brian Silverman099196d2017-06-21 23:26:02 -0700699 switch (tx_state[endpoint]) {
700 case TX_STATE_BOTH_FREE_EVEN_FIRST:
701 next = TX_STATE_ODD_FREE;
702 break;
703 case TX_STATE_BOTH_FREE_ODD_FIRST:
704 b++;
705 next = TX_STATE_EVEN_FREE;
706 break;
707 case TX_STATE_EVEN_FREE:
708 next = TX_STATE_NONE_FREE_ODD_FIRST;
709 break;
710 case TX_STATE_ODD_FREE:
711 b++;
712 next = TX_STATE_NONE_FREE_EVEN_FIRST;
713 break;
714 default:
715 if (tx_first[endpoint] == NULL) {
716 tx_first[endpoint] = packet;
717 } else {
718 tx_last[endpoint]->next = packet;
719 }
720 tx_last[endpoint] = packet;
721 __enable_irq();
722 return;
723 }
724 tx_state[endpoint] = next;
725 b->addr = packet->buf;
726 b->desc = BDT_DESC(packet->len, ((uint32_t)b & 8) ? DATA1 : DATA0);
727 __enable_irq();
728}
729
730void usb_tx_isochronous(uint32_t endpoint, void *data, uint32_t len)
731{
732 bdt_t *b = &table[index(endpoint, TX, EVEN)];
733 uint8_t next, state;
734
735 endpoint--;
736 if (endpoint >= NUM_ENDPOINTS) return;
737 __disable_irq();
738 state = tx_state[endpoint];
739 if (state == 0) {
740 next = 1;
741 } else {
742 b++;
743 next = 0;
744 }
745 tx_state[endpoint] = next;
746 b->addr = data;
747 b->desc = (len << 16) | BDT_OWN;
748 __enable_irq();
749}
750
751
752
753
754void _reboot_Teensyduino_(void)
755{
756 // TODO: initialize R0 with a code....
757 __asm__ volatile("bkpt");
758}
759
760
761
762void usb_isr(void)
763{
764 uint8_t status, stat, t;
765
Brian Silverman099196d2017-06-21 23:26:02 -0700766 restart:
767 status = USB0_ISTAT;
768
769 if ((status & USB_ISTAT_SOFTOK /* 04 */ )) {
770 if (usb_configuration) {
771 t = usb_reboot_timer;
772 if (t) {
773 usb_reboot_timer = --t;
774 if (!t) _reboot_Teensyduino_();
775 }
776#ifdef CDC_DATA_INTERFACE
Brian Silvermanb79af7c2017-06-21 23:48:02 -0700777 t = *usb_cdc_transmit_flush_timer;
Brian Silverman099196d2017-06-21 23:26:02 -0700778 if (t) {
Brian Silvermanb79af7c2017-06-21 23:48:02 -0700779 *usb_cdc_transmit_flush_timer = --t;
780 if (t == 0) usb_serial_flush_callback(0);
781 }
782#endif
783#ifdef CDC2_DATA_INTERFACE
784 t = *usb_cdc2_transmit_flush_timer;
785 if (t) {
786 *usb_cdc2_transmit_flush_timer = --t;
787 if (t == 0) usb_serial_flush_callback(1);
Brian Silverman099196d2017-06-21 23:26:02 -0700788 }
789#endif
790#ifdef SEREMU_INTERFACE
791 t = usb_seremu_transmit_flush_timer;
792 if (t) {
793 usb_seremu_transmit_flush_timer = --t;
794 if (t == 0) usb_seremu_flush_callback();
795 }
796#endif
797#ifdef MIDI_INTERFACE
798 usb_midi_flush_output();
799#endif
800#ifdef FLIGHTSIM_INTERFACE
801 usb_flightsim_flush_callback();
802#endif
803#ifdef MULTITOUCH_INTERFACE
804 usb_touchscreen_update_callback();
805#endif
806 }
807 USB0_ISTAT = USB_ISTAT_SOFTOK;
808 }
809
810 if ((status & USB_ISTAT_TOKDNE /* 08 */ )) {
811 uint8_t endpoint;
812 stat = USB0_STAT;
Brian Silverman099196d2017-06-21 23:26:02 -0700813 endpoint = stat >> 4;
814 if (endpoint == 0) {
815 usb_control(stat);
816 } else {
817 bdt_t *b = stat2bufferdescriptor(stat);
Brian Silvermanb79af7c2017-06-21 23:48:02 -0700818#pragma GCC diagnostic push
819#pragma GCC diagnostic ignored "-Wcast-qual"
Brian Silverman099196d2017-06-21 23:26:02 -0700820 usb_packet_t *packet = (usb_packet_t *)((uint8_t *)(b->addr) - 8);
Brian Silvermanb79af7c2017-06-21 23:48:02 -0700821#pragma GCC diagnostic pop
Brian Silverman099196d2017-06-21 23:26:02 -0700822 endpoint--; // endpoint is index to zero-based arrays
823
824#ifdef AUDIO_INTERFACE
825 if ((endpoint == AUDIO_TX_ENDPOINT-1) && (stat & 0x08)) {
826 unsigned int len;
827 len = usb_audio_transmit_callback();
828 if (len > 0) {
829 b = (bdt_t *)((uint32_t)b ^ 8);
830 b->addr = usb_audio_transmit_buffer;
831 b->desc = (len << 16) | BDT_OWN;
832 tx_state[endpoint] ^= 1;
833 }
834 } else if ((endpoint == AUDIO_RX_ENDPOINT-1) && !(stat & 0x08)) {
835 usb_audio_receive_callback(b->desc >> 16);
836 b->addr = usb_audio_receive_buffer;
837 b->desc = (AUDIO_RX_SIZE << 16) | BDT_OWN;
838 } else if ((endpoint == AUDIO_SYNC_ENDPOINT-1) && (stat & 0x08)) {
839 b = (bdt_t *)((uint32_t)b ^ 8);
840 b->addr = &usb_audio_sync_feedback;
841 b->desc = (3 << 16) | BDT_OWN;
842 tx_state[endpoint] ^= 1;
843 } else
844#endif
845 if (stat & 0x08) { // transmit
846 usb_free(packet);
847 packet = tx_first[endpoint];
848 if (packet) {
Brian Silverman099196d2017-06-21 23:26:02 -0700849 tx_first[endpoint] = packet->next;
850 b->addr = packet->buf;
851 switch (tx_state[endpoint]) {
852 case TX_STATE_BOTH_FREE_EVEN_FIRST:
853 tx_state[endpoint] = TX_STATE_ODD_FREE;
854 break;
855 case TX_STATE_BOTH_FREE_ODD_FIRST:
856 tx_state[endpoint] = TX_STATE_EVEN_FREE;
857 break;
858 case TX_STATE_EVEN_FREE:
859 tx_state[endpoint] = TX_STATE_NONE_FREE_ODD_FIRST;
860 break;
861 case TX_STATE_ODD_FREE:
862 tx_state[endpoint] = TX_STATE_NONE_FREE_EVEN_FIRST;
863 break;
864 default:
865 break;
866 }
867 b->desc = BDT_DESC(packet->len,
868 ((uint32_t)b & 8) ? DATA1 : DATA0);
869 } else {
Brian Silverman099196d2017-06-21 23:26:02 -0700870 switch (tx_state[endpoint]) {
871 case TX_STATE_BOTH_FREE_EVEN_FIRST:
872 case TX_STATE_BOTH_FREE_ODD_FIRST:
873 break;
874 case TX_STATE_EVEN_FREE:
875 tx_state[endpoint] = TX_STATE_BOTH_FREE_EVEN_FIRST;
876 break;
877 case TX_STATE_ODD_FREE:
878 tx_state[endpoint] = TX_STATE_BOTH_FREE_ODD_FIRST;
879 break;
880 default:
881 tx_state[endpoint] = ((uint32_t)b & 8) ?
882 TX_STATE_ODD_FREE : TX_STATE_EVEN_FREE;
883 break;
884 }
885 }
886 } else { // receive
887 packet->len = b->desc >> 16;
888 if (packet->len > 0) {
889 packet->index = 0;
890 packet->next = NULL;
891 if (rx_first[endpoint] == NULL) {
Brian Silverman099196d2017-06-21 23:26:02 -0700892 rx_first[endpoint] = packet;
893 } else {
Brian Silverman099196d2017-06-21 23:26:02 -0700894 rx_last[endpoint]->next = packet;
895 }
896 rx_last[endpoint] = packet;
897 usb_rx_byte_count_data[endpoint] += packet->len;
898 // TODO: implement a per-endpoint maximum # of allocated
899 // packets, so a flood of incoming data on 1 endpoint
900 // doesn't starve the others if the user isn't reading
901 // it regularly
902 packet = usb_malloc();
903 if (packet) {
904 b->addr = packet->buf;
905 b->desc = BDT_DESC(64,
906 ((uint32_t)b & 8) ? DATA1 : DATA0);
907 } else {
Brian Silverman099196d2017-06-21 23:26:02 -0700908 b->desc = 0;
909 usb_rx_memory_needed++;
910 }
911 } else {
912 b->desc = BDT_DESC(64, ((uint32_t)b & 8) ? DATA1 : DATA0);
913 }
914 }
915
916 }
917 USB0_ISTAT = USB_ISTAT_TOKDNE;
918 goto restart;
919 }
920
921
922
923 if (status & USB_ISTAT_USBRST /* 01 */ ) {
Brian Silverman099196d2017-06-21 23:26:02 -0700924 // initialize BDT toggle bits
925 USB0_CTL = USB_CTL_ODDRST;
926 ep0_tx_bdt_bank = 0;
927
928 // set up buffers to receive Setup and OUT packets
929 table[index(0, RX, EVEN)].desc = BDT_DESC(EP0_SIZE, 0);
930 table[index(0, RX, EVEN)].addr = ep0_rx0_buf;
931 table[index(0, RX, ODD)].desc = BDT_DESC(EP0_SIZE, 0);
932 table[index(0, RX, ODD)].addr = ep0_rx1_buf;
933 table[index(0, TX, EVEN)].desc = 0;
934 table[index(0, TX, ODD)].desc = 0;
935
936 // activate endpoint 0
937 USB0_ENDPT0 = USB_ENDPT_EPRXEN | USB_ENDPT_EPTXEN | USB_ENDPT_EPHSHK;
938
939 // clear all ending interrupts
940 USB0_ERRSTAT = 0xFF;
941 USB0_ISTAT = 0xFF;
942
943 // set the address to zero during enumeration
944 USB0_ADDR = 0;
945
946 // enable other interrupts
947 USB0_ERREN = 0xFF;
948 USB0_INTEN = USB_INTEN_TOKDNEEN |
949 USB_INTEN_SOFTOKEN |
950 USB_INTEN_STALLEN |
951 USB_INTEN_ERROREN |
952 USB_INTEN_USBRSTEN |
953 USB_INTEN_SLEEPEN;
954
955 // is this necessary?
956 USB0_CTL = USB_CTL_USBENSOFEN;
957 return;
958 }
959
960
961 if ((status & USB_ISTAT_STALL /* 80 */ )) {
Brian Silverman099196d2017-06-21 23:26:02 -0700962 USB0_ENDPT0 = USB_ENDPT_EPRXEN | USB_ENDPT_EPTXEN | USB_ENDPT_EPHSHK;
963 USB0_ISTAT = USB_ISTAT_STALL;
964 }
965 if ((status & USB_ISTAT_ERROR /* 02 */ )) {
966 uint8_t err = USB0_ERRSTAT;
967 USB0_ERRSTAT = err;
Brian Silverman099196d2017-06-21 23:26:02 -0700968 USB0_ISTAT = USB_ISTAT_ERROR;
969 }
970
971 if ((status & USB_ISTAT_SLEEP /* 10 */ )) {
Brian Silverman099196d2017-06-21 23:26:02 -0700972 USB0_ISTAT = USB_ISTAT_SLEEP;
973 }
974
975}
976
977
978
979void usb_init(void)
980{
981 int i;
982
Brian Silverman099196d2017-06-21 23:26:02 -0700983 for (i=0; i <= NUM_ENDPOINTS*4; i++) {
984 table[i].desc = 0;
985 table[i].addr = 0;
986 }
987
988 // this basically follows the flowchart in the Kinetis
989 // Quick Reference User Guide, Rev. 1, 03/2012, page 141
990
991 // assume 48 MHz clock already running
992 // SIM - enable clock
993 SIM_SCGC4 |= SIM_SCGC4_USBOTG;
994#ifdef HAS_KINETIS_MPU
995 MPU_RGDAAC0 |= 0x03000000;
996#endif
997#if F_CPU == 180000000 || F_CPU == 216000000
998 // if using IRC48M, turn on the USB clock recovery hardware
999 USB0_CLK_RECOVER_IRC_EN = USB_CLK_RECOVER_IRC_EN_IRC_EN | USB_CLK_RECOVER_IRC_EN_REG_EN;
1000 USB0_CLK_RECOVER_CTRL = USB_CLK_RECOVER_CTRL_CLOCK_RECOVER_EN |
1001 USB_CLK_RECOVER_CTRL_RESTART_IFRTRIM_EN;
1002#endif
1003 // reset USB module
1004 //USB0_USBTRC0 = USB_USBTRC_USBRESET;
1005 //while ((USB0_USBTRC0 & USB_USBTRC_USBRESET) != 0) ; // wait for reset to end
1006
1007 // set desc table base addr
1008 USB0_BDTPAGE1 = ((uint32_t)table) >> 8;
1009 USB0_BDTPAGE2 = ((uint32_t)table) >> 16;
1010 USB0_BDTPAGE3 = ((uint32_t)table) >> 24;
1011
1012 // clear all ISR flags
1013 USB0_ISTAT = 0xFF;
1014 USB0_ERRSTAT = 0xFF;
1015 USB0_OTGISTAT = 0xFF;
1016
1017 //USB0_USBTRC0 |= 0x40; // undocumented bit
1018
1019 // enable USB
1020 USB0_CTL = USB_CTL_USBENSOFEN;
1021 USB0_USBCTRL = 0;
1022
1023 // enable reset interrupt
1024 USB0_INTEN = USB_INTEN_USBRSTEN;
1025
1026 // enable interrupt in NVIC...
Brian Silvermanb79af7c2017-06-21 23:48:02 -07001027 //NVIC_SET_PRIORITY(IRQ_USBOTG, 112);
Brian Silverman099196d2017-06-21 23:26:02 -07001028 NVIC_ENABLE_IRQ(IRQ_USBOTG);
1029
1030 // enable d+ pullup
1031 USB0_CONTROL = USB_CONTROL_DPPULLUPNONOTG;
1032}
1033
1034
1035#else // F_CPU < 20 MHz && defined(NUM_ENDPOINTS)
1036
1037void usb_init(void)
1038{
1039}
1040
1041#endif // F_CPU >= 20 MHz && defined(NUM_ENDPOINTS)