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