blob: 8dc8e1f2378938dc72f3ff5338a0da124e2c093d [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
66__attribute__ ((section(".usbdescriptortable"), used))
67static bdt_t table[(NUM_ENDPOINTS+1)*4];
68
69static usb_packet_t *rx_first[NUM_ENDPOINTS];
70static usb_packet_t *rx_last[NUM_ENDPOINTS];
71static usb_packet_t *tx_first[NUM_ENDPOINTS];
72static usb_packet_t *tx_last[NUM_ENDPOINTS];
73uint16_t usb_rx_byte_count_data[NUM_ENDPOINTS];
74
75static uint8_t tx_state[NUM_ENDPOINTS];
76#define TX_STATE_BOTH_FREE_EVEN_FIRST 0
77#define TX_STATE_BOTH_FREE_ODD_FIRST 1
78#define TX_STATE_EVEN_FREE 2
79#define TX_STATE_ODD_FREE 3
80#define TX_STATE_NONE_FREE_EVEN_FIRST 4
81#define TX_STATE_NONE_FREE_ODD_FIRST 5
82
83#define BDT_OWN 0x80
84#define BDT_DATA1 0x40
85#define BDT_DATA0 0x00
86#define BDT_DTS 0x08
87#define BDT_STALL 0x04
88#define BDT_PID(n) (((n) >> 2) & 15)
89
90#define BDT_DESC(count, data) (BDT_OWN | BDT_DTS \
91 | ((data) ? BDT_DATA1 : BDT_DATA0) \
92 | ((count) << 16))
93
94#define TX 1
95#define RX 0
96#define ODD 1
97#define EVEN 0
98#define DATA0 0
99#define DATA1 1
100#define index(endpoint, tx, odd) (((endpoint) << 2) | ((tx) << 1) | (odd))
101#define stat2bufferdescriptor(stat) (table + ((stat) >> 2))
102
103
104static union {
105 struct {
106 union {
107 struct {
108 uint8_t bmRequestType;
109 uint8_t bRequest;
110 };
111 uint16_t wRequestAndType;
112 };
113 uint16_t wValue;
114 uint16_t wIndex;
115 uint16_t wLength;
116 };
117 struct {
118 uint32_t word1;
119 uint32_t word2;
120 };
121} setup;
122
123
124#define GET_STATUS 0
125#define CLEAR_FEATURE 1
126#define SET_FEATURE 3
127#define SET_ADDRESS 5
128#define GET_DESCRIPTOR 6
129#define SET_DESCRIPTOR 7
130#define GET_CONFIGURATION 8
131#define SET_CONFIGURATION 9
132#define GET_INTERFACE 10
133#define SET_INTERFACE 11
134#define SYNCH_FRAME 12
135
136// SETUP always uses a DATA0 PID for the data field of the SETUP transaction.
137// transactions in the data phase start with DATA1 and toggle (figure 8-12, USB1.1)
138// Status stage uses a DATA1 PID.
139
140static uint8_t ep0_rx0_buf[EP0_SIZE] __attribute__ ((aligned (4)));
141static uint8_t ep0_rx1_buf[EP0_SIZE] __attribute__ ((aligned (4)));
142static const uint8_t *ep0_tx_ptr = NULL;
143static uint16_t ep0_tx_len;
144static uint8_t ep0_tx_bdt_bank = 0;
145static uint8_t ep0_tx_data_toggle = 0;
146uint8_t usb_rx_memory_needed = 0;
147
148volatile uint8_t usb_configuration = 0;
149volatile uint8_t usb_reboot_timer = 0;
150
151
152static void endpoint0_stall(void)
153{
154 USB0_ENDPT0 = USB_ENDPT_EPSTALL | USB_ENDPT_EPRXEN | USB_ENDPT_EPTXEN | USB_ENDPT_EPHSHK;
155}
156
157
158static void endpoint0_transmit(const void *data, uint32_t len)
159{
Brian Silvermanb79af7c2017-06-21 23:48:02 -0700160 table[index(0, TX, ep0_tx_bdt_bank)].addr = (const void *)data;
Brian Silverman099196d2017-06-21 23:26:02 -0700161 table[index(0, TX, ep0_tx_bdt_bank)].desc = BDT_DESC(len, ep0_tx_data_toggle);
162 ep0_tx_data_toggle ^= 1;
163 ep0_tx_bdt_bank ^= 1;
164}
165
166static uint8_t reply_buffer[8];
167
168static void usb_setup(void)
169{
170 const uint8_t *data = NULL;
171 uint32_t datalen = 0;
172 const usb_descriptor_list_t *list;
173 uint32_t size;
174 volatile uint8_t *reg;
175 uint8_t epconf;
176 const uint8_t *cfg;
177 int i;
178
179 switch (setup.wRequestAndType) {
180 case 0x0500: // SET_ADDRESS
181 break;
182 case 0x0900: // SET_CONFIGURATION
Brian Silverman099196d2017-06-21 23:26:02 -0700183 usb_configuration = setup.wValue;
184 reg = &USB0_ENDPT1;
185 cfg = usb_endpoint_config_table;
186 // clear all BDT entries, free any allocated memory...
187 for (i=4; i < (NUM_ENDPOINTS+1)*4; i++) {
188 if (table[i].desc & BDT_OWN) {
Brian Silvermanb79af7c2017-06-21 23:48:02 -0700189 usb_free((const usb_packet_t *)((const uint8_t *)(table[i].addr) - 8));
Brian Silverman099196d2017-06-21 23:26:02 -0700190 }
191 }
192 // free all queued packets
193 for (i=0; i < NUM_ENDPOINTS; i++) {
194 usb_packet_t *p, *n;
195 p = rx_first[i];
196 while (p) {
197 n = p->next;
198 usb_free(p);
199 p = n;
200 }
201 rx_first[i] = NULL;
202 rx_last[i] = NULL;
203 p = tx_first[i];
204 while (p) {
205 n = p->next;
206 usb_free(p);
207 p = n;
208 }
209 tx_first[i] = NULL;
210 tx_last[i] = NULL;
211 usb_rx_byte_count_data[i] = 0;
212 switch (tx_state[i]) {
213 case TX_STATE_EVEN_FREE:
214 case TX_STATE_NONE_FREE_EVEN_FIRST:
215 tx_state[i] = TX_STATE_BOTH_FREE_EVEN_FIRST;
216 break;
217 case TX_STATE_ODD_FREE:
218 case TX_STATE_NONE_FREE_ODD_FIRST:
219 tx_state[i] = TX_STATE_BOTH_FREE_ODD_FIRST;
220 break;
221 default:
222 break;
223 }
224 }
225 usb_rx_memory_needed = 0;
226 for (i=1; i <= NUM_ENDPOINTS; i++) {
227 epconf = *cfg++;
228 *reg = epconf;
229 reg += 4;
230#ifdef AUDIO_INTERFACE
231 if (i == AUDIO_RX_ENDPOINT) {
232 table[index(i, RX, EVEN)].addr = usb_audio_receive_buffer;
233 table[index(i, RX, EVEN)].desc = (AUDIO_RX_SIZE<<16) | BDT_OWN;
234 table[index(i, RX, ODD)].addr = usb_audio_receive_buffer;
235 table[index(i, RX, ODD)].desc = (AUDIO_RX_SIZE<<16) | BDT_OWN;
236 } else
237#endif
238 if (epconf & USB_ENDPT_EPRXEN) {
239 usb_packet_t *p;
240 p = usb_malloc();
241 if (p) {
242 table[index(i, RX, EVEN)].addr = p->buf;
243 table[index(i, RX, EVEN)].desc = BDT_DESC(64, 0);
244 } else {
245 table[index(i, RX, EVEN)].desc = 0;
246 usb_rx_memory_needed++;
247 }
248 p = usb_malloc();
249 if (p) {
250 table[index(i, RX, ODD)].addr = p->buf;
251 table[index(i, RX, ODD)].desc = BDT_DESC(64, 1);
252 } else {
253 table[index(i, RX, ODD)].desc = 0;
254 usb_rx_memory_needed++;
255 }
256 }
257 table[index(i, TX, EVEN)].desc = 0;
258 table[index(i, TX, ODD)].desc = 0;
259#ifdef AUDIO_INTERFACE
260 if (i == AUDIO_SYNC_ENDPOINT) {
261 table[index(i, TX, EVEN)].addr = &usb_audio_sync_feedback;
262 table[index(i, TX, EVEN)].desc = (3<<16) | BDT_OWN;
263 }
264#endif
265 }
266 break;
267 case 0x0880: // GET_CONFIGURATION
268 reply_buffer[0] = usb_configuration;
269 datalen = 1;
270 data = reply_buffer;
271 break;
272 case 0x0080: // GET_STATUS (device)
273 reply_buffer[0] = 0;
274 reply_buffer[1] = 0;
275 datalen = 2;
276 data = reply_buffer;
277 break;
278 case 0x0082: // GET_STATUS (endpoint)
279 i = setup.wIndex & 0x7F;
280 if (i > NUM_ENDPOINTS) {
281 // TODO: do we need to handle IN vs OUT here?
282 endpoint0_stall();
283 return;
284 }
285 reply_buffer[0] = 0;
286 reply_buffer[1] = 0;
Brian Silvermanb79af7c2017-06-21 23:48:02 -0700287 if (*(volatile uint8_t *)(&USB0_ENDPT0 + i * 4) & 0x02) {
288 reply_buffer[0] = 1;
289 }
Brian Silverman099196d2017-06-21 23:26:02 -0700290 data = reply_buffer;
291 datalen = 2;
292 break;
293 case 0x0102: // CLEAR_FEATURE (endpoint)
294 i = setup.wIndex & 0x7F;
295 if (i > NUM_ENDPOINTS || setup.wValue != 0) {
296 // TODO: do we need to handle IN vs OUT here?
297 endpoint0_stall();
298 return;
299 }
Brian Silvermanb79af7c2017-06-21 23:48:02 -0700300 (*(volatile uint8_t *)(&USB0_ENDPT0 + i * 4)) &= ~0x02;
Brian Silverman099196d2017-06-21 23:26:02 -0700301 // TODO: do we need to clear the data toggle here?
302 break;
303 case 0x0302: // SET_FEATURE (endpoint)
304 i = setup.wIndex & 0x7F;
305 if (i > NUM_ENDPOINTS || setup.wValue != 0) {
306 // TODO: do we need to handle IN vs OUT here?
307 endpoint0_stall();
308 return;
309 }
Brian Silvermanb79af7c2017-06-21 23:48:02 -0700310 (*(volatile uint8_t *)(&USB0_ENDPT0 + i * 4)) |= 0x02;
Brian Silverman099196d2017-06-21 23:26:02 -0700311 // TODO: do we need to clear the data toggle here?
312 break;
313 case 0x0680: // GET_DESCRIPTOR
314 case 0x0681:
Brian Silverman099196d2017-06-21 23:26:02 -0700315 for (list = usb_descriptor_list; 1; list++) {
316 if (list->addr == NULL) break;
Brian Silverman099196d2017-06-21 23:26:02 -0700317 if (setup.wValue == list->wValue && setup.wIndex == list->wIndex) {
318 data = list->addr;
319 if ((setup.wValue >> 8) == 3) {
320 // for string descriptors, use the descriptor's
321 // length field, allowing runtime configured
322 // length.
323 datalen = *(list->addr);
324 } else {
325 datalen = list->length;
326 }
Brian Silverman099196d2017-06-21 23:26:02 -0700327 goto send;
328 }
329 }
Brian Silverman099196d2017-06-21 23:26:02 -0700330 endpoint0_stall();
331 return;
332#if defined(CDC_STATUS_INTERFACE)
333 case 0x2221: // CDC_SET_CONTROL_LINE_STATE
Brian Silvermanb79af7c2017-06-21 23:48:02 -0700334 // TODO(Brian): wIndex is the interface number this is directed at. Pay
335 // attention to that.
Brian Silverman099196d2017-06-21 23:26:02 -0700336 usb_cdc_line_rtsdtr_millis = systick_millis_count;
337 usb_cdc_line_rtsdtr = setup.wValue;
Brian Silverman099196d2017-06-21 23:26:02 -0700338 break;
339 case 0x2321: // CDC_SEND_BREAK
340 break;
341 case 0x2021: // CDC_SET_LINE_CODING
Brian Silverman099196d2017-06-21 23:26:02 -0700342 return;
343#endif
344
345#if defined(MTP_INTERFACE)
346 case 0x64A1: // Cancel Request (PTP spec, 5.2.1, page 8)
347 // TODO: required by PTP spec
348 endpoint0_stall();
349 return;
350 case 0x66A1: // Device Reset (PTP spec, 5.2.3, page 10)
351 // TODO: required by PTP spec
352 endpoint0_stall();
353 return;
354 case 0x67A1: // Get Device Statis (PTP spec, 5.2.4, page 10)
355 // For now, always respond with status ok.
356 reply_buffer[0] = 0x4;
357 reply_buffer[1] = 0;
358 reply_buffer[2] = 0x01;
359 reply_buffer[3] = 0x20;
360 data = reply_buffer;
361 datalen = 4;
362 break;
363#endif
364
365// TODO: this does not work... why?
366#if defined(SEREMU_INTERFACE) || defined(KEYBOARD_INTERFACE)
367 case 0x0921: // HID SET_REPORT
Brian Silverman099196d2017-06-21 23:26:02 -0700368 return;
369 case 0x0A21: // HID SET_IDLE
370 break;
371 // case 0xC940:
372#endif
373
374#if defined(AUDIO_INTERFACE)
375 case 0x0B01: // SET_INTERFACE (alternate setting)
376 if (setup.wIndex == AUDIO_INTERFACE+1) {
377 usb_audio_transmit_setting = setup.wValue;
378 if (usb_audio_transmit_setting > 0) {
379 bdt_t *b = &table[index(AUDIO_TX_ENDPOINT, TX, EVEN)];
380 uint8_t state = tx_state[AUDIO_TX_ENDPOINT-1];
381 if (state) b++;
382 if (!(b->desc & BDT_OWN)) {
383 memset(usb_audio_transmit_buffer, 0, 176);
384 b->addr = usb_audio_transmit_buffer;
385 b->desc = (176 << 16) | BDT_OWN;
386 tx_state[AUDIO_TX_ENDPOINT-1] = state ^ 1;
387 }
388 }
389 } else if (setup.wIndex == AUDIO_INTERFACE+2) {
390 usb_audio_receive_setting = setup.wValue;
391 } else {
392 endpoint0_stall();
393 return;
394 }
395 break;
396 case 0x0A81: // GET_INTERFACE (alternate setting)
397 datalen = 1;
398 data = reply_buffer;
399 if (setup.wIndex == AUDIO_INTERFACE+1) {
400 reply_buffer[0] = usb_audio_transmit_setting;
401 } else if (setup.wIndex == AUDIO_INTERFACE+2) {
402 reply_buffer[0] = usb_audio_receive_setting;
403 } else {
404 endpoint0_stall();
405 return;
406 }
407 break;
408 case 0x0121: // SET FEATURE
409 case 0x0221:
410 case 0x0321:
411 case 0x0421:
412 // handle these on the next packet. See usb_audio_set_feature()
413 return;
414 case 0x81A1: // GET FEATURE
415 case 0x82A1:
416 case 0x83A1:
417 case 0x84A1:
418 if (usb_audio_get_feature(&setup, reply_buffer, &datalen)) {
419 data = reply_buffer;
420 }
421 else {
422 endpoint0_stall();
423 return;
424 }
425 break;
426
427 case 0x81A2: // GET_CUR (wValue=0, wIndex=interface, wLength=len)
428 if (setup.wLength >= 3) {
429 reply_buffer[0] = 44100 & 255;
430 reply_buffer[1] = 44100 >> 8;
431 reply_buffer[2] = 0;
432 datalen = 3;
433 data = reply_buffer;
434 } else {
435 endpoint0_stall();
436 return;
437 }
438 break;
439#endif
440
441#if defined(MULTITOUCH_INTERFACE)
442 case 0x01A1:
443 if (setup.wValue == 0x0300 && setup.wIndex == MULTITOUCH_INTERFACE) {
444 reply_buffer[0] = MULTITOUCH_FINGERS;
445 data = reply_buffer;
446 datalen = 1;
447 } else {
448 endpoint0_stall();
449 return;
450 }
451 break;
452#endif
453 default:
454 endpoint0_stall();
455 return;
456 }
457 send:
Brian Silverman099196d2017-06-21 23:26:02 -0700458
459 if (datalen > setup.wLength) datalen = setup.wLength;
460 size = datalen;
461 if (size > EP0_SIZE) size = EP0_SIZE;
462 endpoint0_transmit(data, size);
463 data += size;
464 datalen -= size;
465 if (datalen == 0 && size < EP0_SIZE) return;
466
467 size = datalen;
468 if (size > EP0_SIZE) size = EP0_SIZE;
469 endpoint0_transmit(data, size);
470 data += size;
471 datalen -= size;
472 if (datalen == 0 && size < EP0_SIZE) return;
473
474 ep0_tx_ptr = data;
475 ep0_tx_len = datalen;
476}
477
478
479
480//A bulk endpoint's toggle sequence is initialized to DATA0 when the endpoint
481//experiences any configuration event (configuration events are explained in
482//Sections 9.1.1.5 and 9.4.5).
483
484//Configuring a device or changing an alternate setting causes all of the status
485//and configuration values associated with endpoints in the affected interfaces
486//to be set to their default values. This includes setting the data toggle of
487//any endpoint using data toggles to the value DATA0.
488
489//For endpoints using data toggle, regardless of whether an endpoint has the
490//Halt feature set, a ClearFeature(ENDPOINT_HALT) request always results in the
491//data toggle being reinitialized to DATA0.
492
493
494
495// #define stat2bufferdescriptor(stat) (table + ((stat) >> 2))
496
497static void usb_control(uint32_t stat)
498{
499 bdt_t *b;
500 uint32_t pid, size;
Brian Silvermanb79af7c2017-06-21 23:48:02 -0700501 const uint8_t *buf;
Brian Silverman099196d2017-06-21 23:26:02 -0700502 const uint8_t *data;
503
504 b = stat2bufferdescriptor(stat);
505 pid = BDT_PID(b->desc);
Brian Silverman099196d2017-06-21 23:26:02 -0700506 buf = b->addr;
Brian Silverman099196d2017-06-21 23:26:02 -0700507
508 switch (pid) {
509 case 0x0D: // Setup received from host
Brian Silverman099196d2017-06-21 23:26:02 -0700510 // grab the 8 byte setup info
Brian Silvermanb79af7c2017-06-21 23:48:02 -0700511 setup.word1 = *(const uint32_t *)(buf);
512 setup.word2 = *(const uint32_t *)(buf + 4);
Brian Silverman099196d2017-06-21 23:26:02 -0700513
514 // give the buffer back
515 b->desc = BDT_DESC(EP0_SIZE, DATA1);
Brian Silverman099196d2017-06-21 23:26:02 -0700516
517 // clear any leftover pending IN transactions
518 ep0_tx_ptr = NULL;
519 if (ep0_tx_data_toggle) {
520 }
Brian Silverman099196d2017-06-21 23:26:02 -0700521 table[index(0, TX, EVEN)].desc = 0;
522 table[index(0, TX, ODD)].desc = 0;
523 // first IN after Setup is always DATA1
524 ep0_tx_data_toggle = 1;
525
Brian Silverman099196d2017-06-21 23:26:02 -0700526 // actually "do" the setup request
527 usb_setup();
528 // unfreeze the USB, now that we're ready
529 USB0_CTL = USB_CTL_USBENSOFEN; // clear TXSUSPENDTOKENBUSY bit
530 break;
531 case 0x01: // OUT transaction received from host
532 case 0x02:
Brian Silverman099196d2017-06-21 23:26:02 -0700533#ifdef CDC_STATUS_INTERFACE
Brian Silvermanb79af7c2017-06-21 23:48:02 -0700534 // TODO(Brian): wIndex is the interface number this is directed at. Pay
535 // attention to that.
Brian Silverman099196d2017-06-21 23:26:02 -0700536 if (setup.wRequestAndType == 0x2021 /*CDC_SET_LINE_CODING*/) {
537 int i;
538 uint8_t *dst = (uint8_t *)usb_cdc_line_coding;
Brian Silverman099196d2017-06-21 23:26:02 -0700539 for (i=0; i<7; i++) {
Brian Silverman099196d2017-06-21 23:26:02 -0700540 *dst++ = *buf++;
541 }
Brian Silverman099196d2017-06-21 23:26:02 -0700542 if (usb_cdc_line_coding[0] == 134) usb_reboot_timer = 15;
543 endpoint0_transmit(NULL, 0);
544 }
545#endif
546#ifdef KEYBOARD_INTERFACE
547 if (setup.word1 == 0x02000921 && setup.word2 == ((1<<16)|KEYBOARD_INTERFACE)) {
548 keyboard_leds = buf[0];
549 endpoint0_transmit(NULL, 0);
550 }
551#endif
552#ifdef SEREMU_INTERFACE
553 if (setup.word1 == 0x03000921 && setup.word2 == ((4<<16)|SEREMU_INTERFACE)
554 && buf[0] == 0xA9 && buf[1] == 0x45 && buf[2] == 0xC2 && buf[3] == 0x6B) {
555 usb_reboot_timer = 5;
556 endpoint0_transmit(NULL, 0);
557 }
558#endif
559#ifdef AUDIO_INTERFACE
560 if (usb_audio_set_feature(&setup, buf)) {
561 endpoint0_transmit(NULL, 0);
562 }
563#endif
564 // give the buffer back
565 b->desc = BDT_DESC(EP0_SIZE, DATA1);
566 break;
567
568 case 0x09: // IN transaction completed to host
Brian Silverman099196d2017-06-21 23:26:02 -0700569
570 // send remaining data, if any...
571 data = ep0_tx_ptr;
572 if (data) {
573 size = ep0_tx_len;
574 if (size > EP0_SIZE) size = EP0_SIZE;
575 endpoint0_transmit(data, size);
576 data += size;
577 ep0_tx_len -= size;
578 ep0_tx_ptr = (ep0_tx_len > 0 || size == EP0_SIZE) ? data : NULL;
579 }
580
581 if (setup.bRequest == 5 && setup.bmRequestType == 0) {
582 setup.bRequest = 0;
Brian Silverman099196d2017-06-21 23:26:02 -0700583 USB0_ADDR = setup.wValue;
584 }
585
586 break;
Brian Silverman099196d2017-06-21 23:26:02 -0700587 }
588 USB0_CTL = USB_CTL_USBENSOFEN; // clear TXSUSPENDTOKENBUSY bit
589}
590
591
592
593
594
595
596usb_packet_t *usb_rx(uint32_t endpoint)
597{
598 usb_packet_t *ret;
599 endpoint--;
600 if (endpoint >= NUM_ENDPOINTS) return NULL;
601 __disable_irq();
602 ret = rx_first[endpoint];
603 if (ret) {
604 rx_first[endpoint] = ret->next;
605 usb_rx_byte_count_data[endpoint] -= ret->len;
606 }
607 __enable_irq();
Brian Silverman099196d2017-06-21 23:26:02 -0700608 return ret;
609}
610
611static uint32_t usb_queue_byte_count(const usb_packet_t *p)
612{
613 uint32_t count=0;
614
615 __disable_irq();
616 for ( ; p; p = p->next) {
617 count += p->len;
618 }
619 __enable_irq();
620 return count;
621}
622
Brian Silverman099196d2017-06-21 23:26:02 -0700623uint32_t usb_tx_byte_count(uint32_t endpoint)
624{
625 endpoint--;
626 if (endpoint >= NUM_ENDPOINTS) return 0;
627 return usb_queue_byte_count(tx_first[endpoint]);
628}
629
630uint32_t usb_tx_packet_count(uint32_t endpoint)
631{
632 const usb_packet_t *p;
633 uint32_t count=0;
634
635 endpoint--;
636 if (endpoint >= NUM_ENDPOINTS) return 0;
637 __disable_irq();
638 for (p = tx_first[endpoint]; p; p = p->next) count++;
639 __enable_irq();
640 return count;
641}
642
643
644// Called from usb_free, but only when usb_rx_memory_needed > 0, indicating
645// receive endpoints are starving for memory. The intention is to give
646// endpoints needing receive memory priority over the user's code, which is
647// likely calling usb_malloc to obtain memory for transmitting. When the
648// user is creating data very quickly, their consumption could starve reception
649// without this prioritization. The packet buffer (input) is assigned to the
650// first endpoint needing memory.
651//
Brian Silvermanb79af7c2017-06-21 23:48:02 -0700652void usb_rx_memory(const usb_packet_t *packet)
Brian Silverman099196d2017-06-21 23:26:02 -0700653{
654 unsigned int i;
655 const uint8_t *cfg;
656
657 cfg = usb_endpoint_config_table;
Brian Silverman099196d2017-06-21 23:26:02 -0700658 __disable_irq();
659 for (i=1; i <= NUM_ENDPOINTS; i++) {
660#ifdef AUDIO_INTERFACE
661 if (i == AUDIO_RX_ENDPOINT) continue;
662#endif
663 if (*cfg++ & USB_ENDPT_EPRXEN) {
664 if (table[index(i, RX, EVEN)].desc == 0) {
665 table[index(i, RX, EVEN)].addr = packet->buf;
666 table[index(i, RX, EVEN)].desc = BDT_DESC(64, 0);
667 usb_rx_memory_needed--;
668 __enable_irq();
Brian Silverman099196d2017-06-21 23:26:02 -0700669 return;
670 }
671 if (table[index(i, RX, ODD)].desc == 0) {
672 table[index(i, RX, ODD)].addr = packet->buf;
673 table[index(i, RX, ODD)].desc = BDT_DESC(64, 1);
674 usb_rx_memory_needed--;
675 __enable_irq();
Brian Silverman099196d2017-06-21 23:26:02 -0700676 return;
677 }
678 }
679 }
680 __enable_irq();
681 // we should never reach this point. If we get here, it means
682 // usb_rx_memory_needed was set greater than zero, but no memory
683 // was actually needed.
684 usb_rx_memory_needed = 0;
685 usb_free(packet);
686 return;
687}
688
689//#define index(endpoint, tx, odd) (((endpoint) << 2) | ((tx) << 1) | (odd))
690//#define stat2bufferdescriptor(stat) (table + ((stat) >> 2))
691
692void usb_tx(uint32_t endpoint, usb_packet_t *packet)
693{
694 bdt_t *b = &table[index(endpoint, TX, EVEN)];
695 uint8_t next;
696
697 endpoint--;
698 if (endpoint >= NUM_ENDPOINTS) return;
699 __disable_irq();
Brian Silverman099196d2017-06-21 23:26:02 -0700700 switch (tx_state[endpoint]) {
701 case TX_STATE_BOTH_FREE_EVEN_FIRST:
702 next = TX_STATE_ODD_FREE;
703 break;
704 case TX_STATE_BOTH_FREE_ODD_FIRST:
705 b++;
706 next = TX_STATE_EVEN_FREE;
707 break;
708 case TX_STATE_EVEN_FREE:
709 next = TX_STATE_NONE_FREE_ODD_FIRST;
710 break;
711 case TX_STATE_ODD_FREE:
712 b++;
713 next = TX_STATE_NONE_FREE_EVEN_FIRST;
714 break;
715 default:
716 if (tx_first[endpoint] == NULL) {
717 tx_first[endpoint] = packet;
718 } else {
719 tx_last[endpoint]->next = packet;
720 }
721 tx_last[endpoint] = packet;
722 __enable_irq();
723 return;
724 }
725 tx_state[endpoint] = next;
726 b->addr = packet->buf;
727 b->desc = BDT_DESC(packet->len, ((uint32_t)b & 8) ? DATA1 : DATA0);
728 __enable_irq();
729}
730
731void usb_tx_isochronous(uint32_t endpoint, void *data, uint32_t len)
732{
733 bdt_t *b = &table[index(endpoint, TX, EVEN)];
734 uint8_t next, state;
735
736 endpoint--;
737 if (endpoint >= NUM_ENDPOINTS) return;
738 __disable_irq();
739 state = tx_state[endpoint];
740 if (state == 0) {
741 next = 1;
742 } else {
743 b++;
744 next = 0;
745 }
746 tx_state[endpoint] = next;
747 b->addr = data;
748 b->desc = (len << 16) | BDT_OWN;
749 __enable_irq();
750}
751
752
753
754
755void _reboot_Teensyduino_(void)
756{
757 // TODO: initialize R0 with a code....
758 __asm__ volatile("bkpt");
759}
760
761
762
763void usb_isr(void)
764{
765 uint8_t status, stat, t;
766
Brian Silverman099196d2017-06-21 23:26:02 -0700767 restart:
768 status = USB0_ISTAT;
769
770 if ((status & USB_ISTAT_SOFTOK /* 04 */ )) {
771 if (usb_configuration) {
772 t = usb_reboot_timer;
773 if (t) {
774 usb_reboot_timer = --t;
775 if (!t) _reboot_Teensyduino_();
776 }
777#ifdef CDC_DATA_INTERFACE
Brian Silvermanb79af7c2017-06-21 23:48:02 -0700778 t = *usb_cdc_transmit_flush_timer;
Brian Silverman099196d2017-06-21 23:26:02 -0700779 if (t) {
Brian Silvermanb79af7c2017-06-21 23:48:02 -0700780 *usb_cdc_transmit_flush_timer = --t;
781 if (t == 0) usb_serial_flush_callback(0);
782 }
783#endif
784#ifdef CDC2_DATA_INTERFACE
785 t = *usb_cdc2_transmit_flush_timer;
786 if (t) {
787 *usb_cdc2_transmit_flush_timer = --t;
788 if (t == 0) usb_serial_flush_callback(1);
Brian Silverman099196d2017-06-21 23:26:02 -0700789 }
790#endif
791#ifdef SEREMU_INTERFACE
792 t = usb_seremu_transmit_flush_timer;
793 if (t) {
794 usb_seremu_transmit_flush_timer = --t;
795 if (t == 0) usb_seremu_flush_callback();
796 }
797#endif
798#ifdef MIDI_INTERFACE
799 usb_midi_flush_output();
800#endif
801#ifdef FLIGHTSIM_INTERFACE
802 usb_flightsim_flush_callback();
803#endif
804#ifdef MULTITOUCH_INTERFACE
805 usb_touchscreen_update_callback();
806#endif
807 }
808 USB0_ISTAT = USB_ISTAT_SOFTOK;
809 }
810
811 if ((status & USB_ISTAT_TOKDNE /* 08 */ )) {
812 uint8_t endpoint;
813 stat = USB0_STAT;
Brian Silverman099196d2017-06-21 23:26:02 -0700814 endpoint = stat >> 4;
815 if (endpoint == 0) {
816 usb_control(stat);
817 } else {
818 bdt_t *b = stat2bufferdescriptor(stat);
Brian Silvermanb79af7c2017-06-21 23:48:02 -0700819#pragma GCC diagnostic push
820#pragma GCC diagnostic ignored "-Wcast-qual"
Brian Silverman099196d2017-06-21 23:26:02 -0700821 usb_packet_t *packet = (usb_packet_t *)((uint8_t *)(b->addr) - 8);
Brian Silvermanb79af7c2017-06-21 23:48:02 -0700822#pragma GCC diagnostic pop
Brian Silverman099196d2017-06-21 23:26:02 -0700823 endpoint--; // endpoint is index to zero-based arrays
824
825#ifdef AUDIO_INTERFACE
826 if ((endpoint == AUDIO_TX_ENDPOINT-1) && (stat & 0x08)) {
827 unsigned int len;
828 len = usb_audio_transmit_callback();
829 if (len > 0) {
830 b = (bdt_t *)((uint32_t)b ^ 8);
831 b->addr = usb_audio_transmit_buffer;
832 b->desc = (len << 16) | BDT_OWN;
833 tx_state[endpoint] ^= 1;
834 }
835 } else if ((endpoint == AUDIO_RX_ENDPOINT-1) && !(stat & 0x08)) {
836 usb_audio_receive_callback(b->desc >> 16);
837 b->addr = usb_audio_receive_buffer;
838 b->desc = (AUDIO_RX_SIZE << 16) | BDT_OWN;
839 } else if ((endpoint == AUDIO_SYNC_ENDPOINT-1) && (stat & 0x08)) {
840 b = (bdt_t *)((uint32_t)b ^ 8);
841 b->addr = &usb_audio_sync_feedback;
842 b->desc = (3 << 16) | BDT_OWN;
843 tx_state[endpoint] ^= 1;
844 } else
845#endif
846 if (stat & 0x08) { // transmit
847 usb_free(packet);
848 packet = tx_first[endpoint];
849 if (packet) {
Brian Silverman099196d2017-06-21 23:26:02 -0700850 tx_first[endpoint] = packet->next;
851 b->addr = packet->buf;
852 switch (tx_state[endpoint]) {
853 case TX_STATE_BOTH_FREE_EVEN_FIRST:
854 tx_state[endpoint] = TX_STATE_ODD_FREE;
855 break;
856 case TX_STATE_BOTH_FREE_ODD_FIRST:
857 tx_state[endpoint] = TX_STATE_EVEN_FREE;
858 break;
859 case TX_STATE_EVEN_FREE:
860 tx_state[endpoint] = TX_STATE_NONE_FREE_ODD_FIRST;
861 break;
862 case TX_STATE_ODD_FREE:
863 tx_state[endpoint] = TX_STATE_NONE_FREE_EVEN_FIRST;
864 break;
865 default:
866 break;
867 }
868 b->desc = BDT_DESC(packet->len,
869 ((uint32_t)b & 8) ? DATA1 : DATA0);
870 } else {
Brian Silverman099196d2017-06-21 23:26:02 -0700871 switch (tx_state[endpoint]) {
872 case TX_STATE_BOTH_FREE_EVEN_FIRST:
873 case TX_STATE_BOTH_FREE_ODD_FIRST:
874 break;
875 case TX_STATE_EVEN_FREE:
876 tx_state[endpoint] = TX_STATE_BOTH_FREE_EVEN_FIRST;
877 break;
878 case TX_STATE_ODD_FREE:
879 tx_state[endpoint] = TX_STATE_BOTH_FREE_ODD_FIRST;
880 break;
881 default:
882 tx_state[endpoint] = ((uint32_t)b & 8) ?
883 TX_STATE_ODD_FREE : TX_STATE_EVEN_FREE;
884 break;
885 }
886 }
887 } else { // receive
888 packet->len = b->desc >> 16;
889 if (packet->len > 0) {
890 packet->index = 0;
891 packet->next = NULL;
892 if (rx_first[endpoint] == NULL) {
Brian Silverman099196d2017-06-21 23:26:02 -0700893 rx_first[endpoint] = packet;
894 } else {
Brian Silverman099196d2017-06-21 23:26:02 -0700895 rx_last[endpoint]->next = packet;
896 }
897 rx_last[endpoint] = packet;
898 usb_rx_byte_count_data[endpoint] += packet->len;
899 // TODO: implement a per-endpoint maximum # of allocated
900 // packets, so a flood of incoming data on 1 endpoint
901 // doesn't starve the others if the user isn't reading
902 // it regularly
903 packet = usb_malloc();
904 if (packet) {
905 b->addr = packet->buf;
906 b->desc = BDT_DESC(64,
907 ((uint32_t)b & 8) ? DATA1 : DATA0);
908 } else {
Brian Silverman099196d2017-06-21 23:26:02 -0700909 b->desc = 0;
910 usb_rx_memory_needed++;
911 }
912 } else {
913 b->desc = BDT_DESC(64, ((uint32_t)b & 8) ? DATA1 : DATA0);
914 }
915 }
916
917 }
918 USB0_ISTAT = USB_ISTAT_TOKDNE;
919 goto restart;
920 }
921
922
923
924 if (status & USB_ISTAT_USBRST /* 01 */ ) {
Brian Silverman099196d2017-06-21 23:26:02 -0700925 // initialize BDT toggle bits
926 USB0_CTL = USB_CTL_ODDRST;
927 ep0_tx_bdt_bank = 0;
928
929 // set up buffers to receive Setup and OUT packets
930 table[index(0, RX, EVEN)].desc = BDT_DESC(EP0_SIZE, 0);
931 table[index(0, RX, EVEN)].addr = ep0_rx0_buf;
932 table[index(0, RX, ODD)].desc = BDT_DESC(EP0_SIZE, 0);
933 table[index(0, RX, ODD)].addr = ep0_rx1_buf;
934 table[index(0, TX, EVEN)].desc = 0;
935 table[index(0, TX, ODD)].desc = 0;
936
937 // activate endpoint 0
938 USB0_ENDPT0 = USB_ENDPT_EPRXEN | USB_ENDPT_EPTXEN | USB_ENDPT_EPHSHK;
939
940 // clear all ending interrupts
941 USB0_ERRSTAT = 0xFF;
942 USB0_ISTAT = 0xFF;
943
944 // set the address to zero during enumeration
945 USB0_ADDR = 0;
946
947 // enable other interrupts
948 USB0_ERREN = 0xFF;
949 USB0_INTEN = USB_INTEN_TOKDNEEN |
950 USB_INTEN_SOFTOKEN |
951 USB_INTEN_STALLEN |
952 USB_INTEN_ERROREN |
953 USB_INTEN_USBRSTEN |
954 USB_INTEN_SLEEPEN;
955
956 // is this necessary?
957 USB0_CTL = USB_CTL_USBENSOFEN;
958 return;
959 }
960
961
962 if ((status & USB_ISTAT_STALL /* 80 */ )) {
Brian Silverman099196d2017-06-21 23:26:02 -0700963 USB0_ENDPT0 = USB_ENDPT_EPRXEN | USB_ENDPT_EPTXEN | USB_ENDPT_EPHSHK;
964 USB0_ISTAT = USB_ISTAT_STALL;
965 }
966 if ((status & USB_ISTAT_ERROR /* 02 */ )) {
967 uint8_t err = USB0_ERRSTAT;
968 USB0_ERRSTAT = err;
Brian Silverman099196d2017-06-21 23:26:02 -0700969 USB0_ISTAT = USB_ISTAT_ERROR;
970 }
971
972 if ((status & USB_ISTAT_SLEEP /* 10 */ )) {
Brian Silverman099196d2017-06-21 23:26:02 -0700973 USB0_ISTAT = USB_ISTAT_SLEEP;
974 }
975
976}
977
978
979
980void usb_init(void)
981{
982 int i;
983
Brian Silverman099196d2017-06-21 23:26:02 -0700984 usb_init_serialnumber();
985
986 for (i=0; i <= NUM_ENDPOINTS*4; i++) {
987 table[i].desc = 0;
988 table[i].addr = 0;
989 }
990
991 // this basically follows the flowchart in the Kinetis
992 // Quick Reference User Guide, Rev. 1, 03/2012, page 141
993
994 // assume 48 MHz clock already running
995 // SIM - enable clock
996 SIM_SCGC4 |= SIM_SCGC4_USBOTG;
997#ifdef HAS_KINETIS_MPU
998 MPU_RGDAAC0 |= 0x03000000;
999#endif
1000#if F_CPU == 180000000 || F_CPU == 216000000
1001 // if using IRC48M, turn on the USB clock recovery hardware
1002 USB0_CLK_RECOVER_IRC_EN = USB_CLK_RECOVER_IRC_EN_IRC_EN | USB_CLK_RECOVER_IRC_EN_REG_EN;
1003 USB0_CLK_RECOVER_CTRL = USB_CLK_RECOVER_CTRL_CLOCK_RECOVER_EN |
1004 USB_CLK_RECOVER_CTRL_RESTART_IFRTRIM_EN;
1005#endif
1006 // reset USB module
1007 //USB0_USBTRC0 = USB_USBTRC_USBRESET;
1008 //while ((USB0_USBTRC0 & USB_USBTRC_USBRESET) != 0) ; // wait for reset to end
1009
1010 // set desc table base addr
1011 USB0_BDTPAGE1 = ((uint32_t)table) >> 8;
1012 USB0_BDTPAGE2 = ((uint32_t)table) >> 16;
1013 USB0_BDTPAGE3 = ((uint32_t)table) >> 24;
1014
1015 // clear all ISR flags
1016 USB0_ISTAT = 0xFF;
1017 USB0_ERRSTAT = 0xFF;
1018 USB0_OTGISTAT = 0xFF;
1019
1020 //USB0_USBTRC0 |= 0x40; // undocumented bit
1021
1022 // enable USB
1023 USB0_CTL = USB_CTL_USBENSOFEN;
1024 USB0_USBCTRL = 0;
1025
1026 // enable reset interrupt
1027 USB0_INTEN = USB_INTEN_USBRSTEN;
1028
1029 // enable interrupt in NVIC...
Brian Silvermanb79af7c2017-06-21 23:48:02 -07001030 //NVIC_SET_PRIORITY(IRQ_USBOTG, 112);
Brian Silverman099196d2017-06-21 23:26:02 -07001031 NVIC_ENABLE_IRQ(IRQ_USBOTG);
1032
1033 // enable d+ pullup
1034 USB0_CONTROL = USB_CONTROL_DPPULLUPNONOTG;
1035}
1036
1037
1038#else // F_CPU < 20 MHz && defined(NUM_ENDPOINTS)
1039
1040void usb_init(void)
1041{
1042}
1043
1044#endif // F_CPU >= 20 MHz && defined(NUM_ENDPOINTS)