blob: 30f024e16614f32af2e040259a4009a1eb202f89 [file] [log] [blame]
Brian Silverman4aa83042018-01-05 12:47:31 -08001#include "motors/usb/interrupt_out.h"
2
Stephan Pleinesf63bde82024-01-13 15:59:33 -08003namespace frc971::teensy {
Brian Silverman4aa83042018-01-05 12:47:31 -08004
5void 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 Schrader790cb542023-07-05 21:06:52 -070037 endpoint_descriptor->AddByte(1); // bInterval
Brian Silverman4aa83042018-01-05 12:47:31 -080038 }
39}
40
41void InterruptOut::HandleOutFinished(int endpoint, BdtEntry *bdt_entry) {
42 if (endpoint == endpoint_) {
Brian Silverman4aa83042018-01-05 12:47:31 -080043 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
52int 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
73void 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 Pleinesf63bde82024-01-13 15:59:33 -080088} // namespace frc971::teensy