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