teensycore/phys/
usb.rs

1#![allow(dead_code)]
2
3pub mod descriptors;
4pub mod models;
5pub mod registers;
6
7use descriptors::*;
8use models::*;
9use registers::*;
10
11use crate::mem::zero;
12use crate::phys::addrs::*;
13use crate::phys::irq::*;
14use crate::phys::read_word;
15use crate::system::vector::*;
16use crate::*;
17use crate::{assembly, phys::*};
18
19type IrqFn = fn(status: u32);
20
21const BLANK_QUEUE_HEAD: UsbEndpointQueueHead = UsbEndpointQueueHead {
22    config: 0,
23    current: 0,
24    next: 0,
25    status: 0,
26    pointer0: 0,
27    pointer1: 0,
28    pointer2: 0,
29    pointer3: 0,
30    pointer4: 0,
31    reserved: 0,
32    setup0: 0,
33    setup1: 0,
34    callback: noop,
35    first_transfer: 0,
36    last_transfer: 0,
37};
38
39const MAX_ENDPOINTS: usize = 8;
40
41#[no_mangle]
42#[link_section = ".endpoint_queue"]
43static mut ENDPOINT_HEADERS: [UsbEndpointQueueHead; MAX_ENDPOINTS * 2] =
44    [BLANK_QUEUE_HEAD; MAX_ENDPOINTS * 2];
45
46#[link_section = ".dmabuffers"]
47static mut USB_DESCRIPTOR_BUFFER: BufferPage = BufferPage::new();
48
49#[no_mangle]
50#[link_section = ".dmabuffers"]
51static mut ENDPOINT0_BUFFER: BufferPage = BufferPage::new();
52
53#[no_mangle]
54static mut ENDPOINT0_TRANSFER_DATA: UsbEndpointTransferDescriptor =
55    UsbEndpointTransferDescriptor::new();
56
57#[no_mangle]
58static mut ENDPOINT0_TRANSFER_ACK: UsbEndpointTransferDescriptor =
59    UsbEndpointTransferDescriptor::new();
60
61static mut ENDPOINT0_NOTIFY_MASK: u32 = 0;
62static mut IRQ_CALLBACKS: Vector<IrqFn> = Vector::new();
63static mut CONFIGURATION_CALLBACKS: Vector<ConfigFn> = Vector::new();
64static mut CONFIGURATION: u16 = 0;
65static mut HIGHSPEED: bool = false;
66
67/// Attach a callback to be invoked when a setup packet
68/// is received. See usb_serial.rs for examples.
69pub fn usb_attach_setup_callback(callback: ConfigFn) {
70    unsafe {
71        CONFIGURATION_CALLBACKS.push(callback);
72    }
73}
74
75/// Attach a callback to be invoked every time an
76/// interrupt is handled.
77pub fn usb_attach_irq_handler(callback: IrqFn) {
78    unsafe {
79        IRQ_CALLBACKS.push(callback);
80    }
81}
82
83/// Configure the VendorID and ProductID
84/// of the peripheral.
85pub fn usb_configure_codes(vid: u16, pid: u16) {
86    let descriptors = usb_get_descriptors();
87    descriptors.set_codes(vid, pid);
88}
89
90/// Retrieve the specific queue head based on endpoint
91/// and direction.
92///
93/// Returns a mutable UsbEndpointQueueHead.
94pub fn usb_get_queuehead(endpoint: usize, tx: bool) -> &'static mut UsbEndpointQueueHead {
95    unsafe {
96        let index = match tx {
97            true => endpoint * 2 + 1,
98            false => endpoint * 2,
99        };
100
101        return &mut ENDPOINT_HEADERS[index];
102    }
103}
104
105/// Boot up the usb clocks. This method
106/// takes many milliseconds to run.
107pub fn usb_start_clock() {
108    loop {
109        let pll_usb1_status = read_word(PLL1_USB1_ADDR);
110        if (pll_usb1_status & (0x1 << 13)) == 0 {
111            // ENABLE
112            assign(PLL1_USB1_ADDR_SET, 0x1 << 13); // SET
113            continue;
114        }
115
116        if (pll_usb1_status & (0x1 << 12)) == 0 {
117            // POWER
118            assign(PLL1_USB1_ADDR_SET, 0x1 << 12); // SET
119            continue;
120        }
121
122        if (pll_usb1_status & (0x1 << 16)) > 0 {
123            // LOCK
124            continue;
125        }
126
127        if (pll_usb1_status & (0x1 << 31)) == 0 {
128            // BYPASS
129            assign(PLL1_USB1_ADDR_CLR, 0x1 << 31); // CLEAR
130            continue;
131        }
132
133        if (pll_usb1_status & (0x1 << 6)) == 0 {
134            // CLEAR CLOCKGTE
135            assign(0x400D_9038, 0x1 << 30);
136            // USB_EN_CLK
137            assign(PLL1_USB1_ADDR_SET, 0x1 << 6); // SET
138            continue;
139        }
140
141        break;
142    }
143
144    assign(0x400D_8000 + 0x120, 0xF << 8 | 6 << 4 | 1);
145    // Ungate the USB clock
146    assign(0x400F_C000 + 0x80, read_word(0x400F_C000 + 0x80) | 0x1);
147    // Set usb burstsize
148    assign(USB + 0x160, 0x0404);
149}
150
151/// This method will initialize the usb subsystem by priming
152/// the endpoint queues, starting irq, and enabling the
153/// run/stop bit of the USB OTG1 Core.
154pub fn usb_initialize() {
155    // Configure the descriptors
156    usb_initialize_descriptors();
157
158    // Reset
159    // *********************************
160    assign(USBPHY1_CTRL_SET, 1 << 31);
161    usb_cmd(read_word(USBCMD) | 2);
162    while (read_word(USBCMD) & 0x2) > 0 {
163        assembly!("nop");
164    }
165
166    irq_clear_pending();
167
168    assign(USBPHY1_CTRL_CLR, 1 << 31);
169    wait_exact_ns(MS_TO_NANO * 25);
170    assign(USBPHY1_CTRL_CLR, 1 << 30);
171    assign(USBPHY1_PWD, 0);
172
173    // *********************************
174
175    usb_set_mode(UsbMode::DEVICE);
176    endpoint0_initialize();
177
178    assign(USBINTR, 0x143);
179
180    irq_attach(Irq::Usb1, handle_usb_irq);
181    irq_priority(Irq::Usb1, 32);
182    irq_enable(Irq::Usb1);
183
184    usb_cmd(1); // Run/Stop bit
185}
186
187/// Set the mode of the USB device.
188pub fn usb_set_mode(mode: UsbMode) {
189    match mode {
190        UsbMode::DEVICE => {
191            // Enter device mode and set the SLOM bit
192            assign(USBMODE, 0x2 | (0x1 << 3));
193        }
194    }
195}
196
197/// Wait for a register to read all 0's across the borad
198fn waitfor(addr: u32) {
199    while read_word(addr) > 0 {
200        assembly!("nop");
201    }
202}
203
204/// Clear specific interrupts from the status field.
205pub fn usb_irq_clear(value: u32) {
206    assign(USBSTS, value);
207}
208
209/// Internal method to initialize the control endpoints
210fn endpoint0_initialize() {
211    unsafe {
212        let epaddr = &ENDPOINT_HEADERS[0] as *const UsbEndpointQueueHead as u32;
213
214        // 4096 bytes per the linker file
215        zero(epaddr, 4096);
216
217        // Priming the headers
218        // First, set max_packet_size
219        ENDPOINT_HEADERS[0].config |= (64 << 16) | (1 << 15); // RX
220        ENDPOINT_HEADERS[1].config |= 64 << 16; // TX
221
222        assign(ENDPTLISTADDR, epaddr);
223    }
224}
225
226/// Assign a value to the command register.
227pub fn usb_cmd(val: u32) {
228    assign(USBCMD, val);
229}
230
231/// Return true if we are in highspeed mode.
232pub fn usb_is_highspeed() -> bool {
233    return unsafe { HIGHSPEED };
234}
235
236/// Helper method to configure an endpoint queuehead.
237fn configure_ep(qh: &mut UsbEndpointQueueHead, config: u32, cb: Option<TransferCallbackFn>) {
238    qh.config = config;
239    qh.next = 1;
240
241    if cb.is_some() {
242        qh.callback = cb.unwrap();
243    } else {
244        qh.callback = noop;
245    }
246}
247
248fn run_callbacks(qh: &mut UsbEndpointQueueHead) {
249    let mut transfer_addr = qh.first_transfer;
250    while transfer_addr > 1 {
251        // Get the transfer
252        let transfer = unsafe {
253            (transfer_addr as *const UsbEndpointTransferDescriptor)
254                .as_ref()
255                .unwrap()
256        };
257
258        // Still active
259        if (transfer.status & 0x80) > 0 {
260            qh.first_transfer = transfer_addr;
261            break;
262        }
263
264        // Check for the end of queue.
265        if transfer.next == 1 {
266            // Reset queueheads
267            qh.first_transfer = 0;
268            qh.last_transfer = 0;
269        } else {
270            transfer_addr = transfer.next;
271        }
272
273        // Invoke the callback
274        qh.callback.call((transfer,));
275
276        // If we did reach the end of the queue, stop processing.
277        if transfer.next == 1 {
278            break;
279        }
280    }
281}
282
283/// Use this method to fully configure an endpoint
284pub fn usb_setup_endpoint(
285    index: usize,
286    tx_config: Option<EndpointConfig>,
287    rx_config: Option<EndpointConfig>,
288) {
289    let tx_qh = usb_get_queuehead(index, true);
290    let rx_qh = usb_get_queuehead(index, false);
291    let ep_control_addr = USB + 0x1C0 + (index as u32) * 4;
292
293    let isochornous = 1;
294    let bulk = 2;
295    let interrupt = 3;
296    let tx_enable_bit = 1 << 23;
297    let rx_enable_bit = 1 << 7;
298
299    if tx_config.is_some() {
300        let config = tx_config.unwrap();
301
302        let mut config_bits = (config.size as u32) << 16;
303        if config.zlt {
304            config_bits |= 1 << 29;
305        }
306
307        configure_ep(tx_qh, config_bits, config.callback);
308        match config.endpoint_type {
309            EndpointType::ISOCHRONOUS => {
310                assign(
311                    ep_control_addr,
312                    read_word(ep_control_addr) | (isochornous << 18) | tx_enable_bit,
313                );
314            }
315            EndpointType::BULK => {
316                assign(
317                    ep_control_addr,
318                    read_word(ep_control_addr) | (bulk << 18) | tx_enable_bit,
319                );
320            }
321            EndpointType::INTERRUPT => {
322                assign(
323                    ep_control_addr,
324                    read_word(ep_control_addr) | (interrupt << 18) | tx_enable_bit,
325                );
326            }
327        }
328    } else {
329        // Unusued endpoints cannot remain CONTROL type
330        assign(ep_control_addr, read_word(ep_control_addr) | (bulk << 18));
331    }
332
333    if rx_config.is_some() {
334        let config = rx_config.unwrap();
335
336        let mut config_bits = (config.size as u32) << 16;
337        if config.zlt {
338            config_bits |= 1 << 29;
339        }
340
341        configure_ep(rx_qh, config_bits, config.callback);
342        match config.endpoint_type {
343            EndpointType::ISOCHRONOUS => {
344                assign(
345                    ep_control_addr,
346                    read_word(ep_control_addr) | (isochornous << 2) | rx_enable_bit,
347                );
348            }
349            EndpointType::BULK => {
350                assign(
351                    ep_control_addr,
352                    read_word(ep_control_addr) | (bulk << 2) | rx_enable_bit,
353                );
354            }
355            EndpointType::INTERRUPT => {
356                assign(
357                    ep_control_addr,
358                    read_word(ep_control_addr) | (interrupt << 2) | rx_enable_bit,
359                );
360            }
361        }
362    } else {
363        // Unusued endpoints cannot remain CONTROL type
364        assign(ep_control_addr, read_word(ep_control_addr) | (bulk << 2));
365    }
366}
367
368/// This method will configure a UsbEndpointTransferDescriptor
369/// based on various flags. However, DTD structures can
370/// only be modified while they are not in an active state.
371///
372/// This method returns true if it succeeded in modifying the dtd
373/// or false if something went wrong.
374pub fn usb_prepare_transfer(
375    transfer_queue: &mut UsbEndpointTransferDescriptor,
376    addr: u32,
377    len: u32,
378    notify: bool,
379) -> bool {
380    if (transfer_queue.status & 0x80) == 0 {
381        transfer_queue.next = 1;
382        transfer_queue.status = (len << 16) | (1 << 7);
383        transfer_queue.pointer0 = addr;
384        transfer_queue.pointer1 = addr + 4096;
385        transfer_queue.pointer2 = addr + 8192;
386        transfer_queue.pointer3 = addr + 12288;
387        transfer_queue.pointer4 = addr + 16384;
388
389        if notify {
390            transfer_queue.status |= 1 << 15;
391        }
392
393        return true;
394    }
395
396    // Something went wrong.
397    return false;
398}
399
400/// This method will enqueue the transfer descriptor into the endpoint
401/// and prime it for receiving new data.
402pub fn usb_receive(endpoint: usize, transfer: &mut UsbEndpointTransferDescriptor) {
403    schedule_transfer(endpoint as u32, false, transfer);
404}
405
406/// This method will enqueue the transfer descriptor into the endpoint
407/// and prime it for transmitting new data.
408pub fn usb_transmit(endpoint: usize, transfer: &mut UsbEndpointTransferDescriptor) {
409    schedule_transfer(endpoint as u32, true, transfer);
410}
411
412fn schedule_transfer(ep: u32, tx: bool, transfer: &mut UsbEndpointTransferDescriptor) {
413    let qh = usb_get_queuehead(ep as usize, tx);
414    let mask = match tx {
415        true => 1 << (ep + 16),
416        false => 1 << ep,
417    };
418
419    loop {
420        // Case 2. The queue is not empty.
421        if qh.last_transfer > 1 {
422            let last = qh.get_last_transfer();
423
424            // Add the new dtd to the end of the queue
425            last.next = (transfer as *const UsbEndpointTransferDescriptor) as u32;
426
427            // If the thing is still primed, hooray we're done.
428            if (read_word(ENDPTPRIME) & mask) > 0 {
429                break;
430            }
431
432            let mut status;
433            loop {
434                // Set ATDTW bit to USBCMD
435                assign(USBCMD, read_word(USBCMD) | (1 << 14));
436                // Read status for current queue
437                status = read_word(ENDPTSTAT) & mask;
438                // Read atdtw bit
439                let atdtw = read_word(USBCMD) & (1 << 14);
440                // If it's zero, restart this process.
441                // If it's one, we can continue.
442                if atdtw > 0 {
443                    break;
444                } else {
445                    assembly!("nop");
446                }
447            }
448
449            // Write atdtw as zero
450            assign(USBCMD, read_word(USBCMD) & !(1 << 14));
451
452            // If status bit is set, we're done. Otherwise, fall into Case 1.
453            if status > 0 {
454                break;
455            }
456        }
457
458        // Case 1. The queue is empty
459        qh.next = (transfer as *const UsbEndpointTransferDescriptor) as u32;
460        qh.status = 0;
461
462        usb_prime_endpoint(ep, tx);
463        qh.set_first_transfer(transfer);
464        break;
465    }
466
467    qh.set_last_transfer(transfer);
468}
469
470fn usb_prime_endpoint(index: u32, tx: bool) {
471    let mask = match tx {
472        true => 1 << (16 + index),
473        false => 1 << index,
474    };
475
476    assign(ENDPTPRIME, mask);
477
478    loop {
479        let prime = read_word(ENDPTPRIME) & mask;
480        let stat = read_word(ENDPTSTAT) & mask;
481
482        if prime == 0 && stat != 0 {
483            // Success
484            return;
485        } else if prime == 0 && stat == 0 {
486            // Failure
487            return;
488        } else {
489            assembly!("nop");
490        }
491    }
492}
493
494fn endpoint0_setup(packet: SetupPacket) {
495    for callback in unsafe { CONFIGURATION_CALLBACKS.into_iter() } {
496        callback(packet);
497    }
498
499    match packet.bm_request_and_type {
500        0x681 | 0x680 => {
501            // GET_DESCRIPTOR
502            let descriptors = usb_get_descriptors();
503            match descriptors.get_bytes(packet.w_value, packet.w_index) {
504                Some(bytes) => {
505                    let mut byte_length = bytes.size();
506                    if byte_length > packet.w_length as usize {
507                        byte_length = packet.w_length as usize;
508                    }
509
510                    endpoint0_transmit(bytes, byte_length, false);
511                    return;
512                }
513                None => {}
514            }
515        }
516        0x500 => {
517            // Set Address
518            endpoint0_receive(0, 0, false);
519            assign(DEVICEADDR, ((packet.w_value as u32) << 25) | (1 << 24));
520            return;
521        }
522        0x900 => {
523            // Set configuration
524            unsafe {
525                CONFIGURATION = packet.w_value;
526            }
527
528            endpoint0_receive(0, 0, false);
529            return;
530        }
531        0x880 => {
532            // Get configuration
533        }
534        0x80 => {
535            // Get status (device)
536        }
537        0x82 => {
538            // Get status (endpoint)
539        }
540        0x302 => {
541            // Set feature
542        }
543        0x102 => {
544            // Clear feature
545        }
546        0x2021 => {
547            // Set Line Coding
548            if packet.w_length != 7 {
549                // Stall
550                assign(ENDPTCTRL0, (1 << 16) | 1); // Stall
551                return;
552            }
553
554            endpoint0_receive(unsafe { ENDPOINT0_BUFFER.as_ptr() } as u32, 7, true);
555            return;
556        }
557        0x2221 => {
558            //Set control line state
559            endpoint0_receive(0, 0, false);
560            return;
561        }
562        0x2321 => {
563            //Send Break
564            endpoint0_receive(0, 0, false);
565            return;
566        }
567        _ => {}
568    }
569
570    assign(ENDPTCTRL0, (1 << 16) | 1); // Stall
571}
572
573fn endpoint0_transmit(vec: Vector<u8>, byte_length: usize, notify: bool) {
574    // Do the transmit
575    let len = byte_length as u32;
576    let usb_descriptor_buffer_addr = unsafe { USB_DESCRIPTOR_BUFFER.as_ptr() } as u32;
577    arm_dcache_delete(usb_descriptor_buffer_addr, len);
578    let mut i = 0;
579    for byte in vec.into_iter() {
580        unsafe {
581            USB_DESCRIPTOR_BUFFER.bytes[i] = byte;
582        }
583
584        i += 1;
585    }
586
587    if len > 0 {
588        unsafe {
589            ENDPOINT0_TRANSFER_DATA.next = 1;
590            ENDPOINT0_TRANSFER_DATA.status = (len << 16) | (1 << 7);
591
592            let addr = USB_DESCRIPTOR_BUFFER.as_ptr() as u32;
593            let endpoint0_transfer_data_addr =
594                &ENDPOINT0_TRANSFER_DATA as *const UsbEndpointTransferDescriptor as u32;
595
596            ENDPOINT0_TRANSFER_DATA.pointer0 = addr;
597            ENDPOINT0_TRANSFER_DATA.pointer1 = addr + 4096;
598            ENDPOINT0_TRANSFER_DATA.pointer2 = addr + 8192;
599            ENDPOINT0_TRANSFER_DATA.pointer3 = addr + 12288;
600            ENDPOINT0_TRANSFER_DATA.pointer4 = addr + 16384;
601
602            ENDPOINT_HEADERS[1].next = endpoint0_transfer_data_addr;
603            ENDPOINT_HEADERS[1].status = 0;
604        }
605
606        usb_prime_endpoint(0, true);
607    }
608
609    unsafe {
610        ENDPOINT0_TRANSFER_ACK.next = 1;
611        match notify {
612            true => {
613                ENDPOINT0_TRANSFER_ACK.status = (1 << 7) | (1 << 15);
614            }
615            false => {
616                ENDPOINT0_TRANSFER_ACK.status = 1 << 7;
617            }
618        }
619        ENDPOINT0_TRANSFER_ACK.pointer0 = 0;
620        ENDPOINT_HEADERS[0].next =
621            (&ENDPOINT0_TRANSFER_ACK as *const UsbEndpointTransferDescriptor) as u32;
622        ENDPOINT_HEADERS[0].status = 0;
623    }
624
625    usb_prime_endpoint(0, false);
626}
627
628fn endpoint0_receive(addr: u32, len: u32, notify: bool) {
629    if len > 0 {
630        unsafe {
631            ENDPOINT0_TRANSFER_DATA.next = 1;
632            ENDPOINT0_TRANSFER_DATA.status = (len << 16) | (1 << 7);
633            ENDPOINT0_TRANSFER_DATA.pointer0 = addr;
634            ENDPOINT0_TRANSFER_DATA.pointer1 = addr + 4096;
635            ENDPOINT0_TRANSFER_DATA.pointer2 = addr + 8192;
636            ENDPOINT0_TRANSFER_DATA.pointer3 = addr + 12288;
637            ENDPOINT0_TRANSFER_DATA.pointer4 = addr + 16384;
638            let endpoint0_transfer_data_addr =
639                (&ENDPOINT0_TRANSFER_DATA as *const UsbEndpointTransferDescriptor) as u32;
640
641            ENDPOINT_HEADERS[0].next = endpoint0_transfer_data_addr;
642            ENDPOINT_HEADERS[0].status = 0;
643        }
644
645        usb_prime_endpoint(0, false);
646    }
647
648    unsafe {
649        ENDPOINT0_TRANSFER_ACK.next = 1;
650        match notify {
651            true => {
652                ENDPOINT0_TRANSFER_ACK.status = (1 << 7) | (1 << 15);
653            }
654            false => {
655                ENDPOINT0_TRANSFER_ACK.status = 1 << 7;
656            }
657        }
658        ENDPOINT0_TRANSFER_ACK.pointer0 = 0;
659        ENDPOINT_HEADERS[1].next =
660            (&ENDPOINT0_TRANSFER_ACK as *const UsbEndpointTransferDescriptor) as u32;
661        ENDPOINT_HEADERS[1].status = 0;
662    }
663
664    if notify {
665        unsafe {
666            ENDPOINT0_NOTIFY_MASK = 1 << 16;
667        }
668    }
669
670    assign(ENDPTCOMPLETE, 1 | (1 << 16));
671    usb_prime_endpoint(0, true);
672}
673
674fn handle_usb_irq() {
675    irq_disable(Irq::Usb1);
676
677    let irq_status = read_word(USBSTS);
678    assembly!("nop"); // Need this. no idea why.
679    usb_irq_clear(irq_status);
680
681    if (irq_status & HCH) > 0 {}
682
683    if (irq_status & PCI) > 0 {
684        // Check which mode we are in
685        let port_status = read_word(PORTSC1);
686        if port_status & (0x1 << 9) > 0 {
687            unsafe {
688                HIGHSPEED = true;
689            }
690        } else {
691            unsafe {
692                HIGHSPEED = false;
693            }
694        }
695
696        if (port_status & 1) > 0 {
697            // Attached
698        }
699    }
700
701    if (irq_status & SEI) > 0 {
702        // System error flag
703    }
704
705    if (irq_status & USBERRINT) > 0 {
706        // Interrupt error flag
707    }
708
709    if (irq_status & SLI) > 0 {
710        // Enter suspend mode
711    }
712
713    if (irq_status & URI) > 0 {
714        // Reset device
715        assign(ENDPTSTAT, read_word(ENDPTSTAT));
716        assign(ENDPTCOMPLETE, read_word(ENDPTCOMPLETE));
717
718        // Wait for endpoint priming to finish
719        waitfor(ENDPTPRIME);
720
721        // Flush all endpoints
722        assign(ENDPTFLUSH, 0xFFFF_FFFF);
723
724        // Read the reset bit and make sure it is still active
725        let port_status = read_word(PORTSC1);
726        if (port_status & (1 << 8)) == 0 {
727            // ERROR PORT STATUS
728        } else {
729            // Still active
730        }
731    }
732
733    if (irq_status & USBINT) > 0 {
734        let mut setup_status = read_word(ENDPTSETUPSTAT);
735        while setup_status > 0 {
736            // Clear the setup status
737            assign(ENDPTSETUPSTAT, setup_status);
738
739            // Duplicate setup buffer into local byte array
740            let mut setup_packet;
741
742            loop {
743                // Set tripwire
744                assign(USBCMD, read_word(USBCMD) | (1 << 13));
745
746                // Copy the setup queue
747                unsafe {
748                    setup_packet = SetupPacket::from_dwords(
749                        ENDPOINT_HEADERS[0].setup0,
750                        ENDPOINT_HEADERS[0].setup1,
751                    );
752                }
753
754                // Check for finish condition
755                if (read_word(USBCMD) & (1 << 13)) > 0 {
756                    break;
757                }
758            }
759
760            // Write 0 to clear the tripwire
761            assign(USBCMD, read_word(USBCMD) & !(1 << 13));
762
763            // Flush endpoint
764            assign(ENDPTFLUSH, (1 << 16) | 1);
765
766            // Wait for the flush to finish
767            waitfor(ENDPTFLUSH);
768
769            if (read_word(ENDPTSTAT) & ((1 << 16) | 1)) > 0 {
770                // FLUSH FAILED
771                // TODO: Something
772            }
773
774            // Setup
775            endpoint0_setup(setup_packet);
776
777            // Check for another packet
778            setup_status = read_word(ENDPTSETUPSTAT);
779        }
780
781        let complete_status = read_word(ENDPTCOMPLETE);
782
783        unsafe {
784            if (complete_status & ENDPOINT0_NOTIFY_MASK) > 0 {
785                ENDPOINT0_NOTIFY_MASK = 0;
786                endpoint0_complete();
787            }
788        }
789
790        if complete_status > 0 {
791            assign(ENDPTCOMPLETE, complete_status);
792
793            // Run the transmit callbacks
794            for idx in 1..MAX_ENDPOINTS {
795                let mask = 1 << (16 + idx);
796                if (complete_status & mask) > 0 {
797                    run_callbacks(usb_get_queuehead(idx, true));
798                }
799            }
800
801            // Run the receive callbacks
802            for idx in 1..MAX_ENDPOINTS {
803                let mask = 1 << idx;
804                if (complete_status & mask) > 0 {
805                    run_callbacks(usb_get_queuehead(idx, false));
806                }
807            }
808        }
809    }
810
811    unsafe {
812        for other_irq_handler in IRQ_CALLBACKS.into_iter() {
813            other_irq_handler(irq_status);
814        }
815    }
816
817    irq_enable(Irq::Usb1);
818}
819
820fn endpoint0_complete() {
821    // TODO: This is not always what endpoint0_complete means
822    // choose correct action based on request.
823
824    // Read the buffer
825    let buffer = unsafe { ENDPOINT0_BUFFER.bytes };
826    let mut _bitrate = 0;
827
828    for i in 0..4 {
829        _bitrate |= (buffer[i] as u64) << (i * 8);
830    }
831}
832
833fn noop(_packet: &UsbEndpointTransferDescriptor) {}