forked from espressif/arduino-esp32
Update IDF and Camera
This commit is contained in:
@ -84,20 +84,6 @@ esp_err_t esp_coex_status_bit_set(esp_coex_status_type_t type, uint32_t status);
|
||||
*/
|
||||
esp_err_t esp_coex_status_bit_clear(esp_coex_status_type_t type, uint32_t status);
|
||||
|
||||
/**
|
||||
* @brief Enable BLE connection dynamic priority
|
||||
* @attention If the parameter is true, BLE connection performance will be better but WiFi performance
|
||||
will be poorer. And vice versa.
|
||||
* @param low_interval : true - Increase BLE connection priority to be higher than WiFi's when BLE
|
||||
* connection interval is less or equal than 50 ms. The default value
|
||||
* is false.
|
||||
* false - not increace
|
||||
* @param high_interval : true - Increase BLE connection priority to be higher than WiFi's when BLE
|
||||
* connection interval is more than 50 ms. The default value is true.
|
||||
* false - not increace
|
||||
* @return : ESP_OK - success, other - failed
|
||||
*/
|
||||
esp_err_t esp_coex_ble_conn_dynamic_prio_enable(bool low_interval, bool high_interval);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -21,17 +21,19 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define COEX_ADAPTER_VERSION 0x00000001
|
||||
#define COEX_ADAPTER_VERSION 0x00000002
|
||||
#define COEX_ADAPTER_MAGIC 0xDEADBEAF
|
||||
|
||||
#define COEX_ADAPTER_FUNCS_TIME_BLOCKING 0xffffffff
|
||||
|
||||
typedef struct {
|
||||
int32_t _version;
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
void *(* _spin_lock_create)(void);
|
||||
void (* _spin_lock_delete)(void *lock);
|
||||
uint32_t (*_int_disable)(void *mux);
|
||||
void (*_int_enable)(void *mux, uint32_t tmp);
|
||||
#endif
|
||||
void (*_task_yield_from_isr)(void);
|
||||
void *(*_semphr_create)(uint32_t max, uint32_t init);
|
||||
void (*_semphr_delete)(void *semphr);
|
||||
@ -42,10 +44,12 @@ typedef struct {
|
||||
int32_t (* _is_in_isr)(void);
|
||||
void * (* _malloc_internal)(size_t size);
|
||||
void (* _free)(void *p);
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
void (* _timer_disarm)(void *timer);
|
||||
void (* _timer_done)(void *ptimer);
|
||||
void (* _timer_setfn)(void *ptimer, void *pfunction, void *parg);
|
||||
void (* _timer_arm_us)(void *ptimer, uint32_t us, bool repeat);
|
||||
#endif
|
||||
int64_t (* _esp_timer_get_time)(void);
|
||||
int32_t _magic;
|
||||
} coex_adapter_funcs_t;
|
||||
|
@ -54,16 +54,18 @@ esp_err_t coex_init(void);
|
||||
void coex_deinit(void);
|
||||
|
||||
/**
|
||||
* @brief Pause software coexist
|
||||
* @brief Enable software coexist
|
||||
* extern function for internal use.
|
||||
*
|
||||
* @return Enable ok or failed.
|
||||
*/
|
||||
void coex_pause(void);
|
||||
esp_err_t coex_enable(void);
|
||||
|
||||
/**
|
||||
* @brief Resume software coexist
|
||||
* @brief Disable software coexist
|
||||
* extern function for internal use.
|
||||
*/
|
||||
void coex_resume(void);
|
||||
void coex_disable(void);
|
||||
|
||||
/**
|
||||
* @brief Get software coexist version string
|
||||
@ -112,44 +114,82 @@ int coex_wifi_request(uint32_t event, uint32_t latency, uint32_t duration);
|
||||
int coex_wifi_release(uint32_t event);
|
||||
|
||||
/**
|
||||
* @brief Blue tooth requests coexistence.
|
||||
* @brief Set WiFi channel to coexistence module.
|
||||
*
|
||||
* @param event : blue tooth event
|
||||
* @param latency : blue tooth will request coexistence after latency
|
||||
* @param duration : duration for blue tooth to request coexistence
|
||||
* @param primary : WiFi primary channel
|
||||
* @param secondary : WiFi secondary channel
|
||||
* @return : 0 - success, other - failed
|
||||
*/
|
||||
int coex_bt_request(uint32_t event, uint32_t latency, uint32_t duration);
|
||||
int coex_wifi_channel_set(uint8_t primary, uint8_t secondary);
|
||||
|
||||
/**
|
||||
* @brief Blue tooth release coexistence.
|
||||
* @brief Get coexistence event duration.
|
||||
*
|
||||
* @param event : blue tooth event
|
||||
* @param event : Coexistence event
|
||||
* @param duration: Coexistence event duration
|
||||
* @return : 0 - success, other - failed
|
||||
*/
|
||||
int coex_bt_release(uint32_t event);
|
||||
int coex_event_duration_get(uint32_t event, uint32_t *duration);
|
||||
|
||||
/**
|
||||
* @brief Register callback function for blue tooth.
|
||||
* @brief Clear coexistence status.
|
||||
*
|
||||
* @param cb : callback function
|
||||
* @param type : Coexistence status type
|
||||
* @param status: Coexistence status
|
||||
*/
|
||||
void coex_schm_status_bit_clear(uint32_t type, uint32_t status);
|
||||
|
||||
/**
|
||||
* @brief Set coexistence status.
|
||||
*
|
||||
* @param type : Coexistence status type
|
||||
* @param status: Coexistence status
|
||||
*/
|
||||
void coex_schm_status_bit_set(uint32_t type, uint32_t status);
|
||||
|
||||
/**
|
||||
* @brief Set coexistence scheme interval.
|
||||
*
|
||||
* @param interval : Coexistence scheme interval
|
||||
* @return : 0 - success, other - failed
|
||||
*/
|
||||
int coex_register_bt_cb(coex_func_cb_t cb);
|
||||
int coex_schm_interval_set(uint32_t interval);
|
||||
|
||||
/**
|
||||
* @brief Lock before reset base band.
|
||||
* @brief Get coexistence scheme interval.
|
||||
*
|
||||
* @return : lock value
|
||||
* @return : Coexistence scheme interval
|
||||
*/
|
||||
uint32_t coex_bb_reset_lock(void);
|
||||
uint32_t coex_schm_interval_get(void);
|
||||
|
||||
/**
|
||||
* @brief Unlock after reset base band.
|
||||
* @brief Get current coexistence scheme period.
|
||||
*
|
||||
* @param restore : lock value
|
||||
* @return : Coexistence scheme period
|
||||
*/
|
||||
void coex_bb_reset_unlock(uint32_t restore);
|
||||
uint8_t coex_schm_curr_period_get(void);
|
||||
|
||||
/**
|
||||
* @brief Get current coexistence scheme phase.
|
||||
*
|
||||
* @return : Coexistence scheme phase
|
||||
*/
|
||||
void * coex_schm_curr_phase_get(void);
|
||||
|
||||
/**
|
||||
* @brief Set current coexistence scheme phase index.
|
||||
*
|
||||
* @param interval : Coexistence scheme phase index
|
||||
* @return : 0 - success, other - failed
|
||||
*/
|
||||
int coex_schm_curr_phase_idx_set(int idx);
|
||||
|
||||
/**
|
||||
* @brief Get current coexistence scheme phase index.
|
||||
*
|
||||
* @return : Coexistence scheme phase index
|
||||
*/
|
||||
int coex_schm_curr_phase_idx_get(void);
|
||||
|
||||
/**
|
||||
* @brief Register coexistence adapter functions.
|
||||
|
@ -48,21 +48,6 @@ typedef enum {
|
||||
PHY_RF_CAL_FULL = 0x00000002 /*!< Do full RF calibration. Produces best results, but also consumes a lot of time and current. Suggested to be used once. */
|
||||
} esp_phy_calibration_mode_t;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Modules for modem sleep
|
||||
*/
|
||||
typedef enum{
|
||||
MODEM_BLE_MODULE, //!< BLE controller used
|
||||
MODEM_CLASSIC_BT_MODULE, //!< Classic BT controller used
|
||||
MODEM_WIFI_STATION_MODULE, //!< Wi-Fi Station used
|
||||
MODEM_WIFI_SOFTAP_MODULE, //!< Wi-Fi SoftAP used
|
||||
MODEM_WIFI_SNIFFER_MODULE, //!< Wi-Fi Sniffer used
|
||||
MODEM_WIFI_NULL_MODULE, //!< Wi-Fi Null mode used
|
||||
MODEM_USER_MODULE, //!< User used
|
||||
MODEM_MODULE_COUNT //!< Number of items
|
||||
}modem_sleep_module_t;
|
||||
|
||||
#if CONFIG_ESP32_SUPPORT_MULTIPLE_PHY_INIT_DATA_BIN
|
||||
/**
|
||||
* @brief PHY init data type
|
||||
@ -87,30 +72,6 @@ typedef enum {
|
||||
} phy_init_data_type_t;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Module WIFI mask for medem sleep
|
||||
*/
|
||||
#define MODEM_BT_MASK ((1<<MODEM_BLE_MODULE) | \
|
||||
(1<<MODEM_CLASSIC_BT_MODULE))
|
||||
|
||||
/**
|
||||
* @brief Module WIFI mask for medem sleep
|
||||
*/
|
||||
#define MODEM_WIFI_MASK ((1<<MODEM_WIFI_STATION_MODULE) | \
|
||||
(1<<MODEM_WIFI_SOFTAP_MODULE) | \
|
||||
(1<<MODEM_WIFI_SNIFFER_MODULE) | \
|
||||
(1<<MODEM_WIFI_NULL_MODULE))
|
||||
|
||||
/**
|
||||
* @brief Modules needing to call phy_rf_init
|
||||
*/
|
||||
typedef enum{
|
||||
PHY_BT_MODULE, //!< Bluetooth used
|
||||
PHY_WIFI_MODULE, //!< Wi-Fi used
|
||||
PHY_MODEM_MODULE, //!< Modem sleep used
|
||||
PHY_MODULE_COUNT //!< Number of items
|
||||
}phy_rf_module_t;
|
||||
|
||||
/**
|
||||
* @brief Get PHY init data
|
||||
*
|
||||
@ -193,38 +154,29 @@ esp_err_t esp_phy_store_cal_data_to_nvs(const esp_phy_calibration_data_t* cal_da
|
||||
esp_err_t esp_phy_erase_cal_data_in_nvs(void);
|
||||
|
||||
/**
|
||||
* @brief Initialize PHY and RF module
|
||||
* @brief Enable PHY and RF module
|
||||
*
|
||||
* PHY and RF module should be initialized in order to use WiFi or BT.
|
||||
* Now PHY and RF initializing job is done automatically when start WiFi or BT. Users should not
|
||||
* PHY and RF module should be enabled in order to use WiFi or BT.
|
||||
* Now PHY and RF enabling job is done automatically when start WiFi or BT. Users should not
|
||||
* call this API in their application.
|
||||
*
|
||||
* @param init_data PHY parameters. Default set of parameters can
|
||||
* be obtained by calling esp_phy_get_default_init_data
|
||||
* function.
|
||||
* @param mode Calibration mode (Full, partial, or no calibration)
|
||||
* @param[inout] calibration_data
|
||||
* @return ESP_OK on success.
|
||||
* @return ESP_FAIL on fail.
|
||||
*/
|
||||
esp_err_t esp_phy_rf_init(const esp_phy_init_data_t* init_data,esp_phy_calibration_mode_t mode,
|
||||
esp_phy_calibration_data_t* calibration_data, phy_rf_module_t module);
|
||||
void esp_phy_enable(void);
|
||||
|
||||
/**
|
||||
* @brief De-initialize PHY and RF module
|
||||
* @brief Disable PHY and RF module
|
||||
*
|
||||
* PHY module should be de-initialized in order to shutdown WiFi or BT.
|
||||
* Now PHY and RF de-initializing job is done automatically when stop WiFi or BT. Users should not
|
||||
* PHY module should be disabled in order to shutdown WiFi or BT.
|
||||
* Now PHY and RF disabling job is done automatically when stop WiFi or BT. Users should not
|
||||
* call this API in their application.
|
||||
*
|
||||
* @return ESP_OK on success.
|
||||
*/
|
||||
esp_err_t esp_phy_rf_deinit(phy_rf_module_t module);
|
||||
void esp_phy_disable(void);
|
||||
|
||||
/**
|
||||
* @brief Load calibration data from NVS and initialize PHY and RF module
|
||||
*/
|
||||
void esp_phy_load_cal_and_init(phy_rf_module_t module);
|
||||
void esp_phy_load_cal_and_init(void);
|
||||
|
||||
/**
|
||||
* @brief Enable WiFi/BT common clock
|
||||
@ -238,30 +190,6 @@ void esp_phy_common_clock_enable(void);
|
||||
*/
|
||||
void esp_phy_common_clock_disable(void);
|
||||
|
||||
/**
|
||||
* @brief Module requires to enter modem sleep
|
||||
*/
|
||||
esp_err_t esp_modem_sleep_enter(modem_sleep_module_t module);
|
||||
|
||||
/**
|
||||
* @brief Module requires to exit modem sleep
|
||||
*/
|
||||
esp_err_t esp_modem_sleep_exit(modem_sleep_module_t module);
|
||||
|
||||
/**
|
||||
* @brief Register module to make it be able to require to enter/exit modem sleep
|
||||
* Although the module has no sleep function, as long as the module use RF,
|
||||
* it must call esp_modem_sleep_regsiter. Otherwise, other modules with sleep
|
||||
* function will disable RF without checking the module which doesn't call
|
||||
* esp_modem_sleep_regsiter.
|
||||
*/
|
||||
esp_err_t esp_modem_sleep_register(modem_sleep_module_t module);
|
||||
|
||||
/**
|
||||
* @brief De-register module from modem sleep list
|
||||
*/
|
||||
esp_err_t esp_modem_sleep_deregister(modem_sleep_module_t module);
|
||||
|
||||
/**
|
||||
* @brief Get the time stamp when PHY/RF was switched on
|
||||
* @return return 0 if PHY/RF is never switched on. Otherwise return time in
|
||||
|
@ -478,6 +478,28 @@ esp_err_t esp_wifi_internal_get_negotiated_bandwidth(wifi_interface_t ifx, uint8
|
||||
bool esp_wifi_internal_is_tsf_active(void);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @breif TxDone callback function type. Should be registered using esp_wifi_set_tx_done_cb()
|
||||
*
|
||||
* @param ifidx The interface id that the tx callback has been triggered from
|
||||
* @param data Pointer to the data transmitted
|
||||
* @param data_len Length of the data transmitted
|
||||
* @param txStatus True:if the data was transmitted sucessfully False: if data transmission failed
|
||||
*/
|
||||
typedef void (* wifi_tx_done_cb_t)(uint8_t ifidx, uint8_t *data, uint16_t *data_len, bool txStatus);
|
||||
|
||||
/**
|
||||
* @brief Register the txDone callback function of type wifi_tx_done_cb_t
|
||||
*
|
||||
* @param cb The callback function
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: succeed
|
||||
* - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by esp_wifi_init
|
||||
* - ESP_ERR_WIFI_NOT_STARTED: WiFi is not started by esp_wifi_start
|
||||
*/
|
||||
esp_err_t esp_wifi_set_tx_done_cb(wifi_tx_done_cb_t cb);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -21,7 +21,7 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define ESP_WIFI_OS_ADAPTER_VERSION 0x00000007
|
||||
#define ESP_WIFI_OS_ADAPTER_VERSION 0x00000008
|
||||
#define ESP_WIFI_OS_ADAPTER_MAGIC 0xDEADBEAF
|
||||
|
||||
#define OSI_FUNCS_TIME_BLOCKING 0xffffffff
|
||||
@ -32,9 +32,13 @@ extern "C" {
|
||||
|
||||
typedef struct {
|
||||
int32_t _version;
|
||||
bool (* _env_is_chip)(void);
|
||||
void (*_set_intr)(int32_t cpu_no, uint32_t intr_source, uint32_t intr_num, int32_t intr_prio);
|
||||
void (*_clear_intr)(uint32_t intr_source, uint32_t intr_num);
|
||||
void (*_set_isr)(int32_t n, void *f, void *arg);
|
||||
void (*_ints_on)(uint32_t mask);
|
||||
void (*_ints_off)(uint32_t mask);
|
||||
bool (* _is_from_isr)(void);
|
||||
void *(* _spin_lock_create)(void);
|
||||
void (* _spin_lock_delete)(void *lock);
|
||||
uint32_t (*_wifi_int_disable)(void *wifi_int_mux);
|
||||
@ -77,8 +81,10 @@ typedef struct {
|
||||
uint32_t (* _rand)(void);
|
||||
void (* _dport_access_stall_other_cpu_start_wrap)(void);
|
||||
void (* _dport_access_stall_other_cpu_end_wrap)(void);
|
||||
int32_t (* _phy_rf_deinit)(uint32_t module);
|
||||
void (* _phy_load_cal_and_init)(uint32_t module);
|
||||
void (* _wifi_apb80m_request)(void);
|
||||
void (* _wifi_apb80m_release)(void);
|
||||
void (* _phy_disable)(void);
|
||||
void (* _phy_enable)(void);
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
void (* _phy_common_clock_enable)(void);
|
||||
void (* _phy_common_clock_disable)(void);
|
||||
@ -93,6 +99,8 @@ typedef struct {
|
||||
void (* _wifi_reset_mac)(void);
|
||||
void (* _wifi_clock_enable)(void);
|
||||
void (* _wifi_clock_disable)(void);
|
||||
void (* _wifi_rtc_enable_iso)(void);
|
||||
void (* _wifi_rtc_disable_iso)(void);
|
||||
int64_t (* _esp_timer_get_time)(void);
|
||||
int32_t (* _nvs_set_i8)(uint32_t handle, const char* key, int8_t value);
|
||||
int32_t (* _nvs_get_i8)(uint32_t handle, const char* key, int8_t* out_value);
|
||||
@ -109,7 +117,7 @@ typedef struct {
|
||||
int32_t (* _get_random)(uint8_t *buf, size_t len);
|
||||
int32_t (* _get_time)(void *t);
|
||||
unsigned long (* _random)(void);
|
||||
#if CONFIG_IDF_TARGET_ESP32S2
|
||||
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C3
|
||||
uint32_t (* _slowclk_cal_get)(void);
|
||||
#endif
|
||||
void (* _log_write)(uint32_t level, const char* tag, const char* format, ...);
|
||||
@ -125,15 +133,25 @@ typedef struct {
|
||||
void * (* _wifi_zalloc)(size_t size);
|
||||
void * (* _wifi_create_queue)(int32_t queue_len, int32_t item_size);
|
||||
void (* _wifi_delete_queue)(void * queue);
|
||||
int32_t (* _modem_sleep_enter)(uint32_t module);
|
||||
int32_t (* _modem_sleep_exit)(uint32_t module);
|
||||
int32_t (* _modem_sleep_register)(uint32_t module);
|
||||
int32_t (* _modem_sleep_deregister)(uint32_t module);
|
||||
int (* _coex_init)(void);
|
||||
void (* _coex_deinit)(void);
|
||||
int (* _coex_enable)(void);
|
||||
void (* _coex_disable)(void);
|
||||
uint32_t (* _coex_status_get)(void);
|
||||
void (* _coex_condition_set)(uint32_t type, bool dissatisfy);
|
||||
int32_t (* _coex_wifi_request)(uint32_t event, uint32_t latency, uint32_t duration);
|
||||
int32_t (* _coex_wifi_release)(uint32_t event);
|
||||
bool (* _is_from_isr)(void);
|
||||
int (* _coex_wifi_channel_set)(uint8_t primary, uint8_t secondary);
|
||||
int (* _coex_event_duration_get)(uint32_t event, uint32_t *duration);
|
||||
int (* _coex_pti_get)(uint32_t event, uint8_t *pti);
|
||||
void (* _coex_schm_status_bit_clear)(uint32_t type, uint32_t status);
|
||||
void (* _coex_schm_status_bit_set)(uint32_t type, uint32_t status);
|
||||
int (* _coex_schm_interval_set)(uint32_t interval);
|
||||
uint32_t (* _coex_schm_interval_get)(void);
|
||||
uint8_t (* _coex_schm_curr_period_get)(void);
|
||||
void * (* _coex_schm_curr_phase_get)(void);
|
||||
int (* _coex_schm_curr_phase_idx_set)(int idx);
|
||||
int (* _coex_schm_curr_phase_idx_get)(void);
|
||||
int32_t _magic;
|
||||
} wifi_osi_funcs_t;
|
||||
|
||||
|
@ -329,7 +329,7 @@ typedef struct {
|
||||
unsigned sgi:1; /**< Short Guide Interval(SGI). 0: Long GI; 1: Short GI */
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
signed noise_floor:8; /**< noise floor of Radio Frequency Module(RF). unit: 0.25dBm*/
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C3
|
||||
unsigned :8; /**< reserved */
|
||||
#endif
|
||||
unsigned ampdu_cnt:8; /**< ampdu cnt */
|
||||
@ -340,12 +340,20 @@ typedef struct {
|
||||
unsigned :32; /**< reserved */
|
||||
#if CONFIG_IDF_TARGET_ESP32S2
|
||||
unsigned :32; /**< reserved */
|
||||
#elif CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C3
|
||||
signed noise_floor:8; /**< noise floor of Radio Frequency Module(RF). unit: 0.25dBm*/
|
||||
unsigned :24; /**< reserved */
|
||||
unsigned :32; /**< reserved */
|
||||
#endif
|
||||
unsigned :31; /**< reserved */
|
||||
unsigned ant:1; /**< antenna number from which this packet is received. 0: WiFi antenna 0; 1: WiFi antenna 1 */
|
||||
#if CONFIG_IDF_TARGET_ESP32S2
|
||||
signed noise_floor:8; /**< noise floor of Radio Frequency Module(RF). unit: 0.25dBm*/
|
||||
unsigned :24; /**< reserved */
|
||||
#elif CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C3
|
||||
unsigned :32; /**< reserved */
|
||||
unsigned :32; /**< reserved */
|
||||
unsigned :32; /**< reserved */
|
||||
#endif
|
||||
unsigned sig_len:12; /**< length of packet including Frame Check Sequence(FCS) */
|
||||
unsigned :12; /**< reserved */
|
||||
@ -531,6 +539,8 @@ typedef enum {
|
||||
WIFI_EVENT_AP_STADISCONNECTED, /**< a station disconnected from ESP32 soft-AP */
|
||||
WIFI_EVENT_AP_PROBEREQRECVED, /**< Receive probe request packet in soft-AP interface */
|
||||
|
||||
WIFI_EVENT_FTM_REPORT, /**< Receive report of FTM procedure */
|
||||
|
||||
WIFI_EVENT_MAX, /**< Invalid WiFi event ID */
|
||||
} wifi_event_t;
|
||||
|
||||
@ -616,6 +626,7 @@ typedef struct {
|
||||
#define WIFI_STATIS_RXTX (1<<1)
|
||||
#define WIFI_STATIS_HW (1<<2)
|
||||
#define WIFI_STATIS_DIAG (1<<3)
|
||||
#define WIFI_STATIS_PS (1<<4)
|
||||
#define WIFI_STATIS_ALL (-1)
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
Reference in New Issue
Block a user