blob: 9af650a6ccb2a47f2cbf0eafaa69b03a4823948c [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
38 endpoint_descriptor->AddByte(1); // bInterval
39 }
40}
41
42void InterruptOut::HandleOutFinished(int endpoint, BdtEntry *bdt_entry) {
43 if (endpoint == endpoint_) {
44
45 DisableInterrupts disable_interrupts;
46 if (first_rx_held_ == nullptr) {
47 first_rx_held_ = bdt_entry;
48 } else {
49 second_rx_held_ = bdt_entry;
50 }
51 }
52}
53
54int InterruptOut::ReceiveData(char *buffer) {
55 DisableInterrupts disable_interrupts;
56 if (first_rx_held_ == nullptr) {
57 return -1;
58 }
59
60 BdtEntry *const bdt_entry = first_rx_held_;
61 const size_t data_size = G_USB_BD_BC(bdt_entry->buffer_descriptor);
62 memcpy(buffer, bdt_entry->address, kSize);
63 dma_memory_barrier();
64
65 first_rx_held_->buffer_descriptor = M_USB_BD_OWN | M_USB_BD_DTS |
66 V_USB_BD_BC(kSize) |
67 static_cast<uint32_t>(next_rx_toggle_);
68 next_rx_toggle_ = Data01Inverse(next_rx_toggle_);
69
70 first_rx_held_ = second_rx_held_;
71 second_rx_held_ = nullptr;
72 return data_size;
73}
74
75void InterruptOut::HandleConfigured(int endpoint) {
76 if (endpoint == endpoint_) {
77 device()->ConfigureEndpointFor(endpoint_, true, false, true);
78 next_rx_toggle_ = Data01::kData0;
79 device()->SetBdtEntry(
80 endpoint_, Direction::kRx, EvenOdd::kEven,
81 {M_USB_BD_OWN | M_USB_BD_DTS | V_USB_BD_BC(buffers_[0].size()),
82 buffers_[0].data()});
83 device()->SetBdtEntry(endpoint_, Direction::kRx, EvenOdd::kOdd,
84 {M_USB_BD_OWN | M_USB_BD_DTS |
85 V_USB_BD_BC(buffers_[1].size()) | M_USB_BD_DATA1,
86 buffers_[1].data()});
87 }
88}
89
90} // namespace teensy
91} // namespace frc971