1 /*
2  * SPDX-FileCopyrightText: 2016 Intel Corporation
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 /**
8  * @file
9  * @brief USB device controller APIs
10  *
11  * This file contains the USB device controller APIs. All device controller
12  * drivers should implement the APIs described in this file.
13  */
14 
15 #pragma once
16 
17 #include <stdint.h>
18 
19 #ifdef __cplusplus
20 extern "C" {
21 #endif
22 
23 /**
24  * USB endpoint direction and number.
25  */
26 
27 #define USB_EP_DIR_MASK 0x80
28 #define USB_EP_DIR_IN   0x80
29 #define USB_EP_DIR_OUT  0x00
30 
31 /**
32  * USB Driver Status Codes
33  */
34 enum usb_dc_status_code {
35     USB_DC_ERROR,        /* USB error reported by the controller */
36     USB_DC_RESET,        /* USB reset */
37     /* USB connection established, hardware enumeration is completed */
38     USB_DC_CONNECTED,
39     USB_DC_CONFIGURED,   /* USB configuration done */
40     USB_DC_DISCONNECTED, /* USB connection lost */
41     USB_DC_SUSPEND,      /* USB connection suspended by the HOST */
42     USB_DC_RESUME,       /* USB connection resumed by the HOST */
43     USB_DC_INTERFACE,    /* USB interface selected */
44     USB_DC_SET_HALT,     /* Set Feature ENDPOINT_HALT received */
45     USB_DC_CLEAR_HALT,   /* Clear Feature ENDPOINT_HALT received */
46     USB_DC_UNKNOWN       /* Initial USB connection status */
47 };
48 
49 /**
50  * USB Endpoint Callback Status Codes
51  */
52 enum usb_dc_ep_cb_status_code {
53     USB_DC_EP_SETUP,    /* SETUP received */
54     /* Out transaction on this EP, data is available for read */
55     USB_DC_EP_DATA_OUT,
56     USB_DC_EP_DATA_IN,  /* In transaction done on this EP */
57 };
58 
59 /**
60  * USB Endpoint type
61  */
62 enum usb_dc_ep_type {
63     USB_DC_EP_CONTROL = 0,  /* Control type endpoint */
64     USB_DC_EP_ISOCHRONOUS,  /* Isochronous type endpoint */
65     USB_DC_EP_BULK,         /* Bulk type endpoint */
66     USB_DC_EP_INTERRUPT     /* Interrupt type endpoint  */
67 };
68 
69 /**
70  * USB Endpoint Configuration.
71  */
72 struct usb_dc_ep_cfg_data {
73     /** The number associated with the EP in the device
74      *  configuration structure
75      *       IN  EP = 0x80 | \<endpoint number\>
76      *       OUT EP = 0x00 | \<endpoint number\>
77      */
78     uint8_t ep_addr;
79     uint16_t ep_mps;             /** Endpoint max packet size */
80     enum usb_dc_ep_type ep_type; /** Endpoint type */
81 };
82 
83 /**
84  * Callback function signature for the USB Endpoint status
85  */
86 typedef void (*usb_dc_ep_callback)(uint8_t ep,
87                                    enum usb_dc_ep_cb_status_code cb_status);
88 
89 /**
90  * Callback function signature for the device
91  */
92 typedef void (*usb_dc_status_callback)(enum usb_dc_status_code cb_status,
93                                        uint8_t *param);
94 
95 /**
96  * @brief attach USB for device connection
97  *
98  * Function to attach USB for device connection. Upon success, the USB PLL
99  * is enabled, and the USB device is now capable of transmitting and receiving
100  * on the USB bus and of generating interrupts.
101  *
102  * @return 0 on success, negative errno code on fail.
103  */
104 int usb_dc_attach(void);
105 
106 /**
107  * @brief detach the USB device
108  *
109  * Function to detach the USB device. Upon success, the USB hardware PLL
110  * is powered down and USB communication is disabled.
111  *
112  * @return 0 on success, negative errno code on fail.
113  */
114 int usb_dc_detach(void);
115 
116 /**
117  * @brief reset the USB device
118  *
119  * This function returns the USB device and firmware back to it's initial state.
120  * N.B. the USB PLL is handled by the usb_detach function
121  *
122  * @return 0 on success, negative errno code on fail.
123  */
124 int usb_dc_reset(void);
125 
126 /**
127  * @brief set USB device address
128  *
129  * @param[in] addr device address
130  *
131  * @return 0 on success, negative errno code on fail.
132  */
133 int usb_dc_set_address(const uint8_t addr);
134 
135 /**
136  * @brief set USB device controller status callback
137  *
138  * Function to set USB device controller status callback. The registered
139  * callback is used to report changes in the status of the device controller.
140  *
141  * @param[in] cb callback function
142  *
143  * @return 0 on success, negative errno code on fail.
144  */
145 int usb_dc_set_status_callback(const usb_dc_status_callback cb);
146 
147 /**
148  * @brief check endpoint capabilities
149  *
150  * Function to check capabilities of an endpoint. usb_dc_ep_cfg_data structure
151  * provides the endpoint configuration parameters: endpoint address,
152  * endpoint maximum packet size and endpoint type.
153  * The driver should check endpoint capabilities and return 0 if the
154  * endpoint configuration is possible.
155  *
156  * @param[in] cfg Endpoint config
157  *
158  * @return 0 on success, negative errno code on fail.
159  */
160 int usb_dc_ep_check_cap(const struct usb_dc_ep_cfg_data *const cfg);
161 
162 /**
163  * @brief configure endpoint
164  *
165  * Function to configure an endpoint. usb_dc_ep_cfg_data structure provides
166  * the endpoint configuration parameters: endpoint address, endpoint maximum
167  * packet size and endpoint type.
168  *
169  * @param[in] cfg Endpoint config
170  *
171  * @return 0 on success, negative errno code on fail.
172  */
173 int usb_dc_ep_configure(const struct usb_dc_ep_cfg_data *const cfg);
174 
175 /**
176  * @brief set stall condition for the selected endpoint
177  *
178  * @param[in] ep Endpoint address corresponding to the one
179  *               listed in the device configuration table
180  *
181  * @return 0 on success, negative errno code on fail.
182  */
183 int usb_dc_ep_set_stall(const uint8_t ep);
184 
185 /**
186  * @brief clear stall condition for the selected endpoint
187  *
188  * @param[in] ep Endpoint address corresponding to the one
189  *               listed in the device configuration table
190  *
191  * @return 0 on success, negative errno code on fail.
192  */
193 int usb_dc_ep_clear_stall(const uint8_t ep);
194 
195 /**
196  * @brief check if selected endpoint is stalled
197  *
198  * @param[in]  ep       Endpoint address corresponding to the one
199  *                      listed in the device configuration table
200  * @param[out] stalled  Endpoint stall status
201  *
202  * @return 0 on success, negative errno code on fail.
203  */
204 int usb_dc_ep_is_stalled(const uint8_t ep, uint8_t *const stalled);
205 
206 /**
207  * @brief halt the selected endpoint
208  *
209  * @param[in] ep Endpoint address corresponding to the one
210  *               listed in the device configuration table
211  *
212  * @return 0 on success, negative errno code on fail.
213  */
214 int usb_dc_ep_halt(const uint8_t ep);
215 
216 /**
217  * @brief enable the selected endpoint
218  *
219  * Function to enable the selected endpoint. Upon success interrupts are
220  * enabled for the corresponding endpoint and the endpoint is ready for
221  * transmitting/receiving data.
222  *
223  * @param[in] ep Endpoint address corresponding to the one
224  *               listed in the device configuration table
225  *
226  * @return 0 on success, negative errno code on fail.
227  */
228 int usb_dc_ep_enable(const uint8_t ep);
229 
230 /**
231  * @brief disable the selected endpoint
232  *
233  * Function to disable the selected endpoint. Upon success interrupts are
234  * disabled for the corresponding endpoint and the endpoint is no longer able
235  * for transmitting/receiving data.
236  *
237  * @param[in] ep Endpoint address corresponding to the one
238  *               listed in the device configuration table
239  *
240  * @return 0 on success, negative errno code on fail.
241  */
242 int usb_dc_ep_disable(const uint8_t ep);
243 
244 /**
245  * @brief flush the selected endpoint
246  *
247  * @param[in] ep Endpoint address corresponding to the one
248  *               listed in the device configuration table
249  *
250  * @return 0 on success, negative errno code on fail.
251  */
252 int usb_dc_ep_flush(const uint8_t ep);
253 
254 /**
255  * @brief write data to the specified endpoint
256  *
257  * This function is called to write data to the specified endpoint. The supplied
258  * usb_ep_callback function will be called when data is transmitted out.
259  *
260  * @param[in]  ep        Endpoint address corresponding to the one
261  *                       listed in the device configuration table
262  * @param[in]  data      pointer to data to write
263  * @param[in]  data_len  length of data requested to write. This may
264  *                       be zero for a zero length status packet.
265  * @param[out] ret_bytes bytes scheduled for transmission. This value
266  *                       may be NULL if the application expects all
267  *                       bytes to be written
268  *
269  * @return 0 on success, negative errno code on fail.
270  */
271 int usb_dc_ep_write(const uint8_t ep, const uint8_t *const data,
272                     const uint32_t data_len, uint32_t *const ret_bytes);
273 
274 
275 
276 /**
277  * @brief Indicate if the write to an IN endpoint (using usb_dc_ep_write) would block
278  * to wait until the endpoint has enoug space
279  *
280  * @param[in]  ep        Endpoint address corresponding to the one
281  *                       listed in the device configuration table
282  *
283  * @return 0 when writable, 0 when not, negative errno code on fail.
284  */
285 int usb_dc_ep_write_would_block(const uint8_t ep);
286 
287 
288 /**
289  * @brief read data from the specified endpoint
290  *
291  * This function is called by the Endpoint handler function, after an OUT
292  * interrupt has been received for that EP. The application must only call this
293  * function through the supplied usb_ep_callback function. This function clears
294  * the ENDPOINT NAK, if all data in the endpoint FIFO has been read,
295  * so as to accept more data from host.
296  *
297  * @param[in]  ep           Endpoint address corresponding to the one
298  *                          listed in the device configuration table
299  * @param[in]  data         pointer to data buffer to write to
300  * @param[in]  max_data_len max length of data to read
301  * @param[out] read_bytes   Number of bytes read. If data is NULL and
302  *                          max_data_len is 0 the number of bytes
303  *                          available for read should be returned.
304  *
305  * @return 0 on success, negative errno code on fail.
306  */
307 int usb_dc_ep_read(const uint8_t ep, uint8_t *const data,
308                    const uint32_t max_data_len, uint32_t *const read_bytes);
309 
310 /**
311  * @brief set callback function for the specified endpoint
312  *
313  * Function to set callback function for notification of data received and
314  * available to application or transmit done on the selected endpoint,
315  * NULL if callback not required by application code.
316  *
317  * @param[in] ep Endpoint address corresponding to the one
318  *               listed in the device configuration table
319  * @param[in] cb callback function
320  *
321  * @return 0 on success, negative errno code on fail.
322  */
323 int usb_dc_ep_set_callback(const uint8_t ep, const usb_dc_ep_callback cb);
324 
325 /**
326  * @brief read data from the specified endpoint
327  *
328  * This is similar to usb_dc_ep_read, the difference being that, it doesn't
329  * clear the endpoint NAKs so that the consumer is not bogged down by further
330  * upcalls till he is done with the processing of the data. The caller should
331  * reactivate ep by invoking usb_dc_ep_read_continue() do so.
332  *
333  * @param[in]  ep           Endpoint address corresponding to the one
334  *                          listed in the device configuration table
335  * @param[in]  data         pointer to data buffer to write to
336  * @param[in]  max_data_len max length of data to read
337  * @param[out] read_bytes   Number of bytes read. If data is NULL and
338  *                          max_data_len is 0 the number of bytes
339  *                          available for read should be returned.
340  *
341  * @return 0 on success, negative errno code on fail.
342  */
343 int usb_dc_ep_read_wait(uint8_t ep, uint8_t *data, uint32_t max_data_len,
344                         uint32_t *read_bytes);
345 
346 
347 /**
348  * @brief Continue reading data from the endpoint
349  *
350  * Clear the endpoint NAK and enable the endpoint to accept more data
351  * from the host. Usually called after usb_dc_ep_read_wait() when the consumer
352  * is fine to accept more data. Thus these calls together acts as flow control
353  * mechanism.
354  *
355  * @param[in]  ep           Endpoint address corresponding to the one
356  *                          listed in the device configuration table
357  *
358  * @return 0 on success, negative errno code on fail.
359  */
360 int usb_dc_ep_read_continue(uint8_t ep);
361 
362 /**
363  * @brief Get endpoint max packet size
364  *
365  * @param[in]  ep           Endpoint address corresponding to the one
366  *                          listed in the device configuration table
367  *
368  * @return enpoint max packet size (mps)
369  */
370 int usb_dc_ep_mps(uint8_t ep);
371 
372 
373 /**
374  * @brief Poll for interrupts that need to be handled
375  *
376  * When the USB interrupt is not hooked up to an actual CPU interrupt, you
377  * can call this periodically to handle the USB events that need handling.
378  */
379 void usb_dc_check_poll_for_interrupts(void);
380 
381 
382 /*
383  * @brief Prepare for USB persist
384  *
385  * This takes the USB peripheral offline in such a way that it seems 'just busy' to the
386  * host. This way, the chip can reboot (e.g. into bootloader mode) and pick up the USB
387  * configuration again, without the conenction to the host being interrupted.
388  *
389  * @note Actual persistence is depending on USBDC_PERSIST_ENA being set in flags, as this
390  * is also used to e.g. reboot into DFU mode.
391  *
392  * @note Please reboot soon after calling this.
393  */
394 int usb_dc_prepare_persist(void);
395 
396 /*
397  * @brief USB interrupt handler
398  *
399  * This can be hooked up by the OS to the USB peripheral interrupt.
400  */
401 void usb_dw_isr_handler(void);
402 
403 /**
404  * @brief Provide IDF with an interface to clear the static variable usb_dw_ctrl
405  *
406  *
407  */
408 void usb_dw_ctrl_deinit(void);
409 
410 
411 #ifdef __cplusplus
412 }
413 #endif
414