1 /*
2 * Copyright 2012 Jared Boone
3 *
4 * This file is part of HackRF.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2, or (at your option)
9 * any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; see the file COPYING. If not, write to
18 * the Free Software Foundation, Inc., 51 Franklin Street,
19 * Boston, MA 02110-1301, USA.
20 */
21
22 #include <stdint.h>
23 #include <stdbool.h>
24
25 #include "usb.h"
26 #include "usb_type.h"
27 #include "usb_queue.h"
28 #include "usb_standard_request.h"
29
30 #include <libopencm3/lpc43xx/creg.h>
31 #include <libopencm3/lpc43xx/m4/nvic.h>
32 #include <libopencm3/lpc43xx/rgu.h>
33 #include <libopencm3/lpc43xx/usb.h>
34
35 usb_device_t* usb_device_usb0 = 0;
36
37 usb_queue_head_t usb_qh[12] ATTR_ALIGNED(2048);
38
39 #define USB_QH_INDEX(endpoint_address) (((endpoint_address & 0xF) * 2) + ((endpoint_address >> 7) & 1))
40
usb_queue_head(const uint_fast8_t endpoint_address)41 usb_queue_head_t* usb_queue_head(
42 const uint_fast8_t endpoint_address
43 ) {
44 return &usb_qh[USB_QH_INDEX(endpoint_address)];
45 }
46
usb_endpoint_from_address(const uint_fast8_t endpoint_address)47 static usb_endpoint_t* usb_endpoint_from_address(
48 const uint_fast8_t endpoint_address
49 ) {
50 return (usb_endpoint_t*)usb_queue_head(endpoint_address)->_reserved_0;
51 }
52
usb_endpoint_address(const usb_transfer_direction_t direction,const uint_fast8_t number)53 static uint_fast8_t usb_endpoint_address(
54 const usb_transfer_direction_t direction,
55 const uint_fast8_t number
56 ) {
57 return ((direction == USB_TRANSFER_DIRECTION_IN) ? 0x80 : 0x00) + number;
58 }
59
usb_endpoint_is_in(const uint_fast8_t endpoint_address)60 static bool usb_endpoint_is_in(const uint_fast8_t endpoint_address) {
61 return (endpoint_address & 0x80) ? true : false;
62 }
63
usb_endpoint_number(const uint_fast8_t endpoint_address)64 static uint_fast8_t usb_endpoint_number(const uint_fast8_t endpoint_address) {
65 return (endpoint_address & 0xF);
66 }
67
usb_peripheral_reset()68 void usb_peripheral_reset() {
69 RESET_CTRL0 = RESET_CTRL0_USB0_RST;
70 RESET_CTRL0 = 0;
71
72 while( (RESET_ACTIVE_STATUS0 & RESET_CTRL0_USB0_RST) == 0 );
73 }
74
usb_phy_enable()75 void usb_phy_enable() {
76 CREG_CREG0 &= ~CREG_CREG0_USB0PHY;
77 }
78
usb_clear_pending_interrupts(const uint32_t mask)79 static void usb_clear_pending_interrupts(const uint32_t mask) {
80 USB0_ENDPTNAK = mask;
81 USB0_ENDPTNAKEN = mask;
82 USB0_USBSTS_D = mask;
83 USB0_ENDPTSETUPSTAT = USB0_ENDPTSETUPSTAT & mask;
84 USB0_ENDPTCOMPLETE = USB0_ENDPTCOMPLETE & mask;
85 }
86
usb_clear_all_pending_interrupts()87 static void usb_clear_all_pending_interrupts() {
88 usb_clear_pending_interrupts(0xFFFFFFFF);
89 }
90
usb_wait_for_endpoint_priming_to_finish(const uint32_t mask)91 static void usb_wait_for_endpoint_priming_to_finish(const uint32_t mask) {
92 // Wait until controller has parsed new transfer descriptors and prepared
93 // receive buffers.
94 while( USB0_ENDPTPRIME & mask );
95 }
96
usb_flush_endpoints(const uint32_t mask)97 static void usb_flush_endpoints(const uint32_t mask) {
98 // Clear any primed buffers. If a packet is in progress, that transfer
99 // will continue until completion.
100 USB0_ENDPTFLUSH = mask;
101 }
102
usb_wait_for_endpoint_flushing_to_finish(const uint32_t mask)103 static void usb_wait_for_endpoint_flushing_to_finish(const uint32_t mask) {
104 // Wait until controller has flushed all endpoints / cleared any primed
105 // buffers.
106 while( USB0_ENDPTFLUSH & mask );
107 }
108
usb_flush_primed_endpoints(const uint32_t mask)109 static void usb_flush_primed_endpoints(const uint32_t mask) {
110 usb_wait_for_endpoint_priming_to_finish(mask);
111 usb_flush_endpoints(mask);
112 usb_wait_for_endpoint_flushing_to_finish(mask);
113 }
114
usb_flush_all_primed_endpoints()115 static void usb_flush_all_primed_endpoints() {
116 usb_flush_primed_endpoints(0xFFFFFFFF);
117 }
118
usb_endpoint_set_type(const usb_endpoint_t * const endpoint,const usb_transfer_type_t transfer_type)119 static void usb_endpoint_set_type(
120 const usb_endpoint_t* const endpoint,
121 const usb_transfer_type_t transfer_type
122 ) {
123 // NOTE: UM10503 section 23.6.24 "Endpoint 1 to 5 control registers" says
124 // that the disabled side of an endpoint must be set to a non-control type
125 // (e.g. bulk, interrupt, or iso).
126 const uint_fast8_t endpoint_number = usb_endpoint_number(endpoint->address);
127 USB0_ENDPTCTRL(endpoint_number)
128 = ( USB0_ENDPTCTRL(endpoint_number)
129 & ~(USB0_ENDPTCTRL_TXT1_0_MASK | USB0_ENDPTCTRL_RXT_MASK)
130 )
131 | ( USB0_ENDPTCTRL_TXT1_0(transfer_type)
132 | USB0_ENDPTCTRL_RXT(transfer_type)
133 );
134 }
135
usb_endpoint_enable(const usb_endpoint_t * const endpoint)136 static void usb_endpoint_enable(
137 const usb_endpoint_t* const endpoint
138 ) {
139 const uint_fast8_t endpoint_number = usb_endpoint_number(endpoint->address);
140 if( usb_endpoint_is_in(endpoint->address) ) {
141 USB0_ENDPTCTRL(endpoint_number) |= (USB0_ENDPTCTRL_TXE | USB0_ENDPTCTRL_TXR);
142 } else {
143 USB0_ENDPTCTRL(endpoint_number) |= (USB0_ENDPTCTRL_RXE | USB0_ENDPTCTRL_RXR);
144 }
145 }
146
usb_endpoint_clear_pending_interrupts(const usb_endpoint_t * const endpoint)147 static void usb_endpoint_clear_pending_interrupts(
148 const usb_endpoint_t* const endpoint
149 ) {
150 const uint_fast8_t endpoint_number = usb_endpoint_number(endpoint->address);
151 if( usb_endpoint_is_in(endpoint->address) ) {
152 usb_clear_pending_interrupts(USB0_ENDPTCOMPLETE_ETCE(1 << endpoint_number));
153 } else {
154 usb_clear_pending_interrupts(USB0_ENDPTCOMPLETE_ERCE(1 << endpoint_number));
155 }
156 }
157
usb_endpoint_disable(const usb_endpoint_t * const endpoint)158 void usb_endpoint_disable(
159 const usb_endpoint_t* const endpoint
160 ) {
161 const uint_fast8_t endpoint_number = usb_endpoint_number(endpoint->address);
162 if( usb_endpoint_is_in(endpoint->address) ) {
163 USB0_ENDPTCTRL(endpoint_number) &= ~(USB0_ENDPTCTRL_TXE);
164 } else {
165 USB0_ENDPTCTRL(endpoint_number) &= ~(USB0_ENDPTCTRL_RXE);
166 }
167 usb_queue_flush_endpoint(endpoint);
168 usb_endpoint_clear_pending_interrupts(endpoint);
169 usb_endpoint_flush(endpoint);
170 }
171
usb_endpoint_prime(const usb_endpoint_t * const endpoint,usb_transfer_descriptor_t * const first_td)172 void usb_endpoint_prime(
173 const usb_endpoint_t* const endpoint,
174 usb_transfer_descriptor_t* const first_td
175 ) {
176 usb_queue_head_t* const qh = usb_queue_head(endpoint->address);
177
178 qh->next_dtd_pointer = first_td;
179 qh->total_bytes
180 &= ~( USB_TD_DTD_TOKEN_STATUS_ACTIVE
181 | USB_TD_DTD_TOKEN_STATUS_HALTED
182 )
183 ;
184
185 const uint_fast8_t endpoint_number = usb_endpoint_number(endpoint->address);
186 if( usb_endpoint_is_in(endpoint->address) ) {
187 USB0_ENDPTPRIME = USB0_ENDPTPRIME_PETB(1 << endpoint_number);
188 } else {
189 USB0_ENDPTPRIME = USB0_ENDPTPRIME_PERB(1 << endpoint_number);
190 }
191 }
192
usb_endpoint_is_priming(const usb_endpoint_t * const endpoint)193 static bool usb_endpoint_is_priming(
194 const usb_endpoint_t* const endpoint
195 ) {
196 const uint_fast8_t endpoint_number = usb_endpoint_number(endpoint->address);
197 if( usb_endpoint_is_in(endpoint->address) ) {
198 return USB0_ENDPTPRIME & USB0_ENDPTPRIME_PETB(1 << endpoint_number);
199 } else {
200 return USB0_ENDPTPRIME & USB0_ENDPTPRIME_PERB(1 << endpoint_number);
201 }
202 }
203
204 // Schedule an already filled-in transfer descriptor for execution on
205 // the given endpoint, waiting until the endpoint has finished.
usb_endpoint_schedule_wait(const usb_endpoint_t * const endpoint,usb_transfer_descriptor_t * const td)206 void usb_endpoint_schedule_wait(
207 const usb_endpoint_t* const endpoint,
208 usb_transfer_descriptor_t* const td
209 ) {
210 // Ensure that endpoint is ready to be primed.
211 // It may have been flushed due to an aborted transaction.
212 // TODO: This should be preceded by a flush?
213 while( usb_endpoint_is_ready(endpoint) );
214
215 td->next_dtd_pointer = USB_TD_NEXT_DTD_POINTER_TERMINATE;
216
217 usb_endpoint_prime(endpoint, td);
218 }
219
220 // Schedule an already filled-in transfer descriptor for execution on
221 // the given endpoint, appending to the end of the endpoint's queue if
222 // there are pending TDs. Note that this requires that one knows the
223 // tail of the endpoint's TD queue. Moreover, the user is responsible
224 // for setting the TERMINATE bit of next_dtd_pointer if needed.
usb_endpoint_schedule_append(const usb_endpoint_t * const endpoint,usb_transfer_descriptor_t * const tail_td,usb_transfer_descriptor_t * const new_td)225 void usb_endpoint_schedule_append(
226 const usb_endpoint_t* const endpoint,
227 usb_transfer_descriptor_t* const tail_td,
228 usb_transfer_descriptor_t* const new_td
229 ) {
230 bool done;
231
232 tail_td->next_dtd_pointer = new_td;
233
234 if (usb_endpoint_is_priming(endpoint)) {
235 return;
236 }
237
238 do {
239 USB0_USBCMD_D |= USB0_USBCMD_D_ATDTW;
240 done = usb_endpoint_is_ready(endpoint);
241 } while (!(USB0_USBCMD_D & USB0_USBCMD_D_ATDTW));
242
243 USB0_USBCMD_D &= ~USB0_USBCMD_D_ATDTW;
244 if(!done) {
245 usb_endpoint_prime(endpoint, new_td);
246 }
247 }
248
usb_endpoint_flush(const usb_endpoint_t * const endpoint)249 void usb_endpoint_flush(
250 const usb_endpoint_t* const endpoint
251 ) {
252 const uint_fast8_t endpoint_number = usb_endpoint_number(endpoint->address);
253 usb_queue_flush_endpoint(endpoint);
254 if( usb_endpoint_is_in(endpoint->address) ) {
255 usb_flush_primed_endpoints(USB0_ENDPTFLUSH_FETB(1 << endpoint_number));
256 } else {
257 usb_flush_primed_endpoints(USB0_ENDPTFLUSH_FERB(1 << endpoint_number));
258 }
259 }
260 /*
261 static bool usb_endpoint_is_flushing(
262 const usb_endpoint_t* const endpoint
263 ) {
264 const uint_fast8_t endpoint_number = usb_endpoint_number(endpoint->address);
265 if( usb_endpoint_is_in(endpoint->address) ) {
266 return USB0_ENDPTFLUSH & USB0_ENDPTFLUSH_FETB(1 << endpoint_number);
267 } else {
268 return USB0_ENDPTFLUSH & USB0_ENDPTFLUSH_FERB(1 << endpoint_number);
269 }
270 }
271 */
usb_endpoint_is_ready(const usb_endpoint_t * const endpoint)272 bool usb_endpoint_is_ready(
273 const usb_endpoint_t* const endpoint
274 ) {
275 const uint_fast8_t endpoint_number = usb_endpoint_number(endpoint->address);
276 if( usb_endpoint_is_in(endpoint->address) ) {
277 return USB0_ENDPTSTAT & USB0_ENDPTSTAT_ETBR(1 << endpoint_number);
278 } else {
279 return USB0_ENDPTSTAT & USB0_ENDPTSTAT_ERBR(1 << endpoint_number);
280 }
281 }
282
usb_endpoint_is_complete(const usb_endpoint_t * const endpoint)283 bool usb_endpoint_is_complete(
284 const usb_endpoint_t* const endpoint
285 ) {
286 const uint_fast8_t endpoint_number = usb_endpoint_number(endpoint->address);
287 if( usb_endpoint_is_in(endpoint->address) ) {
288 return USB0_ENDPTCOMPLETE & USB0_ENDPTCOMPLETE_ETCE(1 << endpoint_number);
289 } else {
290 return USB0_ENDPTCOMPLETE & USB0_ENDPTCOMPLETE_ERCE(1 << endpoint_number);
291 }
292 }
293
usb_endpoint_stall(const usb_endpoint_t * const endpoint)294 void usb_endpoint_stall(
295 const usb_endpoint_t* const endpoint
296 ) {
297 // Endpoint is to be stalled as a pair -- both OUT and IN.
298 // See UM10503 section 23.10.5.2 "Stalling"
299 const uint_fast8_t endpoint_number = usb_endpoint_number(endpoint->address);
300 USB0_ENDPTCTRL(endpoint_number) |= (USB0_ENDPTCTRL_RXS | USB0_ENDPTCTRL_TXS);
301
302 // TODO: Also need to reset data toggle in both directions?
303 }
304
usb_controller_run()305 static void usb_controller_run() {
306 USB0_USBCMD_D |= USB0_USBCMD_D_RS;
307 }
308
usb_controller_stop()309 static void usb_controller_stop() {
310 USB0_USBCMD_D &= ~USB0_USBCMD_D_RS;
311 }
312
usb_controller_is_resetting()313 static uint_fast8_t usb_controller_is_resetting() {
314 return (USB0_USBCMD_D & USB0_USBCMD_D_RST) != 0;
315 }
316
usb_controller_set_device_mode()317 static void usb_controller_set_device_mode() {
318 // Set USB0 peripheral mode
319 USB0_USBMODE_D = USB0_USBMODE_D_CM1_0(2);
320
321 // Set device-related OTG flags
322 // OTG termination: controls pull-down on USB_DM
323 USB0_OTGSC = USB0_OTGSC_OT;
324 }
325
usb_speed(const usb_device_t * const device)326 usb_speed_t usb_speed(
327 const usb_device_t* const device
328 ) {
329 if( device == usb_device_usb0 ) {
330 switch( USB0_PORTSC1_D & USB0_PORTSC1_D_PSPD_MASK ) {
331 case USB0_PORTSC1_D_PSPD(0):
332 return USB_SPEED_FULL;
333
334 case USB0_PORTSC1_D_PSPD(2):
335 return USB_SPEED_HIGH;
336
337 default:
338 // TODO: What to do/return here? Is this even possible?
339 return USB_SPEED_FULL;
340 }
341 } else {
342 // TODO: This should not be possible with a more class-like
343 // implementation.
344 return USB_SPEED_FULL;
345 }
346 }
347
usb_clear_status(const uint32_t status)348 static void usb_clear_status(const uint32_t status) {
349 USB0_USBSTS_D = status;
350 }
351
usb_get_status()352 static uint32_t usb_get_status() {
353 // Mask status flags with enabled flag interrupts.
354 const uint32_t status = USB0_USBSTS_D & USB0_USBINTR_D;
355
356 // Clear flags that were just read, leaving alone any flags that
357 // were just set (after the read). It's important to read and
358 // reset flags atomically! :-)
359 usb_clear_status(status);
360
361 return status;
362 }
363
usb_clear_endpoint_setup_status(const uint32_t endpoint_setup_status)364 static void usb_clear_endpoint_setup_status(const uint32_t endpoint_setup_status) {
365 USB0_ENDPTSETUPSTAT = endpoint_setup_status;
366 }
367
usb_get_endpoint_setup_status()368 static uint32_t usb_get_endpoint_setup_status() {
369 return USB0_ENDPTSETUPSTAT;
370 }
371
usb_clear_endpoint_complete(const uint32_t endpoint_complete)372 static void usb_clear_endpoint_complete(const uint32_t endpoint_complete) {
373 USB0_ENDPTCOMPLETE = endpoint_complete;
374 }
375
usb_get_endpoint_complete()376 static uint32_t usb_get_endpoint_complete() {
377 return USB0_ENDPTCOMPLETE;
378 }
379
usb_disable_all_endpoints()380 static void usb_disable_all_endpoints() {
381 // Endpoint 0 is always enabled. TODO: So why set ENDPTCTRL0?
382 USB0_ENDPTCTRL0 &= ~(USB0_ENDPTCTRL0_RXE | USB0_ENDPTCTRL0_TXE);
383 USB0_ENDPTCTRL1 &= ~(USB0_ENDPTCTRL1_RXE | USB0_ENDPTCTRL1_TXE);
384 USB0_ENDPTCTRL2 &= ~(USB0_ENDPTCTRL2_RXE | USB0_ENDPTCTRL2_TXE);
385 USB0_ENDPTCTRL3 &= ~(USB0_ENDPTCTRL3_RXE | USB0_ENDPTCTRL3_TXE);
386 USB0_ENDPTCTRL4 &= ~(USB0_ENDPTCTRL4_RXE | USB0_ENDPTCTRL4_TXE);
387 USB0_ENDPTCTRL5 &= ~(USB0_ENDPTCTRL5_RXE | USB0_ENDPTCTRL5_TXE);
388 }
389
usb_set_address_immediate(const usb_device_t * const device,const uint_fast8_t address)390 void usb_set_address_immediate(
391 const usb_device_t* const device,
392 const uint_fast8_t address
393 ) {
394 if( device == usb_device_usb0 ) {
395 USB0_DEVICEADDR = USB0_DEVICEADDR_USBADR(address);
396 }
397 }
398
usb_set_address_deferred(const usb_device_t * const device,const uint_fast8_t address)399 void usb_set_address_deferred(
400 const usb_device_t* const device,
401 const uint_fast8_t address
402 ) {
403 if( device == usb_device_usb0 ) {
404 USB0_DEVICEADDR
405 = USB0_DEVICEADDR_USBADR(address)
406 | USB0_DEVICEADDR_USBADRA
407 ;
408 }
409 }
410
usb_reset_all_endpoints()411 static void usb_reset_all_endpoints() {
412 usb_disable_all_endpoints();
413 usb_clear_all_pending_interrupts();
414 usb_flush_all_primed_endpoints();
415 }
416
usb_controller_reset()417 static void usb_controller_reset() {
418 // TODO: Good to disable some USB interrupts to avoid priming new
419 // new endpoints before the controller is reset?
420 usb_reset_all_endpoints();
421 usb_controller_stop();
422
423 // Reset controller. Resets internal pipelines, timers, counters, state
424 // machines to initial values. Not recommended when device is in attached
425 // state -- effect on attached host is undefined. Detach first by flushing
426 // all primed endpoints and stopping controller.
427 USB0_USBCMD_D = USB0_USBCMD_D_RST;
428
429 while( usb_controller_is_resetting() );
430 }
431
usb_bus_reset(usb_device_t * const device)432 static void usb_bus_reset(usb_device_t* const device) {
433 // According to UM10503 v1.4 section 23.10.3 "Bus reset":
434 usb_reset_all_endpoints();
435 usb_set_address_immediate(device, 0);
436 usb_set_configuration(device, 0);
437
438 // TODO: Enable endpoint 0, which might not actually be necessary,
439 // as the datasheet claims it can't be disabled.
440
441 //wait_ms(3);
442 //
443 //if( USB0_PORTSC1 & USB0_PORTSC1_PR ) {
444 // // Port still is in the reset state.
445 //} else {
446 // usb_hardware_reset();
447 //}
448 }
449
usb_interrupt_enable(usb_device_t * const device)450 static void usb_interrupt_enable(
451 usb_device_t* const device
452 ) {
453 if( device == usb_device_usb0 ) {
454 nvic_enable_irq(NVIC_USB0_IRQ);
455 }
456 }
457
usb_device_init(const uint_fast8_t device_ordinal,usb_device_t * const device)458 void usb_device_init(
459 const uint_fast8_t device_ordinal,
460 usb_device_t* const device
461 ) {
462 if( device_ordinal == 0 ) {
463 usb_device_usb0 = device;
464
465 usb_phy_enable();
466 usb_controller_reset();
467 usb_controller_set_device_mode();
468
469 // Set interrupt threshold interval to 0
470 USB0_USBCMD_D &= ~USB0_USBCMD_D_ITC_MASK;
471
472 // Configure endpoint list address
473 USB0_ENDPOINTLISTADDR = (uint32_t)usb_qh;
474
475 // Enable interrupts
476 USB0_USBINTR_D =
477 USB0_USBINTR_D_UE
478 | USB0_USBINTR_D_UEE
479 | USB0_USBINTR_D_PCE
480 | USB0_USBINTR_D_URE
481 //| USB0_USBINTR_D_SRE
482 | USB0_USBINTR_D_SLE
483 //| USB0_USBINTR_D_NAKE
484 ;
485 }
486 }
487
usb_run(usb_device_t * const device)488 void usb_run(
489 usb_device_t* const device
490 ) {
491 usb_interrupt_enable(device);
492 usb_controller_run(device);
493 }
494
copy_setup(usb_setup_t * const dst,const volatile uint8_t * const src)495 static void copy_setup(usb_setup_t* const dst, const volatile uint8_t* const src) {
496 dst->request_type = src[0];
497 dst->request = src[1];
498 dst->value_l = src[2];
499 dst->value_h = src[3];
500 dst->index_l = src[4];
501 dst->index_h = src[5];
502 dst->length_l = src[6];
503 dst->length_h = src[7];
504 }
505
usb_endpoint_init(const usb_endpoint_t * const endpoint)506 void usb_endpoint_init(
507 const usb_endpoint_t* const endpoint
508 ) {
509 usb_endpoint_flush(endpoint);
510
511 uint_fast16_t max_packet_size = endpoint->device->descriptor[7];
512 usb_transfer_type_t transfer_type = USB_TRANSFER_TYPE_CONTROL;
513 const uint8_t* const endpoint_descriptor = usb_endpoint_descriptor(endpoint);
514 if( endpoint_descriptor ) {
515 max_packet_size = usb_endpoint_descriptor_max_packet_size(endpoint_descriptor);
516 transfer_type = usb_endpoint_descriptor_transfer_type(endpoint_descriptor);
517 }
518
519 // TODO: There are more capabilities to adjust based on the endpoint
520 // descriptor.
521 usb_queue_head_t* const qh = usb_queue_head(endpoint->address);
522 qh->capabilities
523 = USB_QH_CAPABILITIES_MULT(0)
524 | USB_QH_CAPABILITIES_ZLT
525 | USB_QH_CAPABILITIES_MPL(max_packet_size)
526 | ((transfer_type == USB_TRANSFER_TYPE_CONTROL) ? USB_QH_CAPABILITIES_IOS : 0)
527 ;
528 qh->current_dtd_pointer = 0;
529 qh->next_dtd_pointer = USB_TD_NEXT_DTD_POINTER_TERMINATE;
530 qh->total_bytes
531 = USB_TD_DTD_TOKEN_TOTAL_BYTES(0)
532 | USB_TD_DTD_TOKEN_MULTO(0)
533 ;
534 qh->buffer_pointer_page[0] = 0;
535 qh->buffer_pointer_page[1] = 0;
536 qh->buffer_pointer_page[2] = 0;
537 qh->buffer_pointer_page[3] = 0;
538 qh->buffer_pointer_page[4] = 0;
539
540 // This is how we look up an endpoint structure from an endpoint address:
541 qh->_reserved_0 = (uint32_t)endpoint;
542
543 // TODO: Should NAK be enabled? I'm kinda squishy on this...
544 //USB0_ENDPTNAKEN |=
545 // USB0_ENDPTNAKEN_EPRNE(1 << endpoint_out->number);
546
547 usb_endpoint_set_type(endpoint, transfer_type);
548
549 usb_endpoint_enable(endpoint);
550 }
551
usb_check_for_setup_events()552 static void usb_check_for_setup_events() {
553 const uint32_t endptsetupstat = usb_get_endpoint_setup_status();
554 if( endptsetupstat ) {
555 for( uint_fast8_t i=0; i<6; i++ ) {
556 const uint32_t endptsetupstat_bit = USB0_ENDPTSETUPSTAT_ENDPTSETUPSTAT(1 << i);
557 if( endptsetupstat & endptsetupstat_bit ) {
558 usb_endpoint_t* const endpoint =
559 usb_endpoint_from_address(
560 usb_endpoint_address(USB_TRANSFER_DIRECTION_OUT, i)
561 );
562 if( endpoint && endpoint->setup_complete ) {
563 copy_setup(&endpoint->setup, usb_queue_head(endpoint->address)->setup);
564 // TODO: Clean up this duplicated effort by providing
565 // a cleaner way to get the SETUP data.
566 copy_setup(&endpoint->in->setup, usb_queue_head(endpoint->address)->setup);
567 usb_clear_endpoint_setup_status(endptsetupstat_bit);
568 endpoint->setup_complete(endpoint);
569 } else {
570 usb_clear_endpoint_setup_status(endptsetupstat_bit);
571 }
572 }
573 }
574 }
575 }
576
usb_check_for_transfer_events()577 static void usb_check_for_transfer_events() {
578 const uint32_t endptcomplete = usb_get_endpoint_complete();
579 if( endptcomplete ) {
580 for( uint_fast8_t i=0; i<6; i++ ) {
581
582 const uint32_t endptcomplete_out_bit = USB0_ENDPTCOMPLETE_ERCE(1 << i);
583 if( endptcomplete & endptcomplete_out_bit ) {
584 usb_clear_endpoint_complete(endptcomplete_out_bit);
585 usb_endpoint_t* const endpoint =
586 usb_endpoint_from_address(
587 usb_endpoint_address(USB_TRANSFER_DIRECTION_OUT, i)
588 );
589 if( endpoint && endpoint->transfer_complete ) {
590 endpoint->transfer_complete(endpoint);
591 }
592 }
593
594 const uint32_t endptcomplete_in_bit = USB0_ENDPTCOMPLETE_ETCE(1 << i);
595 if( endptcomplete & endptcomplete_in_bit ) {
596 usb_clear_endpoint_complete(endptcomplete_in_bit);
597 usb_endpoint_t* const endpoint =
598 usb_endpoint_from_address(
599 usb_endpoint_address(USB_TRANSFER_DIRECTION_IN, i)
600 );
601 if( endpoint && endpoint->transfer_complete ) {
602 endpoint->transfer_complete(endpoint);
603 }
604 }
605 }
606 }
607 }
608
usb0_isr()609 void usb0_isr() {
610 const uint32_t status = usb_get_status();
611
612 if( status == 0 ) {
613 // Nothing to do.
614 return;
615 }
616
617 if( status & USB0_USBSTS_D_UI ) {
618 // USB:
619 // - Completed transaction transfer descriptor has IOC set.
620 // - Short packet detected.
621 // - SETUP packet received.
622
623 usb_check_for_setup_events();
624 usb_check_for_transfer_events();
625
626 // TODO: Reset ignored ENDPTSETUPSTAT and ENDPTCOMPLETE flags?
627 }
628
629 if( status & USB0_USBSTS_D_SRI ) {
630 // Start Of Frame received.
631 }
632
633 if( status & USB0_USBSTS_D_PCI ) {
634 // Port change detect:
635 // Port controller entered full- or high-speed operational state.
636 }
637
638 if( status & USB0_USBSTS_D_SLI ) {
639 // Device controller suspend.
640 }
641
642 if( status & USB0_USBSTS_D_URI ) {
643 // USB reset received.
644 usb_bus_reset(usb_device_usb0);
645 }
646
647 if( status & USB0_USBSTS_D_UEI ) {
648 // USB error:
649 // Completion of a USB transaction resulted in an error condition.
650 // Set along with USBINT if the TD on which the error interrupt
651 // occurred also had its interrupt on complete (IOC) bit set.
652 // The device controller detects resume signalling only.
653 }
654
655 if( status & USB0_USBSTS_D_NAKI ) {
656 // Both the TX/RX endpoint NAK bit and corresponding TX/RX endpoint
657 // NAK enable bit are set.
658 }
659 }
660