blob: 1117bc8c081808a9f8ef3612b50cbdc54537d69a [file] [log] [blame]
Brian Silvermanf91524f2017-09-23 13:15:55 -04001#ifndef MOTORS_USB_USB_H_
2#define MOTORS_USB_USB_H_
3
4#include <assert.h>
Brian Silvermand930f282017-11-04 23:09:12 -04005#include <string.h>
Philipp Schrader790cb542023-07-05 21:06:52 -07006
7#include <memory>
Brian Silvermanf91524f2017-09-23 13:15:55 -04008#include <string>
9#include <vector>
Brian Silvermanf91524f2017-09-23 13:15:55 -040010
John Park33858a32018-09-28 23:05:48 -070011#include "aos/macros.h"
Brian Silvermanf91524f2017-09-23 13:15:55 -040012#include "motors/core/kinetis.h"
13#include "motors/usb/constants.h"
Brian Silverman45564a82018-09-02 16:35:22 -070014#include "motors/util.h"
Brian Silvermanf91524f2017-09-23 13:15:55 -040015
16namespace frc971 {
17namespace teensy {
18
19// A sufficient memory barrier between writing some data and telling the USB
20// hardware to read it or having the USB hardware say some data is readable and
21// actually reading it.
Brian Silverman45564a82018-09-02 16:35:22 -070022static inline void dma_memory_barrier() { DmaMemoryBarrier(); }
Brian Silvermanf91524f2017-09-23 13:15:55 -040023
24// Aligned for faster access via memcpy etc.
Brian Silverman69f96c22017-11-01 02:54:02 -040025//
26// Also, the Freescale example stack forces aligned buffers to work around some
27// hardware limitations which may or may not apply to our chips.
Brian Silvermanf91524f2017-09-23 13:15:55 -040028typedef void *DataPointer __attribute__((aligned(4)));
29
30// An entry in the Buffer Descriptor Table.
31struct BdtEntry {
32 uint32_t buffer_descriptor;
33 DataPointer address;
34};
35
36#define V_USB_BD_BC(value) \
37 static_cast<uint32_t>(static_cast<uint32_t>(value) << 16)
38#define G_USB_BD_BC(bd) (((bd) >> 16) & UINT32_C(0x3FF))
39#define M_USB_BD_OWN UINT32_C(1 << 7)
40#define M_USB_BD_DATA1 UINT32_C(1 << 6)
41static_assert(static_cast<uint32_t>(Data01::kData1) == M_USB_BD_DATA1,
42 "Wrong value");
43#define M_USB_BD_KEEP UINT32_C(1 << 5)
44#define M_USB_BD_NINC UINT32_C(1 << 4)
45#define M_USB_BD_DTS UINT32_C(1 << 3)
46#define M_USB_BD_STALL UINT32_C(1 << 2)
47#define V_USB_BD_PID(value) \
48 static_cast<uint32_t>(static_cast<uint32_t>(value) << 2)
49#define G_USB_BD_PID(bd) static_cast<UsbPid>(((bd) >> 2) & UINT32_C(0xF))
50
51#define G_USB_STAT_ENDP(stat) (((stat) >> 4) & UINT32_C(0xF))
52#define M_USB_STAT_TX UINT32_C(1 << 3)
53#define M_USB_STAT_ODD UINT32_C(1 << 2)
54
55// The various types of descriptors defined in the standard for retrieval via
56// GetDescriptor.
57static constexpr uint8_t kUsbDescriptorTypeMin = 1;
58static constexpr uint8_t kUsbDescriptorTypeMax = 11;
59enum class UsbDescriptorType : uint8_t {
60 kDevice = 1,
61 kConfiguration = 2,
62 kString = 3,
63 kInterface = 4,
64 kEndpoint = 5,
65 kDeviceQualifier = 6,
66 kOtherSpeedConfiguration = 7,
67 kInterfacePower = 8,
68 kOtg = 9,
69 kDebug = 10,
70 kInterfaceAssociation = 11,
71};
72
73// The class-specific descriptor types.
74enum class UsbClassDescriptorType : uint8_t {
75 kDevice = 0x21,
76 kConfiguration = 0x22,
77 kString = 0x23,
78 kInterface = 0x24,
79 kEndpoint = 0x25,
Brian Silvermand930f282017-11-04 23:09:12 -040080
81 kHidHid = 0x21,
82 kHidReport = 0x22,
83 kHidPhysical = 0x23,
Brian Silvermanf91524f2017-09-23 13:15:55 -040084};
85
86// The names of the setup request types from the standard.
87enum class SetupRequestType {
88 kStandard = 0,
89 kClass = 1,
90 kVendor = 2,
91 kReserved = 3,
92};
93
94// Set means device-to-host, clear means host-to-device.
95#define M_SETUP_REQUEST_TYPE_IN UINT8_C(1 << 7)
96#define G_SETUP_REQUEST_TYPE_TYPE(type) \
97 static_cast<SetupRequestType>(((type) >> 5) & UINT8_C(3))
98#define G_SETUP_REQUEST_TYPE_RECIPIENT(type) ((type)&UINT8_C(0x1F))
99#define G_SETUP_REQUEST_INDEX_ENDPOINT(index) ((index)&UINT8_C(0x7F))
100
101// The names of the standard recipients for setup requests.
102namespace standard_setup_recipients {
103constexpr int kDevice = 0;
104constexpr int kInterface = 1;
105constexpr int kEndpoint = 2;
106constexpr int kOther = 3;
107} // namespace standard_setup_recipients
108
Brian Silverman4aa83042018-01-05 12:47:31 -0800109namespace microsoft_feature_descriptors {
110constexpr int kExtendedCompatibilityId = 4;
111constexpr int kExtendedProperties = 5;
112} // namespace microsoft_feature_descriptors
113
Brian Silvermand930f282017-11-04 23:09:12 -0400114// The HID class specification says this. Can't find any mention in the main
115// standard.
116#define G_DESCRIPTOR_TYPE_TYPE(descriptor_type) \
117 ((descriptor_type) >> 5 & UINT8_C(3))
118namespace standard_descriptor_type_types {
119constexpr int kStandard = 0;
120constexpr int kClass = 1;
121constexpr int kVendor = 2;
122} // namespace standard_descriptor_type_types
123
Brian Silverman4aa83042018-01-05 12:47:31 -0800124constexpr uint8_t vendor_specific_class() { return 0xFF; }
125
Brian Silvermanf91524f2017-09-23 13:15:55 -0400126class UsbFunction;
127
128// Allows building up a list of descriptors. This supports a much nicer API than
129// the usual "hard-code a char[] with all the sizes and offsets at compile
130// time". Space for each descriptor is reserved, and then it may be filled out
131// from beginning to end at any time.
132//
133// An instance is the thing that the GetDescriptor operation sends to the host.
134// This is not the concept that the core and class standards call "Foo
135// Descriptor" etc; see Descriptor for that.
136class UsbDescriptorList {
137 public:
138 // Represents a single descriptor. All of the contents must be written before
139 // this object is destroyed.
140 //
141 // Create one via UsbDescriptorList::CreateDescriptor.
142 class Descriptor {
143 public:
144 // All of the allocated space must be filled first.
145 ~Descriptor() {
146 if (descriptor_list_ == nullptr) {
147 return;
148 }
149 // Verify we wrote all the bytes first.
150 assert(next_index_ == end_index_);
151 --descriptor_list_->open_descriptors_;
152 }
153
154 void AddUint16(uint16_t value) {
155 AddByte(value & 0xFF);
156 AddByte((value >> 8) & 0xFF);
157 }
158
159 void AddByte(uint8_t value) {
160 assert(next_index_ < end_index_);
161 data()[next_index_] = value;
162 ++next_index_;
163 }
164
165 // Overwrites an already-written byte.
166 void SetByte(int index, uint8_t value) {
167 assert(index + start_index_ < end_index_);
168 data()[index + start_index_] = value;
169 }
170
171 private:
172 Descriptor(UsbDescriptorList *descriptor_list, int start_index,
173 int end_index)
174 : descriptor_list_(descriptor_list),
175 start_index_(start_index),
176 end_index_(end_index),
177 next_index_(start_index_) {}
178
Philipp Schrader790cb542023-07-05 21:06:52 -0700179 char *data() const { return &descriptor_list_->data_[0]; }
Brian Silvermanf91524f2017-09-23 13:15:55 -0400180
181 UsbDescriptorList *const descriptor_list_;
182 const int start_index_, end_index_;
183 int next_index_;
184
185 friend class UsbDescriptorList;
186
187 DISALLOW_COPY_AND_ASSIGN(Descriptor);
188 };
189
190 UsbDescriptorList() = default;
191 ~UsbDescriptorList() = default;
192
193 // Creates a new descriptor at the end of the list.
194 // length is the number of bytes, including the length byte.
195 // descriptor_type is the descriptor type, which is the second byte after the
196 // length.
197 ::std::unique_ptr<Descriptor> CreateDescriptor(
198 uint8_t length, UsbDescriptorType descriptor_type) {
199 return CreateDescriptor(length, static_cast<uint8_t>(descriptor_type));
200 }
201
202 ::std::unique_ptr<Descriptor> CreateDescriptor(
203 uint8_t length, UsbClassDescriptorType descriptor_type) {
204 assert(data_.size() > 0);
205 return CreateDescriptor(length, static_cast<uint8_t>(descriptor_type));
206 }
207
Brian Silvermand930f282017-11-04 23:09:12 -0400208 void AddPremadeDescriptor(const uint8_t *data, int length) {
209 const int start_index = data_.size();
210 const int end_index = start_index + length;
211 data_.resize(end_index);
212 memcpy(&data_[start_index], data, length);
213 }
214
Brian Silverman587edcc2018-01-15 12:00:22 -0800215 void AddPremadeDescriptor(const UsbDescriptorList &other_list) {
216 other_list.CheckFinished();
217 AddPremadeDescriptor(
218 reinterpret_cast<const uint8_t *>(other_list.data_.data()),
219 other_list.data_.size());
220 }
221
Brian Silvermanf91524f2017-09-23 13:15:55 -0400222 void CheckFinished() const { assert(open_descriptors_ == 0); }
223
224 int CurrentSize() const { return data_.size(); }
225
Brian Silverman587edcc2018-01-15 12:00:22 -0800226 const char *GetData() const {
227 CheckFinished();
228 return data_.data();
229 }
230
Brian Silvermanf91524f2017-09-23 13:15:55 -0400231 private:
232 ::std::unique_ptr<Descriptor> CreateDescriptor(uint8_t length,
233 uint8_t descriptor_type) {
234 const int start_index = data_.size();
235 const int end_index = start_index + length;
236 data_.resize(end_index);
237 ++open_descriptors_;
238 auto r = ::std::unique_ptr<Descriptor>(
239 new Descriptor(this, start_index, end_index));
240 r->AddByte(length); // bLength
241 r->AddByte(descriptor_type); // bDescriptorType
242 return r;
243 }
244
245 int open_descriptors_ = 0;
246
247 ::std::string data_;
248
249 friend class UsbDevice;
250
251 DISALLOW_COPY_AND_ASSIGN(UsbDescriptorList);
252};
253
254extern "C" void usb_isr(void);
255
256// USB state events are managed by asking each function if it wants to handle
257// them, sequentially. For the small number of functions which can be
258// practically supported with the limited number of endpoints, this performs
259// better than fancier things like hash maps.
260
261// Manages one of the Teensy's USB peripherals as a USB slave device.
262//
263// This supports being a composite device with multiple functions.
264//
265// Attaching functions etc is called "setup", and must be completed before
266// Initialize() is called.
267//
268// Detaching functions is called "teardown" and must happen after Shutdown().
269// TODO(Brian): Implement Shutdown().
270class UsbDevice final {
271 public:
272 // Represents the data that comes with a UsbPid::kSetup.
273 // Note that the order etc is important because we memcpy into this.
274 struct SetupPacket {
275 uint8_t request_type; // bmRequestType
276 uint8_t request; // bRequest
277 uint16_t value; // wValue
278 uint16_t index; // wIndex
279 uint16_t length; // wLength
280 } __attribute__((aligned(4)));
281 static_assert(sizeof(SetupPacket) == 8, "wrong size");
282
283 enum class SetupResponse {
284 // Indicates this function doesn't recognize the setup packet.
285 kIgnored,
286
287 // Indicates the endpoint should be stalled.
288 //
289 // Don't return this if the packet is for another function.
290 kStall,
291
292 // Indicates this setup packet was handled. Functions must avoid eating
293 // packets intended for other functions.
294 kHandled,
295 };
296
297 static constexpr int kEndpoint0MaxSize = 64;
298
299 // The only language code we support.
300 static constexpr uint16_t english_us_code() { return 0x0409; }
301
302 UsbDevice(int index, uint16_t vendor_id, uint16_t product_id);
303 ~UsbDevice();
304
305 // Ends setup and starts being an actual USB device.
306 void Initialize();
307
308 // Adds a string to the table and returns its index.
309 //
310 // For simplicity, we only support strings with english_us_code().
311 //
312 // May only be called during setup.
313 int AddString(const ::std::string &string) {
314 assert(!is_set_up_);
315 const int r = strings_.size();
316 strings_.emplace_back(string.size() * 2 + 2, '\0');
317 strings_.back()[0] = 2 + string.size() * 2;
318 strings_.back()[1] = static_cast<uint8_t>(UsbDescriptorType::kString);
319 for (size_t i = 0; i < string.size(); ++i) {
320 strings_.back()[i * 2 + 2] = string[i];
321 }
322 return r;
323 }
324
325 // Sets the manufacturer string.
326 //
327 // May only be called during setup.
328 void SetManufacturer(const ::std::string &string) {
329 device_descriptor_->SetByte(14, AddString(string)); // iManufacturer
330 }
331
332 // Sets the product string.
333 //
334 // May only be called during setup.
335 void SetProduct(const ::std::string &string) {
336 device_descriptor_->SetByte(15, AddString(string)); // iProduct
337 }
338
339 // Sets the serial number string.
340 //
341 // May only be called during setup.
342 void SetSerialNumber(const ::std::string &string) {
343 device_descriptor_->SetByte(16, AddString(string)); // iSerialNumber
344 }
345
346 // Queues up an empty IN packet for endpoint 0. This is a common way to
347 // respond to various kinds of configuration commands.
348 //
349 // This may only be called from the appropriate function callbacks.
350 void SendEmptyEndpoint0Packet();
351
352 // Queues some data to send on endpoint 0. This includes putting the initial
353 // packets into the TX buffers.
354 //
355 // This may only be called from the appropriate function callbacks.
356 void QueueEndpoint0Data(const char *data, int size);
357
358 // Stalls an endpoint until it's cleared.
359 //
360 // This should only be called by or on behalf of the function which owns
361 // endpoint.
362 void StallEndpoint(int endpoint);
363
364 // Configures an endpoint to send and/or receive, with or without DATA0/DATA1
365 // handshaking. handshake should probably be true for everything except
366 // isochronous endpoints.
367 //
368 // This should only be called by or on behalf of the function which owns
369 // endpoint.
370 void ConfigureEndpointFor(int endpoint, bool rx, bool tx, bool handshake);
371
372 void SetBdtEntry(int endpoint, Direction direction, EvenOdd odd,
373 BdtEntry bdt_entry);
374
375 private:
376 // Clears all pending interrupts.
377 void ClearInterrupts();
378
379 // Deals with an interrupt that has occured.
380 void HandleInterrupt();
381
382 // Processes a token on endpoint 0.
383 void HandleEndpoint0Token(uint8_t stat);
384
385 // Processes a setup packet on endpoint 0.
386 void HandleEndpoint0SetupPacket(const SetupPacket &setup_packet);
387
388 // Sets endpoint 0 to return STALL tokens. We clear this condition upon
389 // receiving the next SETUP token.
390 void StallEndpoint0();
391
392 // Places the first packet from {endpoint0_data_, endpoint0_data_left_} into
393 // the TX buffers (if there is any data). This may only be called when the
394 // next TX buffer is empty.
395 bool BufferEndpoint0TxPacket();
396
397 // Which USB peripheral this is.
398 const int index_;
399
400 // The string descriptors in order.
401 ::std::vector<::std::string> strings_;
402
403 // TODO(Brian): Refactor into something more generic, because I think this is
404 // shared with all non-isochronous endpoints?
405 Data01 endpoint0_tx_toggle_;
406 EvenOdd endpoint0_tx_odd_;
407 uint8_t endpoint0_receive_buffer_[2][kEndpoint0MaxSize]
408 __attribute__((aligned(4)));
409
410 // A temporary buffer for holding data to transmit on endpoint 0. Sometimes
411 // this is used and sometimes the data is sent directly from some other
412 // location (like for descriptors).
413 char endpoint0_transmit_buffer_[kEndpoint0MaxSize];
414
415 // The data we're waiting to send from endpoint 0. The data must remain
416 // constant until this transmission is done.
417 //
418 // When overwriting this, we ignore if it's already non-nullptr. The host is
419 // supposed to read all of the data before asking for more. If it doesn't do
420 // that, it will just get garbage data because it's unclear what it expects.
421 //
422 // Do note that endpoint0_data_ != nullptr && endpoint0_data_left_ == 0 is an
423 // important state. This means we're going to return a 0-length packet the
424 // next time the host asks. However, depending on the length it asked for,
425 // that might never happen.
426 const char *endpoint0_data_ = nullptr;
427 int endpoint0_data_left_ = 0;
428
429 // If non-0, the new address we're going to start using once the status stage
430 // of the current setup request is finished.
431 uint16_t new_address_ = 0;
432
433 UsbDescriptorList device_descriptor_list_;
434 UsbDescriptorList config_descriptor_list_;
435
436 ::std::unique_ptr<UsbDescriptorList::Descriptor> device_descriptor_,
437 config_descriptor_;
438
439 int configuration_ = 0;
440
441 bool is_set_up_ = false;
442
443 // The function which owns each endpoint.
444 ::std::vector<UsbFunction *> endpoint_mapping_;
445 // The function which owns each interface.
446 ::std::vector<UsbFunction *> interface_mapping_;
447 // All of the functions (without duplicates).
448 ::std::vector<UsbFunction *> functions_;
449
Brian Silverman4aa83042018-01-05 12:47:31 -0800450 // Filled out during Initialize().
451 ::std::string microsoft_extended_id_descriptor_;
452
Brian Silvermanf91524f2017-09-23 13:15:55 -0400453 friend void usb_isr(void);
454 friend class UsbFunction;
455};
456
457// Represents a USB function. This consists of a set of descriptors and
458// interfaces.
459//
460// Each instance is a single function, so there can be multiple instances of the
461// same subclass in the same devices (ie two serial ports).
462class UsbFunction {
463 public:
464 UsbFunction(UsbDevice *device) : device_(device) {
465 device_->functions_.push_back(this);
466 }
467 virtual ~UsbFunction() = default;
468
469 protected:
470 using SetupResponse = UsbDevice::SetupResponse;
471
472 static constexpr uint8_t iad_descriptor_length() { return 8; }
473 static constexpr uint8_t interface_descriptor_length() { return 9; }
474 static constexpr uint8_t endpoint_descriptor_length() { return 7; }
475
476 static constexpr uint8_t m_endpoint_address_in() { return 1 << 7; }
477 static constexpr uint8_t m_endpoint_attributes_control() { return 0x00; }
478 static constexpr uint8_t m_endpoint_attributes_isochronous() { return 0x01; }
Brian Silvermanf71c3332017-11-23 20:38:22 -0500479 static constexpr uint8_t m_endpoint_attributes_bulk() { return 0x02; }
Brian Silvermanf91524f2017-09-23 13:15:55 -0400480 static constexpr uint8_t m_endpoint_attributes_interrupt() { return 0x03; }
481
482 // Adds a new endpoint and returns its index.
483 //
484 // Note that at least one descriptor for this newly created endpoint must be
485 // added via CreateConfigDescriptor.
486 //
487 // TODO(Brian): Does this hardware actually only support a single direction
488 // per endpoint number, or can it get a total of 30 endpoints max?
489 //
490 // May only be called during setup.
491 int AddEndpoint();
492
493 // Adds a new interface and returns its index.
494 //
495 // You'll probably want to put this new interface in at least one descriptor
496 // added via CreateConfigDescriptor.
497 //
498 // May only be called during setup.
499 int AddInterface();
500
501 // Adds a new descriptor in the configuration descriptor list. See
502 // UsbDescriptorList::CreateDescriptor for details.
503 //
504 // Note that the order of calls to this is highly significant. In general,
505 // this should only be called from Initialize().
506 //
507 // May only be called during setup.
508 template <typename T>
509 ::std::unique_ptr<UsbDescriptorList::Descriptor> CreateDescriptor(
510 uint8_t length, T descriptor_type) {
511 return device_->config_descriptor_list_.CreateDescriptor(length,
512 descriptor_type);
513 }
Brian Silvermand930f282017-11-04 23:09:12 -0400514 void AddPremadeDescriptor(const uint8_t *data, int length) {
515 device_->config_descriptor_list_.AddPremadeDescriptor(data, length);
516 }
Brian Silverman587edcc2018-01-15 12:00:22 -0800517 void AddPremadeDescriptor(const UsbDescriptorList &other_list) {
518 device_->config_descriptor_list_.AddPremadeDescriptor(other_list);
519 }
Brian Silvermanf91524f2017-09-23 13:15:55 -0400520
521 UsbDevice *device() const { return device_; }
522
Brian Silverman4aa83042018-01-05 12:47:31 -0800523 void CreateIadDescriptor(int first_interface, int interface_count,
524 int function_class, int function_subclass,
525 int function_protocol,
526 const ::std::string &function);
527
528 // Sets the interface GUIDs for this function. Each GUID (one per interface?)
529 // should be followed by a NUL.
530 //
531 // If this is never called, no GUID extended property will be reported.
532 //
533 // This is needed to pass to Windows so WinUSB will be happy. Generate them at
534 // https://www.guidgenerator.com/online-guid-generator.aspx (Uppcase, Braces,
535 // and Hyphens).
536 //
537 // May only be called during setup.
538 void SetMicrosoftDeviceInterfaceGuids(const ::std::string &guids);
539
Brian Silvermanf91524f2017-09-23 13:15:55 -0400540 private:
541 virtual void Initialize() = 0;
542
543 virtual SetupResponse HandleEndpoint0SetupPacket(
544 const UsbDevice::SetupPacket & /*setup_packet*/) {
545 return SetupResponse::kIgnored;
546 }
547
548 virtual SetupResponse HandleEndpoint0OutPacket(void * /*data*/,
549 int /*data_length*/) {
550 return SetupResponse::kIgnored;
551 }
552
Brian Silvermand930f282017-11-04 23:09:12 -0400553 virtual SetupResponse HandleGetDescriptor(
554 const UsbDevice::SetupPacket & /*setup_packet*/) {
555 return SetupResponse::kIgnored;
556 }
557
Brian Silverman4aa83042018-01-05 12:47:31 -0800558 // Returns the concatenated compatible ID and subcompatible ID.
559 virtual ::std::string MicrosoftExtendedCompatibleId() {
560 // Default to both of them being "unused".
561 return ::std::string(16, '\0');
562 }
563
564 virtual void HandleOutFinished(int /*endpoint*/, BdtEntry * /*bdt_entry*/) {}
565 virtual void HandleInFinished(int /*endpoint*/, BdtEntry * /*bdt_entry*/,
566 EvenOdd /*odd*/) {}
Brian Silvermanf91524f2017-09-23 13:15:55 -0400567
568 // Called when a given interface is configured (aka "experiences a
569 // configuration event"). This means all rx and tx buffers have been cleared
570 // and should be filled as appropriate, starting from data0. Also,
571 // ConfigureEndpointFor should be called with the appropriate arguments.
572 virtual void HandleConfigured(int endpoint) = 0;
573
574 // Should reset everything to use the even buffers next.
575 virtual void HandleReset() = 0;
576
Brian Silverman4aa83042018-01-05 12:47:31 -0800577 int first_interface_ = -1;
578
579 // Filled out during Initialize().
580 ::std::string microsoft_extended_property_descriptor_;
581
Brian Silvermanf91524f2017-09-23 13:15:55 -0400582 UsbDevice *const device_;
583
584 friend class UsbDevice;
585};
586
587} // namespace teensy
588} // namespace frc971
589
590#endif // MOTORS_USB_USB_H_