Software APIs
usb_device.h
1 // Copyright lowRISC contributors (OpenTitan project).
2 // Licensed under the Apache License, Version 2.0, see LICENSE for details.
3 // SPDX-License-Identifier: Apache-2.0
4 #ifndef OPENTITAN_SW_HOST_TESTS_USBDEV_USBDEV_STREAM_USB_DEVICE_H_
5 #define OPENTITAN_SW_HOST_TESTS_USBDEV_USBDEV_STREAM_USB_DEVICE_H_
6 #include <iostream>
7 
8 // The 'usbdev_serial' class may be used on platforms where libusb support is
9 // not available; libusb is required to exercise Isochronous streams, Interrupt
10 // streams and Control Transfers.
11 #if STREAMTEST_LIBUSB
12 #include <libusb-1.0/libusb.h>
13 #endif
14 
15 class USBDevice {
16  public:
17 #if STREAMTEST_LIBUSB
18  USBDevice(bool verbose = false, bool manual = false)
19  : verbose_(verbose),
20  manual_(manual),
21  state_(StateStreaming),
22  ctx_(nullptr),
23  devh_(nullptr) {}
24 #else
25  USBDevice(bool verbose = false, bool manual = false)
26  : verbose_(verbose),
27  manual_(manual),
28  state_(StateStreaming),
29  devh_(false) {}
30 #endif
31 
32  // Device states.
33  enum USBDevState {
34  StateStreaming,
35  StateSuspending,
36  StateSuspended,
37  StateResuming
38  };
39 
40  /**
41  * Test phases; named according to the event that we are expecting to occur.
42  */
43  typedef enum {
44  /**
45  * First test phase just tests regular Suspend/Resume signaling; after we've
46  * resumed, we expect a Bus Reset from the DPI/Host.
47  */
49  /**
50  * This test phase instructs the DPI model to put the DUT into Suspend long
51  * enough that this software will attempt to put the device into its Normal
52  * Sleep state and exercise the AON/Wakeup module, stopping the clocks but
53  * not powering down.
54  */
56  /*
57  * The AON/Wakeup module will cause us to awaken in response to a bus reset.
58  */
59  kSuspendPhaseSleepReset,
60  /**
61  * As above, but this time we're expecting a VBUS/SENSE loss.
62  */
64  /**
65  * Mirrors Resume detection for normal sleep, but this time we enter Deep
66  * Sleep and the power is removed too.
67  */
69  /**
70  * Mirrors Bus Reset detection for normal sleep, but this time we enter Deep
71  * Sleep and the power is removed too.
72  */
74  /**
75  * As above, but this time we're expecting a VBUS/SENSE loss.
76  */
78  /**
79  * Final phase; shut down.
80  */
83 
84  // DPI test numbers.
85  typedef enum usb_testutils_test_number {
86  kUsbTestNumberSmoke = 0,
87  kUsbTestNumberStreams,
88  kUsbTestNumberIso,
89  kUsbTestNumberMixed,
90  kUsbTestNumberSuspend,
91  kUsbTestNumberExc,
92  } usb_testutils_test_number_t;
93 
94  // Test/stream flags; these are common with device-side software.
95  typedef enum {
96  /**
97  * Mask for extracting the stream ID number.
98  */
100  /**
101  * Host shall retrieve IN data from the device for this stream.
102  */
104  /**
105  * Host shall check that IN data matches as expected.
106  */
108  /**
109  * DPI model (or Host) shall retry IN data fetches, where possible.
110  */
112  /**
113  * Host shall send OUT data to the device for this stream.
114  */
116  /**
117  * Default stream flags; for non-libusb builds.
118  */
123 
124  // Vendor-Specific requests.
125  static constexpr uint8_t kVendorGetData = 0x7du;
126  static constexpr uint8_t kVendorPutData = 0x7fu;
127 
128  // Maximum packet size of 64 bytes is used for Control, Interrupt and Bulk
129  // Transfers.
130  static constexpr unsigned kDevDataMaxPacketSize = 0x40U;
131 
132  // Our USB device has a maximum packet size of just 64 bytes even for
133  // Isochronous transfers; this may one day be increased.
134  static constexpr unsigned kDevIsoMaxPacketSize = 0x40U;
135 
136  /**
137  * Initialize USB device before test; called once at startup.
138  *
139  * @param vendorID Vendor ID code of the USB device.
140  * @param productID Product ID code of the USB device.
141  * @param devAddress Device address (0 for first accessible device).
142  * @param busNumber Bus number (if devAddress non-zero).
143  * @return true iff initialization was successful.
144  */
145  bool Init(uint16_t productID, uint16_t vendorID, uint8_t devAddress = 0u,
146  uint8_t busNumber = 0u);
147  /**
148  * Finalize USB device before completing test.
149  *
150  * @return true iff finalization was successful.
151  */
152  bool Fin();
153  /**
154  * (Re)open the device. If the device is already open, this function just
155  * returns immediately.
156  *
157  * @return true iff opening was successful, or the device was already open.
158  */
159  bool Open();
160  /**
161  * Close the device, if open. If the device is already closed, this function
162  * just returns immediately.
163  *
164  * @return true iff closing was successful, or the device was already closed.
165  */
166  bool Close();
167  /**
168  * Service the device; keep libusb transfers being processed.
169  *
170  * @return true iff the device is still operational.
171  */
172  bool Service();
173 
174 #if STREAMTEST_LIBUSB
175  /**
176  * Claim an interface on the device.
177  *
178  * @param interface The interface number of the interface to be claimed.
179  * @return The result of the operation.
180  */
181  int ClaimInterface(unsigned interface) const {
182  return libusb_claim_interface(devh_, (int)interface);
183  }
184  /**
185  * Release an interface on the device.
186  *
187  * @param interface The interface number of the interface to be claimed.
188  * @return The result of the operation.
189  */
190  int ReleaseInterface(unsigned interface) const {
191  return libusb_release_interface(devh_, (int)interface);
192  }
193  /**
194  * Emit a textual report of an error returned by libusb.
195  *
196  * @param rc Return code from libusb function.
197  * @return false as a convenience for indicating failure to caller.
198  */
199  inline bool ErrorUSB(const char *prefix, int rc) {
200  std::cerr << prefix << " (" << rc << ", " << libusb_error_name(rc) << ")"
201  << std::endl;
202  return false;
203  }
204  /**
205  * Retrieve libusb device handle.
206  *
207  * @return The device handle, or nullptr if none eg. device not open.
208  */
209  libusb_device_handle *DeviceHandle() const { return devh_; }
210  /**
211  * Fill Control Transfer descriptor.
212  */
213  void FillControlTransfer(struct libusb_transfer *xfr, uint8_t ep,
214  uint8_t *buffer, libusb_transfer_cb_fn callback,
215  void *user_data, unsigned timeout_ms) {
216  libusb_fill_control_transfer(xfr, devh_, buffer, callback, user_data,
217  timeout_ms);
218  // Complete the endpoint number because we're _not_ always targeting
219  // Endpoint Zero.
220  xfr->endpoint = ep;
221  }
222  /**
223  * Fill Bulk Transfer descriptor.
224  */
225  void FillBulkTransfer(struct libusb_transfer *xfr, uint8_t ep,
226  uint8_t *buffer, size_t len,
227  libusb_transfer_cb_fn callback, void *user_data,
228  unsigned timeout_ms) const {
229  libusb_fill_bulk_transfer(xfr, devh_, ep, buffer, len, callback, user_data,
230  timeout_ms);
231  }
232  /**
233  * Fill Interrupt Transfer descriptor.
234  */
235  void FillIntTransfer(struct libusb_transfer *xfr, uint8_t ep, uint8_t *buffer,
236  size_t len, libusb_transfer_cb_fn callback,
237  void *user_data, unsigned timeout_ms) const {
238  libusb_fill_interrupt_transfer(xfr, devh_, ep, buffer, len, callback,
239  user_data, timeout_ms);
240  }
241  /**
242  * Fill Isochronous transfer descriptor,
243  */
244  void FillIsoTransfer(struct libusb_transfer *xfr, uint8_t ep, uint8_t *buffer,
245  size_t len, unsigned num_iso_packets,
246  libusb_transfer_cb_fn callback, void *user_data,
247  unsigned timeout_ms) const {
248  libusb_fill_iso_transfer(xfr, devh_, ep, buffer, len, num_iso_packets,
249  callback, user_data, timeout_ms);
250  }
251  /**
252  * Complete the lengths of the packets in this Isochronous transfer, assuming
253  * that packets are of uniform size.
254  *
255  * @param xfr Isochronous transfer to be completed.
256  * @param len Total length of all packets within the transfer.
257  */
258  void SetIsoPacketLengths(struct libusb_transfer *xfr, unsigned len) const {
259  libusb_set_iso_packet_lengths(xfr, len);
260  }
261  /**
262  * Allocate a transfer descriptor to be completed by the caller.
263  *
264  * @return Pointer to transfer transcript, or NULL if allocation failed.
265  */
266  struct libusb_transfer *AllocTransfer(unsigned iso_packets) const {
267  return libusb_alloc_transfer((int)iso_packets);
268  }
269  /**
270  * Free an allocated transfer descriptor.
271  *
272  * @param xfr The transfer descriptor to be freed.
273  */
274  void FreeTransfer(struct libusb_transfer *xfr) const {
275  return libusb_free_transfer(xfr);
276  }
277  /**
278  * Submit a transfer for processing.
279  *
280  * @param xfr The transfer to be submitted.
281  */
282  int SubmitTransfer(struct libusb_transfer *xfr) const {
283  return libusb_submit_transfer(xfr);
284  }
285  /**
286  * Cancel a pending transfer.
287  *
288  * @param xfr The transfer to be cancelled.
289  */
290  int CancelTransfer(struct libusb_transfer *xfr) const {
291  return libusb_cancel_transfer(xfr);
292  }
293 #endif
294  /**
295  * Is test progress being directed/controlled manually?
296  */
297  inline bool ManualControl() const { return manual_; }
298  /**
299  * Returns the current phase of the test
300  */
301  inline usbdev_suspend_phase_t TestPhase() const { return testPhase_; }
302  /**
303  * Returns microseconds corresponding to the given number of bus frame delays.
304  */
305  static inline uint32_t TimeFrames(unsigned frames) { return frames * 1000u; }
306  /**
307  * Delay for at least the requested number of microseconds (wall time);
308  * this is important in ensuring the appropriate time intervals (eg. Resume
309  * Signaling) are met.
310  *
311  * For verbose reporting, the also indicates whether traffic is expected, and
312  * may be visually paired up with any device-side logging or logic analyzer
313  * traces.
314  *
315  * @param time_us Minimum time delay, in microseconds.
316  * @param with_traffic Indicates whether USB traffic is expected during this
317  * time.
318  * @return true iff delayed without error
319  */
320  bool Delay(uint32_t time_us, bool with_traffic = true);
321  /**
322  * Read Test Descriptor from the DUT using a Vendor-Specific command.
323  *
324  * @return true iff the operation was successful.
325  */
326  bool ReadTestDesc();
327  /**
328  * Return the test number from the test descriptor.
329  *
330  * @return test number
331  */
332  uint8_t TestNumber() const { return testNumber_; }
333  /**
334  * Return the specified test argument from the test descriptor.
335  *
336  * @param arg Argument number.
337  * @return test argument
338  */
339  uint8_t TestArg(unsigned arg) const {
340  // Presently all defined tests support up to 4 arguments.
341  return (arg < 4U) ? testArg_[arg] : 0U;
342  }
343  /**
344  * Reset and Reconfigure the DUT.
345  *
346  * @return true iff the operation was successful.
347  */
348  bool Reset();
349  /**
350  * Suspend device.
351  *
352  * @return true iff the operation was successful.
353  */
354  bool Suspend();
355  /**
356  * Resume operation of suspended device.
357  */
358  bool Resume();
359  /**
360  * Connect device to the USB.
361  *
362  * @param true iff the operation was succesful.
363  */
364  bool Connect();
365  /**
366  * Disconnect device from the USB.
367  *
368  * @param true iff the operation was succesful.
369  */
370  bool Disconnect();
371  /**
372  * Return the textual name of the specified test phase.
373  *
374  * @param phase Test phase.
375  * @return Textual name.
376  */
377  static const char *PhaseName(usbdev_suspend_phase_t phase);
378  /**
379  * Returns the current state of the device.
380  *
381  * @return current state.
382  */
383  USBDevState CurrentState() const { return state_; }
384  /**
385  * Sets the current state of the device in the Suspend/Resume signaling.
386  *
387  * @param state The current state of the device.
388  */
389  void SetState(USBDevState state) { state_ = state; }
390 
391  private:
392  // Verbose logging/reporting.
393  bool verbose_;
394 
395  // Test phases/behavior are being directed/controlled manually.
396  bool manual_;
397 
398  // Current device state.
399  USBDevState state_;
400 
401  // Vendor ID of USB device.
402  uint16_t vendorID_;
403  // Product ID of USB device.
404  uint16_t productID_;
405 
406  // Specified bus number.
407  uint8_t busSpec_;
408  // Specified device address.
409  uint8_t addrSpec_;
410 
411  // Bus number of the device we're using.
412  uint8_t busNumber_;
413  // (Bus-local) device address of the device we're using.
414  uint8_t devAddress_;
415 
416 #if STREAMTEST_LIBUSB
417  // Context information for libusb.
418  libusb_context *ctx_;
419 
420  // Device handle.
421  libusb_device_handle *devh_;
422 
423  // Parent device handler.
424  libusb_device_handle *parenth_;
425  int portNumber_;
426 
427  // Device descriptor.
428  libusb_device_descriptor devDesc_;
429 #else
430  // Device handle; just retain whether open/closed.
431  bool devh_;
432 #endif
433 
434  // Device path (bus number - ports numbers).
435  std::string devPath_;
436 
437  // Current phase within the Suspend-Sleep-Wakeup-Resume testing sequence.
438  usbdev_suspend_phase_t testPhase_;
439 
440  usb_testutils_test_number_t testNumber_;
441 
442  uint8_t testArg_[4];
443 
444  // TODO: We should introduce a timeout on libusb Control Transfers.
445  static const unsigned kControlTransferTimeout = 0u;
446 
447  // Vendor-Specific Commands.
448  static const uint8_t kVendorTestConfig = 0x7cu;
449  static const uint8_t kVendorTestStatus = 0x7eu;
450 };
451 
452 #endif // OPENTITAN_SW_HOST_TESTS_USBDEV_USBDEV_STREAM_USB_DEVICE_H_