Brian Silverman | 4aa8304 | 2018-01-05 12:47:31 -0800 | [diff] [blame] | 1 | #include "motors/usb/interrupt_out.h" |
| 2 | |
Stephan Pleines | f63bde8 | 2024-01-13 15:59:33 -0800 | [diff] [blame] | 3 | namespace frc971::teensy { |
Brian Silverman | 4aa8304 | 2018-01-05 12:47:31 -0800 | [diff] [blame] | 4 | |
| 5 | void InterruptOut::Initialize() { |
| 6 | interface_ = AddInterface(); |
| 7 | endpoint_ = AddEndpoint(); |
| 8 | |
| 9 | SetMicrosoftDeviceInterfaceGuids("{D4FA286B-C60D-4B99-B49B-9656139F5771}"); |
| 10 | |
| 11 | CreateIadDescriptor( |
| 12 | /*first_interface=*/interface_, |
| 13 | /*interface_count=*/1, |
| 14 | /*function_class=*/vendor_specific_class(), |
| 15 | /*function_subclass=*/0, |
| 16 | /*function_protocol=*/0, name_); |
| 17 | |
| 18 | { |
| 19 | const auto interface_descriptor = CreateDescriptor( |
| 20 | interface_descriptor_length(), UsbDescriptorType::kInterface); |
| 21 | interface_descriptor->AddByte(interface_); // bInterfaceNumber |
| 22 | interface_descriptor->AddByte(0); // bAlternateSetting |
| 23 | interface_descriptor->AddByte(1); // bNumEndpoints |
| 24 | interface_descriptor->AddByte(vendor_specific_class()); // bInterfaceClass |
| 25 | interface_descriptor->AddByte(0x97); // bInterfaceSubClass |
| 26 | interface_descriptor->AddByte(0x97); // bInterfaceProtocol |
| 27 | interface_descriptor->AddByte(device()->AddString(name_)); // iInterface |
| 28 | } |
| 29 | |
| 30 | { |
| 31 | const auto endpoint_descriptor = CreateDescriptor( |
| 32 | endpoint_descriptor_length(), UsbDescriptorType::kEndpoint); |
| 33 | endpoint_descriptor->AddByte(endpoint_); // bEndpointAddress |
| 34 | endpoint_descriptor->AddByte( |
| 35 | m_endpoint_attributes_interrupt()); // bmAttributes |
| 36 | endpoint_descriptor->AddUint16(kSize); // wMaxPacketSize |
Philipp Schrader | 790cb54 | 2023-07-05 21:06:52 -0700 | [diff] [blame] | 37 | endpoint_descriptor->AddByte(1); // bInterval |
Brian Silverman | 4aa8304 | 2018-01-05 12:47:31 -0800 | [diff] [blame] | 38 | } |
| 39 | } |
| 40 | |
| 41 | void InterruptOut::HandleOutFinished(int endpoint, BdtEntry *bdt_entry) { |
| 42 | if (endpoint == endpoint_) { |
Brian Silverman | 4aa8304 | 2018-01-05 12:47:31 -0800 | [diff] [blame] | 43 | DisableInterrupts disable_interrupts; |
| 44 | if (first_rx_held_ == nullptr) { |
| 45 | first_rx_held_ = bdt_entry; |
| 46 | } else { |
| 47 | second_rx_held_ = bdt_entry; |
| 48 | } |
| 49 | } |
| 50 | } |
| 51 | |
| 52 | int InterruptOut::ReceiveData(char *buffer) { |
| 53 | DisableInterrupts disable_interrupts; |
| 54 | if (first_rx_held_ == nullptr) { |
| 55 | return -1; |
| 56 | } |
| 57 | |
| 58 | BdtEntry *const bdt_entry = first_rx_held_; |
| 59 | const size_t data_size = G_USB_BD_BC(bdt_entry->buffer_descriptor); |
| 60 | memcpy(buffer, bdt_entry->address, kSize); |
| 61 | dma_memory_barrier(); |
| 62 | |
| 63 | first_rx_held_->buffer_descriptor = M_USB_BD_OWN | M_USB_BD_DTS | |
| 64 | V_USB_BD_BC(kSize) | |
| 65 | static_cast<uint32_t>(next_rx_toggle_); |
| 66 | next_rx_toggle_ = Data01Inverse(next_rx_toggle_); |
| 67 | |
| 68 | first_rx_held_ = second_rx_held_; |
| 69 | second_rx_held_ = nullptr; |
| 70 | return data_size; |
| 71 | } |
| 72 | |
| 73 | void InterruptOut::HandleConfigured(int endpoint) { |
| 74 | if (endpoint == endpoint_) { |
| 75 | device()->ConfigureEndpointFor(endpoint_, true, false, true); |
| 76 | next_rx_toggle_ = Data01::kData0; |
| 77 | device()->SetBdtEntry( |
| 78 | endpoint_, Direction::kRx, EvenOdd::kEven, |
| 79 | {M_USB_BD_OWN | M_USB_BD_DTS | V_USB_BD_BC(buffers_[0].size()), |
| 80 | buffers_[0].data()}); |
| 81 | device()->SetBdtEntry(endpoint_, Direction::kRx, EvenOdd::kOdd, |
| 82 | {M_USB_BD_OWN | M_USB_BD_DTS | |
| 83 | V_USB_BD_BC(buffers_[1].size()) | M_USB_BD_DATA1, |
| 84 | buffers_[1].data()}); |
| 85 | } |
| 86 | } |
| 87 | |
Stephan Pleines | f63bde8 | 2024-01-13 15:59:33 -0800 | [diff] [blame] | 88 | } // namespace frc971::teensy |