1 /******************************************************************************
2  *
3  * Copyright (C) 2022-2023 Maxim Integrated Products, Inc. (now owned by
4  * Analog Devices, Inc.),
5  * Copyright (C) 2023-2024 Analog Devices, Inc.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *     http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  ******************************************************************************/
20 
21 #ifndef LIBRARIES_MAXUSB_INCLUDE_CORE_USB_H_
22 #define LIBRARIES_MAXUSB_INCLUDE_CORE_USB_H_
23 
24 #include <stdbool.h>
25 #include "usb_hwopt.h"
26 #include "usb_protocol.h"
27 
28 #ifdef __cplusplus
29 extern "C" {
30 #endif
31 
32 /**
33  * @file usb.h
34  * @brief Defines the API used to abstract USB hardware away from upper layers.
35  *
36  */
37 
38 /******************************** Definitions *********************************/
39 
40 /*
41  * Current status, as bit field, of physical layer. Note that some bits may
42  * not be available on hardware which lacks detection of that specific condition.
43  *
44  */
45 #define MAXUSB_STATUS_VBUS_ON    0x1
46 #define MAXUSB_STATUS_HIGH_SPEED 0x2
47 
48 /*
49  * Endpoint types, additional types may be supported in the future.
50  *
51  * On non-configurable hardware, an error will be returned if the type selected
52  * disagrees with hardware capability on that endpoint (ie. can't make an IN
53  * into an OUT).
54  *
55  */
56 typedef enum {
57   MAXUSB_EP_TYPE_DISABLED = 0,
58   MAXUSB_EP_TYPE_OUT      = 1,
59   MAXUSB_EP_TYPE_IN       = 2,
60   MAXUSB_EP_TYPE_CONTROL  = 3
61 } maxusb_ep_type_t;
62 
63 /*
64  * USB events. Register for callbacks with usb_register_callback().
65  */
66 typedef enum {
67   MAXUSB_EVENT_DPACT = 0, /* D+ Activity */
68   MAXUSB_EVENT_RWUDN,     /* Remote Wake-Up Signaling Done */
69   MAXUSB_EVENT_BACT,      /* Bus Active */
70   MAXUSB_EVENT_BRST,      /* Bus Reset */
71   MAXUSB_EVENT_SUSP,      /* Suspend */
72   MAXUSB_EVENT_NOVBUS,    /* No VBUS - VBUSDET signal makes 0 -> 1 transition i.e. VBUS not present */
73   MAXUSB_EVENT_VBUS,      /* VBUS present */
74   MAXUSB_EVENT_BRSTDN,    /* Bus Reset Done */
75   MAXUSB_EVENT_SUDAV,     /* Setup Data Available */
76   MAXUSB_NUM_EVENTS
77 } maxusb_event_t;
78 
79 /*
80  * USB events flags.
81  */
82 typedef struct {
83   /* Non-endpoint events */
84   unsigned int dpact  : 1;
85   unsigned int rwudn  : 1;
86   unsigned int bact   : 1;
87   unsigned int brst   : 1;
88   unsigned int susp   : 1;
89   unsigned int novbus : 1;
90   unsigned int vbus   : 1;
91   unsigned int brstdn : 1;
92   unsigned int sudav  : 1;
93 } maxusb_usbio_events_t;
94 
95 /*
96  * USB Request Type
97  */
98 typedef enum {
99   MAXUSB_TYPE_TRANS = 0,
100   /* The request will complete once the requested amount
101    * of data has been received, or when a packet is
102    * received containing less than max packet.
103    */
104   MAXUSB_TYPE_PKT
105   /* The request will complete each time a packet is
106    * received. The caller is responsible for zero-packet
107    * handling
108    */
109 } maxusb_req_type_t;
110 
111 /*
112  * Object for requesting an endpoint read or write. The object is updated with
113  * the transaction status and can be observed when the callback is called.
114  */
115 typedef struct {
116   unsigned int ep;
117   uint8_t *data;
118   unsigned int reqlen; // requested / max length
119   unsigned int actlen; // actual length transacted
120   int error_code;
121   void (*callback)(void *);
122   void *cbdata;
123   maxusb_req_type_t type;
124   void *driver_xtra; /* driver-specific data, do not modify */
125 } MXC_USB_Req_t;
126 
127 
128 /**************************** Function Prototypes *****************************/
129 
130 /**
131  * @brief Initialize the USB hardware to a non-connected, "ready" state
132  *
133  * @param options    Hardware-specific options which are in each chip's MXC_USB_hwopt.h
134  * @return This function returns zero (0) for success, non-zero for failure
135  *
136  */
137 int MXC_USB_Init(maxusb_cfg_options_t *options);
138 
139 #ifdef MAX32690
140 // Clock setter mux APIs are currently only supported on the MAX32690.  It does not exist
141 // on earlier hardware revisions such as the MAX32650
142 
143 #ifndef mxc_usb_clock_t
144 #warning "mxc_usb_clock_t" not implemented.  See note in usb.h on "MXC_USB_SetClockSource"
145 typedef enum {
146   MXC_USB_CLOCK_0 = 0,
147   MXC_USB_CLOCK_1 = 1,
148   MXC_USB_CLOCK_2 = 2
149 } mxc_usb_clock_t;
150 #endif
151 
152 /**
153  * @brief Set the input clock source to the USB peripheral.
154  *
155  * @param   clock_source Input clock source
156  * @note    (Developers): "mxc_usb_clock_t" should be defined as a macro in the top-level "max32xxx.h" file
157  *          so that the pre-processor can check for its existence.  Ex:
158  *
159  *          #define mxc_usb_clock_t _mxc_usb_clock_t
160  *
161  *          where "_mxc_usb_clock_t" is the actual "typedef enum".
162  *          See "max32690.h" for reference.
163  *
164  * @return This function returns zero (0) for success, non-zero for failure
165  *
166  */
167 int MXC_USB_SetClockSource(mxc_usb_clock_t clock_source);
168 
169 /**
170  * @brief   Lock the input clock source to the USB peripheral.
171  *
172  * @param   lock Whether to lock the clock source.  Set to true to lock, false to unlock.
173  *
174  * @return This function returns zero (0) for success, non-zero for failure
175  *
176  */
177 int MXC_USB_LockClockSource(bool lock);
178 
179 #endif
180 
181 /**
182  * @brief Shut down the USB peripheral block
183  *
184  *  This function will shut down the USB IP. Once called, you must call
185  *  MXC_USB_init() to bring the block back into a working condition. No
186  *  state persists after this call, including endpoint configuration,
187  *  pending reads/writes, etc. All pending and outstanding events will be
188  *  quashed at the driver layer.
189  *
190  * @return This function returns zero (0) for success, non-zero for failure
191  *
192  */
193 int MXC_USB_Shutdown(void);
194 
195 /**
196  * @brief Connect to the USB bus
197  * @return This function returns zero (0) for success, non-zero for failure
198  *
199  */
200 int MXC_USB_Connect(void);
201 
202 /**
203  * @brief Disconnect from the USB bus
204  * @return This function returns zero (0) for success, non-zero for failure
205  *
206  */
207 int MXC_USB_Disconnect(void);
208 
209 /**
210  * @brief Get current USB status (VBUS, High Speed, etc.)
211  * @return This function returns a bit field of MAXUSB_STATUS_xxx
212  *
213  */
214 unsigned int MXC_USB_GetStatus(void);
215 
216 /**
217  * @brief Endpoint configuration function
218  *
219  * Endpoints can be Disabled, CONTROL, BULK/INTERRUPT IN, or BULK/INTERRUPT OUT.
220  *  No hardware support for ISOCHRONOUS exists currently, but may appear in the future.
221  *
222  * An endpoint has a configured size, which should match that advertised to the host in
223  * the Device Descriptor.
224  *
225  * @param ep    endpoint number
226  * @param type  endpoint type
227  * @param size  endpoint size
228  * @return This function returns zero (0) for success, non-zero for failure
229  *
230  */
231 int MXC_USB_ConfigEp(unsigned int ep, maxusb_ep_type_t type, unsigned int size);
232 
233 /**
234  * @brief Query the configuration status of the selected endpoint
235  * @param ep   endpoint number
236  * @return This function returns 1 if the endpoint is configured, 0 if it is not, and < 0 for error
237  *
238  */
239 int MXC_USB_IsConfigured(unsigned int ep);
240 
241 /**
242  * @brief Stall the selected endpoint
243  *
244  * If the endpoint is the CONTROL endpoint, then both the IN and OUT pipes are stalled.
245  * In this case, the hardware will also stall the Status stage of the transfer.
246  *
247  * @param ep   endpoint number
248  * @return This function returns zero (0) for success, non-zero for failure
249  *
250  */
251 int MXC_USB_Stall(unsigned int ep);
252 
253 /**
254  * @brief Unstall the selected endpoint
255  *
256  * If this endpoint is the CONTROL endpoint, the IN, OUT, and Status stage stall bits are cleared.
257  * This is not normally needed, as hardware should clear these bits upon reception of the
258  * next SETUP packet.
259  *
260  * @param ep   endpoint number
261  * @return This function returns zero (0) for success, non-zero for failure
262  *
263  */
264 int MXC_USB_Unstall(unsigned int ep);
265 
266 /**
267  * @brief Query the stalled/unstalled status of the selected endpoint
268  * @param ep   endpoint number
269  * @return This function returns 0 if the endpoint is not stalled, 1 if it is, and < 0 for error
270  *
271  */
272 int MXC_USB_IsStalled(unsigned int ep);
273 
274 /**
275  * @brief Reset state and clear the data toggle on the selected endpoint
276  * @param ep   endpoint number
277  * @return This function returns zero (0) for success, non-zero for failure
278  *
279  */
280 int MXC_USB_ResetEp(unsigned int ep);
281 
282 /**
283  * @brief Arm the hardware to ACK the Status stage of a SETUP transfer. Only valid for CONTROL endpoints.
284  * @param ep   endpoint number
285  * @return This function returns zero (0) for success, non-zero for failure
286  *
287  */
288 int MXC_USB_Ackstat(unsigned int ep);
289 
290 /**
291  * @brief Enable the specified event interrupt in hardware
292  * This function is called by the event layer through MXC_USB_event_enable() and
293  * should not be called directly from the application.
294  * @param event   event number
295  * @return This function returns zero (0) for success, non-zero for failure
296  *
297  */
298 int MXC_USB_IrqEnable(maxusb_event_t event);
299 
300 /**
301  * @brief Enable the specified event interrupt in hardware
302  * This function is called by the event layer through MXC_USB_EventDisable() and
303  * should not be called directly from the application.
304  * @param event   event number
305  * @return This function returns zero (0) for success, non-zero for failure
306  *
307  */
308 int MXC_USB_IrqDisable(maxusb_event_t event);
309 
310 /**
311  * @brief Clear the specified interrupt flag in hardware
312  * This function is called by the event layer through MXC_USB_EventClear() and
313  * should not be called directly from the application.
314  * @param event   event number
315  * @return This function returns zero (0) for success, non-zero for failure
316  *
317  */
318 int MXC_USB_IrqClear(maxusb_event_t event);
319 
320 /**
321  * @brief Interrupt handler.
322  * This function is called by the event layer through MXC_USB_EventHandler() and
323  * should not be called directly from the application.
324  * This function will read the interrupt flags, handle any outstanding
325  * I/O in a chip-specific way (DMA, Programmed I/O, Bus Master, etc.)
326  * The event structure is returned to the upper layer so that it may react to
327  * bus conditions.
328  * @param evt   structure of event flags
329  */
330 void MXC_USB_IrqHandler(maxusb_usbio_events_t *events);
331 
332 /**
333  * @brief Read the SETUP data from hardware
334  * @param setup_pkt   Pointer to setup data structure
335  * @return This function returns zero (0) for success, non-zero for failure
336  *
337  */
338 int MXC_USB_GetSetup(MXC_USB_SetupPkt *setup_pkt);
339 
340 /**
341  * @brief Change the function address, in response to a Host request
342  * @param addr The 7-bit address in the SET_ADDRESS request
343  * @return This function returns zero (0) for success, non-zero for failure
344  * @note Some hardware does this automatically; In that case, this function will always return 0.
345  *
346  */
347 int MXC_USB_SetFuncAddr(unsigned int addr);
348 
349 /**
350  * @brief Returns a pointer to the request queued for the specified endpoint
351  * @param ep Endpoint which to query
352  * @return Pointer to request structure, or NULL if none queued
353  *
354  */
355 MXC_USB_Req_t *MXC_USB_GetRequest(unsigned int ep);
356 
357 /**
358  * @brief Remove a queued endpoint request
359  * @param req Pointer to usb request (if not known, use MXC_USB_GetRequest(ep))
360  * @return Zero if successful, non-zero otherwise
361  * @note Callback function on request, if any, will be called with a -1 error result
362  *
363  */
364 int MXC_USB_RemoveRequest(MXC_USB_Req_t *req);
365 
366 /**
367  * @brief Send data to the host via the selected endpoint
368  *
369  * This asynchronous function allows the caller to specify a buffer for outgoing data.
370  * The buffer may have any length, and device-specific code will handle breaking the data
371  * into endpoint-sized chunks.  The request object and data buffer passed to this function must
372  * remain "owned" by the USB stack until the callback function is called indicating completion.
373  * It will handle a zero-length length, as that is a valid message on the USB to indicate
374  * success during various phases of data transfer.
375  *
376  * Once called, the next IN transaction processed by hardware on the selected endpoint
377  * will cause the IN DATAx payload to be sent from the provided buffer. The driver will
378  * keep track of how many bytes have been sent and continue sending additional chunks of
379  * data until all data has been sent to the host. The driver will send a zero-length packet
380  * if the data to be sent is a whole multiple (no remainder after division) of the endpoint size.
381  *
382  * Upon completion of the request, the request object's error_code and actlen fields are
383  * updated to reflect the result of the transaction and the function specified in the request
384  * object is be called.
385  *
386  * Only one outstanding buffer is allowed to exist in the current implementation. This function
387  * will return an error to the caller if it finds that there is an outstanding buffer already
388  * configured. This will not affect the outstanding buffer.
389  *
390  * A special case exists for this call: If the data pointer is NULL, then any existing
391  * outstanding buffer is removed from the driver. This allows for a "disarming" mechanism
392  * without shutting down the entire stack and re-starting.
393  *
394  * @param req   Initialized request object
395  *
396  * @return This function returns zero (0) for success, non-zero for failure
397  *
398  */
399 int MXC_USB_WriteEndpoint(MXC_USB_Req_t *req);
400 
401 /**
402  * @brief Arm the selected endpoint to receive data from the host
403  *
404  * This asynchronous function allows the caller to specify a buffer for incoming data.
405  * The driver will read from the endpoint at most len bytes into the provided buffer.
406  *
407  * Once called, the next OUT transaction processed by hardware on the selected endpoint
408  * will cause the OUT DATAx payload to be loaded into the provided buffer. Additional OUT
409  * DATAx payloads will be concatenated to the buffer until 1) len bytes have been read, or
410  * 2) a DATAx payload of length less than the maximum endpoint size has been read. The
411  * latter case signifies the end of a USB transaction. If case #1 is reached before the end
412  * of the USB transfer, any additional data is thrown away by the driver layer.
413  *
414  * Upon completion of the request, the request object's error_code and actlen fields are
415  * updated to reflect the result of the transaction and the function specified in the request
416  * object is be called.
417  *
418  * Only one outstanding buffer is allowed to exist in the current implementation. This function
419  * will return an error to the caller if it finds that there is an outstanding buffer already
420  * configured. This will not affect the outstanding buffer.
421  *
422  * A special case exists for this call: If the data pointer is NULL, then any existing
423  * outstanding buffer is removed from the driver. This allows for a "disarming" mechanism
424  * without shutting down the entire stack and re-starting.
425  *
426  * @param req   Initialized request object
427  *
428  * @return This function returns zero (0) for success, non-zero for failure
429  *
430  */
431 int MXC_USB_ReadEndpoint(MXC_USB_Req_t *req);
432 
433 /**
434  * @brief Instruct hardware to transmit test mode pattern (USB 2.0 High Speed only)
435  * @detail See Universal Serial Bus Specification Revision 2.0 Section 7.1.20 for details
436  * @param value Test mode selector
437  * @return -1 if selected test mode is not supported, 0 otherwise
438  *
439  */
440 int MXC_USB_TestMode(unsigned int value);
441 
442 #ifdef __cplusplus
443 }
444 #endif
445 
446 #endif //LIBRARIES_MAXUSB_INCLUDE_CORE_USB_H_
447