Compare commits
45 Commits
master
...
release/v2
Author | SHA1 | Date |
---|---|---|
Ivan Grokhotkov | bef9896305 | |
He Yin Ling | 18dbdd46f4 | |
Ivan Grokhotkov | 4184968469 | |
Ivan Grokhotkov | 024ef51d1a | |
island | 4d9778e208 | |
Ivan Grokhotkov | 6181af2a0b | |
He Yin Ling | abf0cd8421 | |
Ivan Grokhotkov | 7a83c87c44 | |
island | 6ad86f0d67 | |
Liu Zhi Fu | fddebe4bcc | |
Liu Zhi Fu | 2102acf266 | |
Liu Zhi Fu | a4ac9bf80b | |
Liu Zhi Fu | 6e2601f389 | |
Ivan Grokhotkov | ea48f43f87 | |
Ivan Grokhotkov | 1b0b34247a | |
Tian Hao | 4aaa453b31 | |
Ivan Grokhotkov | fe69377782 | |
island | 1c9d8744ab | |
Ivan Grokhotkov | 7db3370e20 | |
Angus Gratton | eece22d075 | |
Angus Gratton | 2cc668bbb1 | |
wangmengyang | ad4a1b600a | |
Tian Hao | 877b407c8c | |
me-no-dev | 5850f423d5 | |
island | ea74033d1e | |
Angus Gratton | 7cd1e0ef4b | |
Angus Gratton | f72888544e | |
Tian Hao | a513ac4dec | |
Angus Gratton | b337b20270 | |
Angus Gratton | 8ab96b13af | |
Angus Gratton | 50f414f54c | |
Angus Gratton | 0dfef8c16c | |
Derek Gregory | 6bb1367fe5 | |
lucashutchinson | a286846095 | |
Angus Gratton | 2b2dd845ae | |
Daniel Bovensiepen | b9f9e681ba | |
Angus Gratton | 3429241e1a | |
Neil Kolban | 455a7784a9 | |
Anne Jan Brouwer | 7d9a20e714 | |
Angus Gratton | a6980fce4c | |
alarruskain | 4bd41d4082 | |
gbcwbz | 3302a38432 | |
Daniel Campora | 82ef2b9485 | |
rudi ;-) | de461671aa | |
rudi ;-) | aa2f5e4ae5 |
|
@ -14,10 +14,11 @@ before_script:
|
|||
- chmod 600 ~/.ssh/id_rsa
|
||||
- echo -e "Host gitlab.espressif.cn\n\tStrictHostKeyChecking no\n" >> ~/.ssh/config
|
||||
|
||||
# if testing master branch, use github wifi and bt libs.
|
||||
# if testing other branches, use gitlab wifi and bt libs (as maybe changes aren't merged to master yet)
|
||||
- test "${CI_BUILD_REF_NAME}" = "master" || sed -i "s%https://github.com/espressif/esp32-wifi-lib%${GITLAB_SSH_SERVER}/idf/esp32-wifi-lib%" .gitmodules
|
||||
- test "${CI_BUILD_REF_NAME}" = "master" || sed -i "s%https://github.com/espressif/esp32-bt-lib%${GITLAB_SSH_SERVER}/idf/esp32-bt-lib%" .gitmodules
|
||||
# Set IS_PRIVATE or IS_PUBLIC depending on if our branch is public or not
|
||||
#
|
||||
# (the same regular expressions are used to set these are used in 'only:' sections below
|
||||
- source make/configure_ci_environment.sh
|
||||
|
||||
# fetch all submodules
|
||||
- git submodule update --init --recursive
|
||||
|
||||
|
@ -133,7 +134,7 @@ build_docs:
|
|||
- cd docs
|
||||
- doxygen
|
||||
# If not building master branch, and there are Doxygen warnings, print them and bail out
|
||||
- test "${CI_BUILD_REF_NAME}" = "master" || test $(cat doxygen-warning-log.txt | wc -l) -eq 0 || ( echo "Doxygen pass had some warnings:" && cat doxygen-warning-log.txt && false )
|
||||
- test -n $IS_PRIVATE && test $(cat doxygen-warning-log.txt | wc -l) -eq 0 || ( echo "Doxygen pass had some warnings:" && cat doxygen-warning-log.txt && false )
|
||||
- make gh-linkcheck
|
||||
- make html
|
||||
artifacts:
|
||||
|
@ -159,6 +160,7 @@ test_build_system:
|
|||
variables:
|
||||
IDF_PATH: "$CI_PROJECT_DIR"
|
||||
script:
|
||||
- ./make/test_configure_ci_environment.sh
|
||||
- ./make/test_build_system.sh
|
||||
|
||||
test_report:
|
||||
|
@ -167,7 +169,8 @@ test_report:
|
|||
only:
|
||||
- master
|
||||
- triggers
|
||||
- /^release\/v.*$/
|
||||
- /^release\/v/
|
||||
- /^v\d+\.\d+(\.\d+)?($|-)/
|
||||
tags:
|
||||
- report
|
||||
variables:
|
||||
|
@ -217,13 +220,15 @@ push_master_to_github:
|
|||
stage: deploy
|
||||
only:
|
||||
- master
|
||||
- /^release\/v.*$/
|
||||
- /^release\/v/
|
||||
- /^v\d+\.\d+(\.\d+)?($|-)/
|
||||
tags:
|
||||
- deploy
|
||||
when: on_success
|
||||
image: espressif/esp32-ci-env
|
||||
variables:
|
||||
GIT_STRATEGY: clone
|
||||
GITHUB_PUSH_REFS: refs/remotes/origin/release refs/remotes/origin/master
|
||||
script:
|
||||
- mkdir -p ~/.ssh
|
||||
- chmod 700 ~/.ssh
|
||||
|
@ -232,7 +237,14 @@ push_master_to_github:
|
|||
- chmod 600 ~/.ssh/id_rsa
|
||||
- echo -e "Host github.com\n\tStrictHostKeyChecking no\n" >> ~/.ssh/config
|
||||
- git remote add github git@github.com:espressif/esp-idf.git
|
||||
- git push --follow-tags github HEAD:master
|
||||
# What the next line of script does: goes through the list of refs for all branches we push to github,
|
||||
# generates a snippet of shell which is evaluated. The snippet checks CI_BUILD_REF against the SHA
|
||||
# (aka objectname) at tip of each branch, and if any SHAs match then it checks out the local branch
|
||||
# and then pushes that ref to a corresponding github branch
|
||||
#
|
||||
# NB: In gitlab 9.x, CI_BUILD_REF was deprecated. New name is CI_COMMIT_REF. If below command suddenly
|
||||
# generates bash syntax errors, this is probably why.
|
||||
- eval $(git for-each-ref --shell bash --format 'if [ $CI_BUILD_REF == %(objectname) ]; then git checkout -B %(refname:strip=3); git push --follow-tags github %(refname:strip=3); fi;' $GITHUB_PUSH_REFS)
|
||||
|
||||
|
||||
deploy_docs:
|
||||
|
@ -241,7 +253,8 @@ deploy_docs:
|
|||
stage: deploy
|
||||
only:
|
||||
- master
|
||||
- /^release\/v.*$/
|
||||
- /^release\/v/
|
||||
- /^v\d+\.\d+(\.\d+)?($|-)/
|
||||
- triggers
|
||||
tags:
|
||||
- deploy
|
||||
|
@ -288,7 +301,8 @@ check_doc_links:
|
|||
when: on_success
|
||||
only:
|
||||
- master
|
||||
- /^release\/v.*$/
|
||||
- /^release\/v/
|
||||
- /^v\d+\.\d+(\.\d+)?($|-)/
|
||||
- triggers
|
||||
allow_failure: true
|
||||
|
||||
|
@ -323,6 +337,7 @@ check_doc_links:
|
|||
# clone test bench
|
||||
- git clone $GITLAB_SSH_SERVER/yinling/auto_test_script.git
|
||||
- cd auto_test_script
|
||||
- git checkout ${CI_COMMIT_REF_NAME} || echo "Using default branch..."
|
||||
# run test
|
||||
- python CIRunner.py -l $LOG_PATH -c $CONFIG_FILE -e $LOCAL_ENV_CONFIG_PATH -t $TEST_CASE_FILE_PATH -m $MODULE_UPDATE_FILE bin_path $APP_NAME $BIN_PATH
|
||||
|
||||
|
@ -350,6 +365,7 @@ check_doc_links:
|
|||
# clone test bench
|
||||
- git clone $GITLAB_SSH_SERVER/yinling/auto_test_script.git
|
||||
- cd auto_test_script
|
||||
- git checkout ${CI_COMMIT_REF_NAME} || echo "Using default branch..."
|
||||
# run test
|
||||
- python CIRunner.py -l $LOG_PATH -c $CONFIG_FILE -e $LOCAL_ENV_CONFIG_PATH -t $TEST_CASE_FILE_PATH -m $MODULE_UPDATE_FILE bin_path $APP_NAME $BIN_PATH
|
||||
|
||||
|
@ -366,7 +382,7 @@ check_doc_links:
|
|||
APP_NAME: "ut"
|
||||
TEST_CASE_FILE_PATH: "$CI_PROJECT_DIR/components/idf_test/unit_test"
|
||||
MODULE_UPDATE_FILE: "$CI_PROJECT_DIR/tools/unit-test-app/ModuleDefinition.yml"
|
||||
|
||||
|
||||
dependencies:
|
||||
- build_esp_idf_tests
|
||||
|
||||
|
|
|
@ -19,13 +19,13 @@
|
|||
#include "bt.h"
|
||||
#include "future.h"
|
||||
|
||||
static bool esp_already_enable = false;
|
||||
static bool esp_already_init = false;
|
||||
static bool bd_already_enable = false;
|
||||
static bool bd_already_init = false;
|
||||
|
||||
esp_bluedroid_status_t esp_bluedroid_get_status(void)
|
||||
{
|
||||
if (esp_already_init) {
|
||||
if (esp_already_enable) {
|
||||
if (bd_already_init) {
|
||||
if (bd_already_enable) {
|
||||
return ESP_BLUEDROID_STATUS_ENABLED;
|
||||
} else {
|
||||
return ESP_BLUEDROID_STATUS_INITIALIZED;
|
||||
|
@ -40,15 +40,20 @@ esp_err_t esp_bluedroid_enable(void)
|
|||
btc_msg_t msg;
|
||||
future_t **future_p;
|
||||
|
||||
if (esp_already_enable) {
|
||||
LOG_ERROR("%s already enable\n", __func__);
|
||||
if (!bd_already_init) {
|
||||
LOG_ERROR("Bludroid not initialised\n");
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
if (bd_already_enable) {
|
||||
LOG_ERROR("Bluedroid already enabled\n");
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
future_p = btc_main_get_future_p(BTC_MAIN_ENABLE_FUTURE);
|
||||
*future_p = future_new();
|
||||
if (*future_p == NULL) {
|
||||
LOG_ERROR("%s failed\n", __func__);
|
||||
LOG_ERROR("Bluedroid enable failed\n");
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
|
||||
|
@ -58,11 +63,11 @@ esp_err_t esp_bluedroid_enable(void)
|
|||
btc_transfer_context(&msg, NULL, 0, NULL);
|
||||
|
||||
if (future_await(*future_p) == FUTURE_FAIL) {
|
||||
LOG_ERROR("%s failed\n", __func__);
|
||||
LOG_ERROR("Bluedroid enable failed\n");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
esp_already_enable = true;
|
||||
bd_already_enable = true;
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
@ -72,15 +77,15 @@ esp_err_t esp_bluedroid_disable(void)
|
|||
btc_msg_t msg;
|
||||
future_t **future_p;
|
||||
|
||||
if (!esp_already_enable) {
|
||||
LOG_ERROR("%s already disable\n", __func__);
|
||||
if (!bd_already_enable) {
|
||||
LOG_ERROR("Bluedroid already disabled\n");
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
future_p = btc_main_get_future_p(BTC_MAIN_DISABLE_FUTURE);
|
||||
*future_p = future_new();
|
||||
if (*future_p == NULL) {
|
||||
LOG_ERROR("%s failed\n", __func__);
|
||||
LOG_ERROR("Bluedroid disable failed\n");
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
|
||||
|
@ -90,11 +95,11 @@ esp_err_t esp_bluedroid_disable(void)
|
|||
btc_transfer_context(&msg, NULL, 0, NULL);
|
||||
|
||||
if (future_await(*future_p) == FUTURE_FAIL) {
|
||||
LOG_ERROR("%s failed\n", __func__);
|
||||
LOG_ERROR("Bluedroid disable failed\n");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
esp_already_enable = false;
|
||||
bd_already_enable = false;
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
@ -105,19 +110,19 @@ esp_err_t esp_bluedroid_init(void)
|
|||
future_t **future_p;
|
||||
|
||||
if (esp_bt_controller_get_status() != ESP_BT_CONTROLLER_STATUS_ENABLED) {
|
||||
LOG_ERROR("%s conroller not init\n", __func__);
|
||||
LOG_ERROR("Conroller not initialised\n");
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
if (esp_already_init) {
|
||||
LOG_ERROR("%s already init\n", __func__);
|
||||
if (bd_already_init) {
|
||||
LOG_ERROR("Bluedroid already initialised\n");
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
future_p = btc_main_get_future_p(BTC_MAIN_INIT_FUTURE);
|
||||
*future_p = future_new();
|
||||
if (*future_p == NULL) {
|
||||
LOG_ERROR("%s failed\n", __func__);
|
||||
LOG_ERROR("Bluedroid initialise failed\n");
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
|
||||
|
@ -129,11 +134,11 @@ esp_err_t esp_bluedroid_init(void)
|
|||
btc_transfer_context(&msg, NULL, 0, NULL);
|
||||
|
||||
if (future_await(*future_p) == FUTURE_FAIL) {
|
||||
LOG_ERROR("%s failed\n", __func__);
|
||||
LOG_ERROR("Bluedroid initialise failed\n");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
esp_already_init = true;
|
||||
bd_already_init = true;
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
@ -144,15 +149,20 @@ esp_err_t esp_bluedroid_deinit(void)
|
|||
btc_msg_t msg;
|
||||
future_t **future_p;
|
||||
|
||||
if (!esp_already_init) {
|
||||
LOG_ERROR("%s already deinit\n", __func__);
|
||||
if (!bd_already_init) {
|
||||
LOG_ERROR("Bluedroid already de-initialised\n");
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
if (bd_already_enable) {
|
||||
LOG_ERROR("Bludroid already enabled, do disable first\n");
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
future_p = btc_main_get_future_p(BTC_MAIN_DEINIT_FUTURE);
|
||||
*future_p = future_new();
|
||||
if (*future_p == NULL) {
|
||||
LOG_ERROR("%s failed\n", __func__);
|
||||
LOG_ERROR("Bluedroid de-initialise failed\n");
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
|
||||
|
@ -162,15 +172,14 @@ esp_err_t esp_bluedroid_deinit(void)
|
|||
btc_transfer_context(&msg, NULL, 0, NULL);
|
||||
|
||||
if (future_await(*future_p) == FUTURE_FAIL) {
|
||||
LOG_ERROR("%s failed\n", __func__);
|
||||
LOG_ERROR("Bluedroid de-initialise failed\n");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
btc_deinit();
|
||||
|
||||
esp_already_init = false;
|
||||
bd_already_init = false;
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -142,6 +142,27 @@ esp_err_t esp_ble_gatts_add_char(uint16_t service_handle, esp_bt_uuid_t *char_
|
|||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
/* parameter validation check */
|
||||
if ((control != NULL) && (control->auto_rsp == GATT_STACK_RSP)){
|
||||
if (char_val == NULL){
|
||||
LOG_ERROR("Error in %s, line=%d, for stack respond attribute, char_val should not be NULL here\n",\
|
||||
__func__, __LINE__);
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
} else if (char_val->attr_max_len == 0){
|
||||
LOG_ERROR("Error in %s, line=%d, for stack respond attribute, attribute max length should not be 0\n",\
|
||||
__func__, __LINE__);
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
}
|
||||
|
||||
if (char_val != NULL){
|
||||
if (char_val->attr_len > char_val->attr_max_len){
|
||||
LOG_ERROR("Error in %s, line=%d,attribute actual length (%d) should not be larger than max length (%d)\n",\
|
||||
__func__, __LINE__, char_val->attr_len, char_val->attr_max_len);
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
}
|
||||
|
||||
memset(&arg, 0, sizeof(btc_ble_gatts_args_t));
|
||||
msg.sig = BTC_SIG_API_CALL;
|
||||
msg.pid = BTC_PID_GATTS;
|
||||
|
@ -175,6 +196,29 @@ esp_err_t esp_ble_gatts_add_char_descr (uint16_t service_handle,
|
|||
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
/* parameter validation check */
|
||||
if ((control != NULL) && (control->auto_rsp == GATT_STACK_RSP)){
|
||||
if (char_descr_val == NULL){
|
||||
LOG_ERROR("Error in %s, line=%d, for stack respond attribute, char_descr_val should not be NULL here\n",\
|
||||
__func__, __LINE__);
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
else if (char_descr_val->attr_max_len == 0){
|
||||
LOG_ERROR("Error in %s, line=%d, for stack respond attribute, attribute max length should not be 0\n",\
|
||||
__func__, __LINE__);
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
}
|
||||
|
||||
if (char_descr_val != NULL){
|
||||
if (char_descr_val->attr_len > char_descr_val->attr_max_len){
|
||||
LOG_ERROR("Error in %s, line=%d,attribute actual length (%d) should not be larger than max length (%d)\n",\
|
||||
__func__, __LINE__, char_descr_val->attr_len, char_descr_val->attr_max_len);
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
memset(&arg, 0, sizeof(btc_ble_gatts_args_t));
|
||||
msg.sig = BTC_SIG_API_CALL;
|
||||
|
|
|
@ -268,6 +268,7 @@ static void blufi_profile_cb(tBTA_GATTS_EVT event, tBTA_GATTS *p_data)
|
|||
blufi_env.conn_id = p_data->conn.conn_id;
|
||||
blufi_env.is_connected = false;
|
||||
blufi_env.recv_seq = blufi_env.send_seq = 0;
|
||||
blufi_env.sec_mode = 0x0;
|
||||
|
||||
msg.sig = BTC_SIG_API_CB;
|
||||
msg.pid = BTC_PID_BLUFI;
|
||||
|
|
|
@ -476,8 +476,7 @@ static void btc_search_callback(tBTA_DM_SEARCH_EVT event, tBTA_DM_SEARCH *p_data
|
|||
param.scan_rst.ble_addr_type = p_data->inq_res.ble_addr_type;
|
||||
param.scan_rst.ble_evt_type = p_data->inq_res.ble_evt_type;
|
||||
param.scan_rst.flag = p_data->inq_res.flag;
|
||||
memcpy(param.scan_rst.ble_adv, p_data->inq_res.p_eir,
|
||||
ESP_BLE_ADV_DATA_LEN_MAX);
|
||||
memcpy(param.scan_rst.ble_adv, p_data->inq_res.p_eir, sizeof(param.scan_rst.ble_adv));
|
||||
break;
|
||||
}
|
||||
case BTA_DM_INQ_CMPL_EVT: {
|
||||
|
|
|
@ -166,6 +166,30 @@ void btc_gatts_arg_deep_free(btc_msg_t *msg)
|
|||
}
|
||||
break;
|
||||
}
|
||||
case BTC_GATTS_ACT_ADD_CHAR:{
|
||||
if (arg->add_char.char_val.attr_value != NULL) {
|
||||
GKI_freebuf(arg->add_char.char_val.attr_value);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case BTC_GATTS_ACT_ADD_CHAR_DESCR:{
|
||||
if (arg->add_descr.descr_val.attr_value != NULL){
|
||||
GKI_freebuf(arg->add_descr.descr_val.attr_value);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case BTC_GATTS_ACT_CREATE_ATTR_TAB:{
|
||||
if (arg->create_attr_tab.gatts_attr_db != NULL){
|
||||
GKI_freebuf(arg->create_attr_tab.gatts_attr_db);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case BTC_GATTS_ACT_SET_ATTR_VALUE:{
|
||||
if (arg->set_attr_val.value != NULL){
|
||||
GKI_freebuf(arg->set_attr_val.value);
|
||||
}
|
||||
}
|
||||
|
||||
default:
|
||||
LOG_DEBUG("%s Unhandled deep free %d\n", __func__, msg->act);
|
||||
break;
|
||||
|
@ -182,13 +206,16 @@ static void btc_gatts_act_create_attr_tab(esp_gatts_attr_db_t *gatts_attr_db,
|
|||
future_t *future_p;
|
||||
esp_ble_gatts_cb_param_t param;
|
||||
|
||||
//set the attribute table create service flag to ture
|
||||
//set the attribute table create service flag to true
|
||||
btc_creat_tab_env.is_tab_creat_svc = true;
|
||||
btc_creat_tab_env.num_handle = max_nb_attr;
|
||||
for(int i = 0; i < max_nb_attr; i++){
|
||||
if(gatts_attr_db[i].att_desc.uuid_length== ESP_UUID_LEN_16){
|
||||
uuid = (gatts_attr_db[i].att_desc.uuid_p[1] << 8) + (gatts_attr_db[i].att_desc.uuid_p[0]);
|
||||
}
|
||||
else{
|
||||
continue;
|
||||
}
|
||||
future_p = future_new();
|
||||
if (future_p == NULL) {
|
||||
LOG_ERROR("%s failed:no mem\n", __func__);
|
||||
|
|
|
@ -43,25 +43,27 @@ enum {
|
|||
SIG_BTIF_WORK = 0xff
|
||||
};
|
||||
|
||||
#define HCI_HOST_TASK_STACK_SIZE 1500
|
||||
#define HCI_HOST_TASK_PRIO (configMAX_PRIORITIES - 2)
|
||||
#define HCI_HOST_TASK_NAME "hciHostT"
|
||||
#define HCI_HOST_QUEUE_NUM 40
|
||||
|
||||
#define HCI_H4_TASK_STACK_SIZE 1500
|
||||
#define HCI_H4_TASK_PRIO (configMAX_PRIORITIES - 3)
|
||||
#define HCI_H4_TASK_NAME "hciH4T"
|
||||
#define HCI_H4_QUEUE_NUM 60
|
||||
#define BT_TASK_EXTRA_STACK_SIZE 512
|
||||
#define HCI_HOST_TASK_STACK_SIZE (2048 + BT_TASK_EXTRA_STACK_SIZE)
|
||||
#define HCI_HOST_TASK_PRIO (configMAX_PRIORITIES - 2)
|
||||
#define HCI_HOST_TASK_NAME "hciHostT"
|
||||
#define HCI_HOST_QUEUE_NUM 40
|
||||
|
||||
#define BTU_TASK_STACK_SIZE 4096
|
||||
#define BTU_TASK_PRIO (configMAX_PRIORITIES - 4)
|
||||
#define BTU_TASK_NAME "btuT"
|
||||
#define BTU_QUEUE_NUM 50
|
||||
#define HCI_H4_TASK_STACK_SIZE (2048 + BT_TASK_EXTRA_STACK_SIZE)
|
||||
#define HCI_H4_TASK_PRIO (configMAX_PRIORITIES - 3)
|
||||
#define HCI_H4_TASK_NAME "hciH4T"
|
||||
#define HCI_H4_QUEUE_NUM 60
|
||||
|
||||
#define BTC_TASK_STACK_SIZE CONFIG_BTC_TASK_STACK_SIZE //by menuconfig
|
||||
#define BTC_TASK_NAME "btcT"
|
||||
#define BTC_TASK_PRIO (configMAX_PRIORITIES - 5)
|
||||
#define BTC_TASK_QUEUE_NUM 20
|
||||
#define BTU_TASK_STACK_SIZE (3584 + BT_TASK_EXTRA_STACK_SIZE)
|
||||
#define BTU_TASK_PRIO (configMAX_PRIORITIES - 4)
|
||||
#define BTU_TASK_NAME "btuT"
|
||||
#define BTU_QUEUE_NUM 50
|
||||
|
||||
#define BTC_TASK_STACK_SIZE (CONFIG_BTC_TASK_STACK_SIZE + BT_TASK_EXTRA_STACK_SIZE) //by menuconfig
|
||||
#define BTC_TASK_NAME "btcT"
|
||||
#define BTC_TASK_PRIO (configMAX_PRIORITIES - 5)
|
||||
#define BTC_TASK_QUEUE_NUM 60
|
||||
|
||||
void btu_task_post(uint32_t sig);
|
||||
void hci_host_task_post(void);
|
||||
|
|
|
@ -214,6 +214,7 @@ UINT16 GATTS_CreateService (tGATT_IF gatt_if, tBT_UUID *p_svc_uuid,
|
|||
|
||||
if (p_list) {
|
||||
gatt_remove_an_item_from_list(p_list_info, p_list);
|
||||
gatt_free_attr_value_buffer(p_list);
|
||||
gatt_free_hdl_buffer(p_list);
|
||||
}
|
||||
return (0);
|
||||
|
@ -227,6 +228,7 @@ UINT16 GATTS_CreateService (tGATT_IF gatt_if, tBT_UUID *p_svc_uuid,
|
|||
GATT_TRACE_ERROR ("GATTS_ReserveHandles: service DB initialization failed\n");
|
||||
if (p_list) {
|
||||
gatt_remove_an_item_from_list(p_list_info, p_list);
|
||||
gatt_free_attr_value_buffer(p_list);
|
||||
gatt_free_hdl_buffer(p_list);
|
||||
}
|
||||
|
||||
|
@ -413,6 +415,7 @@ BOOLEAN GATTS_DeleteService (tGATT_IF gatt_if, tBT_UUID *p_svc_uuid, UINT16 svc_
|
|||
}
|
||||
|
||||
gatt_remove_an_item_from_list(p_list_info, p_list);
|
||||
gatt_free_attr_value_buffer(p_list);
|
||||
gatt_free_hdl_buffer(p_list);
|
||||
|
||||
return (TRUE);
|
||||
|
|
|
@ -268,14 +268,21 @@ static tGATT_STATUS read_attr_value (void *p_attr,
|
|||
status = GATT_SUCCESS;
|
||||
}
|
||||
} else { /* characteristic description or characteristic value */
|
||||
|
||||
if (p_attr16->control.auto_rsp == GATT_RSP_BY_STACK) {
|
||||
if (p_attr16->p_value != NULL && p_attr16->p_value->attr_val.attr_val != NULL) {
|
||||
uint8_t *value = p_attr16->p_value->attr_val.attr_val + offset;
|
||||
len = (mtu >= p_attr16->p_value->attr_val.attr_len) ? (p_attr16->p_value->attr_val.attr_len) : mtu;
|
||||
ARRAY_TO_STREAM(p, value, len);
|
||||
if (p_attr16->p_value == NULL || p_attr16->p_value->attr_val.attr_val == NULL) {
|
||||
status = GATT_ESP_ERROR;
|
||||
}
|
||||
else if (offset > p_attr16->p_value->attr_val.attr_len){
|
||||
/*if offset equal to max_len, should respond with zero byte value
|
||||
//if offset is greater than max_len, should respond with an error*/
|
||||
status = GATT_INVALID_OFFSET;
|
||||
} else {
|
||||
UINT8 *value = (UINT8 *)(p_attr16->p_value->attr_val.attr_val) + offset;
|
||||
UINT16 len_left = p_attr16->p_value->attr_val.attr_len - offset;
|
||||
len = (mtu >= len_left) ? (len_left) : mtu;
|
||||
ARRAY_TO_STREAM(p, value, len);
|
||||
status = GATT_STACK_RSP;
|
||||
}
|
||||
status = GATT_STACK_RSP;
|
||||
|
||||
} else {
|
||||
status = GATT_PENDING;
|
||||
|
@ -463,6 +470,27 @@ UINT16 gatts_add_characteristic (tGATT_SVC_DB *p_db, tGATT_PERM perm,
|
|||
tBT_UUID uuid = {LEN_UUID_16, {GATT_UUID_CHAR_DECLARE}};
|
||||
|
||||
GATT_TRACE_DEBUG("gatts_add_characteristic perm=0x%0x property=0x%0x\n", perm, property);
|
||||
/* parameter validation check */
|
||||
if ((control != NULL) && (control->auto_rsp == GATT_STACK_RSP)){
|
||||
if (attr_val == NULL){
|
||||
GATT_TRACE_ERROR("Error in %s, line=%d, for stack respond attribute, attr_val should not be NULL here\n",\
|
||||
__func__, __LINE__);
|
||||
return 0;
|
||||
} else if (attr_val->attr_max_len == 0){
|
||||
GATT_TRACE_ERROR("Error in %s, line=%d, for stack respond attribute, attribute max length should not be 0\n",\
|
||||
__func__, __LINE__);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (attr_val != NULL){
|
||||
if (attr_val->attr_len > attr_val->attr_max_len){
|
||||
GATT_TRACE_ERROR("Error in %s, line=%d,attribute actual length should not be larger than max length\n",\
|
||||
__func__, __LINE__);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if ((p_char_decl = (tGATT_ATTR16 *)allocate_attr_in_db(p_db, &uuid, GATT_PERM_READ)) != NULL) {
|
||||
if (!copy_extra_byte_in_db(p_db, (void **)&p_char_decl->p_value, sizeof(tGATT_CHAR_DECL))) {
|
||||
|
@ -483,10 +511,9 @@ UINT16 gatts_add_characteristic (tGATT_SVC_DB *p_db, tGATT_PERM perm,
|
|||
p_char_val->control.auto_rsp = control->auto_rsp;
|
||||
} else {
|
||||
p_char_val->control.auto_rsp = GATT_RSP_DEFAULT;
|
||||
|
||||
}
|
||||
|
||||
if (attr_val != NULL) {
|
||||
if (attr_val != NULL) {
|
||||
if (!copy_extra_byte_in_db(p_db, (void **)&p_char_val->p_value, sizeof(tGATT_ATTR_VAL))) {
|
||||
deallocate_attr_in_db(p_db, p_char_val);
|
||||
return 0;
|
||||
|
@ -496,12 +523,27 @@ UINT16 gatts_add_characteristic (tGATT_SVC_DB *p_db, tGATT_PERM perm,
|
|||
p_char_val->p_value->attr_val.attr_len = attr_val->attr_len;
|
||||
p_char_val->p_value->attr_val.attr_max_len = attr_val->attr_max_len;
|
||||
p_char_val->p_value->attr_val.attr_val = GKI_getbuf(attr_val->attr_max_len);
|
||||
if (p_char_val->p_value->attr_val.attr_val != NULL) {
|
||||
GATT_TRACE_DEBUG("attribute value not NULL");
|
||||
memcpy(p_char_val->p_value->attr_val.attr_val, attr_val->attr_val, attr_val->attr_len);
|
||||
if (p_char_val->p_value->attr_val.attr_val == NULL) {
|
||||
deallocate_attr_in_db(p_db, p_char_decl);
|
||||
deallocate_attr_in_db(p_db, p_char_val);
|
||||
GATT_TRACE_WARNING("Warning in %s, line=%d, insufficient resource to allocate for attribute value\n", __func__, __LINE__);
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
//add mask to indicate that p_value->attr_val.attr_val is dynamic allocated
|
||||
p_char_val->mask |= GATT_ATTR_VALUE_ALLOCATED;
|
||||
}
|
||||
|
||||
//initiate characteristic attribute value part
|
||||
memset(p_char_val->p_value->attr_val.attr_val, 0, attr_val->attr_max_len);
|
||||
if (attr_val->attr_val != NULL) {
|
||||
if (attr_val->attr_max_len < attr_val->attr_len){
|
||||
GATT_TRACE_ERROR("Error in %s, Line=%d, attribute actual length (%d) should not larger than max size (%d)\n",
|
||||
__func__, __LINE__, attr_val->attr_len, attr_val->attr_max_len);
|
||||
}
|
||||
UINT16 actual_len = (attr_val->attr_max_len < attr_val->attr_len) ? (attr_val->attr_max_len) : (attr_val->attr_len);
|
||||
memcpy(p_char_val->p_value->attr_val.attr_val, attr_val->attr_val, actual_len);
|
||||
}
|
||||
} else {
|
||||
p_char_val->p_value = NULL;
|
||||
}
|
||||
|
||||
return p_char_val->handle;
|
||||
|
@ -582,14 +624,35 @@ UINT16 gatts_add_char_descr (tGATT_SVC_DB *p_db, tGATT_PERM perm,
|
|||
|
||||
GATT_TRACE_DEBUG("gatts_add_char_descr uuid=0x%04x\n", p_descr_uuid->uu.uuid16);
|
||||
|
||||
/* parameter validation check */
|
||||
if ((control != NULL) && (control->auto_rsp == GATT_STACK_RSP)){
|
||||
if (attr_val == NULL){
|
||||
GATT_TRACE_ERROR("Error in %s, line=%d, for stack respond attribute, attr_val should not be NULL here\n",\
|
||||
__func__, __LINE__);
|
||||
return 0;
|
||||
} else if (attr_val->attr_max_len == 0){
|
||||
GATT_TRACE_ERROR("Error in %s, line=%d, for stack respond attribute, attribute max length should not be 0\n",\
|
||||
__func__, __LINE__);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (attr_val != NULL){
|
||||
if (attr_val->attr_len > attr_val->attr_max_len){
|
||||
GATT_TRACE_ERROR("Error in %s, line=%d,attribute actual length (%d) should not be larger than max length (%d)\n",\
|
||||
__func__, __LINE__, attr_val->attr_len, attr_val->attr_max_len);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Add characteristic descriptors */
|
||||
if ((p_char_dscptr = (tGATT_ATTR16 *)allocate_attr_in_db(p_db, p_descr_uuid, perm)) == NULL) {
|
||||
deallocate_attr_in_db(p_db, p_char_dscptr);
|
||||
GATT_TRACE_DEBUG("gatts_add_char_descr Fail for adding char descriptors.");
|
||||
return 0;
|
||||
} else {
|
||||
if (control != NULL) {
|
||||
p_char_dscptr->control.auto_rsp = control->auto_rsp;
|
||||
}
|
||||
p_char_dscptr->control.auto_rsp = (control == NULL) ? GATT_RSP_DEFAULT : (control->auto_rsp);
|
||||
if (attr_val != NULL) {
|
||||
if (!copy_extra_byte_in_db(p_db, (void **)&p_char_dscptr->p_value, sizeof(tGATT_ATTR_VAL))) {
|
||||
deallocate_attr_in_db(p_db, p_char_dscptr);
|
||||
|
@ -599,12 +662,20 @@ UINT16 gatts_add_char_descr (tGATT_SVC_DB *p_db, tGATT_PERM perm,
|
|||
p_char_dscptr->p_value->attr_val.attr_max_len = attr_val->attr_max_len;
|
||||
if (attr_val->attr_max_len != 0) {
|
||||
p_char_dscptr->p_value->attr_val.attr_val = GKI_getbuf(attr_val->attr_max_len);
|
||||
if (p_char_dscptr->p_value->attr_val.attr_val != NULL) {
|
||||
memset(p_char_dscptr->p_value->attr_val.attr_val, 0, attr_val->attr_max_len);
|
||||
if(attr_val->attr_val != NULL) {
|
||||
memcpy(p_char_dscptr->p_value->attr_val.attr_val,
|
||||
attr_val->attr_val, attr_val->attr_len);
|
||||
}
|
||||
if (p_char_dscptr->p_value->attr_val.attr_val == NULL) {
|
||||
deallocate_attr_in_db(p_db, p_char_dscptr);
|
||||
GATT_TRACE_WARNING("Warning in %s, line=%d, insufficient resource to allocate for descriptor value\n", __func__, __LINE__);
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
//add mask to indicate that p_value->attr_val.attr_val is dynamic allocated
|
||||
p_char_dscptr->mask |= GATT_ATTR_VALUE_ALLOCATED;
|
||||
}
|
||||
|
||||
//initiate characteristic attribute value part
|
||||
memset(p_char_dscptr->p_value->attr_val.attr_val, 0, attr_val->attr_max_len);
|
||||
if(attr_val->attr_val != NULL) {
|
||||
memcpy(p_char_dscptr->p_value->attr_val.attr_val, attr_val->attr_val, attr_val->attr_len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -628,7 +699,7 @@ UINT16 gatts_add_char_descr (tGATT_SVC_DB *p_db, tGATT_PERM perm,
|
|||
**
|
||||
*******************************************************************************/
|
||||
tGATT_STATUS gatts_set_attribute_value(tGATT_SVC_DB *p_db, UINT16 attr_handle,
|
||||
UINT16 length, UINT8 *value)
|
||||
UINT16 length, UINT8 *value)
|
||||
{
|
||||
tGATT_ATTR16 *p_cur;
|
||||
|
||||
|
@ -640,51 +711,46 @@ tGATT_STATUS gatts_set_attribute_value(tGATT_SVC_DB *p_db, UINT16 attr_handle,
|
|||
GATT_TRACE_DEBUG("gatts_set_attribute_value Fail:p_db->p_attr_list is NULL.\n");
|
||||
return GATT_INVALID_PDU;
|
||||
}
|
||||
if ((length > 0) && (value == NULL)){
|
||||
GATT_TRACE_ERROR("Error in %s, line=%d, value should not be NULL here\n",__func__, __LINE__);
|
||||
return GATT_INVALID_PDU;
|
||||
}
|
||||
|
||||
p_cur = (tGATT_ATTR16 *) p_db->p_attr_list;
|
||||
|
||||
while (p_cur != NULL) {
|
||||
if (p_cur->handle == attr_handle) {
|
||||
|
||||
/* for characteristic should not be set, return GATT_NOT_FOUND */
|
||||
if (p_cur->uuid_type == GATT_ATTR_UUID_TYPE_16) {
|
||||
switch (p_cur->uuid) {
|
||||
case GATT_UUID_PRI_SERVICE:
|
||||
case GATT_UUID_SEC_SERVICE:
|
||||
case GATT_UUID_CHAR_DECLARE:
|
||||
case GATT_UUID_INCLUDE_SERVICE:
|
||||
return GATT_NOT_FOUND;
|
||||
default:
|
||||
if (p_cur->p_value != NULL && p_cur->p_value->attr_val.attr_max_len < length) {
|
||||
GATT_TRACE_ERROR("gatts_set_attribute_vaule failt:Invalid value length");
|
||||
return GATT_INVALID_ATTR_LEN;
|
||||
} else if (p_cur->p_value != NULL && p_cur->p_value->attr_val.attr_max_len > 0) {
|
||||
memcpy(p_cur->p_value->attr_val.attr_val, value, length);
|
||||
p_cur->p_value->attr_val.attr_len = length;
|
||||
} else {
|
||||
return GATT_INVALID_ATTR_LEN;
|
||||
}
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (p_cur->p_value != NULL && p_cur->p_value->attr_val.attr_max_len < length) {
|
||||
GATT_TRACE_ERROR("gatts_set_attribute_vaule failt:Invalid value length");
|
||||
} else if (p_cur->p_value != NULL && p_cur->p_value->attr_val.attr_max_len > 0) {
|
||||
memcpy(p_cur->p_value->attr_val.attr_val, value, length);
|
||||
p_cur->p_value->attr_val.attr_len = length;
|
||||
} else {
|
||||
return GATT_INVALID_ATTR_LEN;
|
||||
case GATT_UUID_PRI_SERVICE:
|
||||
case GATT_UUID_SEC_SERVICE:
|
||||
case GATT_UUID_CHAR_DECLARE:
|
||||
return GATT_NOT_FOUND;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* in other cases, value can be set*/
|
||||
if ((p_cur->p_value == NULL) || (p_cur->p_value->attr_val.attr_val == NULL) \
|
||||
|| (p_cur->p_value->attr_val.attr_max_len == 0)){
|
||||
GATT_TRACE_ERROR("Error in %s, line=%d, attribute value should not be NULL here\n", __func__, __LINE__);
|
||||
return GATT_NOT_FOUND;
|
||||
} else if (p_cur->p_value->attr_val.attr_max_len < length) {
|
||||
GATT_TRACE_ERROR("gatts_set_attribute_value failed:Invalid value length");
|
||||
return GATT_INVALID_ATTR_LEN;
|
||||
} else{
|
||||
memcpy(p_cur->p_value->attr_val.attr_val, value, length);
|
||||
p_cur->p_value->attr_val.attr_len = length;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
p_cur = p_cur->p_next;
|
||||
}
|
||||
|
||||
return GATT_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function gatts_get_attribute_value
|
||||
|
@ -875,20 +941,25 @@ tGATT_STATUS gatts_write_attr_value_by_handle(tGATT_SVC_DB *p_db,
|
|||
return GATT_APP_RSP;
|
||||
}
|
||||
|
||||
if (p_attr->p_value != NULL && (p_attr->p_value->attr_val.attr_max_len >=
|
||||
offset + len) && p_attr->p_value->attr_val.attr_val != NULL) {
|
||||
if ((p_attr->p_value != NULL) &&
|
||||
(p_attr->p_value->attr_val.attr_max_len >= offset + len) &&
|
||||
p_attr->p_value->attr_val.attr_val != NULL) {
|
||||
memcpy(p_attr->p_value->attr_val.attr_val + offset, p_value, len);
|
||||
p_attr->p_value->attr_val.attr_len = len + offset;
|
||||
return GATT_SUCCESS;
|
||||
} else {
|
||||
return GATT_NOT_LONG;
|
||||
} else if (p_attr->p_value->attr_val.attr_max_len < offset + len){
|
||||
GATT_TRACE_DEBUG("Remote device try to write with a length larger then attribute's max length\n");
|
||||
return GATT_INVALID_ATTR_LEN;
|
||||
} else if ((p_attr->p_value == NULL) || (p_attr->p_value->attr_val.attr_val == NULL)){
|
||||
GATT_TRACE_ERROR("Error in %s, line=%d, %s should not be NULL here\n", __func__, __LINE__, \
|
||||
(p_attr->p_value == NULL) ? "p_value" : "attr_val.attr_val");
|
||||
return GATT_ESP_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
p_attr = (tGATT_ATTR16 *)p_attr->p_next;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return status;
|
||||
|
|
|
@ -33,6 +33,42 @@
|
|||
#define GATT_MTU_REQ_MIN_LEN 2
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function gatt_send_packet
|
||||
**
|
||||
** Description This function is called to send gatt packets directly
|
||||
|
||||
**
|
||||
** Returns status
|
||||
**
|
||||
*******************************************************************************/
|
||||
tGATT_STATUS gatt_send_packet (tGATT_TCB *p_tcb, UINT8 *p_data, UINT16 len)
|
||||
{
|
||||
BT_HDR *p_msg = NULL;
|
||||
UINT8 *p_m = NULL;
|
||||
UINT16 buf_len;
|
||||
tGATT_STATUS status;
|
||||
|
||||
if (len > p_tcb->payload_size){
|
||||
return GATT_ILLEGAL_PARAMETER;
|
||||
}
|
||||
|
||||
buf_len = (UINT16)(sizeof(BT_HDR) + p_tcb->payload_size + L2CAP_MIN_OFFSET);
|
||||
if ((p_msg = (BT_HDR *)GKI_getbuf(buf_len)) == NULL) {
|
||||
return GATT_NO_RESOURCES;
|
||||
}
|
||||
|
||||
memset(p_msg, 0, buf_len);
|
||||
p_msg->len = len;
|
||||
p_m = (UINT8 *)(p_msg + 1) + L2CAP_MIN_OFFSET;
|
||||
memcpy(p_m, p_data, len);
|
||||
|
||||
status = attp_send_sr_msg(p_tcb, p_msg);
|
||||
return status;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function gatt_sr_enqueue_cmd
|
||||
|
@ -300,7 +336,11 @@ void gatt_process_exec_write_req (tGATT_TCB *p_tcb, UINT8 op_code, UINT16 len, U
|
|||
UINT32 trans_id = 0;
|
||||
tGATT_IF gatt_if;
|
||||
UINT16 conn_id;
|
||||
|
||||
UINT16 queue_num = 0;
|
||||
BOOLEAN is_prepare_write_valid = FALSE;
|
||||
BOOLEAN is_need_dequeue_sr_cmd = FALSE;
|
||||
tGATT_PREPARE_WRITE_RECORD *prepare_record = NULL;
|
||||
tGATT_PREPARE_WRITE_QUEUE_DATA * queue_data = NULL;
|
||||
UNUSED(len);
|
||||
|
||||
#if GATT_CONFORMANCE_TESTING == TRUE
|
||||
|
@ -319,11 +359,60 @@ void gatt_process_exec_write_req (tGATT_TCB *p_tcb, UINT8 op_code, UINT16 len, U
|
|||
/* mask the flag */
|
||||
flag &= GATT_PREP_WRITE_EXEC;
|
||||
|
||||
prepare_record = &(p_tcb->prepare_write_record);
|
||||
queue_num = prepare_record->queue._count;
|
||||
|
||||
|
||||
/* no prep write is queued */
|
||||
//if received prepare_write packets include stack_rsp and app_rsp,
|
||||
//stack respond to execute_write only when stack_rsp handle has invalid_offset
|
||||
//or invalid_length error;
|
||||
//app need to respond to execute_write if it has received app_rsp handle packets
|
||||
if (((prepare_record->error_code_app == GATT_SUCCESS) &&
|
||||
(prepare_record->total_num == queue_num))
|
||||
|| (flag == GATT_PREP_WRITE_CANCEL)){
|
||||
tGATT_EXEC_WRITE_RSP gatt_exec_write_rsp;
|
||||
gatt_exec_write_rsp.op_code = GATT_RSP_EXEC_WRITE;
|
||||
gatt_send_packet(p_tcb, (UINT8 *)(&gatt_exec_write_rsp), sizeof(gatt_exec_write_rsp));
|
||||
gatt_dequeue_sr_cmd(p_tcb);
|
||||
if (flag != GATT_PREP_WRITE_CANCEL){
|
||||
is_prepare_write_valid = TRUE;
|
||||
}
|
||||
GATT_TRACE_DEBUG("Send execute_write_rsp\n");
|
||||
} else if ((prepare_record->error_code_app == GATT_SUCCESS) &&
|
||||
(prepare_record->total_num > queue_num)){
|
||||
//No error for stack_rsp's handles and there exist some app_rsp's handles,
|
||||
//so exec_write_rsp depends to app's response; but stack_rsp's data is valid
|
||||
//TODO: there exist problem if stack_rsp's data is valid but app_rsp's data is not valid.
|
||||
is_prepare_write_valid = TRUE;
|
||||
} else if(prepare_record->total_num < queue_num) {
|
||||
GATT_TRACE_ERROR("Error in %s, line=%d, prepare write total number (%d) \
|
||||
should not smaller than prepare queue number (%d)\n", \
|
||||
__func__, __LINE__,prepare_record->total_num, queue_num);
|
||||
} else if (prepare_record->error_code_app != GATT_SUCCESS){
|
||||
GATT_TRACE_DEBUG("Send error code for execute_write, code=0x%x\n", prepare_record->error_code_app);
|
||||
is_need_dequeue_sr_cmd = (prepare_record->total_num == queue_num) ? TRUE : FALSE;
|
||||
gatt_send_error_rsp(p_tcb, prepare_record->error_code_app, GATT_REQ_EXEC_WRITE, 0, is_need_dequeue_sr_cmd);
|
||||
}
|
||||
|
||||
//dequeue prepare write data
|
||||
while(GKI_getfirst(&(prepare_record->queue))) {
|
||||
queue_data = GKI_dequeue(&(prepare_record->queue));
|
||||
if (is_prepare_write_valid){
|
||||
if((queue_data->p_attr->p_value != NULL) && (queue_data->p_attr->p_value->attr_val.attr_val != NULL)){
|
||||
memcpy(queue_data->p_attr->p_value->attr_val.attr_val+queue_data->offset, queue_data->value, queue_data->len);
|
||||
}
|
||||
}
|
||||
GKI_freebuf(queue_data);
|
||||
}
|
||||
|
||||
/* according to ble spec, even if there is no prep write queued,
|
||||
* need to respond execute_write_response
|
||||
* Note: exec_write_rsp callback should be called after all data has been written*/
|
||||
if (!gatt_sr_is_prep_cnt_zero(p_tcb)) {
|
||||
trans_id = gatt_sr_enqueue_cmd(p_tcb, op_code, 0);
|
||||
gatt_sr_copy_prep_cnt_to_cback_cnt(p_tcb);
|
||||
if (prepare_record->total_num > queue_num){
|
||||
trans_id = gatt_sr_enqueue_cmd(p_tcb, op_code, 0);
|
||||
gatt_sr_copy_prep_cnt_to_cback_cnt(p_tcb);
|
||||
}
|
||||
|
||||
for (i = 0; i < GATT_MAX_APPS; i++) {
|
||||
if (p_tcb->prep_cnt[i]) {
|
||||
|
@ -336,10 +425,10 @@ void gatt_process_exec_write_req (tGATT_TCB *p_tcb, UINT8 op_code, UINT16 len, U
|
|||
p_tcb->prep_cnt[i] = 0;
|
||||
}
|
||||
}
|
||||
} else { /* nothing needs to be executed , send response now */
|
||||
GATT_TRACE_ERROR("gatt_process_exec_write_req: no prepare write pending");
|
||||
gatt_send_error_rsp(p_tcb, GATT_ERROR, GATT_REQ_EXEC_WRITE, 0, FALSE);
|
||||
}
|
||||
|
||||
prepare_record->total_num = 0;
|
||||
prepare_record->error_code_app = GATT_SUCCESS;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
|
@ -987,54 +1076,29 @@ void gatts_process_read_by_type_req(tGATT_TCB *p_tcb, UINT8 op_code, UINT16 len,
|
|||
void gatts_process_write_req (tGATT_TCB *p_tcb, UINT8 i_rcb, UINT16 handle,
|
||||
UINT8 op_code, UINT16 len, UINT8 *p_data)
|
||||
{
|
||||
UINT16 buf_len = (UINT16)(sizeof(BT_HDR) + p_tcb->payload_size + L2CAP_MIN_OFFSET);
|
||||
tGATTS_DATA sr_data;
|
||||
UINT32 trans_id;
|
||||
tGATT_STATUS status;
|
||||
UINT8 sec_flag, key_size, *p = p_data, *p_m;
|
||||
UINT8 sec_flag, key_size, *p = p_data;
|
||||
tGATT_SR_REG *p_sreg;
|
||||
UINT16 conn_id, offset = 0;
|
||||
BT_HDR *p_msg = NULL;
|
||||
|
||||
memset(&sr_data, 0, sizeof(tGATTS_DATA));
|
||||
sr_data.write_req.need_rsp = FALSE;
|
||||
|
||||
if ((p_msg = (BT_HDR *)GKI_getbuf(buf_len)) == NULL) {
|
||||
GATT_TRACE_ERROR("gatts_process_write_req failed. no resources.\n");
|
||||
}
|
||||
|
||||
memset(p_msg, 0, buf_len);
|
||||
p_m = (UINT8 *)(p_msg + 1) + L2CAP_MIN_OFFSET;
|
||||
*p_m ++ = op_code + 1;
|
||||
p_msg->len = 1;
|
||||
buf_len = p_tcb->payload_size - 1;
|
||||
|
||||
switch (op_code) {
|
||||
case GATT_REQ_PREPARE_WRITE:
|
||||
sr_data.write_req.is_prep = TRUE;
|
||||
STREAM_TO_UINT16(sr_data.write_req.offset, p);
|
||||
UINT16_TO_STREAM(p_m, sr_data.write_req.is_prep);
|
||||
offset = sr_data.write_req.offset;
|
||||
len -= 2;
|
||||
/* fall through */
|
||||
case GATT_SIGN_CMD_WRITE:
|
||||
if (op_code == GATT_SIGN_CMD_WRITE) {
|
||||
GATT_TRACE_DEBUG("Write CMD with data sigining" );
|
||||
GATT_TRACE_DEBUG("Write CMD with data signing" );
|
||||
len -= GATT_AUTH_SIGN_LEN;
|
||||
}
|
||||
/* fall through */
|
||||
case GATT_CMD_WRITE:
|
||||
case GATT_REQ_WRITE:
|
||||
if (op_code == GATT_REQ_WRITE || op_code == GATT_REQ_PREPARE_WRITE) {
|
||||
sr_data.write_req.need_rsp = TRUE;
|
||||
if(op_code == GATT_REQ_PREPARE_WRITE){
|
||||
memcpy(p_m, p, len);
|
||||
p_msg->len += len;
|
||||
}
|
||||
}
|
||||
sr_data.write_req.handle = handle;
|
||||
sr_data.write_req.len = len;
|
||||
if (len != 0 && p != NULL) {
|
||||
memcpy (sr_data.write_req.value, p, len);
|
||||
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -1059,42 +1123,182 @@ void gatts_process_write_req (tGATT_TCB *p_tcb, UINT8 i_rcb, UINT16 handle,
|
|||
conn_id = GATT_CREATE_CONN_ID(p_tcb->tcb_idx, p_sreg->gatt_if);
|
||||
status = gatts_write_attr_value_by_handle(gatt_cb.sr_reg[i_rcb].p_db,
|
||||
handle, offset, p, len);
|
||||
if((sr_data.write_req.need_rsp == TRUE) && (status == GATT_APP_RSP)){
|
||||
if((op_code == GATT_REQ_WRITE) && (status == GATT_APP_RSP)){
|
||||
sr_data.write_req.need_rsp = TRUE;
|
||||
status = GATT_PENDING;
|
||||
}
|
||||
|
||||
else{
|
||||
sr_data.write_req.need_rsp = FALSE;
|
||||
}
|
||||
|
||||
gatt_sr_send_req_callback(conn_id,
|
||||
trans_id,
|
||||
GATTS_REQ_TYPE_WRITE,
|
||||
&sr_data);
|
||||
|
||||
if (status == GATT_SUCCESS) {
|
||||
attp_send_sr_msg(p_tcb, p_msg);
|
||||
gatt_dequeue_sr_cmd(p_tcb);
|
||||
} else {
|
||||
GKI_freebuf(p_msg);
|
||||
}
|
||||
|
||||
} else {
|
||||
GATT_TRACE_ERROR("max pending command, send error\n");
|
||||
GATT_TRACE_ERROR("Error in %s, line=%d, max pending command, send error\n", __func__, __LINE__);
|
||||
status = GATT_BUSY; /* max pending command, application error */
|
||||
}
|
||||
}
|
||||
|
||||
/* in theroy BUSY is not possible(should already been checked), protected check */
|
||||
if (status != GATT_PENDING && status != GATT_BUSY && status != GATT_SUCCESS &&
|
||||
(op_code == GATT_REQ_PREPARE_WRITE || op_code == GATT_REQ_WRITE)) {
|
||||
gatt_send_error_rsp (p_tcb, status, op_code, handle, FALSE);
|
||||
gatt_dequeue_sr_cmd(p_tcb);
|
||||
/* response should be sent only for write_request */
|
||||
if ((op_code == GATT_REQ_WRITE) && (sr_data.write_req.need_rsp == FALSE)){
|
||||
if (status == GATT_SUCCESS){
|
||||
tGATT_WRITE_REQ_RSP gatt_write_req_rsp;
|
||||
gatt_write_req_rsp.op_code = GATT_RSP_WRITE;
|
||||
gatt_send_packet(p_tcb, (UINT8 *)(&gatt_write_req_rsp), sizeof(gatt_write_req_rsp));
|
||||
gatt_dequeue_sr_cmd(p_tcb);
|
||||
} else if (status != GATT_PENDING){
|
||||
/* note: in case of GATT_BUSY, will respond this application error to remote device */
|
||||
gatt_send_error_rsp (p_tcb, status, op_code, handle, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function gatts_attr_process_preapre_write
|
||||
**
|
||||
** Description This function is called to process the prepare write request
|
||||
** from client.
|
||||
**
|
||||
** Returns void
|
||||
**
|
||||
*******************************************************************************/
|
||||
void gatt_attr_process_prepare_write (tGATT_TCB *p_tcb, UINT8 i_rcb, UINT16 handle,
|
||||
UINT8 op_code, UINT16 len, UINT8 *p_data)
|
||||
{
|
||||
tGATT_STATUS status;
|
||||
tGATT_PREPARE_WRITE_QUEUE_DATA * queue_data = NULL;
|
||||
tGATT_ATTR16 *p_attr;
|
||||
tGATT_ATTR16 *p_attr_temp;
|
||||
tGATTS_DATA sr_data;
|
||||
UINT32 trans_id = 0;
|
||||
UINT8 sec_flag, key_size, *p = p_data;
|
||||
tGATT_SR_REG *p_sreg;
|
||||
UINT16 conn_id, offset = 0;
|
||||
tGATT_SVC_DB *p_db;
|
||||
BOOLEAN is_need_prepare_write_rsp = FALSE;
|
||||
BOOLEAN is_need_queue_data = FALSE;
|
||||
tGATT_PREPARE_WRITE_RECORD *prepare_record = NULL;
|
||||
memset(&sr_data, 0, sizeof(tGATTS_DATA));
|
||||
|
||||
//get offset from p_data
|
||||
STREAM_TO_UINT16(offset, p);
|
||||
len -= 2;
|
||||
p_sreg = &gatt_cb.sr_reg[i_rcb];
|
||||
conn_id = GATT_CREATE_CONN_ID(p_tcb->tcb_idx, p_sreg->gatt_if);
|
||||
//prepare_record = &(prepare_write_record);
|
||||
prepare_record = &(p_tcb->prepare_write_record);
|
||||
|
||||
gatt_sr_get_sec_info(p_tcb->peer_bda,
|
||||
p_tcb->transport,
|
||||
&sec_flag,
|
||||
&key_size);
|
||||
|
||||
status = gatts_write_attr_perm_check (gatt_cb.sr_reg[i_rcb].p_db,
|
||||
op_code,
|
||||
handle,
|
||||
sr_data.write_req.offset,
|
||||
p,
|
||||
len,
|
||||
sec_flag,
|
||||
key_size);
|
||||
|
||||
if (status == GATT_SUCCESS){
|
||||
if ((trans_id = gatt_sr_enqueue_cmd(p_tcb, op_code, handle)) != 0) {
|
||||
p_db = gatt_cb.sr_reg[i_rcb].p_db;
|
||||
if (p_db && p_db->p_attr_list) {
|
||||
p_attr = (tGATT_ATTR16 *)p_db->p_attr_list;
|
||||
while (p_attr && handle >= p_attr->handle) {
|
||||
if (p_attr->handle == handle ) {
|
||||
p_attr_temp = p_attr;
|
||||
if (p_attr->control.auto_rsp == GATT_RSP_BY_APP) {
|
||||
status = GATT_APP_RSP;
|
||||
} else if (p_attr->p_value != NULL &&
|
||||
offset > p_attr->p_value->attr_val.attr_max_len) {
|
||||
status = GATT_INVALID_OFFSET;
|
||||
is_need_prepare_write_rsp = TRUE;
|
||||
is_need_queue_data = TRUE;
|
||||
} else if (p_attr->p_value != NULL &&
|
||||
((offset + len) > p_attr->p_value->attr_val.attr_max_len)){
|
||||
status = GATT_INVALID_ATTR_LEN;
|
||||
is_need_prepare_write_rsp = TRUE;
|
||||
is_need_queue_data = TRUE;
|
||||
} else if (p_attr->p_value == NULL) {
|
||||
LOG_ERROR("Error in %s, attribute of handle 0x%x not allocate value buffer\n",
|
||||
__func__, handle);
|
||||
status = GATT_ESP_ERROR;
|
||||
} else {
|
||||
//valid prepare write request, need to send response and queue the data
|
||||
//status: GATT_SUCCESS
|
||||
is_need_prepare_write_rsp = TRUE;
|
||||
is_need_queue_data = TRUE;
|
||||
}
|
||||
}
|
||||
p_attr = (tGATT_ATTR16 *)p_attr->p_next;
|
||||
}
|
||||
}
|
||||
} else{
|
||||
status = GATT_ESP_ERROR;
|
||||
GATT_TRACE_ERROR("Error in %s, Line %d: GATT BUSY\n", __func__, __LINE__);
|
||||
}
|
||||
}
|
||||
|
||||
if (is_need_queue_data){
|
||||
queue_data = (tGATT_PREPARE_WRITE_QUEUE_DATA *)GKI_getbuf(len + sizeof(tGATT_PREPARE_WRITE_QUEUE_DATA));
|
||||
if (queue_data == NULL){
|
||||
status = GATT_PREPARE_Q_FULL;
|
||||
} else {
|
||||
queue_data->p_attr = p_attr_temp;
|
||||
queue_data->len = len;
|
||||
queue_data->handle = handle;
|
||||
queue_data->offset = offset;
|
||||
memcpy(queue_data->value, p, len);
|
||||
GKI_enqueue(&(prepare_record->queue), queue_data);
|
||||
}
|
||||
}
|
||||
|
||||
if (is_need_prepare_write_rsp){
|
||||
//send prepare write response
|
||||
if (queue_data != NULL){
|
||||
queue_data->op_code = op_code + 1;
|
||||
//5: op_code 1 + handle 2 + offset 2
|
||||
tGATT_STATUS rsp_send_status = gatt_send_packet(p_tcb, &(queue_data->op_code), queue_data->len + 5);
|
||||
gatt_sr_update_prep_cnt(p_tcb, p_sreg->gatt_if, TRUE, FALSE);
|
||||
gatt_dequeue_sr_cmd(p_tcb);
|
||||
|
||||
if (rsp_send_status != GATT_SUCCESS){
|
||||
LOG_ERROR("Error in %s, line=%d, fail to send prepare_write_rsp, status=0x%x\n",
|
||||
__func__, __LINE__, rsp_send_status);
|
||||
}
|
||||
} else{
|
||||
LOG_ERROR("Error in %s, line=%d, queue_data should not be NULL here, fail to send prepare_write_rsp\n",
|
||||
__func__, __LINE__);
|
||||
}
|
||||
}
|
||||
|
||||
if ((status == GATT_APP_RSP) || (is_need_prepare_write_rsp)){
|
||||
prepare_record->total_num++;
|
||||
memset(&sr_data, 0, sizeof(sr_data));
|
||||
sr_data.write_req.is_prep = TRUE;
|
||||
sr_data.write_req.handle = handle;
|
||||
sr_data.write_req.offset = offset;
|
||||
sr_data.write_req.len = len;
|
||||
sr_data.write_req.need_rsp = (status == GATT_APP_RSP) ? TRUE : FALSE;
|
||||
memcpy(sr_data.write_req.value, p, len);
|
||||
gatt_sr_send_req_callback(conn_id, trans_id, GATTS_REQ_TYPE_WRITE, &sr_data);
|
||||
} else{
|
||||
gatt_send_error_rsp(p_tcb, status, GATT_REQ_PREPARE_WRITE, handle, TRUE);
|
||||
}
|
||||
|
||||
if ((prepare_record->error_code_app == GATT_SUCCESS)
|
||||
&& ((status == GATT_INVALID_OFFSET) || (status == GATT_INVALID_ATTR_LEN))){
|
||||
prepare_record->error_code_app = status;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function gatts_process_read_req
|
||||
|
@ -1226,9 +1430,11 @@ void gatts_process_attribute_req (tGATT_TCB *p_tcb, UINT8 op_code,
|
|||
case GATT_REQ_WRITE: /* write char/char descriptor value */
|
||||
case GATT_CMD_WRITE:
|
||||
case GATT_SIGN_CMD_WRITE:
|
||||
case GATT_REQ_PREPARE_WRITE:
|
||||
gatts_process_write_req(p_tcb, i, handle, op_code, len, p);
|
||||
break;
|
||||
|
||||
case GATT_REQ_PREPARE_WRITE:
|
||||
gatt_attr_process_prepare_write (p_tcb, i, handle, op_code, len, p);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -116,6 +116,26 @@ void gatt_free_pending_enc_queue(tGATT_TCB *p_tcb)
|
|||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function gatt_free_pending_prepare_write_queue
|
||||
**
|
||||
** Description Free all buffers in pending prepare write packets queue
|
||||
**
|
||||
** Returns None
|
||||
**
|
||||
*******************************************************************************/
|
||||
void gatt_free_pending_prepare_write_queue(tGATT_TCB *p_tcb)
|
||||
{
|
||||
GATT_TRACE_DEBUG("gatt_free_pending_prepare_write_queue");
|
||||
/* release all queued prepare write packets */
|
||||
while (!GKI_queue_is_empty(&(p_tcb->prepare_write_record.queue))) {
|
||||
GKI_freebuf (GKI_dequeue (&(p_tcb->prepare_write_record.queue)));
|
||||
}
|
||||
p_tcb->prepare_write_record.total_num = 0;
|
||||
p_tcb->prepare_write_record.error_code_app = GATT_SUCCESS;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function gatt_delete_dev_from_srv_chg_clt_list
|
||||
|
@ -377,11 +397,38 @@ tGATT_HDL_LIST_ELEM *gatt_find_hdl_buffer_by_app_id (tBT_UUID *p_app_uuid128,
|
|||
}
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function gatt_free_attr_value_buffer
|
||||
**
|
||||
** Description free characteristic attribute value buffer in a service
|
||||
**
|
||||
** Returns None
|
||||
**
|
||||
*******************************************************************************/
|
||||
void gatt_free_attr_value_buffer(tGATT_HDL_LIST_ELEM *p)
|
||||
{
|
||||
if (p){
|
||||
tGATT_SVC_DB *p_db = &(p->svc_db);
|
||||
tGATT_ATTR16 *p_attr = p_db->p_attr_list;
|
||||
tGATT_ATTR_VALUE *p_value = NULL;
|
||||
|
||||
while(p_attr){
|
||||
if (p_attr->mask & GATT_ATTR_VALUE_ALLOCATED){
|
||||
p_value = p_attr->p_value;
|
||||
if ((p_value != NULL) && (p_value->attr_val.attr_val != NULL)){
|
||||
GKI_freebuf(p_value->attr_val.attr_val);
|
||||
}
|
||||
}
|
||||
p_attr = p_attr->p_next;
|
||||
}
|
||||
}
|
||||
}
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function gatt_free_hdl_buffer
|
||||
**
|
||||
** Description free a handle buffer
|
||||
** Description free a handle buffer
|
||||
**
|
||||
** Returns None
|
||||
** Returns None
|
||||
**
|
||||
*******************************************************************************/
|
||||
void gatt_free_hdl_buffer(tGATT_HDL_LIST_ELEM *p)
|
||||
|
@ -2108,6 +2155,7 @@ void gatt_cleanup_upon_disc(BD_ADDR bda, UINT16 reason, tBT_TRANSPORT transport)
|
|||
btu_stop_timer (&p_tcb->conf_timer_ent);
|
||||
gatt_free_pending_ind(p_tcb);
|
||||
gatt_free_pending_enc_queue(p_tcb);
|
||||
gatt_free_pending_prepare_write_queue(p_tcb);
|
||||
|
||||
for (i = 0; i < GATT_MAX_APPS; i ++) {
|
||||
p_reg = &gatt_cb.cl_rcb[i];
|
||||
|
|
|
@ -133,6 +133,16 @@ typedef struct {
|
|||
UINT8 reason;
|
||||
} tGATT_ERROR;
|
||||
|
||||
/* Execute write response structure */
|
||||
typedef struct {
|
||||
UINT8 op_code;
|
||||
}__attribute__((packed)) tGATT_EXEC_WRITE_RSP;
|
||||
|
||||
/* Write request response structure */
|
||||
typedef struct {
|
||||
UINT8 op_code;
|
||||
}__attribute__((packed)) tGATT_WRITE_REQ_RSP;
|
||||
|
||||
/* server response message to ATT protocol
|
||||
*/
|
||||
typedef union {
|
||||
|
@ -175,6 +185,7 @@ typedef struct {
|
|||
tGATT_ATTR_UUID_TYPE uuid_type;
|
||||
tGATT_PERM permission;
|
||||
tGATTS_ATTR_CONTROL control;
|
||||
tGATT_ATTR_MASK mask;
|
||||
UINT16 handle;
|
||||
UINT16 uuid;
|
||||
} tGATT_ATTR16;
|
||||
|
@ -187,6 +198,7 @@ typedef struct {
|
|||
tGATT_ATTR_UUID_TYPE uuid_type;
|
||||
tGATT_PERM permission;
|
||||
tGATTS_ATTR_CONTROL control;
|
||||
tGATT_ATTR_MASK mask;
|
||||
UINT16 handle;
|
||||
UINT32 uuid;
|
||||
} tGATT_ATTR32;
|
||||
|
@ -200,6 +212,7 @@ typedef struct {
|
|||
tGATT_ATTR_UUID_TYPE uuid_type;
|
||||
tGATT_PERM permission;
|
||||
tGATTS_ATTR_CONTROL control;
|
||||
tGATT_ATTR_MASK mask;
|
||||
UINT16 handle;
|
||||
UINT8 uuid[LEN_UUID_128];
|
||||
} tGATT_ATTR128;
|
||||
|
@ -329,6 +342,32 @@ typedef struct {
|
|||
UINT16 count;
|
||||
} tGATT_SRV_LIST_INFO;
|
||||
|
||||
/* prepare write queue data */
|
||||
typedef struct{
|
||||
//len: length of value
|
||||
tGATT_ATTR16 *p_attr;
|
||||
UINT16 len;
|
||||
UINT8 op_code;
|
||||
UINT16 handle;
|
||||
UINT16 offset;
|
||||
UINT8 value[2];
|
||||
}__attribute__((packed)) tGATT_PREPARE_WRITE_QUEUE_DATA;
|
||||
|
||||
/* structure to store prepare write packts information */
|
||||
typedef struct{
|
||||
//only store prepare write packets which need
|
||||
//to be responded by stack (not by application)
|
||||
BUFFER_Q queue;
|
||||
|
||||
//store the total number of prepare write packets
|
||||
//including that should be responded by stack or by application
|
||||
UINT16 total_num;
|
||||
|
||||
//store application error code for prepare write,
|
||||
//invalid offset && invalid length
|
||||
UINT8 error_code_app;
|
||||
}tGATT_PREPARE_WRITE_RECORD;
|
||||
|
||||
typedef struct {
|
||||
BUFFER_Q pending_enc_clcb; /* pending encryption channel q */
|
||||
tGATT_SEC_ACTION sec_act;
|
||||
|
@ -362,6 +401,7 @@ typedef struct {
|
|||
|
||||
BOOLEAN in_use;
|
||||
UINT8 tcb_idx;
|
||||
tGATT_PREPARE_WRITE_RECORD prepare_write_record; /* prepare write packets record */
|
||||
} tGATT_TCB;
|
||||
|
||||
|
||||
|
@ -584,6 +624,7 @@ extern tGATT_HDL_LIST_ELEM *gatt_find_hdl_buffer_by_handle(UINT16 handle);
|
|||
extern tGATT_HDL_LIST_ELEM *gatt_find_hdl_buffer_by_attr_handle(UINT16 attr_handle);
|
||||
extern tGATT_HDL_LIST_ELEM *gatt_alloc_hdl_buffer(void);
|
||||
extern void gatt_free_hdl_buffer(tGATT_HDL_LIST_ELEM *p);
|
||||
extern void gatt_free_attr_value_buffer(tGATT_HDL_LIST_ELEM *p);
|
||||
extern BOOLEAN gatt_is_last_attribute(tGATT_SRV_LIST_INFO *p_list, tGATT_SRV_LIST_ELEM *p_start, tBT_UUID value);
|
||||
extern void gatt_update_last_pri_srv_info(tGATT_SRV_LIST_INFO *p_list);
|
||||
extern BOOLEAN gatt_add_a_srv_to_list(tGATT_SRV_LIST_INFO *p_list, tGATT_SRV_LIST_ELEM *p_new);
|
||||
|
|
|
@ -65,6 +65,8 @@
|
|||
#define GATT_CONGESTED 0x8f
|
||||
#define GATT_STACK_RSP 0x90
|
||||
#define GATT_APP_RSP 0x91
|
||||
//Error caused by customer application or stack bug
|
||||
#define GATT_ESP_ERROR 0X9f
|
||||
|
||||
/* 0xE0 ~ 0xFC reserved for future use */
|
||||
#define GATT_CCC_CFG_ERR 0xFD /* Client Characteristic Configuration Descriptor Improperly Configured */
|
||||
|
@ -324,6 +326,10 @@ typedef struct{
|
|||
uint8_t auto_rsp;
|
||||
}tGATTS_ATTR_CONTROL;
|
||||
|
||||
/* Mask for gatt server attribute */
|
||||
#define GATT_ATTR_VALUE_ALLOCATED 0x01
|
||||
typedef UINT8 tGATT_ATTR_MASK;
|
||||
|
||||
/* Union of the event data which is used in the server respond API to carry the server response information
|
||||
*/
|
||||
typedef union {
|
||||
|
|
|
@ -79,6 +79,8 @@ struct osi_funcs_t {
|
|||
int32_t (*_mutex_lock)(void *mutex);
|
||||
int32_t (*_mutex_unlock)(void *mutex);
|
||||
int32_t (* _read_efuse_mac)(uint8_t mac[6]);
|
||||
void (* _srand)(unsigned int seed);
|
||||
int (* _rand)(void);
|
||||
};
|
||||
|
||||
/* Static variable declare */
|
||||
|
@ -134,6 +136,16 @@ static int32_t IRAM_ATTR read_mac_wrapper(uint8_t mac[6])
|
|||
return esp_read_mac(mac, ESP_MAC_BT);
|
||||
}
|
||||
|
||||
static void IRAM_ATTR srand_wrapper(unsigned int seed)
|
||||
{
|
||||
/* empty function */
|
||||
}
|
||||
|
||||
static int IRAM_ATTR rand_wrapper(void)
|
||||
{
|
||||
return (int)esp_random();
|
||||
}
|
||||
|
||||
static struct osi_funcs_t osi_funcs = {
|
||||
._set_isr = xt_set_interrupt_handler,
|
||||
._ints_on = xt_ints_on,
|
||||
|
@ -146,7 +158,9 @@ static struct osi_funcs_t osi_funcs = {
|
|||
._mutex_create = mutex_create_wrapper,
|
||||
._mutex_lock = mutex_lock_wrapper,
|
||||
._mutex_unlock = mutex_unlock_wrapper,
|
||||
._read_efuse_mac = read_mac_wrapper
|
||||
._read_efuse_mac = read_mac_wrapper,
|
||||
._srand = srand_wrapper,
|
||||
._rand = rand_wrapper,
|
||||
};
|
||||
|
||||
bool esp_vhci_host_check_send_available(void)
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 9a4bb1d5287572664f170f9df4dbfd71babdfc68
|
||||
Subproject commit 736797b73bf54d20b3688030eb19743c402662a8
|
|
@ -50,10 +50,12 @@ extern "C" {
|
|||
typedef struct {
|
||||
gpio_num_t gpio_cd; ///< GPIO number of card detect signal
|
||||
gpio_num_t gpio_wp; ///< GPIO number of write protect signal
|
||||
uint8_t width; ///< Bus width used by the slot (might be less than the max width supported)
|
||||
} sdmmc_slot_config_t;
|
||||
|
||||
#define SDMMC_SLOT_NO_CD ((gpio_num_t) -1) ///< indicates that card detect line is not used
|
||||
#define SDMMC_SLOT_NO_WP ((gpio_num_t) -1) ///< indicates that write protect line is not used
|
||||
#define SDMMC_SLOT_WIDTH_DEFAULT 0 ///< use the default width for the slot (8 for slot 0, 4 for slot 1)
|
||||
|
||||
/**
|
||||
* Macro defining default configuration of SDMMC host slot
|
||||
|
@ -61,6 +63,7 @@ typedef struct {
|
|||
#define SDMMC_SLOT_CONFIG_DEFAULT() {\
|
||||
.gpio_cd = SDMMC_SLOT_NO_CD, \
|
||||
.gpio_wp = SDMMC_SLOT_NO_WP, \
|
||||
.width = SDMMC_SLOT_WIDTH_DEFAULT, \
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -299,20 +299,31 @@ esp_err_t sdmmc_host_init_slot(int slot, const sdmmc_slot_config_t* slot_config)
|
|||
}
|
||||
int gpio_cd = slot_config->gpio_cd;
|
||||
int gpio_wp = slot_config->gpio_wp;
|
||||
uint8_t slot_width = slot_config->width;
|
||||
|
||||
// Configure pins
|
||||
const sdmmc_slot_info_t* pslot = &s_slot_info[slot];
|
||||
|
||||
if (slot_width == SDMMC_SLOT_WIDTH_DEFAULT) {
|
||||
slot_width = pslot->width;
|
||||
}
|
||||
else if (slot_width > pslot->width) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
configure_pin(pslot->clk);
|
||||
configure_pin(pslot->cmd);
|
||||
configure_pin(pslot->d0);
|
||||
configure_pin(pslot->d1);
|
||||
configure_pin(pslot->d2);
|
||||
configure_pin(pslot->d3);
|
||||
if (pslot->width == 8) {
|
||||
configure_pin(pslot->d4);
|
||||
configure_pin(pslot->d5);
|
||||
configure_pin(pslot->d6);
|
||||
configure_pin(pslot->d7);
|
||||
if (slot_width >= 4) {
|
||||
configure_pin(pslot->d1);
|
||||
configure_pin(pslot->d2);
|
||||
configure_pin(pslot->d3);
|
||||
if (slot_width == 8) {
|
||||
configure_pin(pslot->d4);
|
||||
configure_pin(pslot->d5);
|
||||
configure_pin(pslot->d6);
|
||||
configure_pin(pslot->d7);
|
||||
}
|
||||
}
|
||||
if (gpio_cd != -1) {
|
||||
gpio_set_direction(gpio_cd, GPIO_MODE_INPUT);
|
||||
|
|
|
@ -36,7 +36,7 @@ void esp_set_cpu_freq(void)
|
|||
// wait uart tx finish, otherwise some uart output will be lost
|
||||
uart_tx_wait_idle(CONFIG_CONSOLE_UART_NUM);
|
||||
|
||||
rtc_init_lite(XTAL_AUTO);
|
||||
rtc_init_lite(XTAL_40M);
|
||||
// work around a bug that RTC fast memory may be isolated
|
||||
// from the system after rtc_init_lite
|
||||
SET_PERI_REG_MASK(RTC_CNTL_PWC_REG, RTC_CNTL_FASTMEM_FORCE_NOISO_M);
|
||||
|
|
|
@ -11,10 +11,10 @@
|
|||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#ifndef __ESP_ERR_H__
|
||||
#define __ESP_ERR_H__
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -40,15 +40,38 @@ typedef int32_t esp_err_t;
|
|||
|
||||
#define ESP_ERR_WIFI_BASE 0x3000 /*!< Starting number of WiFi error codes */
|
||||
|
||||
void _esp_error_check_failed(esp_err_t rc, const char *file, int line, const char *function, const char *expression) __attribute__((noreturn));
|
||||
|
||||
#ifndef __ASSERT_FUNC
|
||||
/* This won't happen on IDF, which defines __ASSERT_FUNC in assert.h, but it does happen when building on the host which
|
||||
uses /usr/include/assert.h or equivalent.
|
||||
*/
|
||||
#ifdef __ASSERT_FUNCTION
|
||||
#define __ASSERT_FUNC __ASSERT_FUNCTION /* used in glibc assert.h */
|
||||
#else
|
||||
#define __ASSERT_FUNC "??"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Macro which can be used to check the error code,
|
||||
* and terminate the program in case the code is not ESP_OK.
|
||||
* Prints the failed statement to serial output.
|
||||
* Prints the error code, error location, and the failed statement to serial output.
|
||||
*
|
||||
* Disabled if assertions are disabled.
|
||||
*/
|
||||
#define ESP_ERROR_CHECK(x) do { esp_err_t rc = (x); if (rc != ESP_OK) { assert(0 && #x);} } while(0);
|
||||
#ifdef NDEBUG
|
||||
#define ESP_ERROR_CHECK(x) do { (x); } while (0)
|
||||
#else
|
||||
#define ESP_ERROR_CHECK(x) do { \
|
||||
esp_err_t rc = (x); \
|
||||
if (rc != ESP_OK) { \
|
||||
_esp_error_check_failed(rc, __FILE__, __LINE__, \
|
||||
__ASSERT_FUNC, #x); \
|
||||
} \
|
||||
} while(0);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __ESP_ERR_H__ */
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit e8743355806ed3671f7b0ef8bac1ea63909daaf3
|
||||
Subproject commit ea786aa95d52d225544186698d210aa6cdd970bd
|
|
@ -34,6 +34,7 @@
|
|||
#include "esp_attr.h"
|
||||
#include "esp_err.h"
|
||||
#include "esp_core_dump.h"
|
||||
#include "esp_spi_flash.h"
|
||||
|
||||
/*
|
||||
Panic handlers; these get called when an unhandled exception occurs or the assembly-level
|
||||
|
@ -107,11 +108,8 @@ void __attribute__((weak)) vApplicationStackOverflowHook( TaskHandle_t xTask, s
|
|||
|
||||
static bool abort_called;
|
||||
|
||||
void abort()
|
||||
static __attribute__((noreturn)) inline void invoke_abort()
|
||||
{
|
||||
#if !CONFIG_ESP32_PANIC_SILENT_REBOOT
|
||||
ets_printf("abort() was called at PC 0x%08x\n", (intptr_t)__builtin_return_address(0) - 3);
|
||||
#endif
|
||||
abort_called = true;
|
||||
while(1) {
|
||||
__asm__ ("break 0,0");
|
||||
|
@ -119,6 +117,14 @@ void abort()
|
|||
}
|
||||
}
|
||||
|
||||
void abort()
|
||||
{
|
||||
#if !CONFIG_ESP32_PANIC_SILENT_REBOOT
|
||||
ets_printf("abort() was called at PC 0x%08x\n", (intptr_t)__builtin_return_address(0) - 3);
|
||||
#endif
|
||||
invoke_abort();
|
||||
}
|
||||
|
||||
|
||||
static const char *edesc[] = {
|
||||
"IllegalInstruction", "Syscall", "InstructionFetchError", "LoadStoreError",
|
||||
|
@ -441,4 +447,11 @@ void esp_clear_watchpoint(int no)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
void _esp_error_check_failed(esp_err_t rc, const char *file, int line, const char *function, const char *expression)
|
||||
{
|
||||
ets_printf("ESP_ERROR_CHECK failed: esp_err_t 0x%x at 0x%08x\n", rc, (intptr_t)__builtin_return_address(0) - 3);
|
||||
if (spi_flash_cache_enabled()) { // strings may be in flash cache
|
||||
ets_printf("file: \"%s\" line %d\nfunc: %s\nexpression: %s\n", file, line, function, expression);
|
||||
}
|
||||
invoke_abort();
|
||||
}
|
||||
|
|
|
@ -254,7 +254,7 @@
|
|||
#define configUSE_TIMERS 1
|
||||
#define configTIMER_TASK_PRIORITY 1
|
||||
#define configTIMER_QUEUE_LENGTH 10
|
||||
#define configTIMER_TASK_STACK_DEPTH configMINIMAL_STACK_SIZE
|
||||
#define configTIMER_TASK_STACK_DEPTH 2048
|
||||
|
||||
#define INCLUDE_xTimerPendFunctionCall 1
|
||||
#define INCLUDE_eTaskGetState 1
|
||||
|
|
|
@ -132,8 +132,8 @@ _frxt_int_enter:
|
|||
l32i a2, a2, 0 /* a2 = current TCB */
|
||||
beqz a2, 1f
|
||||
s32i a1, a2, TOPOFSTACK_OFFS /* pxCurrentTCB->pxTopOfStack = SP */
|
||||
movi a1, port_IntStackTop /* a1 = top of intr stack */
|
||||
movi a2, configISR_STACK_SIZE
|
||||
movi a1, port_IntStack+configISR_STACK_SIZE /* a1 = top of intr stack for CPU 0 */
|
||||
movi a2, configISR_STACK_SIZE /* add configISR_STACK_SIZE * cpu_num to arrive at top of stack for cpu_num */
|
||||
mull a2, a4, a2
|
||||
add a1, a1, a2 /* for current proc */
|
||||
|
||||
|
|
|
@ -2935,12 +2935,18 @@ initial condition:
|
|||
test script: InitCondBase
|
||||
- check cmd set:
|
||||
- ''
|
||||
- - FREBOOT UT1
|
||||
- ['']
|
||||
- - DELAY 3
|
||||
- ['']
|
||||
- - UT UT1 -
|
||||
- [R UT1 C Tests C Failures C Ignored]
|
||||
force restore cmd set:
|
||||
- ''
|
||||
- - FREBOOT UT1
|
||||
- ['']
|
||||
- - DELAY 3
|
||||
- ['']
|
||||
- - UT UT1 -
|
||||
- [R UT1 C Tests C Failures C Ignored]
|
||||
initial condition detail: At UT menu page
|
||||
|
@ -2948,6 +2954,8 @@ initial condition:
|
|||
- ''
|
||||
- - FREBOOT UT1
|
||||
- ['']
|
||||
- - DELAY 3
|
||||
- ['']
|
||||
- - UT UT1 -
|
||||
- [R UT1 C Tests C Failures C Ignored]
|
||||
restore post cmd set:
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include MBEDTLS_CONFIG_FILE
|
||||
#endif
|
||||
|
||||
#include "platform.h"
|
||||
#include "bignum.h"
|
||||
#include "ecp.h"
|
||||
|
||||
|
|
|
@ -491,7 +491,7 @@ static const uint8_t * _mdns_read_fqdn(const uint8_t * packet, const uint8_t * s
|
|||
&& (strcmp(buf, MDNS_DEFAULT_DOMAIN) != 0)
|
||||
&& (strcmp(buf, "ip6") != 0)
|
||||
&& (strcmp(buf, "in-addr") != 0)) {
|
||||
sprintf((char*)name, "%s.%s", name->host, buf);
|
||||
snprintf((char*)name, MDNS_NAME_BUF_LEN, "%s.%s", name->host, buf);
|
||||
} else if (strcmp(buf, MDNS_SUB_STR) == 0) {
|
||||
name->sub = 1;
|
||||
} else {
|
||||
|
@ -499,7 +499,7 @@ static const uint8_t * _mdns_read_fqdn(const uint8_t * packet, const uint8_t * s
|
|||
}
|
||||
} else {
|
||||
size_t address = (((uint16_t)len & 0x3F) << 8) | start[index++];
|
||||
if ((packet + address) > start) {
|
||||
if ((packet + address) >= start) {
|
||||
//reference address can not be after where we are
|
||||
return NULL;
|
||||
}
|
||||
|
@ -1182,13 +1182,13 @@ static mdns_service_t * _mdns_create_service(const char * service, const char *
|
|||
s->txt = NULL;
|
||||
s->port = port;
|
||||
|
||||
s->service = strdup(service);
|
||||
s->service = strndup(service, MDNS_NAME_BUF_LEN - 1);
|
||||
if (!s->service) {
|
||||
free(s);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
s->proto = strdup(proto);
|
||||
s->proto = strndup(proto, MDNS_NAME_BUF_LEN - 1);
|
||||
if (!s->proto) {
|
||||
free((char *)s->service);
|
||||
free(s);
|
||||
|
@ -1341,7 +1341,7 @@ static void _mdns_parse_packet(mdns_server_t * server, const uint8_t * data, siz
|
|||
(strcmp(name->proto, server->search.proto) != 0)) {
|
||||
continue;//not searching for service or wrong service/proto
|
||||
}
|
||||
sprintf(answer->instance, "%s", name->host);
|
||||
strlcpy(answer->instance, name->host, MDNS_NAME_BUF_LEN);
|
||||
} else if (type == MDNS_TYPE_SRV) {
|
||||
if (server->search.host[0] ||
|
||||
(strcmp(name->service, server->search.service) != 0) ||
|
||||
|
@ -1353,7 +1353,7 @@ static void _mdns_parse_packet(mdns_server_t * server, const uint8_t * data, siz
|
|||
continue;//instance name is not the same as the one in the PTR record
|
||||
}
|
||||
} else {
|
||||
sprintf(answer->instance, "%s", name->host);
|
||||
strlcpy(answer->instance, name->host, MDNS_NAME_BUF_LEN);
|
||||
}
|
||||
//parse record value
|
||||
if (!_mdns_parse_fqdn(data, data_ptr + MDNS_SRV_FQDN_OFFSET, name)) {
|
||||
|
@ -1367,15 +1367,19 @@ static void _mdns_parse_packet(mdns_server_t * server, const uint8_t * data, siz
|
|||
if (answer->host[0]) {
|
||||
if (strcmp(answer->host, name->host) != 0) {
|
||||
answer->addr = 0;
|
||||
sprintf(answer->host, "%s", name->host);
|
||||
strlcpy(answer->host, name->host, MDNS_NAME_BUF_LEN);
|
||||
}
|
||||
} else {
|
||||
sprintf(answer->host, "%s", name->host);
|
||||
strlcpy(answer->host, name->host, MDNS_NAME_BUF_LEN);
|
||||
}
|
||||
} else if (type == MDNS_TYPE_TXT) {
|
||||
uint16_t i=0,b=0, y;
|
||||
while(i < data_len) {
|
||||
uint8_t partLen = data_ptr[i++];
|
||||
//check if partLen will fit in the buffer
|
||||
if (partLen > (MDNS_TXT_MAX_LEN - b - 1)) {
|
||||
break;
|
||||
}
|
||||
for(y=0; y<partLen; y++) {
|
||||
char d = data_ptr[i++];
|
||||
answer->txt[b++] = d;
|
||||
|
@ -1391,7 +1395,7 @@ static void _mdns_parse_packet(mdns_server_t * server, const uint8_t * data, siz
|
|||
continue;//wrong host
|
||||
}
|
||||
} else if (!answer->ptr) {
|
||||
sprintf(answer->host, "%s", name->host);
|
||||
strlcpy(answer->host, name->host, MDNS_NAME_BUF_LEN);
|
||||
} else if (strcmp(answer->host, name->host) != 0) {
|
||||
continue;//wrong host
|
||||
}
|
||||
|
@ -1402,7 +1406,7 @@ static void _mdns_parse_packet(mdns_server_t * server, const uint8_t * data, siz
|
|||
continue;//wrong host
|
||||
}
|
||||
} else if (!answer->ptr) {
|
||||
sprintf(answer->host, "%s", name->host);
|
||||
strlcpy(answer->host, name->host, MDNS_NAME_BUF_LEN);
|
||||
} else if (strcmp(answer->host, name->host) != 0) {
|
||||
continue;//wrong host
|
||||
}
|
||||
|
@ -1534,6 +1538,9 @@ esp_err_t mdns_set_hostname(mdns_server_t * server, const char * hostname)
|
|||
if (!server) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
if (strlen(hostname) > (MDNS_NAME_BUF_LEN - 1)) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
MDNS_MUTEX_LOCK();
|
||||
free((char*)server->hostname);
|
||||
server->hostname = (char *)malloc(strlen(hostname)+1);
|
||||
|
@ -1541,7 +1548,7 @@ esp_err_t mdns_set_hostname(mdns_server_t * server, const char * hostname)
|
|||
MDNS_MUTEX_UNLOCK();
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
sprintf((char *)server->hostname, "%s", hostname);
|
||||
strlcpy((char *)server->hostname, hostname, MDNS_NAME_BUF_LEN);
|
||||
MDNS_MUTEX_UNLOCK();
|
||||
return ERR_OK;
|
||||
}
|
||||
|
@ -1551,6 +1558,9 @@ esp_err_t mdns_set_instance(mdns_server_t * server, const char * instance)
|
|||
if (!server) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
if (strlen(instance) > (MDNS_NAME_BUF_LEN - 1)) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
MDNS_MUTEX_LOCK();
|
||||
free((char*)server->instance);
|
||||
server->instance = (char *)malloc(strlen(instance)+1);
|
||||
|
@ -1558,7 +1568,7 @@ esp_err_t mdns_set_instance(mdns_server_t * server, const char * instance)
|
|||
MDNS_MUTEX_UNLOCK();
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
sprintf((char *)server->instance, "%s", instance);
|
||||
strlcpy((char *)server->instance, instance, MDNS_NAME_BUF_LEN);
|
||||
MDNS_MUTEX_UNLOCK();
|
||||
return ERR_OK;
|
||||
}
|
||||
|
@ -1655,6 +1665,9 @@ esp_err_t mdns_service_instance_set(mdns_server_t * server, const char * service
|
|||
if (!server || !server->services || !service || !proto) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
if (strlen(instance) > (MDNS_NAME_BUF_LEN - 1)) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
mdns_srv_item_t * s = _mdns_get_service_item(server, service, proto);
|
||||
if (!s) {
|
||||
return ESP_ERR_NOT_FOUND;
|
||||
|
@ -1741,10 +1754,10 @@ uint32_t mdns_query(mdns_server_t * server, const char * service, const char * p
|
|||
mdns_result_free(server);
|
||||
if (proto) {
|
||||
server->search.host[0] = 0;
|
||||
snprintf(server->search.service, MDNS_NAME_MAX_LEN, "%s", service);
|
||||
snprintf(server->search.proto, MDNS_NAME_MAX_LEN, "%s", proto);
|
||||
strlcpy(server->search.service, service, MDNS_NAME_BUF_LEN);
|
||||
strlcpy(server->search.proto, proto, MDNS_NAME_BUF_LEN);
|
||||
} else {
|
||||
snprintf(server->search.host, MDNS_NAME_MAX_LEN, "%s", service);
|
||||
strlcpy(server->search.host, service, MDNS_NAME_BUF_LEN);
|
||||
server->search.service[0] = 0;
|
||||
server->search.proto[0] = 0;
|
||||
qtype = MDNS_TYPE_A;
|
||||
|
|
|
@ -2,6 +2,7 @@ TEST_PROGRAM=test_nvs
|
|||
all: $(TEST_PROGRAM)
|
||||
|
||||
SOURCE_FILES = \
|
||||
esp_error_check_stub.cpp \
|
||||
$(addprefix ../src/, \
|
||||
nvs_types.cpp \
|
||||
nvs_api.cpp \
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
#include "catch.hpp"
|
||||
#include "esp_err.h"
|
||||
|
||||
void _esp_error_check_failed(esp_err_t rc, const char *file, int line, const char *function, const char *expression)
|
||||
{
|
||||
printf("ESP_ERROR_CHECK failed: esp_err_t 0x%x at %p\n", rc, __builtin_return_address(0));
|
||||
printf("file: \"%s\" line %d\nfunc: %s\nexpression: %s\n", file, line, function, expression);
|
||||
abort();
|
||||
}
|
|
@ -275,3 +275,9 @@ static void IRAM_ATTR spi_flash_restore_cache(uint32_t cpuid, uint32_t saved_sta
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
IRAM_ATTR bool spi_flash_cache_enabled()
|
||||
{
|
||||
return REG_GET_BIT(DPORT_PRO_CACHE_CTRL_REG, DPORT_PRO_CACHE_ENABLE)
|
||||
&& REG_GET_BIT(DPORT_APP_CACHE_CTRL_REG, DPORT_APP_CACHE_ENABLE);
|
||||
}
|
||||
|
|
|
@ -197,6 +197,47 @@ void spi_flash_munmap(spi_flash_mmap_handle_t handle);
|
|||
*/
|
||||
void spi_flash_mmap_dump();
|
||||
|
||||
#define SPI_FLASH_CACHE2PHYS_FAIL UINT32_MAX /*<! Result from spi_flash_cache2phys() if flash cache address is invalid */
|
||||
|
||||
/**
|
||||
* @brief Given a memory address where flash is mapped, return the corresponding physical flash offset.
|
||||
*
|
||||
* Cache address does not have have been assigned via spi_flash_mmap(), any address in flash map space can be looked up.
|
||||
*
|
||||
* @param cached Pointer to flashed cached memory.
|
||||
*
|
||||
* @return
|
||||
* - SPI_FLASH_CACHE2PHYS_FAIL If cache address is outside flash cache region, or the address is not mapped.
|
||||
* - Otherwise, returns physical offset in flash
|
||||
*/
|
||||
size_t spi_flash_cache2phys(const void *cached);
|
||||
|
||||
/** @brief Given a physical offset in flash, return the address where it is mapped in the memory space.
|
||||
*
|
||||
* Physical address does not have to have been assigned via spi_flash_mmap(), any address in flash can be looked up.
|
||||
*
|
||||
* @note Only the first matching cache address is returned. If MMU flash cache table is configured so multiple entries
|
||||
* point to the same physical address, there may be more than one cache address corresponding to that physical
|
||||
* address. It is also possible for a single physical address to be mapped to both the IROM and DROM regions.
|
||||
*
|
||||
* @note This function doesn't impose any alignment constraints, but if memory argument is SPI_FLASH_MMAP_INST and
|
||||
* phys_offs is not 4-byte aligned, then reading from the returned pointer will result in a crash.
|
||||
*
|
||||
* @param phys_offs Physical offset in flash memory to look up.
|
||||
* @param memory Memory type to look up a flash cache address mapping for (IROM or DROM)
|
||||
*
|
||||
* @return
|
||||
* - NULL if the physical address is invalid or not mapped to flash cache of the specified memory type.
|
||||
* - Cached memory address (in IROM or DROM space) corresponding to phys_offs.
|
||||
*/
|
||||
const void *spi_flash_phys2cache(size_t phys_offs, spi_flash_mmap_memory_t memory);
|
||||
|
||||
/** @brief Check at runtime if flash cache is enabled on both CPUs
|
||||
*
|
||||
* @return true if both CPUs have flash cache enabled, false otherwise.
|
||||
*/
|
||||
bool spi_flash_cache_enabled();
|
||||
|
||||
/**
|
||||
* @brief SPI flash critical section enter function.
|
||||
*/
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <freertos/FreeRTOS.h>
|
||||
#include <freertos/task.h>
|
||||
#include <freertos/semphr.h>
|
||||
|
||||
#include <unity.h>
|
||||
#include <esp_spi_flash.h>
|
||||
#include <esp_attr.h>
|
||||
#include <esp_flash_encrypt.h>
|
||||
|
||||
#include "../cache_utils.h"
|
||||
|
||||
static QueueHandle_t result_queue;
|
||||
|
||||
static IRAM_ATTR void cache_test_task(void *arg)
|
||||
{
|
||||
bool do_disable = (bool)arg;
|
||||
bool result;
|
||||
if(do_disable) {
|
||||
spi_flash_disable_interrupts_caches_and_other_cpu();
|
||||
}
|
||||
result = spi_flash_cache_enabled();
|
||||
if (do_disable) {
|
||||
spi_flash_enable_interrupts_caches_and_other_cpu();
|
||||
}
|
||||
|
||||
TEST_ASSERT( xQueueSendToBack(result_queue, &result, 0) );
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
TEST_CASE("spi_flash_cache_enabled() works on both CPUs", "[spi_flash]")
|
||||
{
|
||||
result_queue = xQueueCreate(1, sizeof(bool));
|
||||
|
||||
for(int cpu = 0; cpu < portNUM_PROCESSORS; cpu++) {
|
||||
for(int disable = 0; disable <= 1; disable++) {
|
||||
bool do_disable = disable;
|
||||
bool result;
|
||||
printf("Testing cpu %d disabled %d\n", cpu, do_disable);
|
||||
|
||||
xTaskCreatePinnedToCore(cache_test_task, "cache_check_task",
|
||||
2048, (void *)do_disable, configMAX_PRIORITIES-1, NULL, cpu);
|
||||
|
||||
TEST_ASSERT( xQueueReceive(result_queue, &result, 2) );
|
||||
TEST_ASSERT_EQUAL(!do_disable, result);
|
||||
}
|
||||
}
|
||||
|
||||
vQueueDelete(result_queue);
|
||||
}
|
||||
|
|
@ -713,7 +713,7 @@ esp_err_t tcpip_adapter_set_hostname(tcpip_adapter_if_t tcpip_if, const char *ho
|
|||
{
|
||||
#if LWIP_NETIF_HOSTNAME
|
||||
struct netif *p_netif;
|
||||
static char hostinfo[TCPIP_HOSTNAME_MAX_SIZE + 1][TCPIP_ADAPTER_IF_MAX];
|
||||
static char hostinfo[TCPIP_ADAPTER_IF_MAX][TCPIP_HOSTNAME_MAX_SIZE + 1];
|
||||
|
||||
if (tcpip_if >= TCPIP_ADAPTER_IF_MAX || hostname == NULL) {
|
||||
return ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS;
|
||||
|
@ -726,7 +726,7 @@ esp_err_t tcpip_adapter_set_hostname(tcpip_adapter_if_t tcpip_if, const char *ho
|
|||
p_netif = esp_netif[tcpip_if];
|
||||
if (p_netif != NULL) {
|
||||
memset(hostinfo[tcpip_if], 0, sizeof(hostinfo[tcpip_if]));
|
||||
memcpy(hostinfo[tcpip_if], hostname, strlen(hostname));
|
||||
strlcpy(hostinfo[tcpip_if], hostname, sizeof(hostinfo[tcpip_if]));
|
||||
p_netif->hostname = hostinfo[tcpip_if];
|
||||
return ESP_OK;
|
||||
} else {
|
||||
|
|
|
@ -79,6 +79,7 @@ Of all the funtions listed below, only ``sdmmc_host_init``, ``sdmmc_host_init_sl
|
|||
.. doxygendefine:: SDMMC_HOST_SLOT_0
|
||||
.. doxygendefine:: SDMMC_HOST_SLOT_1
|
||||
.. doxygendefine:: SDMMC_HOST_DEFAULT
|
||||
.. doxygendefine:: SDMMC_SLOT_WIDTH_DEFAULT
|
||||
|
||||
.. doxygenfunction:: sdmmc_host_init_slot
|
||||
|
||||
|
|
|
@ -52,6 +52,9 @@ Functions
|
|||
.. doxygenfunction:: spi_flash_mmap
|
||||
.. doxygenfunction:: spi_flash_munmap
|
||||
.. doxygenfunction:: spi_flash_mmap_dump
|
||||
.. doxygenfunction:: spi_flash_cache2phys
|
||||
.. doxygenfunction:: spi_flash_phys2cache
|
||||
.. doxygenfunction:: spi_flash_cache_enabled
|
||||
.. doxygenfunction:: esp_partition_find
|
||||
.. doxygenfunction:: esp_partition_find_first
|
||||
.. doxygenfunction:: esp_partition_get
|
||||
|
|
|
@ -144,7 +144,7 @@ The minimal ``component.mk`` file is an empty file(!). If the file is empty, the
|
|||
|
||||
See `example component makefiles` for more complete component makefile examples.
|
||||
|
||||
Note that there is a different between an empty ``component.mk`` file (which invokes default component build behaviour) and no ``component.mk`` file (which means no default component build behaviour will occur.) It is possible for a component to have no `component.mk` file, if it only contains other files which influence the project configuration or build process.
|
||||
Note that there is a difference between an empty ``component.mk`` file (which invokes default component build behaviour) and no ``component.mk`` file (which means no default component build behaviour will occur.) It is possible for a component to have no `component.mk` file, if it only contains other files which influence the project configuration or build process.
|
||||
|
||||
.. component variables:
|
||||
|
||||
|
|
|
@ -49,7 +49,9 @@ Project Properties
|
|||
|
||||
* Click "Add..." again, and enter name ``IDF_PATH``. The value should be the full path where ESP-IDF is installed.
|
||||
|
||||
*All users, continue with these steps:*
|
||||
* Edit the ``PATH`` environment variable. Keep the current value, and append the path to the Xtensa toolchain that will installed as part of IDF setup (``something/xtensa-esp32-elf/bin``) if this is not already listed on the PATH.
|
||||
|
||||
* On macOS, add a ``PYTHONPATH`` environment variable and set it to ``/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages``. This is so that the system Python, which has pyserial installed as part of the setup steps, overrides any built-in Eclipse Python.
|
||||
|
||||
Navigate to "C/C++ General" -> "Preprocessor Include Paths" property page:
|
||||
|
||||
|
|
|
@ -77,12 +77,18 @@ If you can't think of a reason why you need to build it yourself, then probably
|
|||
|
||||
In any case, here are the steps to compile the toolchain yourself.
|
||||
|
||||
(Note: You will also need the prerequisite packages mentioned in step 0, above.)
|
||||
|
||||
- Install dependencies:
|
||||
|
||||
- Ubuntu::
|
||||
- Ubuntu pre-16.04::
|
||||
|
||||
sudo apt-get install gawk gperf grep gettext libncurses-dev python python-dev automake bison flex texinfo help2man libtool
|
||||
|
||||
- Ubuntu 16.04::
|
||||
|
||||
sudo apt-get install gawk gperf grep gettext python python-dev automake bison flex texinfo help2man libtool libtool-bin
|
||||
|
||||
- Debian::
|
||||
|
||||
TODO
|
||||
|
@ -96,7 +102,7 @@ Download ``crosstool-NG`` and build it::
|
|||
cd ~/esp
|
||||
git clone -b xtensa-1.22.x https://github.com/espressif/crosstool-NG.git
|
||||
cd crosstool-NG
|
||||
./bootstrap && ./configure --prefix=$PWD && make install
|
||||
./bootstrap && ./configure --enable-local && make install
|
||||
|
||||
Build the toolchain::
|
||||
|
||||
|
|
|
@ -89,7 +89,7 @@ Download ``crosstool-NG`` and build it::
|
|||
cd ~/esp
|
||||
git clone -b xtensa-1.22.x https://github.com/espressif/crosstool-NG.git
|
||||
cd crosstool-NG
|
||||
./bootstrap && ./configure --prefix=$PWD && make install
|
||||
./bootstrap && ./configure --enable-local && make install
|
||||
|
||||
Build the toolchain::
|
||||
|
||||
|
|
|
@ -45,7 +45,7 @@ void phy_tlk110_check_phy_init(void)
|
|||
{
|
||||
while((esp_eth_smi_read(BASIC_MODE_STATUS_REG) & AUTO_NEGOTIATION_COMPLETE ) != AUTO_NEGOTIATION_COMPLETE)
|
||||
{};
|
||||
while((esp_eth_smi_read(PHY_STATUS_REG) & AUTO_NEGTIATION_STATUS ) != AUTO_NEGTIATION_STATUS)
|
||||
while((esp_eth_smi_read(PHY_STATUS_REG) & AUTO_NEGOTIATION_STATUS ) != AUTO_NEGOTIATION_STATUS)
|
||||
{};
|
||||
while((esp_eth_smi_read(CABLE_DIAGNOSTIC_CONTROL_REG) & DIAGNOSTIC_DONE ) != DIAGNOSTIC_DONE)
|
||||
{};
|
||||
|
@ -108,7 +108,7 @@ void phy_tlk110_init(void)
|
|||
while (esp_eth_smi_read(PHY_IDENTIFIER_REG) != OUI_MSB_21TO6_DEF) {
|
||||
}
|
||||
|
||||
esp_eth_smi_write(SOFTWARE_STRAP_CONTROL_REG, DEFAULT_PHY_CONFIG |SW_STRAP_CONFIG_DONE);
|
||||
esp_eth_smi_write(SW_STRAP_CONTROL_REG, DEFAULT_PHY_CONFIG | SW_STRAP_CONFIG_DONE);
|
||||
|
||||
ets_delay_us(300);
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
#define PARTNER_ASM_DIR BIT(11)
|
||||
#define PARTNER_PAUSE BIT(10)
|
||||
|
||||
#define SOFTWARE_STRAP_CONTROL_REG (0x9)
|
||||
#define SW_STRAP_CONTROL_REG (0x9)
|
||||
#define SW_STRAP_CONFIG_DONE BIT(15)
|
||||
#define AUTO_MDIX_ENABLE BIT(14)
|
||||
#define AUTO_NEGOTIATION_ENABLE BIT(13)
|
||||
|
@ -23,7 +23,7 @@
|
|||
#define RMII_ENHANCED_MODE BIT(9)
|
||||
|
||||
#define PHY_STATUS_REG (0x10)
|
||||
#define AUTO_NEGTIATION_STATUS BIT(4)
|
||||
#define AUTO_NEGOTIATION_STATUS BIT(4)
|
||||
#define DUPLEX_STATUS BIT(2)
|
||||
#define SPEED_STATUS BIT(1)
|
||||
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
#!/bin/bash
|
||||
#
|
||||
# Short script that is sourced in to the CI environment
|
||||
# in .gitlab-ci.yml
|
||||
#
|
||||
# Sets IS_PUBLIC and IS_PRIVATE based on branch type
|
||||
#
|
||||
# Tweaks .gitmodules file for private builds
|
||||
|
||||
[ -z $CI_BUILD_REF ] && echo "This internal script should only be run by a Gitlab CI runner." && exit 1
|
||||
|
||||
REF=$CI_BUILD_REF
|
||||
|
||||
# Public branches are:
|
||||
# release branches - start with release/
|
||||
# release tags - look like vXX.YY or vXX.YY.ZZ with an optional dash followed by anything on the end
|
||||
# master branch
|
||||
#
|
||||
# These POSIX REs are equivalent to the REs in some "only:" sections of the gitlab-ci.yml file
|
||||
#
|
||||
if [[ $REF = "master" || $REF =~ ^release/v || $REF =~ ^v[0-9]+\.[0-9]+(\.[0-9]+)?(-|$) ]]; then
|
||||
export IS_PUBLIC=1
|
||||
else
|
||||
export IS_PRIVATE=1
|
||||
fi
|
||||
|
||||
unset REF
|
||||
|
||||
set -e
|
||||
|
||||
if [[ $IS_PRIVATE ]]; then
|
||||
# Redirect git submodules from public github to our private gitlab server
|
||||
sed -i "s%https://github.com/espressif/esp32-wifi-lib%${GITLAB_SSH_SERVER}/idf/esp32-wifi-lib%" .gitmodules
|
||||
sed -i "s%https://github.com/espressif/esp32-bt-lib%${GITLAB_SSH_SERVER}/idf/esp32-bt-lib%" .gitmodules
|
||||
fi
|
|
@ -0,0 +1,34 @@
|
|||
#!/bin/bash
|
||||
#
|
||||
# Short script to verify behaviour of configure_ci_environment.sh
|
||||
#
|
||||
#
|
||||
cd $(dirname $0) # make dir
|
||||
|
||||
touch .gitmodules # dummy file
|
||||
|
||||
# $1 - branch name
|
||||
# $2 - 1 if public, empty if private
|
||||
function assert_branch_public()
|
||||
{
|
||||
(
|
||||
CI_BUILD_REF=$1
|
||||
set -e
|
||||
source ./configure_ci_environment.sh
|
||||
[[ $IS_PUBLIC = $2 ]] || exit 1
|
||||
) || ( echo "Expected $1 public=$2. Failing" && exit 1 )
|
||||
}
|
||||
|
||||
assert_branch_public master 1
|
||||
assert_branch_public release/v3.0 1
|
||||
assert_branch_public release/invalid
|
||||
assert_branch_public bugfix/invalid
|
||||
assert_branch_public v1.0 1
|
||||
assert_branch_public v1.0.0 1
|
||||
assert_branch_public v50.50.50 1
|
||||
assert_branch_public v1.2-rc77 1
|
||||
assert_branch_public v1.2.3-rc1 1
|
||||
assert_branch_public v1.2.3invalid
|
||||
|
||||
rm -f .gitmodules
|
||||
|
Loading…
Reference in New Issue