Files
tinyUSB/src/device/dcd.h

245 lines
8.5 KiB
C
Raw Normal View History

/*
2020-01-14 23:30:39 -05:00
* The MIT License (MIT)
*
* Copyright (c) 2019 Ha Thach (tinyusb.org)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* This file is part of the TinyUSB stack.
*/
2024-05-24 14:06:25 +07:00
#ifndef TUSB_DCD_H_
#define TUSB_DCD_H_
2020-01-14 23:30:39 -05:00
#include "common/tusb_common.h"
2021-05-27 17:40:39 +07:00
#include "osal/osal.h"
2021-01-18 17:08:59 +01:00
#include "common/tusb_fifo.h"
2020-01-14 23:30:39 -05:00
#ifdef __cplusplus
extern "C" {
#endif
2021-07-21 17:00:02 +07:00
//--------------------------------------------------------------------+
// MACRO CONSTANT TYPEDEF PROTYPES
//--------------------------------------------------------------------+
2023-11-24 11:38:20 +07:00
typedef enum {
DCD_EVENT_INVALID = 0, // 0
DCD_EVENT_BUS_RESET, // 1
DCD_EVENT_UNPLUGGED, // 2
DCD_EVENT_SOF, // 3
DCD_EVENT_SUSPEND, // 4 TODO LPM Sleep L1 support
DCD_EVENT_RESUME, // 5
DCD_EVENT_SETUP_RECEIVED, // 6
DCD_EVENT_XFER_COMPLETE, // 7
USBD_EVENT_FUNC_CALL, // 8 Not an DCD event, just a convenient way to defer ISR function
2020-01-14 23:30:39 -05:00
DCD_EVENT_COUNT
} dcd_eventid_t;
2023-11-24 11:38:20 +07:00
typedef struct TU_ATTR_ALIGNED(4) {
2020-01-14 23:30:39 -05:00
uint8_t rhport;
uint8_t event_id;
2023-11-24 11:38:20 +07:00
union {
// BUS RESET
struct {
tusb_speed_t speed;
} bus_reset;
// SOF
struct {
uint32_t frame_count;
}sof;
// SETUP_RECEIVED
2020-01-14 23:30:39 -05:00
tusb_control_request_t setup_received;
// XFER_COMPLETE
2020-01-14 23:30:39 -05:00
struct {
uint8_t ep_addr;
uint8_t result;
uint32_t len;
}xfer_complete;
// FUNC_CALL
2020-01-14 23:30:39 -05:00
struct {
void (*func) (void*);
void* param;
}func_call;
};
} dcd_event_t;
//TU_VERIFY_STATIC(sizeof(dcd_event_t) <= 12, "size is not correct");
//--------------------------------------------------------------------+
// Memory API
//--------------------------------------------------------------------+
// clean/flush data cache: write cache -> memory.
// Required before an DMA TX transfer to make sure data is in memory
2023-06-16 12:02:42 +07:00
void dcd_dcache_clean(void const* addr, uint32_t data_size) TU_ATTR_WEAK;
// invalidate data cache: mark cache as invalid, next read will read from memory
// Required BOTH before and after an DMA RX transfer
2023-06-16 12:02:42 +07:00
void dcd_dcache_invalidate(void const* addr, uint32_t data_size) TU_ATTR_WEAK;
// clean and invalidate data cache
// Required before an DMA transfer where memory is both read/write by DMA
2023-06-16 12:02:42 +07:00
void dcd_dcache_clean_invalidate(void const* addr, uint32_t data_size) TU_ATTR_WEAK;
//--------------------------------------------------------------------+
// Controller API
//--------------------------------------------------------------------+
2020-01-14 23:30:39 -05:00
// Initialize controller to device mode
void dcd_init(const tusb_rhport_init_t* rh_init);
2020-01-14 23:30:39 -05:00
// Deinitialize controller, unset device mode.
2024-04-08 22:07:56 +07:00
bool dcd_deinit(uint8_t rhport);
2020-01-14 23:30:39 -05:00
// Interrupt Handler
void dcd_int_handler(uint8_t rhport);
2020-01-14 23:30:39 -05:00
// Enable device interrupt
void dcd_int_enable (uint8_t rhport);
// Disable device interrupt
void dcd_int_disable(uint8_t rhport);
// Receive Set Address request, mcu port must also include status IN response
void dcd_set_address(uint8_t rhport, uint8_t dev_addr);
// Wake up host
void dcd_remote_wakeup(uint8_t rhport);
// Connect by enabling internal pull-up resistor on D+/D-
void dcd_connect(uint8_t rhport);
// Disconnect by disabling internal pull-up resistor on D+/D-
void dcd_disconnect(uint8_t rhport);
2020-04-09 11:42:42 +07:00
// Enable/Disable Start-of-frame interrupt. Default is disabled
void dcd_sof_enable(uint8_t rhport, bool en);
2024-05-13 22:26:19 +02:00
#if CFG_TUD_TEST_MODE
2024-01-15 12:47:13 +00:00
// Put device into a test mode (needs power cycle to quit)
void dcd_enter_test_mode(uint8_t rhport, tusb_feature_test_mode_t test_selector);
2024-05-13 22:26:19 +02:00
#endif
2020-01-14 23:30:39 -05:00
//--------------------------------------------------------------------+
// Endpoint API
//--------------------------------------------------------------------+
// Invoked when a control transfer's status stage is complete.
// May help DCD to prepare for next control transfer, this API is optional.
void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const * request);
2020-01-14 23:30:39 -05:00
// Configure endpoint's registers according to descriptor
bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_ep);
2020-01-14 23:30:39 -05:00
// Close all non-control endpoints, cancel all pending transfers if any.
// Invoked when switching from a non-zero Configuration by SET_CONFIGURE therefore
// required for multiple configuration support.
void dcd_edpt_close_all (uint8_t rhport);
2020-01-14 23:30:39 -05:00
// Submit a transfer, When complete dcd_event_xfer_complete() is invoked to notify the stack
2021-01-31 19:08:23 +01:00
bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes);
2020-01-14 23:30:39 -05:00
2021-03-10 17:58:39 +07:00
// Submit an transfer using fifo, When complete dcd_event_xfer_complete() is invoked to notify the stack
// This API is optional, may be useful for register-based for transferring data.
bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) TU_ATTR_WEAK;
2021-01-18 17:08:59 +01:00
// Stall endpoint, any queuing transfer should be removed from endpoint
2021-01-31 19:08:23 +01:00
void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr);
2020-01-14 23:30:39 -05:00
// clear stall, data toggle is also reset to DATA0
2021-08-12 00:11:04 +07:00
// This API never calls with control endpoints, since it is auto cleared when receiving setup packet
2021-01-31 19:08:23 +01:00
void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr);
2020-01-14 23:30:39 -05:00
#ifdef TUP_DCD_EDPT_ISO_ALLOC
// Allocate packet buffer used by ISO endpoints
2023-11-24 11:38:20 +07:00
// Some MCU need manual packet buffer allocation, we allocate the largest size to avoid clustering
bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size);
// Configure and enable an ISO endpoint according to descriptor
bool dcd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const * desc_ep);
#else
// Close an endpoint.
void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr);
#endif
2020-01-14 23:30:39 -05:00
//--------------------------------------------------------------------+
2020-09-05 15:45:03 +07:00
// Event API (implemented by stack)
2020-01-14 23:30:39 -05:00
//--------------------------------------------------------------------+
// Called by DCD to notify device stack
extern void dcd_event_handler(dcd_event_t const * event, bool in_isr);
// helper to send bus signal event
2023-11-24 11:38:20 +07:00
TU_ATTR_ALWAYS_INLINE static inline void dcd_event_bus_signal (uint8_t rhport, dcd_eventid_t eid, bool in_isr) {
2024-10-11 16:00:51 +07:00
dcd_event_t event;
event.rhport = rhport;
event.event_id = eid;
2022-04-18 17:49:21 +07:00
dcd_event_handler(&event, in_isr);
}
2020-01-14 23:30:39 -05:00
// helper to send bus reset event
2023-11-24 11:38:20 +07:00
TU_ATTR_ALWAYS_INLINE static inline void dcd_event_bus_reset (uint8_t rhport, tusb_speed_t speed, bool in_isr) {
2024-10-11 16:00:51 +07:00
dcd_event_t event;
event.rhport = rhport;
event.event_id = DCD_EVENT_BUS_RESET;
2022-04-18 17:49:21 +07:00
event.bus_reset.speed = speed;
dcd_event_handler(&event, in_isr);
}
2020-01-14 23:30:39 -05:00
// helper to send setup received
2023-11-24 11:38:20 +07:00
TU_ATTR_ALWAYS_INLINE static inline void dcd_event_setup_received(uint8_t rhport, uint8_t const * setup, bool in_isr) {
2024-10-11 16:00:51 +07:00
dcd_event_t event;
event.rhport = rhport;
event.event_id = DCD_EVENT_SETUP_RECEIVED;
memcpy(&event.setup_received, setup, sizeof(tusb_control_request_t));
2022-04-18 17:49:21 +07:00
dcd_event_handler(&event, in_isr);
}
2020-01-14 23:30:39 -05:00
// helper to send transfer complete event
2023-11-24 11:38:20 +07:00
TU_ATTR_ALWAYS_INLINE static inline void dcd_event_xfer_complete (uint8_t rhport, uint8_t ep_addr, uint32_t xferred_bytes, uint8_t result, bool in_isr) {
2024-10-11 16:00:51 +07:00
dcd_event_t event;
event.rhport = rhport;
event.event_id = DCD_EVENT_XFER_COMPLETE;
2022-04-18 17:49:21 +07:00
event.xfer_complete.ep_addr = ep_addr;
event.xfer_complete.len = xferred_bytes;
event.xfer_complete.result = result;
dcd_event_handler(&event, in_isr);
}
2020-01-14 23:30:39 -05:00
2023-11-24 11:38:20 +07:00
TU_ATTR_ALWAYS_INLINE static inline void dcd_event_sof(uint8_t rhport, uint32_t frame_count, bool in_isr) {
2024-10-11 16:00:51 +07:00
dcd_event_t event;
event.rhport = rhport;
event.event_id = DCD_EVENT_SOF;
event.sof.frame_count = frame_count;
dcd_event_handler(&event, in_isr);
}
2020-01-14 23:30:39 -05:00
#ifdef __cplusplus
}
#endif
2024-05-24 14:06:25 +07:00
#endif