Files
kunlun/plc/inc/cvg_api.h

630 lines
24 KiB
C
Raw Normal View History

2024-09-28 14:24:04 +08:00
/****************************************************************************
Copyright(c) 2019 by Aerospace C.Power (Chongqing) Microelectronics. ALL RIGHTS RESERVED.
This Information is proprietary to Aerospace C.Power (Chongqing) Microelectronics and MAY NOT
be copied by any method or incorporated into another program without
the express written consent of Aerospace C.Power. This Information or any portion
thereof remains the property of Aerospace C.Power. The Information contained herein
is believed to be accurate and Aerospace C.Power assumes no responsibility or
liability for its use in any way and conveys no license or title under
any patent or copyright and makes no representation or warranty that this
Information is free from patent or copyright infringement.
****************************************************************************/
#ifndef CVG_API_H
#define CVG_API_H
/* os shim includes */
#include "os_types.h"
/* common includes */
#include "iot_errno.h"
#include "iot_utils.h"
#include "iot_pib.h"
#include "iot_plc_msg_api.h"
#include "iot_plc_msg_cco_api.h"
/* plc common includes */
#include "plc_utils.h"
#include "plc_mme_assoc.h"
#include "plc_scan_tbl.h"
#ifdef __cplusplus
extern "C" {
#endif
/* cvg vdev start up reason */
#define CVG_VDEV_START_INVALID 0
/* chip boot up */
#define CVG_VDEV_START_BOOT_UP 1
/* configuration changed */
#define CVG_VDEV_START_CFG_CHANGED 2
/* application request */
#define CVG_VDEV_START_APP_REQ 3
/* nid confict detected */
#define CVG_VDEV_START_NID_CONFLICT 4
/* enter certification test mode */
#define CVG_VDEV_START_ENTER_CERT_TEST 5
/* exit certification test mode */
#define CVG_VDEV_START_EXIT_CERT_TEST 6
/* leave network */
#define CVG_VDEV_START_LEAVE_NETWORK 7
/* sta assoc request timeout */
#define CVG_VDEV_START_ASSOC_TIMEOUT 8
/* sta assoc request rejected by CCO */
#define CVG_VDEV_START_ASSOC_REJECTED 9
/* boot up for certification test */
#define CVG_VDEV_START_BOOT_UP_CERT_ONLY 10
/* sta device leave network due to rule 1 */
#define CVG_VDEV_START_LEAVE_NW_RULE_1 11
/* sta device leave network due to rule 2 */
#define CVG_VDEV_START_LEAVE_NW_RULE_2 12
/* sta device leave network due to rule 5 */
#define CVG_VDEV_START_LEAVE_NW_RULE_5 13
/* sta device leave network due to rule 6 */
#define CVG_VDEV_START_LEAVE_NW_RULE_6 14
/* sta device leave network due to rule 7 */
#define CVG_VDEV_START_LEAVE_NW_RULE_7 15
/* sta device leave network due to PCO ABNORMAL */
#define CVG_VDEV_START_LEAVE_NW_PCO_ABNORMAL 16
/* sta device leave network due to receive leave indication mme from CCO */
#define CVG_VDEV_START_LEAVE_NW_LEAVE_IND 17
/* sta device leave network due to current preferred network SN changed */
#define CVG_VDEV_START_NW_SN_CHG 18
/* sta device no candidate pco available in pco selection stage */
#define CVG_VDEV_START_NO_CAND_PCO 19
/* sta device no beacon received in whole route period in pco selection stage */
#define CVG_VDEV_START_NO_BC_RX 20
/* sta device found remote peer in the network with same mac address exist */
#define CVG_VDEV_START_DUPLICATE_MAC_EXIST 21
/* sta device force roaming failed */
#define CVG_VDEV_START_ROAM_FAILED 22
/* sta device receive assoc response from cco with invalid pco */
#define CVG_VDEV_START_PCO_INVALID 23
/* sta device detect debug cco network */
#define CVG_VDEV_START_DEBUG_CCO 24
/* sta device leave network due to cco mac address not in white list */
#define CVG_VDEV_START_LEAVE_NW_CCO_ADDR_WL 25
/* sta device leave network due to cco mac address in black list */
#define CVG_VDEV_START_LEAVE_NW_CCO_ADDR_BL 26
/* sta device leave network due to exist other best network */
#define CVG_VDEV_START_LEAVE_NW_EXIST_BEST_NW 27
/* sta device leave network due to level info out of sync with the network */
#define CVG_VDEV_START_LEAVE_NW_LEVEL_ABNORMAL 28
/* sta device leave network due to no assigned beacon time slot in the
* expected time.
*/
#define CVG_VDEV_START_LEAVE_NW_NO_BC_TS 29
/* sta device leave network due to target transformer found */
#define CVG_VDEV_START_LEAVE_NW_TARGET_TSFM 30
/* restart due to current network band switch */
#define CVG_VDEV_START_BAND_SWITCH 31
/* same network NID changed */
#define CVG_VDEV_START_SAME_NW_NID_CHG 32
/* route table corrupted */
#define CVG_VDEV_START_RT_TABLE_ERR 33
/* connecting target devices */
#define CVG_VDEV_START_CONNECT_WITH_CTRL_PROTO 34
/* sta device leave network due to hw tsfm send */
#define CVG_VDEV_START_HW_TSFM_SEND 35
/* white list cleared */
#define CVG_VDEV_START_WL_CLEAR 36
/* sta device leave network due to authorizd request timeout */
#define CVG_VDEV_START_AUTH_TIMEOUT 37
/* sta device leave network due to authentication failed */
#define CVG_VDEV_START_AUTH_FAILED 38
/* max start reason number, always keep this in the last */
#define CVG_VDEV_START_REASON_NUMBER 38
/* software build date buffer length */
#define SW_BUILD_DATE_LEN 6
/* max vdev number supported for each pdev */
#define CVG_MAX_VDEV_PER_PDEV 1
/* max pdev number supported */
#define CVG_MAX_PDEV 1
/* CVG writable PIB configation special mark to identify if the configuration
* is valid.
*/
#define CVG_CFG_RW_MARK 0x5A3DE68
/* vdev common configurations */
typedef struct _cvg_vdev_cmn_cfg {
/* device role. see PLC_DEV_ROLE_XXX */
uint8_t role;
/* device type. see PLC_DEV_TYPE_XXX */
uint8_t type;
/* reboot count */
uint8_t reboot_cnt;
/* proto supported */
uint8_t proto;
/* mac addr type. see PLC_MAC_ADDR_TYPE_METER_XX */
uint8_t addr_type;
/* mac address */
uint8_t mac_addr[IOT_MAC_ADDR_LEN];
/* original module address */
uint8_t module_addr[IOT_MAC_ADDR_LEN];
/* simple pair passcode value. Only same passcode CCO and STA can be
* associated.
*/
uint16_t passcode;
/* support band bitmap, band id see PLC_LIB_FREQ_BAND_xxx */
uint8_t band_bm[IOT_PLC_BAND_BITMAP_SIZE];
} cvg_vdev_cmn_cfg_t;
/* cco vdev configurations */
typedef struct _cvg_cco_vdev_cfg {
/* sta assoc retry interval after cco reject sta assoc request. the
* unit is 1 ms.
*/
uint32_t assoc_retry_int;
/* short network interface id */
uint32_t nid;
/* delay for each frequency band switch request, uint is 1ms */
uint32_t fb_chg_delay;
/* number of supported physical phases. The range should be from 1 - 3.
* if set to 1, only phase A supported.
* if set to 2, both phase A and B are supported.
* if set to 3, Phase A, B and C are supported.
*/
uint8_t p_phase_cnt;
/* network serial number */
uint8_t network_sn;
/* initial frequency band ID */
uint8_t freq_band_id;
/* network hplc tx power cap, unit is 1 dbuv */
uint8_t tx_power_cap;
/* network rf tx power cap, unit is 1 dbm */
int8_t rf_tx_power_cap;
/* allow to use beacon for channel evaluation */
uint8_t allow_chan_eval :1,
/* notify white list info to STA */
wl_notify_enable :1,
/* flag to mark if disable freq band detection */
fb_detect_disable :1,
/* flag to mark if rf tx power is valid */
rf_tx_power_valid :1,
/* flag to mark if enable the authorization process */
auth_enable :1,
/* encryption mode, see ENCRYPT_MODE_XXX */
encrypt_mode :1,
/* encryption_algorithm, see ENCRYPT_ALGO_XXX */
encrypt_algo :1,
/* reserved for future */
rsvd :1;
/* initial allowed to cco traffic success ratio, the unit is 1% */
uint8_t allowed_cco_tf_sr;
/* number of full route period sta need to spend on tr_sf calc. the unit
* is 1 route period.
*/
uint8_t proxy_select_dur;
/* minimal beacon period, the unit is 1s */
uint8_t min_bc_period;
/* allowed maximum nid */
uint16_t max_nid;
/* mac address used in previous network formation */
uint8_t prev_mac_addr[IOT_MAC_ADDR_LEN];
/* rf channel, see RF_CHANNEL_ID_XXX */
uint8_t rf_channel;
/* rf option, see RF_OPTION_XXX */
uint8_t rf_option :2,
/* flag to mark if enable rf channel coordination, default is enabled */
rf_cod_enable :1,
/* disable tx 3phase function */
tx_3phase_disable :1,
/* reserved for future */
rsvd1 :4;
/* delay for each rf channel switch request, uint is 1s */
uint16_t rf_chg_delay;
#if HPLC_RF_SUPPORT
/* record rf scan table index of loop */
uint8_t rf_tbl_idx;
/* valid number in the rf scan table */
uint8_t rf_tbl_cnt;
/* rf select bitmap, 1 - have been selected, 0 - not be selected */
uint8_t rf_select_bm[iot_ceil(IOT_PLC_RF_SCAN_TBL_MAX, 8)];
/* valid size of rf select bitmap */
uint8_t rf_bm_size;
/* rf scan table */
iot_plc_rf_scan_t rf_scan_tbl[IOT_PLC_RF_SCAN_TBL_MAX];
#endif
} cvg_vdev_cco_cfg_t;
/* sta vdev configurations */
typedef struct _cvg_sta_vdev_cfg {
/* association random number */
uint32_t assoc_rand_num;
/* network monitor enable flag */
uint8_t nw_monitor_enable :1,
/* flag to mark if lock network for tsfm */
tsfm_nw_lock :1,
/* role of last joined network, 1 is PCO role, 0 is STA role */
last_role :1,
/* preferred rf option, see RF_OPTION_XXX */
prefer_rf_option :2,
/* 3ps device gpio tx-rx switch phase, see PLC_PHASE_XXX */
gpio_trx_phase :2,
/* reserved for future */
rsvd :1;
/* preferred cco mac address, big endian */
uint8_t prefer_cco_addr[IOT_MAC_ADDR_LEN];
/* prefered sta mac address. big endian */
uint8_t prefer_sta_addr[IOT_MAC_ADDR_LEN];
/* preferred network id */
uint32_t prefer_nid :24,
/* preferred rf channel, see RF_CHANNEL_ID_XXX */
prefer_rf_channel :8;
#if HPLC_RF_DEV_SUPPORT
/* valid number in the rf scan table */
uint8_t rf_tbl_cnt;
/* total duration of rf channel scan table, unit is 1s */
uint32_t rf_scan_dur;
/* total duration of rf channel scan table when no network is found,
* unit is 1s
*/
uint32_t rf_scan_min_dur;
/* rf scan table */
iot_plc_rf_scan_t rf_scan_tbl[IOT_PLC_RF_SCAN_TBL_MAX];
#endif
/* valid number in the plc scan table */
uint8_t plc_tbl_cnt;
/* plc scan table */
plc_scan_band_t plc_scan_tbl[PLC_SCAN_BAND_MAX_CNT];
} cvg_vdev_sta_cfg_t;
/* vdev configurations */
typedef struct _cvg_vdev_cfg {
cvg_vdev_cmn_cfg_t cmn_cfg;
union {
cvg_vdev_sta_cfg_t vdev_sta;
cvg_vdev_cco_cfg_t vdev_cco;
} cfg;
} cvg_vdev_cfg_t;
/* pdev configurations */
typedef struct _cvg_pdev_cfg {
uint8_t vdev_cnt;
cvg_vdev_cfg_t vdev_array[CVG_MAX_VDEV_PER_PDEV];
} cvg_pdev_cfg_t;
/* global configurations */
typedef struct _cvg_cfg {
/* version info */
mme_ver_info_t ver_info;
/* vendor specific info */
mme_vendor_info_t vendor_info;
/* chip management id */
mme_chip_id_t chip_mm_id;
/* software reset count */
uint16_t sw_reset_cnt;
/* hardware reset count */
uint16_t hw_reset_cnt;
/* vendor mark */
uint16_t same_vendor_mark;
/* user type, see USER_TYPE_XXX */
uint8_t user_type;
/* number of physical device */
uint8_t pdev_cnt;
/* ntb offset between collected zc and real zc, negative offset means
* collected zc is earlier than real zc, unit is 0.04us
*/
int32_t zc_ntb_offset;
/* configuration of each physical device */
cvg_pdev_cfg_t pdev_array[CVG_MAX_PDEV];
/* pointer to read only PIB section */
iot_pib_r_cvg_real_cfg_t *pib_ro;
/* pointer to writable PIB section */
iot_pib_w_cvg_real_cfg_t *pib_rw;
} cvg_cfg_t;
/*
* @brief cvg_init - initialize cvg modules
* @param proto: config the protocol for cvg layer. see PLC_PROTO_TYPE_XXX
*
* @retval ERR_OK - for success case
* @retval otherwise - for failure case. see ERR_XXX
*/
uint32_t cvg_init(uint8_t proto);
/*
* @brief start vdev function extended version.
* @param id: vdev id to be started. The upper 4 bits is pdev array index,
* and the lower 4 bits is vdev array index.
* @param cfg: vdev config. default config initialized in cvg_init will be
* used for NULL case.
* @param reason: start up reason. see CVG_VDEV_START_XXX.
* @param force: flag to mark if restart required if vdev is already started.
*
* @retval 0 for success
* @retval non-zero for failure.
*/
uint32_t cvg_start_vdev_ext(uint8_t id, cvg_vdev_cfg_t* cfg, uint8_t reason,
uint8_t force_restart);
/*
* @brief start vdev. if vdev is already started, this request will
* be ignored.
* @param id: vdev id to be started. The upper 4 bits is pdev array index,
* and the lower 4 bits is vdev array index.
* @param cfg: vdev config. default config initialized in cvg_init will be
* used for NULL case.
* @param reason: start up reason. see CVG_VDEV_START_XXX.
*
* @retval 0 for success
* @retval non-zero for failure.
*/
uint32_t cvg_start_vdev(uint8_t id, cvg_vdev_cfg_t* cfg, uint8_t reason);
/* cvg_add_addr_into_wl - add mac address into while list table
* @id vdev id to be added. The upper 4 bits is pdev array index,
* and the lower 4 bits is vdev array index.
* @cnt number of mac address to be added
* @addr mac address array
* @phase power line phase of sta device working
*
* return:
* 0 -- for success case
* otherwise -- error code
*/
uint32_t cvg_add_addr_into_wl(uint8_t id, uint32_t cnt,
uint8_t addr[][IOT_MAC_ADDR_LEN], uint8_t phase);
/* cvg_add_addr_into_bl - add mac address into black list table
* @id vdev id to be added. The upper 4 bits is pdev array index,
* and the lower 4 bits is vdev array index.
* @cnt number of mac address to be added
* @addr mac address array
*
* return:
* 0 -- for success case
* otherwise -- error code
*/
uint32_t cvg_add_addr_into_bl(uint8_t id, uint32_t cnt,
uint8_t addr[][IOT_MAC_ADDR_LEN]);
/* cvg_rm_addr_from_wl - remove mac address from while list table
* @id vdev id to be removed. The upper 4 bits is pdev array index,
* and the lower 4 bits is vdev array index.
* @cnt number of mac address to be removed
* @addr mac address array
*
* return:
* 0 -- for success case
* otherwise -- error code
*/
uint32_t cvg_rm_addr_from_wl(uint8_t id, uint32_t cnt,
uint8_t addr[][IOT_MAC_ADDR_LEN]);
/* cvg_rm_all_addr_from_wl - remove all mac address from while list table
* @id vdev id to be removed. The upper 4 bits is pdev array index,
* and the lower 4 bits is vdev array index.
*
* return:
* 0 -- for success case
* otherwise -- error code
*/
uint32_t cvg_rm_all_addr_from_wl(uint8_t id);
/* cvg_rm_addr_from_bl - remove mac address from black list table
* @id vdev id to be removed. The upper 4 bits is pdev array index,
* and the lower 4 bits is vdev array index.
* @cnt number of mac address to be removed
* @addr mac address array
*
* return:
* 0 -- for success case
* otherwise -- error code
*/
uint32_t cvg_rm_addr_from_bl(uint8_t id, uint32_t cnt,
uint8_t addr[][IOT_MAC_ADDR_LEN]);
/* cvg_rm_all_addr_from_bl - remove all mac address from black list table
* @id vdev id to be removed. The upper 4 bits is pdev array index,
* and the lower 4 bits is vdev array index.
*
* return:
* 0 -- for success case
* otherwise -- error code
*/
uint32_t cvg_rm_all_addr_from_bl(uint8_t id);
/* cvg_set_wl_state - enable or disable whitelist.
* all whitelist check passed with disabled
* @id: vdev id to be removed. The upper 4 bits is pdev array index,
* and the lower 4 bits is vdev array index.
* @enable: non-zero to enable whitelist. 0 to disable whitelist.
*/
void cvg_set_wl_state(uint8_t id, uint8_t enable);
/* cvg_set_wl_state - enable or disable blacklist.
* all blacklist check passed with disabled
* @id: vdev id to be removed. The upper 4 bits is pdev array index,
* and the lower 4 bits is vdev array index.
* @enable: non-zero to enable blacklist. 0 to disable blacklist.
*/
void cvg_set_bl_state(uint8_t id, uint8_t enable);
/* cvg_query_addr_from_wl - query mac address from while list table
* @id vdev id to be queried. The upper 4 bits is pdev array index,
* and the lower 4 bits is vdev array index.
* @start start index to be queried.
* @cnt number of mac address to be queried.
* this will be set to number of queried mac addres for return.
* @addr queried mac address array for return
*
* return:
* 0 -- for success case
* otherwise -- error code
*/
uint32_t cvg_query_addr_from_wl(uint8_t id, uint32_t start, uint32_t *cnt,
uint8_t addr[][IOT_MAC_ADDR_LEN]);
/* cvg_query_wl_ext - query whitelist extend information
* @id vdev id to be queried. The upper 4 bits is pdev array index,
* and the lower 4 bits is vdev array index.
* @start start index to be queried.
* @cnt number of whitelist to be queried.
* this will be set to number of queried whitelist for return.
* @wl queried whitelist array for return
*
* return:
* 0 -- for success case
* otherwise -- error code
*/
uint32_t cvg_query_wl_ext(uint8_t id, uint32_t start, uint32_t *cnt,
iot_plc_wl_ext_t wl[]);
/* cvg_query_addr_from_bl - query mac address from black list table
* @id vdev id to be queried. The upper 4 bits is pdev array index,
* and the lower 4 bits is vdev array index.
* @start start index to be queried.
* @cnt number of mac address to be queried.
* this will be set to number of queried mac addres for return.
* @addr queried mac address array for return
*
* return:
* 0 -- for success case
* otherwise -- error code
*/
uint32_t cvg_query_addr_from_bl(uint8_t id, uint32_t start, uint32_t *cnt,
uint8_t addr[][IOT_MAC_ADDR_LEN]);
/**
* @brief cvg_set_wl_joined_done() - set whitelist nodes joined network status.
* @param id: vdev id to be queried. The upper 4 bits is pdev array index,
* and the lower 4 bits is vdev array index.
* @param wl_joined_done: 1 - whitelist nodes join network completed.
* 0 - whitelist nodes join network not completed.
*/
void cvg_set_wl_joined_done(uint8_t id, uint8_t wl_joined_done);
/**
* @brief cvg_set_freq_band() - set freq band.
* @param id: vdev id to be set. The upper 4 bits is pdev array
* index, and the lower 4 bits is vdev array index.
* @param freq_band_id: new frequency band ID to be set.
* @retval: 0 -- for success case
* @retval: otherwise -- error code
*/
uint32_t cvg_set_freq_band(uint8_t id, uint8_t freq_band_id);
/**
* @brief cvg_get_freq_band() - gets the currently used frequency band ID.
* @param id: vdev id to be queried. The upper 4 bits is pdev array index,
* and the lower 4 bits is vdev array index.
* @retval: currently used frequency band ID.
*/
uint8_t cvg_get_freq_band(uint8_t id);
/**
* @brief cvg_set_rf() - set rf option channel and option.
* @param id: vdev id to be set. The upper 4 bits is pdev array
* index, and the lower 4 bits is vdev array index.
* @param rf_option: new rf option to be set, see RF_OPTION_XXX
* @param rf_channel: new rf channel to be set.
* @retval: 0 -- for success case
* @retval: otherwise -- error code
*/
uint32_t cvg_set_rf(uint8_t id, uint8_t rf_option, uint8_t rf_channel);
/**
* @brief cvg_set_rf_ext() - set rf option channel, option and rf cod flag.
* @param id: vdev id to be set. The upper 4 bits is pdev array
* index, and the lower 4 bits is vdev array index.
* @param rf_option: new rf option to be set, see RF_OPTION_XXX
* @param rf_channel: new rf channel to be set.
* @param rf_cod: pointer to coordination flag.
* @param is_from_inner: flag to mark if rf channel change is initiated
* by internal module.
* @retval: 0 -- for success case
* @retval: otherwise -- error code
*/
uint32_t cvg_set_rf_ext(uint8_t id, uint8_t rf_option, uint8_t rf_channel,
uint8_t *rf_cod, uint8_t is_from_inner);
/**
* @brief cvg_get_rf() - gets the currently used rf channel and option.
* @param id: vdev id to be queried. The upper 4 bits is pdev array index,
* and the lower 4 bits is vdev array index.
* @param option: returns the rf option value currently used, see
* RF_OPRION_XXX.
* @param channel: returns the rf channel value currently used, see
* RF_CHANNEL_ID_XXX.
*/
void cvg_get_rf(uint8_t id, uint8_t *option, uint8_t *channel);
/**
* @brief cvg_get_rf_ext() - gets the currently used rf channel, option and
* rf coordination flag.
* @param id: vdev id to be queried. The upper 4 bits is pdev array index,
* and the lower 4 bits is vdev array index.
* @param option: returns the rf option value currently used, see
* RF_OPRION_XXX.
* @param channel: returns the rf channel value currently used, see
* RF_CHANNEL_ID_XXX.
* @param rf_cod: returns the flag of rf channel coordination enable
*/
void cvg_get_rf_ext(uint8_t id, uint8_t *option, uint8_t *channel,
uint8_t *rf_cod);
/**
* @brief set hplc and rf tx power cap
* @param id: vdev id to be set. The upper 4 bits is pdev array
* index, and the lower 4 bits is vdev array index.
* @param hplc_power: pointer to hplc tx power cap to be set. unit is 1dbuv.
* @param rf_power: pointer to rf tx power cap to be set. unit is 1dbm.
* @return:
* ERR_OK -- for success case
* otherwise -- error code
*/
uint32_t cvg_set_tx_power_cap(uint8_t id, uint8_t *hplc_power,
int8_t *rf_power);
/**
* @brief gets the currently used rf tx power cap.
* @param id: vdev id to be queried. The upper 4 bits is pdev array index,
* and the lower 4 bits is vdev array index.
* @retval: rf tx power cap. unit is 1dbm.
*/
int8_t cvg_get_rf_tx_power_cap(uint8_t id);
/**
* @brief set rf scan table
* @param id: vdev id to be set. The upper 4 bits is pdev array
* index, and the lower 4 bits is vdev array index.
* @param rf_scan_tbl: pointer to rf scan table.
* @param rf_cnt: count of valid rf entry in rf scan table.
* @param set_mac: flag to mark if rf scan table set to mac, this parameter
* is valid only for sta device.
* @return:
* 0 -- for success case
* otherwise -- error code
*/
uint32_t cvg_set_rf_scan_tbl(uint8_t id, iot_plc_rf_scan_t *rf_scan_tbl,
uint8_t rf_cnt, uint8_t set_mac);
/**
* @brief set beacon data. beacon data can be broadcast to whole network in
* each beacon period.
* @param id: vdev id to be set. The upper 4 bits is pdev array
* index, and the lower 4 bits is vdev array index.
* @param data: data to be carried in each beacon
* @param len: length of the data
*
* @return 0 - for success case
* otherwise - error code. see ERR_XXX
*/
uint32_t cvg_set_beacon_data(uint8_t id, uint8_t *data, uint8_t len);
#ifdef __cplusplus
}
#endif
#endif /* CVG_API_H */