Software APIs
usb_testutils.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 
5 #ifndef OPENTITAN_SW_DEVICE_LIB_TESTING_USB_TESTUTILS_H_
6 #define OPENTITAN_SW_DEVICE_LIB_TESTING_USB_TESTUTILS_H_
7 
8 #include <stdbool.h>
9 #include <stddef.h>
10 #include <stdint.h>
11 
12 #include "sw/device/lib/base/status.h"
14 #include "sw/device/lib/testing/test_framework/check.h"
15 #include "usb_testutils_diags.h"
16 
17 // Have Data Toggle Restore functionality (Prod)?
18 #define USBDEV_HAVE_TOGGLE_STATE 0
19 // Have separated Available OUT and SETUP Buffer FIFOs (Prod)?
20 #define USBDEV_HAVE_SEPARATED_FIFOS 0
21 
22 // Result codes to rx/tx callback handlers
23 typedef enum {
24  /**
25  * Successful completion.
26  */
27  kUsbTestutilsXfrResultOk = 0u,
28  /**
29  * Failed to transfer because of internal error,
30  * eg. buffer exhaustion.
31  */
32  kUsbTestutilsXfrResultFailed = 1u,
33  /**
34  * Link reset interrupted transfer.
35  */
36  kUsbTestutilsXfrResultLinkReset = 2u,
37  /**
38  * Canceled by suspend, endpoint removal or finalization.
39  */
40  kUsbTestutilsXfrResultCanceled = 3u,
41 } usb_testutils_xfr_result_t;
42 
43 // Flags affecting the transfer of larger data buffers
44 typedef enum {
45  kUsbTestutilsXfrMaxPacketMask = 0x7fu, // Max packet size [0,0x40U]
46  /**
47  * Explicitly specify the maximum packet size; otherwise the device default
48  * of USBDEV_MAX_PACKET_SIZE shall be assumed.
49  */
50  kUsbTestutilsXfrMaxPacketSupplied = 0x100u,
51  /**
52  * Employ double-buffering to minimize the response time to notification of
53  * each packet transmission. This does require that two device packet buffers
54  * be available for use, but it increases the transfer rate.
55  */
56  kUsbTestutilsXfrDoubleBuffered = 0x200u,
57  /**
58  * Emit/Expect Zero Length Packet as termination of data stage in the event
59  * that the final packet of the transfer is maximum length
60  */
61  kUsbTestutilsXfrEmployZLP = 0x400u,
62 } usb_testutils_xfr_flags_t;
63 
64 // Transfer Type (also describes Endpoints)
65 typedef enum usb_testutils_transfer_type {
66  /**
67  * Control Transfer (Endpoint)
68  */
69  kUsbTransferTypeControl = 0,
70  /**
71  * Isochronous Transfer (Endpoint)
72  */
73  kUsbTransferTypeIsochronous,
74  /**
75  * Bulk Transfer (Endpoint)
76  */
77  kUsbTransferTypeBulk,
78  /**
79  * Interrupt Transfer (Endpoint)
80  */
81  kUsbTransferTypeInterrupt
82 } usb_testutils_transfer_type_t;
83 
84 /* Called once a packet send has completed (success or failure) */
85 typedef status_t (*usb_testutils_tx_done_handler_t)(void *,
86  usb_testutils_xfr_result_t);
87 /* Called when a packet is received */
88 typedef status_t (*usb_testutils_rx_handler_t)(void *,
91 /* Called periodically to permit flushing of buffered data */
92 typedef status_t (*usb_testutils_tx_flush_handler_t)(void *);
93 /* Called when a USB link reset is detected */
94 typedef status_t (*usb_testutils_reset_handler_t)(void *);
95 /* Called when a link event has been detected */
96 typedef status_t (*usb_testutils_link_handler_t)(
97  void *, dif_usbdev_irq_state_snapshot_t, dif_usbdev_link_state_t);
98 
99 // In-progress larger buffer transfer to/from host
100 typedef struct usb_testutils_transfer {
101  /**
102  * Start of buffer for transfer
103  */
104  const uint8_t *buffer;
105  /**
106  * Total number of bytes to be transferred to/from buffer
107  */
108  uint32_t length;
109  /**
110  * Byte offset of the _next_ packet to be transferred
111  */
112  uint32_t offset;
113  /**
114  * Flags modifying the transfer
115  */
116  usb_testutils_xfr_flags_t flags;
117  /**
118  * Indicates that the last packet of the transfer has been reached;
119  * if 'next_valid' is true, then 'next_part' holds the last packet, already
120  * prepared for sending; if next_valid is false, then the last packet has
121  * already been supplied to usbdev and we're just awaiting the 'pkt_sent'
122  * interrupt.
123  */
124  bool last;
125  /**
126  * The next part has been prepared and is ready to send to usbdev
127  */
129  /**
130  * When sending IN data to the host, we may employ double-buffering and keep
131  * an additional buffer ready to be sent as soon as we're notified of the
132  * transfer of its predecessor
133  */
136 
138 
140  dif_usbdev_t *dev;
141  dif_usbdev_buffer_pool_t *buffer_pool;
142  int flushed;
143  /**
144  * Have we received an indication of USB activity?
145  */
146  bool got_frame;
147  /**
148  * Most recent bus frame number received from host
149  */
150  uint16_t frame;
151  /**
152  * Link event callback
153  */
154  usb_testutils_link_handler_t link_callback;
155  /**
156  * Context pointer for link event callkback
157  */
158  void *ctx_link;
159 
160  /**
161  * IN endpoints
162  */
163  struct {
164  /**
165  * Endpoint Transfer Type
166  */
167  usb_testutils_transfer_type_t ep_type;
168  /**
169  * Opaque context handle for callback functions
170  */
171  void *ep_ctx;
172  /**
173  * Callback for transmission of IN packet
174  */
175  usb_testutils_tx_done_handler_t tx_done_callback;
176  /**
177  * Callback for periodically flushing IN data to host
178  */
179  usb_testutils_tx_flush_handler_t flush;
180  /**
181  * Callback for link reset
182  */
183  usb_testutils_reset_handler_t reset;
184  /**
185  * Current in-progress transfer, if any
186  */
187  usb_testutils_transfer_t transfer;
189 
190  /**
191  * OUT endpoints
192  */
193  struct {
194  /**
195  * Endpoint Transfer Type
196  */
197  usb_testutils_transfer_type_t ep_type;
198  /**
199  * Opaque context handle for callback functions
200  */
201  void *ep_ctx;
202  /**
203  * Callback for reception of IN packet
204  */
205  usb_testutils_rx_handler_t rx_callback;
206  /**
207  * Callback for link reset
208  */
209  usb_testutils_reset_handler_t reset;
211 };
212 
213 typedef enum usb_testutils_out_transfer_mode {
214  /**
215  * The endpoint does not support OUT transactions.
216  */
217  kUsbdevOutDisabled = 0,
218  /**
219  * Software does NOT need to call usb_testutils_clear_out_nak() after every
220  * received transaction. If software takes no action, usbdev will allow an
221  * endpoint's transactions to proceed as long as a buffer is available.
222  */
223  kUsbdevOutStream = 1,
224  /**
225  * Software must call usb_testutils_clear_out_nak() after every received
226  * transaction to re-enable packet reception. This gives software time to
227  * respond with the appropriate handshake when it's ready.
228  */
229  kUsbdevOutMessage = 2,
230 } usb_testutils_out_transfer_mode_t;
231 
232 /**
233  * Call to set up IN endpoint.
234  *
235  * @param ctx usb test utils context pointer
236  * @param ep endpoint number
237  * @param ep_type endpoint transfer type
238  * @param ep_ctx context pointer for callee
239  * @param tx_done callback once send has been Acked
240  * @param flush called every 16ms based USB host timebase
241  * @param reset called when an USB link reset is detected
242  * @return The result of the operation
243  */
245 status_t usb_testutils_in_endpoint_setup(
246  usb_testutils_ctx_t *ctx, uint8_t ep, usb_testutils_transfer_type_t ep_type,
247  void *ep_ctx, usb_testutils_tx_done_handler_t tx_done,
248  usb_testutils_tx_flush_handler_t flush,
249  usb_testutils_reset_handler_t reset);
250 
251 /**
252  * Call to set up OUT endpoint.
253  *
254  * @param ctx usb test utils context pointer
255  * @param ep endpoint number
256  * @param ep_type endpoint transfer type
257  * @param out_mode the transfer mode for OUT transactions
258  * @param ep_ctx context pointer for callee
259  * @param rx called when a packet is received
260  * @param reset called when an USB link reset is detected
261  * @return The result of the operation
262  */
264 status_t usb_testutils_out_endpoint_setup(
265  usb_testutils_ctx_t *ctx, uint8_t ep, usb_testutils_transfer_type_t ep_type,
266  usb_testutils_out_transfer_mode_t out_mode, void *ep_ctx,
267  usb_testutils_rx_handler_t rx, usb_testutils_reset_handler_t reset);
268 
269 /**
270  * Call to set up a pair of IN and OUT endpoints.
271  *
272  * @param ctx usb test utils context pointer
273  * @param ep endpoint number
274  * @param in_type transfer type for IN endpoint
275  * @param out_type transfer type for OUT endpoint
276  * @param out_mode the transfer mode for OUT transactions
277  * @param ep_ctx context pointer for callee
278  * @param tx_done callback once send has been Acked
279  * @param rx called when a packet is received
280  * @param flush called every 16ms based USB host timebase
281  * @param reset called when an USB link reset is detected
282  * @return The result of the operation
283  */
285 status_t usb_testutils_endpoint_setup(
286  usb_testutils_ctx_t *ctx, uint8_t ep, usb_testutils_transfer_type_t in_type,
287  usb_testutils_transfer_type_t out_type,
288  usb_testutils_out_transfer_mode_t out_mode, void *ep_ctx,
289  usb_testutils_tx_done_handler_t tx_done, usb_testutils_rx_handler_t rx,
290  usb_testutils_tx_flush_handler_t flush,
291  usb_testutils_reset_handler_t reset);
292 
293 /**
294  * Remove an IN endpoint.
295  *
296  * @param ctx usb test utils context pointer
297  * @param ep endpoint number
298  * @return The result of the operation
299  */
301 status_t usb_testutils_in_endpoint_remove(usb_testutils_ctx_t *ctx, uint8_t ep);
302 
303 /**
304  * Remove an OUT endpoint.
305  *
306  * @param ctx usb test utils context pointer
307  * @param ep endpoint number
308  * @return The result of the operation
309  */
311 status_t usb_testutils_out_endpoint_remove(usb_testutils_ctx_t *ctx,
312  uint8_t ep);
313 
314 /**
315  * Remove a pair of IN and OUT endpoints
316  *
317  * @param ctx usb test utils context pointer
318  * @param ep endpoint number
319  * @return The result of the operation
320  */
322 status_t usb_testutils_endpoint_remove(usb_testutils_ctx_t *ctx, uint8_t ep);
323 
324 /**
325  * Initialize the usbdev interface
326  *
327  * Does not connect the device, since the default endpoint is not yet enabled.
328  * See usb_testutils_connect().
329  *
330  * @param ctx uninitialized usb test utils context pointer
331  * @param pinflip boolean to indicate if PHY should be configured for D+/D- flip
332  * @param en_diff_rcvr boolean to indicate if PHY should enable an external
333  * differential receiver, activating the single-ended D
334  * input
335  * @param tx_use_d_se0 boolean to indicate if PHY uses D/SE0 for TX instead of
336  * Dp/Dn
337  * @return The result of the operation
338  */
340 status_t usb_testutils_init(usb_testutils_ctx_t *ctx, bool pinflip,
341  bool en_diff_rcvr, bool tx_use_d_se0);
342 
343 /**
344  * Register a callback function to be notified of link events
345  *
346  * @param ctx initialized usb test utils context pointer
347  * @param link link event callback handler
348  * @param ctx_link context pointer for link event callback
349  */
351 status_t usb_testutils_link_callback_register(usb_testutils_ctx_t *ctx,
352  usb_testutils_link_handler_t link,
353  void *ctx_link);
354 
355 /**
356  * Send a larger data transfer from the given endpoint
357  *
358  * The usb_testutils layer will, if necessary, break this transfer into multiple
359  * packet buffers to be transferred in turn across the USB. The caller shall be
360  * notified via the tx_done_callback handler of successful completion of the
361  * entire transfer, or failure, and the caller must guarantee the availability
362  * of the supplied data throughout the operation.
363  *
364  * @param ctx usb test utils context pointer
365  * @param ep endpoint number
366  * @param data buffer of data to be transferred
367  * @param length number of bytes to be transferred
368  * @param flags flags modifying the transfer operation
369  * @return `Ok(res)` Where `res` is true if the data has been accepted
370  * for transmission.
371  */
373 status_t usb_testutils_transfer_send(usb_testutils_ctx_t *ctx, uint8_t ep,
374  const uint8_t *data, uint32_t length,
375  usb_testutils_xfr_flags_t flags);
376 
377 /**
378  * Call regularly to poll the usbdev interface
379  *
380  * @param ctx usb test utils context pointer
381  * @return The result of the operation
382  */
384 status_t usb_testutils_poll(usb_testutils_ctx_t *ctx);
385 
386 /**
387  * Finalize the usbdev interface
388  *
389  * Removes all endpoint handlers and disconnects the device from the USB.
390  * This should be used only if the USB device is no longer required, or if it is
391  * required to be restarted with, for example, a different bus configuration.
392  *
393  * @param ctx initialized usb test utils context pointer
394  * @return The result of the operation
395  */
397 status_t usb_testutils_fin(usb_testutils_ctx_t *ctx);
398 
399 #endif // OPENTITAN_SW_DEVICE_LIB_TESTING_USB_TESTUTILS_H_