blob: 30f024e16614f32af2e040259a4009a1eb202f89 [file] [log] [blame]
#include "motors/usb/interrupt_out.h"
namespace frc971::teensy {
void InterruptOut::Initialize() {
interface_ = AddInterface();
endpoint_ = AddEndpoint();
SetMicrosoftDeviceInterfaceGuids("{D4FA286B-C60D-4B99-B49B-9656139F5771}");
CreateIadDescriptor(
/*first_interface=*/interface_,
/*interface_count=*/1,
/*function_class=*/vendor_specific_class(),
/*function_subclass=*/0,
/*function_protocol=*/0, name_);
{
const auto interface_descriptor = CreateDescriptor(
interface_descriptor_length(), UsbDescriptorType::kInterface);
interface_descriptor->AddByte(interface_); // bInterfaceNumber
interface_descriptor->AddByte(0); // bAlternateSetting
interface_descriptor->AddByte(1); // bNumEndpoints
interface_descriptor->AddByte(vendor_specific_class()); // bInterfaceClass
interface_descriptor->AddByte(0x97); // bInterfaceSubClass
interface_descriptor->AddByte(0x97); // bInterfaceProtocol
interface_descriptor->AddByte(device()->AddString(name_)); // iInterface
}
{
const auto endpoint_descriptor = CreateDescriptor(
endpoint_descriptor_length(), UsbDescriptorType::kEndpoint);
endpoint_descriptor->AddByte(endpoint_); // bEndpointAddress
endpoint_descriptor->AddByte(
m_endpoint_attributes_interrupt()); // bmAttributes
endpoint_descriptor->AddUint16(kSize); // wMaxPacketSize
endpoint_descriptor->AddByte(1); // bInterval
}
}
void InterruptOut::HandleOutFinished(int endpoint, BdtEntry *bdt_entry) {
if (endpoint == endpoint_) {
DisableInterrupts disable_interrupts;
if (first_rx_held_ == nullptr) {
first_rx_held_ = bdt_entry;
} else {
second_rx_held_ = bdt_entry;
}
}
}
int InterruptOut::ReceiveData(char *buffer) {
DisableInterrupts disable_interrupts;
if (first_rx_held_ == nullptr) {
return -1;
}
BdtEntry *const bdt_entry = first_rx_held_;
const size_t data_size = G_USB_BD_BC(bdt_entry->buffer_descriptor);
memcpy(buffer, bdt_entry->address, kSize);
dma_memory_barrier();
first_rx_held_->buffer_descriptor = M_USB_BD_OWN | M_USB_BD_DTS |
V_USB_BD_BC(kSize) |
static_cast<uint32_t>(next_rx_toggle_);
next_rx_toggle_ = Data01Inverse(next_rx_toggle_);
first_rx_held_ = second_rx_held_;
second_rx_held_ = nullptr;
return data_size;
}
void InterruptOut::HandleConfigured(int endpoint) {
if (endpoint == endpoint_) {
device()->ConfigureEndpointFor(endpoint_, true, false, true);
next_rx_toggle_ = Data01::kData0;
device()->SetBdtEntry(
endpoint_, Direction::kRx, EvenOdd::kEven,
{M_USB_BD_OWN | M_USB_BD_DTS | V_USB_BD_BC(buffers_[0].size()),
buffers_[0].data()});
device()->SetBdtEntry(endpoint_, Direction::kRx, EvenOdd::kOdd,
{M_USB_BD_OWN | M_USB_BD_DTS |
V_USB_BD_BC(buffers_[1].size()) | M_USB_BD_DATA1,
buffers_[1].data()});
}
}
} // namespace frc971::teensy