Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 | /* SPDX-License-Identifier: BSD-3-Clause */ /* * LPCUSB, an USB device driver for LPC microcontrollers * Copyright (C) 2006 Bertrik Sikken (bertrik@sikken.nl) * Copyright (c) 2016 Intel Corporation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /** * @file * @brief USB device core layer APIs and structures * * This file contains the USB device core layer APIs and structures. */ #ifndef ZEPHYR_INCLUDE_USB_USB_DEVICE_H_ #define ZEPHYR_INCLUDE_USB_USB_DEVICE_H_ #include <drivers/usb/usb_dc.h> #include <usb/usbstruct.h> #include <logging/log.h> #ifdef __cplusplus extern "C" { #endif /* * These macros should be used to place the USB descriptors * in predetermined order in the RAM. */ #define USBD_DEVICE_DESCR_DEFINE(p) \ static __in_section(usb, descriptor_##p, 0) __used __aligned(1) #define USBD_CLASS_DESCR_DEFINE(p, instance) \ static __in_section(usb, descriptor_##p.1, instance) __used __aligned(1) #define USBD_MISC_DESCR_DEFINE(p) \ static __in_section(usb, descriptor_##p, 2) __used __aligned(1) #define USBD_USER_DESCR_DEFINE(p) \ static __in_section(usb, descriptor_##p, 3) __used __aligned(1) #define USBD_STRING_DESCR_DEFINE(p) \ static __in_section(usb, descriptor_##p, 4) __used __aligned(1) #define USBD_TERM_DESCR_DEFINE(p) \ static __in_section(usb, descriptor_##p, 5) __used __aligned(1) /* * This macro should be used to place the struct usb_cfg_data * inside usb data section in the RAM. */ #define USBD_CFG_DATA_DEFINE(p, name) \ static __in_section(usb, data_##p, name) __used /************************************************************************* * USB configuration **************************************************************************/ #define USB_MAX_CTRL_MPS 64 /**< maximum packet size (MPS) for EP 0 */ #define USB_MAX_FS_BULK_MPS 64 /**< full speed MPS for bulk EP */ #define USB_MAX_FS_INT_MPS 64 /**< full speed MPS for interrupt EP */ #define USB_MAX_FS_ISO_MPS 1023 /**< full speed MPS for isochronous EP */ /************************************************************************* * USB application interface **************************************************************************/ /** setup packet definitions */ struct usb_setup_packet { uint8_t bmRequestType; /**< characteristics of the specific request */ uint8_t bRequest; /**< specific request */ uint16_t wValue; /**< request specific parameter */ uint16_t wIndex; /**< request specific parameter */ uint16_t wLength; /**< length of data transferred in data phase */ }; /** * @brief USB Device Core Layer API * @defgroup _usb_device_core_api USB Device Core API * @{ */ /** * @brief Callback function signature for the USB Endpoint status */ typedef void (*usb_ep_callback)(uint8_t ep, enum usb_dc_ep_cb_status_code cb_status); /** * @brief Callback function signature for class specific requests * * Function which handles Class specific requests corresponding to an * interface number specified in the device descriptor table. For host * to device direction the 'len' and 'payload_data' contain the length * of the received data and the pointer to the received data respectively. * For device to host class requests, 'len' and 'payload_data' should be * set by the callback function with the length and the address of the * data to be transmitted buffer respectively. */ typedef int (*usb_request_handler)(struct usb_setup_packet *setup, int32_t *transfer_len, uint8_t **payload_data); /** * @brief Function for interface runtime configuration */ typedef void (*usb_interface_config)(struct usb_desc_header *head, uint8_t bInterfaceNumber); /** * @brief USB Endpoint Configuration * * This structure contains configuration for the endpoint. */ struct usb_ep_cfg_data { /** * Callback function for notification of data received and * available to application or transmit done, NULL if callback * not required by application code */ usb_ep_callback ep_cb; /** * The number associated with the EP in the device configuration * structure * IN EP = 0x80 | \<endpoint number\> * OUT EP = 0x00 | \<endpoint number\> */ uint8_t ep_addr; }; /** * @brief USB Interface Configuration * * This structure contains USB interface configuration. */ struct usb_interface_cfg_data { /** Handler for USB Class specific Control (EP 0) communications */ usb_request_handler class_handler; /** Handler for USB Vendor specific commands */ usb_request_handler vendor_handler; /** * The custom request handler gets a first chance at handling * the request before it is handed over to the 'chapter 9' request * handler. * return 0 on success, -EINVAL if the request has not been handled by * the custom handler and instead needs to be handled by the * core USB stack. Any other error code to denote failure within * the custom handler. */ usb_request_handler custom_handler; }; /** * @brief USB device configuration * * The Application instantiates this with given parameters added * using the "usb_set_config" function. Once this function is called * changes to this structure will result in undefined behavior. This structure * may only be updated after calls to usb_deconfig */ struct usb_cfg_data { /** * USB device description, see * http://www.beyondlogic.org/usbnutshell/usb5.shtml#DeviceDescriptors */ const uint8_t *usb_device_description; /** Pointer to interface descriptor */ void *interface_descriptor; /** Function for interface runtime configuration */ usb_interface_config interface_config; /** Callback to be notified on USB connection status change */ void (*cb_usb_status)(struct usb_cfg_data *cfg, enum usb_dc_status_code cb_status, const uint8_t *param); /** USB interface (Class) handler and storage space */ struct usb_interface_cfg_data interface; /** Number of individual endpoints in the device configuration */ uint8_t num_endpoints; /** * Pointer to an array of endpoint structs of length equal to the * number of EP associated with the device description, * not including control endpoints */ struct usb_ep_cfg_data *endpoint; }; /** * @brief Configure USB controller * * Function to configure USB controller. * Configuration parameters must be valid or an error is returned * * @param[in] usb_descriptor USB descriptor table * * @return 0 on success, negative errno code on fail */ int usb_set_config(const uint8_t *usb_descriptor); /** * @brief Deconfigure USB controller * * This function returns the USB device to it's initial state * * @return 0 on success, negative errno code on fail */ int usb_deconfig(void); /** * @brief Enable the USB subsystem and associated hardware * * This function initializes the USB core subsystem and enables the * corresponding hardware so that it can begin transmitting and receiving * on the USB bus, as well as generating interrupts. * * Class-specific initialization and registration must be performed by the user * before invoking this, so that any data or events on the bus are processed * correctly by the associated class handling code. * * @param[in] status_cb Callback registered by user to notify * about USB device controller state. * * @return 0 on success, negative errno code on fail. */ int usb_enable(usb_dc_status_callback status_cb); /** * @brief Disable the USB device * * Function to disable the USB device. * Upon success, the specified USB interface is clock gated in hardware, * it is no longer capable of generating interrupts. * * @return 0 on success, negative errno code on fail */ int usb_disable(void); /** * @brief Write data to the specified endpoint * * Function to write data to the specified endpoint. The supplied * usb_ep_callback will be called when transmission is done. * * @param[in] ep Endpoint address corresponding to the one listed in the * device configuration table * @param[in] data Pointer to data to write * @param[in] data_len Length of data requested to write. This may be zero for * a zero length status packet. * @param[out] bytes_ret Bytes written to the EP FIFO. This value may be NULL if * the application expects all bytes to be written * * @return 0 on success, negative errno code on fail */ int usb_write(uint8_t ep, const uint8_t *data, uint32_t data_len, uint32_t *bytes_ret); /** * @brief Read data from the specified endpoint * * This function is called by the Endpoint handler function, after an * OUT interrupt has been received for that EP. The application must * only call this function through the supplied usb_ep_callback function. * * @param[in] ep Endpoint address corresponding to the one listed in * the device configuration table * @param[in] data Pointer to data buffer to write to * @param[in] max_data_len Max length of data to read * @param[out] ret_bytes Number of bytes read. If data is NULL and * max_data_len is 0 the number of bytes available * for read is returned. * * @return 0 on success, negative errno code on fail */ int usb_read(uint8_t ep, uint8_t *data, uint32_t max_data_len, uint32_t *ret_bytes); /** * @brief Set STALL condition on the specified endpoint * * This function is called by USB device class handler code to set stall * condition on endpoint. * * @param[in] ep Endpoint address corresponding to the one listed in * the device configuration table * * @return 0 on success, negative errno code on fail */ int usb_ep_set_stall(uint8_t ep); /** * @brief Clears STALL condition on the specified endpoint * * This function is called by USB device class handler code to clear stall * condition on endpoint. * * @param[in] ep Endpoint address corresponding to the one listed in * the device configuration table * * @return 0 on success, negative errno code on fail */ int usb_ep_clear_stall(uint8_t ep); /** * @brief Read data from the specified endpoint * * This is similar to usb_ep_read, the difference being that, it doesn't * clear the endpoint NAKs so that the consumer is not bogged down by further * upcalls till he is done with the processing of the data. The caller should * reactivate ep by invoking usb_ep_read_continue() do so. * * @param[in] ep Endpoint address corresponding to the one * listed in the device configuration table * @param[in] data pointer to data buffer to write to * @param[in] max_data_len max length of data to read * @param[out] read_bytes Number of bytes read. If data is NULL and * max_data_len is 0 the number of bytes * available for read should be returned. * * @return 0 on success, negative errno code on fail. */ int usb_ep_read_wait(uint8_t ep, uint8_t *data, uint32_t max_data_len, uint32_t *read_bytes); /** * @brief Continue reading data from the endpoint * * Clear the endpoint NAK and enable the endpoint to accept more data * from the host. Usually called after usb_ep_read_wait() when the consumer * is fine to accept more data. Thus these calls together acts as flow control * mechanism. * * @param[in] ep Endpoint address corresponding to the one * listed in the device configuration table * * @return 0 on success, negative errno code on fail. */ int usb_ep_read_continue(uint8_t ep); /** * Callback function signature for transfer completion. */ typedef void (*usb_transfer_callback)(uint8_t ep, int tsize, void *priv); /* USB transfer flags */ #define USB_TRANS_READ BIT(0) /** Read transfer flag */ #define USB_TRANS_WRITE BIT(1) /** Write transfer flag */ #define USB_TRANS_NO_ZLP BIT(2) /** No zero-length packet flag */ /** * @brief Transfer management endpoint callback * * If a USB class driver wants to use high-level transfer functions, driver * needs to register this callback as usb endpoint callback. */ void usb_transfer_ep_callback(uint8_t ep, enum usb_dc_ep_cb_status_code); /** * @brief Start a transfer * * Start a usb transfer to/from the data buffer. This function is asynchronous * and can be executed in IRQ context. The provided callback will be called * on transfer completion (or error) in thread context. * * @param[in] ep Endpoint address corresponding to the one * listed in the device configuration table * @param[in] data Pointer to data buffer to write-to/read-from * @param[in] dlen Size of data buffer * @param[in] flags Transfer flags (USB_TRANS_READ, USB_TRANS_WRITE...) * @param[in] cb Function called on transfer completion/failure * @param[in] priv Data passed back to the transfer completion callback * * @return 0 on success, negative errno code on fail. */ int usb_transfer(uint8_t ep, uint8_t *data, size_t dlen, unsigned int flags, usb_transfer_callback cb, void *priv); /** * @brief Start a transfer and block-wait for completion * * Synchronous version of usb_transfer, wait for transfer completion before * returning. * * @param[in] ep Endpoint address corresponding to the one * listed in the device configuration table * @param[in] data Pointer to data buffer to write-to/read-from * @param[in] dlen Size of data buffer * @param[in] flags Transfer flags * * @return number of bytes transferred on success, negative errno code on fail. */ int usb_transfer_sync(uint8_t ep, uint8_t *data, size_t dlen, unsigned int flags); /** * @brief Cancel any ongoing transfer on the specified endpoint * * @param[in] ep Endpoint address corresponding to the one * listed in the device configuration table * * @return 0 on success, negative errno code on fail. */ void usb_cancel_transfer(uint8_t ep); /** * @brief Cancel all ongoing transfers */ void usb_cancel_transfers(void); /** * @brief Check that transfer is ongoing for the endpoint * * @param[in] ep Endpoint address corresponding to the one * listed in the device configuration table * * @return true if transfer is ongoing, false otherwise. */ bool usb_transfer_is_busy(uint8_t ep); /** * @brief Start the USB remote wakeup procedure * * Function to request a remote wakeup. * This feature must be enabled in configuration, otherwise * it will always return -ENOTSUP error. * * @return 0 on success, negative errno code on fail, * i.e. when the bus is already active. */ int usb_wakeup_request(void); /** * @} */ #ifdef __cplusplus } #endif #endif /* ZEPHYR_INCLUDE_USB_USB_DEVICE_H_ */ |