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