mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
Merge branch 'master' into feature/btdm_avrc
# Conflicts: # components/bt/bluedroid/hci/packet_fragmenter.c # components/bt/bluedroid/stack/include/gatt_api.h
This commit is contained in:
commit
49b68c38fa
@ -150,11 +150,12 @@ test_build_system:
|
||||
|
||||
test_report:
|
||||
stage: test_report
|
||||
image: espressif/esp32-ci-env
|
||||
only:
|
||||
- master
|
||||
- triggers
|
||||
tags:
|
||||
- test_report
|
||||
- report
|
||||
variables:
|
||||
LOG_PATH: "$CI_PROJECT_DIR/$CI_BUILD_REF"
|
||||
TEST_CASE_FILE_PATH: "$CI_PROJECT_DIR/components/idf_test"
|
||||
@ -166,12 +167,34 @@ test_report:
|
||||
- $LOG_PATH
|
||||
expire_in: 12 mos
|
||||
script:
|
||||
# calc log path
|
||||
- VER_NUM=`git rev-list HEAD | wc -l | awk '{print $1}'`
|
||||
- SHA_ID=`echo $CI_BUILD_REF | cut -c 1-7`
|
||||
- REVISION="${VER_NUM}_${SHA_ID}"
|
||||
# replace / to _ in branch name
|
||||
- ESCAPED_BRANCH_NAME=`echo $CI_BUILD_REF_NAME | sed 's/\//___/g'`
|
||||
# result path and artifacts path
|
||||
- RESULT_PATH="$CI_PROJECT_NAME/$ESCAPED_BRANCH_NAME/$REVISION"
|
||||
- ARTIFACTS_PATH="$GITLAB_HTTP_SERVER/idf/esp-idf/builds/$CI_BUILD_ID/artifacts/browse/$CI_BUILD_REF"
|
||||
# clone test bench
|
||||
- git clone $GITLAB_SSH_SERVER/yinling/auto_test_script.git
|
||||
- cd auto_test_script
|
||||
# generate report
|
||||
- python CITestReport.py -l $LOG_PATH -t $TEST_CASE_FILE_PATH -p $REPORT_PATH
|
||||
|
||||
- TEST_RESULT=Pass
|
||||
- python CITestReport.py -l $LOG_PATH -t $TEST_CASE_FILE_PATH -p $REPORT_PATH -r $RESULT_PATH -a $ARTIFACTS_PATH || TEST_RESULT=Fail
|
||||
# commit to CI-test-result project
|
||||
- git clone $GITLAB_SSH_SERVER/qa/CI-test-result.git
|
||||
- rm -rf CI-test-result/RawData/$RESULT_PATH
|
||||
- cp -R $CI_PROJECT_NAME CI-test-result/RawData
|
||||
- cd CI-test-result
|
||||
# config git user
|
||||
- git config --global user.email "ci-test-result@espressif.com"
|
||||
- git config --global user.name "ci-test-result"
|
||||
# commit test result
|
||||
- git add .
|
||||
- git commit . -m "update test result for $CI_PROJECT_NAME/$CI_BUILD_REF_NAME/$CI_BUILD_REF, pipeline ID $CI_PIPELINE_ID" || exit 0
|
||||
- git push origin master
|
||||
- test "${TEST_RESULT}" = "Pass" || exit 1
|
||||
|
||||
push_master_to_github:
|
||||
before_script:
|
||||
|
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -10,3 +10,6 @@
|
||||
[submodule "components/micro-ecc/micro-ecc"]
|
||||
path = components/micro-ecc/micro-ecc
|
||||
url = https://github.com/kmackay/micro-ecc.git
|
||||
[submodule "components/coap/libcoap"]
|
||||
path = components/coap/libcoap
|
||||
url = https://github.com/obgm/libcoap.git
|
||||
|
58
README.md
58
README.md
@ -1,32 +1,36 @@
|
||||
# Using Espressif IoT Development Framework with the ESP32
|
||||
# Espressif IoT Development Framework
|
||||
|
||||
[![alt text](https://readthedocs.org/projects/docs/badge/?version=latest "Documentation Status")](http://esp-idf.readthedocs.io/en/latest/?badge=latest)
|
||||
|
||||
# Setting Up ESP-IDF
|
||||
ESP-IDF is the official development framework for the `ESP32 <https://espressif.com/en/products/hardware/esp32/overview>`_ chip.
|
||||
|
||||
In the [docs](docs) directory you will find per-platform setup guides:
|
||||
# Developing With the ESP-IDF
|
||||
|
||||
* [Windows Setup Guide](docs/windows-setup.rst)
|
||||
* [Mac OS Setup Guide](docs/macos-setup.rst)
|
||||
* [Linux Setup Guide](docs/linux-setup.rst)
|
||||
## Setting Up ESP-IDF
|
||||
|
||||
# Finding A Project
|
||||
See setup guides for detailed instructions to set up the ESP-IDF:
|
||||
|
||||
As well as the [esp-idf-template](https://github.com/espressif/esp-idf-template) project mentioned in the setup guide, esp-idf comes with some example projects in the [examples](examples) directory.
|
||||
* [Windows Setup Guide](http://esp-idf.readthedocs.io/en/latest/windows-setup.html)
|
||||
* [Mac OS Setup Guide](http://esp-idf.readthedocs.io/en/latest/macos-setup.html)
|
||||
* [Linux Setup Guide](http://esp-idf.readthedocs.io/en/latest/linux-setup.html)
|
||||
|
||||
Once you've found the project you want to work with, change to its directory and you can configure and build it:
|
||||
## Finding a Project
|
||||
|
||||
# Configuring your project
|
||||
As well as the [esp-idf-template](https://github.com/espressif/esp-idf-template) project mentioned in the setup guide, ESP-IDF comes with some example projects in the [examples](examples) directory.
|
||||
|
||||
Once you've found the project you want to work with, change to its directory and you can configure and build it.
|
||||
|
||||
## Configuring the Project
|
||||
|
||||
`make menuconfig`
|
||||
|
||||
# Compiling your project
|
||||
## Compiling the Project
|
||||
|
||||
`make all`
|
||||
|
||||
... will compile app, bootloader and generate a partition table based on the config.
|
||||
|
||||
# Flashing your project
|
||||
## Flashing the Project
|
||||
|
||||
When `make all` finishes, it will print a command line to use esptool.py to flash the chip. However you can also do this from make by running:
|
||||
|
||||
@ -36,7 +40,17 @@ This will flash the entire project (app, bootloader and partition table) to a ne
|
||||
|
||||
You don't need to run `make all` before running `make flash`, `make flash` will automatically rebuild anything which needs it.
|
||||
|
||||
# Compiling & Flashing Just the App
|
||||
## Viewing Serial Output
|
||||
|
||||
The `make monitor` target will use the already-installed [miniterm](http://pyserial.readthedocs.io/en/latest/tools.html#module-serial.tools.miniterm) (a part of pyserial) to display serial output from the ESP32 on the terminal console.
|
||||
|
||||
Exit miniterm by typing Ctrl-].
|
||||
|
||||
To flash and monitor output in one pass, you can run:
|
||||
|
||||
`make flash monitor`
|
||||
|
||||
## Compiling & Flashing Just the App
|
||||
|
||||
After the initial flash, you may just want to build and flash just your app, not the bootloader and partition table:
|
||||
|
||||
@ -47,7 +61,17 @@ After the initial flash, you may just want to build and flash just your app, not
|
||||
|
||||
(There's no downside to reflashing the bootloader and partition table each time, if they haven't changed.)
|
||||
|
||||
# The Partition Table
|
||||
## Parallel Builds
|
||||
|
||||
ESP-IDF supports compiling multiple files in parallel, so all of the above commands can be run as `make -jN` where `N` is the number of parallel make processes to run (generally N should be equal to or one more than the number of CPU cores in your system.)
|
||||
|
||||
Multiple make functions can be combined into one. For example: to build the app & bootloader using 5 jobs in parallel, then flash everything, and then display serial output from the ESP32 run:
|
||||
|
||||
```
|
||||
make -j5 flash monitor
|
||||
```
|
||||
|
||||
## The Partition Table
|
||||
|
||||
Once you've compiled your project, the "build" directory will contain a binary file with a name like "my_app.bin". This is an ESP32 image binary that can be loaded by the bootloader.
|
||||
|
||||
@ -64,7 +88,7 @@ In both cases the factory app is flashed at offset 0x10000. If you `make partiti
|
||||
|
||||
For more details about partition tables and how to create custom variations, view the `docs/partition-tables.rst` file.
|
||||
|
||||
# Erasing Flash
|
||||
## Erasing Flash
|
||||
|
||||
The `make flash` target does not erase the entire flash contents. However it is sometimes useful to set the device back to a totally erased state, particularly when making partition table changes or OTA app updates. To erase the entire flash, run `make erase_flash`.
|
||||
|
||||
@ -72,11 +96,11 @@ This can be combined with other targets, ie `make erase_flash flash` will erase
|
||||
|
||||
# Resources
|
||||
|
||||
* The [docs directory of the esp-idf repository](docs) contains source of [esp-idf](http://esp-idf.readthedocs.io/) documentation.
|
||||
* Documentation for the latest version: http://esp-idf.readthedocs.io/. This documentation is built from the [docs directory](docs) of this repository.
|
||||
|
||||
* The [esp32.com forum](http://esp32.com/) is a place to ask questions and find community resources.
|
||||
|
||||
* [Check the Issues section on github](https://github.com/espressif/esp-idf/issues) if you find a bug or have a feature request. Please check existing Issues before opening a new one.
|
||||
|
||||
* If you're interested in contributing to esp-idf, please check the [Contributions Guide](http://esp-idf.readthedocs.io/en/latest/contributing.html>).
|
||||
* If you're interested in contributing to ESP-IDF, please check the [Contributions Guide](http://esp-idf.readthedocs.io/en/latest/contributing.html>).
|
||||
|
||||
|
@ -50,11 +50,14 @@ else ifdef CONFIG_SECURE_BOOTLOADER_ONE_TIME_FLASH
|
||||
|
||||
# One time flashing requires user to run esptool.py command themselves,
|
||||
# and warning is printed about inability to reflash.
|
||||
#
|
||||
# The flashing command is deliberately printed without an auto-reset
|
||||
# step, so the device doesn't immediately reset to flash itself.
|
||||
|
||||
bootloader: $(BOOTLOADER_BIN)
|
||||
@echo $(SEPARATOR)
|
||||
@echo "Bootloader built. One-time flash command is:"
|
||||
@echo "$(ESPTOOLPY_WRITE_FLASH) $(BOOTLOADER_OFFSET) $(BOOTLOADER_BIN)"
|
||||
@echo "$(subst hard_reset,no_reset,$(ESPTOOLPY_WRITE_FLASH)) $(BOOTLOADER_OFFSET) $(BOOTLOADER_BIN)"
|
||||
@echo $(SEPARATOR)
|
||||
@echo "* IMPORTANT: After first boot, BOOTLOADER CANNOT BE RE-FLASHED on same device"
|
||||
|
||||
|
@ -23,7 +23,6 @@ extern "C"
|
||||
|
||||
#include "esp_flash_data_types.h"
|
||||
|
||||
#define BOOT_VERSION "V0.1"
|
||||
#define SPI_SEC_SIZE 0x1000
|
||||
#define IROM_LOW 0x400D0000
|
||||
#define IROM_HIGH 0x40400000
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include "rom/rtc.h"
|
||||
#include "rom/uart.h"
|
||||
#include "rom/gpio.h"
|
||||
#include "rom/secure_boot.h"
|
||||
|
||||
#include "soc/soc.h"
|
||||
#include "soc/cpu.h"
|
||||
@ -40,9 +41,11 @@
|
||||
#include "esp_image_format.h"
|
||||
#include "esp_secure_boot.h"
|
||||
#include "esp_flash_encrypt.h"
|
||||
#include "esp_flash_partitions.h"
|
||||
#include "bootloader_flash.h"
|
||||
|
||||
#include "bootloader_random.h"
|
||||
#include "bootloader_config.h"
|
||||
#include "rtc.h"
|
||||
|
||||
extern int _bss_start;
|
||||
extern int _bss_end;
|
||||
@ -116,16 +119,14 @@ bool load_partition_table(bootloader_state_t* bs)
|
||||
{
|
||||
const esp_partition_info_t *partitions;
|
||||
const int ESP_PARTITION_TABLE_DATA_LEN = 0xC00; /* length of actual data (signature is appended to this) */
|
||||
const int MAX_PARTITIONS = ESP_PARTITION_TABLE_DATA_LEN / sizeof(esp_partition_info_t);
|
||||
char *partition_usage;
|
||||
|
||||
ESP_LOGI(TAG, "Partition Table:");
|
||||
ESP_LOGI(TAG, "## Label Usage Type ST Offset Length");
|
||||
esp_err_t err;
|
||||
int num_partitions;
|
||||
|
||||
#ifdef CONFIG_SECURE_BOOT_ENABLED
|
||||
if(esp_secure_boot_enabled()) {
|
||||
ESP_LOGI(TAG, "Verifying partition table signature...");
|
||||
esp_err_t err = esp_secure_boot_verify_signature(ESP_PARTITION_TABLE_ADDR, ESP_PARTITION_TABLE_DATA_LEN);
|
||||
err = esp_secure_boot_verify_signature(ESP_PARTITION_TABLE_ADDR, ESP_PARTITION_TABLE_DATA_LEN);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to verify partition table signature.");
|
||||
return false;
|
||||
@ -141,17 +142,21 @@ bool load_partition_table(bootloader_state_t* bs)
|
||||
}
|
||||
ESP_LOGD(TAG, "mapped partition table 0x%x at 0x%x", ESP_PARTITION_TABLE_ADDR, (intptr_t)partitions);
|
||||
|
||||
for(int i = 0; i < MAX_PARTITIONS; i++) {
|
||||
err = esp_partition_table_basic_verify(partitions, true, &num_partitions);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to verify partition table");
|
||||
return false;
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "Partition Table:");
|
||||
ESP_LOGI(TAG, "## Label Usage Type ST Offset Length");
|
||||
|
||||
for(int i = 0; i < num_partitions; i++) {
|
||||
const esp_partition_info_t *partition = &partitions[i];
|
||||
ESP_LOGD(TAG, "load partition table entry 0x%x", (intptr_t)partition);
|
||||
ESP_LOGD(TAG, "type=%x subtype=%x", partition->type, partition->subtype);
|
||||
partition_usage = "unknown";
|
||||
|
||||
if (partition->magic != ESP_PARTITION_MAGIC) {
|
||||
/* invalid partition definition indicates end-of-table */
|
||||
break;
|
||||
}
|
||||
|
||||
/* valid partition table */
|
||||
switch(partition->type) {
|
||||
case PART_TYPE_APP: /* app partition */
|
||||
@ -229,8 +234,15 @@ static bool ota_select_valid(const esp_ota_select_entry_t *s)
|
||||
|
||||
void bootloader_main()
|
||||
{
|
||||
/* Set CPU to 80MHz.
|
||||
Start by ensuring it is set to XTAL, as PLL must be off first
|
||||
(may still be on due to soft reset.)
|
||||
*/
|
||||
rtc_set_cpu_freq(CPU_XTAL);
|
||||
rtc_set_cpu_freq(CPU_80M);
|
||||
|
||||
uart_console_configure();
|
||||
ESP_LOGI(TAG, "Espressif ESP32 2nd stage bootloader v. %s", BOOT_VERSION);
|
||||
ESP_LOGI(TAG, "ESP-IDF %s 2nd stage bootloader", IDF_VER);
|
||||
#if defined(CONFIG_SECURE_BOOT_ENABLED) || defined(CONFIG_FLASH_ENCRYPTION_ENABLED)
|
||||
esp_err_t err;
|
||||
#endif
|
||||
@ -248,6 +260,9 @@ void bootloader_main()
|
||||
REG_CLR_BIT( TIMG_WDTCONFIG0_REG(0), TIMG_WDT_FLASHBOOT_MOD_EN );
|
||||
SPIUnlock();
|
||||
|
||||
ESP_LOGI(TAG, "Enabling RNG early entropy source...");
|
||||
bootloader_random_enable();
|
||||
|
||||
if(esp_image_load_header(0x1000, true, &fhdr) != ESP_OK) {
|
||||
ESP_LOGE(TAG, "failed to load bootloader header!");
|
||||
return;
|
||||
@ -359,6 +374,9 @@ void bootloader_main()
|
||||
}
|
||||
#endif
|
||||
|
||||
ESP_LOGI(TAG, "Disabling RNG early entropy source...");
|
||||
bootloader_random_disable();
|
||||
|
||||
// copy loaded segments to RAM, set up caches for mapped segments, and start application
|
||||
ESP_LOGI(TAG, "Loading app partition at offset %08x", load_part_pos);
|
||||
unpack_load_app(&load_part_pos);
|
||||
@ -663,49 +681,28 @@ void print_flash_info(const esp_image_header_t* phdr)
|
||||
#endif
|
||||
}
|
||||
|
||||
#if CONFIG_CONSOLE_UART_CUSTOM
|
||||
static uint32_t get_apb_freq(void)
|
||||
{
|
||||
// Get the value of APB clock from RTC memory.
|
||||
// The value is initialized in ROM code, and updated by librtc.a
|
||||
// when APB clock is changed.
|
||||
// This value is stored in RTC_CNTL_STORE5_REG as follows:
|
||||
// RTC_CNTL_STORE5_REG = (freq >> 12) | ((freq >> 12) << 16)
|
||||
uint32_t apb_freq_reg = REG_READ(RTC_CNTL_STORE5_REG);
|
||||
uint32_t apb_freq_l = apb_freq_reg & 0xffff;
|
||||
uint32_t apb_freq_h = apb_freq_reg >> 16;
|
||||
if (apb_freq_l == apb_freq_h && apb_freq_l != 0) {
|
||||
return apb_freq_l << 12;
|
||||
} else {
|
||||
// fallback value
|
||||
return APB_CLK_FREQ_ROM;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static void uart_console_configure(void)
|
||||
{
|
||||
#if CONFIG_CONSOLE_UART_NONE
|
||||
ets_install_putc1(NULL);
|
||||
ets_install_putc2(NULL);
|
||||
#else // CONFIG_CONSOLE_UART_NONE
|
||||
const int uart_num = CONFIG_CONSOLE_UART_NUM;
|
||||
|
||||
uartAttach();
|
||||
ets_install_uart_printf();
|
||||
|
||||
#if CONFIG_CONSOLE_UART_CUSTOM
|
||||
// Some constants to make the following code less upper-case
|
||||
const int uart_num = CONFIG_CONSOLE_UART_NUM;
|
||||
const int uart_baud = CONFIG_CONSOLE_UART_BAUDRATE;
|
||||
const int uart_tx_gpio = CONFIG_CONSOLE_UART_TX_GPIO;
|
||||
const int uart_rx_gpio = CONFIG_CONSOLE_UART_RX_GPIO;
|
||||
// ROM bootloader may have put a lot of text into UART0 FIFO.
|
||||
// Wait for it to be printed.
|
||||
uart_tx_wait_idle(0);
|
||||
|
||||
#if CONFIG_CONSOLE_UART_CUSTOM
|
||||
// Some constants to make the following code less upper-case
|
||||
const int uart_tx_gpio = CONFIG_CONSOLE_UART_TX_GPIO;
|
||||
const int uart_rx_gpio = CONFIG_CONSOLE_UART_RX_GPIO;
|
||||
// Switch to the new UART (this just changes UART number used for
|
||||
// ets_printf in ROM code).
|
||||
uart_tx_switch(uart_num);
|
||||
// Set new baud rate
|
||||
uart_div_modify(uart_num, (((uint64_t) get_apb_freq()) << 4) / uart_baud);
|
||||
// If console is attached to UART1 or if non-default pins are used,
|
||||
// need to reconfigure pins using GPIO matrix
|
||||
if (uart_num != 0 || uart_tx_gpio != 1 || uart_rx_gpio != 3) {
|
||||
@ -722,5 +719,19 @@ static void uart_console_configure(void)
|
||||
gpio_matrix_in(uart_rx_gpio, rx_idx, 0);
|
||||
}
|
||||
#endif // CONFIG_CONSOLE_UART_CUSTOM
|
||||
|
||||
// Set configured UART console baud rate
|
||||
const int uart_baud = CONFIG_CONSOLE_UART_BAUDRATE;
|
||||
uart_div_modify(uart_num, (APB_CLK_FREQ << 4) / uart_baud);
|
||||
|
||||
#endif // CONFIG_CONSOLE_UART_NONE
|
||||
}
|
||||
|
||||
/* empty rtc_printf implementation, to work with librtc
|
||||
linking. Can be removed once -lrtc is removed from bootloader's
|
||||
main component.mk.
|
||||
*/
|
||||
int rtc_printf(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
@ -5,8 +5,19 @@
|
||||
# we pull in bootloader-specific linker arguments.
|
||||
#
|
||||
|
||||
LINKER_SCRIPTS := esp32.bootloader.ld $(IDF_PATH)/components/esp32/ld/esp32.rom.ld
|
||||
LINKER_SCRIPTS := \
|
||||
esp32.bootloader.ld \
|
||||
$(IDF_PATH)/components/esp32/ld/esp32.rom.ld \
|
||||
esp32.bootloader.rom.ld
|
||||
|
||||
COMPONENT_ADD_LDFLAGS := -L $(COMPONENT_PATH) -lmain $(addprefix -T ,$(LINKER_SCRIPTS))
|
||||
|
||||
COMPONENT_ADD_LINKER_DEPS := $(LINKER_SCRIPTS)
|
||||
|
||||
ifdef IS_BOOTLOADER_BUILD
|
||||
# following lines are a workaround to link librtc into the
|
||||
# bootloader, until clock setting code is in a source-based esp-idf
|
||||
# component. See also rtc_printf() in bootloader_start.c
|
||||
COMPONENT_ADD_LDFLAGS += -L $(IDF_PATH)/components/esp32/lib/ -lrtc
|
||||
COMPONENT_EXTRA_INCLUDES += $(IDF_PATH)/components/esp32/
|
||||
endif
|
||||
|
@ -17,7 +17,7 @@ MEMORY
|
||||
dport0_seg (RW) : org = 0x3FF00000, len = 0x10 /* IO */
|
||||
iram_seg (RWX) : org = 0x40080000, len = 0x400 /* 1k of IRAM used by bootloader functions which need to flush/enable APP CPU cache */
|
||||
iram_pool_1_seg (RWX) : org = 0x40078000, len = 0x8000 /* IRAM POOL1, used for APP CPU cache. We can abuse it in bootloader because APP CPU is still held in reset, until we enable APP CPU cache */
|
||||
dram_seg (RW) : org = 0x3FFC0000, len = 0x20000 /* Shared RAM, minus rom bss/data/stack.*/
|
||||
dram_seg (RW) : org = 0x3FFF0000, len = 0x10000 /* 64k at the end of DRAM, after ROM bootloader stack */
|
||||
}
|
||||
|
||||
/* Default entry point: */
|
||||
|
1
components/bootloader/src/main/esp32.bootloader.rom.ld
Normal file
1
components/bootloader/src/main/esp32.bootloader.rom.ld
Normal file
@ -0,0 +1 @@
|
||||
PROVIDE ( ets_update_cpu_frequency = 0x40008550 ); /* Updates g_ticks_per_us on the current CPU only; not on the other core */
|
@ -16,6 +16,30 @@
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
/**
|
||||
* @brief Enable early entropy source for RNG
|
||||
*
|
||||
* Uses the SAR ADC to feed entropy into the HWRNG. The ADC is put
|
||||
* into a test mode that reads the 1.1V internal reference source and
|
||||
* feeds the LSB of data into the HWRNG.
|
||||
*
|
||||
* Can also be used from app code early during operation, if entropy
|
||||
* is required before WiFi stack is initialised. Call this function
|
||||
* from app code only if WiFi/BT are not yet enabled and I2S and SAR
|
||||
* ADC are not in use.
|
||||
*
|
||||
* Call bootloader_random_disable() when done.
|
||||
*/
|
||||
void bootloader_random_enable(void);
|
||||
|
||||
/**
|
||||
* @brief Disable early entropy source for RNG
|
||||
*
|
||||
* Disables SAR ADC source and resets the I2S hardware.
|
||||
*
|
||||
*/
|
||||
void bootloader_random_disable(void);
|
||||
|
||||
/**
|
||||
* @brief Fill buffer with 'length' random bytes
|
||||
*
|
||||
|
@ -12,37 +12,45 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#include "bootloader_random.h"
|
||||
#include "soc/cpu.h"
|
||||
#include "soc/wdev_reg.h"
|
||||
#include "soc/rtc_cntl_reg.h"
|
||||
#include "soc/sens_reg.h"
|
||||
#include "soc/syscon_reg.h"
|
||||
#include "soc/dport_reg.h"
|
||||
#include "soc/i2s_reg.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
#ifndef BOOTLOADER_BUILD
|
||||
#include "esp_system.h"
|
||||
#endif
|
||||
|
||||
const char *TAG = "boot_rng";
|
||||
|
||||
void bootloader_fill_random(void *buffer, size_t length)
|
||||
{
|
||||
uint8_t *buffer_bytes = (uint8_t *)buffer;
|
||||
uint32_t random;
|
||||
|
||||
/* TODO: enable HW RNG clock
|
||||
|
||||
Until this clock is enabled, this is not secure
|
||||
*/
|
||||
#ifdef BOOTLOADER_BUILD
|
||||
uint32_t start, now;
|
||||
#endif
|
||||
|
||||
for (int i = 0; i < length; i++) {
|
||||
if (i == 0 || i % 4 == 0) { /* redundant check is for a compiler warning */
|
||||
#ifdef BOOTLOADER_BUILD
|
||||
/* HW RNG generates 32 bits entropy per 16 APB cycles,
|
||||
in bootloader CPU clock == APB clock.
|
||||
/* in bootloader with ADC feeding HWRNG, we accumulate 1
|
||||
bit of entropy per 40 APB cycles (==80 CPU cycles.)
|
||||
|
||||
We are being conservative here and waiting at least
|
||||
that long, as loop shift overhead, etc will add more
|
||||
cycles.
|
||||
To avoid reading the entire RNG hardware state out
|
||||
as-is, we repeatedly read the RNG register and XOR all
|
||||
values.
|
||||
*/
|
||||
asm volatile("nop; nop; nop; nop;");
|
||||
asm volatile("nop; nop; nop; nop;");
|
||||
asm volatile("nop; nop; nop; nop;");
|
||||
asm volatile("nop; nop; nop; nop;");
|
||||
random = REG_READ(WDEV_RND_REG);
|
||||
RSR(CCOUNT, start);
|
||||
do {
|
||||
random ^= REG_READ(WDEV_RND_REG);
|
||||
RSR(CCOUNT, now);
|
||||
} while(now - start < 80*32*2); /* extra factor of 2 is precautionary */
|
||||
#else
|
||||
random = esp_random();
|
||||
#endif
|
||||
@ -51,3 +59,80 @@ void bootloader_fill_random(void *buffer, size_t length)
|
||||
buffer_bytes[i] = random >> ((i % 4) * 8);
|
||||
}
|
||||
}
|
||||
|
||||
void bootloader_random_enable(void)
|
||||
{
|
||||
/* Enable SAR ADC in test mode to feed ADC readings of the 1.1V
|
||||
reference via I2S into the RNG entropy input.
|
||||
|
||||
Note: I2S requires the PLL to be running, so the call to rtc_set_cpu_freq(CPU_80M)
|
||||
in early bootloader startup must have been made.
|
||||
*/
|
||||
SET_PERI_REG_BITS(RTC_CNTL_TEST_MUX_REG, RTC_CNTL_DTEST_RTC, 2, RTC_CNTL_DTEST_RTC_S);
|
||||
SET_PERI_REG_MASK(RTC_CNTL_TEST_MUX_REG, RTC_CNTL_ENT_RTC);
|
||||
SET_PERI_REG_MASK(SENS_SAR_START_FORCE_REG, SENS_SAR2_EN_TEST);
|
||||
|
||||
SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_I2S0_CLK_EN);
|
||||
CLEAR_PERI_REG_MASK(SENS_SAR_START_FORCE_REG, SENS_ULP_CP_FORCE_START_TOP);
|
||||
CLEAR_PERI_REG_MASK(SENS_SAR_START_FORCE_REG, SENS_ULP_CP_START_TOP);
|
||||
// Test pattern configuration byte 0xAD:
|
||||
//--[7:4] channel_sel: 10-->en_test
|
||||
//--[3:2] bit_width : 3-->12bit
|
||||
//--[1:0] atten : 1-->3dB attenuation
|
||||
WRITE_PERI_REG(SYSCON_SARADC_SAR2_PATT_TAB1_REG, 0xADADADAD);
|
||||
WRITE_PERI_REG(SYSCON_SARADC_SAR2_PATT_TAB2_REG, 0xADADADAD);
|
||||
WRITE_PERI_REG(SYSCON_SARADC_SAR2_PATT_TAB3_REG, 0xADADADAD);
|
||||
WRITE_PERI_REG(SYSCON_SARADC_SAR2_PATT_TAB4_REG, 0xADADADAD);
|
||||
|
||||
SET_PERI_REG_BITS(SENS_SAR_MEAS_WAIT2_REG, SENS_FORCE_XPD_SAR, 3, SENS_FORCE_XPD_SAR_S);
|
||||
SET_PERI_REG_MASK(SENS_SAR_READ_CTRL_REG, SENS_SAR1_DIG_FORCE);
|
||||
SET_PERI_REG_MASK(SENS_SAR_READ_CTRL2_REG, SENS_SAR2_DIG_FORCE);
|
||||
SET_PERI_REG_MASK(SYSCON_SARADC_CTRL_REG, SYSCON_SARADC_SAR2_MUX);
|
||||
SET_PERI_REG_BITS(SYSCON_SARADC_CTRL_REG, SYSCON_SARADC_SAR_CLK_DIV, 4, SYSCON_SARADC_SAR_CLK_DIV_S);
|
||||
|
||||
SET_PERI_REG_BITS(SYSCON_SARADC_FSM_REG, SYSCON_SARADC_RSTB_WAIT, 8, SYSCON_SARADC_RSTB_WAIT_S); /* was 1 */
|
||||
SET_PERI_REG_BITS(SYSCON_SARADC_FSM_REG, SYSCON_SARADC_START_WAIT, 10, SYSCON_SARADC_START_WAIT_S);
|
||||
SET_PERI_REG_BITS(SYSCON_SARADC_CTRL_REG, SYSCON_SARADC_WORK_MODE, 0, SYSCON_SARADC_WORK_MODE_S);
|
||||
SET_PERI_REG_MASK(SYSCON_SARADC_CTRL_REG, SYSCON_SARADC_SAR_SEL);
|
||||
CLEAR_PERI_REG_MASK(SYSCON_SARADC_CTRL_REG, SYSCON_SARADC_DATA_SAR_SEL);
|
||||
|
||||
SET_PERI_REG_BITS(I2S_SAMPLE_RATE_CONF_REG(0), I2S_RX_BCK_DIV_NUM, 20, I2S_RX_BCK_DIV_NUM_S);
|
||||
|
||||
SET_PERI_REG_MASK(SYSCON_SARADC_CTRL_REG,SYSCON_SARADC_DATA_TO_I2S);
|
||||
|
||||
CLEAR_PERI_REG_MASK(I2S_CONF2_REG(0), I2S_CAMERA_EN);
|
||||
SET_PERI_REG_MASK(I2S_CONF2_REG(0), I2S_LCD_EN);
|
||||
SET_PERI_REG_MASK(I2S_CONF2_REG(0), I2S_DATA_ENABLE);
|
||||
SET_PERI_REG_MASK(I2S_CONF2_REG(0), I2S_DATA_ENABLE_TEST_EN);
|
||||
SET_PERI_REG_MASK(I2S_CONF_REG(0), I2S_RX_START);
|
||||
}
|
||||
|
||||
void bootloader_random_disable(void)
|
||||
{
|
||||
/* Disable i2s clock */
|
||||
CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_I2S0_CLK_EN);
|
||||
|
||||
|
||||
/* Reset some i2s configuration (possibly redundant as we reset entire
|
||||
I2S peripheral further down). */
|
||||
CLEAR_PERI_REG_MASK(I2S_CONF2_REG(0), I2S_CAMERA_EN);
|
||||
CLEAR_PERI_REG_MASK(I2S_CONF2_REG(0), I2S_LCD_EN);
|
||||
CLEAR_PERI_REG_MASK(I2S_CONF2_REG(0), I2S_DATA_ENABLE_TEST_EN);
|
||||
CLEAR_PERI_REG_MASK(I2S_CONF2_REG(0), I2S_DATA_ENABLE);
|
||||
CLEAR_PERI_REG_MASK(I2S_CONF_REG(0), I2S_RX_START);
|
||||
|
||||
/* Restore SYSCON mode registers */
|
||||
CLEAR_PERI_REG_MASK(SENS_SAR_READ_CTRL_REG, SENS_SAR1_DIG_FORCE);
|
||||
CLEAR_PERI_REG_MASK(SENS_SAR_READ_CTRL2_REG, SENS_SAR2_DIG_FORCE);
|
||||
|
||||
/* Restore SAR ADC mode */
|
||||
CLEAR_PERI_REG_MASK(SENS_SAR_START_FORCE_REG, SENS_SAR2_EN_TEST);
|
||||
CLEAR_PERI_REG_MASK(SYSCON_SARADC_CTRL_REG, SYSCON_SARADC_SAR2_MUX
|
||||
| SYSCON_SARADC_SAR_SEL | SYSCON_SARADC_DATA_TO_I2S);
|
||||
SET_PERI_REG_BITS(SENS_SAR_MEAS_WAIT2_REG, SENS_FORCE_XPD_SAR, 0, SENS_FORCE_XPD_SAR_S);
|
||||
SET_PERI_REG_BITS(SYSCON_SARADC_FSM_REG, SYSCON_SARADC_START_WAIT, 8, SYSCON_SARADC_START_WAIT_S);
|
||||
|
||||
/* Reset i2s peripheral */
|
||||
SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_I2S0_RST);
|
||||
CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_I2S0_RST);
|
||||
}
|
||||
|
@ -78,12 +78,19 @@ static esp_err_t initialise_flash_encryption(void)
|
||||
&& REG_READ(EFUSE_BLK1_RDATA5_REG) == 0
|
||||
&& REG_READ(EFUSE_BLK1_RDATA6_REG) == 0
|
||||
&& REG_READ(EFUSE_BLK1_RDATA7_REG) == 0) {
|
||||
ESP_LOGI(TAG, "Generating new flash encryption key...");
|
||||
uint32_t buf[8];
|
||||
bootloader_fill_random(buf, sizeof(buf));
|
||||
for (int i = 0; i < 8; i++) {
|
||||
ESP_LOGV(TAG, "EFUSE_BLK1_WDATA%d_REG = 0x%08x", i, buf[i]);
|
||||
REG_WRITE(EFUSE_BLK1_WDATA0_REG + 4*i, buf[i]);
|
||||
}
|
||||
bzero(buf, sizeof(buf));
|
||||
esp_efuse_burn_new_values();
|
||||
|
||||
/* On-device key generation is temporarily disabled, until
|
||||
* RNG operation during bootloader is qualified.
|
||||
* See docs/security/flash-encryption.rst for details. */
|
||||
ESP_LOGE(TAG, "On-device key generation is not yet available.");
|
||||
return ESP_ERR_NOT_SUPPORTED;
|
||||
ESP_LOGI(TAG, "Read & write protecting new key...");
|
||||
REG_WRITE(EFUSE_BLK0_WDATA0_REG, EFUSE_WR_DIS_BLK1 | EFUSE_RD_DIS_BLK1);
|
||||
esp_efuse_burn_new_values();
|
||||
} else {
|
||||
|
||||
if(!(efuse_key_read_protected && efuse_key_write_protected)) {
|
||||
|
@ -13,18 +13,20 @@
|
||||
// limitations under the License.
|
||||
#include "esp_flash_partitions.h"
|
||||
#include "esp_log.h"
|
||||
#include "rom/spi_flash.h"
|
||||
|
||||
static const char *TAG = "flash_parts";
|
||||
|
||||
esp_err_t esp_partition_table_basic_verify(const esp_partition_info_t *partition_table, bool log_errors, int *num_partitions)
|
||||
{
|
||||
int num_parts;
|
||||
uint32_t chip_size = g_rom_flashchip.chip_size;
|
||||
*num_partitions = 0;
|
||||
|
||||
for(num_parts = 0; num_parts < ESP_PARTITION_TABLE_MAX_ENTRIES; num_parts++) {
|
||||
const esp_partition_info_t *part = &partition_table[num_parts];
|
||||
|
||||
if(part->magic == 0xFFFF
|
||||
if (part->magic == 0xFFFF
|
||||
&& part->type == PART_TYPE_END
|
||||
&& part->subtype == PART_SUBTYPE_END) {
|
||||
/* TODO: check md5 */
|
||||
@ -33,12 +35,21 @@ esp_err_t esp_partition_table_basic_verify(const esp_partition_info_t *partition
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
if(part->magic != ESP_PARTITION_MAGIC) {
|
||||
if (part->magic != ESP_PARTITION_MAGIC) {
|
||||
if (log_errors) {
|
||||
ESP_LOGE(TAG, "partition %d invalid magic number 0x%x", num_parts, part->magic);
|
||||
}
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
const esp_partition_pos_t *pos = &part->pos;
|
||||
if (pos->offset > chip_size || pos->offset + pos->size > chip_size) {
|
||||
if (log_errors) {
|
||||
ESP_LOGE(TAG, "partition %d invalid - offset 0x%x size 0x%x exceeds flash chip size 0x%x",
|
||||
num_parts, pos->offset, pos->size, chip_size);
|
||||
}
|
||||
return ESP_ERR_INVALID_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
if (log_errors) {
|
||||
|
@ -130,12 +130,21 @@ esp_err_t esp_secure_boot_permanently_enable(void) {
|
||||
&& REG_READ(EFUSE_BLK2_RDATA5_REG) == 0
|
||||
&& REG_READ(EFUSE_BLK2_RDATA6_REG) == 0
|
||||
&& REG_READ(EFUSE_BLK2_RDATA7_REG) == 0) {
|
||||
ESP_LOGI(TAG, "Generating new secure boot key...");
|
||||
uint32_t buf[8];
|
||||
bootloader_fill_random(buf, sizeof(buf));
|
||||
for (int i = 0; i < 8; i++) {
|
||||
ESP_LOGV(TAG, "EFUSE_BLK2_WDATA%d_REG = 0x%08x", i, buf[i]);
|
||||
REG_WRITE(EFUSE_BLK2_WDATA0_REG + 4*i, buf[i]);
|
||||
}
|
||||
bzero(buf, sizeof(buf));
|
||||
burn_efuses();
|
||||
ESP_LOGI(TAG, "Read & write protecting new key...");
|
||||
REG_WRITE(EFUSE_BLK0_WDATA0_REG, EFUSE_WR_DIS_BLK2 | EFUSE_RD_DIS_BLK2);
|
||||
burn_efuses();
|
||||
efuse_key_read_protected = true;
|
||||
efuse_key_write_protected = true;
|
||||
|
||||
/* On-device key generation is temporarily disabled, until
|
||||
* RNG operation during bootloader is qualified.
|
||||
* See docs/security/secure-boot.rst for details. */
|
||||
ESP_LOGE(TAG, "On-device key generation is not yet available.");
|
||||
return ESP_ERR_NOT_SUPPORTED;
|
||||
} else {
|
||||
ESP_LOGW(TAG, "Using pre-loaded secure boot key in EFUSE block 2");
|
||||
}
|
||||
|
@ -1,41 +1,24 @@
|
||||
menu "BT config"
|
||||
visible if MEMMAP_BT
|
||||
|
||||
|
||||
config BT_ENABLED
|
||||
bool
|
||||
depends on ESP32_ENABLE_STACK_BT
|
||||
menuconfig BT_ENABLED
|
||||
bool "Bluetooth"
|
||||
help
|
||||
This compiles in the low-level BT stack.
|
||||
Select this option to enable Bluetooth stack and show the submenu with Bluetooth configuration choices.
|
||||
|
||||
config BTC_TASK_STACK_SIZE
|
||||
int "BT event (callback to application) task stack size"
|
||||
int "Bluetooth event (callback to application) task stack size"
|
||||
depends on BT_ENABLED
|
||||
default 3072
|
||||
help
|
||||
This select btc task stack size
|
||||
|
||||
config BLUEDROID_MEM_DEBUG
|
||||
bool "Bluedroid memory debug"
|
||||
default no
|
||||
depends on BT_ENABLED
|
||||
default n
|
||||
help
|
||||
Bluedroid memory debug
|
||||
|
||||
#config BT_BTLE
|
||||
# bool "Enable BTLE"
|
||||
# depends on BT_ENABLED
|
||||
# help
|
||||
# This compiles BTLE support
|
||||
#
|
||||
#config BT_BT
|
||||
# bool "Enable classic BT"
|
||||
# depends on BT_ENABLED
|
||||
# help
|
||||
# This enables classic BT support
|
||||
|
||||
endmenu
|
||||
|
||||
# Memory reserved at start of DRAM for Bluetooth stack
|
||||
config BT_RESERVE_DRAM
|
||||
hex
|
||||
default 0x10000 if MEMMAP_BT
|
||||
default 0x10000 if BT_ENABLED
|
||||
default 0
|
||||
|
@ -22,22 +22,38 @@
|
||||
#include "btc_main.h"
|
||||
#include "future.h"
|
||||
|
||||
esp_err_t esp_blufi_register_callback(esp_profile_cb_t callback)
|
||||
esp_err_t esp_blufi_register_callbacks(esp_blufi_callbacks_t *callbacks)
|
||||
{
|
||||
return (btc_profile_cb_set(BTC_PID_BLUFI, callback) == 0 ? ESP_OK : ESP_FAIL);
|
||||
if (esp_bluedroid_get_status() == ESP_BLUEDROID_STATUS_UNINITIALIZED) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
if (callbacks == NULL) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
btc_blufi_set_callbacks(callbacks);
|
||||
return (btc_profile_cb_set(BTC_PID_BLUFI, callbacks->event_cb) == 0 ? ESP_OK : ESP_FAIL);
|
||||
}
|
||||
|
||||
esp_err_t esp_blufi_send_config_state(esp_blufi_config_state_t state)
|
||||
esp_err_t esp_blufi_send_wifi_conn_report(wifi_mode_t opmode, esp_blufi_sta_conn_state_t sta_conn_state, uint8_t softap_conn_num, esp_blufi_extra_info_t *extra_info)
|
||||
{
|
||||
btc_msg_t msg;
|
||||
btc_blufi_args_t arg;
|
||||
|
||||
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
msg.sig = BTC_SIG_API_CALL;
|
||||
msg.pid = BTC_PID_BLUFI;
|
||||
msg.act = BTC_BLUFI_ACT_SEND_CFG_STATE;
|
||||
arg.cfg_state.state = state;
|
||||
msg.act = BTC_BLUFI_ACT_SEND_CFG_REPORT;
|
||||
arg.wifi_conn_report.opmode = opmode;
|
||||
arg.wifi_conn_report.sta_conn_state = sta_conn_state;
|
||||
arg.wifi_conn_report.softap_conn_num = softap_conn_num;
|
||||
arg.wifi_conn_report.extra_info = extra_info;
|
||||
|
||||
return (btc_transfer_context(&msg, &arg, sizeof(btc_blufi_args_t), NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
|
||||
return (btc_transfer_context(&msg, &arg, sizeof(btc_blufi_args_t), btc_blufi_call_deep_copy) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
|
||||
}
|
||||
|
||||
|
||||
@ -45,6 +61,10 @@ esp_err_t esp_blufi_profile_init(void)
|
||||
{
|
||||
btc_msg_t msg;
|
||||
|
||||
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
msg.sig = BTC_SIG_API_CALL;
|
||||
msg.pid = BTC_PID_BLUFI;
|
||||
msg.act = BTC_BLUFI_ACT_INIT;
|
||||
@ -56,6 +76,10 @@ esp_err_t esp_blufi_profile_deinit(void)
|
||||
{
|
||||
btc_msg_t msg;
|
||||
|
||||
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
msg.sig = BTC_SIG_API_CALL;
|
||||
msg.pid = BTC_PID_BLUFI;
|
||||
msg.act = BTC_BLUFI_ACT_DEINIT;
|
||||
@ -63,4 +87,8 @@ esp_err_t esp_blufi_profile_deinit(void)
|
||||
return (btc_transfer_context(&msg, NULL, 0, NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
|
||||
}
|
||||
|
||||
uint16_t esp_blufi_get_version(void)
|
||||
{
|
||||
return btc_blufi_get_version();
|
||||
}
|
||||
|
||||
|
26
components/bt/bluedroid/api/esp_bt_device.c
Normal file
26
components/bt/bluedroid/api/esp_bt_device.c
Normal file
@ -0,0 +1,26 @@
|
||||
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// 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.
|
||||
|
||||
|
||||
#include "esp_bt_device.h"
|
||||
#include "esp_bt_main.h"
|
||||
#include "controller.h"
|
||||
|
||||
const uint8_t *esp_bt_dev_get_address(void)
|
||||
{
|
||||
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
|
||||
return NULL;
|
||||
}
|
||||
return controller_get_interface()->get_address()->address;
|
||||
}
|
@ -21,7 +21,20 @@
|
||||
static bool esp_already_enable = false;
|
||||
static bool esp_already_init = false;
|
||||
|
||||
esp_err_t esp_enable_bluetooth(void)
|
||||
esp_bluedroid_status_t esp_bluedroid_get_status(void)
|
||||
{
|
||||
if (esp_already_init) {
|
||||
if (esp_already_enable) {
|
||||
return ESP_BLUEDROID_STATUS_ENABLED;
|
||||
} else {
|
||||
return ESP_BLUEDROID_STATUS_INITIALIZED;
|
||||
}
|
||||
} else {
|
||||
return ESP_BLUEDROID_STATUS_UNINITIALIZED;
|
||||
}
|
||||
}
|
||||
|
||||
esp_err_t esp_bluedroid_enable(void)
|
||||
{
|
||||
btc_msg_t msg;
|
||||
future_t **future_p;
|
||||
@ -53,7 +66,7 @@ esp_err_t esp_enable_bluetooth(void)
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_disable_bluetooth(void)
|
||||
esp_err_t esp_bluedroid_disable(void)
|
||||
{
|
||||
btc_msg_t msg;
|
||||
future_t **future_p;
|
||||
@ -85,7 +98,7 @@ esp_err_t esp_disable_bluetooth(void)
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_init_bluetooth(void)
|
||||
esp_err_t esp_bluedroid_init(void)
|
||||
{
|
||||
btc_msg_t msg;
|
||||
future_t **future_p;
|
||||
@ -114,13 +127,13 @@ esp_err_t esp_init_bluetooth(void)
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
esp_already_init = true;;
|
||||
esp_already_init = true;
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
|
||||
esp_err_t esp_deinit_bluetooth(void)
|
||||
esp_err_t esp_bluedroid_deinit(void)
|
||||
{
|
||||
btc_msg_t msg;
|
||||
future_t **future_p;
|
||||
|
@ -14,6 +14,7 @@
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "esp_bt_main.h"
|
||||
#include "esp_gap_ble_api.h"
|
||||
#include "bta_api.h"
|
||||
#include "bt_trace.h"
|
||||
@ -21,8 +22,11 @@
|
||||
#include "btc_gap_ble.h"
|
||||
|
||||
|
||||
esp_err_t esp_ble_gap_register_callback(esp_profile_cb_t callback)
|
||||
esp_err_t esp_ble_gap_register_callback(esp_gap_ble_cb_t callback)
|
||||
{
|
||||
if (esp_bluedroid_get_status() == ESP_BLUEDROID_STATUS_UNINITIALIZED) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
return (btc_profile_cb_set(BTC_PID_GAP_BLE, callback) == 0 ? ESP_OK : ESP_FAIL);
|
||||
}
|
||||
|
||||
@ -32,6 +36,10 @@ esp_err_t esp_ble_gap_config_adv_data(esp_ble_adv_data_t *adv_data)
|
||||
btc_msg_t msg;
|
||||
btc_ble_gap_args_t arg;
|
||||
|
||||
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
if (adv_data == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
@ -55,6 +63,10 @@ esp_err_t esp_ble_gap_set_scan_params(esp_ble_scan_params_t *scan_params)
|
||||
btc_msg_t msg;
|
||||
btc_ble_gap_args_t arg;
|
||||
|
||||
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
if (scan_params == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
@ -72,6 +84,10 @@ esp_err_t esp_ble_gap_start_scanning(uint32_t duration)
|
||||
btc_msg_t msg;
|
||||
btc_ble_gap_args_t arg;
|
||||
|
||||
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
msg.sig = BTC_SIG_API_CALL;
|
||||
msg.pid = BTC_PID_GAP_BLE;
|
||||
msg.act = BTC_GAP_BLE_ACT_START_SCAN;
|
||||
@ -85,6 +101,10 @@ esp_err_t esp_ble_gap_stop_scanning(void)
|
||||
{
|
||||
btc_msg_t msg;
|
||||
|
||||
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
msg.sig = BTC_SIG_API_CALL;
|
||||
msg.pid = BTC_PID_GAP_BLE;
|
||||
msg.act = BTC_GAP_BLE_ACT_STOP_SCAN;
|
||||
@ -96,6 +116,10 @@ esp_err_t esp_ble_gap_start_advertising(esp_ble_adv_params_t *adv_params)
|
||||
btc_msg_t msg;
|
||||
btc_ble_gap_args_t arg;
|
||||
|
||||
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
msg.sig = BTC_SIG_API_CALL;
|
||||
msg.pid = BTC_PID_GAP_BLE;
|
||||
msg.act = BTC_GAP_BLE_ACT_START_ADV;
|
||||
@ -108,6 +132,10 @@ esp_err_t esp_ble_gap_stop_advertising(void)
|
||||
{
|
||||
btc_msg_t msg;
|
||||
|
||||
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
msg.sig = BTC_SIG_API_CALL;
|
||||
msg.pid = BTC_PID_GAP_BLE;
|
||||
msg.act = BTC_GAP_BLE_ACT_STOP_ADV;
|
||||
@ -121,6 +149,10 @@ esp_err_t esp_ble_gap_update_conn_params(esp_ble_conn_update_params_t *params)
|
||||
btc_msg_t msg;
|
||||
btc_ble_gap_args_t arg;
|
||||
|
||||
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
msg.sig = BTC_SIG_API_CALL;
|
||||
msg.pid = BTC_PID_GAP_BLE;
|
||||
msg.act = BTC_GAP_BLE_ACT_UPDATE_CONN_PARAM;
|
||||
@ -134,6 +166,10 @@ esp_err_t esp_ble_gap_set_pkt_data_len(esp_bd_addr_t remote_device, uint16_t tx_
|
||||
btc_msg_t msg;
|
||||
btc_ble_gap_args_t arg;
|
||||
|
||||
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
msg.sig = BTC_SIG_API_CALL;
|
||||
msg.pid = BTC_PID_GAP_BLE;
|
||||
msg.act = BTC_GAP_BLE_ACT_SET_PKT_DATA_LEN;
|
||||
@ -149,6 +185,10 @@ esp_err_t esp_ble_gap_set_rand_addr(esp_bd_addr_t rand_addr)
|
||||
btc_msg_t msg;
|
||||
btc_ble_gap_args_t arg;
|
||||
|
||||
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
msg.sig = BTC_SIG_API_CALL;
|
||||
msg.pid = BTC_PID_GAP_BLE;
|
||||
msg.act = BTC_GAP_BLE_ACT_SET_RAND_ADDRESS;
|
||||
@ -163,6 +203,10 @@ esp_err_t esp_ble_gap_config_local_privacy (bool privacy_enable)
|
||||
btc_msg_t msg;
|
||||
btc_ble_gap_args_t arg;
|
||||
|
||||
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
msg.sig = BTC_SIG_API_CALL;
|
||||
msg.pid = BTC_PID_GAP_BLE;
|
||||
msg.act = BTC_GAP_BLE_ACT_CONFIG_LOCAL_PRIVACY;
|
||||
@ -176,6 +220,10 @@ esp_err_t esp_ble_gap_set_device_name(const char *name)
|
||||
btc_msg_t msg;
|
||||
btc_ble_gap_args_t arg;
|
||||
|
||||
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
if (strlen(name) > ESP_GAP_DEVICE_NAME_MAX) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
@ -15,11 +15,17 @@
|
||||
#include <string.h>
|
||||
|
||||
#include "esp_gattc_api.h"
|
||||
#include "esp_bt_main.h"
|
||||
#include "btc_manage.h"
|
||||
#include "btc_gattc.h"
|
||||
#include "btc_gatt_util.h"
|
||||
|
||||
esp_err_t esp_ble_gattc_register_callback(esp_profile_cb_t callback)
|
||||
esp_err_t esp_ble_gattc_register_callback(esp_gattc_cb_t callback)
|
||||
{
|
||||
if (esp_bluedroid_get_status() == ESP_BLUEDROID_STATUS_UNINITIALIZED) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
if (callback == NULL) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
@ -33,7 +39,10 @@ esp_err_t esp_ble_gattc_app_register(uint16_t app_id)
|
||||
btc_msg_t msg;
|
||||
btc_ble_gattc_args_t arg;
|
||||
|
||||
//if (app_id < ESP_APP_ID_MIN || app_id > ESP_APP_ID_MAX) {
|
||||
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
if (app_id > ESP_APP_ID_MAX) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
@ -46,52 +55,68 @@ esp_err_t esp_ble_gattc_app_register(uint16_t app_id)
|
||||
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gattc_args_t), NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_gattc_app_unregister(esp_gatt_if_t gatt_if)
|
||||
esp_err_t esp_ble_gattc_app_unregister(esp_gatt_if_t gattc_if)
|
||||
{
|
||||
btc_msg_t msg;
|
||||
btc_ble_gattc_args_t arg;
|
||||
|
||||
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
msg.sig = BTC_SIG_API_CALL;
|
||||
msg.pid = BTC_PID_GATTC;
|
||||
msg.act = BTC_GATTC_ACT_APP_UNREGISTER;
|
||||
arg.app_unreg.gatt_if = gatt_if;
|
||||
arg.app_unreg.gattc_if = gattc_if;
|
||||
|
||||
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gattc_args_t), NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_gattc_open(esp_gatt_if_t gatt_if, esp_bd_addr_t remote_bda, bool is_direct)
|
||||
esp_err_t esp_ble_gattc_open(esp_gatt_if_t gattc_if, esp_bd_addr_t remote_bda, bool is_direct)
|
||||
{
|
||||
btc_msg_t msg;
|
||||
btc_ble_gattc_args_t arg;
|
||||
|
||||
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
msg.sig = BTC_SIG_API_CALL;
|
||||
msg.pid = BTC_PID_GATTC;
|
||||
msg.act = BTC_GATTC_ACT_OPEN;
|
||||
arg.open.gatt_if = gatt_if;
|
||||
arg.open.gattc_if = gattc_if;
|
||||
memcpy(arg.open.remote_bda, remote_bda, ESP_BD_ADDR_LEN);
|
||||
arg.open.is_direct = is_direct;
|
||||
|
||||
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gattc_args_t), NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_gattc_close (uint16_t conn_id)
|
||||
esp_err_t esp_ble_gattc_close (esp_gatt_if_t gattc_if, uint16_t conn_id)
|
||||
{
|
||||
btc_msg_t msg;
|
||||
btc_ble_gattc_args_t arg;
|
||||
|
||||
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
msg.sig = BTC_SIG_API_CALL;
|
||||
msg.pid = BTC_PID_GATTC;
|
||||
msg.act = BTC_GATTC_ACT_CLOSE;
|
||||
arg.close.conn_id = conn_id;
|
||||
arg.close.conn_id = BTC_GATT_CREATE_CONN_ID(gattc_if, conn_id);
|
||||
|
||||
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gattc_args_t), NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_gattc_config_mtu (uint16_t conn_id, uint16_t mtu)
|
||||
esp_err_t esp_ble_gattc_config_mtu (esp_gatt_if_t gattc_if, uint16_t conn_id, uint16_t mtu)
|
||||
{
|
||||
btc_msg_t msg;
|
||||
btc_ble_gattc_args_t arg;
|
||||
|
||||
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
if ((mtu < ESP_GATT_DEF_BLE_MTU_SIZE) || (mtu > ESP_GATT_MAX_MTU_SIZE)) {
|
||||
return ESP_GATT_ILLEGAL_PARAMETER;
|
||||
}
|
||||
@ -99,21 +124,26 @@ esp_err_t esp_ble_gattc_config_mtu (uint16_t conn_id, uint16_t mtu)
|
||||
msg.sig = BTC_SIG_API_CALL;
|
||||
msg.pid = BTC_PID_GATTC;
|
||||
msg.act = BTC_GATTC_ACT_CFG_MTU;
|
||||
arg.cfg_mtu.conn_id = conn_id;
|
||||
arg.cfg_mtu.conn_id = BTC_GATT_CREATE_CONN_ID(gattc_if, conn_id);
|
||||
arg.cfg_mtu.mtu = mtu;
|
||||
|
||||
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gattc_args_t), NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_gattc_search_service(uint16_t conn_id, esp_bt_uuid_t *filter_uuid)
|
||||
esp_err_t esp_ble_gattc_search_service(esp_gatt_if_t gattc_if, uint16_t conn_id, esp_bt_uuid_t *filter_uuid)
|
||||
{
|
||||
btc_msg_t msg;
|
||||
btc_ble_gattc_args_t arg;
|
||||
|
||||
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
msg.sig = BTC_SIG_API_CALL;
|
||||
msg.pid = BTC_PID_GATTC;
|
||||
msg.act = BTC_GATTC_ACT_SEARCH_SERVICE;
|
||||
arg.search_srvc.conn_id = conn_id;
|
||||
arg.search_srvc.conn_id = BTC_GATT_CREATE_CONN_ID(gattc_if, conn_id);
|
||||
|
||||
if (filter_uuid) {
|
||||
arg.search_srvc.filter_uuid_enable = true;
|
||||
memcpy(&arg.search_srvc.filter_uuid, filter_uuid, sizeof(esp_bt_uuid_t));
|
||||
@ -124,22 +154,27 @@ esp_err_t esp_ble_gattc_search_service(uint16_t conn_id, esp_bt_uuid_t *filter_u
|
||||
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gattc_args_t), NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_gattc_get_characteristic(uint16_t conn_id,
|
||||
esp_err_t esp_ble_gattc_get_characteristic(esp_gatt_if_t gattc_if,
|
||||
uint16_t conn_id,
|
||||
esp_gatt_srvc_id_t *srvc_id,
|
||||
esp_gatt_id_t *start_char_id)
|
||||
{
|
||||
btc_msg_t msg;
|
||||
btc_ble_gattc_args_t arg;
|
||||
|
||||
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
msg.sig = BTC_SIG_API_CALL;
|
||||
msg.pid = BTC_PID_GATTC;
|
||||
if (start_char_id) {
|
||||
arg.get_next_char.conn_id = conn_id;
|
||||
arg.get_next_char.conn_id = BTC_GATT_CREATE_CONN_ID(gattc_if, conn_id);
|
||||
memcpy(&arg.get_next_char.service_id, srvc_id, sizeof(esp_gatt_srvc_id_t));
|
||||
memcpy(&arg.get_next_char.char_id, start_char_id, sizeof(esp_gatt_id_t));
|
||||
msg.act = BTC_GATTC_ACT_GET_NEXT_CHAR;
|
||||
} else {
|
||||
arg.get_first_char.conn_id = conn_id;
|
||||
arg.get_first_char.conn_id = BTC_GATT_CREATE_CONN_ID(gattc_if, conn_id);
|
||||
memcpy(&arg.get_first_char.service_id, srvc_id, sizeof(esp_gatt_srvc_id_t));
|
||||
msg.act = BTC_GATTC_ACT_GET_FIRST_CHAR;
|
||||
}
|
||||
@ -147,7 +182,8 @@ esp_err_t esp_ble_gattc_get_characteristic(uint16_t conn_id,
|
||||
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gattc_args_t), NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_gattc_get_descriptor(uint16_t conn_id,
|
||||
esp_err_t esp_ble_gattc_get_descriptor(esp_gatt_if_t gattc_if,
|
||||
uint16_t conn_id,
|
||||
esp_gatt_srvc_id_t *srvc_id,
|
||||
esp_gatt_id_t *char_id,
|
||||
esp_gatt_id_t *start_descr_id)
|
||||
@ -155,17 +191,21 @@ esp_err_t esp_ble_gattc_get_descriptor(uint16_t conn_id,
|
||||
btc_msg_t msg;
|
||||
btc_ble_gattc_args_t arg;
|
||||
|
||||
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
msg.sig = BTC_SIG_API_CALL;
|
||||
msg.pid = BTC_PID_GATTC;
|
||||
|
||||
if (start_descr_id) {
|
||||
arg.get_next_descr.conn_id = conn_id;
|
||||
arg.get_next_descr.conn_id = BTC_GATT_CREATE_CONN_ID(gattc_if, conn_id);
|
||||
memcpy(&arg.get_next_descr.service_id, srvc_id, sizeof(esp_gatt_srvc_id_t));
|
||||
memcpy(&arg.get_next_descr.char_id, char_id, sizeof(esp_gatt_id_t));
|
||||
memcpy(&arg.get_next_descr.descr_id, start_descr_id, sizeof(esp_gatt_id_t));
|
||||
msg.act = BTC_GATTC_ACT_GET_NEXT_DESCR;
|
||||
} else {
|
||||
arg.get_first_descr.conn_id = conn_id;
|
||||
arg.get_first_descr.conn_id = BTC_GATT_CREATE_CONN_ID(gattc_if, conn_id);
|
||||
memcpy(&arg.get_first_descr.service_id, srvc_id, sizeof(esp_gatt_srvc_id_t));
|
||||
memcpy(&arg.get_first_descr.char_id, char_id, sizeof(esp_gatt_id_t));
|
||||
msg.act = BTC_GATTC_ACT_GET_FIRST_DESCR;
|
||||
@ -174,23 +214,28 @@ esp_err_t esp_ble_gattc_get_descriptor(uint16_t conn_id,
|
||||
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gattc_args_t), NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_gattc_get_included_service(uint16_t conn_id,
|
||||
esp_err_t esp_ble_gattc_get_included_service(esp_gatt_if_t gattc_if,
|
||||
uint16_t conn_id,
|
||||
esp_gatt_srvc_id_t *srvc_id,
|
||||
esp_gatt_srvc_id_t *start_incl_srvc_id)
|
||||
{
|
||||
btc_msg_t msg;
|
||||
btc_ble_gattc_args_t arg;
|
||||
|
||||
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
msg.sig = BTC_SIG_API_CALL;
|
||||
msg.pid = BTC_PID_GATTC;
|
||||
|
||||
if (start_incl_srvc_id) {
|
||||
arg.get_next_incl_srvc.conn_id = conn_id;
|
||||
arg.get_next_incl_srvc.conn_id = BTC_GATT_CREATE_CONN_ID(gattc_if, conn_id);
|
||||
memcpy(&arg.get_next_incl_srvc.service_id, srvc_id, sizeof(esp_gatt_srvc_id_t));
|
||||
memcpy(&arg.get_next_incl_srvc.start_service_id, start_incl_srvc_id, sizeof(esp_gatt_srvc_id_t));
|
||||
msg.act = BTC_GATTC_ACT_GET_NEXT_INCL_SERVICE;
|
||||
} else {
|
||||
arg.get_first_incl_srvc.conn_id = conn_id;
|
||||
arg.get_first_incl_srvc.conn_id = BTC_GATT_CREATE_CONN_ID(gattc_if, conn_id);
|
||||
memcpy(&arg.get_first_incl_srvc.service_id, srvc_id, sizeof(esp_gatt_srvc_id_t));
|
||||
msg.act = BTC_GATTC_ACT_GET_FIRST_INCL_SERVICE;
|
||||
}
|
||||
@ -198,16 +243,23 @@ esp_err_t esp_ble_gattc_get_included_service(uint16_t conn_id,
|
||||
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gattc_args_t), NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_gattc_read_char (uint16_t conn_id, esp_gatt_srvc_id_t *srvc_id,
|
||||
esp_gatt_id_t *char_id, esp_gatt_auth_req_t auth_req)
|
||||
esp_err_t esp_ble_gattc_read_char (esp_gatt_if_t gattc_if,
|
||||
uint16_t conn_id,
|
||||
esp_gatt_srvc_id_t *srvc_id,
|
||||
esp_gatt_id_t *char_id,
|
||||
esp_gatt_auth_req_t auth_req)
|
||||
{
|
||||
btc_msg_t msg;
|
||||
btc_ble_gattc_args_t arg;
|
||||
|
||||
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
msg.sig = BTC_SIG_API_CALL;
|
||||
msg.pid = BTC_PID_GATTC;
|
||||
msg.act = BTC_GATTC_ACT_READ_CHAR;
|
||||
arg.read_char.conn_id = conn_id;
|
||||
arg.read_char.conn_id = BTC_GATT_CREATE_CONN_ID(gattc_if, conn_id);
|
||||
memcpy(&arg.read_char.service_id, srvc_id, sizeof(esp_gatt_srvc_id_t));
|
||||
memcpy(&arg.read_char.char_id, char_id, sizeof(esp_gatt_id_t));
|
||||
arg.read_char.auth_req = auth_req;
|
||||
@ -215,7 +267,8 @@ esp_err_t esp_ble_gattc_read_char (uint16_t conn_id, esp_gatt_srvc_id_t *srvc_id
|
||||
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gattc_args_t), NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_gattc_read_char_descr (uint16_t conn_id,
|
||||
esp_err_t esp_ble_gattc_read_char_descr (esp_gatt_if_t gattc_if,
|
||||
uint16_t conn_id,
|
||||
esp_gatt_srvc_id_t *srvc_id,
|
||||
esp_gatt_id_t *char_id,
|
||||
esp_gatt_id_t *descr_id,
|
||||
@ -224,10 +277,14 @@ esp_err_t esp_ble_gattc_read_char_descr (uint16_t conn_id,
|
||||
btc_msg_t msg;
|
||||
btc_ble_gattc_args_t arg;
|
||||
|
||||
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
msg.sig = BTC_SIG_API_CALL;
|
||||
msg.pid = BTC_PID_GATTC;
|
||||
msg.act = BTC_GATTC_ACT_READ_CHAR_DESCR;
|
||||
arg.read_descr.conn_id = conn_id;
|
||||
arg.read_descr.conn_id = BTC_GATT_CREATE_CONN_ID(gattc_if, conn_id);
|
||||
memcpy(&arg.read_descr.service_id, srvc_id, sizeof(esp_gatt_srvc_id_t));
|
||||
memcpy(&arg.read_descr.char_id, char_id, sizeof(esp_gatt_id_t));
|
||||
memcpy(&arg.read_descr.descr_id, descr_id, sizeof(esp_gatt_id_t));
|
||||
@ -236,7 +293,8 @@ esp_err_t esp_ble_gattc_read_char_descr (uint16_t conn_id,
|
||||
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gattc_args_t), NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_gattc_write_char( uint16_t conn_id,
|
||||
esp_err_t esp_ble_gattc_write_char( esp_gatt_if_t gattc_if,
|
||||
uint16_t conn_id,
|
||||
esp_gatt_srvc_id_t *srvc_id,
|
||||
esp_gatt_id_t *char_id,
|
||||
uint16_t value_len,
|
||||
@ -247,10 +305,14 @@ esp_err_t esp_ble_gattc_write_char( uint16_t conn_id,
|
||||
btc_msg_t msg;
|
||||
btc_ble_gattc_args_t arg;
|
||||
|
||||
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
msg.sig = BTC_SIG_API_CALL;
|
||||
msg.pid = BTC_PID_GATTC;
|
||||
msg.act = BTC_GATTC_ACT_WRITE_CHAR;
|
||||
arg.write_char.conn_id = (uint16_t) conn_id;
|
||||
arg.write_char.conn_id = BTC_GATT_CREATE_CONN_ID(gattc_if, conn_id);
|
||||
memcpy(&arg.write_char.service_id, srvc_id, sizeof(esp_gatt_srvc_id_t));
|
||||
memcpy(&arg.write_char.char_id, char_id, sizeof(esp_gatt_id_t));
|
||||
arg.write_char.value_len = value_len > ESP_GATT_MAX_ATTR_LEN ? ESP_GATT_MAX_ATTR_LEN : value_len;
|
||||
@ -261,7 +323,8 @@ esp_err_t esp_ble_gattc_write_char( uint16_t conn_id,
|
||||
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gattc_args_t), btc_gattc_arg_deep_copy) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_gattc_write_char_descr (uint16_t conn_id,
|
||||
esp_err_t esp_ble_gattc_write_char_descr (esp_gatt_if_t gattc_if,
|
||||
uint16_t conn_id,
|
||||
esp_gatt_srvc_id_t *srvc_id,
|
||||
esp_gatt_id_t *char_id,
|
||||
esp_gatt_id_t *descr_id,
|
||||
@ -273,10 +336,14 @@ esp_err_t esp_ble_gattc_write_char_descr (uint16_t conn_id,
|
||||
btc_msg_t msg;
|
||||
btc_ble_gattc_args_t arg;
|
||||
|
||||
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
msg.sig = BTC_SIG_API_CALL;
|
||||
msg.pid = BTC_PID_GATTC;
|
||||
msg.act = BTC_GATTC_ACT_WRITE_CHAR_DESCR;
|
||||
arg.write_descr.conn_id = (uint16_t) conn_id;
|
||||
arg.write_descr.conn_id = BTC_GATT_CREATE_CONN_ID(gattc_if, conn_id);
|
||||
memcpy(&arg.write_descr.service_id, srvc_id, sizeof(esp_gatt_srvc_id_t));
|
||||
memcpy(&arg.write_descr.char_id, char_id, sizeof(esp_gatt_id_t));
|
||||
memcpy(&arg.write_descr.descr_id, descr_id, sizeof(esp_gatt_id_t));
|
||||
@ -288,7 +355,8 @@ esp_err_t esp_ble_gattc_write_char_descr (uint16_t conn_id,
|
||||
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gattc_args_t), btc_gattc_arg_deep_copy) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_gattc_prepare_write(uint16_t conn_id,
|
||||
esp_err_t esp_ble_gattc_prepare_write(esp_gatt_if_t gattc_if,
|
||||
uint16_t conn_id,
|
||||
esp_gatt_srvc_id_t *srvc_id,
|
||||
esp_gatt_id_t *char_id,
|
||||
uint16_t offset,
|
||||
@ -300,10 +368,14 @@ esp_err_t esp_ble_gattc_prepare_write(uint16_t conn_id,
|
||||
btc_msg_t msg;
|
||||
btc_ble_gattc_args_t arg;
|
||||
|
||||
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
msg.sig = BTC_SIG_API_CALL;
|
||||
msg.pid = BTC_PID_GATTC;
|
||||
msg.act = BTC_GATTC_ACT_PREPARE_WRITE;
|
||||
arg.prep_write.conn_id = conn_id;
|
||||
arg.prep_write.conn_id = BTC_GATT_CREATE_CONN_ID(gattc_if, conn_id);
|
||||
memcpy(&arg.prep_write.service_id, srvc_id, sizeof(esp_gatt_srvc_id_t));
|
||||
memcpy(&arg.prep_write.char_id, char_id, sizeof(esp_gatt_id_t));
|
||||
arg.prep_write.offset = offset;
|
||||
@ -314,21 +386,25 @@ esp_err_t esp_ble_gattc_prepare_write(uint16_t conn_id,
|
||||
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gattc_args_t), btc_gattc_arg_deep_copy) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_gattc_execute_write (uint16_t conn_id, bool is_execute)
|
||||
esp_err_t esp_ble_gattc_execute_write (esp_gatt_if_t gattc_if, uint16_t conn_id, bool is_execute)
|
||||
{
|
||||
btc_msg_t msg;
|
||||
btc_ble_gattc_args_t arg;
|
||||
|
||||
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
msg.sig = BTC_SIG_API_CALL;
|
||||
msg.pid = BTC_PID_GATTC;
|
||||
msg.act = BTC_GATTC_ACT_EXECUTE_WRITE;
|
||||
arg.exec_write.conn_id = conn_id;
|
||||
arg.exec_write.conn_id = BTC_GATT_CREATE_CONN_ID(gattc_if, conn_id);
|
||||
arg.exec_write.is_execute = is_execute;
|
||||
|
||||
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gattc_args_t), NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
|
||||
}
|
||||
|
||||
esp_gatt_status_t esp_ble_gattc_register_for_notify (esp_gatt_if_t gatt_if,
|
||||
esp_gatt_status_t esp_ble_gattc_register_for_notify (esp_gatt_if_t gattc_if,
|
||||
esp_bd_addr_t server_bda,
|
||||
esp_gatt_srvc_id_t *srvc_id,
|
||||
esp_gatt_id_t *char_id)
|
||||
@ -336,10 +412,14 @@ esp_gatt_status_t esp_ble_gattc_register_for_notify (esp_gatt_if_t gatt_if,
|
||||
btc_msg_t msg;
|
||||
btc_ble_gattc_args_t arg;
|
||||
|
||||
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
msg.sig = BTC_SIG_API_CALL;
|
||||
msg.pid = BTC_PID_GATTC;
|
||||
msg.act = BTC_GATTC_ACT_REG_FOR_NOTIFY;
|
||||
arg.reg_for_notify.gatt_if = gatt_if;
|
||||
arg.reg_for_notify.gattc_if = gattc_if;
|
||||
memcpy(arg.reg_for_notify.remote_bda, server_bda, sizeof(esp_bd_addr_t));
|
||||
memcpy(&arg.reg_for_notify.service_id, srvc_id, sizeof(esp_gatt_srvc_id_t));
|
||||
memcpy(&arg.reg_for_notify.char_id, char_id, sizeof(esp_gatt_id_t));
|
||||
@ -347,7 +427,7 @@ esp_gatt_status_t esp_ble_gattc_register_for_notify (esp_gatt_if_t gatt_if,
|
||||
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gattc_args_t), NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
|
||||
}
|
||||
|
||||
esp_gatt_status_t esp_ble_gattc_unregister_for_notify (esp_gatt_if_t gatt_if,
|
||||
esp_gatt_status_t esp_ble_gattc_unregister_for_notify (esp_gatt_if_t gattc_if,
|
||||
esp_bd_addr_t server_bda,
|
||||
esp_gatt_srvc_id_t *srvc_id,
|
||||
esp_gatt_id_t *char_id)
|
||||
@ -355,10 +435,14 @@ esp_gatt_status_t esp_ble_gattc_unregister_for_notify (esp_gatt_if_t gatt_if,
|
||||
btc_msg_t msg;
|
||||
btc_ble_gattc_args_t arg;
|
||||
|
||||
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
msg.sig = BTC_SIG_API_CALL;
|
||||
msg.pid = BTC_PID_GATTC;
|
||||
msg.act = BTC_GATTC_ACT_UNREG_FOR_NOTIFY;
|
||||
arg.unreg_for_notify.gatt_if = gatt_if;
|
||||
arg.unreg_for_notify.gattc_if = gattc_if;
|
||||
memcpy(arg.unreg_for_notify.remote_bda, server_bda, sizeof(esp_bd_addr_t));
|
||||
memcpy(&arg.unreg_for_notify.service_id, srvc_id, sizeof(esp_gatt_srvc_id_t));
|
||||
memcpy(&arg.unreg_for_notify.char_id, char_id, sizeof(esp_gatt_id_t));
|
||||
|
@ -15,13 +15,19 @@
|
||||
#include "string.h"
|
||||
#include "esp_gatt_defs.h"
|
||||
#include "esp_gatts_api.h"
|
||||
#include "esp_bt_main.h"
|
||||
#include "btc_manage.h"
|
||||
#include "btc_gatts.h"
|
||||
#include "btc_gatt_util.h"
|
||||
|
||||
#define COPY_TO_GATTS_ARGS(_gatt_args, _arg, _arg_type) memcpy(_gatt_args, _arg, sizeof(_arg_type))
|
||||
|
||||
esp_err_t esp_ble_gatts_register_callback(esp_profile_cb_t callback)
|
||||
|
||||
esp_err_t esp_ble_gatts_register_callback(esp_gatts_cb_t callback)
|
||||
{
|
||||
if (esp_bluedroid_get_status() == ESP_BLUEDROID_STATUS_UNINITIALIZED) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
return (btc_profile_cb_set(BTC_PID_GATTS, callback) == 0 ? ESP_OK : ESP_FAIL);
|
||||
}
|
||||
|
||||
@ -30,6 +36,10 @@ esp_err_t esp_ble_gatts_app_register(uint16_t app_id)
|
||||
btc_msg_t msg;
|
||||
btc_ble_gatts_args_t arg;
|
||||
|
||||
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
//if (app_id < ESP_APP_ID_MIN || app_id > ESP_APP_ID_MAX) {
|
||||
if (app_id > ESP_APP_ID_MAX) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
@ -44,41 +54,73 @@ esp_err_t esp_ble_gatts_app_register(uint16_t app_id)
|
||||
}
|
||||
|
||||
|
||||
esp_err_t esp_ble_gatts_app_unregister(esp_gatt_if_t gatt_if)
|
||||
esp_err_t esp_ble_gatts_app_unregister(esp_gatt_if_t gatts_if)
|
||||
{
|
||||
btc_msg_t msg;
|
||||
btc_ble_gatts_args_t arg;
|
||||
|
||||
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
msg.sig = BTC_SIG_API_CALL;
|
||||
msg.pid = BTC_PID_GATTS;
|
||||
msg.act = BTC_GATTS_ACT_APP_UNREGISTER;
|
||||
arg.app_unreg.gatt_if = gatt_if;
|
||||
arg.app_unreg.gatts_if = gatts_if;
|
||||
|
||||
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gatts_args_t), NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_gatts_create_service(esp_gatt_if_t gatt_if,
|
||||
esp_err_t esp_ble_gatts_create_service(esp_gatt_if_t gatts_if,
|
||||
esp_gatt_srvc_id_t *service_id, uint16_t num_handle)
|
||||
{
|
||||
btc_msg_t msg;
|
||||
btc_ble_gatts_args_t arg;
|
||||
|
||||
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
msg.sig = BTC_SIG_API_CALL;
|
||||
msg.pid = BTC_PID_GATTS;
|
||||
msg.act = BTC_GATTS_ACT_CREATE_SERVICE;
|
||||
arg.create_srvc.gatt_if = gatt_if;
|
||||
arg.create_srvc.gatts_if = gatts_if;
|
||||
arg.create_srvc.num_handle = num_handle;
|
||||
memcpy(&arg.create_srvc.service_id, service_id, sizeof(esp_gatt_srvc_id_t));
|
||||
|
||||
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gatts_args_t), NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_gatts_create_attr_tab(const esp_gatts_attr_db_t *gatts_attr_db,
|
||||
esp_gatt_if_t gatts_if,
|
||||
uint8_t max_nb_attr,
|
||||
uint8_t srvc_inst_id)
|
||||
{
|
||||
btc_msg_t msg;
|
||||
btc_ble_gatts_args_t arg;
|
||||
|
||||
msg.sig = BTC_SIG_API_CALL;
|
||||
msg.pid = BTC_PID_GATTS;
|
||||
msg.act = BTC_GATTS_ACT_CREATE_ATTR_TAB;
|
||||
arg.create_attr_tab.gatts_if = gatts_if;
|
||||
arg.create_attr_tab.max_nb_attr = max_nb_attr;
|
||||
arg.create_attr_tab.srvc_inst_id = srvc_inst_id;
|
||||
arg.create_attr_tab.gatts_attr_db = (esp_gatts_attr_db_t *)gatts_attr_db;
|
||||
|
||||
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gatts_args_t), btc_gatts_arg_deep_copy)
|
||||
== BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
|
||||
}
|
||||
|
||||
|
||||
esp_err_t esp_ble_gatts_add_included_service(uint16_t service_handle, uint16_t included_service_handle)
|
||||
{
|
||||
btc_msg_t msg;
|
||||
btc_ble_gatts_args_t arg;
|
||||
|
||||
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
msg.sig = BTC_SIG_API_CALL;
|
||||
msg.pid = BTC_PID_GATTS;
|
||||
msg.act = BTC_GATTS_ACT_ADD_INCLUDE_SERVICE;
|
||||
@ -90,38 +132,69 @@ esp_err_t esp_ble_gatts_add_included_service(uint16_t service_handle, uint16_t i
|
||||
|
||||
|
||||
esp_err_t esp_ble_gatts_add_char(uint16_t service_handle, esp_bt_uuid_t *char_uuid,
|
||||
esp_gatt_perm_t perm, esp_gatt_char_prop_t property)
|
||||
esp_gatt_perm_t perm, esp_gatt_char_prop_t property, esp_attr_value_t *char_val,
|
||||
esp_attr_control_t *control)
|
||||
{
|
||||
btc_msg_t msg;
|
||||
btc_ble_gatts_args_t arg;
|
||||
|
||||
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
memset(&arg, 0, sizeof(btc_ble_gatts_args_t));
|
||||
msg.sig = BTC_SIG_API_CALL;
|
||||
msg.pid = BTC_PID_GATTS;
|
||||
msg.act = BTC_GATTS_ACT_ADD_CHAR;
|
||||
arg.add_char.service_handle = service_handle;
|
||||
arg.add_char.perm = perm;
|
||||
arg.add_char.property = property;
|
||||
if (char_val != NULL) {
|
||||
arg.add_char.char_val.attr_max_len = char_val->attr_max_len;
|
||||
arg.add_char.char_val.attr_len = char_val->attr_len;
|
||||
arg.add_char.char_val.attr_value = char_val->attr_value;
|
||||
}
|
||||
|
||||
if (control != NULL) {
|
||||
arg.add_char.attr_control.auto_rsp = control->auto_rsp;
|
||||
}
|
||||
memcpy(&arg.add_char.char_uuid, char_uuid, sizeof(esp_bt_uuid_t));
|
||||
|
||||
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gatts_args_t), NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
|
||||
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gatts_args_t), btc_gatts_arg_deep_copy) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
|
||||
}
|
||||
|
||||
|
||||
esp_err_t esp_ble_gatts_add_char_descr (uint16_t service_handle,
|
||||
esp_bt_uuid_t *descr_uuid,
|
||||
esp_gatt_perm_t perm)
|
||||
esp_gatt_perm_t perm, esp_attr_value_t *char_descr_val,
|
||||
esp_attr_control_t *control)
|
||||
{
|
||||
btc_msg_t msg;
|
||||
btc_ble_gatts_args_t arg;
|
||||
|
||||
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
memset(&arg, 0, sizeof(btc_ble_gatts_args_t));
|
||||
msg.sig = BTC_SIG_API_CALL;
|
||||
msg.pid = BTC_PID_GATTS;
|
||||
msg.act = BTC_GATTS_ACT_ADD_CHAR_DESCR;
|
||||
arg.add_descr.service_handle = service_handle;
|
||||
arg.add_descr.perm = perm;
|
||||
|
||||
if (char_descr_val != NULL) {
|
||||
arg.add_descr.descr_val.attr_max_len = char_descr_val->attr_max_len;
|
||||
arg.add_descr.descr_val.attr_len = char_descr_val->attr_len;
|
||||
arg.add_descr.descr_val.attr_value = char_descr_val->attr_value;
|
||||
}
|
||||
|
||||
if (control != NULL) {
|
||||
arg.add_descr.attr_control.auto_rsp = control->auto_rsp;
|
||||
}
|
||||
memcpy(&arg.add_descr.descr_uuid, descr_uuid, sizeof(esp_bt_uuid_t));
|
||||
|
||||
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gatts_args_t), NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
|
||||
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gatts_args_t), btc_gatts_arg_deep_copy) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_gatts_delete_service(uint16_t service_handle)
|
||||
@ -129,6 +202,10 @@ esp_err_t esp_ble_gatts_delete_service(uint16_t service_handle)
|
||||
btc_msg_t msg;
|
||||
btc_ble_gatts_args_t arg;
|
||||
|
||||
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
msg.sig = BTC_SIG_API_CALL;
|
||||
msg.pid = BTC_PID_GATTS;
|
||||
msg.act = BTC_GATTS_ACT_DELETE_SERVICE;
|
||||
@ -142,6 +219,10 @@ esp_err_t esp_ble_gatts_start_service(uint16_t service_handle)
|
||||
btc_msg_t msg;
|
||||
btc_ble_gatts_args_t arg;
|
||||
|
||||
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
msg.sig = BTC_SIG_API_CALL;
|
||||
msg.pid = BTC_PID_GATTS;
|
||||
msg.act = BTC_GATTS_ACT_START_SERVICE;
|
||||
@ -155,6 +236,10 @@ esp_err_t esp_ble_gatts_stop_service(uint16_t service_handle)
|
||||
btc_msg_t msg;
|
||||
btc_ble_gatts_args_t arg;
|
||||
|
||||
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
msg.sig = BTC_SIG_API_CALL;
|
||||
msg.pid = BTC_PID_GATTS;
|
||||
msg.act = BTC_GATTS_ACT_STOP_SERVICE;
|
||||
@ -164,65 +249,109 @@ esp_err_t esp_ble_gatts_stop_service(uint16_t service_handle)
|
||||
}
|
||||
|
||||
|
||||
esp_err_t esp_ble_gatts_send_indicate(uint16_t conn_id, uint16_t attr_handle,
|
||||
esp_err_t esp_ble_gatts_send_indicate(esp_gatt_if_t gatts_if, uint16_t conn_id, uint16_t attr_handle,
|
||||
uint16_t value_len, uint8_t *value, bool need_confirm)
|
||||
{
|
||||
btc_msg_t msg;
|
||||
btc_ble_gatts_args_t arg;
|
||||
|
||||
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
msg.sig = BTC_SIG_API_CALL;
|
||||
msg.pid = BTC_PID_GATTS;
|
||||
msg.act = BTC_GATTS_ACT_SEND_INDICATE;
|
||||
arg.send_ind.conn_id = conn_id;
|
||||
arg.send_ind.conn_id = BTC_GATT_CREATE_CONN_ID(gatts_if, conn_id);
|
||||
arg.send_ind.attr_handle = attr_handle;
|
||||
arg.send_ind.need_confirm = need_confirm;
|
||||
arg.send_ind.value_len = value_len;
|
||||
arg.send_ind.value = value;
|
||||
|
||||
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gatts_args_t), btc_gatts_arg_deep_copy) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
|
||||
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gatts_args_t),
|
||||
btc_gatts_arg_deep_copy) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_gatts_send_response(uint16_t conn_id, uint32_t trans_id,
|
||||
esp_err_t esp_ble_gatts_send_response(esp_gatt_if_t gatts_if, uint16_t conn_id, uint32_t trans_id,
|
||||
esp_gatt_status_t status, esp_gatt_rsp_t *rsp)
|
||||
{
|
||||
btc_msg_t msg;
|
||||
btc_ble_gatts_args_t arg;
|
||||
|
||||
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
msg.sig = BTC_SIG_API_CALL;
|
||||
msg.pid = BTC_PID_GATTS;
|
||||
msg.act = BTC_GATTS_ACT_SEND_RESPONSE;
|
||||
arg.send_rsp.conn_id = conn_id;
|
||||
arg.send_rsp.conn_id = BTC_GATT_CREATE_CONN_ID(gatts_if, conn_id);
|
||||
arg.send_rsp.trans_id = trans_id;
|
||||
arg.send_rsp.status = status;
|
||||
arg.send_rsp.rsp = rsp;
|
||||
|
||||
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gatts_args_t), btc_gatts_arg_deep_copy) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
|
||||
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gatts_args_t),
|
||||
btc_gatts_arg_deep_copy) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_gatts_open(esp_gatt_if_t gatt_if, esp_bd_addr_t remote_bda, bool is_direct)
|
||||
esp_err_t esp_ble_gatts_set_attr_value(uint16_t attr_handle, uint16_t length, const uint8_t *value)
|
||||
{
|
||||
btc_msg_t msg;
|
||||
btc_ble_gatts_args_t arg;
|
||||
|
||||
msg.sig = BTC_SIG_API_CALL;
|
||||
msg.pid = BTC_PID_GATTS;
|
||||
msg.act = BTC_GATTS_ACT_SET_ATTR_VALUE;
|
||||
arg.set_attr_val.length = length;
|
||||
arg.set_attr_val.value = (uint8_t *)value;
|
||||
|
||||
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gatts_args_t),
|
||||
btc_gatts_arg_deep_copy) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_gatts_get_attr_value(uint16_t attr_handle, uint16_t *length, const uint8_t **value)
|
||||
{
|
||||
if (attr_handle == ESP_GATT_ILLEGAL_HANDLE) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
btc_gatts_get_attr_value(attr_handle, length, (uint8_t **)value);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_gatts_open(esp_gatt_if_t gatts_if, esp_bd_addr_t remote_bda, bool is_direct)
|
||||
{
|
||||
btc_msg_t msg;
|
||||
btc_ble_gatts_args_t arg;
|
||||
|
||||
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
msg.sig = BTC_SIG_API_CALL;
|
||||
msg.pid = BTC_PID_GATTS;
|
||||
msg.act = BTC_GATTS_ACT_OPEN;
|
||||
arg.open.gatt_if = gatt_if;
|
||||
arg.open.gatts_if = gatts_if;
|
||||
arg.open.is_direct = is_direct;
|
||||
memcpy(&arg.open.remote_bda, remote_bda, sizeof(esp_bd_addr_t));
|
||||
|
||||
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gatts_args_t), NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
|
||||
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gatts_args_t), NULL)
|
||||
== BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_gatts_close(uint16_t conn_id)
|
||||
esp_err_t esp_ble_gatts_close(esp_gatt_if_t gatts_if, uint16_t conn_id)
|
||||
{
|
||||
btc_msg_t msg;
|
||||
btc_ble_gatts_args_t arg;
|
||||
|
||||
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
msg.sig = BTC_SIG_API_CALL;
|
||||
msg.pid = BTC_PID_GATTS;
|
||||
msg.act = BTC_GATTS_ACT_CLOSE;
|
||||
arg.close.conn_id = conn_id;
|
||||
arg.close.conn_id = BTC_GATT_CREATE_CONN_ID(gatts_if, conn_id);
|
||||
|
||||
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gatts_args_t), NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
|
||||
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gatts_args_t), NULL)
|
||||
== BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
|
||||
}
|
||||
|
@ -118,6 +118,13 @@ typedef union {
|
||||
} audio_cfg;
|
||||
} esp_a2d_cb_param_t;
|
||||
|
||||
/**
|
||||
* @brief A2DP profile callback function, data is ou
|
||||
* @param event : Event type
|
||||
* @param param : Point to callback parameter
|
||||
*/
|
||||
typedef void (* esp_a2d_cb_t)(esp_a2d_cb_event_t event, esp_a2d_cb_param_t *param);
|
||||
|
||||
/**
|
||||
* @brief A2DP profile data callback function, data is ou
|
||||
*
|
||||
@ -140,7 +147,7 @@ typedef void (* esp_a2d_data_cb_t)(const uint8_t *buf, uint32_t len);
|
||||
* - ESP_OK: success
|
||||
*
|
||||
*/
|
||||
esp_err_t esp_a2d_register_callback(esp_profile_cb_t callback);
|
||||
esp_err_t esp_a2d_register_callback(esp_a2d_cb_t callback);
|
||||
|
||||
|
||||
/**
|
||||
|
@ -18,22 +18,44 @@
|
||||
#include "esp_bt_defs.h"
|
||||
#include "esp_gatt_defs.h"
|
||||
#include "esp_err.h"
|
||||
#include "esp_wifi_types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define ESP_BLUFI_RECV_DATA_LEN_MAX (64+1)
|
||||
|
||||
#define ESP_BLUFI_EVENT_INIT_FINISH 0
|
||||
#define ESP_BLUFI_EVENT_DEINIT_FINISH 1
|
||||
#define ESP_BLUFI_EVENT_RECV_DATA 2
|
||||
typedef enum {
|
||||
ESP_BLUFI_EVENT_INIT_FINISH = 0, /*<! When BLUFI init complete, this event happen */
|
||||
ESP_BLUFI_EVENT_DEINIT_FINISH, /*<! When BLUFI deinit complete, this event happen */
|
||||
ESP_BLUFI_EVENT_SET_WIFI_OPMODE, /*<! When Phone set ESP32 wifi operation mode(AP/STA/AP_STA), this event happen */
|
||||
ESP_BLUFI_EVENT_BLE_CONNECT, /*<! When Phone connect to ESP32 with BLE, this event happen */
|
||||
ESP_BLUFI_EVENT_BLE_DISCONNECT, /*<! When Phone disconnect with BLE, this event happen */
|
||||
ESP_BLUFI_EVENT_REQ_CONNECT_TO_AP, /*<! When Phone request ESP32's STA connect to AP, this event happen */
|
||||
ESP_BLUFI_EVENT_REQ_DISCONNECT_FROM_AP, /*<! When Phone request ESP32's STA disconnect from AP, this event happen */
|
||||
ESP_BLUFI_EVENT_GET_WIFI_STATUS, /*<! When Phone get ESP32 wifi status, this event happen */
|
||||
ESP_BLUFI_EVENT_DEAUTHENTICATE_STA, /*<! When Phone deauthenticate sta from SOFTAP, this event happen */
|
||||
/* recv data */
|
||||
ESP_BLUFI_EVENT_RECV_STA_BSSID, /*<! When Phone send STA BSSID to ESP32 to connect, this event happen */
|
||||
ESP_BLUFI_EVENT_RECV_STA_SSID, /*<! When Phone send STA SSID to ESP32 to connect, this event happen */
|
||||
ESP_BLUFI_EVENT_RECV_STA_PASSWD, /*<! When Phone send STA PASSWORD to ESP32 to connect, this event happen */
|
||||
ESP_BLUFI_EVENT_RECV_SOFTAP_SSID, /*<! When Phone send SOFTAP SSID to ESP32 to start SOFTAP, this event happen */
|
||||
ESP_BLUFI_EVENT_RECV_SOFTAP_PASSWD, /*<! When Phone send SOFTAP PASSWORD to ESP32 to start SOFTAP, this event happen */
|
||||
ESP_BLUFI_EVENT_RECV_SOFTAP_MAX_CONN_NUM, /*<! When Phone send SOFTAP max connection number to ESP32 to start SOFTAP, this event happen */
|
||||
ESP_BLUFI_EVENT_RECV_SOFTAP_AUTH_MODE, /*<! When Phone send SOFTAP authentication mode to ESP32 to start SOFTAP, this event happen */
|
||||
ESP_BLUFI_EVENT_RECV_SOFTAP_CHANNEL, /*<! When Phone send SOFTAP channel to ESP32 to start SOFTAP, this event happen */
|
||||
ESP_BLUFI_EVENT_RECV_USERNAME, /*<! When Phone send username to ESP32, this event happen */
|
||||
ESP_BLUFI_EVENT_RECV_CA_CERT, /*<! When Phone send CA certificate to ESP32, this event happen */
|
||||
ESP_BLUFI_EVENT_RECV_CLIENT_CERT, /*<! When Phone send Client certificate to ESP32, this event happen */
|
||||
ESP_BLUFI_EVENT_RECV_SERVER_CERT, /*<! When Phone send Server certificate to ESP32, this event happen */
|
||||
ESP_BLUFI_EVENT_RECV_CLIENT_PRIV_KEY, /*<! When Phone send Client Private key to ESP32, this event happen */
|
||||
ESP_BLUFI_EVENT_RECV_SERVER_PRIV_KEY, /*<! When Phone send Server Private key to ESP32, this event happen */
|
||||
} esp_blufi_cb_event_t;
|
||||
|
||||
/// BLUFI config status
|
||||
typedef enum {
|
||||
ESP_BLUFI_CONFIG_OK = 0,
|
||||
ESP_BLUFI_CONFIG_FAILED,
|
||||
} esp_blufi_config_state_t;
|
||||
ESP_BLUFI_STA_CONN_SUCCESS = 0x00,
|
||||
ESP_BLUFI_STA_CONN_FAIL = 0x01,
|
||||
} esp_blufi_sta_conn_state_t;
|
||||
|
||||
/// BLUFI init status
|
||||
typedef enum {
|
||||
@ -47,6 +69,29 @@ typedef enum {
|
||||
ESP_BLUFI_DEINIT_FAILED = 0,
|
||||
} esp_blufi_deinit_state_t;
|
||||
|
||||
/**
|
||||
* @brief BLUFI extra information structure
|
||||
*/
|
||||
typedef struct {
|
||||
//station
|
||||
uint8_t sta_bssid[6]; /*!< BSSID of station interface */
|
||||
bool sta_bssid_set; /*!< is BSSID of station interface set */
|
||||
uint8_t *sta_ssid; /*!< SSID of station interface */
|
||||
int sta_ssid_len; /*!< length of SSID of station interface */
|
||||
uint8_t *sta_passwd; /*!< password of station interface */
|
||||
int sta_passwd_len; /*!< length of password of station interface */
|
||||
uint8_t *softap_ssid; /*!< SSID of softap interface */
|
||||
int softap_ssid_len; /*!< length of SSID of softap interface */
|
||||
uint8_t *softap_passwd; /*!< password of station interface */
|
||||
int softap_passwd_len; /*!< length of password of station interface */
|
||||
uint8_t softap_authmode; /*!< authentication mode of softap interface */
|
||||
bool softap_authmode_set; /*!< is authentication mode of softap interface set */
|
||||
uint8_t softap_max_conn_num; /*!< max connection number of softap interface */
|
||||
bool softap_max_conn_num_set; /*!< is max connection number of softap interface set */
|
||||
uint8_t softap_channel; /*!< channel of softap interface */
|
||||
bool softap_channel_set; /*!< is channel of softap interface set */
|
||||
} esp_blufi_extra_info_t;
|
||||
|
||||
/**
|
||||
* @brief BLUFI callback parameters union
|
||||
*/
|
||||
@ -66,35 +111,207 @@ typedef union {
|
||||
} deinit_finish; /*!< Blufi callback param of ESP_BLUFI_EVENT_DEINIT_FINISH */
|
||||
|
||||
/**
|
||||
* @brief ESP_BLUFI_EVENT_RECV_DATA
|
||||
* @brief ESP_BLUFI_EVENT_SET_WIFI_MODE
|
||||
*/
|
||||
struct blufi_recv_evt_param {
|
||||
uint8_t data[ESP_BLUFI_RECV_DATA_LEN_MAX]; /*!< Blufi receive data */
|
||||
uint8_t data_len; /*!< Blufi receive data length */
|
||||
} recv_data; /*!< Blufi callback param of ESP_BLUFI_EVENT_RECV_DATA */
|
||||
struct blufi_set_wifi_mode_evt_param {
|
||||
wifi_mode_t op_mode; /*!< Wifi operation mode */
|
||||
} wifi_mode; /*!< Blufi callback param of ESP_BLUFI_EVENT_INIT_FINISH */
|
||||
|
||||
/**
|
||||
* @brief ESP_BLUFI_EVENT_CONNECT
|
||||
*/
|
||||
struct blufi_connect_evt_param {
|
||||
esp_bd_addr_t remote_bda; /*!< Blufi Remote bluetooth device address */
|
||||
} connect; /*!< Blufi callback param of ESP_BLUFI_EVENT_CONNECT */
|
||||
|
||||
/**
|
||||
* @brief ESP_BLUFI_EVENT_DISCONNECT
|
||||
*/
|
||||
struct blufi_disconnect_evt_param {
|
||||
esp_bd_addr_t remote_bda; /*!< Blufi Remote bluetooth device address */
|
||||
} disconnect; /*!< Blufi callback param of ESP_BLUFI_EVENT_DISCONNECT */
|
||||
|
||||
/* ESP_BLUFI_EVENT_REQ_WIFI_CONNECT */ /* No callback param */
|
||||
/* ESP_BLUFI_EVENT_REQ_WIFI_DISCONNECT */ /* No callback param */
|
||||
|
||||
/**
|
||||
* @brief ESP_BLUFI_EVENT_RECV_STA_BSSID
|
||||
*/
|
||||
struct blufi_recv_sta_bssid_evt_param {
|
||||
uint8_t bssid[6]; /*!< BSSID */
|
||||
} sta_bssid; /*!< Blufi callback param of ESP_BLUFI_EVENT_RECV_STA_BSSID */
|
||||
|
||||
/**
|
||||
* @brief ESP_BLUFI_EVENT_RECV_STA_SSID
|
||||
*/
|
||||
struct blufi_recv_sta_ssid_evt_param {
|
||||
uint8_t *ssid; /*!< SSID */
|
||||
int ssid_len; /*!< SSID length */
|
||||
} sta_ssid; /*!< Blufi callback param of ESP_BLUFI_EVENT_RECV_STA_SSID */
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* ESP_BLUFI_EVENT_RECV_STA_PASSWD
|
||||
*/
|
||||
struct blufi_recv_sta_passwd_evt_param {
|
||||
uint8_t *passwd; /*!< Password */
|
||||
int passwd_len; /*!< Password Length */
|
||||
} sta_passwd; /*!< Blufi callback param of ESP_BLUFI_EVENT_RECV_STA_PASSWD */
|
||||
|
||||
/**
|
||||
* @brief ESP_BLUFI_EVENT_RECV_SOFTAP_SSID
|
||||
*/
|
||||
struct blufi_recv_softap_ssid_evt_param {
|
||||
uint8_t *ssid; /*!< SSID */
|
||||
int ssid_len; /*!< SSID length */
|
||||
} softap_ssid; /*!< Blufi callback param of ESP_BLUFI_EVENT_RECV_SOFTAP_SSID */
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* ESP_BLUFI_EVENT_RECV_SOFTAP_PASSWD
|
||||
*/
|
||||
struct blufi_recv_softap_passwd_evt_param {
|
||||
uint8_t *passwd; /*!< Password */
|
||||
int passwd_len; /*!< Password Length */
|
||||
} softap_passwd; /*!< Blufi callback param of ESP_BLUFI_EVENT_RECV_SOFTAP_PASSWD */
|
||||
|
||||
/**
|
||||
* @brief ESP_BLUFI_EVENT_RECV_SOFTAP_MAX_CONN_NUM
|
||||
*/
|
||||
struct blufi_recv_softap_max_conn_num_evt_param {
|
||||
int max_conn_num; /*!< SSID */
|
||||
} softap_max_conn_num; /*!< Blufi callback param of ESP_BLUFI_EVENT_RECV_SOFTAP_MAX_CONN_NUM */
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* ESP_BLUFI_EVENT_RECV_SOFTAP_AUTH_MODE
|
||||
*/
|
||||
struct blufi_recv_softap_auth_mode_evt_param {
|
||||
wifi_auth_mode_t auth_mode; /*!< Authentication mode */
|
||||
} softap_auth_mode; /*!< Blufi callback param of ESP_BLUFI_EVENT_RECV_SOFTAP_AUTH_MODE */
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* ESP_BLUFI_EVENT_RECV_SOFTAP_CHANNEL
|
||||
*/
|
||||
struct blufi_recv_softap_channel_evt_param {
|
||||
uint8_t channel; /*!< Authentication mode */
|
||||
} softap_channel; /*!< Blufi callback param of ESP_BLUFI_EVENT_RECV_SOFTAP_CHANNEL */
|
||||
|
||||
/**
|
||||
* @brief ESP_BLUFI_EVENT_RECV_USERNAME
|
||||
*/
|
||||
struct blufi_recv_username_evt_param {
|
||||
uint8_t *name; /*!< Username point */
|
||||
int name_len; /*!< Username length */
|
||||
} username; /*!< Blufi callback param of ESP_BLUFI_EVENT_RECV_USERNAME*/
|
||||
|
||||
/**
|
||||
* @brief ESP_BLUFI_EVENT_RECV_CA_CERT
|
||||
*/
|
||||
struct blufi_recv_ca_evt_param {
|
||||
uint8_t *cert; /*!< CA certificate point */
|
||||
int cert_len; /*!< CA certificate length */
|
||||
} ca; /*!< Blufi callback param of ESP_BLUFI_EVENT_RECV_CA_CERT */
|
||||
|
||||
/**
|
||||
* ESP_BLUFI_EVENT_RECV_CLIENT_CERT
|
||||
*/
|
||||
struct blufi_recv_client_cert_evt_param {
|
||||
uint8_t *cert; /*!< Client certificate point */
|
||||
int cert_len; /*!< Client certificate length */
|
||||
} client_cert; /*!< Blufi callback param of ESP_BLUFI_EVENT_RECV_CLIENT_CERT */
|
||||
|
||||
/**
|
||||
* ESP_BLUFI_EVENT_RECV_SERVER_CERT
|
||||
*/
|
||||
struct blufi_recv_server_cert_evt_param {
|
||||
uint8_t *cert; /*!< Client certificate point */
|
||||
int cert_len; /*!< Client certificate length */
|
||||
} server_cert; /*!< Blufi callback param of ESP_BLUFI_EVENT_RECV_SERVER_CERT */
|
||||
|
||||
/**
|
||||
* ESP_BLUFI_EVENT_RECV_CLIENT_PRIV_KEY
|
||||
*/
|
||||
struct blufi_recv_client_pkey_evt_param {
|
||||
uint8_t *pkey; /*!< Client Private Key point, if Client certificate not contain Key */
|
||||
int pkey_len; /*!< Client Private key length */
|
||||
} client_pkey; /*!< Blufi callback param of ESP_BLUFI_EVENT_RECV_CLIENT_PRIV_KEY */
|
||||
/**
|
||||
* ESP_BLUFI_EVENT_RECV_SERVER_PRIV_KEY
|
||||
*/
|
||||
struct blufi_recv_server_pkey_evt_param {
|
||||
uint8_t *pkey; /*!< Client Private Key point, if Client certificate not contain Key */
|
||||
int pkey_len; /*!< Client Private key length */
|
||||
} server_pkey; /*!< Blufi callback param of ESP_BLUFI_EVENT_RECV_SERVER_PRIV_KEY */
|
||||
|
||||
} esp_blufi_cb_param_t;
|
||||
|
||||
/**
|
||||
* @brief BLUFI event callback function type
|
||||
* @param event : Event type
|
||||
* @param param : Point to callback parameter, currently is union type
|
||||
*/
|
||||
typedef void (* esp_blufi_event_cb_t)(esp_blufi_cb_event_t event, esp_blufi_cb_param_t *param);
|
||||
|
||||
/* security function declare */
|
||||
|
||||
/**
|
||||
* @brief BLUFI negotiate data handler
|
||||
* @param data : data from phone
|
||||
* @param len : length of data from phone
|
||||
* @param output_data : data want to send to phone
|
||||
* @param output_len : length of data want to send to phone
|
||||
*/
|
||||
typedef void (*esp_blufi_negotiate_data_handler_t)(uint8_t *data, int len, uint8_t **output_data, int *output_len, bool *need_free);
|
||||
|
||||
/**
|
||||
* @brief BLUFI encrypt the data after negotiate a share key
|
||||
* @param iv8 : initial vector(8bit), normally, blufi core will input packet sequence number
|
||||
* @param crypt_data : plain text and encrypted data, the encrypt function must support autochthonous encrypt
|
||||
* @param crypt_len : length of plain text
|
||||
* @return Nonnegative number is encrypted length, if error, return negative number;
|
||||
*/
|
||||
typedef int (* esp_blufi_encrypt_func_t)(uint8_t iv8, uint8_t *crypt_data, int cyprt_len);
|
||||
|
||||
/**
|
||||
* @brief BLUFI decrypt the data after negotiate a share key
|
||||
* @param iv8 : initial vector(8bit), normally, blufi core will input packet sequence number
|
||||
* @param crypt_data : encrypted data and plain text, the encrypt function must support autochthonous decrypt
|
||||
* @param crypt_len : length of encrypted text
|
||||
* @return Nonnegative number is decrypted length, if error, return negative number;
|
||||
*/
|
||||
typedef int (* esp_blufi_decrypt_func_t)(uint8_t iv8, uint8_t *crypt_data, int crypt_len);
|
||||
|
||||
/**
|
||||
* @brief BLUFI checksum
|
||||
* @param iv8 : initial vector(8bit), normally, blufi core will input packet sequence number
|
||||
* @param data : data need to checksum
|
||||
* @param len : length of data
|
||||
*/
|
||||
typedef uint16_t (*esp_blufi_checksum_func_t)(uint8_t iv8, uint8_t *data, int len);
|
||||
|
||||
/**
|
||||
* @brief BLUFI callback functions type
|
||||
*/
|
||||
typedef struct {
|
||||
esp_blufi_event_cb_t event_cb; /*!< BLUFI event callback */
|
||||
esp_blufi_negotiate_data_handler_t negotiate_data_handler; /*!< BLUFI negotiate data function for negotiate share key */
|
||||
esp_blufi_encrypt_func_t encrypt_func; /*!< BLUFI encrypt data function with share key generated by negotiate_data_handler */
|
||||
esp_blufi_decrypt_func_t decrypt_func; /*!< BLUFI decrypt data function with share key generated by negotiate_data_handler */
|
||||
esp_blufi_checksum_func_t checksum_func; /*!< BLUFI check sum function (FCS) */
|
||||
} esp_blufi_callbacks_t;
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief This function is called to receive blufi callback event
|
||||
*
|
||||
* @param[in] callback: callback function
|
||||
* @param[in] callbacks: callback functions
|
||||
*
|
||||
* @return ESP_OK - success, other - failed
|
||||
*
|
||||
*/
|
||||
esp_err_t esp_blufi_register_callback(esp_profile_cb_t callback);
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief This function is called to send config state to phone
|
||||
*
|
||||
* @param[in] state: blufi config OK or not
|
||||
*
|
||||
* @return ESP_OK - success, other - failed
|
||||
*
|
||||
*/
|
||||
esp_err_t esp_blufi_send_config_state(esp_blufi_config_state_t state);
|
||||
esp_err_t esp_blufi_register_callbacks(esp_blufi_callbacks_t *callbacks);
|
||||
|
||||
/**
|
||||
*
|
||||
@ -114,6 +331,28 @@ esp_err_t esp_blufi_profile_init(void);
|
||||
*/
|
||||
esp_err_t esp_blufi_profile_deinit(void);
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief This function is called to send wifi connection report
|
||||
* @param opmode : wifi opmode
|
||||
* @param sta_conn_state : station is already in connection or not
|
||||
* @param softap_conn_num : softap connection number
|
||||
* @param extra_info : extra information, such as sta_ssid, softap_ssid and etc.
|
||||
*
|
||||
* @return ESP_OK - success, other - failed
|
||||
*
|
||||
*/
|
||||
esp_err_t esp_blufi_send_wifi_conn_report(wifi_mode_t opmode, esp_blufi_sta_conn_state_t sta_conn_state, uint8_t softap_conn_num, esp_blufi_extra_info_t *extra_info);
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Get BLUFI profile version
|
||||
*
|
||||
* @return Most 8bit significant is Great version, Least 8bit is Sub version
|
||||
*
|
||||
*/
|
||||
uint16_t esp_blufi_get_version(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -96,12 +96,8 @@ typedef enum {
|
||||
/// Maximum of the application id
|
||||
#define ESP_APP_ID_MAX 0x7fff
|
||||
|
||||
/**
|
||||
* @brief Each profile callback function type
|
||||
* @param event : Event type
|
||||
* @param param : Point to callback parameter, currently is union type
|
||||
*/
|
||||
typedef void (* esp_profile_cb_t)(uint32_t event, void *param);
|
||||
#define ESP_BD_ADDR_STR "%02x:%02x:%02x:%02x:%02x:%02x"
|
||||
#define ESP_BD_ADDR_HEX(addr) addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -12,28 +12,27 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef __BT_APP_COMMON_H__
|
||||
#define __BT_APP_COMMON_H__
|
||||
#ifndef __ESP_BT_DEVICE_H__
|
||||
#define __ESP_BT_DEVICE_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include "osi.h"
|
||||
#include "bt_common_types.h"
|
||||
#include "esp_err.h"
|
||||
#include <stdbool.h>
|
||||
|
||||
enum BLUFI_SIG {
|
||||
BLUFI_SIG_SWITCH_CONTEXT = 0,
|
||||
BLUFI_SIG_ENABLE,
|
||||
BLUFI_SIG_DISABLE,
|
||||
};
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef esp_err_t (*blufi_task_cb_t)(void *arg);
|
||||
/**
|
||||
*
|
||||
* @brief Get bluetooth device address. Must use after "esp_bluedroid_enable".
|
||||
*
|
||||
* @return bluetooth device address (six bytes), or NULL if bluetooth stack is not enabled
|
||||
*/
|
||||
const uint8_t *esp_bt_dev_get_address(void);
|
||||
|
||||
void blufi_init(void);
|
||||
void blufi_deinit(void);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
esp_err_t blufi_enable(void *arg);
|
||||
esp_err_t blufi_disable(void *arg);
|
||||
|
||||
esp_err_t blufi_transfer_context(blufi_task_cb_t cb, void *arg);
|
||||
|
||||
#endif /* __BT_APP_COMMON_H__ */
|
||||
#endif /* __ESP_BT_DEVICE_H__ */
|
@ -22,22 +22,39 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Enable bluetooth, must after esp_init_bluetooth()
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK : Succeed
|
||||
* - Other : Failed
|
||||
* @brief Bluetooth stack status type, to indicate whether the bluetooth stack is ready
|
||||
*/
|
||||
esp_err_t esp_enable_bluetooth(void);
|
||||
typedef enum {
|
||||
ESP_BLUEDROID_STATUS_UNINITIALIZED = 0, /*!< Bluetooth not initialized */
|
||||
ESP_BLUEDROID_STATUS_INITIALIZED, /*!< Bluetooth initialized but not enabled */
|
||||
ESP_BLUEDROID_STATUS_ENABLED /*!< Bluetooth initialized and enabled */
|
||||
} esp_bluedroid_status_t;
|
||||
|
||||
/**
|
||||
* @brief Disable bluetooth, must prior to esp_deinit_bluetooth()
|
||||
* @brief Get bluetooth stack status
|
||||
*
|
||||
* @return Bluetooth stack status
|
||||
*
|
||||
*/
|
||||
esp_bluedroid_status_t esp_bluedroid_get_status(void);
|
||||
|
||||
/**
|
||||
* @brief Enable bluetooth, must after esp_bluedroid_init()
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK : Succeed
|
||||
* - Other : Failed
|
||||
*/
|
||||
esp_err_t esp_disable_bluetooth(void);
|
||||
esp_err_t esp_bluedroid_enable(void);
|
||||
|
||||
/**
|
||||
* @brief Disable bluetooth, must prior to esp_bluedroid_deinit()
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK : Succeed
|
||||
* - Other : Failed
|
||||
*/
|
||||
esp_err_t esp_bluedroid_disable(void);
|
||||
|
||||
/**
|
||||
* @brief Init and alloc the resource for bluetooth, must be prior to every bluetooth stuff
|
||||
@ -46,7 +63,7 @@ esp_err_t esp_disable_bluetooth(void);
|
||||
* - ESP_OK : Succeed
|
||||
* - Other : Failed
|
||||
*/
|
||||
esp_err_t esp_init_bluetooth(void);
|
||||
esp_err_t esp_bluedroid_init(void);
|
||||
|
||||
/**
|
||||
* @brief Deinit and free the resource for bluetooth, must be after every bluetooth stuff
|
||||
@ -55,7 +72,7 @@ esp_err_t esp_init_bluetooth(void);
|
||||
* - ESP_OK : Succeed
|
||||
* - Other : Failed
|
||||
*/
|
||||
esp_err_t esp_deinit_bluetooth(void);
|
||||
esp_err_t esp_bluedroid_deinit(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -25,16 +25,31 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**@{
|
||||
* BLE_ADV_DATA_FLAG data flag bit definition used for advertising data flag
|
||||
*/
|
||||
#define ESP_BLE_ADV_FLAG_LIMIT_DISC (0x01 << 0)
|
||||
#define ESP_BLE_ADV_FLAG_GEN_DISC (0x01 << 1)
|
||||
#define ESP_BLE_ADV_FLAG_BREDR_NOT_SPT (0x01 << 2)
|
||||
#define ESP_BLE_ADV_FLAG_DMT_CONTROLLER_SPT (0x01 << 3)
|
||||
#define ESP_BLE_ADV_FLAG_DMT_HOST_SPT (0x01 << 4)
|
||||
#define ESP_BLE_ADV_FLAG_NON_LIMIT_DISC (0x00 )
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/// GAP BLE callback event type
|
||||
typedef enum {
|
||||
ESP_GAP_BLE_ADV_DATA_SET_COMPLETE_EVT = 0, /*!< When advertising data set complete, the event comes */
|
||||
ESP_GAP_BLE_SCAN_RSP_DATA_SET_COMPLETE_EVT , /*!< When scan response data set complete, the event comes */
|
||||
ESP_GAP_BLE_SCAN_RSP_DATA_SET_COMPLETE_EVT, /*!< When scan response data set complete, the event comes */
|
||||
ESP_GAP_BLE_SCAN_PARAM_SET_COMPLETE_EVT, /*!< When scan parameters set complete, the event comes */
|
||||
ESP_GAP_BLE_SCAN_RESULT_EVT, /*!< When one scan result ready, the event comes each time */
|
||||
}esp_gap_ble_cb_event_t;
|
||||
} esp_gap_ble_cb_event_t;
|
||||
|
||||
/// Advertising data maximum length
|
||||
#define ESP_BLE_ADV_DATA_LEN_MAX 31
|
||||
/// Scan response data maximum length
|
||||
#define ESP_BLE_SCAN_RSP_DATA_LEN_MAX 31
|
||||
|
||||
/// The type of advertising data(not adv_type)
|
||||
typedef enum {
|
||||
@ -126,7 +141,7 @@ typedef struct {
|
||||
uint8_t *p_service_data; /*!< Service data point */
|
||||
uint16_t service_uuid_len; /*!< Service uuid length */
|
||||
uint8_t *p_service_uuid; /*!< Service uuid array point */
|
||||
uint8_t flag; /*!< Advertising flag of discovery mode */
|
||||
uint8_t flag; /*!< Advertising flag of discovery mode, see BLE_ADV_DATA_FLAG detail */
|
||||
} esp_ble_adv_data_t;
|
||||
|
||||
/// Own BD address source of the device
|
||||
@ -251,12 +266,19 @@ typedef union {
|
||||
esp_ble_addr_type_t ble_addr_type; /*!< Ble device address type */
|
||||
esp_ble_evt_type_t ble_evt_type; /*!< Ble scan result event type */
|
||||
int rssi; /*!< Searched device's RSSI */
|
||||
uint8_t ble_adv[ESP_BLE_ADV_DATA_LEN_MAX]; /*!< Received EIR */
|
||||
uint8_t ble_adv[ESP_BLE_ADV_DATA_LEN_MAX + ESP_BLE_SCAN_RSP_DATA_LEN_MAX]; /*!< Received EIR */
|
||||
int flag; /*!< Advertising data flag bit */
|
||||
int num_resps; /*!< Scan result number */
|
||||
} scan_rst; /*!< Event parameter of ESP_GAP_BLE_SCAN_RESULT_EVT */
|
||||
} esp_ble_gap_cb_param_t;
|
||||
|
||||
/**
|
||||
* @brief GAP callback function type
|
||||
* @param event : Event type
|
||||
* @param param : Point to callback parameter, currently is union type
|
||||
*/
|
||||
typedef void (* esp_gap_ble_cb_t)(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param);
|
||||
|
||||
/**
|
||||
* @brief This function is called to occur gap event, such as scan result
|
||||
*
|
||||
@ -267,7 +289,7 @@ typedef union {
|
||||
* - other : failed
|
||||
*
|
||||
*/
|
||||
esp_err_t esp_ble_gap_register_callback(esp_profile_cb_t callback);
|
||||
esp_err_t esp_ble_gap_register_callback(esp_gap_ble_cb_t callback);
|
||||
|
||||
|
||||
/**
|
||||
@ -420,7 +442,8 @@ esp_err_t esp_ble_gap_set_device_name(const char *name);
|
||||
* @param[in] type - finding ADV data type
|
||||
* @param[out] length - return the length of ADV data not including type
|
||||
*
|
||||
* @return pointer of ADV data
|
||||
* @return - ESP_OK : success
|
||||
* - other : failed
|
||||
*
|
||||
*/
|
||||
uint8_t *esp_ble_resolve_adv_data(uint8_t *adv_data, uint8_t type, uint8_t *length);
|
||||
|
@ -23,10 +23,38 @@ extern "C" {
|
||||
|
||||
/// GATT INVALID UUID
|
||||
#define ESP_GATT_ILLEGAL_UUID 0
|
||||
/// GATT INVALID HANDLE
|
||||
#define ESP_GATT_ILLEGAL_HANDLE 0
|
||||
/// GATT attribute max handle
|
||||
#define ESP_GATT_ATTR_HANDLE_MAX 100
|
||||
|
||||
|
||||
/**@{
|
||||
* All "ESP_GATT_UUID_xxx" is attribute types
|
||||
*/
|
||||
#define ESP_GATT_UUID_IMMEDIATE_ALERT_SVC 0x1802 /* Immediate alert Service*/
|
||||
#define ESP_GATT_UUID_LINK_LOSS_SVC 0x1803 /* Link Loss Service*/
|
||||
#define ESP_GATT_UUID_TX_POWER_SVC 0x1804 /* TX Power Service*/
|
||||
#define ESP_GATT_UUID_CURRENT_TIME_SVC 0x1805 /* Current Time Service Service*/
|
||||
#define ESP_GATT_UUID_REF_TIME_UPDATE_SVC 0x1806 /* Reference Time Update Service*/
|
||||
#define ESP_GATT_UUID_NEXT_DST_CHANGE_SVC 0x1807 /* Next DST Change Service*/
|
||||
#define ESP_GATT_UUID_GLUCOSE_SVC 0x1808 /* Glucose Service*/
|
||||
#define ESP_GATT_UUID_HEALTH_THERMOM_SVC 0x1809 /* Health Thermometer Service*/
|
||||
#define ESP_GATT_UUID_DEVICE_INFO_SVC 0x180A /* Device Information Service*/
|
||||
#define ESP_GATT_UUID_HEART_RATE_SVC 0x180D /* Heart Rate Service*/
|
||||
#define ESP_GATT_UUID_PHONE_ALERT_STATUS_SVC 0x180E /* Phone Alert Status Service*/
|
||||
#define ESP_GATT_UUID_BATTERY_SERVICE_SVC 0x180F /* Battery Service*/
|
||||
#define ESP_GATT_UUID_BLOOD_PRESSURE_SVC 0x1810 /* Blood Pressure Service*/
|
||||
#define ESP_GATT_UUID_ALERT_NTF_SVC 0x1811 /* Alert Notification Service*/
|
||||
#define ESP_GATT_UUID_HID_SVC 0x1812 /* HID Service*/
|
||||
#define ESP_GATT_UUID_SCAN_PARAMETERS_SVC 0x1813 /* Scan Parameters Service*/
|
||||
#define ESP_GATT_UUID_RUNNING_SPEED_CADENCE_SVC 0x1814 /* Running Speed and Cadence Service*/
|
||||
#define ESP_GATT_UUID_CYCLING_SPEED_CADENCE_SVC 0x1816 /* Cycling Speed and Cadence Service*/
|
||||
#define ESP_GATT_UUID_CYCLING_POWER_SVC 0x1818 /* Cycling Power Service*/
|
||||
#define ESP_GATT_UUID_LOCATION_AND_NAVIGATION_SVC 0x1819 /* Location and Navigation Service*/
|
||||
#define ESP_GATT_UUID_USER_DATA_SVC 0x181C /* User Data Service*/
|
||||
#define ESP_GATT_UUID_WEIGHT_SCALE_SVC 0x181D /* Weight Scale Service*/
|
||||
|
||||
#define ESP_GATT_UUID_PRI_SERVICE 0x2800
|
||||
#define ESP_GATT_UUID_SEC_SERVICE 0x2801
|
||||
#define ESP_GATT_UUID_INCLUDE_SERVICE 0x2802
|
||||
@ -96,6 +124,13 @@ extern "C" {
|
||||
#define ESP_GATT_UUID_HID_BT_KB_OUTPUT 0x2A32
|
||||
#define ESP_GATT_UUID_HID_BT_MOUSE_INPUT 0x2A33
|
||||
|
||||
/// Heart Rate Measurement
|
||||
#define ESP_GATT_HEART_RATE_MEAS 0x2A37
|
||||
/// Body Sensor Location
|
||||
#define ESP_GATT_BODY_SENSOR_LOCATION 0x2A38
|
||||
/// Heart Rate Control Point
|
||||
#define ESP_GATT_HEART_RATE_CNTL_POINT 0x2A39
|
||||
|
||||
/* Battery Service characteristics */
|
||||
#define ESP_GATT_UUID_BATTERY_LEVEL 0x2A19
|
||||
|
||||
@ -246,6 +281,75 @@ typedef enum {
|
||||
/// GATT maximum attribute length
|
||||
#define ESP_GATT_MAX_ATTR_LEN 600 //as same as GATT_MAX_ATTR_LEN
|
||||
|
||||
|
||||
/**
|
||||
* @brief Attribute description (used to create database)
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint16_t uuid_length; /*!< UUID length */
|
||||
uint8_t *uuid_p; /*!< UUID value */
|
||||
uint16_t perm; /*!< Attribute permission */
|
||||
uint16_t max_length; /*!< Maximum length of the element*/
|
||||
uint16_t length; /*!< Current length of the element*/
|
||||
uint8_t *value; /*!< Element value array*/
|
||||
} esp_attr_desc_t;
|
||||
|
||||
|
||||
/**
|
||||
* @brief attribute auto respose flag
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
#define ESP_GATT_RSP_BY_APP 0
|
||||
#define ESP_GATT_AUTO_RSP 1
|
||||
uint8_t auto_rsp; /*!< need the app response to the client if need_rsp set to 1*/
|
||||
} esp_attr_control_t;
|
||||
|
||||
|
||||
/**
|
||||
* @brief attribute type added to the gatt server database
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
esp_attr_control_t attr_control; /*!< The attribue control type*/
|
||||
esp_attr_desc_t att_desc; /*!< The attribue type*/
|
||||
} esp_gatts_attr_db_t;
|
||||
|
||||
|
||||
/**
|
||||
* @brief set the attribute value type
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint16_t attr_max_len; /*!< attribute max value length */
|
||||
uint16_t attr_len; /*!< attribute current value length */
|
||||
uint8_t *attr_value; /*!< the pointer to attribute value */
|
||||
} esp_attr_value_t;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Gatt include service entry element
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint16_t start_hdl; /*!< Gatt start handle value of included service */
|
||||
uint16_t end_hdl; /*!< Gatt end handle value of included service */
|
||||
uint16_t uuid; /*!< Gatt attribute value UUID of included service */
|
||||
} esp_gatts_incl_svc_desc_t; /*!< Gatt include service entry element */
|
||||
|
||||
/**
|
||||
* @brief Gatt include 128 bit service entry element
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint16_t start_hdl; /*!< Gatt start handle value of included 128 bit service */
|
||||
uint16_t end_hdl; /*!< Gatt end handle value of included 128 bit service */
|
||||
} esp_gatts_incl128_svc_desc_t; /*!< Gatt include 128 bit service entry element */
|
||||
|
||||
|
||||
|
||||
|
||||
/// Gatt attribute value
|
||||
typedef struct {
|
||||
uint8_t value[ESP_GATT_MAX_ATTR_LEN]; /*!< Gatt attribute value */
|
||||
@ -269,7 +373,9 @@ typedef enum {
|
||||
ESP_GATT_WRITE_TYPE_RSP, /*!< Gatt write attribute need remote response */
|
||||
} esp_gatt_write_type_t;
|
||||
|
||||
typedef uint32_t esp_gatt_if_t; /*!< Gatt interface type, different application on GATT client use different gatt_if */
|
||||
#define ESP_GATT_IF_NONE 0xff /*!< If callback report gattc_if/gatts_if as this macro, means this event is not correspond to any app */
|
||||
|
||||
typedef uint8_t esp_gatt_if_t; /*!< Gatt interface type, different application on GATT client use different gatt_if */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -81,7 +81,6 @@ typedef union {
|
||||
*/
|
||||
struct gattc_reg_evt_param {
|
||||
esp_gatt_status_t status; /*!< Operation status */
|
||||
esp_gatt_if_t gatt_if; /*!< Gatt interface id, different application on gatt client different gatt_if */
|
||||
uint16_t app_id; /*!< Application id which input in register API */
|
||||
} reg; /*!< Gatt client callback param of ESP_GATTC_REG_EVT */
|
||||
|
||||
@ -91,7 +90,6 @@ typedef union {
|
||||
struct gattc_open_evt_param {
|
||||
esp_gatt_status_t status; /*!< Operation status */
|
||||
uint16_t conn_id; /*!< Connection id */
|
||||
esp_gatt_if_t gatt_if; /*!< Gatt interface id, different application on gatt client different gatt_if */
|
||||
esp_bd_addr_t remote_bda; /*!< Remote bluetooth device address */
|
||||
uint16_t mtu; /*!< MTU size */
|
||||
} open; /*!< Gatt client callback param of ESP_GATTC_OPEN_EVT */
|
||||
@ -102,7 +100,6 @@ typedef union {
|
||||
struct gattc_close_evt_param {
|
||||
esp_gatt_status_t status; /*!< Operation status */
|
||||
uint16_t conn_id; /*!< Connection id */
|
||||
esp_gatt_if_t gatt_if; /*!< Gatt interface id, different application on gatt client different gatt_if */
|
||||
esp_bd_addr_t remote_bda; /*!< Remote bluetooth device address */
|
||||
esp_gatt_conn_reason_t reason; /*!< The reason of gatt connection close */
|
||||
} close; /*!< Gatt client callback param of ESP_GATTC_CLOSE_EVT */
|
||||
@ -247,6 +244,14 @@ typedef union {
|
||||
|
||||
} esp_ble_gattc_cb_param_t; /*!< GATT client callback parameter union type */
|
||||
|
||||
/**
|
||||
* @brief GATT Client callback function type
|
||||
* @param event : Event type
|
||||
* @param gatts_if : GATT client access interface, normally
|
||||
* different gattc_if correspond to different profile
|
||||
* @param param : Point to callback parameter, currently is union type
|
||||
*/
|
||||
typedef void (* esp_gattc_cb_t)(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gattc_cb_param_t *param);
|
||||
|
||||
/**
|
||||
* @brief This function is called to register application callbacks
|
||||
@ -259,7 +264,7 @@ typedef union {
|
||||
* - other: failed
|
||||
*
|
||||
*/
|
||||
esp_err_t esp_ble_gattc_register_callback(esp_profile_cb_t callback);
|
||||
esp_err_t esp_ble_gattc_register_callback(esp_gattc_cb_t callback);
|
||||
|
||||
|
||||
/**
|
||||
@ -280,20 +285,20 @@ esp_err_t esp_ble_gattc_app_register(uint16_t app_id);
|
||||
* @brief This function is called to unregister an application
|
||||
* from GATTC module.
|
||||
*
|
||||
* @param[in] gatt_if : app identifier.
|
||||
* @param[in] gattc_if: Gatt client access interface.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: success
|
||||
* - other: failed
|
||||
*
|
||||
*/
|
||||
esp_err_t esp_ble_gattc_app_unregister(esp_gatt_if_t gatt_if);
|
||||
esp_err_t esp_ble_gattc_app_unregister(esp_gatt_if_t gattc_if);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Open a direct connection or add a background auto connection
|
||||
*
|
||||
* @param[in] gatt_if: application identity.
|
||||
* @param[in] gattc_if: Gatt client access interface.
|
||||
* @param[in] remote_bda: remote device bluetooth device address.
|
||||
* @param[in] is_direct: direct connection or background auto connection
|
||||
*
|
||||
@ -302,12 +307,13 @@ esp_err_t esp_ble_gattc_app_unregister(esp_gatt_if_t gatt_if);
|
||||
* - other: failed
|
||||
*
|
||||
*/
|
||||
esp_err_t esp_ble_gattc_open(esp_gatt_if_t gatt_if, esp_bd_addr_t remote_bda, bool is_direct);
|
||||
esp_err_t esp_ble_gattc_open(esp_gatt_if_t gattc_if, esp_bd_addr_t remote_bda, bool is_direct);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Close a connection to a GATT server.
|
||||
*
|
||||
* @param[in] gattc_if: Gatt client access interface.
|
||||
* @param[in] conn_id: connection ID to be closed.
|
||||
*
|
||||
* @return
|
||||
@ -315,13 +321,14 @@ esp_err_t esp_ble_gattc_open(esp_gatt_if_t gatt_if, esp_bd_addr_t remote_bda, bo
|
||||
* - other: failed
|
||||
*
|
||||
*/
|
||||
esp_err_t esp_ble_gattc_close(uint16_t conn_id);
|
||||
esp_err_t esp_ble_gattc_close (esp_gatt_if_t gattc_if, uint16_t conn_id);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Configure the MTU size in the GATT channel. This can be done
|
||||
* only once per connection.
|
||||
*
|
||||
* @param[in] gattc_if: Gatt client access interface.
|
||||
* @param[in] conn_id: connection ID.
|
||||
* @param[in] mtu: desired MTU size to use.
|
||||
*
|
||||
@ -330,7 +337,7 @@ esp_err_t esp_ble_gattc_close(uint16_t conn_id);
|
||||
* - other: failed
|
||||
*
|
||||
*/
|
||||
esp_err_t esp_ble_gattc_config_mtu(uint16_t conn_id, uint16_t mtu);
|
||||
esp_err_t esp_ble_gattc_config_mtu (esp_gatt_if_t gattc_if, uint16_t conn_id, uint16_t mtu);
|
||||
|
||||
|
||||
/**
|
||||
@ -339,6 +346,7 @@ esp_err_t esp_ble_gattc_config_mtu(uint16_t conn_id, uint16_t mtu);
|
||||
* by a callback event, and followed by a service search complete
|
||||
* event.
|
||||
*
|
||||
* @param[in] gattc_if: Gatt client access interface.
|
||||
* @param[in] conn_id: connection ID.
|
||||
* @param[in] filter_uuid: a UUID of the service application is interested in.
|
||||
* If Null, discover for all services.
|
||||
@ -348,32 +356,32 @@ esp_err_t esp_ble_gattc_config_mtu(uint16_t conn_id, uint16_t mtu);
|
||||
* - other: failed
|
||||
*
|
||||
*/
|
||||
esp_err_t esp_ble_gattc_search_service(uint16_t conn_id, esp_bt_uuid_t *filter_uuid);
|
||||
esp_err_t esp_ble_gattc_search_service(esp_gatt_if_t gattc_if, uint16_t conn_id, esp_bt_uuid_t *filter_uuid);
|
||||
|
||||
|
||||
/**
|
||||
* @brief This function is called to find the first characteristic of the
|
||||
* service on the given server.
|
||||
*
|
||||
* @param[in] gattc_if: Gatt client access interface.
|
||||
* @param[in] conn_id: connection ID which identify the server.
|
||||
*
|
||||
* @param[in] srvc_id: service ID
|
||||
*
|
||||
* @param[in] start_char_id: the start characteristic ID
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: success
|
||||
* - other: failed
|
||||
*
|
||||
*/
|
||||
esp_err_t esp_ble_gattc_get_characteristic(uint16_t conn_id,
|
||||
esp_gatt_srvc_id_t *srvc_id, esp_gatt_id_t *start_char_id);
|
||||
|
||||
esp_err_t esp_ble_gattc_get_characteristic(esp_gatt_if_t gattc_if,
|
||||
uint16_t conn_id,
|
||||
esp_gatt_srvc_id_t *srvc_id,
|
||||
esp_gatt_id_t *start_char_id);
|
||||
|
||||
/**
|
||||
* @brief This function is called to find the descriptor of the
|
||||
* service on the given server.
|
||||
*
|
||||
* @param[in] gattc_if: Gatt client access interface.
|
||||
* @param[in] conn_id: connection ID which identify the server.
|
||||
* @param[in] srvc_id: the service ID of which the characteristic is belonged to.
|
||||
* @param[in] char_id: Characteristic ID, if NULL find the first available
|
||||
@ -385,8 +393,10 @@ esp_err_t esp_ble_gattc_get_characteristic(uint16_t conn_id,
|
||||
* - other: failed
|
||||
*
|
||||
*/
|
||||
esp_err_t esp_ble_gattc_get_descriptor(uint16_t conn_id,
|
||||
esp_gatt_srvc_id_t *srvc_id, esp_gatt_id_t *char_id,
|
||||
esp_err_t esp_ble_gattc_get_descriptor(esp_gatt_if_t gattc_if,
|
||||
uint16_t conn_id,
|
||||
esp_gatt_srvc_id_t *srvc_id,
|
||||
esp_gatt_id_t *char_id,
|
||||
esp_gatt_id_t *start_descr_id);
|
||||
|
||||
|
||||
@ -394,6 +404,7 @@ esp_err_t esp_ble_gattc_get_descriptor(uint16_t conn_id,
|
||||
* @brief This function is called to find the first characteristic of the
|
||||
* service on the given server.
|
||||
*
|
||||
* @param[in] gattc_if: Gatt client access interface.
|
||||
* @param[in] conn_id: connection ID which identify the server.
|
||||
* @param[in] srvc_id: the service ID of which the characteristic is belonged to.
|
||||
* @param[in] start_incl_srvc_id: the start include service id
|
||||
@ -403,14 +414,17 @@ esp_err_t esp_ble_gattc_get_descriptor(uint16_t conn_id,
|
||||
* - other: failed
|
||||
*
|
||||
*/
|
||||
esp_err_t esp_ble_gattc_get_included_service(uint16_t conn_id,
|
||||
esp_gatt_srvc_id_t *srvc_id, esp_gatt_srvc_id_t *start_incl_srvc_id);
|
||||
esp_err_t esp_ble_gattc_get_included_service(esp_gatt_if_t gattc_if,
|
||||
uint16_t conn_id,
|
||||
esp_gatt_srvc_id_t *srvc_id,
|
||||
esp_gatt_srvc_id_t *start_incl_srvc_id);
|
||||
|
||||
|
||||
/**
|
||||
* @brief This function is called to read a service's characteristics of
|
||||
* the given characteriistic ID
|
||||
* the given characteristic ID
|
||||
*
|
||||
* @param[in] gattc_if: Gatt client access interface.
|
||||
* @param[in] conn_id : connection ID.
|
||||
* @param[in] srvc_id : service ID.
|
||||
* @param[in] char_id : characteristic ID to read.
|
||||
@ -421,7 +435,8 @@ esp_err_t esp_ble_gattc_get_included_service(uint16_t conn_id,
|
||||
* - other: failed
|
||||
*
|
||||
*/
|
||||
esp_err_t esp_ble_gattc_read_char (uint16_t conn_id,
|
||||
esp_err_t esp_ble_gattc_read_char (esp_gatt_if_t gattc_if,
|
||||
uint16_t conn_id,
|
||||
esp_gatt_srvc_id_t *srvc_id,
|
||||
esp_gatt_id_t *char_id,
|
||||
esp_gatt_auth_req_t auth_req);
|
||||
@ -430,6 +445,7 @@ esp_err_t esp_ble_gattc_read_char (uint16_t conn_id,
|
||||
/**
|
||||
* @brief This function is called to read a characteristics descriptor.
|
||||
*
|
||||
* @param[in] gattc_if: Gatt client access interface.
|
||||
* @param[in] conn_id : connection ID.
|
||||
* @param[in] srvc_id : service ID.
|
||||
* @param[in] char_id : characteristic ID to read.
|
||||
@ -441,7 +457,8 @@ esp_err_t esp_ble_gattc_read_char (uint16_t conn_id,
|
||||
* - other: failed
|
||||
*
|
||||
*/
|
||||
esp_err_t esp_ble_gattc_read_char_descr (uint16_t conn_id,
|
||||
esp_err_t esp_ble_gattc_read_char_descr (esp_gatt_if_t gattc_if,
|
||||
uint16_t conn_id,
|
||||
esp_gatt_srvc_id_t *srvc_id,
|
||||
esp_gatt_id_t *char_id,
|
||||
esp_gatt_id_t *descr_id,
|
||||
@ -451,6 +468,7 @@ esp_err_t esp_ble_gattc_read_char_descr (uint16_t conn_id,
|
||||
/**
|
||||
* @brief This function is called to write characteristic value.
|
||||
*
|
||||
* @param[in] gattc_if: Gatt client access interface.
|
||||
* @param[in] conn_id : connection ID.
|
||||
* @param[in] srvc_id : service ID.
|
||||
* @param[in] char_id : characteristic ID to write.
|
||||
@ -464,7 +482,8 @@ esp_err_t esp_ble_gattc_read_char_descr (uint16_t conn_id,
|
||||
* - other: failed
|
||||
*
|
||||
*/
|
||||
esp_err_t esp_ble_gattc_write_char( uint16_t conn_id,
|
||||
esp_err_t esp_ble_gattc_write_char( esp_gatt_if_t gattc_if,
|
||||
uint16_t conn_id,
|
||||
esp_gatt_srvc_id_t *srvc_id,
|
||||
esp_gatt_id_t *char_id,
|
||||
uint16_t value_len,
|
||||
@ -476,6 +495,7 @@ esp_err_t esp_ble_gattc_write_char( uint16_t conn_id,
|
||||
/**
|
||||
* @brief This function is called to write characteristic descriptor value.
|
||||
*
|
||||
* @param[in] gattc_if: Gatt client access interface.
|
||||
* @param[in] conn_id : connection ID
|
||||
* @param[in] srvc_id : service ID.
|
||||
* @param[in] char_id : characteristic ID.
|
||||
@ -490,7 +510,8 @@ esp_err_t esp_ble_gattc_write_char( uint16_t conn_id,
|
||||
* - other: failed
|
||||
*
|
||||
*/
|
||||
esp_err_t esp_ble_gattc_write_char_descr (uint16_t conn_id,
|
||||
esp_err_t esp_ble_gattc_write_char_descr (esp_gatt_if_t gattc_if,
|
||||
uint16_t conn_id,
|
||||
esp_gatt_srvc_id_t *srvc_id,
|
||||
esp_gatt_id_t *char_id,
|
||||
esp_gatt_id_t *descr_id,
|
||||
@ -503,6 +524,7 @@ esp_err_t esp_ble_gattc_write_char_descr (uint16_t conn_id,
|
||||
/**
|
||||
* @brief This function is called to prepare write a characteristic value.
|
||||
*
|
||||
* @param[in] gattc_if: Gatt client access interface.
|
||||
* @param[in] conn_id : connection ID.
|
||||
* @param[in] srvc_id : service ID.
|
||||
* @param[in] char_id : GATT characteristic ID of the service.
|
||||
@ -516,7 +538,8 @@ esp_err_t esp_ble_gattc_write_char_descr (uint16_t conn_id,
|
||||
* - other: failed
|
||||
*
|
||||
*/
|
||||
esp_err_t esp_ble_gattc_prepare_write(uint16_t conn_id,
|
||||
esp_err_t esp_ble_gattc_prepare_write(esp_gatt_if_t gattc_if,
|
||||
uint16_t conn_id,
|
||||
esp_gatt_srvc_id_t *srvc_id,
|
||||
esp_gatt_id_t *char_id,
|
||||
uint16_t offset,
|
||||
@ -524,9 +547,11 @@ esp_err_t esp_ble_gattc_prepare_write(uint16_t conn_id,
|
||||
uint8_t *value,
|
||||
esp_gatt_auth_req_t auth_req);
|
||||
|
||||
|
||||
/**
|
||||
* @brief This function is called to execute write a prepare write sequence.
|
||||
*
|
||||
* @param[in] gattc_if: Gatt client access interface.
|
||||
* @param[in] conn_id : connection ID.
|
||||
* @param[in] is_execute : execute or cancel.
|
||||
*
|
||||
@ -535,13 +560,13 @@ esp_err_t esp_ble_gattc_prepare_write(uint16_t conn_id,
|
||||
* - other: failed
|
||||
*
|
||||
*/
|
||||
esp_err_t esp_ble_gattc_execute_write (uint16_t conn_id, bool is_execute);
|
||||
esp_err_t esp_ble_gattc_execute_write (esp_gatt_if_t gattc_if, uint16_t conn_id, bool is_execute);
|
||||
|
||||
|
||||
/**
|
||||
* @brief This function is called to register for notification of a service.
|
||||
*
|
||||
* @param[in] gatt_if : gatt interface id.
|
||||
* @param[in] gattc_if: Gatt client access interface.
|
||||
* @param[in] server_bda : target GATT server.
|
||||
* @param[in] srvc_id : pointer to GATT service ID.
|
||||
* @param[in] char_id : pointer to GATT characteristic ID.
|
||||
@ -551,7 +576,7 @@ esp_err_t esp_ble_gattc_execute_write (uint16_t conn_id, bool is_execute);
|
||||
* - other: failed
|
||||
*
|
||||
*/
|
||||
esp_gatt_status_t esp_ble_gattc_register_for_notify (esp_gatt_if_t gatt_if,
|
||||
esp_gatt_status_t esp_ble_gattc_register_for_notify (esp_gatt_if_t gattc_if,
|
||||
esp_bd_addr_t server_bda,
|
||||
esp_gatt_srvc_id_t *srvc_id,
|
||||
esp_gatt_id_t *char_id);
|
||||
@ -560,7 +585,7 @@ esp_gatt_status_t esp_ble_gattc_register_for_notify (esp_gatt_if_t gatt_if,
|
||||
/**
|
||||
* @brief This function is called to de-register for notification of a service.
|
||||
*
|
||||
* @param[in] gatt_if : gatt interface id.
|
||||
* @param[in] gattc_if: Gatt client access interface.
|
||||
* @param[in] server_bda : target GATT server.
|
||||
* @param[in] srvc_id : pointer to GATT service ID.
|
||||
* @param[in] char_id : pointer to GATT characteristic ID.
|
||||
@ -570,7 +595,7 @@ esp_gatt_status_t esp_ble_gattc_register_for_notify (esp_gatt_if_t gatt_if,
|
||||
* - other: failed
|
||||
*
|
||||
*/
|
||||
esp_gatt_status_t esp_ble_gattc_unregister_for_notify (esp_gatt_if_t gatt_if,
|
||||
esp_gatt_status_t esp_ble_gattc_unregister_for_notify (esp_gatt_if_t gattc_if,
|
||||
esp_bd_addr_t server_bda,
|
||||
esp_gatt_srvc_id_t *srvc_id,
|
||||
esp_gatt_id_t *char_id);
|
||||
|
@ -48,6 +48,8 @@ typedef enum {
|
||||
ESP_GATTS_CONGEST_EVT = 20, /*!< When congest happen, the event comes */
|
||||
/* following is extra event */
|
||||
ESP_GATTS_RESPONSE_EVT = 21, /*!< When gatt send response complete, the event comes */
|
||||
ESP_GATTS_CREAT_ATTR_TAB_EVT = 22,
|
||||
ESP_GATTS_SET_ATTR_VAL_EVT = 23,
|
||||
} esp_gatts_cb_event_t;
|
||||
|
||||
/**
|
||||
@ -59,7 +61,6 @@ typedef union {
|
||||
*/
|
||||
struct gatts_reg_evt_param {
|
||||
esp_gatt_status_t status; /*!< Operation status */
|
||||
uint16_t gatt_if; /*!< Gatt interface id, different application on gatt client different gatt_if */
|
||||
uint16_t app_id; /*!< Application id which input in register API */
|
||||
} reg; /*!< Gatt server callback param of ESP_GATTS_REG_EVT */
|
||||
|
||||
@ -73,8 +74,10 @@ typedef union {
|
||||
uint16_t handle; /*!< The attribute handle */
|
||||
uint16_t offset; /*!< Offset of the value, if the value is too long */
|
||||
bool is_long; /*!< The value is too long or not */
|
||||
bool need_rsp; /*!< The read operation need to do response */
|
||||
} read; /*!< Gatt server callback param of ESP_GATTS_READ_EVT */
|
||||
|
||||
|
||||
/**
|
||||
* @brief ESP_GATTS_WRITE_EVT
|
||||
*/
|
||||
@ -97,8 +100,8 @@ typedef union {
|
||||
uint16_t conn_id; /*!< Connection id */
|
||||
uint32_t trans_id; /*!< Transfer id */
|
||||
esp_bd_addr_t bda; /*!< The bluetooth device address which been written */
|
||||
#define ESP_GATT_PREP_WRITE_CANCEL 0x00
|
||||
#define ESP_GATT_PREP_WRITE_EXEC 0x01
|
||||
#define ESP_GATT_PREP_WRITE_CANCEL 0x00 /*!< Prepare write flag to indicate cancel prepare write */
|
||||
#define ESP_GATT_PREP_WRITE_EXEC 0x01 /*!< Prepare write flag to indicate execute prepare write */
|
||||
uint8_t exec_write_flag; /*!< Execute write flag */
|
||||
} exec_write; /*!< Gatt server callback param of ESP_GATTS_EXEC_WRITE_EVT */
|
||||
|
||||
@ -127,7 +130,6 @@ typedef union {
|
||||
*/
|
||||
struct gatts_create_evt_param {
|
||||
esp_gatt_status_t status; /*!< Operation status */
|
||||
uint16_t gatt_if; /*!< Gatt interface id, different application on gatt client different gatt_if */
|
||||
uint16_t service_handle; /*!< Service attribute handle */
|
||||
esp_gatt_srvc_id_t service_id; /*!< Service id, include service uuid and other information */
|
||||
} create; /*!< Gatt server callback param of ESP_GATTS_CREATE_EVT */
|
||||
@ -137,7 +139,6 @@ typedef union {
|
||||
*/
|
||||
struct gatts_add_incl_srvc_evt_param {
|
||||
esp_gatt_status_t status; /*!< Operation status */
|
||||
uint16_t gatt_if; /*!< Gatt interface id, different application on gatt client different gatt_if */
|
||||
uint16_t attr_handle; /*!< Included service attribute handle */
|
||||
uint16_t service_handle; /*!< Service attribute handle */
|
||||
} add_incl_srvc; /*!< Gatt server callback param of ESP_GATTS_ADD_INCL_SRVC_EVT */
|
||||
@ -147,7 +148,6 @@ typedef union {
|
||||
*/
|
||||
struct gatts_add_char_evt_param {
|
||||
esp_gatt_status_t status; /*!< Operation status */
|
||||
uint16_t gatt_if; /*!< Gatt interface id, different application on gatt client different gatt_if */
|
||||
uint16_t attr_handle; /*!< Characteristic attribute handle */
|
||||
uint16_t service_handle; /*!< Service attribute handle */
|
||||
esp_bt_uuid_t char_uuid; /*!< Characteristic uuid */
|
||||
@ -158,7 +158,6 @@ typedef union {
|
||||
*/
|
||||
struct gatts_add_char_descr_evt_param {
|
||||
esp_gatt_status_t status; /*!< Operation status */
|
||||
uint16_t gatt_if; /*!< Gatt interface id, different application on gatt client different gatt_if */
|
||||
uint16_t attr_handle; /*!< Descriptor attribute handle */
|
||||
uint16_t service_handle; /*!< Service attribute handle */
|
||||
esp_bt_uuid_t char_uuid; /*!< Characteristic uuid */
|
||||
@ -169,7 +168,6 @@ typedef union {
|
||||
*/
|
||||
struct gatts_delete_evt_param {
|
||||
esp_gatt_status_t status; /*!< Operation status */
|
||||
uint16_t gatt_if; /*!< Gatt interface id, different application on gatt client different gatt_if */
|
||||
uint16_t service_handle; /*!< Service attribute handle */
|
||||
} del; /*!< Gatt server callback param of ESP_GATTS_DELETE_EVT */
|
||||
|
||||
@ -178,7 +176,6 @@ typedef union {
|
||||
*/
|
||||
struct gatts_start_evt_param {
|
||||
esp_gatt_status_t status; /*!< Operation status */
|
||||
uint16_t gatt_if; /*!< Gatt interface id, different application on gatt client different gatt_if */
|
||||
uint16_t service_handle; /*!< Service attribute handle */
|
||||
} start; /*!< Gatt server callback param of ESP_GATTS_START_EVT */
|
||||
|
||||
@ -187,7 +184,6 @@ typedef union {
|
||||
*/
|
||||
struct gatts_stop_evt_param {
|
||||
esp_gatt_status_t status; /*!< Operation status */
|
||||
uint16_t gatt_if; /*!< Gatt interface id, different application on gatt client different gatt_if */
|
||||
uint16_t service_handle; /*!< Service attribute handle */
|
||||
} stop; /*!< Gatt server callback param of ESP_GATTS_STOP_EVT */
|
||||
|
||||
@ -196,7 +192,6 @@ typedef union {
|
||||
*/
|
||||
struct gatts_connect_evt_param {
|
||||
uint16_t conn_id; /*!< Connection id */
|
||||
uint16_t gatt_if; /*!< Gatt interface id, different application on gatt client different gatt_if */
|
||||
esp_bd_addr_t remote_bda; /*!< Remote bluetooth device address */
|
||||
bool is_connected; /*!< Indicate it is connected or not */
|
||||
} connect; /*!< Gatt server callback param of ESP_GATTS_CONNECT_EVT */
|
||||
@ -206,7 +201,6 @@ typedef union {
|
||||
*/
|
||||
struct gatts_disconnect_evt_param {
|
||||
uint16_t conn_id; /*!< Connection id */
|
||||
uint16_t gatt_if; /*!< Gatt interface id, different application on gatt client different gatt_if */
|
||||
esp_bd_addr_t remote_bda; /*!< Remote bluetooth device address */
|
||||
bool is_connected; /*!< Indicate it is connected or not */
|
||||
} disconnect; /*!< Gatt server callback param of ESP_GATTS_DISCONNECT_EVT */
|
||||
@ -238,8 +232,38 @@ typedef union {
|
||||
esp_gatt_status_t status; /*!< Operation status */
|
||||
uint16_t handle; /*!< Attribute handle which send response */
|
||||
} rsp; /*!< Gatt server callback param of ESP_GATTS_RESPONSE_EVT */
|
||||
|
||||
/**
|
||||
* @brief ESP_GATTS_CREAT_ATTR_TAB_EVT
|
||||
*/
|
||||
struct gatts_add_attr_tab_evt_param{
|
||||
esp_gatt_status_t status; /*!< Operation status */
|
||||
esp_bt_uuid_t svc_uuid; /*!< Service uuid type */
|
||||
uint16_t num_handle; /*!< The number of the attribute handle to be added to the gatts database */
|
||||
uint16_t *handles; /*!< The number to the handles */
|
||||
} add_attr_tab; /*!< Gatt server callback param of ESP_GATTS_CREAT_ATTR_TAB_EVT */
|
||||
|
||||
|
||||
/**
|
||||
* @brief ESP_GATTS_SET_ATTR_VAL_EVT
|
||||
*/
|
||||
struct gatts_set_attr_val_evt_param{
|
||||
uint16_t srvc_handle; /*!< The service handle */
|
||||
uint16_t attr_handle; /*!< The attribute handle */
|
||||
esp_gatt_status_t status; /*!< Operation status*/
|
||||
} set_attr_val; /*!< Gatt server callback param of ESP_GATTS_SET_ATTR_VAL_EVT */
|
||||
|
||||
} esp_ble_gatts_cb_param_t;
|
||||
|
||||
/**
|
||||
* @brief GATT Server callback function type
|
||||
* @param event : Event type
|
||||
* @param gatts_if : GATT server access interface, normally
|
||||
* different gatts_if correspond to different profile
|
||||
* @param param : Point to callback parameter, currently is union type
|
||||
*/
|
||||
typedef void (* esp_gatts_cb_t)(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param);
|
||||
|
||||
/**
|
||||
* @brief This function is called to register application callbacks
|
||||
* with BTA GATTS module.
|
||||
@ -249,9 +273,7 @@ typedef union {
|
||||
* - other : failed
|
||||
*
|
||||
*/
|
||||
esp_err_t esp_ble_gatts_register_callback(esp_profile_cb_t callback);
|
||||
|
||||
|
||||
esp_err_t esp_ble_gatts_register_callback(esp_gatts_cb_t callback);
|
||||
|
||||
/**
|
||||
* @brief This function is called to register application identifier
|
||||
@ -268,14 +290,13 @@ esp_err_t esp_ble_gatts_app_register(uint16_t app_id);
|
||||
/**
|
||||
* @brief unregister with GATT Server.
|
||||
*
|
||||
* @param[in] gatt_if: gatt interface id.
|
||||
*
|
||||
* @param[in] gatts_if: GATT server access interface
|
||||
* @return
|
||||
* - ESP_OK : success
|
||||
* - other : failed
|
||||
*
|
||||
*/
|
||||
esp_err_t esp_ble_gatts_app_unregister(esp_gatt_if_t gatt_if);
|
||||
esp_err_t esp_ble_gatts_app_unregister(esp_gatt_if_t gatts_if);
|
||||
|
||||
|
||||
/**
|
||||
@ -285,7 +306,7 @@ esp_err_t esp_ble_gatts_app_unregister(esp_gatt_if_t gatt_if);
|
||||
* the callback function needs to be used when adding included
|
||||
* service and characteristics/descriptors into the service.
|
||||
*
|
||||
* @param[in] gatt_if: gatt interface ID
|
||||
* @param[in] gatts_if: GATT server access interface
|
||||
* @param[in] service_id: service ID.
|
||||
* @param[in] num_handle: number of handle requested for this service.
|
||||
*
|
||||
@ -294,11 +315,26 @@ esp_err_t esp_ble_gatts_app_unregister(esp_gatt_if_t gatt_if);
|
||||
* - other : failed
|
||||
*
|
||||
*/
|
||||
esp_err_t esp_ble_gatts_create_service(esp_gatt_if_t gatt_if,
|
||||
esp_err_t esp_ble_gatts_create_service(esp_gatt_if_t gatts_if,
|
||||
esp_gatt_srvc_id_t *service_id, uint16_t num_handle);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief Create a service attribute tab.
|
||||
* @param[in] gatts_attr_db: the pointer to the service attr tab
|
||||
* @param[in] gatts_if: GATT server access interface
|
||||
* @param[in] max_nb_attr: the number of attribute to be added to the service database.
|
||||
* @param[in] srvc_inst_id: the instance id of the service
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK : success
|
||||
* - other : failed
|
||||
*
|
||||
*/
|
||||
esp_err_t esp_ble_gatts_create_attr_tab(const esp_gatts_attr_db_t *gatts_attr_db,
|
||||
esp_gatt_if_t gatts_if,
|
||||
uint8_t max_nb_attr,
|
||||
uint8_t srvc_inst_id);
|
||||
/**
|
||||
* @brief This function is called to add an included service. After included
|
||||
* service is included, a callback event BTA_GATTS_ADD_INCL_SRVC_EVT
|
||||
@ -325,6 +361,8 @@ esp_err_t esp_ble_gatts_add_included_service(uint16_t service_handle, uint16_t i
|
||||
* @param[in] char_uuid : Characteristic UUID.
|
||||
* @param[in] perm : Characteristic value declaration attribute permission.
|
||||
* @param[in] property : Characteristic Properties
|
||||
* @param[in] char_val : Characteristic value
|
||||
* @param[in] control : attribute response control byte
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK : success
|
||||
@ -332,7 +370,8 @@ esp_err_t esp_ble_gatts_add_included_service(uint16_t service_handle, uint16_t i
|
||||
*
|
||||
*/
|
||||
esp_err_t esp_ble_gatts_add_char(uint16_t service_handle, esp_bt_uuid_t *char_uuid,
|
||||
esp_gatt_perm_t perm, esp_gatt_char_prop_t property);
|
||||
esp_gatt_perm_t perm, esp_gatt_char_prop_t property, esp_attr_value_t *char_val,
|
||||
esp_attr_control_t *control);
|
||||
|
||||
|
||||
/**
|
||||
@ -344,7 +383,8 @@ esp_err_t esp_ble_gatts_add_char(uint16_t service_handle, esp_bt_uuid_t *char_
|
||||
* be added.
|
||||
* @param[in] perm: descriptor access permission.
|
||||
* @param[in] descr_uuid: descriptor UUID.
|
||||
*
|
||||
* @param[in] char_descr_val : Characteristic descriptor value
|
||||
* @param[in] control : attribute response control byte
|
||||
* @return
|
||||
* - ESP_OK : success
|
||||
* - other : failed
|
||||
@ -352,7 +392,8 @@ esp_err_t esp_ble_gatts_add_char(uint16_t service_handle, esp_bt_uuid_t *char_
|
||||
*/
|
||||
esp_err_t esp_ble_gatts_add_char_descr (uint16_t service_handle,
|
||||
esp_bt_uuid_t *descr_uuid,
|
||||
esp_gatt_perm_t perm);
|
||||
esp_gatt_perm_t perm, esp_attr_value_t *char_descr_val,
|
||||
esp_attr_control_t *control);
|
||||
|
||||
|
||||
|
||||
@ -400,8 +441,10 @@ esp_err_t esp_ble_gatts_stop_service(uint16_t service_handle);
|
||||
|
||||
|
||||
/**
|
||||
* @brief This function is called to read a characteristics descriptor.
|
||||
* @brief Send indicate or notify to GATT client.
|
||||
* Set param need_confirm as false will send notification, otherwise indication.
|
||||
*
|
||||
* @param[in] gatts_if: GATT server access interface
|
||||
* @param[in] conn_id - connection id to indicate.
|
||||
* @param[in] attr_handle - attribute handle to indicate.
|
||||
* @param[in] value_len - indicate value length.
|
||||
@ -413,13 +456,14 @@ esp_err_t esp_ble_gatts_stop_service(uint16_t service_handle);
|
||||
* - other : failed
|
||||
*
|
||||
*/
|
||||
esp_err_t esp_ble_gatts_send_indicate(uint16_t conn_id, uint16_t attr_handle,
|
||||
esp_err_t esp_ble_gatts_send_indicate(esp_gatt_if_t gatts_if, uint16_t conn_id, uint16_t attr_handle,
|
||||
uint16_t value_len, uint8_t *value, bool need_confirm);
|
||||
|
||||
|
||||
/**
|
||||
* @brief This function is called to send a response to a request.
|
||||
*
|
||||
* @param[in] gatts_if: GATT server access interface
|
||||
* @param[in] conn_id - connection identifier.
|
||||
* @param[in] trans_id - transfer id
|
||||
* @param[in] status - response status
|
||||
@ -430,14 +474,43 @@ esp_err_t esp_ble_gatts_send_indicate(uint16_t conn_id, uint16_t attr_handle,
|
||||
* - other : failed
|
||||
*
|
||||
*/
|
||||
esp_err_t esp_ble_gatts_send_response(uint16_t conn_id, uint32_t trans_id,
|
||||
esp_err_t esp_ble_gatts_send_response(esp_gatt_if_t gatts_if, uint16_t conn_id, uint32_t trans_id,
|
||||
esp_gatt_status_t status, esp_gatt_rsp_t *rsp);
|
||||
|
||||
|
||||
/**
|
||||
* @brief This function is called to set the attribute value by the application
|
||||
*
|
||||
* @param[in] attr_handle: the attribute handle which to be set
|
||||
* @param[in] length: the value length
|
||||
* @param[in] value: the pointer to the attribute value
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK : success
|
||||
* - other : failed
|
||||
*
|
||||
*/
|
||||
esp_err_t esp_ble_gatts_set_attr_value(uint16_t attr_handle, uint16_t length, const uint8_t *value);
|
||||
|
||||
/**
|
||||
* @brief Retrieve attribute value
|
||||
*
|
||||
* @param[in] attr_handle: Attribute handle.
|
||||
* @param[out] length: pointer to the attribute value length
|
||||
* @param[out] value: Pointer to attribute value payload, the value cannot be modified by user
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK : success
|
||||
* - other : failed
|
||||
*
|
||||
*/
|
||||
esp_err_t esp_ble_gatts_get_attr_value(uint16_t attr_handle, uint16_t *length, const uint8_t **value);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Open a direct open connection or add a background auto connection
|
||||
*
|
||||
* @param[in] gatt_if: application ID.
|
||||
* @param[in] gatts_if: GATT server access interface
|
||||
* @param[in] remote_bda: remote device bluetooth device address.
|
||||
* @param[in] is_direct: direct connection or background auto connection
|
||||
*
|
||||
@ -446,11 +519,12 @@ esp_err_t esp_ble_gatts_send_response(uint16_t conn_id, uint32_t trans_id,
|
||||
* - other : failed
|
||||
*
|
||||
*/
|
||||
esp_err_t esp_ble_gatts_open(esp_gatt_if_t gatt_if, esp_bd_addr_t remote_bda, bool is_direct);
|
||||
esp_err_t esp_ble_gatts_open(esp_gatt_if_t gatts_if, esp_bd_addr_t remote_bda, bool is_direct);
|
||||
|
||||
/**
|
||||
* @brief Close a connection a remote device.
|
||||
*
|
||||
* @param[in] gatts_if: GATT server access interface
|
||||
* @param[in] conn_id: connection ID to be closed.
|
||||
*
|
||||
* @return
|
||||
@ -458,7 +532,7 @@ esp_err_t esp_ble_gatts_open(esp_gatt_if_t gatt_if, esp_bd_addr_t remote_bda, bo
|
||||
* - other : failed
|
||||
*
|
||||
*/
|
||||
esp_err_t esp_ble_gatts_close(uint16_t conn_id);
|
||||
esp_err_t esp_ble_gatts_close(esp_gatt_if_t gatts_if, uint16_t conn_id);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -1014,8 +1014,8 @@ void BTA_DmSetBleAdvParamsAll (UINT16 adv_int_min, UINT16 adv_int_max,
|
||||
#if BLE_INCLUDED == TRUE
|
||||
tBTA_DM_API_BLE_ADV_PARAMS_ALL *p_msg;
|
||||
|
||||
APPL_TRACE_ERROR ("BTA_DmSetBleAdvParamsAll: %d, %d\n", adv_int_min, adv_int_max);
|
||||
APPL_TRACE_ERROR ("adv_type = %d, addr_type_own = %d, chnl_map = %d, adv_fil_pol = %d\n",
|
||||
APPL_TRACE_API ("BTA_DmSetBleAdvParamsAll: %d, %d\n", adv_int_min, adv_int_max);
|
||||
APPL_TRACE_API ("adv_type = %d, addr_type_own = %d, chnl_map = %d, adv_fil_pol = %d\n",
|
||||
adv_type, addr_type_own, chnl_map, adv_fil_pol);
|
||||
if ((p_msg = (tBTA_DM_API_BLE_ADV_PARAMS_ALL *) GKI_getbuf(sizeof(tBTA_DM_API_BLE_ADV_PARAMS_ALL)
|
||||
+ sizeof(tBLE_BD_ADDR))) != NULL) {
|
||||
|
@ -34,7 +34,6 @@
|
||||
#include "bta_gatts_int.h"
|
||||
#include "bta_gatts_co.h"
|
||||
#include "btm_ble_api.h"
|
||||
// #include "btif/include/btif_debug_conn.h"
|
||||
#include <string.h>
|
||||
|
||||
static void bta_gatts_nv_save_cback(BOOLEAN is_saved, tGATTS_HNDL_RANGE *p_hndl_range);
|
||||
@ -233,8 +232,6 @@ void bta_gatts_register(tBTA_GATTS_CB *p_cb, tBTA_GATTS_DATA *p_msg)
|
||||
if (p_msg->api_reg.p_cback) {
|
||||
(*p_msg->api_reg.p_cback)(BTA_GATTS_REG_EVT, &cb_data);
|
||||
}
|
||||
|
||||
LOG_ERROR("status=%x\n", status);
|
||||
}
|
||||
|
||||
|
||||
@ -406,10 +403,22 @@ void bta_gatts_add_char(tBTA_GATTS_SRVC_CB *p_srvc_cb, tBTA_GATTS_DATA *p_msg)
|
||||
UINT16 attr_id = 0;
|
||||
tBTA_GATTS cb_data;
|
||||
|
||||
tGATT_ATTR_VAL *p_attr_val = NULL;
|
||||
tGATTS_ATTR_CONTROL *p_control = NULL;
|
||||
|
||||
if(p_msg->api_add_char.attr_val.attr_max_len != 0){
|
||||
p_attr_val = &p_msg->api_add_char.attr_val;
|
||||
}
|
||||
|
||||
if(p_msg->api_add_char.control.auto_rsp != 0){
|
||||
p_control = &p_msg->api_add_char.control;
|
||||
}
|
||||
|
||||
|
||||
attr_id = GATTS_AddCharacteristic(p_msg->api_add_char.hdr.layer_specific,
|
||||
&p_msg->api_add_char.char_uuid,
|
||||
p_msg->api_add_char.perm,
|
||||
p_msg->api_add_char.property);
|
||||
p_msg->api_add_char.property, p_attr_val, p_control);
|
||||
cb_data.add_result.server_if = p_rcb->gatt_if;
|
||||
cb_data.add_result.service_id = p_msg->api_add_incl_srvc.hdr.layer_specific;
|
||||
cb_data.add_result.attr_id = attr_id;
|
||||
@ -422,11 +431,15 @@ void bta_gatts_add_char(tBTA_GATTS_SRVC_CB *p_srvc_cb, tBTA_GATTS_DATA *p_msg)
|
||||
} else {
|
||||
cb_data.add_result.status = BTA_GATT_ERROR;
|
||||
}
|
||||
if((p_attr_val != NULL) && (p_attr_val->attr_val != NULL)){
|
||||
GKI_freebuf(p_attr_val->attr_val);
|
||||
}
|
||||
|
||||
if (p_rcb->p_cback) {
|
||||
(*p_rcb->p_cback)(BTA_GATTS_ADD_CHAR_EVT, &cb_data);
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function bta_gatts_add_char_descr
|
||||
@ -441,10 +454,20 @@ void bta_gatts_add_char_descr(tBTA_GATTS_SRVC_CB *p_srvc_cb, tBTA_GATTS_DATA *p_
|
||||
tBTA_GATTS_RCB *p_rcb = &bta_gatts_cb.rcb[p_srvc_cb->rcb_idx];
|
||||
UINT16 attr_id = 0;
|
||||
tBTA_GATTS cb_data;
|
||||
tGATT_ATTR_VAL *p_attr_val = NULL;
|
||||
tGATTS_ATTR_CONTROL *p_control = NULL;
|
||||
|
||||
if (p_msg->api_add_char_descr.attr_val.attr_max_len != 0) {
|
||||
p_attr_val = &p_msg->api_add_char_descr.attr_val;
|
||||
}
|
||||
|
||||
if (p_msg->api_add_char_descr.control.auto_rsp != 0) {
|
||||
p_control = &p_msg->api_add_char_descr.control;
|
||||
}
|
||||
attr_id = GATTS_AddCharDescriptor(p_msg->api_add_char_descr.hdr.layer_specific,
|
||||
p_msg->api_add_char_descr.perm,
|
||||
&p_msg->api_add_char_descr.descr_uuid);
|
||||
&p_msg->api_add_char_descr.descr_uuid, p_attr_val,
|
||||
p_control);
|
||||
|
||||
cb_data.add_result.server_if = p_rcb->gatt_if;
|
||||
cb_data.add_result.service_id = p_msg->api_add_incl_srvc.hdr.layer_specific;
|
||||
@ -458,12 +481,50 @@ void bta_gatts_add_char_descr(tBTA_GATTS_SRVC_CB *p_srvc_cb, tBTA_GATTS_DATA *p_
|
||||
} else {
|
||||
cb_data.add_result.status = BTA_GATT_ERROR;
|
||||
}
|
||||
if((p_attr_val != NULL) && (p_attr_val->attr_val != NULL)){
|
||||
GKI_freebuf(p_attr_val->attr_val);
|
||||
}
|
||||
|
||||
if (p_rcb->p_cback) {
|
||||
(*p_rcb->p_cback)(BTA_GATTS_ADD_CHAR_DESCR_EVT, &cb_data);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function bta_gatts_add_char_descr
|
||||
**
|
||||
** Description action function to add characteristic descriptor.
|
||||
**
|
||||
** Returns none.
|
||||
**
|
||||
*******************************************************************************/
|
||||
void bta_gatts_set_attr_value(tBTA_GATTS_SRVC_CB *p_srvc_cb, tBTA_GATTS_DATA *p_msg)
|
||||
{
|
||||
tBTA_GATTS_RCB *p_rcb = &bta_gatts_cb.rcb[p_srvc_cb->rcb_idx];
|
||||
UINT16 attr_id = 0;
|
||||
tBTA_GATTS cb_data;
|
||||
tBTA_GATT_STATUS gatts_status;
|
||||
gatts_status = GATTS_SetAttributeValue(p_msg->api_add_char_descr.hdr.layer_specific,
|
||||
p_msg->api_set_val.length,
|
||||
p_msg->api_set_val.value);
|
||||
|
||||
cb_data.attr_val.server_if = p_rcb->gatt_if;
|
||||
cb_data.attr_val.service_id = p_msg->api_set_val.hdr.layer_specific;
|
||||
cb_data.attr_val.attr_id = attr_id;
|
||||
cb_data.attr_val.status = gatts_status;
|
||||
|
||||
if (p_rcb->p_cback) {
|
||||
(*p_rcb->p_cback)(BTA_GATTS_SET_ATTR_VAL_EVT, &cb_data);
|
||||
}
|
||||
}
|
||||
|
||||
void bta_gatts_get_attr_value(UINT16 attr_handle, UINT16 *length, UINT8 **value)
|
||||
{
|
||||
GATTS_GetAttributeValue(attr_handle, length, value);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function bta_gatts_delete_service
|
||||
|
@ -215,10 +215,14 @@ void BTA_GATTS_AddIncludeService(UINT16 service_id, UINT16 included_service_id)
|
||||
**
|
||||
*******************************************************************************/
|
||||
void BTA_GATTS_AddCharacteristic (UINT16 service_id, tBT_UUID *p_char_uuid,
|
||||
tBTA_GATT_PERM perm, tBTA_GATT_CHAR_PROP property)
|
||||
tBTA_GATT_PERM perm, tBTA_GATT_CHAR_PROP property, tGATT_ATTR_VAL *attr_val,
|
||||
tBTA_GATTS_ATTR_CONTROL *control)
|
||||
{
|
||||
tBTA_GATTS_API_ADD_CHAR *p_buf;
|
||||
|
||||
UINT16 len = 0;
|
||||
if(attr_val != NULL){
|
||||
len = attr_val->attr_len;
|
||||
}
|
||||
if ((p_buf = (tBTA_GATTS_API_ADD_CHAR *) GKI_getbuf(sizeof(tBTA_GATTS_API_ADD_CHAR))) != NULL) {
|
||||
memset(p_buf, 0, sizeof(tBTA_GATTS_API_ADD_CHAR));
|
||||
|
||||
@ -226,6 +230,19 @@ void BTA_GATTS_AddCharacteristic (UINT16 service_id, tBT_UUID *p_char_uuid,
|
||||
p_buf->hdr.layer_specific = service_id;
|
||||
p_buf->perm = perm;
|
||||
p_buf->property = property;
|
||||
if(control !=NULL){
|
||||
p_buf->control.auto_rsp = control->auto_rsp;
|
||||
}
|
||||
if(attr_val != NULL){
|
||||
APPL_TRACE_DEBUG("!!!!!!attr_val->attr_len = %x\n",attr_val->attr_len);
|
||||
APPL_TRACE_DEBUG("!!!!!!!attr_val->attr_max_len = %x\n",attr_val->attr_max_len);
|
||||
p_buf->attr_val.attr_len = attr_val->attr_len;
|
||||
p_buf->attr_val.attr_max_len = attr_val->attr_max_len;
|
||||
p_buf->attr_val.attr_val = (uint8_t *)GKI_getbuf(len);
|
||||
if(p_buf->attr_val.attr_val != NULL){
|
||||
memcpy(p_buf->attr_val.attr_val, attr_val->attr_val, attr_val->attr_len);
|
||||
}
|
||||
}
|
||||
|
||||
if (p_char_uuid) {
|
||||
memcpy(&p_buf->char_uuid, p_char_uuid, sizeof(tBT_UUID));
|
||||
@ -253,22 +270,43 @@ void BTA_GATTS_AddCharacteristic (UINT16 service_id, tBT_UUID *p_char_uuid,
|
||||
*******************************************************************************/
|
||||
void BTA_GATTS_AddCharDescriptor (UINT16 service_id,
|
||||
tBTA_GATT_PERM perm,
|
||||
tBT_UUID *p_descr_uuid)
|
||||
tBT_UUID *p_descr_uuid, tBTA_GATT_ATTR_VAL *attr_val,
|
||||
tBTA_GATTS_ATTR_CONTROL *control)
|
||||
{
|
||||
tBTA_GATTS_API_ADD_DESCR *p_buf;
|
||||
UINT16 len = sizeof(tBTA_GATTS_API_ADD_DESCR);
|
||||
UINT16 value_len = 0;
|
||||
|
||||
|
||||
if ((p_buf = (tBTA_GATTS_API_ADD_DESCR *) GKI_getbuf(len)) != NULL) {
|
||||
memset(p_buf, 0, len);
|
||||
if ((p_buf = (tBTA_GATTS_API_ADD_DESCR *) GKI_getbuf(sizeof(tBTA_GATTS_API_ADD_DESCR))) != NULL) {
|
||||
memset(p_buf, 0, sizeof(tBTA_GATTS_API_ADD_DESCR));
|
||||
|
||||
p_buf->hdr.event = BTA_GATTS_API_ADD_DESCR_EVT;
|
||||
p_buf->hdr.layer_specific = service_id;
|
||||
p_buf->perm = perm;
|
||||
|
||||
if(control != NULL){
|
||||
p_buf->control.auto_rsp = control->auto_rsp;
|
||||
}
|
||||
|
||||
if (p_descr_uuid) {
|
||||
memcpy(&p_buf->descr_uuid, p_descr_uuid, sizeof(tBT_UUID));
|
||||
}
|
||||
|
||||
if(attr_val != NULL){
|
||||
p_buf->attr_val.attr_len = attr_val->attr_len;
|
||||
p_buf->attr_val.attr_max_len = attr_val->attr_max_len;
|
||||
value_len = attr_val->attr_len;
|
||||
if (value_len != 0){
|
||||
p_buf->attr_val.attr_val = (uint8_t*)GKI_getbuf(value_len);
|
||||
if(p_buf->attr_val.attr_val != NULL){
|
||||
memcpy(p_buf->attr_val.attr_val, attr_val->attr_val, value_len);
|
||||
}
|
||||
else{
|
||||
APPL_TRACE_ERROR("Allocate fail for %s\n", __func__);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bta_sys_sendmsg(p_buf);
|
||||
}
|
||||
return;
|
||||
@ -276,14 +314,14 @@ void BTA_GATTS_AddCharDescriptor (UINT16 service_id,
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function BTA_GATTS_DeleteService
|
||||
**
|
||||
** Description This function is called to delete a service. When this is done,
|
||||
** a callback event BTA_GATTS_DELETE_EVT is report with the status.
|
||||
**
|
||||
** Parameters service_id: service_id to be deleted.
|
||||
**
|
||||
**
|
||||
** Function BTA_GATTS_DeleteService
|
||||
**
|
||||
** Description This function is called to delete a service. When this is done,
|
||||
** a callback event BTA_GATTS_DELETE_EVT is report with the status.
|
||||
**
|
||||
** Parameters service_id: service_id to be deleted.
|
||||
**
|
||||
** Returns returns none.
|
||||
**
|
||||
*******************************************************************************/
|
||||
@ -433,6 +471,29 @@ void BTA_GATTS_SendRsp (UINT16 conn_id, UINT32 trans_id,
|
||||
}
|
||||
|
||||
|
||||
void BTA_SetAttributeValue(UINT16 attr_handle, UINT16 length, UINT8 *value)
|
||||
{
|
||||
tBTA_GATTS_API_SET_ATTR_VAL *p_buf;
|
||||
if((p_buf = (tBTA_GATTS_API_SET_ATTR_VAL *)GKI_getbuf(
|
||||
sizeof(tBTA_GATTS_API_SET_ATTR_VAL))) != NULL){
|
||||
p_buf->hdr.event = BTA_GATTS_API_SET_ATTR_VAL_EVT;
|
||||
p_buf->hdr.layer_specific = attr_handle;
|
||||
p_buf->length = length;
|
||||
if(value != NULL){
|
||||
if((p_buf->value = (UINT8 *)GKI_getbuf(length)) != NULL){
|
||||
memcpy(p_buf->value, value, length);
|
||||
}
|
||||
}
|
||||
|
||||
bta_sys_sendmsg(p_buf);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void BTA_GetAttributeValue(UINT16 attr_handle, UINT16 *length, UINT8 **value)
|
||||
{
|
||||
bta_gatts_get_attr_value(attr_handle, length, value);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
|
@ -104,29 +104,30 @@ BOOLEAN bta_gatts_hdl_event(BT_HDR *p_msg)
|
||||
case BTA_GATTS_API_RSP_EVT:
|
||||
bta_gatts_send_rsp(p_cb, (tBTA_GATTS_DATA *) p_msg);
|
||||
break;
|
||||
|
||||
case BTA_GATTS_API_SET_ATTR_VAL_EVT:{
|
||||
UINT16 attr_id = ((tBTA_GATTS_DATA *) p_msg)->api_set_val.hdr.layer_specific;
|
||||
p_srvc_cb = bta_gatts_find_srvc_cb_by_attr_id(p_cb, attr_id);
|
||||
bta_gatts_set_attr_value(p_srvc_cb, (tBTA_GATTS_DATA *) p_msg);
|
||||
break;
|
||||
}
|
||||
case BTA_GATTS_API_LISTEN_EVT:
|
||||
bta_gatts_listen(p_cb, (tBTA_GATTS_DATA *) p_msg);
|
||||
break;
|
||||
|
||||
|
||||
case BTA_GATTS_API_ADD_INCL_SRVC_EVT:
|
||||
case BTA_GATTS_API_ADD_CHAR_EVT:
|
||||
case BTA_GATTS_API_ADD_DESCR_EVT:
|
||||
case BTA_GATTS_API_DEL_SRVC_EVT:
|
||||
case BTA_GATTS_API_START_SRVC_EVT:
|
||||
case BTA_GATTS_API_STOP_SRVC_EVT:
|
||||
|
||||
p_srvc_cb = bta_gatts_find_srvc_cb_by_srvc_id(p_cb,
|
||||
((tBTA_GATTS_DATA *)p_msg)->api_add_incl_srvc.hdr.layer_specific);
|
||||
|
||||
if (p_srvc_cb != NULL) {
|
||||
bta_gatts_srvc_build_act[p_msg->event - BTA_GATTS_API_ADD_INCL_SRVC_EVT](p_srvc_cb, (tBTA_GATTS_DATA *) p_msg);
|
||||
} else {
|
||||
APPL_TRACE_ERROR("service not created");
|
||||
APPL_TRACE_ERROR("service not created\n");
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -395,7 +395,6 @@ typedef void (tBTA_GATTC_ENB_CBACK)(tBTA_GATT_STATUS status);
|
||||
/* Client callback function */
|
||||
typedef void (tBTA_GATTC_CBACK)(tBTA_GATTC_EVT event, tBTA_GATTC *p_data);
|
||||
|
||||
|
||||
/* GATT Server Data Structure */
|
||||
/* Server callback function events */
|
||||
#define BTA_GATTS_REG_EVT 0
|
||||
@ -419,6 +418,7 @@ typedef void (tBTA_GATTC_CBACK)(tBTA_GATTC_EVT event, tBTA_GATTC *p_data);
|
||||
#define BTA_GATTS_CLOSE_EVT 18
|
||||
#define BTA_GATTS_LISTEN_EVT 19
|
||||
#define BTA_GATTS_CONGEST_EVT 20
|
||||
#define BTA_GATTS_SET_ATTR_VAL_EVT 21
|
||||
|
||||
typedef UINT8 tBTA_GATTS_EVT;
|
||||
typedef tGATT_IF tBTA_GATTS_IF;
|
||||
@ -434,6 +434,8 @@ typedef tGATT_IF tBTA_GATTS_IF;
|
||||
#define BTA_GATT_PERM_WRITE_SIGNED GATT_PERM_WRITE_SIGNED /* bit 7 - 0x0080 */
|
||||
#define BTA_GATT_PERM_WRITE_SIGNED_MITM GATT_PERM_WRITE_SIGNED_MITM /* bit 8 - 0x0100 */
|
||||
typedef UINT16 tBTA_GATT_PERM;
|
||||
typedef tGATT_ATTR_VAL tBTA_GATT_ATTR_VAL;
|
||||
typedef tGATTS_ATTR_CONTROL tBTA_GATTS_ATTR_CONTROL;
|
||||
|
||||
#define BTA_GATTS_INVALID_APP 0xff
|
||||
|
||||
@ -539,6 +541,13 @@ typedef struct {
|
||||
// btla-specific --
|
||||
} tBTA_GATTS_ADD_RESULT;
|
||||
|
||||
typedef struct{
|
||||
tBTA_GATTS_IF server_if;
|
||||
UINT16 service_id;
|
||||
UINT16 attr_id;
|
||||
tBTA_GATT_STATUS status;
|
||||
}tBAT_GATTS_ATTR_VAL_RESULT;
|
||||
|
||||
typedef struct {
|
||||
tBTA_GATTS_IF server_if;
|
||||
UINT16 service_id;
|
||||
@ -573,6 +582,7 @@ typedef union {
|
||||
tBTA_GATTS_ADD_RESULT add_result; /* add included service: BTA_GATTS_ADD_INCL_SRVC_EVT
|
||||
add char : BTA_GATTS_ADD_CHAR_EVT
|
||||
add char descriptor: BTA_GATTS_ADD_CHAR_DESCR_EVT */
|
||||
tBAT_GATTS_ATTR_VAL_RESULT attr_val;
|
||||
tBTA_GATTS_REQ req_data;
|
||||
tBTA_GATTS_CONN conn; /* BTA_GATTS_CONN_EVT */
|
||||
tBTA_GATTS_CONGEST congest; /* BTA_GATTS_CONGEST_EVT callback data */
|
||||
@ -1194,7 +1204,8 @@ extern void BTA_GATTS_AddIncludeService(UINT16 service_id, UINT16 included_servi
|
||||
**
|
||||
*******************************************************************************/
|
||||
extern void BTA_GATTS_AddCharacteristic (UINT16 service_id, tBT_UUID *p_char_uuid,
|
||||
tBTA_GATT_PERM perm, tBTA_GATT_CHAR_PROP property);
|
||||
tBTA_GATT_PERM perm, tBTA_GATT_CHAR_PROP property, tGATT_ATTR_VAL *attr_val,
|
||||
tBTA_GATTS_ATTR_CONTROL *control);
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
@ -1215,7 +1226,8 @@ extern void BTA_GATTS_AddCharacteristic (UINT16 service_id, tBT_UUID *p_char_
|
||||
*******************************************************************************/
|
||||
extern void BTA_GATTS_AddCharDescriptor (UINT16 service_id,
|
||||
tBTA_GATT_PERM perm,
|
||||
tBT_UUID *p_descr_uuid);
|
||||
tBT_UUID *p_descr_uuid, tBTA_GATT_ATTR_VAL *attr_val,
|
||||
tBTA_GATTS_ATTR_CONTROL *control);
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
@ -1296,6 +1308,38 @@ extern void BTA_GATTS_SendRsp (UINT16 conn_id, UINT32 trans_id,
|
||||
tBTA_GATT_STATUS status, tBTA_GATTS_RSP *p_msg);
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function BTA_SetAttributeValue
|
||||
**
|
||||
** Description This function is called to set the attribute value in the gatt database
|
||||
**
|
||||
** Parameters attr_handle - the attribute value handle.
|
||||
** length - the value length which has been set to the attribute.
|
||||
** value - the pointer to the value
|
||||
**
|
||||
** Returns None
|
||||
**
|
||||
*******************************************************************************/
|
||||
extern void BTA_SetAttributeValue(UINT16 attr_handle, UINT16 length, UINT8 *value);
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function BTA_GetAttributeValue
|
||||
**
|
||||
** Description This function is called to get the attribute value in the gatt database
|
||||
**
|
||||
** Parameters attr_handle - the attribute value handle.
|
||||
** length - the value length which has been set to the attribute.
|
||||
** value - the pointer to the value
|
||||
**
|
||||
** Returns None
|
||||
**
|
||||
*******************************************************************************/
|
||||
extern void BTA_GetAttributeValue(UINT16 attr_handle, UINT16 *length, UINT8 **value);
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function BTA_GATTS_Open
|
||||
|
@ -48,6 +48,7 @@ enum {
|
||||
BTA_GATTS_API_START_SRVC_EVT,
|
||||
BTA_GATTS_API_STOP_SRVC_EVT,
|
||||
BTA_GATTS_API_RSP_EVT,
|
||||
BTA_GATTS_API_SET_ATTR_VAL_EVT,
|
||||
BTA_GATTS_API_OPEN_EVT,
|
||||
BTA_GATTS_API_CANCEL_OPEN_EVT,
|
||||
BTA_GATTS_API_CLOSE_EVT,
|
||||
@ -91,19 +92,21 @@ typedef struct {
|
||||
tBT_UUID char_uuid;
|
||||
tBTA_GATT_PERM perm;
|
||||
tBTA_GATT_CHAR_PROP property;
|
||||
|
||||
tBTA_GATTS_ATTR_CONTROL control;
|
||||
tBTA_GATT_ATTR_VAL attr_val;
|
||||
} tBTA_GATTS_API_ADD_CHAR;
|
||||
|
||||
typedef struct {
|
||||
BT_HDR hdr;
|
||||
UINT16 included_service_id;
|
||||
|
||||
} tBTA_GATTS_API_ADD_INCL_SRVC;
|
||||
|
||||
typedef struct {
|
||||
BT_HDR hdr;
|
||||
tBT_UUID descr_uuid;
|
||||
tBTA_GATT_PERM perm;
|
||||
tBTA_GATTS_ATTR_CONTROL control;
|
||||
tBTA_GATT_ATTR_VAL attr_val;
|
||||
} tBTA_GATTS_API_ADD_DESCR;
|
||||
|
||||
typedef struct {
|
||||
@ -121,6 +124,12 @@ typedef struct {
|
||||
tBTA_GATTS_RSP *p_rsp;
|
||||
} tBTA_GATTS_API_RSP;
|
||||
|
||||
typedef struct{
|
||||
BT_HDR hdr;
|
||||
UINT16 length;
|
||||
UINT8 *value;
|
||||
}tBTA_GATTS_API_SET_ATTR_VAL;
|
||||
|
||||
typedef struct {
|
||||
BT_HDR hdr;
|
||||
tBTA_GATT_TRANSPORT transport;
|
||||
@ -156,6 +165,7 @@ typedef union {
|
||||
tBTA_GATTS_API_START api_start;
|
||||
tBTA_GATTS_API_INDICATION api_indicate;
|
||||
tBTA_GATTS_API_RSP api_rsp;
|
||||
tBTA_GATTS_API_SET_ATTR_VAL api_set_val;
|
||||
tBTA_GATTS_API_OPEN api_open;
|
||||
tBTA_GATTS_API_CANCEL_OPEN api_cancel_open;
|
||||
|
||||
@ -219,6 +229,8 @@ extern void bta_gatts_create_srvc(tBTA_GATTS_CB *p_cb, tBTA_GATTS_DATA *p_msg);
|
||||
extern void bta_gatts_add_include_srvc(tBTA_GATTS_SRVC_CB *p_srvc_cb, tBTA_GATTS_DATA *p_msg);
|
||||
extern void bta_gatts_add_char(tBTA_GATTS_SRVC_CB *p_srvc_cb, tBTA_GATTS_DATA *p_msg);
|
||||
extern void bta_gatts_add_char_descr(tBTA_GATTS_SRVC_CB *p_srvc_cb, tBTA_GATTS_DATA *p_msg);
|
||||
extern void bta_gatts_set_attr_value(tBTA_GATTS_SRVC_CB *p_srvc_cb, tBTA_GATTS_DATA *p_msg);
|
||||
extern void bta_gatts_get_attr_value(UINT16 attr_handle, UINT16 *length, UINT8 **value);
|
||||
extern void bta_gatts_delete_service(tBTA_GATTS_SRVC_CB *p_srvc_cb, tBTA_GATTS_DATA *p_msg);
|
||||
extern void bta_gatts_start_service(tBTA_GATTS_SRVC_CB *p_srvc_cb, tBTA_GATTS_DATA *p_msg);
|
||||
extern void bta_gatts_stop_service(tBTA_GATTS_SRVC_CB *p_srvc_cb, tBTA_GATTS_DATA *p_msg);
|
||||
|
@ -42,14 +42,14 @@ static void btc_sec_callback(tBTA_DM_SEC_EVT event, tBTA_DM_SEC *p_data)
|
||||
static void btc_enable_bluetooth(void)
|
||||
{
|
||||
if (BTA_EnableBluetooth(btc_sec_callback) != BTA_SUCCESS) {
|
||||
future_ready(*btc_main_get_future_p(BTC_MAIN_ENABLE_FUTURE), FUTURE_SUCCESS);
|
||||
future_ready(*btc_main_get_future_p(BTC_MAIN_ENABLE_FUTURE), FUTURE_FAIL);
|
||||
}
|
||||
}
|
||||
|
||||
static void btc_disable_bluetooth(void)
|
||||
{
|
||||
if (BTA_DisableBluetooth() != BTA_SUCCESS) {
|
||||
future_ready(*btc_main_get_future_p(BTC_MAIN_DISABLE_FUTURE), FUTURE_SUCCESS);
|
||||
future_ready(*btc_main_get_future_p(BTC_MAIN_DISABLE_FUTURE), FUTURE_FAIL);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -20,7 +20,7 @@
|
||||
#include "esp_bt_defs.h"
|
||||
#include "esp_gatt_defs.h"
|
||||
|
||||
static esp_profile_cb_t btc_profile_cb_tab[BTC_PID_NUM] = {};
|
||||
static void *btc_profile_cb_tab[BTC_PID_NUM] = {};
|
||||
|
||||
void esp_profile_cb_reset(void)
|
||||
{
|
||||
@ -31,7 +31,7 @@ void esp_profile_cb_reset(void)
|
||||
}
|
||||
}
|
||||
|
||||
int btc_profile_cb_set(btc_pid_t profile_id, esp_profile_cb_t cb)
|
||||
int btc_profile_cb_set(btc_pid_t profile_id, void *cb)
|
||||
{
|
||||
if (profile_id < 0 || profile_id >= BTC_PID_NUM) {
|
||||
return -1;
|
||||
@ -42,7 +42,7 @@ int btc_profile_cb_set(btc_pid_t profile_id, esp_profile_cb_t cb)
|
||||
return 0;
|
||||
}
|
||||
|
||||
esp_profile_cb_t btc_profile_cb_get(btc_pid_t profile_id)
|
||||
void *btc_profile_cb_get(btc_pid_t profile_id)
|
||||
{
|
||||
if (profile_id < 0 || profile_id >= BTC_PID_NUM) {
|
||||
return NULL;
|
||||
|
@ -80,7 +80,7 @@ static bt_status_t btc_task_post(btc_msg_t *msg)
|
||||
return BT_STATUS_PARM_INVALID;
|
||||
}
|
||||
|
||||
if (xQueueSend(xBtcQueue, msg, 10 / portTICK_RATE_MS) != pdTRUE) {
|
||||
if (xQueueSend(xBtcQueue, msg, 10 / portTICK_PERIOD_MS) != pdTRUE) {
|
||||
LOG_ERROR("Btc Post failed\n");
|
||||
return BT_STATUS_BUSY;
|
||||
}
|
||||
@ -120,7 +120,7 @@ bt_status_t btc_transfer_context(btc_msg_t *msg, void *arg, int arg_len, btc_arg
|
||||
int btc_init(void)
|
||||
{
|
||||
xBtcQueue = xQueueCreate(BTC_TASK_QUEUE_NUM, sizeof(btc_msg_t));
|
||||
xTaskCreate(btc_task, "Btc_task", BTC_TASK_STACK_SIZE, NULL, BTC_TASK_PRIO, &xBtcTaskHandle);
|
||||
xTaskCreatePinnedToCore(btc_task, "Btc_task", BTC_TASK_STACK_SIZE, NULL, BTC_TASK_PRIO, &xBtcTaskHandle, 0);
|
||||
|
||||
/* TODO: initial the profile_tab */
|
||||
|
||||
|
@ -22,7 +22,7 @@
|
||||
/* reset gatt callback table */
|
||||
void esp_profile_cb_reset(void);
|
||||
|
||||
int btc_profile_cb_set(btc_pid_t profile_id, esp_profile_cb_t cb);
|
||||
esp_profile_cb_t btc_profile_cb_get(btc_pid_t profile_id);
|
||||
int btc_profile_cb_set(btc_pid_t profile_id, void *cb);
|
||||
void *btc_profile_cb_get(btc_pid_t profile_id);
|
||||
|
||||
#endif /* __BTC_MANAGE_H__ */
|
||||
|
@ -1,164 +0,0 @@
|
||||
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// 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.
|
||||
|
||||
#include "blufi_adv.h"
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function BlufiConfigadvData
|
||||
**
|
||||
** Description This function is called to override the BTA default ADV parameters.
|
||||
**
|
||||
** adv_data: Pointer to User defined ADV data structure. This
|
||||
** memory space can not be freed until p_adv_data_cback
|
||||
** is received.
|
||||
** p_adv_data_cback: set adv data complete callback.
|
||||
**
|
||||
** Returns None
|
||||
**
|
||||
*******************************************************************************/
|
||||
void BlufiBleConfigadvData(tBLUFI_BLE_ADV_DATA *adv_data,
|
||||
tBTA_SET_ADV_DATA_CMPL_CBACK *p_adv_data_cback)
|
||||
{
|
||||
tBTA_BLE_AD_MASK data_mask = 0;
|
||||
if (adv_data->adv_name != NULL) {
|
||||
data_mask |= BTM_BLE_AD_BIT_DEV_NAME;
|
||||
BTA_DmSetDeviceName(adv_data->adv_name);
|
||||
}
|
||||
if (adv_data->ble_adv_data.int_range.low != 0 ||
|
||||
adv_data->ble_adv_data.int_range.hi != 0) {
|
||||
data_mask |= BTM_BLE_AD_BIT_INT_RANGE;
|
||||
}
|
||||
|
||||
if (adv_data->ble_adv_data.p_manu != NULL) {
|
||||
data_mask |= BTM_BLE_AD_BIT_MANU;
|
||||
}
|
||||
|
||||
if (adv_data->ble_adv_data.p_services != NULL) {
|
||||
data_mask |= BTM_BLE_AD_BIT_SERVICE;
|
||||
}
|
||||
|
||||
if (adv_data->ble_adv_data.p_service_32b != NULL) {
|
||||
data_mask |= BTM_BLE_AD_BIT_SERVICE_32;
|
||||
}
|
||||
|
||||
if (adv_data->ble_adv_data.p_services_128b != NULL) {
|
||||
data_mask |= BTM_BLE_AD_BIT_SERVICE_128;
|
||||
}
|
||||
|
||||
if (adv_data->ble_adv_data.p_sol_services != NULL) {
|
||||
data_mask |= BTM_BLE_AD_BIT_SERVICE_SOL;
|
||||
}
|
||||
|
||||
if (adv_data->ble_adv_data.p_sol_service_32b != NULL) {
|
||||
data_mask |= BTM_BLE_AD_BIT_SERVICE_32SOL;
|
||||
}
|
||||
|
||||
if (adv_data->ble_adv_data.p_sol_service_128b != NULL) {
|
||||
data_mask |= BTM_BLE_AD_BIT_SERVICE_128SOL;
|
||||
}
|
||||
|
||||
if (adv_data->ble_adv_data.p_service_data != NULL) {
|
||||
data_mask |= BTM_BLE_AD_BIT_SERVICE_DATA;
|
||||
}
|
||||
|
||||
if (adv_data->ble_adv_data.appearance != 0) {
|
||||
data_mask |= BTM_BLE_AD_BIT_APPEARANCE;
|
||||
}
|
||||
|
||||
if (adv_data->ble_adv_data.p_proprietary != NULL) {
|
||||
data_mask |= BTM_BLE_AD_BIT_PROPRIETARY;
|
||||
}
|
||||
|
||||
if (adv_data->ble_adv_data.tx_power != 0) {
|
||||
data_mask |= BTM_BLE_AD_BIT_TX_PWR;
|
||||
}
|
||||
|
||||
BTA_DmBleSetAdvConfig(data_mask, &(adv_data->ble_adv_data), p_adv_data_cback);
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function BLUFI_BleSetScanRsp
|
||||
**
|
||||
** Description This function is called to override the app scan response.
|
||||
**
|
||||
** Parameters Pointer to User defined ADV data structure
|
||||
**
|
||||
** Returns None
|
||||
**
|
||||
*******************************************************************************/
|
||||
void BlufiBleSetScanRsp(tBLUFI_BLE_ADV_DATA *scan_rsp_data,
|
||||
tBTA_SET_ADV_DATA_CMPL_CBACK *p_scan_rsp_data_cback)
|
||||
{
|
||||
tBTA_BLE_AD_MASK data_mask = 0;
|
||||
if (scan_rsp_data->adv_name != NULL) {
|
||||
data_mask |= BTM_BLE_AD_BIT_DEV_NAME;
|
||||
BTA_DmSetDeviceName(scan_rsp_data->adv_name);
|
||||
}
|
||||
if (scan_rsp_data->ble_adv_data.int_range.low != 0 ||
|
||||
scan_rsp_data->ble_adv_data.int_range.hi != 0) {
|
||||
data_mask |= BTM_BLE_AD_BIT_INT_RANGE;
|
||||
}
|
||||
|
||||
if (scan_rsp_data->ble_adv_data.p_manu != NULL) {
|
||||
data_mask |= BTM_BLE_AD_BIT_MANU;
|
||||
}
|
||||
|
||||
if (scan_rsp_data->ble_adv_data.p_services != NULL) {
|
||||
data_mask |= BTM_BLE_AD_BIT_SERVICE;
|
||||
}
|
||||
|
||||
if (scan_rsp_data->ble_adv_data.p_service_32b != NULL) {
|
||||
data_mask |= BTM_BLE_AD_BIT_SERVICE_32;
|
||||
}
|
||||
|
||||
if (scan_rsp_data->ble_adv_data.p_services_128b != NULL) {
|
||||
data_mask |= BTM_BLE_AD_BIT_SERVICE_128;
|
||||
}
|
||||
|
||||
if (scan_rsp_data->ble_adv_data.p_sol_services != NULL) {
|
||||
data_mask |= BTM_BLE_AD_BIT_SERVICE_SOL;
|
||||
}
|
||||
|
||||
if (scan_rsp_data->ble_adv_data.p_sol_service_32b != NULL) {
|
||||
data_mask |= BTM_BLE_AD_BIT_SERVICE_32SOL;
|
||||
}
|
||||
|
||||
if (scan_rsp_data->ble_adv_data.p_sol_service_128b != NULL) {
|
||||
data_mask |= BTM_BLE_AD_BIT_SERVICE_128SOL;
|
||||
}
|
||||
|
||||
if (scan_rsp_data->ble_adv_data.p_service_data != NULL) {
|
||||
data_mask |= BTM_BLE_AD_BIT_SERVICE_DATA;
|
||||
}
|
||||
|
||||
if (scan_rsp_data->ble_adv_data.appearance != 0) {
|
||||
data_mask |= BTM_BLE_AD_BIT_APPEARANCE;
|
||||
}
|
||||
|
||||
if (scan_rsp_data->ble_adv_data.p_proprietary != NULL) {
|
||||
data_mask |= BTM_BLE_AD_BIT_PROPRIETARY;
|
||||
}
|
||||
|
||||
if (scan_rsp_data->ble_adv_data.tx_power != 0) {
|
||||
data_mask |= BTM_BLE_AD_BIT_TX_PWR;
|
||||
}
|
||||
|
||||
BTA_DmBleSetScanRsp(data_mask, &(scan_rsp_data->ble_adv_data), p_scan_rsp_data_cback);
|
||||
}
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
249
components/bt/bluedroid/btc/profile/esp/blufi/blufi_protocol.c
Normal file
249
components/bt/bluedroid/btc/profile/esp/blufi/blufi_protocol.c
Normal file
@ -0,0 +1,249 @@
|
||||
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// 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.
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
#include "bt_target.h"
|
||||
#include "bt_trace.h"
|
||||
#include "bt_types.h"
|
||||
#include "gatt_api.h"
|
||||
#include "bta_api.h"
|
||||
#include "bta_gatt_api.h"
|
||||
#include "bta_gatts_int.h"
|
||||
|
||||
#include "btc_blufi_prf.h"
|
||||
#include "btc_task.h"
|
||||
#include "btc_manage.h"
|
||||
|
||||
#include "blufi_int.h"
|
||||
|
||||
#include "esp_wifi.h"
|
||||
|
||||
extern tBLUFI_ENV blufi_env;
|
||||
|
||||
void btc_blufi_protocol_handler(uint8_t type, uint8_t *data, int len)
|
||||
{
|
||||
btc_msg_t msg;
|
||||
esp_blufi_cb_param_t param;
|
||||
uint8_t *output_data = NULL;
|
||||
int output_len = 0;
|
||||
bool need_free = false;
|
||||
|
||||
switch (BLUFI_GET_TYPE(type)) {
|
||||
case BLUFI_TYPE_CTRL:
|
||||
switch (BLUFI_GET_SUBTYPE(type)) {
|
||||
case BLUFI_TYPE_CTRL_SUBTYPE_ACK:
|
||||
/* TODO: check sequence */
|
||||
break;
|
||||
case BLUFI_TYPE_CTRL_SUBTYPE_SET_SEC_MODE:
|
||||
blufi_env.sec_mode = data[0];
|
||||
break;
|
||||
case BLUFI_TYPE_CTRL_SUBTYPE_SET_WIFI_OPMODE:
|
||||
msg.sig = BTC_SIG_API_CB;
|
||||
msg.pid = BTC_PID_BLUFI;
|
||||
msg.act = ESP_BLUFI_EVENT_SET_WIFI_OPMODE;
|
||||
param.wifi_mode.op_mode = data[0];
|
||||
|
||||
btc_transfer_context(&msg, ¶m, sizeof(esp_blufi_cb_param_t), NULL);
|
||||
break;
|
||||
case BLUFI_TYPE_CTRL_SUBTYPE_CONN_TO_AP:
|
||||
msg.sig = BTC_SIG_API_CB;
|
||||
msg.pid = BTC_PID_BLUFI;
|
||||
msg.act = ESP_BLUFI_EVENT_REQ_CONNECT_TO_AP;
|
||||
|
||||
btc_transfer_context(&msg, NULL, 0, NULL);
|
||||
break;
|
||||
case BLUFI_TYPE_CTRL_SUBTYPE_DISCONN_FROM_AP:
|
||||
msg.sig = BTC_SIG_API_CB;
|
||||
msg.pid = BTC_PID_BLUFI;
|
||||
msg.act = ESP_BLUFI_EVENT_REQ_DISCONNECT_FROM_AP;
|
||||
|
||||
btc_transfer_context(&msg, NULL, 0, NULL);
|
||||
break;
|
||||
case BLUFI_TYPE_CTRL_SUBTYPE_GET_WIFI_STATUS:
|
||||
msg.sig = BTC_SIG_API_CB;
|
||||
msg.pid = BTC_PID_BLUFI;
|
||||
msg.act = ESP_BLUFI_EVENT_GET_WIFI_STATUS;
|
||||
|
||||
btc_transfer_context(&msg, NULL, 0, NULL);
|
||||
break;
|
||||
case BLUFI_TYPE_CTRL_SUBTYPE_DEAUTHENTICATE_STA:
|
||||
msg.sig = BTC_SIG_API_CB;
|
||||
msg.pid = BTC_PID_BLUFI;
|
||||
msg.act = ESP_BLUFI_EVENT_DEAUTHENTICATE_STA;
|
||||
|
||||
btc_transfer_context(&msg, NULL, 0, NULL);
|
||||
break;
|
||||
case BLUFI_TYPE_CTRL_SUBTYPE_GET_VERSION: {
|
||||
uint8_t type = BLUFI_BUILD_TYPE(BLUFI_TYPE_DATA, BLUFI_TYPE_DATA_SUBTYPE_REPLY_VERSION);
|
||||
uint8_t data[2];
|
||||
|
||||
data[0] = BTC_BLUFI_GREAT_VER;
|
||||
data[1] = BTC_BLUFI_SUB_VER;
|
||||
btc_blufi_send_encap(type, &data[0], sizeof(data));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
LOG_ERROR("%s Unkown Ctrl pkt %02x\n", __func__, type);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case BLUFI_TYPE_DATA:
|
||||
switch (BLUFI_GET_SUBTYPE(type)) {
|
||||
case BLUFI_TYPE_DATA_SUBTYPE_NEG:
|
||||
if (blufi_env.cbs && blufi_env.cbs->negotiate_data_handler) {
|
||||
blufi_env.cbs->negotiate_data_handler(data, len, &output_data, &output_len, &need_free);
|
||||
}
|
||||
|
||||
if (output_data && output_len > 0) {
|
||||
btc_blufi_send_encap(BLUFI_BUILD_TYPE(BLUFI_TYPE_DATA, BLUFI_TYPE_DATA_SUBTYPE_NEG),
|
||||
output_data, output_len);
|
||||
}
|
||||
break;
|
||||
case BLUFI_TYPE_DATA_SUBTYPE_STA_BSSID:
|
||||
msg.sig = BTC_SIG_API_CB;
|
||||
msg.pid = BTC_PID_BLUFI;
|
||||
msg.act = ESP_BLUFI_EVENT_RECV_STA_BSSID;
|
||||
memcpy(param.sta_bssid.bssid, &data[0], 6);
|
||||
|
||||
btc_transfer_context(&msg, ¶m, sizeof(esp_blufi_cb_param_t), NULL);
|
||||
break;
|
||||
case BLUFI_TYPE_DATA_SUBTYPE_STA_SSID:
|
||||
msg.sig = BTC_SIG_API_CB;
|
||||
msg.pid = BTC_PID_BLUFI;
|
||||
msg.act = ESP_BLUFI_EVENT_RECV_STA_SSID;
|
||||
param.sta_ssid.ssid = &data[0];
|
||||
param.sta_ssid.ssid_len = len;
|
||||
|
||||
btc_transfer_context(&msg, ¶m, sizeof(esp_blufi_cb_param_t), btc_blufi_cb_deep_copy);
|
||||
break;
|
||||
case BLUFI_TYPE_DATA_SUBTYPE_STA_PASSWD:
|
||||
msg.sig = BTC_SIG_API_CB;
|
||||
msg.pid = BTC_PID_BLUFI;
|
||||
msg.act = ESP_BLUFI_EVENT_RECV_STA_PASSWD;
|
||||
param.sta_passwd.passwd = &data[0];
|
||||
param.sta_passwd.passwd_len = len;
|
||||
|
||||
btc_transfer_context(&msg, ¶m, sizeof(esp_blufi_cb_param_t), btc_blufi_cb_deep_copy);
|
||||
break;
|
||||
case BLUFI_TYPE_DATA_SUBTYPE_SOFTAP_SSID:
|
||||
msg.sig = BTC_SIG_API_CB;
|
||||
msg.pid = BTC_PID_BLUFI;
|
||||
msg.act = ESP_BLUFI_EVENT_RECV_SOFTAP_SSID;
|
||||
param.softap_ssid.ssid = &data[0];
|
||||
param.softap_ssid.ssid_len = len;
|
||||
|
||||
btc_transfer_context(&msg, ¶m, sizeof(esp_blufi_cb_param_t), btc_blufi_cb_deep_copy);
|
||||
break;
|
||||
case BLUFI_TYPE_DATA_SUBTYPE_SOFTAP_PASSWD:
|
||||
msg.sig = BTC_SIG_API_CB;
|
||||
msg.pid = BTC_PID_BLUFI;
|
||||
msg.act = ESP_BLUFI_EVENT_RECV_SOFTAP_PASSWD;
|
||||
param.softap_passwd.passwd = &data[0];
|
||||
param.softap_passwd.passwd_len = len;
|
||||
|
||||
btc_transfer_context(&msg, ¶m, sizeof(esp_blufi_cb_param_t), btc_blufi_cb_deep_copy);
|
||||
break;
|
||||
case BLUFI_TYPE_DATA_SUBTYPE_SOFTAP_MAX_CONN_NUM:
|
||||
msg.sig = BTC_SIG_API_CB;
|
||||
msg.pid = BTC_PID_BLUFI;
|
||||
msg.act = ESP_BLUFI_EVENT_RECV_SOFTAP_MAX_CONN_NUM;
|
||||
param.softap_max_conn_num.max_conn_num = data[0];
|
||||
|
||||
btc_transfer_context(&msg, ¶m, sizeof(esp_blufi_cb_param_t), NULL);
|
||||
break;
|
||||
case BLUFI_TYPE_DATA_SUBTYPE_SOFTAP_AUTH_MODE:
|
||||
msg.sig = BTC_SIG_API_CB;
|
||||
msg.pid = BTC_PID_BLUFI;
|
||||
msg.act = ESP_BLUFI_EVENT_RECV_SOFTAP_AUTH_MODE;
|
||||
param.softap_auth_mode.auth_mode = data[0];
|
||||
|
||||
btc_transfer_context(&msg, ¶m, sizeof(esp_blufi_cb_param_t), NULL);
|
||||
break;
|
||||
case BLUFI_TYPE_DATA_SUBTYPE_SOFTAP_CHANNEL:
|
||||
msg.sig = BTC_SIG_API_CB;
|
||||
msg.pid = BTC_PID_BLUFI;
|
||||
msg.act = ESP_BLUFI_EVENT_RECV_SOFTAP_CHANNEL;
|
||||
param.softap_channel.channel = data[0];
|
||||
|
||||
btc_transfer_context(&msg, ¶m, sizeof(esp_blufi_cb_param_t), NULL);
|
||||
break;
|
||||
case BLUFI_TYPE_DATA_SUBTYPE_USERNAME:
|
||||
msg.sig = BTC_SIG_API_CB;
|
||||
msg.pid = BTC_PID_BLUFI;
|
||||
msg.act = ESP_BLUFI_EVENT_RECV_USERNAME;
|
||||
param.username.name = &data[0];
|
||||
param.username.name_len = len;
|
||||
|
||||
btc_transfer_context(&msg, ¶m, sizeof(esp_blufi_cb_param_t), btc_blufi_cb_deep_copy);
|
||||
break;
|
||||
case BLUFI_TYPE_DATA_SUBTYPE_CA:
|
||||
msg.sig = BTC_SIG_API_CB;
|
||||
msg.pid = BTC_PID_BLUFI;
|
||||
msg.act = ESP_BLUFI_EVENT_RECV_CA_CERT;
|
||||
param.ca.cert = &data[0];
|
||||
param.ca.cert_len = len;
|
||||
|
||||
btc_transfer_context(&msg, ¶m, sizeof(esp_blufi_cb_param_t), btc_blufi_cb_deep_copy);
|
||||
break;
|
||||
case BLUFI_TYPE_DATA_SUBTYPE_CLIENT_CERT:
|
||||
msg.sig = BTC_SIG_API_CB;
|
||||
msg.pid = BTC_PID_BLUFI;
|
||||
msg.act = ESP_BLUFI_EVENT_RECV_CLIENT_CERT;
|
||||
param.client_cert.cert = &data[0];
|
||||
param.client_cert.cert_len = len;
|
||||
|
||||
btc_transfer_context(&msg, ¶m, sizeof(esp_blufi_cb_param_t), btc_blufi_cb_deep_copy);
|
||||
break;
|
||||
case BLUFI_TYPE_DATA_SUBTYPE_SERVER_CERT:
|
||||
msg.sig = BTC_SIG_API_CB;
|
||||
msg.pid = BTC_PID_BLUFI;
|
||||
msg.act = ESP_BLUFI_EVENT_RECV_SERVER_CERT;
|
||||
param.client_cert.cert = &data[0];
|
||||
param.client_cert.cert_len = len;
|
||||
|
||||
btc_transfer_context(&msg, ¶m, sizeof(esp_blufi_cb_param_t), btc_blufi_cb_deep_copy);
|
||||
break;
|
||||
case BLUFI_TYPE_DATA_SUBTYPE_CLIENT_PRIV_KEY:
|
||||
msg.sig = BTC_SIG_API_CB;
|
||||
msg.pid = BTC_PID_BLUFI;
|
||||
msg.act = ESP_BLUFI_EVENT_RECV_CLIENT_PRIV_KEY;
|
||||
param.client_pkey.pkey = &data[0];
|
||||
param.client_pkey.pkey_len = len;
|
||||
|
||||
btc_transfer_context(&msg, ¶m, sizeof(esp_blufi_cb_param_t), btc_blufi_cb_deep_copy);
|
||||
break;
|
||||
case BLUFI_TYPE_DATA_SUBTYPE_SERVER_PRIV_KEY:
|
||||
msg.sig = BTC_SIG_API_CB;
|
||||
msg.pid = BTC_PID_BLUFI;
|
||||
msg.act = ESP_BLUFI_EVENT_RECV_SERVER_PRIV_KEY;
|
||||
param.client_pkey.pkey = &data[0];
|
||||
param.client_pkey.pkey_len = len;
|
||||
|
||||
btc_transfer_context(&msg, ¶m, sizeof(esp_blufi_cb_param_t), btc_blufi_cb_deep_copy);
|
||||
break;
|
||||
default:
|
||||
LOG_ERROR("%s Unkown Ctrl pkt %02x\n", __func__, type);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
@ -1,39 +0,0 @@
|
||||
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// 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 __BLUFI_ADV_H__
|
||||
#define __BLUFI_ADV_H__
|
||||
|
||||
#include "bta_api.h"
|
||||
#include "btm_ble_api.h"
|
||||
#include "esp_bt_defs.h"
|
||||
|
||||
typedef enum {
|
||||
BLE_ADV_DATA_IDX = 0,
|
||||
BLE_SCAN_RSP_DATA_IDX = 1,
|
||||
ADV_SCAN_IDX_MAX,
|
||||
} ADV_SCAN_IDX_t;
|
||||
|
||||
typedef struct {
|
||||
char *adv_name; //set the device name to be sent on the advertising
|
||||
tBTA_BLE_ADV_DATA ble_adv_data;
|
||||
} tBLUFI_BLE_ADV_DATA;
|
||||
|
||||
extern void BlufiBleConfigadvData(tBLUFI_BLE_ADV_DATA *adv_data,
|
||||
tBTA_SET_ADV_DATA_CMPL_CBACK *p_adv_data_cback);
|
||||
|
||||
extern void BlufiBleSetScanRsp(tBLUFI_BLE_ADV_DATA *scan_rsp_data,
|
||||
tBTA_SET_ADV_DATA_CMPL_CBACK *p_scan_rsp_data_cback);
|
||||
|
||||
#endif /* __BLUFI_ADV_H__ */
|
@ -15,38 +15,162 @@
|
||||
#ifndef __BLUFI_INT_H__
|
||||
#define __BLUFI_INT_H__
|
||||
|
||||
//define the blufi serivce uuid
|
||||
#define SVC_BLUFI_UUID 0xFFFF
|
||||
//define the blufi Char uuid
|
||||
#define CHAR_BLUFI_UUID 0xFF01
|
||||
|
||||
#define BLUFI_HDL_NUM 4
|
||||
|
||||
#define BLUFI_VAL_MAX_LEN (128)
|
||||
|
||||
#define BLUFI_MAX_STRING_DATA 128
|
||||
|
||||
|
||||
typedef struct {
|
||||
UINT8 app_id;
|
||||
UINT16 blufi_hdl;
|
||||
} tBLUFI_INST;
|
||||
|
||||
#define BTC_BLUFI_GREAT_VER 0x01 //Version + Subversion
|
||||
#define BTC_BLUFI_SUB_VER 0x00 //Version + Subversion
|
||||
#define BTC_BLUFI_VERSION ((BTC_BLUFI_GREAT_VER<<8)|BTC_BLUFI_SUB_VER) //Version + Subversion
|
||||
|
||||
/* service engine control block */
|
||||
typedef struct {
|
||||
BOOLEAN enabled;
|
||||
BOOLEAN is_primery;
|
||||
UINT8 inst_id;
|
||||
/* Protocol reference */
|
||||
tGATT_IF gatt_if;
|
||||
tBLUFI_INST blufi_inst;
|
||||
BOOLEAN in_use;
|
||||
BOOLEAN congest;
|
||||
UINT8 srvc_inst;
|
||||
UINT16 handle_srvc;
|
||||
UINT16 handle_char_p2e;
|
||||
UINT16 handle_char_e2p;
|
||||
UINT16 handle_descr_e2p;
|
||||
UINT16 conn_id;
|
||||
BOOLEAN connected;
|
||||
BOOLEAN is_connected;
|
||||
BD_ADDR remote_bda;
|
||||
UINT32 trans_id;
|
||||
UINT8 cur_srvc_id;
|
||||
} tBLUFI_CB_ENV;
|
||||
UINT8 congest;
|
||||
#define BLUFI_PREPAIR_BUF_MAX_SIZE 1024
|
||||
uint8_t *prepare_buf;
|
||||
int prepare_len;
|
||||
/* Control reference */
|
||||
esp_blufi_callbacks_t *cbs;
|
||||
BOOLEAN enabled;
|
||||
uint8_t send_seq;
|
||||
uint8_t recv_seq;
|
||||
uint8_t sec_mode;
|
||||
uint8_t *aggr_buf;
|
||||
uint16_t total_len;
|
||||
uint16_t offset;
|
||||
} tBLUFI_ENV;
|
||||
|
||||
/* BLUFI protocol */
|
||||
struct blufi_hdr{
|
||||
uint8_t type;
|
||||
uint8_t fc;
|
||||
uint8_t seq;
|
||||
uint8_t data_len;
|
||||
uint8_t data[0];
|
||||
};
|
||||
typedef struct blufi_hdr blufi_hd_t;
|
||||
|
||||
struct blufi_frag_hdr {
|
||||
uint8_t type;
|
||||
uint8_t fc;
|
||||
uint8_t seq;
|
||||
uint8_t data_len;
|
||||
uint16_t total_len;
|
||||
uint8_t content[0];
|
||||
};
|
||||
typedef struct blufi_frag_hdr blufi_frag_hdr_t;
|
||||
|
||||
#define BLUFI_DATA_SEC_MODE_CHECK_MASK 0x01
|
||||
#define BLUFI_DATA_SEC_MODE_ENC_MASK 0x02
|
||||
#define BLUFI_CTRL_SEC_MODE_CHECK_MASK 0x10
|
||||
#define BLUFI_CTRL_SEC_MODE_ENC_MASK 0x20
|
||||
|
||||
// packet type
|
||||
#define BLUFI_TYPE_MASK 0x03
|
||||
#define BLUFI_TYPE_SHIFT 0
|
||||
#define BLUFI_SUBTYPE_MASK 0xFC
|
||||
#define BLUFI_SUBTYPE_SHIFT 2
|
||||
|
||||
#define BLUFI_GET_TYPE(type) ((type) & BLUFI_TYPE_MASK)
|
||||
#define BLUFI_GET_SUBTYPE(type) (((type) & BLUFI_SUBTYPE_MASK) >>BLUFI_SUBTYPE_SHIFT)
|
||||
#define BLUFI_BUILD_TYPE(type, subtype) (((type) & BLUFI_TYPE_MASK) | ((subtype)<<BLUFI_SUBTYPE_SHIFT))
|
||||
|
||||
#define BLUFI_TYPE_CTRL 0x0
|
||||
#define BLUFI_TYPE_CTRL_SUBTYPE_ACK 0x00
|
||||
#define BLUFI_TYPE_CTRL_SUBTYPE_SET_SEC_MODE 0x01
|
||||
#define BLUFI_TYPE_CTRL_SUBTYPE_SET_WIFI_OPMODE 0x02
|
||||
#define BLUFI_TYPE_CTRL_SUBTYPE_CONN_TO_AP 0x03
|
||||
#define BLUFI_TYPE_CTRL_SUBTYPE_DISCONN_FROM_AP 0x04
|
||||
#define BLUFI_TYPE_CTRL_SUBTYPE_GET_WIFI_STATUS 0x05
|
||||
#define BLUFI_TYPE_CTRL_SUBTYPE_DEAUTHENTICATE_STA 0x06
|
||||
#define BLUFI_TYPE_CTRL_SUBTYPE_GET_VERSION 0x07
|
||||
|
||||
#define BLUFI_TYPE_DATA 0x1
|
||||
#define BLUFI_TYPE_DATA_SUBTYPE_NEG 0x00
|
||||
#define BLUFI_TYPE_DATA_SUBTYPE_STA_BSSID 0x01
|
||||
#define BLUFI_TYPE_DATA_SUBTYPE_STA_SSID 0x02
|
||||
#define BLUFI_TYPE_DATA_SUBTYPE_STA_PASSWD 0x03
|
||||
#define BLUFI_TYPE_DATA_SUBTYPE_SOFTAP_SSID 0x04
|
||||
#define BLUFI_TYPE_DATA_SUBTYPE_SOFTAP_PASSWD 0x05
|
||||
#define BLUFI_TYPE_DATA_SUBTYPE_SOFTAP_MAX_CONN_NUM 0x06
|
||||
#define BLUFI_TYPE_DATA_SUBTYPE_SOFTAP_AUTH_MODE 0x07
|
||||
#define BLUFI_TYPE_DATA_SUBTYPE_SOFTAP_CHANNEL 0x08
|
||||
#define BLUFI_TYPE_DATA_SUBTYPE_USERNAME 0x09
|
||||
#define BLUFI_TYPE_DATA_SUBTYPE_CA 0x0a
|
||||
#define BLUFI_TYPE_DATA_SUBTYPE_CLIENT_CERT 0x0b
|
||||
#define BLUFI_TYPE_DATA_SUBTYPE_SERVER_CERT 0x0c
|
||||
#define BLUFI_TYPE_DATA_SUBTYPE_CLIENT_PRIV_KEY 0x0d
|
||||
#define BLUFI_TYPE_DATA_SUBTYPE_SERVER_PRIV_KEY 0x0e
|
||||
#define BLUFI_TYPE_DATA_SUBTYPE_WIFI_REP 0x0f
|
||||
#define BLUFI_TYPE_DATA_SUBTYPE_REPLY_VERSION 0x10
|
||||
#define BLUFI_TYPE_IS_CTRL(type) (BLUFI_GET_TYPE((type)) == BLUFI_TYPE_CTRL)
|
||||
#define BLUFI_TYPE_IS_DATA(type) (BLUFI_GET_TYPE((type)) == BLUFI_TYPE_DATA)
|
||||
|
||||
#define BLUFI_TYPE_IS_CTRL_ACK(type) (BLUFI_TYPE_IS_CTRL((type)) && BLUFI_GET_SUBTYPE((type)) == BLUFI_TYPE_CTRL_SUBTYPE_ACK)
|
||||
#define BLUFI_TYPE_IS_CTRL_START_NEG(type) (BLUFI_TYPE_IS_CTRL((type)) && BLUFI_GET_SUBTYPE((type)) == BLUFI_TYPE_CTRL_SUBTYPE_START_NEG)
|
||||
#define BLUFI_TYPE_IS_CTRL_STOP_NEG(type) (BLUFI_TYPE_IS_CTRL((type)) && BLUFI_GET_SUBTYPE((type)) == BLUFI_TYPE_CTRL_SUBTYPE_STOP_NEG)
|
||||
#define BLUFI_TYPE_IS_CTRL_SET_WIFI_OPMODE(type) (BLUFI_TYPE_IS_CTRL((type)) && BLUFI_GET_SUBTYPE((type)) == BLUFI_TYPE_CTRL_SUBTYPE_SET_WIFI_OPMODE)
|
||||
#define BLUFI_TYPE_IS_CTRL_CONN_WIFI(type) (BLUFI_TYPE_IS_CTRL((type)) && BLUFI_GET_SUBTYPE((type)) == BLUFI_TYPE_CTRL_SUBTYPE_CONN_TO_AP)
|
||||
#define BLUFI_TYPE_IS_CTRL_DISCONN_WIFI(type) (BLUFI_TYPE_IS_CTRL((type)) && BLUFI_GET_SUBTYPE((type)) == BLUFI_TYPE_CTRL_SUBTYPE_DISCONN_FROM_AP)
|
||||
#define BLUFI_TYPE_IS_CTRL_GET_WIFI_STATUS(type) (BLUFI_TYPE_IS_CTRL((type)) && BLUFI_GET_SUBTYPE((type)) == BLUFI_TYPE_CTRL_SUBTYPE_GET_WIFI_STATUS)
|
||||
#define BLUFI_TYPE_IS_CTRL_DEAUTHENTICATE_STA(type) (BLUFI_TYPE_IS_CTRL((type)) && BLUFI_GET_SUBTYPE((type)) == BLUFI_TYPE_CTRL_SUBTYPE_DEAUTHENTICATE_STA)
|
||||
#define BLUFI_TYPE_IS_CTRL_GET_VERSION(type) (BLUFI_TYPE_IS_CTRL((type)) && BLUFI_GET_SUBTYPE((type)) == BLUFI_TYPE_CTRL_SUBTYPE_GET_VERSION)
|
||||
|
||||
#define BLUFI_TYPE_IS_DATA_NEG(type) (BLUFI_TYPE_IS_DATA((type)) && BLUFI_GET_SUBTYPE((type)) == BLUFI_TYPE_DATA_SUBTYPE_NEG)
|
||||
#define BLUFI_TYPE_IS_DATA_STA_BSSID(type) (BLUFI_TYPE_IS_DATA((type)) && BLUFI_GET_SUBTYPE((type)) == BLUFI_TYPE_DATA_SUBTYPE_STA_BSSID)
|
||||
#define BLUFI_TYPE_IS_DATA_STA_SSID(type) (BLUFI_TYPE_IS_DATA((type)) && BLUFI_GET_SUBTYPE((type)) == BLUFI_TYPE_DATA_SUBTYPE_STA_SSID)
|
||||
#define BLUFI_TYPE_IS_DATA_STA_PASSWD(type) (BLUFI_TYPE_IS_DATA((type)) && BLUFI_GET_SUBTYPE((type)) == BLUFI_TYPE_DATA_SUBTYPE_STA_PASSWD)
|
||||
#define BLUFI_TYPE_IS_DATA_SOFTAP_SSID(type) (BLUFI_TYPE_IS_DATA((type)) && BLUFI_GET_SUBTYPE((type)) == BLUFI_TYPE_DATA_SUBTYPE_SOFTAP_SSID)
|
||||
#define BLUFI_TYPE_IS_DATA_SOFTAP_PASSWD(type) (BLUFI_TYPE_IS_DATA((type)) && BLUFI_GET_SUBTYPE((type)) == BLUFI_TYPE_DATA_SUBTYPE_SOFTAP_PASSWD)
|
||||
#define BLUFI_TYPE_IS_DATA_SOFTAP_MAX_CONN_NUM(type) (BLUFI_TYPE_IS_DATA((type)) && BLUFI_GET_SUBTYPE((type)) == BLUFI_TYPE_DATA_SUBTYPE_SOFTAP_MAX_CONN_NUM)
|
||||
#define BLUFI_TYPE_IS_DATA_SOFTAP_AUTH_MODE(type) (BLUFI_TYPE_IS_DATA((type)) && BLUFI_GET_SUBTYPE((type)) == BLUFI_TYPE_DATA_SUBTYPE_SOFTAP_AUTH_MODE)
|
||||
#define BLUFI_TYPE_IS_DATA_SOFTAP_CHANNEL(type) (BLUFI_TYPE_IS_DATA((type)) && BLUFI_GET_SUBTYPE((type)) == BLUFI_TYPE_DATA_SUBTYPE_SOFTAP_CHANNEL)
|
||||
#define BLUFI_TYPE_IS_DATA_USERNAME(type) (BLUFI_TYPE_IS_DATA((type)) && BLUFI_GET_SUBTYPE((type)) == BLUFI_TYPE_DATA_SUBTYPE_USERNAME)
|
||||
#define BLUFI_TYPE_IS_DATA_CA(type) (BLUFI_TYPE_IS_DATA((type)) && BLUFI_GET_SUBTYPE((type)) == BLUFI_TYPE_DATA_SUBTYPE_CA)
|
||||
#define BLUFI_TYPE_IS_DATA_CLEINT_CERT(type) (BLUFI_TYPE_IS_DATA((type)) && BLUFI_GET_SUBTYPE((type)) == BLUFI_TYPE_DATA_SUBTYPE_CLIENT_CERT)
|
||||
#define BLUFI_TYPE_IS_DATA_SERVER_CERT(type) (BLUFI_TYPE_IS_DATA((type)) && BLUFI_GET_SUBTYPE((type)) == BLUFI_TYPE_DATA_SUBTYPE_SERVER_CERT)
|
||||
#define BLUFI_TYPE_IS_DATA_CLIENT_PRIV_KEY(type) (BLUFI_TYPE_IS_DATA((type)) && BLUFI_GET_SUBTYPE((type)) == BLUFI_TYPE_DATA_SUBTYPE_CLIENT_PRIV_KEY)
|
||||
#define BLUFI_TYPE_IS_DATA_SERVER_PRIV_KEY(type) (BLUFI_TYPE_IS_DATA((type)) && BLUFI_GET_SUBTYPE((type)) == BLUFI_TYPE_DATA_SUBTYPE_SERVER_PRIV_KEY)
|
||||
|
||||
// packet frame control
|
||||
#define BLUFI_FC_ENC_MASK 0x01
|
||||
#define BLUFI_FC_CHECK_MASK 0x02
|
||||
#define BLUFI_FC_DIR_MASK 0x04
|
||||
#define BLUFI_FC_REQ_ACK_MASK 0x08
|
||||
#define BLUFI_FC_FRAG_MASK 0x10
|
||||
|
||||
#define BLUFI_FC_ENC 0x01
|
||||
#define BLUFI_FC_CHECK 0x02
|
||||
#define BLUFI_FC_DIR_P2E 0x00
|
||||
#define BLUFI_FC_DIR_E2P 0x04
|
||||
#define BLUFI_FC_REQ_ACK 0x08
|
||||
#define BLUFI_FC_FRAG 0x10
|
||||
|
||||
#define BLUFI_FC_IS_ENC(fc) ((fc) & BLUFI_FC_ENC_MASK)
|
||||
#define BLUFI_FC_IS_CHECK(fc) ((fc) & BLUFI_FC_CHECK_MASK)
|
||||
#define BLUFI_FC_IS_DIR_P2E(fc) ((fc) & BLUFI_FC_DIR_P2E_MASK)
|
||||
#define BLUFI_FC_IS_DIR_E2P(fc) (!((fc) & BLUFI_DIR_P2E_MASK))
|
||||
#define BLUFI_FC_IS_REQ_ACK(fc) ((fc) & BLUFI_FC_REQ_ACK_MASK)
|
||||
#define BLUFI_FC_IS_FRAG(fc) ((fc) & BLUFI_FC_FRAG_MASK)
|
||||
|
||||
#define BLUFI_FRAG_DATA_MAX_LEN 50
|
||||
|
||||
//function declare
|
||||
void btc_blufi_protocol_handler(uint8_t type, uint8_t *data, int len);
|
||||
|
||||
void btc_blufi_send_encap(uint8_t type, uint8_t *data, int data_len);
|
||||
|
||||
void btc_blufi_set_callbacks(esp_blufi_callbacks_t *callbacks);
|
||||
|
||||
void btc_blufi_cb_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src);
|
||||
|
||||
void btc_blufi_cb_deep_free(btc_msg_t *msg);
|
||||
|
||||
#endif /* __BLUFI_INT_H__ */
|
||||
|
@ -22,31 +22,26 @@
|
||||
typedef enum {
|
||||
BTC_BLUFI_ACT_INIT = 0,
|
||||
BTC_BLUFI_ACT_DEINIT,
|
||||
BTC_BLUFI_ACT_SEND_CFG_STATE,
|
||||
BTC_BLUFI_ACT_SEND_CFG_REPORT,
|
||||
} btc_blufi_act_t;
|
||||
|
||||
typedef enum {
|
||||
BTC_BLUFI_CB_ACT_INIT_FINISH = 0,
|
||||
BTC_BLUFI_CB_ACT_DEINIT_FINISH,
|
||||
BTC_BLUFI_CB_ACT_RECV_DATA,
|
||||
} btc_blufi_cb_act_t;
|
||||
|
||||
typedef union {
|
||||
#if 0
|
||||
//BTC_BLUFI_ACT_INIT = 0,
|
||||
struct blufi_init_param {
|
||||
} init;
|
||||
//BTC_BLUFI_ACT_DEINIT,
|
||||
struct blufi_deinit_param {
|
||||
} deinit;
|
||||
#endif
|
||||
//BTC_BLUFI_ACT_SEND_CFG_STATE,
|
||||
struct blufi_send_cfg_state_pram {
|
||||
esp_blufi_config_state_t state;
|
||||
} cfg_state;
|
||||
struct blufi_cfg_report {
|
||||
wifi_mode_t opmode;
|
||||
esp_blufi_sta_conn_state_t sta_conn_state;
|
||||
uint8_t softap_conn_num;
|
||||
esp_blufi_extra_info_t *extra_info;
|
||||
int extra_info_len;
|
||||
} wifi_conn_report;
|
||||
} btc_blufi_args_t;
|
||||
|
||||
void btc_blufi_cb_handler(btc_msg_t *msg);
|
||||
void btc_blufi_call_handler(btc_msg_t *msg);
|
||||
void btc_blufi_set_callbacks(esp_blufi_callbacks_t *callbacks);
|
||||
|
||||
void btc_blufi_call_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src);
|
||||
void btc_blufi_call_deep_free(btc_msg_t *msg);
|
||||
|
||||
uint16_t btc_blufi_get_version(void);
|
||||
|
||||
#endif /* __BTC_BLUFI_PRF_H__ */
|
||||
|
@ -26,8 +26,13 @@
|
||||
static tBTA_BLE_ADV_DATA gl_bta_adv_data;
|
||||
static tBTA_BLE_ADV_DATA gl_bta_scan_rsp_data;
|
||||
|
||||
#define BTC_GAP_BLE_CB_TO_APP(_event, _param) ((esp_profile_cb_t )btc_profile_cb_get(BTC_PID_GAP_BLE))(_event, _param)
|
||||
|
||||
static inline void btc_gap_ble_cb_to_app(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param)
|
||||
{
|
||||
esp_gap_ble_cb_t btc_gap_ble_cb = (esp_gap_ble_cb_t)btc_profile_cb_get(BTC_PID_GAP_BLE);
|
||||
if (btc_gap_ble_cb) {
|
||||
btc_gap_ble_cb(event, param);
|
||||
}
|
||||
}
|
||||
|
||||
static void btc_gap_adv_point_cleanup(void **buf)
|
||||
{
|
||||
@ -109,6 +114,7 @@ static void btc_to_bta_adv_data(esp_ble_adv_data_t *p_adv_data, tBTA_BLE_ADV_DAT
|
||||
|
||||
if (p_adv_data->flag != 0) {
|
||||
mask = BTM_BLE_AD_BIT_FLAGS;
|
||||
bta_adv_data->flag = p_adv_data->flag;
|
||||
}
|
||||
|
||||
if (p_adv_data->include_name) {
|
||||
@ -200,7 +206,7 @@ static void btc_to_bta_adv_data(esp_ble_adv_data_t *p_adv_data, tBTA_BLE_ADV_DAT
|
||||
}
|
||||
|
||||
if (NULL != bta_adv_data->p_services->p_uuid) {
|
||||
LOG_ERROR("%s - In 16-UUID_data", __FUNCTION__);
|
||||
LOG_DEBUG("%s - In 16-UUID_data", __FUNCTION__);
|
||||
mask |= BTM_BLE_AD_BIT_SERVICE;
|
||||
++bta_adv_data->p_services->num_service;
|
||||
*p_uuid_out16++ = bt_uuid.uu.uuid16;
|
||||
@ -220,7 +226,7 @@ static void btc_to_bta_adv_data(esp_ble_adv_data_t *p_adv_data, tBTA_BLE_ADV_DAT
|
||||
}
|
||||
|
||||
if (NULL != bta_adv_data->p_service_32b->p_uuid) {
|
||||
LOG_ERROR("%s - In 32-UUID_data", __FUNCTION__);
|
||||
LOG_DEBUG("%s - In 32-UUID_data", __FUNCTION__);
|
||||
mask |= BTM_BLE_AD_BIT_SERVICE_32;
|
||||
++bta_adv_data->p_service_32b->num_service;
|
||||
*p_uuid_out32++ = bt_uuid.uu.uuid32;
|
||||
@ -503,16 +509,16 @@ void btc_gap_ble_cb_handler(btc_msg_t *msg)
|
||||
|
||||
switch (msg->act) {
|
||||
case ESP_GAP_BLE_ADV_DATA_SET_COMPLETE_EVT:
|
||||
BTC_GAP_BLE_CB_TO_APP(ESP_GAP_BLE_ADV_DATA_SET_COMPLETE_EVT, param);
|
||||
btc_gap_ble_cb_to_app(ESP_GAP_BLE_ADV_DATA_SET_COMPLETE_EVT, param);
|
||||
break;
|
||||
case ESP_GAP_BLE_SCAN_RSP_DATA_SET_COMPLETE_EVT :
|
||||
BTC_GAP_BLE_CB_TO_APP(ESP_GAP_BLE_SCAN_RSP_DATA_SET_COMPLETE_EVT, param);
|
||||
btc_gap_ble_cb_to_app(ESP_GAP_BLE_SCAN_RSP_DATA_SET_COMPLETE_EVT, param);
|
||||
break;
|
||||
case ESP_GAP_BLE_SCAN_PARAM_SET_COMPLETE_EVT:
|
||||
BTC_GAP_BLE_CB_TO_APP(ESP_GAP_BLE_SCAN_PARAM_SET_COMPLETE_EVT, param);
|
||||
btc_gap_ble_cb_to_app(ESP_GAP_BLE_SCAN_PARAM_SET_COMPLETE_EVT, param);
|
||||
break;
|
||||
case ESP_GAP_BLE_SCAN_RESULT_EVT:
|
||||
BTC_GAP_BLE_CB_TO_APP(ESP_GAP_BLE_SCAN_RESULT_EVT, param);
|
||||
btc_gap_ble_cb_to_app(ESP_GAP_BLE_SCAN_RESULT_EVT, param);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -169,13 +169,14 @@ uint16_t get_uuid16(tBT_UUID *p_uuid)
|
||||
return (UINT16) p_uuid->uu.uuid32;
|
||||
}
|
||||
}
|
||||
uint16_t set_read_value(esp_ble_gattc_cb_param_t *p_dest, tBTA_GATTC_READ *p_src)
|
||||
uint16_t set_read_value(uint8_t *gattc_if, esp_ble_gattc_cb_param_t *p_dest, tBTA_GATTC_READ *p_src)
|
||||
{
|
||||
uint16_t descr_type = 0;
|
||||
uint16_t len = 0;
|
||||
|
||||
p_dest->read.status = p_src->status;
|
||||
p_dest->read.conn_id = p_src->conn_id;
|
||||
p_dest->read.conn_id = BTC_GATT_GET_CONN_ID(p_src->conn_id);
|
||||
*gattc_if = BTC_GATT_GET_GATT_IF(p_src->conn_id);
|
||||
bta_to_btc_srvc_id(&p_dest->read.srvc_id, &p_src->srvc_id);
|
||||
bta_to_btc_gatt_id(&p_dest->read.char_id, &p_src->char_id);
|
||||
bta_to_btc_gatt_id(&p_dest->read.descr_id, &p_src->descr_type);
|
||||
|
@ -22,7 +22,13 @@
|
||||
#include "bt_trace.h"
|
||||
#include "esp_gattc_api.h"
|
||||
|
||||
#define BTC_GATTC_CB_TO_APP(_event, _param) ((esp_profile_cb_t )btc_profile_cb_get(BTC_PID_GATTC))(_event, _param)
|
||||
static inline void btc_gattc_cb_to_app(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gattc_cb_param_t *param)
|
||||
{
|
||||
esp_gattc_cb_t btc_gattc_cb = (esp_gattc_cb_t )btc_profile_cb_get(BTC_PID_GATTC);
|
||||
if (btc_gattc_cb) {
|
||||
btc_gattc_cb(event, gattc_if, param);
|
||||
}
|
||||
}
|
||||
|
||||
void btc_gattc_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src)
|
||||
{
|
||||
@ -141,13 +147,13 @@ static void btc_gattc_app_register(btc_ble_gattc_args_t *arg)
|
||||
|
||||
static void btc_gattc_app_unregister(btc_ble_gattc_args_t *arg)
|
||||
{
|
||||
BTA_GATTC_AppDeregister(arg->app_unreg.gatt_if);
|
||||
BTA_GATTC_AppDeregister(arg->app_unreg.gattc_if);
|
||||
}
|
||||
|
||||
static void btc_gattc_open(btc_ble_gattc_args_t *arg)
|
||||
{
|
||||
tBTA_GATT_TRANSPORT transport = BTA_GATT_TRANSPORT_LE;
|
||||
BTA_GATTC_Open(arg->open.gatt_if, arg->open.remote_bda, arg->open.is_direct, transport);
|
||||
BTA_GATTC_Open(arg->open.gattc_if, arg->open.remote_bda, arg->open.is_direct, transport);
|
||||
}
|
||||
|
||||
static void btc_gattc_close(btc_ble_gattc_args_t *arg)
|
||||
@ -181,6 +187,7 @@ static void btc_gattc_get_first_char(btc_ble_gattc_args_t *arg)
|
||||
tBTA_GATT_CHAR_PROP out_char_prop;
|
||||
tBTA_GATT_SRVC_ID srvc_id;
|
||||
esp_ble_gattc_cb_param_t param;
|
||||
esp_gatt_if_t gattc_if;
|
||||
|
||||
btc_to_bta_srvc_id(&srvc_id, &arg->get_first_char.service_id);
|
||||
status = BTA_GATTC_GetFirstChar(arg->get_first_char.conn_id, &srvc_id, NULL,
|
||||
@ -189,13 +196,14 @@ static void btc_gattc_get_first_char(btc_ble_gattc_args_t *arg)
|
||||
bta_to_btc_gatt_id(&char_id, &out_char_id.char_id);
|
||||
}
|
||||
|
||||
gattc_if = BTC_GATT_GET_GATT_IF(arg->get_first_char.conn_id);
|
||||
memset(¶m, 0, sizeof(esp_ble_gattc_cb_param_t));
|
||||
param.get_char.conn_id = arg->get_first_char.conn_id;
|
||||
param.get_char.conn_id = BTC_GATT_GET_CONN_ID(arg->get_first_char.conn_id);
|
||||
param.get_char.status = status;
|
||||
memcpy(¶m.get_char.srvc_id, &arg->get_first_char.service_id, sizeof(esp_gatt_srvc_id_t));
|
||||
memcpy(¶m.get_char.char_id, &char_id, sizeof(esp_gatt_id_t));
|
||||
param.get_char.char_prop = out_char_prop;
|
||||
BTC_GATTC_CB_TO_APP(ESP_GATTC_GET_CHAR_EVT, ¶m);
|
||||
btc_gattc_cb_to_app(ESP_GATTC_GET_CHAR_EVT, gattc_if, ¶m);
|
||||
}
|
||||
|
||||
static void btc_gattc_get_next_char(btc_ble_gattc_args_t *arg)
|
||||
@ -206,6 +214,8 @@ static void btc_gattc_get_next_char(btc_ble_gattc_args_t *arg)
|
||||
tBTA_GATTC_CHAR_ID out_char_id;
|
||||
tBTA_GATT_CHAR_PROP out_char_prop;
|
||||
esp_ble_gattc_cb_param_t param;
|
||||
esp_gatt_if_t gattc_if;
|
||||
|
||||
btc_to_bta_srvc_id(&in_char_id.srvc_id, &arg->get_next_char.service_id);
|
||||
btc_to_bta_gatt_id(&in_char_id.char_id, &arg->get_next_char.char_id);
|
||||
|
||||
@ -216,13 +226,14 @@ static void btc_gattc_get_next_char(btc_ble_gattc_args_t *arg)
|
||||
bta_to_btc_gatt_id(&char_id, &out_char_id.char_id);
|
||||
}
|
||||
|
||||
gattc_if = BTC_GATT_GET_GATT_IF(arg->get_next_char.conn_id);
|
||||
memset(¶m, 0, sizeof(esp_ble_gattc_cb_param_t));
|
||||
param.get_char.conn_id = arg->get_next_char.conn_id;
|
||||
param.get_char.conn_id = BTC_GATT_GET_CONN_ID(arg->get_next_char.conn_id);
|
||||
param.get_char.status = status;
|
||||
memcpy(¶m.get_char.srvc_id, &arg->get_next_char.service_id, sizeof(esp_gatt_srvc_id_t));
|
||||
memcpy(¶m.get_char.char_id, &char_id, sizeof(esp_gatt_id_t));
|
||||
param.get_char.char_prop = out_char_prop;
|
||||
BTC_GATTC_CB_TO_APP(ESP_GATTC_GET_CHAR_EVT, ¶m);
|
||||
btc_gattc_cb_to_app(ESP_GATTC_GET_CHAR_EVT, gattc_if, ¶m);
|
||||
}
|
||||
|
||||
static void btc_gattc_get_first_descr(btc_ble_gattc_args_t *arg)
|
||||
@ -232,6 +243,7 @@ static void btc_gattc_get_first_descr(btc_ble_gattc_args_t *arg)
|
||||
tBTA_GATTC_CHAR_ID in_char_id;
|
||||
tBTA_GATTC_CHAR_DESCR_ID out_char_descr_id;
|
||||
esp_ble_gattc_cb_param_t param;
|
||||
esp_gatt_if_t gattc_if;
|
||||
|
||||
btc_to_bta_srvc_id(&in_char_id.srvc_id, &arg->get_first_descr.service_id);
|
||||
btc_to_bta_gatt_id(&in_char_id.char_id, &arg->get_first_descr.char_id);
|
||||
@ -243,13 +255,14 @@ static void btc_gattc_get_first_descr(btc_ble_gattc_args_t *arg)
|
||||
bta_to_btc_gatt_id(&descr_id, &out_char_descr_id.descr_id);
|
||||
}
|
||||
|
||||
gattc_if = BTC_GATT_GET_GATT_IF(arg->get_first_descr.conn_id);
|
||||
memset(¶m, 0, sizeof(esp_ble_gattc_cb_param_t));
|
||||
param.get_descr.conn_id = arg->get_first_descr.conn_id;
|
||||
param.get_descr.conn_id = BTC_GATT_GET_CONN_ID(arg->get_first_descr.conn_id);
|
||||
param.get_descr.status = status;
|
||||
memcpy(¶m.get_descr.srvc_id, &arg->get_first_descr.service_id, sizeof(esp_gatt_srvc_id_t));
|
||||
memcpy(¶m.get_descr.char_id, &arg->get_first_descr.char_id, sizeof(esp_gatt_id_t));
|
||||
memcpy(¶m.get_descr.descr_id, &descr_id, sizeof(esp_gatt_id_t));
|
||||
BTC_GATTC_CB_TO_APP(ESP_GATTC_GET_DESCR_EVT, ¶m);
|
||||
btc_gattc_cb_to_app(ESP_GATTC_GET_DESCR_EVT, gattc_if, ¶m);
|
||||
}
|
||||
|
||||
static void btc_gattc_get_next_descr(btc_ble_gattc_args_t *arg)
|
||||
@ -259,6 +272,7 @@ static void btc_gattc_get_next_descr(btc_ble_gattc_args_t *arg)
|
||||
tBTA_GATTC_CHAR_DESCR_ID in_char_descr_id;
|
||||
tBTA_GATTC_CHAR_DESCR_ID out_char_descr_id;
|
||||
esp_ble_gattc_cb_param_t param;
|
||||
esp_gatt_if_t gattc_if;
|
||||
|
||||
btc_to_bta_srvc_id(&in_char_descr_id.char_id.srvc_id, &arg->get_next_descr.service_id);
|
||||
btc_to_bta_gatt_id(&in_char_descr_id.char_id.char_id, &arg->get_next_descr.char_id);
|
||||
@ -270,13 +284,14 @@ static void btc_gattc_get_next_descr(btc_ble_gattc_args_t *arg)
|
||||
bta_to_btc_gatt_id(&descr_id, &out_char_descr_id.descr_id);
|
||||
}
|
||||
|
||||
gattc_if = BTC_GATT_GET_GATT_IF(arg->get_next_descr.conn_id);
|
||||
memset(¶m, 0, sizeof(esp_ble_gattc_cb_param_t));
|
||||
param.get_descr.conn_id = arg->get_next_descr.conn_id;
|
||||
param.get_descr.conn_id = BTC_GATT_GET_CONN_ID(arg->get_next_descr.conn_id);
|
||||
param.get_descr.status = status;
|
||||
memcpy(¶m.get_descr.srvc_id, &arg->get_next_descr.service_id, sizeof(esp_gatt_srvc_id_t));
|
||||
memcpy(¶m.get_descr.char_id, &arg->get_next_descr.char_id, sizeof(esp_gatt_id_t));
|
||||
memcpy(¶m.get_descr.descr_id, &descr_id, sizeof(esp_gatt_id_t));
|
||||
BTC_GATTC_CB_TO_APP(ESP_GATTC_GET_DESCR_EVT, ¶m);
|
||||
btc_gattc_cb_to_app(ESP_GATTC_GET_DESCR_EVT, gattc_if, ¶m);
|
||||
}
|
||||
|
||||
static void btc_gattc_get_first_incl_service(btc_ble_gattc_args_t *arg)
|
||||
@ -286,6 +301,7 @@ static void btc_gattc_get_first_incl_service(btc_ble_gattc_args_t *arg)
|
||||
tBTA_GATT_SRVC_ID srvc_id;
|
||||
tBTA_GATTC_INCL_SVC_ID out_incl_svc_id;
|
||||
esp_ble_gattc_cb_param_t param;
|
||||
esp_gatt_if_t gattc_if;
|
||||
|
||||
btc_to_bta_srvc_id(&srvc_id, &arg->get_first_incl_srvc.service_id);
|
||||
|
||||
@ -294,12 +310,13 @@ static void btc_gattc_get_first_incl_service(btc_ble_gattc_args_t *arg)
|
||||
|
||||
bta_to_btc_srvc_id(&incl_srvc_id, &out_incl_svc_id.incl_svc_id);
|
||||
|
||||
gattc_if = BTC_GATT_GET_GATT_IF(arg->get_first_incl_srvc.conn_id);
|
||||
memset(¶m, 0, sizeof(esp_ble_gattc_cb_param_t));
|
||||
param.get_incl_srvc.conn_id = arg->get_first_incl_srvc.conn_id;
|
||||
param.get_incl_srvc.conn_id = BTC_GATT_GET_CONN_ID(arg->get_first_incl_srvc.conn_id);
|
||||
param.get_incl_srvc.status = status;
|
||||
memcpy(¶m.get_incl_srvc.srvc_id, &arg->get_first_incl_srvc.service_id, sizeof(esp_gatt_srvc_id_t));
|
||||
memcpy(¶m.get_incl_srvc.incl_srvc_id, &incl_srvc_id, sizeof(esp_gatt_srvc_id_t));
|
||||
BTC_GATTC_CB_TO_APP(ESP_GATTC_GET_INCL_SRVC_EVT, ¶m);
|
||||
btc_gattc_cb_to_app(ESP_GATTC_GET_INCL_SRVC_EVT, gattc_if, ¶m);
|
||||
}
|
||||
|
||||
static void btc_gattc_get_next_incl_service(btc_ble_gattc_args_t *arg)
|
||||
@ -309,6 +326,7 @@ static void btc_gattc_get_next_incl_service(btc_ble_gattc_args_t *arg)
|
||||
tBTA_GATTC_INCL_SVC_ID in_incl_svc_id;
|
||||
tBTA_GATTC_INCL_SVC_ID out_incl_svc_id;
|
||||
esp_ble_gattc_cb_param_t param;
|
||||
esp_gatt_if_t gattc_if;
|
||||
|
||||
btc_to_bta_srvc_id(&in_incl_svc_id.srvc_id, &arg->get_next_incl_srvc.service_id);
|
||||
btc_to_bta_srvc_id(&in_incl_svc_id.incl_svc_id, &arg->get_next_incl_srvc.start_service_id);
|
||||
@ -318,12 +336,13 @@ static void btc_gattc_get_next_incl_service(btc_ble_gattc_args_t *arg)
|
||||
|
||||
bta_to_btc_srvc_id(&incl_srvc_id, &out_incl_svc_id.incl_svc_id);
|
||||
|
||||
gattc_if = BTC_GATT_GET_GATT_IF(arg->get_next_incl_srvc.conn_id);
|
||||
memset(¶m, 0, sizeof(esp_ble_gattc_cb_param_t));
|
||||
param.get_incl_srvc.conn_id = arg->get_next_incl_srvc.conn_id;
|
||||
param.get_incl_srvc.conn_id = BTC_GATT_GET_CONN_ID(arg->get_next_incl_srvc.conn_id);
|
||||
param.get_incl_srvc.status = status;
|
||||
memcpy(¶m.get_incl_srvc.srvc_id, &arg->get_next_incl_srvc.service_id, sizeof(esp_gatt_srvc_id_t));
|
||||
memcpy(¶m.get_incl_srvc.incl_srvc_id, &incl_srvc_id, sizeof(esp_gatt_srvc_id_t));
|
||||
BTC_GATTC_CB_TO_APP(ESP_GATTC_GET_INCL_SRVC_EVT, ¶m);
|
||||
btc_gattc_cb_to_app(ESP_GATTC_GET_INCL_SRVC_EVT, gattc_if, ¶m);
|
||||
}
|
||||
|
||||
static void btc_gattc_read_char(btc_ble_gattc_args_t *arg)
|
||||
@ -402,15 +421,15 @@ static void btc_gattc_reg_for_notify(btc_ble_gattc_args_t *arg)
|
||||
btc_to_bta_srvc_id(&in_char_id.srvc_id, &arg->reg_for_notify.service_id);
|
||||
btc_to_bta_gatt_id(&in_char_id.char_id, &arg->reg_for_notify.char_id);
|
||||
|
||||
status = BTA_GATTC_RegisterForNotifications(arg->reg_for_notify.gatt_if,
|
||||
status = BTA_GATTC_RegisterForNotifications(arg->reg_for_notify.gattc_if,
|
||||
arg->reg_for_notify.remote_bda,
|
||||
&in_char_id);
|
||||
|
||||
memset(¶m, 0, sizeof(esp_ble_gattc_cb_param_t));
|
||||
param.reg_for_notify.status = status;
|
||||
memcpy(¶m.reg_for_notify.srvc_id, &arg->reg_for_notify.service_id, sizeof(esp_gatt_srvc_id_t));
|
||||
memcpy(¶m.reg_for_notify.char_id, &arg->reg_for_notify.service_id, sizeof(esp_gatt_id_t));
|
||||
BTC_GATTC_CB_TO_APP(ESP_GATTC_REG_FOR_NOTIFY_EVT, ¶m);
|
||||
memcpy(¶m.reg_for_notify.char_id, &arg->reg_for_notify.char_id, sizeof(esp_gatt_id_t));
|
||||
btc_gattc_cb_to_app(ESP_GATTC_REG_FOR_NOTIFY_EVT, arg->reg_for_notify.gattc_if, ¶m);
|
||||
}
|
||||
|
||||
static void btc_gattc_unreg_for_notify(btc_ble_gattc_args_t *arg)
|
||||
@ -422,7 +441,7 @@ static void btc_gattc_unreg_for_notify(btc_ble_gattc_args_t *arg)
|
||||
btc_to_bta_srvc_id(&in_char_id.srvc_id, &arg->unreg_for_notify.service_id);
|
||||
btc_to_bta_gatt_id(&in_char_id.char_id, &arg->unreg_for_notify.char_id);
|
||||
|
||||
status = BTA_GATTC_DeregisterForNotifications(arg->unreg_for_notify.gatt_if,
|
||||
status = BTA_GATTC_DeregisterForNotifications(arg->unreg_for_notify.gattc_if,
|
||||
arg->unreg_for_notify.remote_bda,
|
||||
&in_char_id);
|
||||
|
||||
@ -430,7 +449,7 @@ static void btc_gattc_unreg_for_notify(btc_ble_gattc_args_t *arg)
|
||||
param.unreg_for_notify.status = status;
|
||||
memcpy(¶m.unreg_for_notify.srvc_id, &arg->unreg_for_notify.service_id, sizeof(esp_gatt_srvc_id_t));
|
||||
memcpy(¶m.unreg_for_notify.char_id, &arg->unreg_for_notify.service_id, sizeof(esp_gatt_id_t));
|
||||
BTC_GATTC_CB_TO_APP(ESP_GATTC_UNREG_FOR_NOTIFY_EVT, ¶m);
|
||||
btc_gattc_cb_to_app(ESP_GATTC_UNREG_FOR_NOTIFY_EVT, arg->unreg_for_notify.gattc_if, ¶m);
|
||||
}
|
||||
|
||||
void btc_gattc_call_handler(btc_msg_t *msg)
|
||||
@ -508,6 +527,7 @@ void btc_gattc_call_handler(btc_msg_t *msg)
|
||||
void btc_gattc_cb_handler(btc_msg_t *msg)
|
||||
{
|
||||
tBTA_GATTC *arg = (tBTA_GATTC *)(msg->arg);
|
||||
esp_gatt_if_t gattc_if;
|
||||
esp_ble_gattc_cb_param_t param;
|
||||
|
||||
memset(¶m, 0, sizeof(esp_ble_gattc_cb_param_t));
|
||||
@ -515,75 +535,90 @@ void btc_gattc_cb_handler(btc_msg_t *msg)
|
||||
switch (msg->act) {
|
||||
case BTA_GATTC_REG_EVT: {
|
||||
tBTA_GATTC_REG *reg_oper = &arg->reg_oper;
|
||||
|
||||
gattc_if = reg_oper->client_if;
|
||||
param.reg.status = reg_oper->status;
|
||||
param.reg.gatt_if = reg_oper->client_if;
|
||||
param.reg.app_id = reg_oper->app_uuid.uu.uuid16;
|
||||
BTC_GATTC_CB_TO_APP(ESP_GATTC_REG_EVT, ¶m);
|
||||
btc_gattc_cb_to_app(ESP_GATTC_REG_EVT, gattc_if, ¶m);
|
||||
break;
|
||||
}
|
||||
case BTA_GATTC_DEREG_EVT: {
|
||||
BTC_GATTC_CB_TO_APP(ESP_GATTC_UNREG_EVT, NULL);
|
||||
tBTA_GATTC_REG *reg_oper = &arg->reg_oper;
|
||||
|
||||
gattc_if = reg_oper->client_if;
|
||||
btc_gattc_cb_to_app(ESP_GATTC_UNREG_EVT, gattc_if, NULL);
|
||||
break;
|
||||
}
|
||||
case BTA_GATTC_READ_CHAR_EVT: {
|
||||
set_read_value(¶m, &arg->read);
|
||||
BTC_GATTC_CB_TO_APP(ESP_GATTC_READ_CHAR_EVT, ¶m);
|
||||
set_read_value(&gattc_if, ¶m, &arg->read);
|
||||
btc_gattc_cb_to_app(ESP_GATTC_READ_CHAR_EVT, gattc_if, ¶m);
|
||||
break;
|
||||
}
|
||||
|
||||
case BTA_GATTC_WRITE_CHAR_EVT:
|
||||
case BTA_GATTC_PREP_WRITE_EVT: {
|
||||
tBTA_GATTC_WRITE *write = &arg->write;
|
||||
uint32_t ret_evt = (msg->act == BTA_GATTC_WRITE_CHAR_EVT) ?
|
||||
ESP_GATTC_WRITE_CHAR_EVT : ESP_GATTC_PREP_WRITE_EVT;
|
||||
param.write.conn_id = write->conn_id;
|
||||
|
||||
gattc_if = BTC_GATT_GET_GATT_IF(write->conn_id);
|
||||
param.write.conn_id = BTC_GATT_GET_CONN_ID(write->conn_id);
|
||||
param.write.status = write->status;
|
||||
bta_to_btc_srvc_id(¶m.write.srvc_id, &write->srvc_id);
|
||||
bta_to_btc_gatt_id(¶m.write.char_id, &write->char_id);
|
||||
BTC_GATTC_CB_TO_APP(ret_evt, ¶m);
|
||||
btc_gattc_cb_to_app(ret_evt, gattc_if, ¶m);
|
||||
break;
|
||||
}
|
||||
|
||||
case BTA_GATTC_EXEC_EVT: {
|
||||
tBTA_GATTC_EXEC_CMPL *exec_cmpl = &arg->exec_cmpl;
|
||||
param.exec_cmpl.conn_id = exec_cmpl->conn_id;
|
||||
|
||||
gattc_if = BTC_GATT_GET_GATT_IF(exec_cmpl->conn_id);
|
||||
param.exec_cmpl.conn_id = BTC_GATT_GET_CONN_ID(exec_cmpl->conn_id);
|
||||
param.exec_cmpl.status = exec_cmpl->status;
|
||||
BTC_GATTC_CB_TO_APP(ESP_GATTC_EXEC_EVT, ¶m);
|
||||
btc_gattc_cb_to_app(ESP_GATTC_EXEC_EVT, gattc_if, ¶m);
|
||||
break;
|
||||
}
|
||||
|
||||
case BTA_GATTC_SEARCH_CMPL_EVT: {
|
||||
tBTA_GATTC_SEARCH_CMPL *search_cmpl = &arg->search_cmpl;
|
||||
param.search_cmpl.conn_id = search_cmpl->conn_id;
|
||||
|
||||
gattc_if = BTC_GATT_GET_GATT_IF(search_cmpl->conn_id);
|
||||
param.search_cmpl.conn_id = BTC_GATT_GET_CONN_ID(search_cmpl->conn_id);
|
||||
param.search_cmpl.status = search_cmpl->status;
|
||||
BTC_GATTC_CB_TO_APP(ESP_GATTC_SEARCH_CMPL_EVT, ¶m);
|
||||
btc_gattc_cb_to_app(ESP_GATTC_SEARCH_CMPL_EVT, gattc_if, ¶m);
|
||||
break;
|
||||
}
|
||||
case BTA_GATTC_SEARCH_RES_EVT: {
|
||||
tBTA_GATTC_SRVC_RES *srvc_res = &arg->srvc_res;
|
||||
param.search_res.conn_id = srvc_res->conn_id;
|
||||
|
||||
gattc_if = BTC_GATT_GET_GATT_IF(srvc_res->conn_id);
|
||||
param.search_res.conn_id = BTC_GATT_GET_CONN_ID(srvc_res->conn_id);
|
||||
bta_to_btc_srvc_id(¶m.search_res.srvc_id, &srvc_res->service_uuid);
|
||||
BTC_GATTC_CB_TO_APP(ESP_GATTC_SEARCH_RES_EVT, ¶m);
|
||||
btc_gattc_cb_to_app(ESP_GATTC_SEARCH_RES_EVT, gattc_if, ¶m);
|
||||
break;
|
||||
}
|
||||
case BTA_GATTC_READ_DESCR_EVT: {
|
||||
set_read_value(¶m, &arg->read);
|
||||
BTC_GATTC_CB_TO_APP(ESP_GATTC_READ_DESCR_EVT, ¶m);
|
||||
set_read_value(&gattc_if, ¶m, &arg->read);
|
||||
btc_gattc_cb_to_app(ESP_GATTC_READ_DESCR_EVT, gattc_if, ¶m);
|
||||
break;
|
||||
}
|
||||
case BTA_GATTC_WRITE_DESCR_EVT: {
|
||||
tBTA_GATTC_WRITE *write = &arg->write;
|
||||
param.write.conn_id = write->conn_id;
|
||||
|
||||
gattc_if = BTC_GATT_GET_GATT_IF(write->conn_id);
|
||||
param.write.conn_id = BTC_GATT_GET_CONN_ID(write->conn_id);
|
||||
param.write.status = write->status;
|
||||
bta_to_btc_srvc_id(¶m.write.srvc_id, &write->srvc_id);
|
||||
bta_to_btc_gatt_id(¶m.write.char_id, &write->char_id);
|
||||
bta_to_btc_gatt_id(¶m.write.descr_id, &write->descr_type);
|
||||
BTC_GATTC_CB_TO_APP(ESP_GATTC_WRITE_DESCR_EVT, ¶m);
|
||||
btc_gattc_cb_to_app(ESP_GATTC_WRITE_DESCR_EVT, gattc_if, ¶m);
|
||||
break;
|
||||
}
|
||||
case BTA_GATTC_NOTIF_EVT: {
|
||||
tBTA_GATTC_NOTIFY *notify = &arg->notify;
|
||||
param.notify.conn_id = notify->conn_id;
|
||||
|
||||
gattc_if = BTC_GATT_GET_GATT_IF(notify->conn_id);
|
||||
param.notify.conn_id = BTC_GATT_GET_CONN_ID(notify->conn_id);
|
||||
memcpy(param.notify.remote_bda, notify->bda, sizeof(esp_bd_addr_t));
|
||||
bta_to_btc_srvc_id(¶m.notify.srvc_id, ¬ify->char_id.srvc_id);
|
||||
bta_to_btc_gatt_id(¶m.notify.char_id, ¬ify->char_id.char_id);
|
||||
@ -597,57 +632,63 @@ void btc_gattc_cb_handler(btc_msg_t *msg)
|
||||
BTA_GATTC_SendIndConfirm(notify->conn_id, ¬ify->char_id);
|
||||
}
|
||||
|
||||
BTC_GATTC_CB_TO_APP(ESP_GATTC_NOTIFY_EVT, ¶m);
|
||||
btc_gattc_cb_to_app(ESP_GATTC_NOTIFY_EVT, gattc_if, ¶m);
|
||||
break;
|
||||
}
|
||||
case BTA_GATTC_OPEN_EVT: {
|
||||
tBTA_GATTC_OPEN *open = &arg->open;
|
||||
|
||||
gattc_if = open->client_if;
|
||||
param.open.status = open->status;
|
||||
param.open.conn_id = open->conn_id;
|
||||
param.open.gatt_if = open->client_if;
|
||||
param.open.conn_id = BTC_GATT_GET_CONN_ID(open->conn_id);
|
||||
memcpy(param.open.remote_bda, open->remote_bda, sizeof(esp_bd_addr_t));
|
||||
param.open.mtu = open->mtu;
|
||||
BTC_GATTC_CB_TO_APP(ESP_GATTC_OPEN_EVT, ¶m);
|
||||
btc_gattc_cb_to_app(ESP_GATTC_OPEN_EVT, gattc_if, ¶m);
|
||||
break;
|
||||
}
|
||||
case BTA_GATTC_CLOSE_EVT: {
|
||||
tBTA_GATTC_CLOSE *close = &arg->close;
|
||||
|
||||
gattc_if = close->client_if;
|
||||
param.close.status = close->status;
|
||||
param.close.conn_id = close->conn_id;
|
||||
param.close.gatt_if = close->client_if;
|
||||
param.close.conn_id = BTC_GATT_GET_CONN_ID(close->conn_id);
|
||||
memcpy(param.close.remote_bda, close->remote_bda, sizeof(esp_bd_addr_t));
|
||||
param.close.reason = close->reason;
|
||||
BTC_GATTC_CB_TO_APP(ESP_GATTC_CLOSE_EVT, ¶m);
|
||||
btc_gattc_cb_to_app(ESP_GATTC_CLOSE_EVT, gattc_if, ¶m);
|
||||
break;
|
||||
}
|
||||
|
||||
case BTA_GATTC_CFG_MTU_EVT: {
|
||||
tBTA_GATTC_CFG_MTU *cfg_mtu = &arg->cfg_mtu;
|
||||
param.cfg_mtu.conn_id = cfg_mtu->conn_id;
|
||||
|
||||
gattc_if = BTC_GATT_GET_GATT_IF(cfg_mtu->conn_id);
|
||||
param.cfg_mtu.conn_id = BTC_GATT_GET_CONN_ID(cfg_mtu->conn_id);
|
||||
param.cfg_mtu.status = cfg_mtu->status;
|
||||
param.cfg_mtu.mtu = cfg_mtu->mtu;
|
||||
BTC_GATTC_CB_TO_APP(ESP_GATTC_CFG_MTU_EVT, ¶m);
|
||||
btc_gattc_cb_to_app(ESP_GATTC_CFG_MTU_EVT, gattc_if, ¶m);
|
||||
break;
|
||||
}
|
||||
|
||||
case BTA_GATTC_ACL_EVT: {
|
||||
BTC_GATTC_CB_TO_APP(ESP_GATTC_ACL_EVT, NULL);
|
||||
/* Currently, this event will never happen */
|
||||
break;
|
||||
}
|
||||
case BTA_GATTC_CANCEL_OPEN_EVT: {
|
||||
BTC_GATTC_CB_TO_APP(ESP_GATTC_CANCEL_OPEN_EVT, NULL);
|
||||
/* Currently, this event will never happen */
|
||||
break;
|
||||
}
|
||||
case BTA_GATTC_CONGEST_EVT: {
|
||||
tBTA_GATTC_CONGEST *congest = &arg->congest;
|
||||
param.congest.conn_id = congest->conn_id;
|
||||
|
||||
gattc_if = BTC_GATT_GET_GATT_IF(congest->conn_id);
|
||||
param.congest.conn_id = BTC_GATT_GET_CONN_ID(congest->conn_id);
|
||||
param.congest.congested = (congest->congested == TRUE) ? true : false;
|
||||
BTC_GATTC_CB_TO_APP(ESP_GATTC_CONGEST_EVT, ¶m);
|
||||
btc_gattc_cb_to_app(ESP_GATTC_CONGEST_EVT, gattc_if, ¶m);
|
||||
break;
|
||||
}
|
||||
case BTA_GATTC_SRVC_CHG_EVT: {
|
||||
memcpy(param.srvc_chg.remote_bda, arg->remote_bda, sizeof(esp_bd_addr_t));
|
||||
BTC_GATTC_CB_TO_APP(ESP_GATTC_SRVC_CHG_EVT, ¶m);
|
||||
btc_gattc_cb_to_app(ESP_GATTC_SRVC_CHG_EVT, ESP_GATT_IF_NONE, ¶m);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
@ -20,14 +20,52 @@
|
||||
#include "btc_manage.h"
|
||||
#include "btc_gatts.h"
|
||||
#include "btc_gatt_util.h"
|
||||
|
||||
#include "future.h"
|
||||
#include "btc_main.h"
|
||||
#include "esp_gatts_api.h"
|
||||
|
||||
#define BTC_GATTS_CB_TO_APP(_event, _param) ((esp_profile_cb_t)btc_profile_cb_get(BTC_PID_GATTS))(_event, _param)
|
||||
|
||||
#define A2C_GATTS_EVT(_bta_event) (_bta_event) //BTA TO BTC EVT
|
||||
#define C2A_GATTS_EVT(_btc_event) (_btc_event) //BTC TO BTA EVT
|
||||
|
||||
typedef struct {
|
||||
future_t *complete_future;
|
||||
uint16_t svc_start_hdl;
|
||||
esp_bt_uuid_t svc_uuid;
|
||||
bool is_tab_creat_svc;
|
||||
uint8_t num_handle;
|
||||
uint8_t handle_idx;
|
||||
uint16_t handles[ESP_GATT_ATTR_HANDLE_MAX];
|
||||
} esp_btc_creat_tab_t;
|
||||
|
||||
static esp_btc_creat_tab_t btc_creat_tab_env;
|
||||
|
||||
static inline void btc_gatts_cb_to_app(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param)
|
||||
{
|
||||
esp_gatts_cb_t btc_gatts_cb = (esp_gatts_cb_t)btc_profile_cb_get(BTC_PID_GATTS);
|
||||
if (btc_gatts_cb) {
|
||||
btc_gatts_cb(event, gatts_if, param);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void btc_gatts_uuid_format_convert(esp_bt_uuid_t* dest_uuid, uint16_t src_uuid_len, uint8_t* src_uuid_p)
|
||||
{
|
||||
dest_uuid->len = src_uuid_len;
|
||||
if(src_uuid_len == ESP_UUID_LEN_16){
|
||||
dest_uuid->uuid.uuid16 = src_uuid_p[0] + (src_uuid_p[1]<<8);
|
||||
}
|
||||
else if(src_uuid_len == ESP_UUID_LEN_32){
|
||||
dest_uuid->uuid.uuid32 = src_uuid_p[0] + (src_uuid_p[1]<<8) + (src_uuid_p[2]<<16) + (src_uuid_p[3]<<24);
|
||||
}
|
||||
else if(src_uuid_len == ESP_UUID_LEN_128){
|
||||
memcpy(dest_uuid->uuid.uuid128, src_uuid_p, src_uuid_len);
|
||||
}
|
||||
else{
|
||||
LOG_ERROR("%s wrong uuid length %d\n", __func__, src_uuid_len);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void btc_gatts_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src)
|
||||
{
|
||||
btc_ble_gatts_args_t *dst = (btc_ble_gatts_args_t *) p_dest;
|
||||
@ -53,6 +91,56 @@ void btc_gatts_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src)
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
case BTC_GATTS_ACT_ADD_CHAR:{
|
||||
if (src->add_char.char_val.attr_value != NULL){
|
||||
dst->add_char.char_val.attr_value = (uint8_t *)GKI_getbuf(src->add_char.char_val.attr_len);
|
||||
if(dst->add_char.char_val.attr_value != NULL){
|
||||
memcpy(dst->add_char.char_val.attr_value, src->add_char.char_val.attr_value,
|
||||
src->add_char.char_val.attr_len);
|
||||
}else{
|
||||
LOG_ERROR("%s %d no mem\n", __func__, msg->act);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case BTC_GATTS_ACT_ADD_CHAR_DESCR:{
|
||||
if(src->add_descr.descr_val.attr_value != NULL){
|
||||
dst->add_descr.descr_val.attr_value = (uint8_t *)GKI_getbuf(src->add_descr.descr_val.attr_len);
|
||||
if(dst->add_descr.descr_val.attr_value != NULL){
|
||||
memcpy(dst->add_descr.descr_val.attr_value, src->add_descr.descr_val.attr_value,
|
||||
src->add_descr.descr_val.attr_len);
|
||||
}else{
|
||||
LOG_ERROR("%s %d no mem\n", __func__, msg->act);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case BTC_GATTS_ACT_CREATE_ATTR_TAB:{
|
||||
uint8_t num_attr = src->create_attr_tab.max_nb_attr;
|
||||
if(src->create_attr_tab.gatts_attr_db != NULL){
|
||||
dst->create_attr_tab.gatts_attr_db = (esp_gatts_attr_db_t *)GKI_getbuf(sizeof(esp_gatts_attr_db_t)*num_attr);
|
||||
if(dst->create_attr_tab.gatts_attr_db != NULL){
|
||||
memcpy(dst->create_attr_tab.gatts_attr_db, src->create_attr_tab.gatts_attr_db,
|
||||
sizeof(esp_gatts_attr_db_t)*num_attr);
|
||||
}else{
|
||||
LOG_ERROR("%s %d no mem\n",__func__, msg->act);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case BTC_GATTS_ACT_SET_ATTR_VALUE:{
|
||||
uint8_t len = src->set_attr_val.length;
|
||||
if(src->set_attr_val.value){
|
||||
dst->set_attr_val.value = (uint8_t *)GKI_getbuf(len);
|
||||
if(dst->set_attr_val.value != NULL){
|
||||
memcpy(dst->set_attr_val.value, src->set_attr_val.value, len);
|
||||
}else{
|
||||
LOG_ERROR("%s %d no mem\n",__func__, msg->act);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
LOG_DEBUG("%s Unhandled deep copy %d\n", __func__, msg->act);
|
||||
@ -85,6 +173,175 @@ void btc_gatts_arg_deep_free(btc_msg_t *msg)
|
||||
|
||||
}
|
||||
|
||||
static void btc_gatts_act_create_attr_tab(esp_gatts_attr_db_t *gatts_attr_db,
|
||||
esp_gatt_if_t gatts_if,
|
||||
uint8_t max_nb_attr,
|
||||
uint8_t srvc_inst_id)
|
||||
{
|
||||
uint16_t uuid = 0;
|
||||
future_t *future_p;
|
||||
esp_ble_gatts_cb_param_t param;
|
||||
|
||||
//set the attribute table create service flag to ture
|
||||
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]);
|
||||
}
|
||||
future_p = future_new();
|
||||
if (future_p == NULL) {
|
||||
LOG_ERROR("%s failed:no mem\n", __func__);
|
||||
return ;
|
||||
}
|
||||
btc_creat_tab_env.complete_future = future_p;
|
||||
btc_creat_tab_env.handle_idx = i;
|
||||
switch(uuid)
|
||||
{
|
||||
case ESP_GATT_UUID_PRI_SERVICE:{
|
||||
tBTA_GATT_SRVC_ID srvc_id;
|
||||
esp_gatt_srvc_id_t esp_srvc_id;
|
||||
|
||||
esp_srvc_id.id.inst_id = srvc_inst_id;
|
||||
btc_gatts_uuid_format_convert(&esp_srvc_id.id.uuid,gatts_attr_db[i].att_desc.length,
|
||||
gatts_attr_db[i].att_desc.value);
|
||||
|
||||
btc_to_bta_srvc_id(&srvc_id, &esp_srvc_id);
|
||||
BTA_GATTS_CreateService(gatts_if, &srvc_id.id.uuid,
|
||||
srvc_inst_id, max_nb_attr, true);
|
||||
|
||||
if (future_await(future_p) == FUTURE_FAIL) {
|
||||
LOG_ERROR("%s failed\n", __func__);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ESP_GATT_UUID_SEC_SERVICE:{
|
||||
tBTA_GATT_SRVC_ID srvc_id;
|
||||
esp_gatt_srvc_id_t esp_srvc_id;
|
||||
|
||||
esp_srvc_id.id.inst_id = srvc_inst_id;
|
||||
btc_gatts_uuid_format_convert(&esp_srvc_id.id.uuid,gatts_attr_db[i].att_desc.uuid_length,
|
||||
gatts_attr_db[i].att_desc.uuid_p);
|
||||
btc_to_bta_srvc_id(&srvc_id, &esp_srvc_id);
|
||||
BTA_GATTS_CreateService(gatts_if, &srvc_id.id.uuid,
|
||||
srvc_inst_id, max_nb_attr, false);
|
||||
if (future_await(future_p) == FUTURE_FAIL) {
|
||||
LOG_ERROR("%s failed\n", __func__);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ESP_GATT_UUID_INCLUDE_SERVICE:{
|
||||
esp_gatts_incl_svc_desc_t *incl_svc_desc = (esp_gatts_incl_svc_desc_t *)gatts_attr_db[i].att_desc.value;
|
||||
|
||||
if(incl_svc_desc!= NULL){
|
||||
if(btc_creat_tab_env.svc_start_hdl != 0){
|
||||
BTA_GATTS_AddIncludeService(btc_creat_tab_env.svc_start_hdl,
|
||||
incl_svc_desc->start_hdl);
|
||||
|
||||
if (future_await(future_p) == FUTURE_FAIL) {
|
||||
LOG_ERROR("%s failed\n", __func__);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ESP_GATT_UUID_CHAR_DECLARE:{
|
||||
uint16_t svc_hal = 0;
|
||||
tBT_UUID bta_char_uuid;
|
||||
tGATT_ATTR_VAL attr_val;
|
||||
esp_bt_uuid_t uuid_temp;
|
||||
tBTA_GATT_PERM perm;
|
||||
tBTA_GATTS_ATTR_CONTROL control;
|
||||
uint8_t char_property;
|
||||
|
||||
if(btc_creat_tab_env.svc_start_hdl != 0){
|
||||
svc_hal = btc_creat_tab_env.svc_start_hdl;
|
||||
if((gatts_attr_db[i].att_desc.value) == NULL){
|
||||
LOG_ERROR("%s Characteristic declaration should not be NULL\n", __func__);
|
||||
}
|
||||
else{
|
||||
char_property = (uint8_t)(*(uint8_t*)(gatts_attr_db[i].att_desc.value));
|
||||
perm = gatts_attr_db[i+1].att_desc.perm;
|
||||
attr_val.attr_len = gatts_attr_db[i+1].att_desc.length;
|
||||
attr_val.attr_max_len = gatts_attr_db[i+1].att_desc.max_length;
|
||||
btc_gatts_uuid_format_convert(&uuid_temp, gatts_attr_db[i+1].att_desc.uuid_length,gatts_attr_db[i+1].att_desc.uuid_p);
|
||||
btc_to_bta_uuid(&bta_char_uuid, &uuid_temp);
|
||||
attr_val.attr_val = gatts_attr_db[i+1].att_desc.value;
|
||||
control.auto_rsp = gatts_attr_db[i+1].attr_control.auto_rsp;
|
||||
BTA_GATTS_AddCharacteristic (svc_hal, &bta_char_uuid,
|
||||
perm, char_property, &attr_val, &control);
|
||||
|
||||
if (future_await(future_p) == FUTURE_FAIL) {
|
||||
LOG_ERROR("%s failed\n", __func__);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case ESP_GATT_UUID_CHAR_EXT_PROP:
|
||||
case ESP_GATT_UUID_CHAR_DESCRIPTION:
|
||||
case ESP_GATT_UUID_CHAR_CLIENT_CONFIG:
|
||||
case ESP_GATT_UUID_CHAR_SRVR_CONFIG:
|
||||
case ESP_GATT_UUID_CHAR_PRESENT_FORMAT:
|
||||
case ESP_GATT_UUID_CHAR_AGG_FORMAT:
|
||||
case ESP_GATT_UUID_CHAR_VALID_RANGE:
|
||||
case ESP_GATT_UUID_EXT_RPT_REF_DESCR:
|
||||
case ESP_GATT_UUID_RPT_REF_DESCR:{
|
||||
uint16_t svc_hal = btc_creat_tab_env.svc_start_hdl;
|
||||
tBT_UUID bta_char_uuid;
|
||||
esp_bt_uuid_t uuid_temp;
|
||||
tGATT_ATTR_VAL attr_val;
|
||||
tBTA_GATT_PERM perm = gatts_attr_db[i].att_desc.perm;
|
||||
tBTA_GATTS_ATTR_CONTROL control;
|
||||
|
||||
if(svc_hal != 0){
|
||||
attr_val.attr_len = gatts_attr_db[i].att_desc.length;
|
||||
attr_val.attr_max_len = gatts_attr_db[i].att_desc.max_length;
|
||||
attr_val.attr_val = gatts_attr_db[i].att_desc.value;
|
||||
btc_gatts_uuid_format_convert(&uuid_temp, gatts_attr_db[i].att_desc.uuid_length,
|
||||
gatts_attr_db[i].att_desc.uuid_p);
|
||||
btc_to_bta_uuid(&bta_char_uuid, &uuid_temp);
|
||||
control.auto_rsp = gatts_attr_db[i].attr_control.auto_rsp;
|
||||
BTA_GATTS_AddCharDescriptor(svc_hal, perm, &bta_char_uuid, &attr_val, &control);
|
||||
|
||||
if (future_await(future_p) == FUTURE_FAIL) {
|
||||
LOG_ERROR("%s failed\n", __func__);
|
||||
return;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
param.add_attr_tab.status = ESP_GATT_OK;
|
||||
param.add_attr_tab.num_handle = max_nb_attr;
|
||||
param.add_attr_tab.handles = btc_creat_tab_env.handles;
|
||||
memcpy(¶m.add_attr_tab.svc_uuid, &btc_creat_tab_env.svc_uuid, sizeof(esp_bt_uuid_t));
|
||||
|
||||
btc_gatts_cb_to_app(ESP_GATTS_CREAT_ATTR_TAB_EVT, gatts_if, ¶m);
|
||||
//reset the env after sent the data to app
|
||||
memset(&btc_creat_tab_env, 0, sizeof(esp_btc_creat_tab_t));
|
||||
|
||||
//release the flag vaule to false after finish the service created.
|
||||
btc_creat_tab_env.is_tab_creat_svc = false;
|
||||
}
|
||||
|
||||
void btc_gatts_get_attr_value(uint16_t attr_handle, uint16_t *length, uint8_t **value)
|
||||
{
|
||||
|
||||
BTA_GetAttributeValue(attr_handle, length, value);
|
||||
}
|
||||
|
||||
|
||||
static void btc_gatts_cb_param_copy_req(btc_msg_t *msg, void *p_dest, void *p_src)
|
||||
{
|
||||
@ -131,7 +388,6 @@ static void btc_gatts_cb_param_copy_free(btc_msg_t *msg, tBTA_GATTS *p_data)
|
||||
GKI_freebuf(p_data->req_data.p_data);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -146,7 +402,39 @@ static void btc_gatts_inter_cb(tBTA_GATTS_EVT event, tBTA_GATTS *p_data)
|
||||
msg.sig = BTC_SIG_API_CB;
|
||||
msg.pid = BTC_PID_GATTS;
|
||||
msg.act = event;
|
||||
if(btc_creat_tab_env.is_tab_creat_svc && btc_creat_tab_env.complete_future){
|
||||
switch(event){
|
||||
case BTA_GATTS_CREATE_EVT:{
|
||||
//save the service handle to the btc module after used
|
||||
//the attribute table method to creat a service
|
||||
bta_to_btc_uuid(&btc_creat_tab_env.svc_uuid, &p_data->create.uuid);
|
||||
uint8_t index = btc_creat_tab_env.handle_idx;
|
||||
btc_creat_tab_env.svc_start_hdl = p_data->create.service_id;
|
||||
btc_creat_tab_env.handles[index] = p_data->create.service_id;
|
||||
break;
|
||||
}
|
||||
case BTA_GATTS_ADD_INCL_SRVC_EVT:{
|
||||
uint8_t index = btc_creat_tab_env.handle_idx;
|
||||
btc_creat_tab_env.handles[index] = p_data->add_result.attr_id;
|
||||
break;
|
||||
}
|
||||
case BTA_GATTS_ADD_CHAR_EVT:{
|
||||
uint8_t index = btc_creat_tab_env.handle_idx;
|
||||
btc_creat_tab_env.handles[index] = p_data->add_result.attr_id - 1;
|
||||
btc_creat_tab_env.handles[index+1] = p_data->add_result.attr_id;
|
||||
break;
|
||||
}
|
||||
case BTA_GATTS_ADD_CHAR_DESCR_EVT:{
|
||||
uint8_t index = btc_creat_tab_env.handle_idx;
|
||||
btc_creat_tab_env.handles[index] = p_data->add_result.attr_id;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
|
||||
}
|
||||
future_ready(btc_creat_tab_env.complete_future, FUTURE_SUCCESS);
|
||||
}
|
||||
status = btc_transfer_context(&msg, p_data,
|
||||
sizeof(tBTA_GATTS), btc_gatts_cb_param_copy_req);
|
||||
|
||||
@ -171,16 +459,22 @@ void btc_gatts_call_handler(btc_msg_t *msg)
|
||||
break;
|
||||
}
|
||||
case BTC_GATTS_ACT_APP_UNREGISTER:
|
||||
BTA_GATTS_AppDeregister(arg->app_unreg.gatt_if);
|
||||
BTA_GATTS_AppDeregister(arg->app_unreg.gatts_if);
|
||||
break;
|
||||
case BTC_GATTS_ACT_CREATE_SERVICE: {
|
||||
tBTA_GATT_SRVC_ID srvc_id;
|
||||
btc_to_bta_srvc_id(&srvc_id, &arg->create_srvc.service_id);
|
||||
BTA_GATTS_CreateService(arg->create_srvc.gatt_if, &srvc_id.id.uuid,
|
||||
BTA_GATTS_CreateService(arg->create_srvc.gatts_if, &srvc_id.id.uuid,
|
||||
srvc_id.id.inst_id, arg->create_srvc.num_handle,
|
||||
srvc_id.is_primary);
|
||||
break;
|
||||
}
|
||||
case BTC_GATTS_ACT_CREATE_ATTR_TAB:
|
||||
btc_gatts_act_create_attr_tab(arg->create_attr_tab.gatts_attr_db,
|
||||
arg->create_attr_tab.gatts_if,
|
||||
arg->create_attr_tab.max_nb_attr,
|
||||
arg->create_attr_tab.srvc_inst_id);
|
||||
break;
|
||||
case BTC_GATTS_ACT_DELETE_SERVICE:
|
||||
BTA_GATTS_DeleteService(arg->delete_srvc.service_handle);
|
||||
break;
|
||||
@ -198,13 +492,17 @@ void btc_gatts_call_handler(btc_msg_t *msg)
|
||||
btc_to_bta_uuid(&uuid, &arg->add_char.char_uuid);
|
||||
|
||||
BTA_GATTS_AddCharacteristic(arg->add_char.service_handle, &uuid,
|
||||
arg->add_char.perm, arg->add_char.property);
|
||||
arg->add_char.perm, arg->add_char.property,
|
||||
(tGATT_ATTR_VAL *)&arg->add_char.char_val,
|
||||
(tBTA_GATTS_ATTR_CONTROL *)&arg->add_char.attr_control);
|
||||
break;
|
||||
}
|
||||
case BTC_GATTS_ACT_ADD_CHAR_DESCR: {
|
||||
tBT_UUID uuid;
|
||||
btc_to_bta_uuid(&uuid, &arg->add_descr.descr_uuid);
|
||||
BTA_GATTS_AddCharDescriptor(arg->add_descr.service_handle, arg->add_descr.perm, &uuid);
|
||||
BTA_GATTS_AddCharDescriptor(arg->add_descr.service_handle, arg->add_descr.perm, &uuid,
|
||||
(tBTA_GATT_ATTR_VAL *)&arg->add_descr.descr_val,
|
||||
(tBTA_GATTS_ATTR_CONTROL *)&arg->add_descr.attr_control);
|
||||
break;
|
||||
}
|
||||
case BTC_GATTS_ACT_SEND_INDICATE:
|
||||
@ -227,9 +525,12 @@ void btc_gatts_call_handler(btc_msg_t *msg)
|
||||
}
|
||||
|
||||
param.rsp.status = 0;
|
||||
BTC_GATTS_CB_TO_APP(ESP_GATTS_RESPONSE_EVT, ¶m);
|
||||
btc_gatts_cb_to_app(ESP_GATTS_RESPONSE_EVT, BTC_GATT_GET_GATT_IF(arg->send_rsp.conn_id), ¶m);
|
||||
break;
|
||||
}
|
||||
case BTC_GATTS_ACT_SET_ATTR_VALUE:
|
||||
|
||||
break;
|
||||
case BTC_GATTS_ACT_OPEN: {
|
||||
// Ensure device is in inquiry database
|
||||
tBTA_GATT_TRANSPORT transport = BTA_GATT_TRANSPORT_LE;
|
||||
@ -252,7 +553,7 @@ void btc_gatts_call_handler(btc_msg_t *msg)
|
||||
transport = BTA_GATT_TRANSPORT_LE;
|
||||
|
||||
// Connect!
|
||||
BTA_GATTS_Open(arg->open.gatt_if, arg->open.remote_bda,
|
||||
BTA_GATTS_Open(arg->open.gatts_if, arg->open.remote_bda,
|
||||
arg->open.is_direct, transport);
|
||||
break;
|
||||
}
|
||||
@ -277,34 +578,39 @@ void btc_gatts_call_handler(btc_msg_t *msg)
|
||||
void btc_gatts_cb_handler(btc_msg_t *msg)
|
||||
{
|
||||
esp_ble_gatts_cb_param_t param;
|
||||
|
||||
tBTA_GATTS *p_data = (tBTA_GATTS *)msg->arg;
|
||||
esp_gatt_if_t gatts_if;
|
||||
|
||||
switch (msg->act) {
|
||||
case BTA_GATTS_REG_EVT: {
|
||||
gatts_if = p_data->reg_oper.server_if;
|
||||
param.reg.status = p_data->reg_oper.status;
|
||||
param.reg.gatt_if = p_data->reg_oper.server_if;
|
||||
param.reg.app_id = p_data->reg_oper.uuid.uu.uuid16;
|
||||
|
||||
BTC_GATTS_CB_TO_APP(ESP_GATTS_REG_EVT, ¶m);
|
||||
btc_gatts_cb_to_app(ESP_GATTS_REG_EVT, gatts_if, ¶m);
|
||||
break;
|
||||
}
|
||||
case BTA_GATTS_DEREG_EVT:
|
||||
// do nothing
|
||||
case BTA_GATTS_DEREG_EVT: {
|
||||
gatts_if = p_data->reg_oper.server_if;
|
||||
btc_gatts_cb_to_app(ESP_GATTS_UNREG_EVT, gatts_if, NULL);
|
||||
break;
|
||||
}
|
||||
case BTA_GATTS_READ_EVT: {
|
||||
param.read.conn_id = p_data->req_data.conn_id;
|
||||
gatts_if = BTC_GATT_GET_GATT_IF(p_data->req_data.conn_id);
|
||||
param.read.conn_id = BTC_GATT_GET_CONN_ID(p_data->req_data.conn_id);
|
||||
param.read.trans_id = p_data->req_data.trans_id;
|
||||
memcpy(param.read.bda, p_data->req_data.remote_bda, ESP_BD_ADDR_LEN);
|
||||
param.read.handle = p_data->req_data.p_data->read_req.handle,
|
||||
param.read.offset = p_data->req_data.p_data->read_req.offset,
|
||||
param.read.is_long = p_data->req_data.p_data->read_req.is_long,
|
||||
param.read.handle = p_data->req_data.p_data->read_req.handle;
|
||||
param.read.offset = p_data->req_data.p_data->read_req.offset;
|
||||
param.read.is_long = p_data->req_data.p_data->read_req.is_long;
|
||||
|
||||
BTC_GATTS_CB_TO_APP(ESP_GATTS_READ_EVT, ¶m);
|
||||
param.read.need_rsp = p_data->req_data.p_data->read_req.need_rsp;
|
||||
btc_gatts_cb_to_app(ESP_GATTS_READ_EVT, gatts_if, ¶m);
|
||||
break;
|
||||
}
|
||||
case BTA_GATTS_WRITE_EVT: {
|
||||
param.write.conn_id = p_data->req_data.conn_id;
|
||||
gatts_if = BTC_GATT_GET_GATT_IF(p_data->req_data.conn_id);
|
||||
param.write.conn_id = BTC_GATT_GET_CONN_ID(p_data->req_data.conn_id);
|
||||
param.write.trans_id = p_data->req_data.trans_id;
|
||||
memcpy(param.write.bda, p_data->req_data.remote_bda, ESP_BD_ADDR_LEN);
|
||||
param.write.handle = p_data->req_data.p_data->write_req.handle;
|
||||
@ -314,103 +620,106 @@ void btc_gatts_cb_handler(btc_msg_t *msg)
|
||||
param.write.len = p_data->req_data.p_data->write_req.len;
|
||||
param.write.value = p_data->req_data.p_data->write_req.value;
|
||||
|
||||
BTC_GATTS_CB_TO_APP(ESP_GATTS_WRITE_EVT, ¶m);
|
||||
btc_gatts_cb_to_app(ESP_GATTS_WRITE_EVT, gatts_if, ¶m);
|
||||
|
||||
break;
|
||||
}
|
||||
case BTA_GATTS_EXEC_WRITE_EVT: {
|
||||
param.exec_write.conn_id = p_data->req_data.conn_id;
|
||||
gatts_if = BTC_GATT_GET_GATT_IF(p_data->req_data.conn_id);
|
||||
param.exec_write.conn_id = BTC_GATT_GET_CONN_ID(p_data->req_data.conn_id);
|
||||
param.exec_write.trans_id = p_data->req_data.trans_id;
|
||||
memcpy(param.exec_write.bda, p_data->req_data.remote_bda, ESP_BD_ADDR_LEN);
|
||||
param.exec_write.exec_write_flag = p_data->req_data.p_data->exec_write;
|
||||
|
||||
BTC_GATTS_CB_TO_APP(ESP_GATTS_EXEC_WRITE_EVT, ¶m);
|
||||
|
||||
btc_gatts_cb_to_app(ESP_GATTS_EXEC_WRITE_EVT, gatts_if, ¶m);
|
||||
break;
|
||||
}
|
||||
case BTA_GATTS_MTU_EVT:
|
||||
param.mtu.conn_id = p_data->req_data.conn_id;
|
||||
gatts_if = BTC_GATT_GET_GATT_IF(p_data->req_data.conn_id);
|
||||
param.mtu.conn_id = BTC_GATT_GET_CONN_ID(p_data->req_data.conn_id);
|
||||
param.mtu.mtu = p_data->req_data.p_data->mtu;
|
||||
|
||||
BTC_GATTS_CB_TO_APP(ESP_GATTS_MTU_EVT, ¶m);
|
||||
btc_gatts_cb_to_app(ESP_GATTS_MTU_EVT, gatts_if, ¶m);
|
||||
break;
|
||||
case BTA_GATTS_CONF_EVT:
|
||||
param.conf.conn_id = p_data->req_data.conn_id;
|
||||
gatts_if = BTC_GATT_GET_GATT_IF(p_data->req_data.conn_id);
|
||||
param.conf.conn_id = BTC_GATT_GET_CONN_ID(p_data->req_data.conn_id);
|
||||
param.conf.status = p_data->req_data.status;
|
||||
|
||||
BTC_GATTS_CB_TO_APP(ESP_GATTS_CONF_EVT, ¶m);
|
||||
btc_gatts_cb_to_app(ESP_GATTS_CONF_EVT, gatts_if, ¶m);
|
||||
break;
|
||||
case BTA_GATTS_CREATE_EVT:
|
||||
gatts_if = p_data->create.server_if;
|
||||
param.create.status = p_data->create.status;
|
||||
param.create.gatt_if = p_data->create.server_if;
|
||||
param.create.service_handle = p_data->create.service_id;
|
||||
param.create.service_id.is_primary = p_data->create.is_primary;
|
||||
param.create.service_id.id.inst_id = p_data->create.svc_instance;
|
||||
bta_to_btc_uuid(¶m.create.service_id.id.uuid, &p_data->create.uuid);
|
||||
BTC_GATTS_CB_TO_APP(ESP_GATTS_CREATE_EVT, ¶m);
|
||||
|
||||
btc_gatts_cb_to_app(ESP_GATTS_CREATE_EVT, gatts_if, ¶m);
|
||||
break;
|
||||
case BTA_GATTS_ADD_INCL_SRVC_EVT:
|
||||
gatts_if = p_data->add_result.server_if;
|
||||
param.add_incl_srvc.status = p_data->add_result.status;
|
||||
param.add_incl_srvc.gatt_if = p_data->add_result.server_if;
|
||||
param.add_incl_srvc.attr_handle = p_data->add_result.attr_id;
|
||||
param.add_incl_srvc.service_handle = p_data->add_result.service_id;
|
||||
|
||||
BTC_GATTS_CB_TO_APP(ESP_GATTS_ADD_INCL_SRVC_EVT, ¶m);
|
||||
btc_gatts_cb_to_app(ESP_GATTS_ADD_INCL_SRVC_EVT, gatts_if, ¶m);
|
||||
break;
|
||||
case BTA_GATTS_ADD_CHAR_EVT:
|
||||
gatts_if = p_data->add_result.server_if;
|
||||
param.add_char.status = p_data->add_result.status;
|
||||
param.add_char.gatt_if = p_data->add_result.server_if;
|
||||
param.add_char.attr_handle = p_data->add_result.attr_id;
|
||||
param.add_char.service_handle = p_data->add_result.service_id;
|
||||
bta_to_btc_uuid(¶m.add_char.char_uuid, &p_data->add_result.char_uuid);
|
||||
|
||||
BTC_GATTS_CB_TO_APP(ESP_GATTS_ADD_CHAR_EVT, ¶m);
|
||||
btc_gatts_cb_to_app(ESP_GATTS_ADD_CHAR_EVT, gatts_if, ¶m);
|
||||
break;
|
||||
case BTA_GATTS_ADD_CHAR_DESCR_EVT:
|
||||
gatts_if = p_data->add_result.server_if;
|
||||
param.add_char_descr.status = p_data->add_result.status;
|
||||
param.add_char_descr.gatt_if = p_data->add_result.server_if;
|
||||
param.add_char_descr.attr_handle = p_data->add_result.attr_id;
|
||||
param.add_char_descr.service_handle = p_data->add_result.service_id;
|
||||
bta_to_btc_uuid(¶m.add_char_descr.char_uuid, &p_data->add_result.char_uuid);
|
||||
|
||||
BTC_GATTS_CB_TO_APP(ESP_GATTS_ADD_CHAR_DESCR_EVT, ¶m);
|
||||
btc_gatts_cb_to_app(ESP_GATTS_ADD_CHAR_DESCR_EVT, gatts_if, ¶m);
|
||||
break;
|
||||
case BTA_GATTS_DELELTE_EVT:
|
||||
gatts_if = p_data->srvc_oper.server_if;
|
||||
param.del.status = p_data->srvc_oper.status;
|
||||
param.del.gatt_if = p_data->srvc_oper.server_if;
|
||||
param.del.service_handle = p_data->srvc_oper.service_id;
|
||||
|
||||
BTC_GATTS_CB_TO_APP(ESP_GATTS_DELETE_EVT, ¶m);
|
||||
btc_gatts_cb_to_app(ESP_GATTS_DELETE_EVT, gatts_if, ¶m);
|
||||
break;
|
||||
case BTA_GATTS_START_EVT:
|
||||
gatts_if = p_data->srvc_oper.server_if;
|
||||
param.start.status = p_data->srvc_oper.status;
|
||||
param.start.gatt_if = p_data->srvc_oper.server_if;
|
||||
param.start.service_handle = p_data->srvc_oper.service_id;
|
||||
|
||||
BTC_GATTS_CB_TO_APP(ESP_GATTS_START_EVT, ¶m);
|
||||
btc_gatts_cb_to_app(ESP_GATTS_START_EVT, gatts_if, ¶m);
|
||||
break;
|
||||
case BTA_GATTS_STOP_EVT:
|
||||
gatts_if = p_data->srvc_oper.server_if;
|
||||
param.stop.status = p_data->srvc_oper.status;
|
||||
param.stop.gatt_if = p_data->srvc_oper.server_if;
|
||||
param.stop.service_handle = p_data->srvc_oper.service_id;
|
||||
|
||||
BTC_GATTS_CB_TO_APP(ESP_GATTS_STOP_EVT, ¶m);
|
||||
btc_gatts_cb_to_app(ESP_GATTS_STOP_EVT, gatts_if, ¶m);
|
||||
break;
|
||||
case BTA_GATTS_CONNECT_EVT:
|
||||
param.connect.conn_id = p_data->conn.conn_id;
|
||||
param.connect.gatt_if = p_data->conn.server_if;
|
||||
gatts_if = p_data->conn.server_if;
|
||||
param.connect.conn_id = BTC_GATT_GET_CONN_ID(p_data->conn.conn_id);
|
||||
param.connect.is_connected = true;
|
||||
memcpy(param.connect.remote_bda, p_data->conn.remote_bda, ESP_BD_ADDR_LEN);
|
||||
|
||||
BTC_GATTS_CB_TO_APP(ESP_GATTS_CONNECT_EVT, ¶m);
|
||||
btc_gatts_cb_to_app(ESP_GATTS_CONNECT_EVT, gatts_if, ¶m);
|
||||
break;
|
||||
case BTA_GATTS_DISCONNECT_EVT:
|
||||
param.connect.conn_id = p_data->conn.conn_id;
|
||||
param.connect.gatt_if = p_data->conn.server_if;
|
||||
param.connect.is_connected = false;
|
||||
memcpy(param.connect.remote_bda, p_data->conn.remote_bda, ESP_BD_ADDR_LEN);
|
||||
gatts_if = p_data->conn.server_if;
|
||||
param.disconnect.conn_id = BTC_GATT_GET_CONN_ID(p_data->conn.conn_id);
|
||||
param.disconnect.is_connected = false;
|
||||
memcpy(param.disconnect.remote_bda, p_data->conn.remote_bda, ESP_BD_ADDR_LEN);
|
||||
|
||||
BTC_GATTS_CB_TO_APP(ESP_GATTS_DISCONNECT_EVT, ¶m);
|
||||
btc_gatts_cb_to_app(ESP_GATTS_DISCONNECT_EVT, gatts_if, ¶m);
|
||||
break;
|
||||
case BTA_GATTS_OPEN_EVT:
|
||||
// do nothing
|
||||
@ -422,8 +731,17 @@ void btc_gatts_cb_handler(btc_msg_t *msg)
|
||||
// do nothing
|
||||
break;
|
||||
case BTA_GATTS_CONGEST_EVT:
|
||||
param.congest.conn_id = p_data->congest.conn_id;
|
||||
gatts_if = BTC_GATT_GET_GATT_IF(p_data->congest.conn_id);
|
||||
param.congest.conn_id = BTC_GATT_GET_CONN_ID(p_data->congest.conn_id);
|
||||
param.congest.congested = p_data->congest.congested;
|
||||
btc_gatts_cb_to_app(ESP_GATTS_CONGEST_EVT, gatts_if, ¶m);
|
||||
break;
|
||||
case BTA_GATTS_SET_ATTR_VAL_EVT:
|
||||
gatts_if = p_data->attr_val.server_if;
|
||||
param.set_attr_val.srvc_handle = p_data->attr_val.service_id;
|
||||
param.set_attr_val.attr_handle = p_data->attr_val.attr_id;
|
||||
param.set_attr_val.status = p_data->attr_val.status;
|
||||
btc_gatts_cb_to_app(ESP_GATTS_SET_ATTR_VAL_EVT, gatts_if, ¶m);
|
||||
break;
|
||||
default:
|
||||
// do nothing
|
||||
|
@ -21,6 +21,10 @@
|
||||
#include "esp_gatt_defs.h"
|
||||
#include "esp_gattc_api.h"
|
||||
|
||||
#define BTC_GATT_CREATE_CONN_ID(gatt_if, conn_id) ((uint16_t) ((((uint8_t)(conn_id)) << 8) | ((uint8_t)(gatt_if))))
|
||||
#define BTC_GATT_GET_CONN_ID(conn_id) (((uint16_t)(conn_id)) >> 8)
|
||||
#define BTC_GATT_GET_GATT_IF(conn_id) ((uint8_t)(conn_id))
|
||||
|
||||
void btc128_to_bta_uuid(tBT_UUID *p_dest, uint8_t *p_src);
|
||||
void btc_to_bta_uuid(tBT_UUID *p_dest, esp_bt_uuid_t *p_src);
|
||||
void btc_to_bta_gatt_id(tBTA_GATT_ID *p_dest, esp_gatt_id_t *p_src);
|
||||
@ -31,6 +35,6 @@ void bta_to_btc_uuid(esp_bt_uuid_t *p_dest, tBT_UUID *p_src);
|
||||
void bta_to_btc_gatt_id(esp_gatt_id_t *p_dest, tBTA_GATT_ID *p_src);
|
||||
void bta_to_btc_srvc_id(esp_gatt_srvc_id_t *p_dest, tBTA_GATT_SRVC_ID *p_src);
|
||||
|
||||
uint16_t set_read_value(esp_ble_gattc_cb_param_t *p_dest, tBTA_GATTC_READ *p_src);
|
||||
uint16_t set_read_value(uint8_t *gattc_if, esp_ble_gattc_cb_param_t *p_dest, tBTA_GATTC_READ *p_src);
|
||||
|
||||
#endif /* __BTC_GATT_UTIL_H__*/
|
@ -51,11 +51,11 @@ typedef union {
|
||||
} app_reg;
|
||||
//BTC_GATTC_ACT_APP_UNREGISTER,
|
||||
struct app_unreg_arg {
|
||||
esp_gatt_if_t gatt_if;
|
||||
esp_gatt_if_t gattc_if;
|
||||
} app_unreg;
|
||||
//BTC_GATTC_ACT_OPEN,
|
||||
struct open_arg {
|
||||
esp_gatt_if_t gatt_if;
|
||||
esp_gatt_if_t gattc_if;
|
||||
esp_bd_addr_t remote_bda;
|
||||
bool is_direct;
|
||||
} open;
|
||||
@ -162,14 +162,14 @@ typedef union {
|
||||
} exec_write;
|
||||
//BTC_GATTC_ACT_REG_FOR_NOTIFY,
|
||||
struct reg_for_notify_arg {
|
||||
esp_gatt_if_t gatt_if;
|
||||
esp_gatt_if_t gattc_if;
|
||||
esp_bd_addr_t remote_bda;
|
||||
esp_gatt_srvc_id_t service_id;
|
||||
esp_gatt_id_t char_id;
|
||||
} reg_for_notify;
|
||||
//BTC_GATTC_ACT_UNREG_FOR_NOTIFY
|
||||
struct unreg_for_notify_arg {
|
||||
esp_gatt_if_t gatt_if;
|
||||
esp_gatt_if_t gattc_if;
|
||||
esp_bd_addr_t remote_bda;
|
||||
esp_gatt_srvc_id_t service_id;
|
||||
esp_gatt_id_t char_id;
|
||||
|
@ -24,6 +24,7 @@ typedef enum {
|
||||
BTC_GATTS_ACT_APP_REGISTER = 0,
|
||||
BTC_GATTS_ACT_APP_UNREGISTER,
|
||||
BTC_GATTS_ACT_CREATE_SERVICE,
|
||||
BTC_GATTS_ACT_CREATE_ATTR_TAB,
|
||||
BTC_GATTS_ACT_DELETE_SERVICE,
|
||||
BTC_GATTS_ACT_START_SERVICE,
|
||||
BTC_GATTS_ACT_STOP_SERVICE,
|
||||
@ -32,6 +33,7 @@ typedef enum {
|
||||
BTC_GATTS_ACT_ADD_CHAR_DESCR,
|
||||
BTC_GATTS_ACT_SEND_INDICATE,
|
||||
BTC_GATTS_ACT_SEND_RESPONSE,
|
||||
BTC_GATTS_ACT_SET_ATTR_VALUE,
|
||||
BTC_GATTS_ACT_OPEN,
|
||||
BTC_GATTS_ACT_CLOSE,
|
||||
} btc_gatts_act_t;
|
||||
@ -42,46 +44,67 @@ typedef union {
|
||||
struct app_reg_args {
|
||||
uint16_t app_id;
|
||||
} app_reg;
|
||||
|
||||
//BTC_GATTS_ACT_APP_UNREGISTER,
|
||||
struct app_unreg_args {
|
||||
esp_gatt_if_t gatt_if;
|
||||
esp_gatt_if_t gatts_if;
|
||||
} app_unreg;
|
||||
|
||||
//BTC_GATTS_ACT_CREATE_SERVICE,
|
||||
struct create_srvc_args {
|
||||
esp_gatt_if_t gatt_if;
|
||||
esp_gatt_if_t gatts_if;
|
||||
esp_gatt_srvc_id_t service_id;
|
||||
uint16_t num_handle;
|
||||
} create_srvc;
|
||||
|
||||
//BTC_GATTS_ACT_CREATE_ATTR_TAB
|
||||
struct create_attr_tab_args{
|
||||
esp_gatt_if_t gatts_if;
|
||||
uint8_t srvc_inst_id;
|
||||
uint8_t max_nb_attr;
|
||||
esp_gatts_attr_db_t *gatts_attr_db;
|
||||
}create_attr_tab;
|
||||
|
||||
//BTC_GATTS_ACT_DELETE_SERVICE,
|
||||
struct delete_srvc_args {
|
||||
uint16_t service_handle;
|
||||
} delete_srvc;
|
||||
|
||||
//BTC_GATTS_ACT_START_SERVICE,
|
||||
struct start_srvc_args {
|
||||
uint16_t service_handle;
|
||||
} start_srvc;
|
||||
|
||||
//BTC_GATTS_ACT_STOP_SERVICE,
|
||||
struct stop_srvc_args {
|
||||
uint16_t service_handle;
|
||||
} stop_srvc;
|
||||
|
||||
//BTC_GATTS_ACT_ADD_INCLUDE_SERVICE,
|
||||
struct add_incl_srvc_args {
|
||||
uint16_t service_handle;
|
||||
uint16_t included_service_handle;
|
||||
} add_incl_srvc;
|
||||
|
||||
//BTC_GATTS_ACT_ADD_CHAR,
|
||||
struct add_char_args {
|
||||
uint16_t service_handle;
|
||||
esp_bt_uuid_t char_uuid;
|
||||
esp_gatt_perm_t perm;
|
||||
esp_gatt_char_prop_t property;
|
||||
esp_attr_control_t attr_control;
|
||||
esp_attr_value_t char_val;
|
||||
} add_char;
|
||||
|
||||
//BTC_GATTS_ACT_ADD_CHAR_DESCR,
|
||||
struct add_descr_args {
|
||||
uint16_t service_handle;
|
||||
esp_bt_uuid_t descr_uuid;
|
||||
esp_gatt_perm_t perm;
|
||||
esp_attr_control_t attr_control;
|
||||
esp_attr_value_t descr_val;
|
||||
} add_descr;
|
||||
|
||||
//BTC_GATTS_ACT_SEND_INDICATE,
|
||||
struct send_indicate_args {
|
||||
uint16_t conn_id;
|
||||
@ -90,6 +113,7 @@ typedef union {
|
||||
uint16_t value_len;
|
||||
uint8_t *value;
|
||||
} send_ind;
|
||||
|
||||
//BTC_GATTS_ACT_SEND_RESPONSE,
|
||||
struct send_rsp_args {
|
||||
uint16_t conn_id;
|
||||
@ -97,21 +121,32 @@ typedef union {
|
||||
esp_gatt_status_t status;
|
||||
esp_gatt_rsp_t *rsp;
|
||||
} send_rsp;
|
||||
|
||||
//BTC_GATTS_SET_ATTR_VALUE
|
||||
struct set_attr_val_args{
|
||||
uint16_t length;
|
||||
uint8_t *value;
|
||||
} set_attr_val;
|
||||
|
||||
//BTC_GATTS_ACT_OPEN,
|
||||
struct open_args {
|
||||
esp_gatt_if_t gatt_if;
|
||||
esp_gatt_if_t gatts_if;
|
||||
esp_bd_addr_t remote_bda;
|
||||
bool is_direct;
|
||||
} open;
|
||||
|
||||
//BTC_GATTS_ACT_CLOSE,
|
||||
struct close_args {
|
||||
uint16_t conn_id;
|
||||
} close;
|
||||
|
||||
} btc_ble_gatts_args_t;
|
||||
|
||||
|
||||
void btc_gatts_call_handler(btc_msg_t *msg);
|
||||
void btc_gatts_cb_handler(btc_msg_t *msg);
|
||||
void btc_gatts_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src);
|
||||
void btc_gatts_get_attr_value(uint16_t attr_handle, uint16_t *length, uint8_t **value);
|
||||
|
||||
|
||||
#endif /* __BTC_GATTS_H__ */
|
||||
|
@ -92,7 +92,7 @@ typedef struct {
|
||||
** Static variables
|
||||
******************************************************************************/
|
||||
|
||||
static esp_profile_cb_t bt_av_sink_callback = NULL;
|
||||
static esp_a2d_cb_t bt_av_sink_callback = NULL;
|
||||
|
||||
static btif_av_cb_t btif_av_cb = {0};
|
||||
static TIMER_LIST_ENT tle_av_open_on_rc;
|
||||
@ -952,7 +952,7 @@ bt_status_t btif_av_init()
|
||||
* Returns bt_status_t
|
||||
*
|
||||
*/
|
||||
esp_err_t esp_a2d_register_callback(esp_profile_cb_t callback)
|
||||
esp_err_t esp_a2d_register_callback(esp_a2d_cb_t callback)
|
||||
{
|
||||
// TODO: need protection against race
|
||||
bt_av_sink_callback = callback;
|
||||
|
@ -314,7 +314,7 @@ bt_status_t btif_init_bluetooth(void)
|
||||
goto error_exit;
|
||||
}
|
||||
xBtifQueue = xQueueCreate(60, sizeof(void *));
|
||||
xTaskCreate(btif_task_thread_handler, "BtifT", 2048, NULL, configMAX_PRIORITIES - 1, &xBtifTaskHandle);
|
||||
xTaskCreatePinnedToCore(btif_task_thread_handler, "BtifT", 2048, NULL, configMAX_PRIORITIES - 1, &xBtifTaskHandle, 0);
|
||||
fixed_queue_register_dequeue(btif_msg_queue, bt_jni_msg_ready);
|
||||
|
||||
return BT_STATUS_SUCCESS;
|
||||
|
@ -421,7 +421,7 @@ bool btif_a2dp_start_media_task(void)
|
||||
if (xBtifMediaQueue == 0) {
|
||||
goto error_exit;
|
||||
}
|
||||
xTaskCreate(btif_media_task_handler, "BtifMediaT\n", 2048, NULL, configMAX_PRIORITIES - 1, &xBtifMediaTaskHandle);
|
||||
xTaskCreatePinnedToCore(btif_media_task_handler, "BtifMediaT\n", 2048, NULL, configMAX_PRIORITIES - 1, &xBtifMediaTaskHandle, 0);
|
||||
if (xBtifMediaTaskHandle == NULL) {
|
||||
goto error_exit;
|
||||
}
|
||||
|
@ -57,7 +57,7 @@ typedef struct {
|
||||
static hci_hal_env_t hci_hal_env;
|
||||
static const hci_hal_t interface;
|
||||
static const hci_hal_callbacks_t *callbacks;
|
||||
static const vhci_host_callback_t vhci_host_cb;
|
||||
static const esp_vhci_host_callback_t vhci_host_cb;
|
||||
|
||||
static xTaskHandle xHciH4TaskHandle;
|
||||
static xQueueHandle xHciH4Queue;
|
||||
@ -102,10 +102,10 @@ static bool hal_open(const hci_hal_callbacks_t *upper_callbacks)
|
||||
hci_hal_env_init(HCI_HAL_SERIAL_BUFFER_SIZE, SIZE_MAX);
|
||||
|
||||
xHciH4Queue = xQueueCreate(HCI_H4_QUEUE_NUM, sizeof(BtTaskEvt_t));
|
||||
xTaskCreate(hci_hal_h4_rx_handler, HCI_H4_TASK_NAME, HCI_H4_TASK_STACK_SIZE, NULL, HCI_H4_TASK_PRIO, &xHciH4TaskHandle);
|
||||
xTaskCreatePinnedToCore(hci_hal_h4_rx_handler, HCI_H4_TASK_NAME, HCI_H4_TASK_STACK_SIZE, NULL, HCI_H4_TASK_PRIO, &xHciH4TaskHandle, 0);
|
||||
|
||||
//register vhci host cb
|
||||
API_vhci_host_register_callback(&vhci_host_cb);
|
||||
esp_vhci_host_register_callback(&vhci_host_cb);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -147,7 +147,7 @@ static uint16_t transmit_data(serial_data_type_t type,
|
||||
BTTRC_DUMP_BUFFER("Transmit Pkt", data, length);
|
||||
|
||||
// TX Data to target
|
||||
API_vhci_host_send_packet(data, length);
|
||||
esp_vhci_host_send_packet(data, length);
|
||||
|
||||
// Be nice and restore the old value of that byte
|
||||
*(data) = previous_byte;
|
||||
@ -175,7 +175,7 @@ void hci_hal_h4_task_post(void)
|
||||
evt.sig = 0xff;
|
||||
evt.par = 0;
|
||||
|
||||
if (xQueueSend(xHciH4Queue, &evt, 10 / portTICK_RATE_MS) != pdTRUE) {
|
||||
if (xQueueSend(xHciH4Queue, &evt, 10 / portTICK_PERIOD_MS) != pdTRUE) {
|
||||
LOG_ERROR("xHciH4Queue failed\n");
|
||||
}
|
||||
}
|
||||
@ -273,7 +273,7 @@ static int host_recv_pkt_cb(uint8_t *data, uint16_t len)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const vhci_host_callback_t vhci_host_cb = {
|
||||
static const esp_vhci_host_callback_t vhci_host_cb = {
|
||||
.notify_host_send_available = host_send_pkt_available_cb,
|
||||
.notify_host_recv = host_recv_pkt_cb,
|
||||
};
|
||||
|
@ -109,7 +109,7 @@ int hci_start_up(void)
|
||||
}
|
||||
|
||||
xHciHostQueue = xQueueCreate(HCI_HOST_QUEUE_NUM, sizeof(BtTaskEvt_t));
|
||||
xTaskCreate(hci_host_thread_handler, HCI_HOST_TASK_NAME, HCI_HOST_TASK_STACK_SIZE, NULL, HCI_HOST_TASK_PRIO, &xHciHostTaskHandle);
|
||||
xTaskCreatePinnedToCore(hci_host_thread_handler, HCI_HOST_TASK_NAME, HCI_HOST_TASK_STACK_SIZE, NULL, HCI_HOST_TASK_PRIO, &xHciHostTaskHandle, 0);
|
||||
|
||||
packet_fragmenter->init(&packet_fragmenter_callbacks);
|
||||
hal->open(&hal_callbacks);
|
||||
@ -146,7 +146,7 @@ void hci_host_task_post(void)
|
||||
evt.sig = 0xff;
|
||||
evt.par = 0;
|
||||
|
||||
if (xQueueSend(xHciHostQueue, &evt, 10 / portTICK_RATE_MS) != pdTRUE) {
|
||||
if (xQueueSend(xHciHostQueue, &evt, 10 / portTICK_PERIOD_MS) != pdTRUE) {
|
||||
LOG_ERROR("xHciHostQueue failed\n");
|
||||
}
|
||||
}
|
||||
@ -226,7 +226,7 @@ static void hci_host_thread_handler(void *arg)
|
||||
for (;;) {
|
||||
if (pdTRUE == xQueueReceive(xHciHostQueue, &e, (portTickType)portMAX_DELAY)) {
|
||||
if (e.sig == 0xff) {
|
||||
if (API_vhci_host_check_send_available()) {
|
||||
if (esp_vhci_host_check_send_available()) {
|
||||
/*Now Target only allowed one packet per TX*/
|
||||
BT_HDR *pkt = packet_fragmenter->fragment_current_packet();
|
||||
if (pkt != NULL) {
|
||||
|
@ -32,7 +32,7 @@
|
||||
#define assert(x) do { if (!(x)) BT_PRINTF("bt host error %s %u\n", __FILE__, __LINE__); } while (0)
|
||||
#endif
|
||||
|
||||
inline void trc_dump_buffer(uint8_t *prefix, uint8_t *data, uint16_t len)
|
||||
inline void trc_dump_buffer(const char *prefix, uint8_t *data, uint16_t len)
|
||||
{
|
||||
uint16_t i;
|
||||
|
||||
@ -41,14 +41,13 @@ inline void trc_dump_buffer(uint8_t *prefix, uint8_t *data, uint16_t len)
|
||||
}
|
||||
|
||||
if (prefix) {
|
||||
BT_PRINTF("%s:\t", prefix);
|
||||
BT_PRINTF("%s: len %d\n", prefix, len);
|
||||
}
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
BT_PRINTF(" %02x", *(data + i));
|
||||
if (!((i + 1) & 0xf)) {
|
||||
BT_PRINTF("\n");
|
||||
}
|
||||
for (i = 0; i < len; i+=16) {
|
||||
BT_PRINTF("%02x, %02x, %02x, %02x, %02x, %02x, %02x, %02x, %02x, %02x, %02x, %02x, %02x, %02x, %02x, %02x\n",
|
||||
*(data + i), *(data + i + 1), *(data + i + 2), *(data + i + 3), *(data + i + 4), *(data + i + 5), *(data + i + 6), *(data + i + 7),
|
||||
*(data + i + 8), *(data + i + 9), *(data + i + 10), *(data + i + 11), *(data + i + 12), *(data + i + 13), *(data + i + 14), *(data + i + 15));
|
||||
}
|
||||
BT_PRINTF("\n");
|
||||
}
|
||||
|
@ -137,9 +137,9 @@ osi_sem_wait(osi_sem_t *sem, uint32_t timeout)
|
||||
StartTime = xTaskGetTickCount();
|
||||
|
||||
if (timeout != 0) {
|
||||
if (xSemaphoreTake(*sem, timeout / portTICK_RATE_MS) == pdTRUE) {
|
||||
if (xSemaphoreTake(*sem, timeout / portTICK_PERIOD_MS) == pdTRUE) {
|
||||
EndTime = xTaskGetTickCount();
|
||||
Elapsed = (EndTime - StartTime) * portTICK_RATE_MS;
|
||||
Elapsed = (EndTime - StartTime) * portTICK_PERIOD_MS;
|
||||
|
||||
if (Elapsed == 0) {
|
||||
Elapsed = 1;
|
||||
@ -153,7 +153,7 @@ osi_sem_wait(osi_sem_t *sem, uint32_t timeout)
|
||||
while (xSemaphoreTake(*sem, portMAX_DELAY) != pdTRUE);
|
||||
|
||||
EndTime = xTaskGetTickCount();
|
||||
Elapsed = (EndTime - StartTime) * portTICK_RATE_MS;
|
||||
Elapsed = (EndTime - StartTime) * portTICK_PERIOD_MS;
|
||||
|
||||
if (Elapsed == 0) {
|
||||
Elapsed = 1;
|
||||
@ -190,7 +190,7 @@ osi_now(void)
|
||||
|
||||
void osi_delay_ms(uint32_t ms)
|
||||
{
|
||||
vTaskDelay(ms / portTICK_RATE_MS);
|
||||
vTaskDelay(ms / portTICK_PERIOD_MS);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1089,7 +1089,6 @@ tBTM_STATUS BTM_BleSetAdvParamsStartAdv(UINT16 adv_int_min, UINT16 adv_int_max,
|
||||
p_cb->adv_chnl_map = chnl_map;
|
||||
p_addr_cb->own_addr_type = own_bda_type;
|
||||
p_cb->evt_type = adv_type;
|
||||
p_cb->adv_mode = BTM_BLE_ADV_ENABLE;
|
||||
p_cb->afp = afp;
|
||||
|
||||
if (p_dir_bda) {
|
||||
|
@ -201,7 +201,7 @@ void BTU_StartUp(void)
|
||||
}
|
||||
|
||||
xBtuQueue = xQueueCreate(BTU_QUEUE_NUM, sizeof(BtTaskEvt_t));
|
||||
xTaskCreate(btu_task_thread_handler, BTU_TASK_NAME, BTU_TASK_STACK_SIZE, NULL, BTU_TASK_PRIO, &xBtuTaskHandle);
|
||||
xTaskCreatePinnedToCore(btu_task_thread_handler, BTU_TASK_NAME, BTU_TASK_STACK_SIZE, NULL, BTU_TASK_PRIO, &xBtuTaskHandle, 0);
|
||||
btu_task_post(SIG_BTU_START_UP);
|
||||
/*
|
||||
// Continue startup on bt workqueue thread.
|
||||
|
@ -338,7 +338,7 @@ void btu_task_post(uint32_t sig)
|
||||
evt.sig = sig;
|
||||
evt.par = 0;
|
||||
|
||||
if (xQueueSend(xBtuQueue, &evt, 10 / portTICK_RATE_MS) != pdTRUE) {
|
||||
if (xQueueSend(xBtuQueue, &evt, 10 / portTICK_PERIOD_MS) != pdTRUE) {
|
||||
LOG_ERROR("xBtuQueue failed\n");
|
||||
}
|
||||
}
|
||||
|
@ -392,7 +392,8 @@ void gap_attr_db_init(void)
|
||||
*/
|
||||
uuid.len = LEN_UUID_16;
|
||||
uuid.uu.uuid16 = p_db_attr->uuid = GATT_UUID_GAP_DEVICE_NAME;
|
||||
p_db_attr->handle = GATTS_AddCharacteristic(service_handle, &uuid, GATT_PERM_READ, GATT_CHAR_PROP_BIT_READ);
|
||||
p_db_attr->handle = GATTS_AddCharacteristic(service_handle, &uuid, GATT_PERM_READ, GATT_CHAR_PROP_BIT_READ,
|
||||
NULL, NULL);
|
||||
p_db_attr ++;
|
||||
|
||||
/* add Icon characteristic
|
||||
@ -401,7 +402,8 @@ void gap_attr_db_init(void)
|
||||
p_db_attr->handle = GATTS_AddCharacteristic(service_handle,
|
||||
&uuid,
|
||||
GATT_PERM_READ,
|
||||
GATT_CHAR_PROP_BIT_READ);
|
||||
GATT_CHAR_PROP_BIT_READ,
|
||||
NULL, NULL);
|
||||
p_db_attr ++;
|
||||
|
||||
#if ((defined BTM_PERIPHERAL_ENABLED) && (BTM_PERIPHERAL_ENABLED == TRUE))
|
||||
@ -416,7 +418,8 @@ void gap_attr_db_init(void)
|
||||
p_db_attr->handle = GATTS_AddCharacteristic(service_handle,
|
||||
&uuid,
|
||||
GATT_PERM_READ,
|
||||
GATT_CHAR_PROP_BIT_READ);
|
||||
GATT_CHAR_PROP_BIT_READ,
|
||||
NULL, NULL);
|
||||
p_db_attr ++;
|
||||
#endif
|
||||
|
||||
@ -424,7 +427,8 @@ void gap_attr_db_init(void)
|
||||
uuid.len = LEN_UUID_16;
|
||||
uuid.uu.uuid16 = p_db_attr->uuid = GATT_UUID_GAP_CENTRAL_ADDR_RESOL;
|
||||
p_db_attr->handle = GATTS_AddCharacteristic(service_handle, &uuid,
|
||||
GATT_PERM_READ, GATT_CHAR_PROP_BIT_READ);
|
||||
GATT_PERM_READ, GATT_CHAR_PROP_BIT_READ,
|
||||
NULL, NULL);
|
||||
p_db_attr->attr_value.addr_resolution = 0;
|
||||
p_db_attr++;
|
||||
|
||||
|
@ -151,10 +151,10 @@ UINT16 GATTS_CreateService (tGATT_IF gatt_if, tBT_UUID *p_svc_uuid,
|
||||
tBT_UUID *p_app_uuid128;
|
||||
|
||||
|
||||
GATT_TRACE_API ("GATTS_CreateService" );
|
||||
GATT_TRACE_API ("GATTS_CreateService\n" );
|
||||
|
||||
if (p_reg == NULL) {
|
||||
GATT_TRACE_ERROR ("Inavlid gatt_if=%d", gatt_if);
|
||||
GATT_TRACE_ERROR ("Inavlid gatt_if=%d\n", gatt_if);
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -162,7 +162,7 @@ UINT16 GATTS_CreateService (tGATT_IF gatt_if, tBT_UUID *p_svc_uuid,
|
||||
|
||||
if ((p_list = gatt_find_hdl_buffer_by_app_id(p_app_uuid128, p_svc_uuid, svc_inst)) != NULL) {
|
||||
s_hdl = p_list->asgn_range.s_handle;
|
||||
GATT_TRACE_DEBUG ("Service already been created!!");
|
||||
GATT_TRACE_DEBUG ("Service already been created!!\n");
|
||||
} else {
|
||||
if ( (p_svc_uuid->len == LEN_UUID_16) && (p_svc_uuid->uu.uuid16 == UUID_SERVCLASS_GATT_SERVER)) {
|
||||
s_hdl = gatt_cb.hdl_cfg.gatt_start_hdl;
|
||||
@ -184,13 +184,13 @@ UINT16 GATTS_CreateService (tGATT_IF gatt_if, tBT_UUID *p_svc_uuid,
|
||||
|
||||
/* check for space */
|
||||
if (num_handles > (0xFFFF - s_hdl + 1)) {
|
||||
GATT_TRACE_ERROR ("GATTS_ReserveHandles: no handles, s_hdl: %u needed: %u", s_hdl, num_handles);
|
||||
GATT_TRACE_ERROR ("GATTS_ReserveHandles: no handles, s_hdl: %u needed: %u\n", s_hdl, num_handles);
|
||||
return (0);
|
||||
}
|
||||
|
||||
if ( (p_list = gatt_alloc_hdl_buffer()) == NULL) {
|
||||
/* No free entry */
|
||||
GATT_TRACE_ERROR ("GATTS_ReserveHandles: no free handle blocks");
|
||||
GATT_TRACE_ERROR ("GATTS_ReserveHandles: no free handle blocks\n");
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -210,7 +210,7 @@ UINT16 GATTS_CreateService (tGATT_IF gatt_if, tBT_UUID *p_svc_uuid,
|
||||
/* add a pending new service change item to the list */
|
||||
if ( (p_buf = gatt_add_pending_new_srv_start(&p_list->asgn_range)) == NULL) {
|
||||
/* No free entry */
|
||||
GATT_TRACE_ERROR ("gatt_add_pending_new_srv_start: no free blocks");
|
||||
GATT_TRACE_ERROR ("gatt_add_pending_new_srv_start: no free blocks\n");
|
||||
|
||||
if (p_list) {
|
||||
gatt_remove_an_item_from_list(p_list_info, p_list);
|
||||
@ -219,12 +219,12 @@ UINT16 GATTS_CreateService (tGATT_IF gatt_if, tBT_UUID *p_svc_uuid,
|
||||
return (0);
|
||||
}
|
||||
|
||||
GATT_TRACE_DEBUG ("Add a new srv chg item");
|
||||
GATT_TRACE_DEBUG ("Add a new srv chg item\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (!gatts_init_service_db(&p_list->svc_db, p_svc_uuid, is_pri, s_hdl , num_handles)) {
|
||||
GATT_TRACE_ERROR ("GATTS_ReserveHandles: service DB initialization failed");
|
||||
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_hdl_buffer(p_list);
|
||||
@ -236,12 +236,6 @@ UINT16 GATTS_CreateService (tGATT_IF gatt_if, tBT_UUID *p_svc_uuid,
|
||||
return (0);
|
||||
}
|
||||
|
||||
GATT_TRACE_DEBUG ("GATTS_CreateService(success): handles needed:%u s_hdl=%u e_hdl=%u %s[%x] is_primary=%d",
|
||||
num_handles, p_list->asgn_range.s_handle , p_list->asgn_range.e_handle,
|
||||
((p_list->asgn_range.svc_uuid.len == 2) ? "uuid16" : "uuid128" ),
|
||||
p_list->asgn_range.svc_uuid.uu.uuid16,
|
||||
p_list->asgn_range.is_primary);
|
||||
|
||||
return (s_hdl);
|
||||
}
|
||||
|
||||
@ -295,25 +289,27 @@ UINT16 GATTS_AddIncludeService (UINT16 service_handle, UINT16 include_svc_handle
|
||||
**
|
||||
*******************************************************************************/
|
||||
UINT16 GATTS_AddCharacteristic (UINT16 service_handle, tBT_UUID *p_char_uuid,
|
||||
tGATT_PERM perm, tGATT_CHAR_PROP property)
|
||||
tGATT_PERM perm, tGATT_CHAR_PROP property,
|
||||
tGATT_ATTR_VAL *attr_val, tGATTS_ATTR_CONTROL *control)
|
||||
{
|
||||
tGATT_HDL_LIST_ELEM *p_decl;
|
||||
|
||||
if ((p_decl = gatt_find_hdl_buffer_by_handle(service_handle)) == NULL) {
|
||||
GATT_TRACE_DEBUG("Service not created");
|
||||
GATT_TRACE_DEBUG("Service not created\n");
|
||||
return 0;
|
||||
}
|
||||
/* data validity checking */
|
||||
if ( ((property & GATT_CHAR_PROP_BIT_AUTH) && !(perm & GATT_WRITE_SIGNED_PERM)) ||
|
||||
((perm & GATT_WRITE_SIGNED_PERM) && !(property & GATT_CHAR_PROP_BIT_AUTH)) ) {
|
||||
GATT_TRACE_DEBUG("Invalid configuration property=0x%x perm=0x%x ", property, perm);
|
||||
GATT_TRACE_DEBUG("Invalid configuration property=0x%x perm=0x%x\n ", property, perm);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return gatts_add_characteristic(&p_decl->svc_db,
|
||||
perm,
|
||||
property,
|
||||
p_char_uuid);
|
||||
p_char_uuid,
|
||||
attr_val, control);
|
||||
}
|
||||
/*******************************************************************************
|
||||
**
|
||||
@ -336,7 +332,7 @@ UINT16 GATTS_AddCharacteristic (UINT16 service_handle, tBT_UUID *p_char_uuid,
|
||||
*******************************************************************************/
|
||||
UINT16 GATTS_AddCharDescriptor (UINT16 service_handle,
|
||||
tGATT_PERM perm,
|
||||
tBT_UUID *p_descr_uuid)
|
||||
tBT_UUID *p_descr_uuid, tGATT_ATTR_VAL *attr_val, tGATTS_ATTR_CONTROL *control)
|
||||
{
|
||||
tGATT_HDL_LIST_ELEM *p_decl;
|
||||
|
||||
@ -353,7 +349,8 @@ UINT16 GATTS_AddCharDescriptor (UINT16 service_handle,
|
||||
|
||||
return gatts_add_char_descr(&p_decl->svc_db,
|
||||
perm,
|
||||
p_descr_uuid);
|
||||
p_descr_uuid,
|
||||
attr_val, control);
|
||||
|
||||
}
|
||||
/*******************************************************************************
|
||||
@ -493,9 +490,9 @@ tGATT_STATUS GATTS_StartService (tGATT_IF gatt_if, UINT16 service_handle,
|
||||
|
||||
gatt_add_a_srv_to_list(&gatt_cb.srv_list_info, &gatt_cb.srv_list[i_sreg]);
|
||||
|
||||
GATT_TRACE_DEBUG ("allocated i_sreg=%d ", i_sreg);
|
||||
GATT_TRACE_DEBUG ("allocated i_sreg=%d\n", i_sreg);
|
||||
|
||||
GATT_TRACE_DEBUG ("s_hdl=%d e_hdl=%d type=0x%x svc_inst=%d sdp_hdl=0x%x",
|
||||
GATT_TRACE_DEBUG ("s_hdl=%d e_hdl=%d type=0x%x svc_inst=%d sdp_hdl=0x%x\n",
|
||||
p_sreg->s_hdl, p_sreg->e_hdl,
|
||||
p_sreg->type, p_sreg->service_instance,
|
||||
p_sreg->sdp_handle);
|
||||
@ -676,16 +673,16 @@ tGATT_STATUS GATTS_SendRsp (UINT16 conn_id, UINT32 trans_id,
|
||||
tGATT_REG *p_reg = gatt_get_regcb(gatt_if);
|
||||
tGATT_TCB *p_tcb = gatt_get_tcb_by_idx(tcb_idx);
|
||||
|
||||
GATT_TRACE_API ("GATTS_SendRsp: conn_id: %u trans_id: %u Status: 0x%04x",
|
||||
GATT_TRACE_API ("GATTS_SendRsp: conn_id: %u trans_id: %u Status: 0x%04x\n",
|
||||
conn_id, trans_id, status);
|
||||
|
||||
if ( (p_reg == NULL) || (p_tcb == NULL)) {
|
||||
GATT_TRACE_ERROR ("GATTS_SendRsp Unknown conn_id: %u ", conn_id);
|
||||
GATT_TRACE_ERROR ("GATTS_SendRsp Unknown conn_id: %u\n", conn_id);
|
||||
return (tGATT_STATUS) GATT_INVALID_CONN_ID;
|
||||
}
|
||||
|
||||
if (p_tcb->sr_cmd.trans_id != trans_id) {
|
||||
GATT_TRACE_ERROR ("GATTS_SendRsp conn_id: %u waiting for op_code = %02x",
|
||||
GATT_TRACE_ERROR ("GATTS_SendRsp conn_id: %u waiting for op_code = %02x\n",
|
||||
conn_id, p_tcb->sr_cmd.op_code);
|
||||
|
||||
return (GATT_WRONG_STATE);
|
||||
@ -696,6 +693,69 @@ tGATT_STATUS GATTS_SendRsp (UINT16 conn_id, UINT32 trans_id,
|
||||
return cmd_sent;
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function GATTS_SetAttributeValue
|
||||
**
|
||||
** Description This function sends to set the attribute value .
|
||||
**
|
||||
** Parameter attr_handle:the attribute handle
|
||||
** length: the attribute length
|
||||
** value: the value to be set to the attribute in the database
|
||||
**
|
||||
** Returns GATT_SUCCESS if successfully sent; otherwise error code.
|
||||
**
|
||||
*******************************************************************************/
|
||||
tGATT_STATUS GATTS_SetAttributeValue(UINT16 attr_handle, UINT16 length, UINT8 *value)
|
||||
{
|
||||
tGATT_STATUS status;
|
||||
tGATT_HDL_LIST_ELEM *p_decl = NULL;
|
||||
|
||||
GATT_TRACE_DEBUG("GATTS_SetAttributeValue: attr_handle: %u length: %u \n",
|
||||
attr_handle, length);
|
||||
|
||||
if ((p_decl = gatt_find_hdl_buffer_by_attr_handle(attr_handle)) == NULL) {
|
||||
GATT_TRACE_DEBUG("Service not created\n");
|
||||
return GATT_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
status = gatts_set_attribute_value(&p_decl->svc_db, attr_handle, length, value);
|
||||
return status;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function GATTS_GetAttributeValue
|
||||
**
|
||||
** Description This function sends to set the attribute value .
|
||||
**
|
||||
** Parameter attr_handle: the attribute handle
|
||||
** length:the attribute value length in the database
|
||||
** value: the attribute value out put
|
||||
**
|
||||
** Returns GATT_SUCCESS if successfully sent; otherwise error code.
|
||||
**
|
||||
*******************************************************************************/
|
||||
tGATT_STATUS GATTS_GetAttributeValue(UINT16 attr_handle, UINT16 *length, UINT8 **value)
|
||||
{
|
||||
tGATT_STATUS status;
|
||||
tGATT_HDL_LIST_ELEM *p_decl;
|
||||
|
||||
GATT_TRACE_DEBUG("GATTS_GetAttributeValue: attr_handle: %u\n",
|
||||
attr_handle);
|
||||
|
||||
if ((p_decl = gatt_find_hdl_buffer_by_attr_handle(attr_handle)) == NULL) {
|
||||
GATT_TRACE_ERROR("Service not created\n");
|
||||
return GATT_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
status = gatts_get_attribute_value(&p_decl->svc_db, attr_handle, length, value);
|
||||
return status;
|
||||
}
|
||||
|
||||
/*******************************************************************************/
|
||||
/* GATT Profile Srvr Functions */
|
||||
/*******************************************************************************/
|
||||
@ -1132,7 +1192,7 @@ tGATT_IF GATT_Register (tBT_UUID *p_app_uuid128, tGATT_CBACK *p_cb_info)
|
||||
break;
|
||||
}
|
||||
}
|
||||
GATT_TRACE_API ("allocated gatt_if=%d", gatt_if);
|
||||
GATT_TRACE_API ("allocated gatt_if=%d\n", gatt_if);
|
||||
return gatt_if;
|
||||
}
|
||||
|
||||
|
@ -279,21 +279,24 @@ void gatt_profile_db_init (void)
|
||||
GATT_StartIf(gatt_cb.gatt_if);
|
||||
|
||||
service_handle = GATTS_CreateService (gatt_cb.gatt_if , &uuid, 0, GATTP_MAX_ATTR_NUM, TRUE);
|
||||
GATT_TRACE_ERROR ("GATTS_CreateService: handle of service handle%x", service_handle);
|
||||
|
||||
/* add Service Changed characteristic
|
||||
*/
|
||||
uuid.uu.uuid16 = gatt_cb.gattp_attr.uuid = GATT_UUID_GATT_SRV_CHGD;
|
||||
gatt_cb.gattp_attr.service_change = 0;
|
||||
gatt_cb.gattp_attr.handle =
|
||||
gatt_cb.handle_of_h_r = GATTS_AddCharacteristic(service_handle, &uuid, 0, GATT_CHAR_PROP_BIT_INDICATE);
|
||||
gatt_cb.handle_of_h_r = GATTS_AddCharacteristic(service_handle, &uuid, 0, GATT_CHAR_PROP_BIT_INDICATE,
|
||||
NULL, NULL);
|
||||
|
||||
GATT_TRACE_DEBUG ("gatt_profile_db_init: handle of service changed%d",
|
||||
gatt_cb.handle_of_h_r );
|
||||
GATT_TRACE_DEBUG ("gatt_profile_db_init: handle of service changed%d\n",
|
||||
gatt_cb.handle_of_h_r);
|
||||
|
||||
/* start service
|
||||
*/
|
||||
status = GATTS_StartService (gatt_cb.gatt_if, service_handle, GATTP_TRANSPORT_SUPPORTED );
|
||||
|
||||
GATT_TRACE_DEBUG ("gatt_profile_db_init: gatt_if=%d start status%d",
|
||||
GATT_TRACE_DEBUG ("gatt_profile_db_init: gatt_if=%d start status%d\n",
|
||||
gatt_cb.gatt_if, status);
|
||||
}
|
||||
|
||||
|
@ -45,7 +45,7 @@ static BOOLEAN copy_extra_byte_in_db(tGATT_SVC_DB *p_db, void **p_dst, UINT16 le
|
||||
|
||||
static BOOLEAN gatts_db_add_service_declaration(tGATT_SVC_DB *p_db, tBT_UUID *p_service, BOOLEAN is_pri);
|
||||
static tGATT_STATUS gatts_send_app_read_request(tGATT_TCB *p_tcb, UINT8 op_code,
|
||||
UINT16 handle, UINT16 offset, UINT32 trans_id);
|
||||
UINT16 handle, UINT16 offset, UINT32 trans_id, BOOLEAN need_rsp);
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
@ -65,12 +65,12 @@ BOOLEAN gatts_init_service_db (tGATT_SVC_DB *p_db, tBT_UUID *p_service, BOOLEAN
|
||||
GKI_init_q(&p_db->svc_buffer);
|
||||
|
||||
if (!allocate_svc_db_buf(p_db)) {
|
||||
GATT_TRACE_ERROR("gatts_init_service_db failed, no resources");
|
||||
GATT_TRACE_ERROR("gatts_init_service_db failed, no resources\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
GATT_TRACE_DEBUG("gatts_init_service_db");
|
||||
GATT_TRACE_DEBUG("s_hdl = %d num_handle = %d", s_hdl, num_handle );
|
||||
GATT_TRACE_DEBUG("gatts_init_service_db\n");
|
||||
GATT_TRACE_DEBUG("s_hdl = %d num_handle = %d\n", s_hdl, num_handle );
|
||||
|
||||
/* update service database information */
|
||||
p_db->next_handle = s_hdl;
|
||||
@ -94,7 +94,7 @@ BOOLEAN gatts_init_service_db (tGATT_SVC_DB *p_db, tBT_UUID *p_service, BOOLEAN
|
||||
tBT_UUID *gatts_get_service_uuid (tGATT_SVC_DB *p_db)
|
||||
{
|
||||
if (!p_db || !p_db->p_attr_list) {
|
||||
GATT_TRACE_ERROR("service DB empty");
|
||||
GATT_TRACE_ERROR("service DB empty\n");
|
||||
|
||||
return NULL;
|
||||
} else {
|
||||
@ -127,28 +127,28 @@ static tGATT_STATUS gatts_check_attr_readability(tGATT_ATTR16 *p_attr,
|
||||
}
|
||||
|
||||
if (!(perm & GATT_READ_ALLOWED)) {
|
||||
GATT_TRACE_ERROR( "GATT_READ_NOT_PERMIT");
|
||||
GATT_TRACE_ERROR( "GATT_READ_NOT_PERMIT\n");
|
||||
return GATT_READ_NOT_PERMIT;
|
||||
}
|
||||
|
||||
if ((perm & GATT_READ_AUTH_REQUIRED ) && !(sec_flag & GATT_SEC_FLAG_LKEY_UNAUTHED) &&
|
||||
!(sec_flag & BTM_SEC_FLAG_ENCRYPTED)) {
|
||||
GATT_TRACE_ERROR( "GATT_INSUF_AUTHENTICATION");
|
||||
GATT_TRACE_ERROR( "GATT_INSUF_AUTHENTICATION\n");
|
||||
return GATT_INSUF_AUTHENTICATION;
|
||||
}
|
||||
|
||||
if ((perm & GATT_READ_MITM_REQUIRED ) && !(sec_flag & GATT_SEC_FLAG_LKEY_AUTHED)) {
|
||||
GATT_TRACE_ERROR( "GATT_INSUF_AUTHENTICATION: MITM Required");
|
||||
GATT_TRACE_ERROR( "GATT_INSUF_AUTHENTICATION: MITM Required\n");
|
||||
return GATT_INSUF_AUTHENTICATION;
|
||||
}
|
||||
|
||||
if ((perm & GATT_READ_ENCRYPTED_REQUIRED ) && !(sec_flag & GATT_SEC_FLAG_ENCRYPTED)) {
|
||||
GATT_TRACE_ERROR( "GATT_INSUF_ENCRYPTION");
|
||||
GATT_TRACE_ERROR( "GATT_INSUF_ENCRYPTION\n");
|
||||
return GATT_INSUF_ENCRYPTION;
|
||||
}
|
||||
|
||||
if ( (perm & GATT_READ_ENCRYPTED_REQUIRED) && (sec_flag & GATT_SEC_FLAG_ENCRYPTED) && (key_size < min_key_size)) {
|
||||
GATT_TRACE_ERROR( "GATT_INSUF_KEY_SIZE");
|
||||
GATT_TRACE_ERROR( "GATT_INSUF_KEY_SIZE\n");
|
||||
return GATT_INSUF_KEY_SIZE;
|
||||
}
|
||||
|
||||
@ -163,7 +163,7 @@ static tGATT_STATUS gatts_check_attr_readability(tGATT_ATTR16 *p_attr,
|
||||
case GATT_UUID_CHAR_CLIENT_CONFIG:
|
||||
case GATT_UUID_CHAR_SRVR_CONFIG:
|
||||
case GATT_UUID_CHAR_PRESENT_FORMAT:
|
||||
GATT_TRACE_ERROR("GATT_NOT_LONG");
|
||||
GATT_TRACE_ERROR("GATT_NOT_LONG\n");
|
||||
return GATT_NOT_LONG;
|
||||
|
||||
default:
|
||||
@ -206,7 +206,7 @@ static tGATT_STATUS read_attr_value (void *p_attr,
|
||||
tGATT_STATUS status;
|
||||
tGATT_ATTR16 *p_attr16 = (tGATT_ATTR16 *)p_attr;
|
||||
|
||||
GATT_TRACE_DEBUG("read_attr_value uuid=0x%04x perm=0x%0x sec_flag=0x%x offset=%d read_long=%d",
|
||||
GATT_TRACE_DEBUG("read_attr_value uuid=0x%04x perm=0x%0x sec_flag=0x%x offset=%d read_long=%d\n",
|
||||
p_attr16->uuid,
|
||||
p_attr16->permission,
|
||||
sec_flag,
|
||||
@ -268,8 +268,19 @@ 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);
|
||||
}
|
||||
status = GATT_STACK_RSP;
|
||||
|
||||
} else {
|
||||
status = GATT_PENDING;
|
||||
}
|
||||
}
|
||||
|
||||
*p_len = len;
|
||||
*p_data = p;
|
||||
@ -341,8 +352,9 @@ tGATT_STATUS gatts_db_read_attr_value_by_type (tGATT_TCB *p_tcb,
|
||||
|
||||
status = read_attr_value ((void *)p_attr, 0, &p, FALSE, (UINT16)(*p_len - 2), &len, sec_flag, key_size);
|
||||
|
||||
if (status == GATT_PENDING) {
|
||||
status = gatts_send_app_read_request(p_tcb, op_code, p_attr->handle, 0, trans_id);
|
||||
if (status == GATT_PENDING || status == GATT_STACK_RSP) {
|
||||
BOOLEAN need_rsp = (status != GATT_STACK_RSP);
|
||||
status = gatts_send_app_read_request(p_tcb, op_code, p_attr->handle, 0, trans_id, need_rsp);
|
||||
|
||||
/* one callback at a time */
|
||||
break;
|
||||
@ -445,12 +457,12 @@ UINT16 gatts_add_included_service (tGATT_SVC_DB *p_db, UINT16 s_handle, UINT16 e
|
||||
*******************************************************************************/
|
||||
UINT16 gatts_add_characteristic (tGATT_SVC_DB *p_db, tGATT_PERM perm,
|
||||
tGATT_CHAR_PROP property,
|
||||
tBT_UUID *p_char_uuid)
|
||||
tBT_UUID *p_char_uuid, tGATT_ATTR_VAL *attr_val, tGATTS_ATTR_CONTROL *control)
|
||||
{
|
||||
tGATT_ATTR16 *p_char_decl, *p_char_val;
|
||||
tBT_UUID uuid = {LEN_UUID_16, {GATT_UUID_CHAR_DECLARE}};
|
||||
|
||||
GATT_TRACE_DEBUG("gatts_add_characteristic perm=0x%0x property=0x%0x", perm, property);
|
||||
GATT_TRACE_DEBUG("gatts_add_characteristic perm=0x%0x property=0x%0x\n", perm, property);
|
||||
|
||||
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))) {
|
||||
@ -467,8 +479,30 @@ UINT16 gatts_add_characteristic (tGATT_SVC_DB *p_db, tGATT_PERM perm,
|
||||
|
||||
p_char_decl->p_value->char_decl.property = property;
|
||||
p_char_decl->p_value->char_decl.char_val_handle = p_char_val->handle;
|
||||
if (control != NULL) {
|
||||
p_char_val->control.auto_rsp = control->auto_rsp;
|
||||
} else {
|
||||
p_char_val->control.auto_rsp = GATT_RSP_DEFAULT;
|
||||
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
GATT_TRACE_DEBUG("attr_val->attr_len = %x, attr_val->attr_max_len = %x\n", attr_val->attr_len, attr_val->attr_max_len);
|
||||
GATT_TRACE_DEBUG("attribute handle = %x\n", p_char_val->handle);
|
||||
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);
|
||||
}
|
||||
} else {
|
||||
p_char_val->p_value = NULL;
|
||||
}
|
||||
|
||||
return p_char_val->handle;
|
||||
}
|
||||
@ -542,24 +576,227 @@ UINT8 gatt_convertchar_descr_type(tBT_UUID *p_descr_uuid)
|
||||
**
|
||||
*******************************************************************************/
|
||||
UINT16 gatts_add_char_descr (tGATT_SVC_DB *p_db, tGATT_PERM perm,
|
||||
tBT_UUID *p_descr_uuid)
|
||||
tBT_UUID *p_descr_uuid, tGATT_ATTR_VAL *attr_val, tGATTS_ATTR_CONTROL *control)
|
||||
{
|
||||
tGATT_ATTR16 *p_char_dscptr;
|
||||
|
||||
GATT_TRACE_DEBUG("gatts_add_char_descr uuid=0x%04x", p_descr_uuid->uu.uuid16);
|
||||
GATT_TRACE_DEBUG("gatts_add_char_descr uuid=0x%04x\n", p_descr_uuid->uu.uuid16);
|
||||
|
||||
/* Add characteristic descriptors */
|
||||
if ((p_char_dscptr = (tGATT_ATTR16 *)allocate_attr_in_db(p_db,
|
||||
p_descr_uuid,
|
||||
perm))
|
||||
== NULL) {
|
||||
if ((p_char_dscptr = (tGATT_ATTR16 *)allocate_attr_in_db(p_db, p_descr_uuid, perm)) == NULL) {
|
||||
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;
|
||||
}
|
||||
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);
|
||||
return 0;
|
||||
}
|
||||
p_char_dscptr->p_value->attr_val.attr_len = attr_val->attr_len;
|
||||
p_char_dscptr->p_value->attr_val.attr_max_len = attr_val->attr_max_len;
|
||||
if (attr_val->attr_val != NULL) {
|
||||
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);
|
||||
memcpy(p_char_dscptr->p_value->attr_val.attr_val, attr_val->attr_val, attr_val->attr_len);
|
||||
}
|
||||
}
|
||||
}
|
||||
return p_char_dscptr->handle;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function gatts_set_attribute_value
|
||||
**
|
||||
** Description This function add the attribute value in the database
|
||||
**
|
||||
** Parameter p_db: database pointer.
|
||||
** attr_handle: the attribute handle
|
||||
** length: the attribute value length
|
||||
** value: the pointer to the data to be set to the attribute value in the database
|
||||
**
|
||||
** Returns Status of the operation.
|
||||
**
|
||||
*******************************************************************************/
|
||||
tGATT_STATUS gatts_set_attribute_value(tGATT_SVC_DB *p_db, UINT16 attr_handle,
|
||||
UINT16 length, UINT8 *value)
|
||||
{
|
||||
tGATT_ATTR16 *p_cur;
|
||||
|
||||
if (p_db == NULL) {
|
||||
GATT_TRACE_DEBUG("gatts_set_attribute_value Fail:p_db is NULL.\n");
|
||||
return GATT_INVALID_PDU;
|
||||
}
|
||||
if (p_db->p_attr_list == NULL) {
|
||||
GATT_TRACE_DEBUG("gatts_set_attribute_value Fail:p_db->p_attr_list is NULL.\n");
|
||||
return GATT_INVALID_PDU;
|
||||
}
|
||||
|
||||
p_cur = (tGATT_ATTR16 *) p_db->p_attr_list;
|
||||
|
||||
while (p_cur != NULL) {
|
||||
if (p_cur->handle == attr_handle) {
|
||||
|
||||
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->attr_val.attr_max_len < length) {
|
||||
GATT_TRACE_ERROR("gatts_set_attribute_vaule failt: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;
|
||||
}
|
||||
} else {
|
||||
if (p_cur->p_value->attr_val.attr_max_len < length) {
|
||||
GATT_TRACE_ERROR("gatts_set_attribute_vaule failt:Invalid value length");
|
||||
} 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
|
||||
**
|
||||
** Description This function get the attribute value in the database
|
||||
**
|
||||
** Parameter p_db: database pointer.
|
||||
** attr_handle: the attribute handle
|
||||
** length: the attribute value length
|
||||
** value: the pointer to the data to be get to the attribute value in the database
|
||||
**
|
||||
** Returns Status of the operation.
|
||||
**
|
||||
*******************************************************************************/
|
||||
tGATT_STATUS gatts_get_attribute_value(tGATT_SVC_DB *p_db, UINT16 attr_handle,
|
||||
UINT16 *length, UINT8 **value)
|
||||
{
|
||||
tGATT_ATTR16 *p_cur;
|
||||
GATT_TRACE_DEBUG("***********%s*************\n", __func__);
|
||||
GATT_TRACE_DEBUG("attr_handle = %x\n", attr_handle);
|
||||
if (p_db == NULL) {
|
||||
GATT_TRACE_ERROR("gatts_get_attribute_value Fail:p_db is NULL.\n");
|
||||
return GATT_INVALID_PDU;
|
||||
}
|
||||
if (p_db->p_attr_list == NULL) {
|
||||
GATT_TRACE_ERROR("gatts_get_attribute_value Fail:p_db->p_attr_list is NULL.\n");
|
||||
return GATT_INVALID_PDU;
|
||||
}
|
||||
|
||||
p_cur = (tGATT_ATTR16 *) p_db->p_attr_list;
|
||||
|
||||
while (p_cur != NULL) {
|
||||
LOG_ERROR("p_ur->handle = %x\n", p_cur->handle);
|
||||
if (p_cur->handle == attr_handle) {
|
||||
|
||||
if (p_cur->uuid_type == GATT_ATTR_UUID_TYPE_16) {
|
||||
switch (p_cur->uuid) {
|
||||
case GATT_UUID_CHAR_DECLARE:
|
||||
case GATT_UUID_INCLUDE_SERVICE:
|
||||
break;
|
||||
default:
|
||||
if (p_cur->p_value->attr_val.attr_len != 0) {
|
||||
*length = p_cur->p_value->attr_val.attr_len;
|
||||
*value = p_cur->p_value->attr_val.attr_val;
|
||||
return GATT_SUCCESS;
|
||||
} else {
|
||||
GATT_TRACE_ERROR("gatts_get_attribute_vaule failt:the value length is 0");
|
||||
return GATT_INVALID_ATTR_LEN;
|
||||
}
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (p_cur->p_value->attr_val.attr_len != 0) {
|
||||
*length = p_cur->p_value->attr_val.attr_len;
|
||||
*value = p_cur->p_value->attr_val.attr_val;
|
||||
return GATT_SUCCESS;
|
||||
} else {
|
||||
GATT_TRACE_ERROR("gatts_get_attribute_vaule failed:the value length is 0");
|
||||
return GATT_INVALID_ATTR_LEN;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
|
||||
p_cur = p_cur->p_next;
|
||||
}
|
||||
|
||||
return GATT_NOT_FOUND;
|
||||
}
|
||||
|
||||
BOOLEAN gatts_is_auto_response(UINT16 attr_handle)
|
||||
{
|
||||
tGATT_HDL_LIST_ELEM *p_decl = NULL;
|
||||
BOOLEAN rsp = FALSE;
|
||||
tGATT_SVC_DB *p_db = NULL;
|
||||
if ((p_decl = gatt_find_hdl_buffer_by_attr_handle(attr_handle)) == NULL) {
|
||||
GATT_TRACE_DEBUG("Service not created\n");
|
||||
return rsp;
|
||||
}
|
||||
|
||||
p_db = &p_decl->svc_db;
|
||||
|
||||
tGATT_ATTR16 *p_cur, *p_next;
|
||||
|
||||
if (p_db == NULL) {
|
||||
GATT_TRACE_DEBUG("gatts_get_attribute_value Fail:p_db is NULL.\n");
|
||||
return rsp;
|
||||
}
|
||||
if (p_db->p_attr_list == NULL) {
|
||||
GATT_TRACE_DEBUG("gatts_get_attribute_value Fail:p_db->p_attr_list is NULL.\n");
|
||||
return rsp;
|
||||
}
|
||||
|
||||
p_cur = (tGATT_ATTR16 *) p_db->p_attr_list;
|
||||
p_next = (tGATT_ATTR16 *) p_cur->p_next;
|
||||
|
||||
for (; p_cur != NULL && p_next != NULL;
|
||||
p_cur = p_next, p_next = (tGATT_ATTR16 *)p_next->p_next) {
|
||||
if (p_cur->handle == attr_handle) {
|
||||
if (p_cur->p_value != NULL && p_cur->control.auto_rsp == GATT_RSP_BY_STACK) {
|
||||
rsp = true;
|
||||
return rsp;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return rsp;
|
||||
|
||||
}
|
||||
|
||||
/*******************************************************************************/
|
||||
/* Service Attribute Database Query Utility Functions */
|
||||
/*******************************************************************************/
|
||||
@ -605,8 +842,9 @@ tGATT_STATUS gatts_read_attr_value_by_handle(tGATT_TCB *p_tcb,
|
||||
(BOOLEAN)(op_code == GATT_REQ_READ_BLOB),
|
||||
mtu, p_len, sec_flag, key_size);
|
||||
|
||||
if (status == GATT_PENDING) {
|
||||
status = gatts_send_app_read_request(p_tcb, op_code, p_attr->handle, offset, trans_id);
|
||||
if ((status == GATT_PENDING) || (status == GATT_STACK_RSP)) {
|
||||
BOOLEAN need_rsp = (status != GATT_STACK_RSP);
|
||||
status = gatts_send_app_read_request(p_tcb, op_code, p_attr->handle, offset, trans_id, need_rsp);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -614,6 +852,42 @@ tGATT_STATUS gatts_read_attr_value_by_handle(tGATT_TCB *p_tcb,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
tGATT_STATUS gatts_write_attr_value_by_handle(tGATT_SVC_DB *p_db,
|
||||
UINT16 handle, UINT16 offset,
|
||||
UINT8 *p_value, UINT16 len)
|
||||
{
|
||||
tGATT_STATUS status = GATT_NOT_FOUND;
|
||||
tGATT_ATTR16 *p_attr;
|
||||
|
||||
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 ) {
|
||||
if (p_attr->control.auto_rsp == GATT_RSP_BY_APP) {
|
||||
return GATT_APP_RSP;
|
||||
}
|
||||
|
||||
if (p_attr->p_value != NULL && (p_attr->p_value->attr_val.attr_max_len >=
|
||||
offset + len)) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
p_attr = (tGATT_ATTR16 *)p_attr->p_next;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
@ -661,6 +935,8 @@ tGATT_STATUS gatts_read_attr_perm_check(tGATT_SVC_DB *p_db,
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function gatts_write_attr_perm_check
|
||||
@ -835,7 +1111,7 @@ static void *allocate_attr_in_db(tGATT_SVC_DB *p_db, tBT_UUID *p_uuid, tGATT_PER
|
||||
UINT16 len = sizeof(tGATT_ATTR128);
|
||||
|
||||
if (p_uuid == NULL) {
|
||||
GATT_TRACE_ERROR("illegal UUID");
|
||||
GATT_TRACE_ERROR("illegal UUID\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -845,17 +1121,17 @@ static void *allocate_attr_in_db(tGATT_SVC_DB *p_db, tBT_UUID *p_uuid, tGATT_PER
|
||||
len = sizeof(tGATT_ATTR32);
|
||||
}
|
||||
|
||||
GATT_TRACE_DEBUG("allocate attr %d bytes ", len);
|
||||
GATT_TRACE_DEBUG("allocate attr %d bytes\n", len);
|
||||
|
||||
if (p_db->end_handle <= p_db->next_handle) {
|
||||
GATT_TRACE_DEBUG("handle space full. handle_max = %d next_handle = %d",
|
||||
GATT_TRACE_DEBUG("handle space full. handle_max = %d next_handle = %d\n",
|
||||
p_db->end_handle, p_db->next_handle);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (p_db->mem_free < len) {
|
||||
if (!allocate_svc_db_buf(p_db)) {
|
||||
GATT_TRACE_ERROR("allocate_attr_in_db failed, no resources");
|
||||
GATT_TRACE_ERROR("allocate_attr_in_db failed, no resources\n");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
@ -896,19 +1172,21 @@ static void *allocate_attr_in_db(tGATT_SVC_DB *p_db, tBT_UUID *p_uuid, tGATT_PER
|
||||
}
|
||||
|
||||
if (p_attr16->uuid_type == GATT_ATTR_UUID_TYPE_16) {
|
||||
GATT_TRACE_DEBUG("=====> handle = [0x%04x] uuid16 = [0x%04x] perm=0x%02x ",
|
||||
GATT_TRACE_DEBUG("=====> handle = [0x%04x] uuid16 = [0x%04x] perm=0x%02x\n",
|
||||
p_attr16->handle, p_attr16->uuid, p_attr16->permission);
|
||||
} else if (p_attr16->uuid_type == GATT_ATTR_UUID_TYPE_32) {
|
||||
GATT_TRACE_DEBUG("=====> handle = [0x%04x] uuid32 = [0x%08x] perm=0x%02x ",
|
||||
GATT_TRACE_DEBUG("=====> handle = [0x%04x] uuid32 = [0x%08x] perm=0x%02x\n",
|
||||
p_attr32->handle, p_attr32->uuid, p_attr32->permission);
|
||||
} else {
|
||||
GATT_TRACE_DEBUG("=====> handle = [0x%04x] uuid128 = [0x%02x:0x%02x] perm=0x%02x ",
|
||||
GATT_TRACE_DEBUG("=====> handle = [0x%04x] uuid128 = [0x%02x:0x%02x] perm=0x%02x\n",
|
||||
p_attr128->handle, p_attr128->uuid[0], p_attr128->uuid[1],
|
||||
p_attr128->permission);
|
||||
}
|
||||
return (void *)p_attr16;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function deallocate_attr_in_db
|
||||
@ -974,7 +1252,7 @@ static BOOLEAN copy_extra_byte_in_db(tGATT_SVC_DB *p_db, void **p_dst, UINT16 le
|
||||
|
||||
if (p_db->mem_free < len) {
|
||||
if (!allocate_svc_db_buf(p_db)) {
|
||||
GATT_TRACE_ERROR("copy_extra_byte_in_db failed, no resources");
|
||||
GATT_TRACE_ERROR("copy_extra_byte_in_db failed, no resources\n");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
@ -1028,7 +1306,7 @@ static BOOLEAN allocate_svc_db_buf(tGATT_SVC_DB *p_db)
|
||||
**
|
||||
*******************************************************************************/
|
||||
static tGATT_STATUS gatts_send_app_read_request(tGATT_TCB *p_tcb, UINT8 op_code,
|
||||
UINT16 handle, UINT16 offset, UINT32 trans_id)
|
||||
UINT16 handle, UINT16 offset, UINT32 trans_id, BOOLEAN need_rsp)
|
||||
{
|
||||
tGATTS_DATA sr_data;
|
||||
UINT8 i_rcb;
|
||||
@ -1050,6 +1328,7 @@ static tGATT_STATUS gatts_send_app_read_request(tGATT_TCB *p_tcb, UINT8 op_code,
|
||||
sr_data.read_req.handle = handle;
|
||||
sr_data.read_req.is_long = (BOOLEAN)(op_code == GATT_REQ_READ_BLOB);
|
||||
sr_data.read_req.offset = offset;
|
||||
sr_data.read_req.need_rsp = need_rsp;
|
||||
|
||||
gatt_sr_send_req_callback(conn_id,
|
||||
trans_id, GATTS_REQ_TYPE_READ, &sr_data);
|
||||
|
@ -508,7 +508,7 @@ static void gatt_le_data_ind (UINT16 chan, BD_ADDR bd_addr, BT_HDR *p_buf)
|
||||
GKI_freebuf (p_buf);
|
||||
|
||||
if (p_tcb != NULL) {
|
||||
GATT_TRACE_WARNING ("ATT - Ignored L2CAP data while in state: %d",
|
||||
GATT_TRACE_WARNING ("ATT - Ignored L2CAP data while in state: %d\n",
|
||||
gatt_get_ch_state(p_tcb));
|
||||
}
|
||||
}
|
||||
@ -906,10 +906,10 @@ void gatt_data_process (tGATT_TCB *p_tcb, BT_HDR *p_buf)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
GATT_TRACE_ERROR ("ATT - Rcvd L2CAP data, unknown cmd: 0x%x", op_code);
|
||||
GATT_TRACE_ERROR ("ATT - Rcvd L2CAP data, unknown cmd: 0x%x\n", op_code);
|
||||
}
|
||||
} else {
|
||||
GATT_TRACE_ERROR ("invalid data length, ignore");
|
||||
GATT_TRACE_ERROR ("invalid data length, ignore\n");
|
||||
}
|
||||
|
||||
GKI_freebuf (p_buf);
|
||||
|
@ -239,7 +239,7 @@ tGATT_STATUS gatt_sr_process_app_rsp (tGATT_TCB *p_tcb, tGATT_IF gatt_if,
|
||||
tGATT_STATUS ret_code = GATT_SUCCESS;
|
||||
UNUSED(trans_id);
|
||||
|
||||
GATT_TRACE_DEBUG("gatt_sr_process_app_rsp gatt_if=%d", gatt_if);
|
||||
GATT_TRACE_DEBUG("gatt_sr_process_app_rsp gatt_if=%d\n", gatt_if);
|
||||
|
||||
gatt_sr_update_cback_cnt(p_tcb, gatt_if, FALSE, FALSE);
|
||||
|
||||
@ -264,7 +264,7 @@ tGATT_STATUS gatt_sr_process_app_rsp (tGATT_TCB *p_tcb, tGATT_IF gatt_if,
|
||||
if (p_tcb->sr_cmd.p_rsp_msg == NULL) {
|
||||
p_tcb->sr_cmd.p_rsp_msg = attp_build_sr_msg (p_tcb, (UINT8)(op_code + 1), (tGATT_SR_MSG *)p_msg);
|
||||
} else {
|
||||
GATT_TRACE_ERROR("Exception!!! already has respond message");
|
||||
GATT_TRACE_ERROR("Exception!!! already has respond message\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -279,7 +279,7 @@ tGATT_STATUS gatt_sr_process_app_rsp (tGATT_TCB *p_tcb, tGATT_IF gatt_if,
|
||||
gatt_dequeue_sr_cmd(p_tcb);
|
||||
}
|
||||
|
||||
GATT_TRACE_DEBUG("gatt_sr_process_app_rsp ret_code=%d", ret_code);
|
||||
GATT_TRACE_DEBUG("gatt_sr_process_app_rsp ret_code=%d\n", ret_code);
|
||||
|
||||
return ret_code;
|
||||
}
|
||||
@ -371,7 +371,7 @@ void gatt_process_read_multi_req (tGATT_TCB *p_tcb, UINT8 op_code, UINT16 len, U
|
||||
|
||||
#if GATT_CONFORMANCE_TESTING == TRUE
|
||||
if (gatt_cb.enable_err_rsp && gatt_cb.req_op_code == op_code) {
|
||||
GATT_TRACE_DEBUG("Conformance tst: forced err rspvofr ReadMultiple: error status=%d", gatt_cb.err_status);
|
||||
GATT_TRACE_DEBUG("Conformance tst: forced err rspvofr ReadMultiple: error status=%d\n", gatt_cb.err_status);
|
||||
|
||||
STREAM_TO_UINT16(handle, p);
|
||||
|
||||
@ -889,10 +889,10 @@ void gatts_process_read_by_type_req(tGATT_TCB *p_tcb, UINT8 op_code, UINT16 len,
|
||||
tGATT_SRV_LIST_ELEM *p_srv = NULL;
|
||||
|
||||
reason = gatts_validate_packet_format(op_code, &len, &p_data, &uuid, &s_hdl, &e_hdl);
|
||||
|
||||
GATT_TRACE_DEBUG("%s, op_code =%x, len = %x\n", __func__, op_code, len);
|
||||
#if GATT_CONFORMANCE_TESTING == TRUE
|
||||
if (gatt_cb.enable_err_rsp && gatt_cb.req_op_code == op_code) {
|
||||
GATT_TRACE_DEBUG("Conformance tst: forced err rsp for ReadByType: error status=%d", gatt_cb.err_status);
|
||||
GATT_TRACE_DEBUG("Conformance tst: forced err rsp for ReadByType: error status=%d\n", gatt_cb.err_status);
|
||||
|
||||
gatt_send_error_rsp (p_tcb, gatt_cb.err_status, gatt_cb.req_op_code, s_hdl, FALSE);
|
||||
|
||||
@ -902,7 +902,7 @@ void gatts_process_read_by_type_req(tGATT_TCB *p_tcb, UINT8 op_code, UINT16 len,
|
||||
|
||||
if (reason == GATT_SUCCESS) {
|
||||
if ((p_msg = (BT_HDR *)GKI_getbuf(msg_len)) == NULL) {
|
||||
GATT_TRACE_ERROR("gatts_process_find_info failed. no resources.");
|
||||
GATT_TRACE_ERROR("gatts_process_find_info failed. no resources.\n");
|
||||
|
||||
reason = GATT_NO_RESOURCES;
|
||||
} else {
|
||||
@ -959,7 +959,7 @@ void gatts_process_read_by_type_req(tGATT_TCB *p_tcb, UINT8 op_code, UINT16 len,
|
||||
p_msg->offset = L2CAP_MIN_OFFSET;
|
||||
}
|
||||
}
|
||||
if (reason != GATT_SUCCESS) {
|
||||
if (reason != GATT_SUCCESS && reason != GATT_STACK_RSP) {
|
||||
if (p_msg) {
|
||||
GKI_freebuf(p_msg);
|
||||
}
|
||||
@ -987,19 +987,32 @@ 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;
|
||||
UINT8 sec_flag, key_size, *p = p_data, *p_m;
|
||||
tGATT_SR_REG *p_sreg;
|
||||
UINT16 conn_id;
|
||||
|
||||
UINT16 conn_id, offset = 0;
|
||||
BT_HDR *p_msg = NULL;
|
||||
memset(&sr_data, 0, sizeof(tGATTS_DATA));
|
||||
|
||||
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:
|
||||
@ -1012,11 +1025,16 @@ void gatts_process_write_req (tGATT_TCB *p_tcb, UINT8 i_rcb, UINT16 handle,
|
||||
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;
|
||||
}
|
||||
@ -1039,36 +1057,52 @@ void gatts_process_write_req (tGATT_TCB *p_tcb, UINT8 i_rcb, UINT16 handle,
|
||||
if ((trans_id = gatt_sr_enqueue_cmd(p_tcb, op_code, handle)) != 0) {
|
||||
p_sreg = &gatt_cb.sr_reg[i_rcb];
|
||||
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)){
|
||||
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);
|
||||
|
||||
status = GATT_PENDING;
|
||||
if(status == GATT_SUCCESS){
|
||||
attp_send_sr_msg(p_tcb, p_msg);
|
||||
gatt_dequeue_sr_cmd(p_tcb);
|
||||
}
|
||||
|
||||
} else {
|
||||
GATT_TRACE_ERROR("max pending command, send error");
|
||||
GATT_TRACE_ERROR("max pending command, send error\n");
|
||||
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 &&
|
||||
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);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function gatts_process_read_req
|
||||
**
|
||||
** Description This function is called to process the read request
|
||||
** from client.
|
||||
**
|
||||
** Returns void
|
||||
**
|
||||
*******************************************************************************/
|
||||
**
|
||||
** Function gatts_process_read_req
|
||||
**
|
||||
** Description This function is called to process the read request
|
||||
** from client.
|
||||
**
|
||||
** Returns void
|
||||
**
|
||||
*******************************************************************************/
|
||||
static void gatts_process_read_req(tGATT_TCB *p_tcb, tGATT_SR_REG *p_rcb, UINT8 op_code,
|
||||
UINT16 handle, UINT16 len, UINT8 *p_data)
|
||||
{
|
||||
@ -1080,7 +1114,7 @@ static void gatts_process_read_req(tGATT_TCB *p_tcb, tGATT_SR_REG *p_rcb, UINT8
|
||||
|
||||
UNUSED (len);
|
||||
if ((p_msg = (BT_HDR *)GKI_getbuf(buf_len)) == NULL) {
|
||||
GATT_TRACE_ERROR("gatts_process_find_info failed. no resources.");
|
||||
GATT_TRACE_ERROR("gatts_process_find_info failed. no resources.\n");
|
||||
|
||||
reason = GATT_NO_RESOURCES;
|
||||
} else {
|
||||
@ -1114,17 +1148,20 @@ static void gatts_process_read_req(tGATT_TCB *p_tcb, tGATT_SR_REG *p_rcb, UINT8
|
||||
p_msg->len += value_len;
|
||||
}
|
||||
|
||||
if (reason != GATT_SUCCESS) {
|
||||
|
||||
if (reason != GATT_SUCCESS && reason != GATT_PENDING && reason != GATT_STACK_RSP) {
|
||||
if (p_msg) {
|
||||
GKI_freebuf(p_msg);
|
||||
}
|
||||
|
||||
/* in theroy BUSY is not possible(should already been checked), protected check */
|
||||
if (reason != GATT_PENDING && reason != GATT_BUSY) {
|
||||
if (reason != GATT_BUSY) {
|
||||
gatt_send_error_rsp (p_tcb, reason, op_code, handle, FALSE);
|
||||
gatt_dequeue_sr_cmd(p_tcb);
|
||||
}
|
||||
} else {
|
||||
attp_send_sr_msg(p_tcb, p_msg);
|
||||
gatt_dequeue_sr_cmd(p_tcb);
|
||||
}
|
||||
|
||||
}
|
||||
@ -1149,7 +1186,7 @@ void gatts_process_attribute_req (tGATT_TCB *p_tcb, UINT8 op_code,
|
||||
tGATT_ATTR16 *p_attr;
|
||||
|
||||
if (len < 2) {
|
||||
GATT_TRACE_ERROR("Illegal PDU length, discard request");
|
||||
GATT_TRACE_ERROR("Illegal PDU length, discard request\n");
|
||||
status = GATT_INVALID_PDU;
|
||||
} else {
|
||||
STREAM_TO_UINT16(handle, p);
|
||||
@ -1159,7 +1196,7 @@ void gatts_process_attribute_req (tGATT_TCB *p_tcb, UINT8 op_code,
|
||||
#if GATT_CONFORMANCE_TESTING == TRUE
|
||||
gatt_cb.handle = handle;
|
||||
if (gatt_cb.enable_err_rsp && gatt_cb.req_op_code == op_code) {
|
||||
GATT_TRACE_DEBUG("Conformance tst: forced err rsp: error status=%d", gatt_cb.err_status);
|
||||
GATT_TRACE_DEBUG("Conformance tst: forced err rsp: error status=%d\n", gatt_cb.err_status);
|
||||
|
||||
gatt_send_error_rsp (p_tcb, gatt_cb.err_status, gatt_cb.req_op_code, handle, FALSE);
|
||||
|
||||
@ -1355,7 +1392,7 @@ void gatt_server_handle_client_req (tGATT_TCB *p_tcb, UINT8 op_code,
|
||||
gatts_process_primary_service_req (p_tcb, op_code, len, p_data);
|
||||
break;
|
||||
|
||||
case GATT_REQ_FIND_INFO:/* discover char descrptor */
|
||||
case GATT_REQ_FIND_INFO: /* discover char descrptor */
|
||||
gatts_process_find_info(p_tcb, op_code, len, p_data);
|
||||
break;
|
||||
|
||||
|
@ -318,6 +318,34 @@ tGATT_HDL_LIST_ELEM *gatt_find_hdl_buffer_by_handle(UINT16 handle)
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function gatt_find_hdl_buffer_by_attr_handle
|
||||
**
|
||||
** Description Find handle range buffer by attribute handle.
|
||||
**
|
||||
** Returns Pointer to the buffer, NULL no buffer available
|
||||
**
|
||||
*******************************************************************************/
|
||||
tGATT_HDL_LIST_ELEM *gatt_find_hdl_buffer_by_attr_handle(UINT16 attr_handle)
|
||||
{
|
||||
tGATT_HDL_LIST_INFO *p_list_info = &gatt_cb.hdl_list_info;
|
||||
tGATT_HDL_LIST_ELEM *p_list = NULL;
|
||||
|
||||
p_list = p_list_info->p_first;
|
||||
|
||||
while (p_list != NULL) {
|
||||
if (p_list->in_use && (p_list->asgn_range.s_handle <= attr_handle)
|
||||
&& (p_list->asgn_range.e_handle >= attr_handle)) {
|
||||
return (p_list);
|
||||
}
|
||||
p_list = p_list->p_next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function gatt_find_hdl_buffer_by_app_id
|
||||
@ -1476,7 +1504,7 @@ tGATT_REG *gatt_get_regcb (tGATT_IF gatt_if)
|
||||
p_reg = &gatt_cb.cl_rcb[ii - 1];
|
||||
|
||||
if (!p_reg->in_use) {
|
||||
GATT_TRACE_WARNING("gatt_if found but not in use.");
|
||||
GATT_TRACE_WARNING("gatt_if found but not in use.\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -36,6 +36,9 @@
|
||||
|
||||
#define GATT_GET_SR_REG_PTR(index) (&gatt_cb.sr_reg[(UINT8) (index)]);
|
||||
#define GATT_TRANS_ID_MAX 0x0fffffff /* 4 MSB is reserved */
|
||||
#define GATT_RSP_BY_APP 0x00
|
||||
#define GATT_RSP_BY_STACK 0x01
|
||||
#define GATT_RSP_DEFAULT GATT_RSP_BY_APP //need to rsp by the app.
|
||||
|
||||
/* security action for GATT write and read request */
|
||||
#define GATT_SEC_NONE 0
|
||||
@ -154,7 +157,7 @@ typedef union {
|
||||
tBT_UUID uuid; /* service declaration */
|
||||
tGATT_CHAR_DECL char_decl; /* characteristic declaration */
|
||||
tGATT_INCL_SRVC incl_handle; /* included service */
|
||||
|
||||
tGATT_ATTR_VAL attr_val;
|
||||
} tGATT_ATTR_VALUE;
|
||||
|
||||
/* Attribute UUID type
|
||||
@ -167,11 +170,11 @@ typedef UINT8 tGATT_ATTR_UUID_TYPE;
|
||||
/* 16 bits UUID Attribute in server database
|
||||
*/
|
||||
typedef struct {
|
||||
void *p_next; /* pointer to the next attribute,
|
||||
either tGATT_ATTR16 or tGATT_ATTR128 */
|
||||
void *p_next; /* pointer to the next attribute, either tGATT_ATTR16 or tGATT_ATTR128 */
|
||||
tGATT_ATTR_VALUE *p_value;
|
||||
tGATT_ATTR_UUID_TYPE uuid_type;
|
||||
tGATT_PERM permission;
|
||||
tGATTS_ATTR_CONTROL control;
|
||||
UINT16 handle;
|
||||
UINT16 uuid;
|
||||
} tGATT_ATTR16;
|
||||
@ -179,11 +182,11 @@ typedef struct {
|
||||
/* 32 bits UUID Attribute in server database
|
||||
*/
|
||||
typedef struct {
|
||||
void *p_next; /* pointer to the next attribute,
|
||||
either tGATT_ATTR16, tGATT_ATTR32 or tGATT_ATTR128 */
|
||||
void *p_next; /* pointer to the next attribute, either tGATT_ATTR16, tGATT_ATTR32 or tGATT_ATTR128 */
|
||||
tGATT_ATTR_VALUE *p_value;
|
||||
tGATT_ATTR_UUID_TYPE uuid_type;
|
||||
tGATT_PERM permission;
|
||||
tGATTS_ATTR_CONTROL control;
|
||||
UINT16 handle;
|
||||
UINT32 uuid;
|
||||
} tGATT_ATTR32;
|
||||
@ -192,11 +195,11 @@ typedef struct {
|
||||
/* 128 bits UUID Attribute in server database
|
||||
*/
|
||||
typedef struct {
|
||||
void *p_next; /* pointer to the next attribute,
|
||||
either tGATT_ATTR16 or tGATT_ATTR128 */
|
||||
void *p_next; /* pointer to the next attribute, either tGATT_ATTR16 or tGATT_ATTR128 */
|
||||
tGATT_ATTR_VALUE *p_value;
|
||||
tGATT_ATTR_UUID_TYPE uuid_type;
|
||||
tGATT_PERM permission;
|
||||
tGATTS_ATTR_CONTROL control;
|
||||
UINT16 handle;
|
||||
UINT8 uuid[LEN_UUID_128];
|
||||
} tGATT_ATTR128;
|
||||
@ -204,8 +207,7 @@ typedef struct {
|
||||
/* Service Database definition
|
||||
*/
|
||||
typedef struct {
|
||||
void *p_attr_list; /* pointer to the first attribute,
|
||||
either tGATT_ATTR16 or tGATT_ATTR128 */
|
||||
void *p_attr_list; /* pointer to the first attribute, either tGATT_ATTR16 or tGATT_ATTR128 */
|
||||
UINT8 *p_free_mem; /* Pointer to free memory */
|
||||
BUFFER_Q svc_buffer; /* buffer queue used for service database */
|
||||
UINT32 mem_free; /* Memory still available */
|
||||
@ -579,6 +581,7 @@ extern BOOLEAN gatt_cl_send_next_cmd_inq(tGATT_TCB *p_tcb);
|
||||
/* reserved handle list */
|
||||
extern tGATT_HDL_LIST_ELEM *gatt_find_hdl_buffer_by_app_id (tBT_UUID *p_app_uuid128, tBT_UUID *p_svc_uuid, UINT16 svc_inst);
|
||||
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 BOOLEAN gatt_is_last_attribute(tGATT_SRV_LIST_INFO *p_list, tGATT_SRV_LIST_ELEM *p_start, tBT_UUID value);
|
||||
@ -664,12 +667,27 @@ extern void gatt_set_sec_act(tGATT_TCB *p_tcb, tGATT_SEC_ACTION sec_act);
|
||||
/* gatt_db.c */
|
||||
extern BOOLEAN gatts_init_service_db (tGATT_SVC_DB *p_db, tBT_UUID *p_service, BOOLEAN is_pri, UINT16 s_hdl, UINT16 num_handle);
|
||||
extern UINT16 gatts_add_included_service (tGATT_SVC_DB *p_db, UINT16 s_handle, UINT16 e_handle, tBT_UUID service);
|
||||
extern UINT16 gatts_add_characteristic (tGATT_SVC_DB *p_db, tGATT_PERM perm, tGATT_CHAR_PROP property, tBT_UUID *p_char_uuid);
|
||||
extern UINT16 gatts_add_char_descr (tGATT_SVC_DB *p_db, tGATT_PERM perm, tBT_UUID *p_dscp_uuid);
|
||||
extern UINT16 gatts_add_characteristic (tGATT_SVC_DB *p_db, tGATT_PERM perm,
|
||||
tGATT_CHAR_PROP property,
|
||||
tBT_UUID *p_char_uuid, tGATT_ATTR_VAL *attr_val,
|
||||
tGATTS_ATTR_CONTROL *control);
|
||||
extern UINT16 gatts_add_char_descr (tGATT_SVC_DB *p_db, tGATT_PERM perm,
|
||||
tBT_UUID *p_dscp_uuid, tGATT_ATTR_VAL *attr_val,
|
||||
tGATTS_ATTR_CONTROL *control);
|
||||
|
||||
extern tGATT_STATUS gatts_set_attribute_value(tGATT_SVC_DB *p_db, UINT16 attr_handle,
|
||||
UINT16 length, UINT8 *value);
|
||||
|
||||
extern tGATT_STATUS gatts_get_attribute_value(tGATT_SVC_DB *p_db, UINT16 attr_handle,
|
||||
UINT16 *length, UINT8 **value);
|
||||
extern BOOLEAN gatts_is_auto_response(UINT16 attr_handle);
|
||||
extern tGATT_STATUS gatts_db_read_attr_value_by_type (tGATT_TCB *p_tcb, tGATT_SVC_DB *p_db, UINT8 op_code, BT_HDR *p_rsp, UINT16 s_handle,
|
||||
UINT16 e_handle, tBT_UUID type, UINT16 *p_len, tGATT_SEC_FLAG sec_flag, UINT8 key_size, UINT32 trans_id, UINT16 *p_cur_handle);
|
||||
extern tGATT_STATUS gatts_read_attr_value_by_handle(tGATT_TCB *p_tcb, tGATT_SVC_DB *p_db, UINT8 op_code, UINT16 handle, UINT16 offset,
|
||||
UINT8 *p_value, UINT16 *p_len, UINT16 mtu, tGATT_SEC_FLAG sec_flag, UINT8 key_size, UINT32 trans_id);
|
||||
extern tGATT_STATUS gatts_write_attr_value_by_handle(tGATT_SVC_DB *p_db,
|
||||
UINT16 handle, UINT16 offset,
|
||||
UINT8 *p_value, UINT16 len);
|
||||
extern tGATT_STATUS gatts_write_attr_perm_check (tGATT_SVC_DB *p_db, UINT8 op_code, UINT16 handle, UINT16 offset, UINT8 *p_data,
|
||||
UINT16 len, tGATT_SEC_FLAG sec_flag, UINT8 key_size);
|
||||
extern tGATT_STATUS gatts_read_attr_perm_check(tGATT_SVC_DB *p_db, BOOLEAN is_long, UINT16 handle, tGATT_SEC_FLAG sec_flag, UINT8 key_size);
|
||||
|
@ -63,6 +63,8 @@
|
||||
#define GATT_ENCRYPED_NO_MITM 0x8d
|
||||
#define GATT_NOT_ENCRYPTED 0x8e
|
||||
#define GATT_CONGESTED 0x8f
|
||||
#define GATT_STACK_RSP 0x90
|
||||
#define GATT_APP_RSP 0x91
|
||||
|
||||
/* 0xE0 ~ 0xFC reserved for future use */
|
||||
#define GATT_CCC_CFG_ERR 0xFD /* Client Characteristic Configuration Descriptor Improperly Configured */
|
||||
@ -135,11 +137,11 @@ typedef UINT16 tGATT_DISCONN_REASON;
|
||||
#define GATT_INVALID_CONN_ID 0xFFFF
|
||||
|
||||
#ifndef GATT_CL_MAX_LCB
|
||||
#define GATT_CL_MAX_LCB 4 // 22
|
||||
#define GATT_CL_MAX_LCB 4 // 22
|
||||
#endif
|
||||
|
||||
#ifndef GATT_MAX_SCCB
|
||||
#define GATT_MAX_SCCB 4
|
||||
#define GATT_MAX_SCCB 4
|
||||
#endif
|
||||
|
||||
|
||||
@ -312,6 +314,16 @@ typedef struct {
|
||||
UINT8 value[GATT_MAX_ATTR_LEN]; /* the actual attribute value */
|
||||
} tGATT_VALUE;
|
||||
|
||||
typedef struct{
|
||||
UINT16 attr_max_len;
|
||||
UINT16 attr_len;
|
||||
UINT8 *attr_val;
|
||||
}tGATT_ATTR_VAL;
|
||||
|
||||
typedef struct{
|
||||
uint8_t auto_rsp;
|
||||
}tGATTS_ATTR_CONTROL;
|
||||
|
||||
/* Union of the event data which is used in the server respond API to carry the server response information
|
||||
*/
|
||||
typedef union {
|
||||
@ -337,6 +349,7 @@ typedef struct {
|
||||
UINT16 handle;
|
||||
UINT16 offset;
|
||||
BOOLEAN is_long;
|
||||
BOOLEAN need_rsp;
|
||||
} tGATT_READ_REQ;
|
||||
|
||||
/* write request data */
|
||||
@ -740,8 +753,9 @@ extern UINT16 GATTS_AddIncludeService (UINT16 service_handle,
|
||||
** characteristic failed.
|
||||
**
|
||||
*******************************************************************************/
|
||||
extern UINT16 GATTS_AddCharacteristic (UINT16 service_handle, tBT_UUID *char_uuid,
|
||||
tGATT_PERM perm, tGATT_CHAR_PROP property);
|
||||
extern UINT16 GATTS_AddCharacteristic (UINT16 service_handle, tBT_UUID *p_char_uuid,
|
||||
tGATT_PERM perm, tGATT_CHAR_PROP property,
|
||||
tGATT_ATTR_VAL *attr_val, tGATTS_ATTR_CONTROL *control);
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
@ -763,7 +777,8 @@ extern UINT16 GATTS_AddCharacteristic (UINT16 service_handle, tBT_UUID *char_uui
|
||||
**
|
||||
*******************************************************************************/
|
||||
extern UINT16 GATTS_AddCharDescriptor (UINT16 service_handle, tGATT_PERM perm,
|
||||
tBT_UUID *p_descr_uuid);
|
||||
tBT_UUID *p_descr_uuid, tGATT_ATTR_VAL *attr_val,
|
||||
tGATTS_ATTR_CONTROL *control);
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
@ -866,6 +881,39 @@ extern tGATT_STATUS GATTS_SendRsp (UINT16 conn_id, UINT32 trans_id,
|
||||
tGATT_STATUS status, tGATTS_RSP *p_msg);
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function GATTS_SetAttributeValue
|
||||
**
|
||||
** Description This function sends to set the attribute value .
|
||||
**
|
||||
** Parameter attr_handle:the attribute handle
|
||||
** length: the attribute length
|
||||
** value: the value to be set to the attribute in the database
|
||||
**
|
||||
** Returns GATT_SUCCESS if sucessfully sent; otherwise error code.
|
||||
**
|
||||
*******************************************************************************/
|
||||
tGATT_STATUS GATTS_SetAttributeValue(UINT16 attr_handle, UINT16 length, UINT8 *value);
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function GATTS_GetAttributeValue
|
||||
**
|
||||
** Description This function sends to set the attribute value .
|
||||
**
|
||||
** Parameter attr_handle: the attribute handle
|
||||
** length:the attribute value length in the database
|
||||
** value: the attribute value out put
|
||||
**
|
||||
** Returns GATT_SUCCESS if sucessfully sent; otherwise error code.
|
||||
**
|
||||
*******************************************************************************/
|
||||
tGATT_STATUS GATTS_GetAttributeValue(UINT16 attr_handle, UINT16 *length, UINT8 **value);
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************/
|
||||
/* GATT Profile Client Functions */
|
||||
/*******************************************************************************/
|
||||
|
@ -419,7 +419,7 @@ static const UINT8 smp_master_create_local_sec_conn_oob_data[][SMP_SM_NUM_COLS]
|
||||
static const UINT8 smp_slave_entry_map[][SMP_STATE_MAX] = {
|
||||
/* state name: Idle WaitApp SecReq Pair Wait Confirm Rand PublKey SCPhs1 Wait Wait SCPhs2 Wait DHKChk Enc Bond CrLocSc
|
||||
Rsp Pend ReqRsp Cfm Exch Strt Cmtm Nonce Strt DHKChk Pend Pend OobData */
|
||||
/* PAIR_REQ */{ 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
|
||||
/* PAIR_REQ */{ 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
|
||||
/* PAIR_RSP */{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
|
||||
/* CONFIRM */{ 0, 4, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
|
||||
/* RAND */{ 0, 0, 0, 0, 0, 1, 2, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0 },
|
||||
|
@ -35,6 +35,15 @@
|
||||
extern void btdm_osi_funcs_register(void *osi_funcs);
|
||||
extern void btdm_controller_init(void);
|
||||
|
||||
/* VHCI function interface */
|
||||
typedef struct vhci_host_callback {
|
||||
void (*notify_host_send_available)(void); /*!< callback used to notify that the host can send packet to controller */
|
||||
int (*notify_host_recv)(uint8_t *data, uint16_t len); /*!< callback used to notify that the controller has a packet to send to the host*/
|
||||
} vhci_host_callback_t;
|
||||
|
||||
extern bool API_vhci_host_check_send_available(void);
|
||||
extern void API_vhci_host_send_packet(uint8_t *data, uint16_t len);
|
||||
extern void API_vhci_host_register_callback(const vhci_host_callback_t *callback);
|
||||
|
||||
#define BT_DEBUG(...)
|
||||
#define BT_API_CALL_CHECK(info, api_call, ret) \
|
||||
@ -85,7 +94,7 @@ static int32_t IRAM_ATTR semphr_give_from_isr_wrapper(void *semphr, void *hptw)
|
||||
|
||||
static int32_t IRAM_ATTR semphr_take_wrapper(void *semphr, uint32_t block_time_ms)
|
||||
{
|
||||
return (int32_t)xSemaphoreTake(semphr, block_time_ms / portTICK_RATE_MS);
|
||||
return (int32_t)xSemaphoreTake(semphr, block_time_ms / portTICK_PERIOD_MS);
|
||||
}
|
||||
|
||||
static void *IRAM_ATTR mutex_create_wrapper(void)
|
||||
@ -118,13 +127,28 @@ static struct osi_funcs_t osi_funcs = {
|
||||
._read_efuse_mac = esp_efuse_read_mac,
|
||||
};
|
||||
|
||||
bool esp_vhci_host_check_send_available(void)
|
||||
{
|
||||
return API_vhci_host_check_send_available();
|
||||
}
|
||||
|
||||
void esp_vhci_host_send_packet(uint8_t *data, uint16_t len)
|
||||
{
|
||||
API_vhci_host_send_packet(data, len);
|
||||
}
|
||||
|
||||
void esp_vhci_host_register_callback(const esp_vhci_host_callback_t *callback)
|
||||
{
|
||||
API_vhci_host_register_callback((const vhci_host_callback_t *)callback);
|
||||
}
|
||||
|
||||
static void bt_controller_task(void *pvParam)
|
||||
{
|
||||
btdm_osi_funcs_register(&osi_funcs);
|
||||
btdm_controller_init();
|
||||
}
|
||||
|
||||
void bt_controller_init()
|
||||
void esp_bt_controller_init()
|
||||
{
|
||||
xTaskCreatePinnedToCore(bt_controller_task, "btController",
|
||||
ESP_TASK_BT_CONTROLLER_STACK, NULL,
|
||||
|
@ -1,6 +1,7 @@
|
||||
#
|
||||
# Component Makefile
|
||||
#
|
||||
ifdef CONFIG_BT_ENABLED
|
||||
|
||||
COMPONENT_ADD_INCLUDEDIRS := bluedroid/bta/include \
|
||||
bluedroid/bta/sys/include \
|
||||
@ -87,3 +88,5 @@ COMPONENT_SRCDIRS := bluedroid/bta/dm \
|
||||
.
|
||||
|
||||
COMPONENT_SUBMODULES += lib
|
||||
|
||||
endif
|
||||
|
@ -29,35 +29,35 @@ extern "C" {
|
||||
*
|
||||
* This function should be called only once, before any other BT functions are called.
|
||||
*/
|
||||
void bt_controller_init(void);
|
||||
void esp_bt_controller_init(void);
|
||||
|
||||
/** @brief vhci_host_callback
|
||||
/** @brief esp_vhci_host_callback
|
||||
* used for vhci call host function to notify what host need to do
|
||||
*/
|
||||
typedef struct vhci_host_callback {
|
||||
typedef struct esp_vhci_host_callback {
|
||||
void (*notify_host_send_available)(void); /*!< callback used to notify that the host can send packet to controller */
|
||||
int (*notify_host_recv)(uint8_t *data, uint16_t len); /*!< callback used to notify that the controller has a packet to send to the host*/
|
||||
} vhci_host_callback_t;
|
||||
} esp_vhci_host_callback_t;
|
||||
|
||||
/** @brief API_vhci_host_check_send_available
|
||||
/** @brief esp_vhci_host_check_send_available
|
||||
* used for check actively if the host can send packet to controller or not.
|
||||
* @return true for ready to send, false means cannot send packet
|
||||
*/
|
||||
bool API_vhci_host_check_send_available(void);
|
||||
bool esp_vhci_host_check_send_available(void);
|
||||
|
||||
/** @brief API_vhci_host_send_packet
|
||||
/** @brief esp_vhci_host_send_packet
|
||||
* host send packet to controller
|
||||
* @param data the packet point
|
||||
*,@param len the packet length
|
||||
*/
|
||||
void API_vhci_host_send_packet(uint8_t *data, uint16_t len);
|
||||
void esp_vhci_host_send_packet(uint8_t *data, uint16_t len);
|
||||
|
||||
/** @brief API_vhci_host_register_callback
|
||||
/** @brief esp_vhci_host_register_callback
|
||||
* register the vhci referece callback, the call back
|
||||
* struct defined by vhci_host_callback structure.
|
||||
* @param callback vhci_host_callback type variable
|
||||
* @param callback esp_vhci_host_callback type variable
|
||||
*/
|
||||
void API_vhci_host_register_callback(const vhci_host_callback_t *callback);
|
||||
void esp_vhci_host_register_callback(const esp_vhci_host_callback_t *callback);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit 91657e0c4025f5a694b0a89f449c347b0f2fdf79
|
||||
Subproject commit 566acfd8c61a4ba0fb6b9026c89488b01af0fff0
|
1
components/coap/Makefile.projbuild
Normal file
1
components/coap/Makefile.projbuild
Normal file
@ -0,0 +1 @@
|
||||
CFLAGS += -DWITH_POSIX
|
11
components/coap/component.mk
Normal file
11
components/coap/component.mk
Normal file
@ -0,0 +1,11 @@
|
||||
#
|
||||
# Component Makefile
|
||||
#
|
||||
|
||||
COMPONENT_ADD_INCLUDEDIRS := port/include port/include/coap libcoap/include libcoap/include/coap
|
||||
|
||||
COMPONENT_OBJS = libcoap/src/address.o libcoap/src/async.o libcoap/src/block.o libcoap/src/coap_time.o libcoap/src/debug.o libcoap/src/encode.o libcoap/src/hashkey.o libcoap/src/mem.o libcoap/src/net.o libcoap/src/option.o libcoap/src/pdu.o libcoap/src/resource.o libcoap/src/str.o libcoap/src/subscribe.o libcoap/src/uri.o port/coap_io_socket.o
|
||||
|
||||
COMPONENT_SRCDIRS := libcoap/src libcoap port
|
||||
|
||||
COMPONENT_SUBMODULES += libcoap
|
1
components/coap/libcoap
Submodule
1
components/coap/libcoap
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit 6468887a12666f88b8704d797fc176cd4f40ee4c
|
468
components/coap/port/coap_io_socket.c
Normal file
468
components/coap/port/coap_io_socket.c
Normal file
@ -0,0 +1,468 @@
|
||||
/*
|
||||
* Network function implementation with socket for ESP32 platform.
|
||||
*
|
||||
* Uses libcoap software implementation for failover when concurrent
|
||||
* network operations are in use.
|
||||
*
|
||||
* coap_io.h -- Default network I/O functions for libcoap
|
||||
*
|
||||
* Copyright (C) 2012,2014 Olaf Bergmann <bergmann@tzi.org>
|
||||
*
|
||||
* Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
||||
*
|
||||
* This file is part of the CoAP library libcoap. Please see
|
||||
* README for terms of use.
|
||||
*/
|
||||
|
||||
#include "coap_config.h"
|
||||
|
||||
#ifdef HAVE_STDIO_H
|
||||
# include <stdio.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SYS_SELECT_H
|
||||
# include <sys/select.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_SOCKET_H
|
||||
# include <sys/socket.h>
|
||||
#endif
|
||||
#ifdef HAVE_NETINET_IN_H
|
||||
# include <netinet/in.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_UIO_H
|
||||
# include <sys/uio.h>
|
||||
#endif
|
||||
#ifdef HAVE_UNISTD_H
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
#include <errno.h>
|
||||
|
||||
#ifdef WITH_CONTIKI
|
||||
# include "uip.h"
|
||||
#endif
|
||||
|
||||
#include "pdu.h"
|
||||
#include "debug.h"
|
||||
#include "mem.h"
|
||||
#include "coap_io.h"
|
||||
|
||||
#ifdef WITH_POSIX
|
||||
/* define generic PKTINFO for IPv4 */
|
||||
#if defined(IP_PKTINFO)
|
||||
# define GEN_IP_PKTINFO IP_PKTINFO
|
||||
#elif defined(IP_RECVDSTADDR)
|
||||
# define GEN_IP_PKTINFO IP_RECVDSTADDR
|
||||
#else
|
||||
# error "Need IP_PKTINFO or IP_RECVDSTADDR to request ancillary data from OS."
|
||||
#endif /* IP_PKTINFO */
|
||||
|
||||
/* define generic KTINFO for IPv6 */
|
||||
#ifdef IPV6_RECVPKTINFO
|
||||
# define GEN_IPV6_PKTINFO IPV6_RECVPKTINFO
|
||||
#elif defined(IPV6_PKTINFO)
|
||||
# define GEN_IPV6_PKTINFO IPV6_PKTINFO
|
||||
#else
|
||||
# error "Need IPV6_PKTINFO or IPV6_RECVPKTINFO to request ancillary data from OS."
|
||||
#endif /* IPV6_RECVPKTINFO */
|
||||
|
||||
struct coap_packet_t {
|
||||
coap_if_handle_t hnd; /**< the interface handle */
|
||||
coap_address_t src; /**< the packet's source address */
|
||||
coap_address_t dst; /**< the packet's destination address */
|
||||
const coap_endpoint_t *interface;
|
||||
|
||||
int ifindex;
|
||||
void *session; /**< opaque session data */
|
||||
|
||||
size_t length; /**< length of payload */
|
||||
unsigned char payload[]; /**< payload */
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef CUSTOM_COAP_NETWORK_ENDPOINT
|
||||
|
||||
#ifdef WITH_CONTIKI
|
||||
static int ep_initialized = 0;
|
||||
|
||||
static inline struct coap_endpoint_t *
|
||||
coap_malloc_contiki_endpoint() {
|
||||
static struct coap_endpoint_t ep;
|
||||
|
||||
if (ep_initialized) {
|
||||
return NULL;
|
||||
} else {
|
||||
ep_initialized = 1;
|
||||
return &ep;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
coap_free_contiki_endpoint(struct coap_endpoint_t *ep) {
|
||||
ep_initialized = 0;
|
||||
}
|
||||
|
||||
coap_endpoint_t *
|
||||
coap_new_endpoint(const coap_address_t *addr, int flags) {
|
||||
struct coap_endpoint_t *ep = coap_malloc_contiki_endpoint();
|
||||
|
||||
if (ep) {
|
||||
memset(ep, 0, sizeof(struct coap_endpoint_t));
|
||||
ep->handle.conn = udp_new(NULL, 0, NULL);
|
||||
|
||||
if (!ep->handle.conn) {
|
||||
coap_free_endpoint(ep);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
coap_address_init(&ep->addr);
|
||||
uip_ipaddr_copy(&ep->addr.addr, &addr->addr);
|
||||
ep->addr.port = addr->port;
|
||||
udp_bind((struct uip_udp_conn *)ep->handle.conn, addr->port);
|
||||
}
|
||||
return ep;
|
||||
}
|
||||
|
||||
void
|
||||
coap_free_endpoint(coap_endpoint_t *ep) {
|
||||
if (ep) {
|
||||
if (ep->handle.conn) {
|
||||
uip_udp_remove((struct uip_udp_conn *)ep->handle.conn);
|
||||
}
|
||||
coap_free_contiki_endpoint(ep);
|
||||
}
|
||||
}
|
||||
|
||||
#else /* WITH_CONTIKI */
|
||||
static inline struct coap_endpoint_t *
|
||||
coap_malloc_posix_endpoint(void) {
|
||||
return (struct coap_endpoint_t *)coap_malloc(sizeof(struct coap_endpoint_t));
|
||||
}
|
||||
|
||||
static inline void
|
||||
coap_free_posix_endpoint(struct coap_endpoint_t *ep) {
|
||||
coap_free(ep);
|
||||
}
|
||||
|
||||
coap_endpoint_t *
|
||||
coap_new_endpoint(const coap_address_t *addr, int flags) {
|
||||
int sockfd = socket(addr->addr.sa.sa_family, SOCK_DGRAM, 0);
|
||||
int on = 1;
|
||||
struct coap_endpoint_t *ep;
|
||||
|
||||
if (sockfd < 0) {
|
||||
coap_log(LOG_WARNING, "coap_new_endpoint: socket");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0)
|
||||
coap_log(LOG_WARNING, "coap_new_endpoint: setsockopt SO_REUSEADDR");
|
||||
|
||||
if (bind(sockfd, &addr->addr.sa, addr->size) < 0) {
|
||||
coap_log(LOG_WARNING, "coap_new_endpoint: bind");
|
||||
close (sockfd);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ep = coap_malloc_posix_endpoint();
|
||||
if (!ep) {
|
||||
coap_log(LOG_WARNING, "coap_new_endpoint: malloc");
|
||||
close(sockfd);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memset(ep, 0, sizeof(struct coap_endpoint_t));
|
||||
ep->handle.fd = sockfd;
|
||||
ep->flags = flags;
|
||||
|
||||
ep->addr.size = addr->size;
|
||||
if (getsockname(sockfd, &ep->addr.addr.sa, &ep->addr.size) < 0) {
|
||||
coap_log(LOG_WARNING, "coap_new_endpoint: cannot determine local address");
|
||||
close (sockfd);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
if (LOG_DEBUG <= coap_get_log_level()) {
|
||||
#ifndef INET6_ADDRSTRLEN
|
||||
#define INET6_ADDRSTRLEN 40
|
||||
#endif
|
||||
unsigned char addr_str[INET6_ADDRSTRLEN+8];
|
||||
|
||||
if (coap_print_addr(&ep->addr, addr_str, INET6_ADDRSTRLEN+8)) {
|
||||
debug("created %sendpoint %s\n",
|
||||
ep->flags & COAP_ENDPOINT_DTLS ? "DTLS " : "",
|
||||
addr_str);
|
||||
}
|
||||
}
|
||||
#endif /* NDEBUG */
|
||||
|
||||
return (coap_endpoint_t *)ep;
|
||||
}
|
||||
|
||||
void
|
||||
coap_free_endpoint(coap_endpoint_t *ep) {
|
||||
if(ep) {
|
||||
if (ep->handle.fd >= 0)
|
||||
close(ep->handle.fd);
|
||||
coap_free_posix_endpoint((struct coap_endpoint_t *)ep);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* WITH_CONTIKI */
|
||||
#endif /* CUSTOM_COAP_NETWORK_ENDPOINT */
|
||||
|
||||
#ifdef CUSTOM_COAP_NETWORK_SEND
|
||||
|
||||
#if defined(WITH_POSIX) != defined(HAVE_NETINET_IN_H)
|
||||
/* define struct in6_pktinfo and struct in_pktinfo if not available
|
||||
FIXME: check with configure
|
||||
*/
|
||||
struct in6_pktinfo {
|
||||
struct in6_addr ipi6_addr; /* src/dst IPv6 address */
|
||||
unsigned int ipi6_ifindex; /* send/recv interface index */
|
||||
};
|
||||
|
||||
struct in_pktinfo {
|
||||
int ipi_ifindex;
|
||||
struct in_addr ipi_spec_dst;
|
||||
struct in_addr ipi_addr;
|
||||
};
|
||||
#endif
|
||||
|
||||
#if defined(WITH_POSIX) && !defined(SOL_IP)
|
||||
/* Solaris expects level IPPROTO_IP for ancillary data. */
|
||||
#define SOL_IP IPPROTO_IP
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define UNUSED_PARAM __attribute__ ((unused))
|
||||
#else /* not a GCC */
|
||||
#define UNUSED_PARAM
|
||||
#endif /* GCC */
|
||||
|
||||
ssize_t
|
||||
coap_network_send(struct coap_context_t *context UNUSED_PARAM,
|
||||
const coap_endpoint_t *local_interface,
|
||||
const coap_address_t *dst,
|
||||
unsigned char *data,
|
||||
size_t datalen) {
|
||||
|
||||
struct coap_endpoint_t *ep =
|
||||
(struct coap_endpoint_t *)local_interface;
|
||||
|
||||
#ifndef WITH_CONTIKI
|
||||
return sendto(ep->handle.fd, data, datalen, 0, (struct sockaddr*)&dst->addr.sa, sizeof(struct sockaddr));
|
||||
#else /* WITH_CONTIKI */
|
||||
/* FIXME: untested */
|
||||
/* FIXME: is there a way to check if send was successful? */
|
||||
uip_udp_packet_sendto((struct uip_udp_conn *)ep->handle.conn, data, datalen,
|
||||
&dst->addr, dst->port);
|
||||
return datalen;
|
||||
#endif /* WITH_CONTIKI */
|
||||
}
|
||||
|
||||
#endif /* CUSTOM_COAP_NETWORK_SEND */
|
||||
|
||||
#ifdef CUSTOM_COAP_NETWORK_READ
|
||||
|
||||
#define SIN6(A) ((struct sockaddr_in6 *)(A))
|
||||
|
||||
#ifdef WITH_POSIX
|
||||
static coap_packet_t *
|
||||
coap_malloc_packet(void) {
|
||||
coap_packet_t *packet;
|
||||
const size_t need = sizeof(coap_packet_t) + COAP_MAX_PDU_SIZE;
|
||||
|
||||
packet = (coap_packet_t *)coap_malloc(need);
|
||||
if (packet) {
|
||||
memset(packet, 0, need);
|
||||
}
|
||||
return packet;
|
||||
}
|
||||
|
||||
void
|
||||
coap_free_packet(coap_packet_t *packet) {
|
||||
coap_free(packet);
|
||||
}
|
||||
#endif /* WITH_POSIX */
|
||||
#ifdef WITH_CONTIKI
|
||||
static inline coap_packet_t *
|
||||
coap_malloc_packet(void) {
|
||||
return (coap_packet_t *)coap_malloc_type(COAP_PACKET, 0);
|
||||
}
|
||||
|
||||
void
|
||||
coap_free_packet(coap_packet_t *packet) {
|
||||
coap_free_type(COAP_PACKET, packet);
|
||||
}
|
||||
#endif /* WITH_CONTIKI */
|
||||
|
||||
static inline size_t
|
||||
coap_get_max_packetlength(const coap_packet_t *packet UNUSED_PARAM) {
|
||||
return COAP_MAX_PDU_SIZE;
|
||||
}
|
||||
|
||||
void
|
||||
coap_packet_populate_endpoint(coap_packet_t *packet, coap_endpoint_t *target)
|
||||
{
|
||||
target->handle = packet->interface->handle;
|
||||
memcpy(&target->addr, &packet->dst, sizeof(target->addr));
|
||||
target->ifindex = packet->ifindex;
|
||||
target->flags = 0; /* FIXME */
|
||||
}
|
||||
void
|
||||
coap_packet_copy_source(coap_packet_t *packet, coap_address_t *target)
|
||||
{
|
||||
memcpy(target, &packet->src, sizeof(coap_address_t));
|
||||
}
|
||||
void
|
||||
coap_packet_get_memmapped(coap_packet_t *packet, unsigned char **address, size_t *length)
|
||||
{
|
||||
*address = packet->payload;
|
||||
*length = packet->length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a message with destination address @p dst matches the
|
||||
* local interface with address @p local. This function returns @c 1
|
||||
* if @p dst is a valid match, and @c 0 otherwise.
|
||||
*/
|
||||
static inline int
|
||||
is_local_if(const coap_address_t *local, const coap_address_t *dst) {
|
||||
return coap_address_isany(local) || coap_address_equals(dst, local) ||
|
||||
coap_is_mcast(dst);
|
||||
}
|
||||
|
||||
ssize_t
|
||||
coap_network_read(coap_endpoint_t *ep, coap_packet_t **packet) {
|
||||
ssize_t len = -1;
|
||||
|
||||
#ifdef WITH_POSIX
|
||||
#define SOC_APPDATA_LEN 1460
|
||||
char *soc_appdata = NULL;
|
||||
struct sockaddr_in soc_srcipaddr;
|
||||
socklen_t soc_srcsize = sizeof(struct sockaddr_in);
|
||||
#endif /* WITH_POSIX */
|
||||
|
||||
assert(ep);
|
||||
assert(packet);
|
||||
|
||||
*packet = coap_malloc_packet();
|
||||
|
||||
if (!*packet) {
|
||||
warn("coap_network_read: insufficient memory, drop packet\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
coap_address_init(&(*packet)->dst); /* the local interface address */
|
||||
coap_address_init(&(*packet)->src); /* the remote peer */
|
||||
|
||||
#ifdef WITH_POSIX
|
||||
soc_appdata = coap_malloc(SOC_APPDATA_LEN);
|
||||
if (soc_appdata){
|
||||
len = recvfrom(ep->handle.fd, soc_appdata, SOC_APPDATA_LEN, 0, (struct sockaddr *)&soc_srcipaddr, (socklen_t *)&soc_srcsize);
|
||||
|
||||
if (len < 0){
|
||||
coap_log(LOG_WARNING, "coap_network_read: %s\n", strerror(errno));
|
||||
goto error;
|
||||
} else {
|
||||
/* use getsockname() to get the local port */
|
||||
(*packet)->dst.size = sizeof((*packet)->dst.addr);
|
||||
if (getsockname(ep->handle.fd, &(*packet)->dst.addr.sa, &(*packet)->dst.size) < 0) {
|
||||
coap_log(LOG_DEBUG, "cannot determine local port\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* local interface for IPv4 */
|
||||
(*packet)->src.size = sizeof((*packet)->src.addr);
|
||||
memcpy(&(*packet)->src.addr.sa, &soc_srcipaddr, (*packet)->src.size);
|
||||
|
||||
if (len > coap_get_max_packetlength(*packet)) {
|
||||
/* FIXME: we might want to send back a response */
|
||||
warn("discarded oversized packet\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (!is_local_if(&ep->addr, &(*packet)->dst)) {
|
||||
coap_log(LOG_DEBUG, "packet received on wrong interface, dropped\n");
|
||||
printf("error 3\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
(*packet)->length = len;
|
||||
|
||||
memcpy(&(*packet)->payload, soc_appdata, len);
|
||||
}
|
||||
|
||||
coap_free(soc_appdata);
|
||||
soc_appdata = NULL;
|
||||
} else {
|
||||
goto error;
|
||||
}
|
||||
#endif /* WITH_POSIX */
|
||||
#ifdef WITH_CONTIKI
|
||||
/* FIXME: untested, make this work */
|
||||
#define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN])
|
||||
#define UIP_UDP_BUF ((struct uip_udp_hdr *)&uip_buf[UIP_LLIPH_LEN])
|
||||
|
||||
if(uip_newdata()) {
|
||||
uip_ipaddr_copy(&(*packet)->src.addr, &UIP_IP_BUF->srcipaddr);
|
||||
(*packet)->src.port = UIP_UDP_BUF->srcport;
|
||||
uip_ipaddr_copy(&(*packet)->dst.addr, &UIP_IP_BUF->destipaddr);
|
||||
(*packet)->dst.port = UIP_UDP_BUF->destport;
|
||||
|
||||
if (!is_local_if(&ep->addr, &(*packet)->dst)) {
|
||||
coap_log(LOG_DEBUG, "packet received on wrong interface, dropped\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
len = uip_datalen();
|
||||
|
||||
if (len > coap_get_max_packetlength(*packet)) {
|
||||
/* FIXME: we might want to send back a response */
|
||||
warn("discarded oversized packet\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
((char *)uip_appdata)[len] = 0;
|
||||
#ifndef NDEBUG
|
||||
if (LOG_DEBUG <= coap_get_log_level()) {
|
||||
#ifndef INET6_ADDRSTRLEN
|
||||
#define INET6_ADDRSTRLEN 40
|
||||
#endif
|
||||
unsigned char addr_str[INET6_ADDRSTRLEN+8];
|
||||
|
||||
if (coap_print_addr(&(*packet)->src, addr_str, INET6_ADDRSTRLEN+8)) {
|
||||
debug("received %zd bytes from %s\n", len, addr_str);
|
||||
}
|
||||
}
|
||||
#endif /* NDEBUG */
|
||||
|
||||
(*packet)->length = len;
|
||||
memcpy(&(*packet)->payload, uip_appdata, len);
|
||||
}
|
||||
|
||||
#undef UIP_IP_BUF
|
||||
#undef UIP_UDP_BUF
|
||||
#endif /* WITH_CONTIKI */
|
||||
#ifdef WITH_LWIP
|
||||
#error "coap_network_read() not implemented on this platform"
|
||||
#endif
|
||||
|
||||
(*packet)->interface = ep;
|
||||
|
||||
return len;
|
||||
error:
|
||||
#ifdef WITH_POSIX
|
||||
if (soc_appdata)
|
||||
coap_free(soc_appdata);
|
||||
soc_appdata = NULL;
|
||||
#endif
|
||||
coap_free_packet(*packet);
|
||||
*packet = NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
#undef SIN6
|
||||
|
||||
#endif /* CUSTOM_COAP_NETWORK_READ */
|
50
components/coap/port/include/coap/coap.h
Normal file
50
components/coap/port/include/coap/coap.h
Normal file
@ -0,0 +1,50 @@
|
||||
/* Modify head file implementation for ESP32 platform.
|
||||
*
|
||||
* Uses libcoap software implementation for failover when concurrent
|
||||
* define operations are in use.
|
||||
*
|
||||
* coap.h -- main header file for CoAP stack of libcoap
|
||||
*
|
||||
* Copyright (C) 2010-2012,2015-2016 Olaf Bergmann <bergmann@tzi.org>
|
||||
* 2015 Carsten Schoenert <c.schoenert@t-online.de>
|
||||
*
|
||||
* Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
||||
*
|
||||
* This file is part of the CoAP library libcoap. Please see README for terms
|
||||
* of use.
|
||||
*/
|
||||
|
||||
#ifndef _COAP_H_
|
||||
#define _COAP_H_
|
||||
|
||||
#include "libcoap.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "address.h"
|
||||
#include "async.h"
|
||||
#include "bits.h"
|
||||
#include "block.h"
|
||||
#include "coap_io.h"
|
||||
#include "coap_time.h"
|
||||
#include "debug.h"
|
||||
#include "encode.h"
|
||||
#include "mem.h"
|
||||
#include "net.h"
|
||||
#include "option.h"
|
||||
#include "pdu.h"
|
||||
#include "prng.h"
|
||||
#include "resource.h"
|
||||
#include "str.h"
|
||||
#include "subscribe.h"
|
||||
#include "uri.h"
|
||||
#include "uthash.h"
|
||||
#include "utlist.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _COAP_H_ */
|
39
components/coap/port/include/coap_config.h
Normal file
39
components/coap/port/include/coap_config.h
Normal file
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* libcoap configure implementation for ESP32 platform.
|
||||
*
|
||||
* Uses libcoap software implementation for failover when concurrent
|
||||
* configure operations are in use.
|
||||
*
|
||||
* coap.h -- main header file for CoAP stack of libcoap
|
||||
*
|
||||
* Copyright (C) 2010-2012,2015-2016 Olaf Bergmann <bergmann@tzi.org>
|
||||
* 2015 Carsten Schoenert <c.schoenert@t-online.de>
|
||||
*
|
||||
* Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
||||
*
|
||||
* This file is part of the CoAP library libcoap. Please see README for terms
|
||||
* of use.
|
||||
*/
|
||||
|
||||
#ifndef _CONFIG_H_
|
||||
#define _CONFIG_H_
|
||||
|
||||
#ifdef WITH_POSIX
|
||||
#include "coap_config_posix.h"
|
||||
#endif
|
||||
|
||||
#define HAVE_STDIO_H
|
||||
#define HAVE_ASSERT_H
|
||||
|
||||
#define PACKAGE_STRING PACKAGE_NAME PACKAGE_VERSION
|
||||
|
||||
/* it's just provided by libc. i hope we don't get too many of those, as
|
||||
* actually we'd need autotools again to find out what environment we're
|
||||
* building in */
|
||||
#define HAVE_STRNLEN 1
|
||||
|
||||
#define HAVE_LIMITS_H
|
||||
|
||||
#define COAP_RESOURCES_NOHASH
|
||||
|
||||
#endif /* _CONFIG_H_ */
|
41
components/coap/port/include/coap_config_posix.h
Normal file
41
components/coap/port/include/coap_config_posix.h
Normal file
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* libcoap configure implementation for ESP32 platform.
|
||||
*
|
||||
* Uses libcoap software implementation for failover when concurrent
|
||||
* configure operations are in use.
|
||||
*
|
||||
* coap.h -- main header file for CoAP stack of libcoap
|
||||
*
|
||||
* Copyright (C) 2010-2012,2015-2016 Olaf Bergmann <bergmann@tzi.org>
|
||||
* 2015 Carsten Schoenert <c.schoenert@t-online.de>
|
||||
*
|
||||
* Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
||||
*
|
||||
* This file is part of the CoAP library libcoap. Please see README for terms
|
||||
* of use.
|
||||
*/
|
||||
|
||||
#ifndef COAP_CONFIG_POSIX_H_
|
||||
#define COAP_CONFIG_POSIX_H_
|
||||
|
||||
#ifdef WITH_POSIX
|
||||
|
||||
#include <sys/socket.h>
|
||||
|
||||
#define HAVE_SYS_SOCKET_H
|
||||
#define HAVE_MALLOC
|
||||
#define HAVE_ARPA_INET_H
|
||||
|
||||
#define IP_PKTINFO IP_MULTICAST_IF
|
||||
#define IPV6_PKTINFO IPV6_V6ONLY
|
||||
|
||||
#define PACKAGE_NAME "libcoap-posix"
|
||||
#define PACKAGE_VERSION "?"
|
||||
|
||||
#define CUSTOM_COAP_NETWORK_ENDPOINT
|
||||
#define CUSTOM_COAP_NETWORK_SEND
|
||||
#define CUSTOM_COAP_NETWORK_READ
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* COAP_CONFIG_POSIX_H_ */
|
3
components/cxx/component.mk
Normal file
3
components/cxx/component.mk
Normal file
@ -0,0 +1,3 @@
|
||||
# Mark __cxa_guard_dummy as undefined so that implementation of static guards
|
||||
# is taken from cxx_guards.o instead of libstdc++.a
|
||||
COMPONENT_ADD_LDFLAGS := -l$(COMPONENT_NAME) -u __cxa_guard_dummy
|
216
components/cxx/cxx_guards.cpp
Normal file
216
components/cxx/cxx_guards.cpp
Normal file
@ -0,0 +1,216 @@
|
||||
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// 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.
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <cxxabi.h>
|
||||
#include <stdint.h>
|
||||
#include <limits.h>
|
||||
#include <algorithm>
|
||||
#include <sys/lock.h>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include "freertos/task.h"
|
||||
|
||||
using __cxxabiv1::__guard;
|
||||
|
||||
static SemaphoreHandle_t s_static_init_mutex = NULL; //!< lock used for the critical section
|
||||
static SemaphoreHandle_t s_static_init_wait_sem = NULL; //!< counting semaphore used by the waiting tasks
|
||||
static portMUX_TYPE s_init_spinlock = portMUX_INITIALIZER_UNLOCKED; //!< spinlock used to guard initialization of the above two primitives
|
||||
static size_t s_static_init_waiting_count = 0; //!< number of tasks which are waiting for static init guards
|
||||
#ifndef _NDEBUG
|
||||
static size_t s_static_init_max_waiting_count = 0; //!< maximum ever value of the above; can be inspected using GDB for debugging purposes
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* Layout of the guard object (defined by the ABI).
|
||||
*
|
||||
* Compiler will check lower byte before calling guard functions.
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t ready; //!< nonzero if initialization is done
|
||||
uint8_t pending; //!< nonzero if initialization is in progress
|
||||
} guard_t;
|
||||
|
||||
static void static_init_prepare()
|
||||
{
|
||||
portENTER_CRITICAL(&s_init_spinlock);
|
||||
if (s_static_init_mutex == NULL) {
|
||||
s_static_init_mutex = xSemaphoreCreateMutex();
|
||||
s_static_init_wait_sem = xSemaphoreCreateCounting(INT_MAX, 0);
|
||||
if (s_static_init_mutex == NULL || s_static_init_wait_sem == NULL) {
|
||||
// no way to bail out of static initialization without these
|
||||
abort();
|
||||
}
|
||||
}
|
||||
portEXIT_CRITICAL(&s_init_spinlock);
|
||||
}
|
||||
|
||||
/**
|
||||
* Use s_static_init_wait_sem to wait until guard->pending == 0.
|
||||
* Preconditions:
|
||||
* - s_static_init_mutex taken
|
||||
* - guard.pending == 1
|
||||
* Postconditions:
|
||||
* - s_static_init_mutex taken
|
||||
* - guard.pending == 0
|
||||
*/
|
||||
static void wait_for_guard_obj(guard_t* g)
|
||||
{
|
||||
s_static_init_waiting_count++;
|
||||
#ifndef _NDEBUG
|
||||
s_static_init_max_waiting_count = std::max(s_static_init_waiting_count,
|
||||
s_static_init_max_waiting_count);
|
||||
#endif
|
||||
|
||||
do {
|
||||
auto result = xSemaphoreGive(s_static_init_mutex);
|
||||
assert(result);
|
||||
/* Task may be preempted here, but this isn't a problem,
|
||||
* as the semaphore will be given exactly the s_static_init_waiting_count
|
||||
* number of times; eventually the current task will execute next statement,
|
||||
* which will immediately succeed.
|
||||
*/
|
||||
result = xSemaphoreTake(s_static_init_wait_sem, portMAX_DELAY);
|
||||
assert(result);
|
||||
/* At this point the semaphore was given, so all waiting tasks have woken up.
|
||||
* We take s_static_init_mutex before accessing the state of the guard
|
||||
* object again.
|
||||
*/
|
||||
result = xSemaphoreTake(s_static_init_mutex, portMAX_DELAY);
|
||||
assert(result);
|
||||
/* Semaphore may have been given because some other guard object became ready.
|
||||
* Check the guard object we need and wait again if it is still pending.
|
||||
*/
|
||||
} while(g->pending);
|
||||
s_static_init_waiting_count--;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unblock tasks waiting for static initialization to complete.
|
||||
* Preconditions:
|
||||
* - s_static_init_mutex taken
|
||||
* Postconditions:
|
||||
* - s_static_init_mutex taken
|
||||
*/
|
||||
static void signal_waiting_tasks()
|
||||
{
|
||||
auto count = s_static_init_waiting_count;
|
||||
while (count--) {
|
||||
xSemaphoreGive(s_static_init_wait_sem);
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" int __cxa_guard_acquire(__guard* pg)
|
||||
{
|
||||
guard_t* g = reinterpret_cast<guard_t*>(pg);
|
||||
const auto scheduler_started = xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED;
|
||||
if (!scheduler_started) {
|
||||
if (g->pending) {
|
||||
/* Before the scheduler has started, there we don't support simultaneous
|
||||
* static initialization. This may be implemented using a spinlock and a
|
||||
* s32c1i instruction, though.
|
||||
*/
|
||||
abort();
|
||||
}
|
||||
} else {
|
||||
if (s_static_init_mutex == NULL) {
|
||||
static_init_prepare();
|
||||
}
|
||||
|
||||
/* We don't need to use double-checked locking pattern here, as the compiler
|
||||
* must generate code to check if the first byte of *pg is non-zero, before
|
||||
* calling __cxa_guard_acquire.
|
||||
*/
|
||||
auto result = xSemaphoreTake(s_static_init_mutex, portMAX_DELAY);
|
||||
assert(result);
|
||||
if (g->pending) {
|
||||
/* Another task is doing initialization at the moment; wait until it calls
|
||||
* __cxa_guard_release or __cxa_guard_abort
|
||||
*/
|
||||
wait_for_guard_obj(g);
|
||||
/* At this point there are two scenarios:
|
||||
* - the task which was doing static initialization has called __cxa_guard_release,
|
||||
* which means that g->ready is set. We need to return 0.
|
||||
* - the task which was doing static initialization has called __cxa_guard_abort,
|
||||
* which means that g->ready is not set; we should acquire the guard and return 1,
|
||||
* same as for the case if we didn't have to wait.
|
||||
* Note: actually the second scenario is unlikely to occur in the current
|
||||
* configuration because exception support is disabled.
|
||||
*/
|
||||
}
|
||||
}
|
||||
int ret;
|
||||
if (g->ready) {
|
||||
/* Static initialization has been done by another task; nothing to do here */
|
||||
ret = 0;
|
||||
} else {
|
||||
/* Current task can start doing static initialization */
|
||||
g->pending = 1;
|
||||
ret = 1;
|
||||
}
|
||||
if (scheduler_started) {
|
||||
auto result = xSemaphoreGive(s_static_init_mutex);
|
||||
assert(result);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
extern "C" void __cxa_guard_release(__guard* pg)
|
||||
{
|
||||
guard_t* g = reinterpret_cast<guard_t*>(pg);
|
||||
const auto scheduler_started = xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED;
|
||||
if (scheduler_started) {
|
||||
auto result = xSemaphoreTake(s_static_init_mutex, portMAX_DELAY);
|
||||
assert(result);
|
||||
}
|
||||
assert(g->pending && "tried to release a guard which wasn't acquired");
|
||||
g->pending = 0;
|
||||
/* Initialization was successful */
|
||||
g->ready = 1;
|
||||
if (scheduler_started) {
|
||||
/* Unblock the tasks waiting for static initialization to complete */
|
||||
signal_waiting_tasks();
|
||||
auto result = xSemaphoreGive(s_static_init_mutex);
|
||||
assert(result);
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" void __cxa_guard_abort(__guard* pg)
|
||||
{
|
||||
guard_t* g = reinterpret_cast<guard_t*>(pg);
|
||||
const auto scheduler_started = xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED;
|
||||
if (scheduler_started) {
|
||||
auto result = xSemaphoreTake(s_static_init_mutex, portMAX_DELAY);
|
||||
assert(result);
|
||||
}
|
||||
assert(!g->ready && "tried to abort a guard which is ready");
|
||||
assert(g->pending && "tried to release a guard which is not acquired");
|
||||
g->pending = 0;
|
||||
if (scheduler_started) {
|
||||
/* Unblock the tasks waiting for static initialization to complete */
|
||||
signal_waiting_tasks();
|
||||
auto result = xSemaphoreGive(s_static_init_mutex);
|
||||
assert(result);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Dummy function used to force linking this file instead of the same one in libstdc++.
|
||||
* This works via -u __cxa_guard_dummy flag in component.mk
|
||||
*/
|
||||
extern "C" void __cxa_guard_dummy()
|
||||
{
|
||||
}
|
1
components/cxx/test/component.mk
Normal file
1
components/cxx/test/component.mk
Normal file
@ -0,0 +1 @@
|
||||
COMPONENT_ADD_LDFLAGS = -Wl,--whole-archive -l$(COMPONENT_NAME) -Wl,--no-whole-archive
|
210
components/cxx/test/test_cxx.cpp
Normal file
210
components/cxx/test/test_cxx.cpp
Normal file
@ -0,0 +1,210 @@
|
||||
#include <functional>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
#include "unity.h"
|
||||
#include "esp_log.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/semphr.h"
|
||||
|
||||
static const char* TAG = "cxx";
|
||||
|
||||
TEST_CASE("can use new and delete", "[cxx]")
|
||||
{
|
||||
int* int_p = new int(10);
|
||||
delete int_p;
|
||||
int* int_array = new int[10];
|
||||
delete[] int_array;
|
||||
}
|
||||
|
||||
class Base
|
||||
{
|
||||
public:
|
||||
virtual ~Base() {}
|
||||
virtual void foo() = 0;
|
||||
};
|
||||
|
||||
class Derived : public Base
|
||||
{
|
||||
public:
|
||||
virtual void foo() { }
|
||||
};
|
||||
|
||||
TEST_CASE("can call virtual functions", "[cxx]")
|
||||
{
|
||||
Derived d;
|
||||
Base& b = static_cast<Base&>(d);
|
||||
b.foo();
|
||||
}
|
||||
|
||||
class NonPOD
|
||||
{
|
||||
public:
|
||||
NonPOD(int a_) : a(a_) { }
|
||||
int a;
|
||||
};
|
||||
|
||||
static int non_pod_test_helper(int new_val)
|
||||
{
|
||||
static NonPOD non_pod(42);
|
||||
int ret = non_pod.a;
|
||||
non_pod.a = new_val;
|
||||
return ret;
|
||||
}
|
||||
|
||||
TEST_CASE("can use static initializers for non-POD types", "[cxx]")
|
||||
{
|
||||
TEST_ASSERT_EQUAL(42, non_pod_test_helper(1));
|
||||
TEST_ASSERT_EQUAL(1, non_pod_test_helper(0));
|
||||
}
|
||||
|
||||
TEST_CASE("can call std::function and bind", "[cxx]")
|
||||
{
|
||||
int outer = 1;
|
||||
std::function<int(int)> fn = [&outer](int x) -> int {
|
||||
return x + outer;
|
||||
};
|
||||
outer = 5;
|
||||
TEST_ASSERT_EQUAL(6, fn(1));
|
||||
|
||||
auto bound = std::bind(fn, outer);
|
||||
outer = 10;
|
||||
TEST_ASSERT_EQUAL(15, bound());
|
||||
}
|
||||
|
||||
TEST_CASE("can use std::vector", "[cxx]")
|
||||
{
|
||||
std::vector<int> v(10, 1);
|
||||
v[0] = 42;
|
||||
TEST_ASSERT_EQUAL(51, std::accumulate(std::begin(v), std::end(v), 0));
|
||||
}
|
||||
|
||||
/*
|
||||
* This test exercises static initialization guards for two objects.
|
||||
* For each object, 4 tasks are created which attempt to perform static initialization.
|
||||
* We check that constructor runs only once for each object.
|
||||
*/
|
||||
|
||||
static SemaphoreHandle_t s_slow_init_sem = NULL;
|
||||
|
||||
template<int obj>
|
||||
class SlowInit
|
||||
{
|
||||
public:
|
||||
SlowInit(int arg) {
|
||||
ESP_LOGD(TAG, "init obj=%d start, arg=%d\n", obj, arg);
|
||||
vTaskDelay(300/portTICK_PERIOD_MS);
|
||||
TEST_ASSERT_EQUAL(-1, mInitBy);
|
||||
TEST_ASSERT_EQUAL(0, mInitCount);
|
||||
mInitBy = arg;
|
||||
++mInitCount;
|
||||
ESP_LOGD(TAG, "init obj=%d done\n", obj);
|
||||
}
|
||||
|
||||
static void task(void* arg) {
|
||||
int taskId = reinterpret_cast<int>(arg);
|
||||
ESP_LOGD(TAG, "obj=%d before static init, task=%d\n", obj, taskId);
|
||||
static SlowInit slowinit(taskId);
|
||||
ESP_LOGD(TAG, "obj=%d after static init, task=%d\n", obj, taskId);
|
||||
xSemaphoreGive(s_slow_init_sem);
|
||||
vTaskDelay(10);
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
private:
|
||||
static int mInitBy;
|
||||
static int mInitCount;
|
||||
};
|
||||
|
||||
template<> int SlowInit<1>::mInitBy = -1;
|
||||
template<> int SlowInit<1>::mInitCount = 0;
|
||||
template<> int SlowInit<2>::mInitBy = -1;
|
||||
template<> int SlowInit<2>::mInitCount = 0;
|
||||
|
||||
template<int obj>
|
||||
static void start_slow_init_task(int id, int affinity)
|
||||
{
|
||||
xTaskCreatePinnedToCore(&SlowInit<obj>::task, "slow_init", 2048,
|
||||
reinterpret_cast<void*>(id), 3, NULL, affinity);
|
||||
}
|
||||
|
||||
TEST_CASE("static initialization guards work as expected", "[cxx]")
|
||||
{
|
||||
s_slow_init_sem = xSemaphoreCreateCounting(10, 0);
|
||||
TEST_ASSERT_NOT_NULL(s_slow_init_sem);
|
||||
// four tasks competing for static initialization of one object
|
||||
start_slow_init_task<1>(0, PRO_CPU_NUM);
|
||||
start_slow_init_task<1>(1, APP_CPU_NUM);
|
||||
start_slow_init_task<1>(2, PRO_CPU_NUM);
|
||||
start_slow_init_task<1>(3, tskNO_AFFINITY);
|
||||
|
||||
// four tasks competing for static initialization of another object
|
||||
start_slow_init_task<2>(0, PRO_CPU_NUM);
|
||||
start_slow_init_task<2>(1, APP_CPU_NUM);
|
||||
start_slow_init_task<2>(2, PRO_CPU_NUM);
|
||||
start_slow_init_task<2>(3, tskNO_AFFINITY);
|
||||
|
||||
// All tasks should
|
||||
for (int i = 0; i < 8; ++i) {
|
||||
TEST_ASSERT_TRUE(xSemaphoreTake(s_slow_init_sem, 500/portTICK_PERIOD_MS));
|
||||
}
|
||||
vSemaphoreDelete(s_slow_init_sem);
|
||||
}
|
||||
|
||||
struct GlobalInitTest
|
||||
{
|
||||
GlobalInitTest() : index(order++) {
|
||||
}
|
||||
int index;
|
||||
static int order;
|
||||
};
|
||||
|
||||
int GlobalInitTest::order = 0;
|
||||
|
||||
GlobalInitTest g_init_test1;
|
||||
GlobalInitTest g_init_test2;
|
||||
GlobalInitTest g_init_test3;
|
||||
|
||||
TEST_CASE("global initializers run in the correct order", "[cxx]")
|
||||
{
|
||||
TEST_ASSERT_EQUAL(0, g_init_test1.index);
|
||||
TEST_ASSERT_EQUAL(1, g_init_test2.index);
|
||||
TEST_ASSERT_EQUAL(2, g_init_test3.index);
|
||||
}
|
||||
|
||||
struct StaticInitTestBeforeScheduler
|
||||
{
|
||||
StaticInitTestBeforeScheduler()
|
||||
{
|
||||
static int first_init_order = getOrder();
|
||||
index = first_init_order;
|
||||
}
|
||||
|
||||
int getOrder()
|
||||
{
|
||||
return order++;
|
||||
}
|
||||
|
||||
int index;
|
||||
static int order;
|
||||
};
|
||||
|
||||
int StaticInitTestBeforeScheduler::order = 1;
|
||||
|
||||
StaticInitTestBeforeScheduler g_static_init_test1;
|
||||
StaticInitTestBeforeScheduler g_static_init_test2;
|
||||
StaticInitTestBeforeScheduler g_static_init_test3;
|
||||
|
||||
TEST_CASE("before scheduler has started, static initializers work correctly", "[cxx]")
|
||||
{
|
||||
TEST_ASSERT_EQUAL(1, g_static_init_test1.index);
|
||||
TEST_ASSERT_EQUAL(1, g_static_init_test2.index);
|
||||
TEST_ASSERT_EQUAL(1, g_static_init_test3.index);
|
||||
TEST_ASSERT_EQUAL(2, StaticInitTestBeforeScheduler::order);
|
||||
}
|
||||
|
||||
|
||||
TEST_CASE("can use iostreams", "[cxx]")
|
||||
{
|
||||
std::cout << "hello world";
|
||||
}
|
@ -72,45 +72,59 @@ const uint32_t GPIO_PIN_MUX_REG[GPIO_PIN_COUNT] = {
|
||||
GPIO_PIN_REG_39
|
||||
};
|
||||
|
||||
esp_err_t gpio_pullup_en(gpio_num_t gpio_num) {
|
||||
typedef struct {
|
||||
gpio_isr_t fn; /*!< isr function */
|
||||
void* args; /*!< isr function args */
|
||||
} gpio_isr_func_t;
|
||||
|
||||
static gpio_isr_func_t* gpio_isr_func = NULL;
|
||||
static gpio_isr_handle_t gpio_isr_handle;
|
||||
static portMUX_TYPE gpio_spinlock = portMUX_INITIALIZER_UNLOCKED;
|
||||
|
||||
esp_err_t gpio_pullup_en(gpio_num_t gpio_num)
|
||||
{
|
||||
GPIO_CHECK(GPIO_IS_VALID_GPIO(gpio_num), "GPIO number error", ESP_ERR_INVALID_ARG);
|
||||
if(RTC_GPIO_IS_VALID_GPIO(gpio_num)){
|
||||
if (RTC_GPIO_IS_VALID_GPIO(gpio_num)) {
|
||||
rtc_gpio_pullup_en(gpio_num);
|
||||
}else{
|
||||
} else {
|
||||
REG_SET_BIT(GPIO_PIN_MUX_REG[gpio_num], FUN_PU);
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t gpio_pullup_dis(gpio_num_t gpio_num) {
|
||||
esp_err_t gpio_pullup_dis(gpio_num_t gpio_num)
|
||||
{
|
||||
GPIO_CHECK(GPIO_IS_VALID_GPIO(gpio_num), "GPIO number error", ESP_ERR_INVALID_ARG);
|
||||
if(RTC_GPIO_IS_VALID_GPIO(gpio_num)){
|
||||
if (RTC_GPIO_IS_VALID_GPIO(gpio_num)) {
|
||||
rtc_gpio_pullup_dis(gpio_num);
|
||||
}else{
|
||||
} else {
|
||||
REG_CLR_BIT(GPIO_PIN_MUX_REG[gpio_num], FUN_PU);
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t gpio_pulldown_en(gpio_num_t gpio_num) {
|
||||
esp_err_t gpio_pulldown_en(gpio_num_t gpio_num)
|
||||
{
|
||||
GPIO_CHECK(GPIO_IS_VALID_GPIO(gpio_num), "GPIO number error", ESP_ERR_INVALID_ARG);
|
||||
if(RTC_GPIO_IS_VALID_GPIO(gpio_num)){
|
||||
if (RTC_GPIO_IS_VALID_GPIO(gpio_num)) {
|
||||
rtc_gpio_pulldown_en(gpio_num);
|
||||
}else{
|
||||
} else {
|
||||
REG_SET_BIT(GPIO_PIN_MUX_REG[gpio_num], FUN_PD);
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t gpio_pulldown_dis(gpio_num_t gpio_num) {
|
||||
esp_err_t gpio_pulldown_dis(gpio_num_t gpio_num)
|
||||
{
|
||||
GPIO_CHECK(GPIO_IS_VALID_GPIO(gpio_num), "GPIO number error", ESP_ERR_INVALID_ARG);
|
||||
if(RTC_GPIO_IS_VALID_GPIO(gpio_num)){
|
||||
if (RTC_GPIO_IS_VALID_GPIO(gpio_num)) {
|
||||
rtc_gpio_pulldown_dis(gpio_num);
|
||||
}else{
|
||||
} else {
|
||||
REG_CLR_BIT(GPIO_PIN_MUX_REG[gpio_num], FUN_PD);
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t gpio_set_intr_type(gpio_num_t gpio_num, gpio_int_type_t intr_type)
|
||||
{
|
||||
GPIO_CHECK(GPIO_IS_VALID_GPIO(gpio_num), "GPIO number error", ESP_ERR_INVALID_ARG);
|
||||
@ -161,7 +175,7 @@ static esp_err_t gpio_output_enable(gpio_num_t gpio_num)
|
||||
|
||||
esp_err_t gpio_set_level(gpio_num_t gpio_num, uint32_t level)
|
||||
{
|
||||
GPIO_CHECK(GPIO_IS_VALID_GPIO(gpio_num), "GPIO number error", ESP_ERR_INVALID_ARG);
|
||||
GPIO_CHECK(GPIO_IS_VALID_OUTPUT_GPIO(gpio_num), "GPIO output gpio_num error", ESP_ERR_INVALID_ARG);
|
||||
if (level) {
|
||||
if (gpio_num < 32) {
|
||||
GPIO.out_w1ts = (1 << gpio_num);
|
||||
@ -323,6 +337,96 @@ esp_err_t gpio_config(gpio_config_t *pGPIOConfig)
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
void IRAM_ATTR gpio_intr_service(void* arg)
|
||||
{
|
||||
//GPIO intr process
|
||||
uint32_t gpio_num = 0;
|
||||
//read status to get interrupt status for GPIO0-31
|
||||
uint32_t gpio_intr_status;
|
||||
gpio_intr_status = GPIO.status;
|
||||
//read status1 to get interrupt status for GPIO32-39
|
||||
uint32_t gpio_intr_status_h;
|
||||
gpio_intr_status_h = GPIO.status1.intr_st;
|
||||
|
||||
if (gpio_isr_func == NULL) {
|
||||
return;
|
||||
}
|
||||
do {
|
||||
if (gpio_num < 32) {
|
||||
if (gpio_intr_status & BIT(gpio_num)) { //gpio0-gpio31
|
||||
if (gpio_isr_func[gpio_num].fn != NULL) {
|
||||
gpio_isr_func[gpio_num].fn(gpio_isr_func[gpio_num].args);
|
||||
}
|
||||
GPIO.status_w1tc = BIT(gpio_num);
|
||||
}
|
||||
} else {
|
||||
if (gpio_intr_status_h & BIT(gpio_num - 32)) {
|
||||
if (gpio_isr_func[gpio_num].fn != NULL) {
|
||||
gpio_isr_func[gpio_num].fn(gpio_isr_func[gpio_num].args);
|
||||
}
|
||||
GPIO.status1_w1tc.intr_st = BIT(gpio_num - 32);
|
||||
}
|
||||
}
|
||||
} while (++gpio_num < GPIO_PIN_COUNT);
|
||||
}
|
||||
|
||||
esp_err_t gpio_isr_handler_add(gpio_num_t gpio_num, gpio_isr_t isr_handler, void* args)
|
||||
{
|
||||
GPIO_CHECK(gpio_isr_func != NULL, "GPIO isr service is not installed, call gpio_install_isr_service() first", ESP_ERR_INVALID_STATE);
|
||||
GPIO_CHECK(GPIO_IS_VALID_GPIO(gpio_num), "GPIO number error", ESP_ERR_INVALID_ARG);
|
||||
portENTER_CRITICAL(&gpio_spinlock);
|
||||
gpio_intr_disable(gpio_num);
|
||||
if (gpio_isr_func) {
|
||||
gpio_isr_func[gpio_num].fn = isr_handler;
|
||||
gpio_isr_func[gpio_num].args = args;
|
||||
}
|
||||
gpio_intr_enable(gpio_num);
|
||||
portEXIT_CRITICAL(&gpio_spinlock);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t gpio_isr_handler_remove(gpio_num_t gpio_num)
|
||||
{
|
||||
GPIO_CHECK(gpio_isr_func != NULL, "GPIO isr service is not installed, call gpio_install_isr_service() first", ESP_ERR_INVALID_STATE);
|
||||
GPIO_CHECK(GPIO_IS_VALID_GPIO(gpio_num), "GPIO number error", ESP_ERR_INVALID_ARG);
|
||||
portENTER_CRITICAL(&gpio_spinlock);
|
||||
gpio_intr_disable(gpio_num);
|
||||
if (gpio_isr_func) {
|
||||
gpio_isr_func[gpio_num].fn = NULL;
|
||||
gpio_isr_func[gpio_num].args = NULL;
|
||||
}
|
||||
portEXIT_CRITICAL(&gpio_spinlock);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t gpio_install_isr_service(int intr_alloc_flags)
|
||||
{
|
||||
GPIO_CHECK(gpio_isr_func == NULL, "GPIO isr service already installed", ESP_FAIL);
|
||||
esp_err_t ret;
|
||||
portENTER_CRITICAL(&gpio_spinlock);
|
||||
gpio_isr_func = (gpio_isr_func_t*) calloc(GPIO_NUM_MAX, sizeof(gpio_isr_func_t));
|
||||
if (gpio_isr_func == NULL) {
|
||||
ret = ESP_ERR_NO_MEM;
|
||||
} else {
|
||||
ret = gpio_isr_register(gpio_intr_service, NULL, intr_alloc_flags, &gpio_isr_handle);
|
||||
}
|
||||
portEXIT_CRITICAL(&gpio_spinlock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void gpio_uninstall_isr_service()
|
||||
{
|
||||
if (gpio_isr_func == NULL) {
|
||||
return;
|
||||
}
|
||||
portENTER_CRITICAL(&gpio_spinlock);
|
||||
esp_intr_free(gpio_isr_handle);
|
||||
free(gpio_isr_func);
|
||||
gpio_isr_func = NULL;
|
||||
portEXIT_CRITICAL(&gpio_spinlock);
|
||||
return;
|
||||
}
|
||||
|
||||
esp_err_t gpio_isr_register(void (*fn)(void*), void * arg, int intr_alloc_flags, gpio_isr_handle_t *handle)
|
||||
{
|
||||
GPIO_CHECK(fn, "GPIO ISR null", ESP_ERR_INVALID_ARG);
|
||||
@ -334,7 +438,7 @@ esp_err_t gpio_wakeup_enable(gpio_num_t gpio_num, gpio_int_type_t intr_type)
|
||||
{
|
||||
GPIO_CHECK(GPIO_IS_VALID_GPIO(gpio_num), "GPIO number error", ESP_ERR_INVALID_ARG);
|
||||
esp_err_t ret = ESP_OK;
|
||||
if ((intr_type == GPIO_INTR_LOW_LEVEL) || (intr_type == GPIO_INTR_HIGH_LEVEL)) {
|
||||
if (( intr_type == GPIO_INTR_LOW_LEVEL ) || ( intr_type == GPIO_INTR_HIGH_LEVEL )) {
|
||||
GPIO.pin[gpio_num].int_type = intr_type;
|
||||
GPIO.pin[gpio_num].wakeup_enable = 0x1;
|
||||
} else {
|
||||
|
1037
components/driver/i2c.c
Normal file
1037
components/driver/i2c.c
Normal file
File diff suppressed because it is too large
Load Diff
807
components/driver/i2s.c
Normal file
807
components/driver/i2s.c
Normal file
@ -0,0 +1,807 @@
|
||||
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// 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.
|
||||
#include <string.h>
|
||||
#include <esp_types.h>
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/queue.h"
|
||||
#include "freertos/xtensa_api.h"
|
||||
|
||||
#include "soc/dport_reg.h"
|
||||
#include "soc/rtc_cntl_reg.h"
|
||||
#include "soc/rtc_io_reg.h"
|
||||
#include "soc/sens_reg.h"
|
||||
#include "rom/lldesc.h"
|
||||
|
||||
#include "driver/gpio.h"
|
||||
#include "driver/i2s.h"
|
||||
|
||||
#include "esp_intr.h"
|
||||
#include "esp_err.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
static const char* I2S_TAG = "I2S";
|
||||
#define I2S_CHECK(a, str, ret) if (!(a)) { \
|
||||
ESP_LOGE(I2S_TAG,"%s:%d (%s):%s", __FILE__, __LINE__, __FUNCTION__, str); \
|
||||
return (ret); \
|
||||
}
|
||||
#define I2S_BASE_CLK (2*APB_CLK_FREQ)
|
||||
#define I2S_ENTER_CRITICAL_ISR() portENTER_CRITICAL_ISR(&i2s_spinlock[i2s_num])
|
||||
#define I2S_EXIT_CRITICAL_ISR() portEXIT_CRITICAL_ISR(&i2s_spinlock[i2s_num])
|
||||
#define I2S_ENTER_CRITICAL() portENTER_CRITICAL(&i2s_spinlock[i2s_num])
|
||||
#define I2S_EXIT_CRITICAL() portEXIT_CRITICAL(&i2s_spinlock[i2s_num])
|
||||
#define gpio_matrix_out_check(a, b, c, d) if(a != -1) gpio_matrix_out(a, b, c, d) //if pin = -1, do not need to configure
|
||||
#define gpio_matrix_in_check(a, b, c) if(a != -1) gpio_matrix_in(a, b, c)
|
||||
|
||||
|
||||
/**
|
||||
* @brief DMA buffer object
|
||||
*
|
||||
*/
|
||||
typedef struct {
|
||||
char **buf;
|
||||
int buf_size;
|
||||
int rw_pos;
|
||||
void *curr_ptr;
|
||||
SemaphoreHandle_t mux;
|
||||
xQueueHandle queue;
|
||||
lldesc_t **desc;
|
||||
} i2s_dma_t;
|
||||
|
||||
/**
|
||||
* @brief I2S object instance
|
||||
*
|
||||
*/
|
||||
typedef struct {
|
||||
i2s_port_t i2s_num; /*!< I2S port number*/
|
||||
int queue_size; /*!< I2S event queue size*/
|
||||
QueueHandle_t i2s_queue; /*!< I2S queue handler*/
|
||||
int dma_buf_count; /*!< DMA buffer count, number of buffer*/
|
||||
int dma_buf_len; /*!< DMA buffer length, length of each buffer*/
|
||||
i2s_dma_t *rx; /*!< DMA Tx buffer*/
|
||||
i2s_dma_t *tx; /*!< DMA Rx buffer*/
|
||||
i2s_isr_handle_t i2s_isr_handle; /*!< I2S Interrupt handle*/
|
||||
int channel_num; /*!< Number of channels*/
|
||||
int bytes_per_sample; /*!< Bytes per sample*/
|
||||
i2s_mode_t mode; /*!< I2S Working mode*/
|
||||
} i2s_obj_t;
|
||||
|
||||
static i2s_obj_t *p_i2s_obj[I2S_NUM_MAX] = {0};
|
||||
static i2s_dev_t* I2S[I2S_NUM_MAX] = {&I2S0, &I2S1};
|
||||
static portMUX_TYPE i2s_spinlock[I2S_NUM_MAX] = {portMUX_INITIALIZER_UNLOCKED, portMUX_INITIALIZER_UNLOCKED};
|
||||
static esp_err_t i2s_reset_fifo(i2s_port_t i2s_num)
|
||||
{
|
||||
I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_FAIL);
|
||||
I2S_ENTER_CRITICAL();
|
||||
I2S[i2s_num]->conf.rx_fifo_reset = 1;
|
||||
I2S[i2s_num]->conf.rx_fifo_reset = 0;
|
||||
I2S[i2s_num]->conf.tx_fifo_reset = 1;
|
||||
I2S[i2s_num]->conf.tx_fifo_reset = 0;
|
||||
I2S_EXIT_CRITICAL();
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t i2s_clear_intr_status(i2s_port_t i2s_num, uint32_t clr_mask)
|
||||
{
|
||||
I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_FAIL);
|
||||
I2S[i2s_num]->int_clr.val = clr_mask;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t i2s_enable_rx_intr(i2s_port_t i2s_num)
|
||||
{
|
||||
|
||||
I2S_ENTER_CRITICAL();
|
||||
I2S[i2s_num]->int_ena.in_suc_eof = 1;
|
||||
I2S[i2s_num]->int_ena.in_dscr_err = 1;
|
||||
I2S_EXIT_CRITICAL();
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t i2s_disable_rx_intr(i2s_port_t i2s_num)
|
||||
{
|
||||
I2S_ENTER_CRITICAL();
|
||||
I2S[i2s_num]->int_ena.in_suc_eof = 0;
|
||||
I2S[i2s_num]->int_ena.in_dscr_err = 0;
|
||||
I2S_EXIT_CRITICAL();
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t i2s_disable_tx_intr(i2s_port_t i2s_num)
|
||||
{
|
||||
I2S_ENTER_CRITICAL();
|
||||
I2S[i2s_num]->int_ena.out_eof = 0;
|
||||
I2S[i2s_num]->int_ena.out_dscr_err = 0;
|
||||
I2S_EXIT_CRITICAL();
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t i2s_enable_tx_intr(i2s_port_t i2s_num)
|
||||
{
|
||||
I2S_ENTER_CRITICAL();
|
||||
I2S[i2s_num]->int_ena.out_eof = 1;
|
||||
I2S[i2s_num]->int_ena.out_dscr_err = 1;
|
||||
I2S_EXIT_CRITICAL();
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t i2s_isr_register(i2s_port_t i2s_num, uint8_t intr_alloc_flags, void (*fn)(void*), void * arg, i2s_isr_handle_t *handle)
|
||||
{
|
||||
return esp_intr_alloc(ETS_I2S0_INTR_SOURCE + i2s_num, intr_alloc_flags, fn, arg, handle);
|
||||
}
|
||||
|
||||
static esp_err_t i2s_set_clk(i2s_port_t i2s_num, uint32_t rate, uint8_t bits, bool fuzzy)
|
||||
{
|
||||
int factor = (256%bits)? 384 : 256; // According to hardware codec requirement(supported 256fs or 384fs)
|
||||
int clkmInteger, clkmDecimals, bck = 0;
|
||||
float denom = (float)1 / 64;
|
||||
int channel = 2;
|
||||
|
||||
float clkmdiv = (float)I2S_BASE_CLK / (rate * factor);
|
||||
if (clkmdiv > 256) {
|
||||
ESP_LOGE(I2S_TAG, "clkmdiv is too large\r\n");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
clkmInteger = clkmdiv;
|
||||
clkmDecimals = (clkmdiv - clkmInteger) / denom;
|
||||
float mclk = clkmInteger + denom * clkmDecimals;
|
||||
bck = factor/(bits * channel);
|
||||
|
||||
I2S[i2s_num]->clkm_conf.clka_en = 0;
|
||||
I2S[i2s_num]->clkm_conf.clkm_div_a = 63;
|
||||
I2S[i2s_num]->clkm_conf.clkm_div_b = clkmDecimals;
|
||||
I2S[i2s_num]->clkm_conf.clkm_div_num = clkmInteger;
|
||||
I2S[i2s_num]->sample_rate_conf.tx_bck_div_num = bck;
|
||||
I2S[i2s_num]->sample_rate_conf.rx_bck_div_num = bck;
|
||||
I2S[i2s_num]->sample_rate_conf.tx_bits_mod = bits;
|
||||
I2S[i2s_num]->sample_rate_conf.rx_bits_mod = bits;
|
||||
float real_rate = (float)(I2S_BASE_CLK / (bck * bits * clkmInteger)/2);
|
||||
ESP_LOGI(I2S_TAG, "Req RATE: %d, real rate: %0.3f, BITS: %u, CLKM: %u, BCK: %u, MCLK: %0.3f, SCLK: %f, diva: %d, divb: %d",
|
||||
rate, real_rate, bits, clkmInteger, bck, (float)I2S_BASE_CLK / mclk, real_rate *16*2, 64, clkmDecimals);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static void IRAM_ATTR i2s_intr_handler_default(void *arg)
|
||||
{
|
||||
i2s_obj_t *p_i2s = (i2s_obj_t*) arg;
|
||||
uint8_t i2s_num = p_i2s->i2s_num;
|
||||
i2s_dev_t* i2s_reg = I2S[i2s_num];
|
||||
i2s_event_t i2s_event;
|
||||
int dummy;
|
||||
|
||||
portBASE_TYPE high_priority_task_awoken = 0;
|
||||
|
||||
lldesc_t *finish_desc;
|
||||
|
||||
if (i2s_reg->int_st.out_dscr_err || i2s_reg->int_st.in_dscr_err) {
|
||||
ESP_LOGE(I2S_TAG, "out_dscr_err: %d or in_dscr_err:%d", i2s_reg->int_st.out_dscr_err == 1, i2s_reg->int_st.in_dscr_err == 1);
|
||||
if (p_i2s->i2s_queue) {
|
||||
i2s_event.type = I2S_EVENT_DMA_ERROR;
|
||||
if (xQueueIsQueueFullFromISR(p_i2s->i2s_queue)) {
|
||||
xQueueReceiveFromISR(p_i2s->i2s_queue, &dummy, &high_priority_task_awoken);
|
||||
}
|
||||
xQueueSendFromISR(p_i2s->i2s_queue, (void * )&i2s_event, &high_priority_task_awoken);
|
||||
}
|
||||
}
|
||||
|
||||
if (i2s_reg->int_st.out_eof && p_i2s->tx) {
|
||||
finish_desc = (lldesc_t*) i2s_reg->out_eof_des_addr;
|
||||
// All buffers are empty. This means we have an underflow on our hands.
|
||||
if (xQueueIsQueueFullFromISR(p_i2s->tx->queue)) {
|
||||
xQueueReceiveFromISR(p_i2s->tx->queue, &dummy, &high_priority_task_awoken);
|
||||
}
|
||||
xQueueSendFromISR(p_i2s->tx->queue, (void*)(&finish_desc->buf), &high_priority_task_awoken);
|
||||
if (p_i2s->i2s_queue) {
|
||||
i2s_event.type = I2S_EVENT_TX_DONE;
|
||||
if (xQueueIsQueueFullFromISR(p_i2s->i2s_queue)) {
|
||||
xQueueReceiveFromISR(p_i2s->i2s_queue, &dummy, &high_priority_task_awoken);
|
||||
}
|
||||
xQueueSendFromISR(p_i2s->i2s_queue, (void * )&i2s_event, &high_priority_task_awoken);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (i2s_reg->int_st.in_suc_eof && p_i2s->rx) {
|
||||
// All buffers are full. This means we have an overflow.
|
||||
finish_desc = (lldesc_t*) i2s_reg->in_eof_des_addr;
|
||||
if (xQueueIsQueueFullFromISR(p_i2s->rx->queue)) {
|
||||
xQueueReceiveFromISR(p_i2s->rx->queue, &dummy, &high_priority_task_awoken);
|
||||
}
|
||||
xQueueSendFromISR(p_i2s->rx->queue, (void*)(&finish_desc->buf), &high_priority_task_awoken);
|
||||
if (p_i2s->i2s_queue) {
|
||||
i2s_event.type = I2S_EVENT_RX_DONE;
|
||||
if (p_i2s->i2s_queue && xQueueIsQueueFullFromISR(p_i2s->i2s_queue)) {
|
||||
xQueueReceiveFromISR(p_i2s->i2s_queue, &dummy, &high_priority_task_awoken);
|
||||
}
|
||||
xQueueSendFromISR(p_i2s->i2s_queue, (void * )&i2s_event, &high_priority_task_awoken);
|
||||
}
|
||||
}
|
||||
if (high_priority_task_awoken == pdTRUE) {
|
||||
portYIELD_FROM_ISR();
|
||||
}
|
||||
|
||||
i2s_reg->int_clr.val = I2S[i2s_num]->int_st.val;
|
||||
}
|
||||
|
||||
static esp_err_t i2s_destroy_dma_queue(i2s_port_t i2s_num, i2s_dma_t *dma)
|
||||
{
|
||||
int bux_idx;
|
||||
if (p_i2s_obj[i2s_num] == NULL) {
|
||||
ESP_LOGE(I2S_TAG, "Not initialized yet");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
if (dma == NULL) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
for (bux_idx = 0; bux_idx < p_i2s_obj[i2s_num]->dma_buf_count; bux_idx++) {
|
||||
if (dma->desc && dma->desc[bux_idx])
|
||||
free(dma->desc[bux_idx]);
|
||||
if (dma->buf && dma->buf[bux_idx])
|
||||
free(dma->buf[bux_idx]);
|
||||
}
|
||||
if (dma->buf)
|
||||
free(dma->buf);
|
||||
if (dma->desc)
|
||||
free(dma->desc);
|
||||
vQueueDelete(dma->queue);
|
||||
vSemaphoreDelete(dma->mux);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static i2s_dma_t *i2s_create_dma_queue(i2s_port_t i2s_num, int dma_buf_count, int dma_buf_len)
|
||||
{
|
||||
int bux_idx;
|
||||
int sample_size = p_i2s_obj[i2s_num]->bytes_per_sample * p_i2s_obj[i2s_num]->channel_num;
|
||||
i2s_dma_t *dma = (i2s_dma_t*) malloc(sizeof(i2s_dma_t));
|
||||
if (dma == NULL) {
|
||||
ESP_LOGE(I2S_TAG, "Error malloc i2s_dma_t");
|
||||
return NULL;
|
||||
}
|
||||
memset(dma, 0, sizeof(i2s_dma_t));
|
||||
|
||||
dma->buf = (char **)malloc(sizeof(char*) * dma_buf_count);
|
||||
if (dma->buf == NULL) {
|
||||
ESP_LOGE(I2S_TAG, "Error malloc dma buffer pointer");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
memset(dma->buf, 0, sizeof(char*) * dma_buf_count);
|
||||
|
||||
for (bux_idx = 0; bux_idx < dma_buf_count; bux_idx++) {
|
||||
dma->buf[bux_idx] = (char*) malloc(dma_buf_len * sample_size);
|
||||
if (dma->buf[bux_idx] == NULL) {
|
||||
ESP_LOGE(I2S_TAG, "Error malloc dma buffer");
|
||||
i2s_destroy_dma_queue(i2s_num, dma);
|
||||
return NULL;
|
||||
}
|
||||
ESP_LOGD(I2S_TAG, "Addr[%d] = %d", bux_idx, (int)dma->buf[bux_idx]);
|
||||
memset(dma->buf[bux_idx], 0, dma_buf_len * sample_size);
|
||||
}
|
||||
|
||||
dma->desc = (lldesc_t**) malloc(sizeof(lldesc_t*) * dma_buf_count);
|
||||
if (dma->desc == NULL) {
|
||||
ESP_LOGE(I2S_TAG, "Error malloc dma description");
|
||||
i2s_destroy_dma_queue(i2s_num, dma);
|
||||
return NULL;
|
||||
}
|
||||
for (bux_idx = 0; bux_idx < dma_buf_count; bux_idx++) {
|
||||
dma->desc[bux_idx] = (lldesc_t*) malloc(sizeof(lldesc_t));
|
||||
if (dma->desc[bux_idx] == NULL) {
|
||||
ESP_LOGE(I2S_TAG, "Error malloc dma description entry");
|
||||
i2s_destroy_dma_queue(i2s_num, dma);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
for (bux_idx = 0; bux_idx < dma_buf_count; bux_idx++) {
|
||||
dma->desc[bux_idx]->owner = 1;
|
||||
dma->desc[bux_idx]->eof = 1;
|
||||
dma->desc[bux_idx]->sosf = 0;
|
||||
dma->desc[bux_idx]->length = dma_buf_len * sample_size;
|
||||
dma->desc[bux_idx]->size = dma_buf_len * sample_size;
|
||||
dma->desc[bux_idx]->buf = (uint8_t *) dma->buf[bux_idx];
|
||||
dma->desc[bux_idx]->offset = 0;
|
||||
dma->desc[bux_idx]->empty = (uint32_t)((bux_idx < (dma_buf_count - 1)) ? (dma->desc[bux_idx + 1]) : dma->desc[0]);
|
||||
}
|
||||
dma->queue = xQueueCreate(dma_buf_count - 1, sizeof(char*));
|
||||
dma->mux = xSemaphoreCreateMutex();
|
||||
dma->rw_pos = 0;
|
||||
dma->buf_size = dma_buf_len * sample_size;
|
||||
dma->curr_ptr = NULL;
|
||||
ESP_LOGI(I2S_TAG, "DMA Malloc info, datalen=blocksize=%d, dma_buf_count=%d", dma_buf_len * sample_size, dma_buf_count);
|
||||
return dma;
|
||||
}
|
||||
|
||||
|
||||
esp_err_t i2s_start(i2s_port_t i2s_num)
|
||||
{
|
||||
//start DMA link
|
||||
I2S_ENTER_CRITICAL();
|
||||
esp_intr_disable(p_i2s_obj[i2s_num]->i2s_isr_handle);
|
||||
I2S[i2s_num]->int_clr.val = 0xFFFFFFFF;
|
||||
if (p_i2s_obj[i2s_num]->mode & I2S_MODE_TX) {
|
||||
ESP_LOGD(I2S_TAG, "I2S_MODE_TX");
|
||||
i2s_enable_tx_intr(i2s_num);
|
||||
I2S[i2s_num]->out_link.start = 1;
|
||||
I2S[i2s_num]->conf.tx_start = 1;
|
||||
}
|
||||
if (p_i2s_obj[i2s_num]->mode & I2S_MODE_RX) {
|
||||
ESP_LOGD(I2S_TAG, "I2S_MODE_RX");
|
||||
i2s_enable_rx_intr(i2s_num);
|
||||
I2S[i2s_num]->in_link.start = 1;
|
||||
I2S[i2s_num]->conf.rx_start = 1;
|
||||
}
|
||||
esp_intr_enable(p_i2s_obj[i2s_num]->i2s_isr_handle);
|
||||
I2S_EXIT_CRITICAL();
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t i2s_stop(i2s_port_t i2s_num)
|
||||
{
|
||||
I2S_ENTER_CRITICAL();
|
||||
esp_intr_disable(p_i2s_obj[i2s_num]->i2s_isr_handle);
|
||||
if (p_i2s_obj[i2s_num]->mode & I2S_MODE_TX) {
|
||||
I2S[i2s_num]->out_link.stop = 1;
|
||||
I2S[i2s_num]->conf.tx_start = 0;
|
||||
i2s_disable_tx_intr(i2s_num);
|
||||
}
|
||||
if (p_i2s_obj[i2s_num]->mode & I2S_MODE_RX) {
|
||||
I2S[i2s_num]->in_link.stop = 1;
|
||||
I2S[i2s_num]->conf.rx_start = 0;
|
||||
i2s_disable_rx_intr(i2s_num);
|
||||
}
|
||||
I2S_EXIT_CRITICAL();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static esp_err_t configure_dac_pin(void)
|
||||
{
|
||||
SET_PERI_REG_MASK(SENS_SAR_DAC_CTRL1_REG, SENS_DAC_DIG_FORCE_M);
|
||||
SET_PERI_REG_MASK(SENS_SAR_DAC_CTRL1_REG, SENS_DAC_CLK_INV_M);
|
||||
|
||||
SET_PERI_REG_MASK(RTC_IO_PAD_DAC1_REG, RTC_IO_PDAC1_DAC_XPD_FORCE_M);
|
||||
SET_PERI_REG_MASK(RTC_IO_PAD_DAC1_REG, RTC_IO_PDAC1_XPD_DAC_M);
|
||||
|
||||
CLEAR_PERI_REG_MASK(RTC_IO_PAD_DAC1_REG, RTC_IO_PDAC1_RUE_M);
|
||||
CLEAR_PERI_REG_MASK(RTC_IO_PAD_DAC1_REG, RTC_IO_PDAC1_RDE_M);
|
||||
|
||||
SET_PERI_REG_MASK(RTC_IO_PAD_DAC2_REG, RTC_IO_PDAC2_DAC_XPD_FORCE_M);
|
||||
SET_PERI_REG_MASK(RTC_IO_PAD_DAC2_REG, RTC_IO_PDAC2_XPD_DAC_M);
|
||||
|
||||
CLEAR_PERI_REG_MASK(RTC_IO_PAD_DAC2_REG, RTC_IO_PDAC2_RUE_M);
|
||||
CLEAR_PERI_REG_MASK(RTC_IO_PAD_DAC2_REG, RTC_IO_PDAC2_RDE_M);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t i2s_set_pin(i2s_port_t i2s_num, const i2s_pin_config_t *pin)
|
||||
{
|
||||
I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_FAIL);
|
||||
if (pin == NULL) {
|
||||
return configure_dac_pin();
|
||||
}
|
||||
if (pin->bck_io_num != -1 && !GPIO_IS_VALID_GPIO(pin->bck_io_num)) {
|
||||
ESP_LOGE(I2S_TAG, "bck_io_num error");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
if (pin->ws_io_num != -1 && !GPIO_IS_VALID_GPIO(pin->ws_io_num)) {
|
||||
ESP_LOGE(I2S_TAG, "ws_io_num error");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
if (pin->data_out_num != -1 && !GPIO_IS_VALID_GPIO(pin->data_out_num)) {
|
||||
ESP_LOGE(I2S_TAG, "data_out_num error");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
if (pin->data_in_num != -1 && !GPIO_IS_VALID_GPIO(pin->data_in_num)) {
|
||||
ESP_LOGE(I2S_TAG, "data_in_num error");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
int bck_sig = -1, ws_sig = -1, data_out_sig = -1, data_in_sig = -1;
|
||||
//TX & RX
|
||||
if (p_i2s_obj[i2s_num]->mode & I2S_MODE_RX) {
|
||||
bck_sig = I2S0I_BCK_OUT_IDX;
|
||||
ws_sig = I2S0I_WS_OUT_IDX;
|
||||
data_in_sig = I2S0I_DATA_IN15_IDX;
|
||||
if (i2s_num == I2S_NUM_1) {
|
||||
bck_sig = I2S1I_BCK_OUT_IDX;
|
||||
ws_sig = I2S1I_WS_OUT_IDX;
|
||||
data_in_sig = I2S1I_DATA_IN15_IDX;
|
||||
}
|
||||
}
|
||||
if (p_i2s_obj[i2s_num]->mode & I2S_MODE_TX) {
|
||||
bck_sig = I2S0O_BCK_OUT_IDX;
|
||||
ws_sig = I2S0O_WS_OUT_IDX;
|
||||
data_out_sig = I2S0O_DATA_OUT23_IDX;
|
||||
if (i2s_num == I2S_NUM_1) {
|
||||
bck_sig = I2S1O_BCK_OUT_IDX;
|
||||
ws_sig = I2S1O_WS_OUT_IDX;
|
||||
data_out_sig = I2S1O_DATA_OUT23_IDX;
|
||||
}
|
||||
}
|
||||
|
||||
gpio_matrix_out_check(pin->data_out_num, data_out_sig, 0, 0);
|
||||
gpio_matrix_in_check(pin->data_in_num, data_in_sig, 0);
|
||||
if (p_i2s_obj[i2s_num]->mode & I2S_MODE_MASTER) {
|
||||
gpio_matrix_out_check(pin->ws_io_num, ws_sig, 0, 0);
|
||||
gpio_matrix_out_check(pin->bck_io_num, bck_sig, 0, 0);
|
||||
} else if (p_i2s_obj[i2s_num]->mode & I2S_MODE_SLAVE) {
|
||||
gpio_matrix_in_check(pin->ws_io_num, ws_sig, 0);
|
||||
gpio_matrix_in_check(pin->bck_io_num, bck_sig, 0);
|
||||
}
|
||||
ESP_LOGE(I2S_TAG, "data: out %d, in: %d, ws: %d, bck: %d", data_out_sig, data_in_sig, ws_sig, bck_sig);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t i2s_set_sample_rates(i2s_port_t i2s_num, uint32_t rate)
|
||||
{
|
||||
I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_FAIL);
|
||||
I2S_CHECK((p_i2s_obj[i2s_num]->bytes_per_sample > 0), "bits_per_sample not set", ESP_FAIL);
|
||||
return i2s_set_clk(i2s_num, rate, p_i2s_obj[i2s_num]->bytes_per_sample*8, 0);
|
||||
}
|
||||
static esp_err_t i2s_param_config(i2s_port_t i2s_num, const i2s_config_t *i2s_config)
|
||||
{
|
||||
I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_FAIL);
|
||||
I2S_CHECK((i2s_config), "param null", ESP_FAIL);
|
||||
if (i2s_num == I2S_NUM_1) {
|
||||
periph_module_enable(PERIPH_I2S1_MODULE);
|
||||
} else {
|
||||
periph_module_enable(PERIPH_I2S0_MODULE);
|
||||
}
|
||||
// configure I2S data port interface.
|
||||
i2s_reset_fifo(i2s_num);
|
||||
|
||||
//reset i2s
|
||||
I2S[i2s_num]->conf.tx_reset = 1;
|
||||
I2S[i2s_num]->conf.tx_reset = 0;
|
||||
I2S[i2s_num]->conf.rx_reset = 1;
|
||||
I2S[i2s_num]->conf.rx_reset = 0;
|
||||
|
||||
|
||||
//reset dma
|
||||
I2S[i2s_num]->lc_conf.in_rst = 1;
|
||||
I2S[i2s_num]->lc_conf.in_rst = 0;
|
||||
I2S[i2s_num]->lc_conf.out_rst = 1;
|
||||
I2S[i2s_num]->lc_conf.out_rst = 0;
|
||||
|
||||
|
||||
//Enable and configure DMA
|
||||
I2S[i2s_num]->lc_conf.check_owner = 0;
|
||||
I2S[i2s_num]->lc_conf.out_loop_test = 0;
|
||||
I2S[i2s_num]->lc_conf.out_auto_wrback = 0;
|
||||
I2S[i2s_num]->lc_conf.out_data_burst_en = 0;
|
||||
I2S[i2s_num]->lc_conf.outdscr_burst_en = 0;
|
||||
I2S[i2s_num]->lc_conf.out_no_restart_clr = 0;
|
||||
I2S[i2s_num]->lc_conf.indscr_burst_en = 0;
|
||||
I2S[i2s_num]->lc_conf.out_eof_mode = 1;
|
||||
|
||||
|
||||
I2S[i2s_num]->conf2.lcd_en = 0;
|
||||
I2S[i2s_num]->conf2.camera_en = 0;
|
||||
I2S[i2s_num]->pdm_conf.pcm2pdm_conv_en = 0;
|
||||
I2S[i2s_num]->pdm_conf.pdm2pcm_conv_en = 0;
|
||||
|
||||
I2S[i2s_num]->fifo_conf.dscr_en = 0;
|
||||
p_i2s_obj[i2s_num]->channel_num = i2s_config->channel_format < I2S_CHANNEL_FMT_ONLY_RIGHT ? 2 : 1;
|
||||
|
||||
I2S[i2s_num]->conf_chan.tx_chan_mod = i2s_config->channel_format < I2S_CHANNEL_FMT_ONLY_RIGHT ? i2s_config->channel_format : (i2s_config->channel_format >> 1); // 0-two channel;1-right;2-left;3-righ;4-left
|
||||
I2S[i2s_num]->fifo_conf.tx_fifo_mod = i2s_config->channel_format < I2S_CHANNEL_FMT_ONLY_RIGHT ? 0 : 1; // 0-right&left channel;1-one channel
|
||||
I2S[i2s_num]->conf.tx_mono = i2s_config->channel_format < I2S_CHANNEL_FMT_ONLY_RIGHT ? 0 : 1; // 0-right&left channel;1-one channel
|
||||
|
||||
I2S[i2s_num]->conf_chan.rx_chan_mod = i2s_config->channel_format < I2S_CHANNEL_FMT_ONLY_RIGHT ? i2s_config->channel_format : (i2s_config->channel_format >> 1); // 0-two channel;1-right;2-left;3-righ;4-left
|
||||
I2S[i2s_num]->fifo_conf.rx_fifo_mod = i2s_config->channel_format < I2S_CHANNEL_FMT_ONLY_RIGHT ? 0 : 1; // 0-right&left channel;1-one channel
|
||||
I2S[i2s_num]->conf.rx_mono = i2s_config->channel_format < I2S_CHANNEL_FMT_ONLY_RIGHT ? 0 : 1; // 0-right&left channel;1-one channel
|
||||
I2S[i2s_num]->fifo_conf.dscr_en = 1;//connect dma to fifo
|
||||
|
||||
I2S[i2s_num]->conf.tx_start = 0;
|
||||
I2S[i2s_num]->conf.rx_start = 0;
|
||||
|
||||
if (i2s_config->mode & I2S_MODE_TX) {
|
||||
I2S[i2s_num]->conf.tx_msb_right = 0;
|
||||
I2S[i2s_num]->conf.tx_right_first = 0;
|
||||
|
||||
I2S[i2s_num]->conf.tx_slave_mod = 0; // Master
|
||||
I2S[i2s_num]->fifo_conf.tx_fifo_mod_force_en = 1;//?
|
||||
|
||||
if (i2s_config->mode & I2S_MODE_SLAVE) {
|
||||
I2S[i2s_num]->conf.tx_slave_mod = 1;//TX Slave
|
||||
}
|
||||
}
|
||||
|
||||
if (i2s_config->mode & I2S_MODE_RX) {
|
||||
I2S[i2s_num]->conf.rx_msb_right = 0;
|
||||
I2S[i2s_num]->conf.rx_right_first = 0;
|
||||
I2S[i2s_num]->conf.rx_slave_mod = 0; // Master
|
||||
I2S[i2s_num]->fifo_conf.rx_fifo_mod_force_en = 1;//?
|
||||
I2S[i2s_num]->rx_eof_num = (i2s_config->dma_buf_len);
|
||||
if (i2s_config->mode & I2S_MODE_SLAVE) {
|
||||
I2S[i2s_num]->conf.rx_slave_mod = 1;//RX Slave
|
||||
}
|
||||
}
|
||||
|
||||
if (i2s_config->mode & I2S_MODE_DAC_BUILT_IN) {
|
||||
I2S[i2s_num]->conf2.lcd_en = 1;
|
||||
I2S[i2s_num]->conf.tx_right_first = 1;
|
||||
I2S[i2s_num]->fifo_conf.tx_fifo_mod = 3;
|
||||
}
|
||||
|
||||
if (i2s_config->communication_format & I2S_COMM_FORMAT_I2S) {
|
||||
I2S[i2s_num]->conf.tx_short_sync = 0;
|
||||
I2S[i2s_num]->conf.rx_short_sync = 0;
|
||||
I2S[i2s_num]->conf.tx_msb_shift = 1;
|
||||
I2S[i2s_num]->conf.rx_msb_shift = 1;
|
||||
if (i2s_config->communication_format & I2S_COMM_FORMAT_I2S_LSB) {
|
||||
if (i2s_config->mode & I2S_MODE_TX) {
|
||||
I2S[i2s_num]->conf.tx_msb_shift = 0;
|
||||
}
|
||||
if (i2s_config->mode & I2S_MODE_RX) {
|
||||
I2S[i2s_num]->conf.rx_msb_shift = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (i2s_config->communication_format & I2S_COMM_FORMAT_PCM) {
|
||||
I2S[i2s_num]->conf.tx_msb_shift = 0;
|
||||
I2S[i2s_num]->conf.rx_msb_shift = 0;
|
||||
I2S[i2s_num]->conf.tx_short_sync = 0;
|
||||
I2S[i2s_num]->conf.rx_short_sync = 0;
|
||||
if (i2s_config->communication_format & I2S_COMM_FORMAT_PCM_SHORT) {
|
||||
if (i2s_config->mode & I2S_MODE_TX) {
|
||||
I2S[i2s_num]->conf.tx_short_sync = 1;
|
||||
}
|
||||
if (i2s_config->mode & I2S_MODE_RX) {
|
||||
I2S[i2s_num]->conf.rx_short_sync = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((p_i2s_obj[i2s_num]->mode & I2S_MODE_RX) && (p_i2s_obj[i2s_num]->mode & I2S_MODE_TX)) {
|
||||
I2S[i2s_num]->conf.sig_loopback = 1;
|
||||
}
|
||||
i2s_set_clk(i2s_num, i2s_config->sample_rate, p_i2s_obj[i2s_num]->bytes_per_sample*8, 0);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t i2s_zero_dma_buffer(i2s_port_t i2s_num)
|
||||
{
|
||||
int total_buffer_in_bytes = p_i2s_obj[i2s_num]->dma_buf_count * p_i2s_obj[i2s_num]->dma_buf_len * p_i2s_obj[i2s_num]->bytes_per_sample * p_i2s_obj[i2s_num]->channel_num;
|
||||
const uint32_t zero_sample[2] = { 0 };
|
||||
I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_FAIL);
|
||||
while (total_buffer_in_bytes > 0) {
|
||||
i2s_push_sample(i2s_num, (const char*) zero_sample, 10);
|
||||
total_buffer_in_bytes -= p_i2s_obj[i2s_num]->bytes_per_sample * p_i2s_obj[i2s_num]->channel_num;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t i2s_driver_install(i2s_port_t i2s_num, const i2s_config_t *i2s_config, int queue_size, void* i2s_queue)
|
||||
{
|
||||
I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_FAIL);
|
||||
I2S_CHECK((i2s_config != NULL), "I2S configuration must not NULL", ESP_FAIL);
|
||||
I2S_CHECK((i2s_config->dma_buf_count >= 2 && i2s_config->dma_buf_count <= 128), "I2S buffer count less than 128 and more than 2", ESP_FAIL);
|
||||
I2S_CHECK((i2s_config->dma_buf_len >= 8 && i2s_config->dma_buf_len <= 2048), "I2S buffer length at most 2048 and more than 8", ESP_FAIL);
|
||||
if (p_i2s_obj[i2s_num] == NULL) {
|
||||
p_i2s_obj[i2s_num] = (i2s_obj_t*) malloc(sizeof(i2s_obj_t));
|
||||
if (p_i2s_obj[i2s_num] == NULL) {
|
||||
ESP_LOGE(I2S_TAG, "Malloc I2S driver error");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
p_i2s_obj[i2s_num]->i2s_num = i2s_num;
|
||||
p_i2s_obj[i2s_num]->dma_buf_count = i2s_config->dma_buf_count;
|
||||
p_i2s_obj[i2s_num]->dma_buf_len = i2s_config->dma_buf_len;
|
||||
p_i2s_obj[i2s_num]->i2s_queue = i2s_queue;
|
||||
p_i2s_obj[i2s_num]->mode = i2s_config->mode;
|
||||
p_i2s_obj[i2s_num]->bytes_per_sample = i2s_config->bits_per_sample/8;
|
||||
|
||||
//initial dma
|
||||
if (ESP_FAIL == i2s_isr_register(i2s_num, i2s_config->intr_alloc_flags, i2s_intr_handler_default, p_i2s_obj[i2s_num], &p_i2s_obj[i2s_num]->i2s_isr_handle)) {
|
||||
free(p_i2s_obj[i2s_num]);
|
||||
ESP_LOGE(I2S_TAG, "Register I2S Interrupt error");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
i2s_stop(i2s_num);
|
||||
i2s_param_config(i2s_num, i2s_config);
|
||||
|
||||
if (p_i2s_obj[i2s_num]->mode & I2S_MODE_TX) {
|
||||
p_i2s_obj[i2s_num]->tx = i2s_create_dma_queue(i2s_num, i2s_config->dma_buf_count, i2s_config->dma_buf_len);
|
||||
if (p_i2s_obj[i2s_num]->tx == NULL) {
|
||||
ESP_LOGE(I2S_TAG, "Failed to create tx dma buffer");
|
||||
i2s_driver_uninstall(i2s_num);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
I2S[i2s_num]->out_link.addr = (uint32_t) p_i2s_obj[i2s_num]->tx->desc[0];
|
||||
}
|
||||
|
||||
if (p_i2s_obj[i2s_num]->mode & I2S_MODE_RX) {
|
||||
p_i2s_obj[i2s_num]->rx = i2s_create_dma_queue(i2s_num, i2s_config->dma_buf_count, i2s_config->dma_buf_len);
|
||||
if (p_i2s_obj[i2s_num]->rx == NULL){
|
||||
ESP_LOGE(I2S_TAG, "Failed to create rx dma buffer");
|
||||
i2s_driver_uninstall(i2s_num);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
I2S[i2s_num]->in_link.addr = (uint32_t) p_i2s_obj[i2s_num]->rx->desc[0];
|
||||
}
|
||||
|
||||
|
||||
if (i2s_queue) {
|
||||
p_i2s_obj[i2s_num]->i2s_queue = xQueueCreate(queue_size, sizeof(i2s_event_t));
|
||||
*((QueueHandle_t*) i2s_queue) = p_i2s_obj[i2s_num]->i2s_queue;
|
||||
ESP_LOGI(I2S_TAG, "queue free spaces: %d", uxQueueSpacesAvailable(p_i2s_obj[i2s_num]->i2s_queue));
|
||||
} else {
|
||||
p_i2s_obj[i2s_num]->i2s_queue = NULL;
|
||||
}
|
||||
|
||||
i2s_start(i2s_num);
|
||||
} else {
|
||||
ESP_LOGE(I2S_TAG, "I2S driver already installed");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t i2s_driver_uninstall(i2s_port_t i2s_num)
|
||||
{
|
||||
I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_FAIL);
|
||||
if (p_i2s_obj[i2s_num] == NULL) {
|
||||
ESP_LOGI(I2S_TAG, "ALREADY NULL");
|
||||
return ESP_OK;
|
||||
}
|
||||
i2s_stop(i2s_num);
|
||||
esp_intr_free(p_i2s_obj[i2s_num]->i2s_isr_handle);
|
||||
|
||||
if (p_i2s_obj[i2s_num]->tx != NULL && p_i2s_obj[i2s_num]->mode & I2S_MODE_TX) {
|
||||
i2s_destroy_dma_queue(i2s_num, p_i2s_obj[i2s_num]->tx);
|
||||
p_i2s_obj[i2s_num]->tx = NULL;
|
||||
}
|
||||
if (p_i2s_obj[i2s_num]->rx != NULL && p_i2s_obj[i2s_num]->mode & I2S_MODE_RX) {
|
||||
i2s_destroy_dma_queue(i2s_num, p_i2s_obj[i2s_num]->rx);
|
||||
p_i2s_obj[i2s_num]->rx = NULL;
|
||||
}
|
||||
|
||||
if (p_i2s_obj[i2s_num]->i2s_queue) {
|
||||
vQueueDelete(p_i2s_obj[i2s_num]->i2s_queue);
|
||||
p_i2s_obj[i2s_num]->i2s_queue = NULL;
|
||||
}
|
||||
|
||||
free(p_i2s_obj[i2s_num]);
|
||||
p_i2s_obj[i2s_num] = NULL;
|
||||
|
||||
if (i2s_num == I2S_NUM_0) {
|
||||
periph_module_disable(PERIPH_I2S0_MODULE);
|
||||
} else if (i2s_num == I2S_NUM_1) {
|
||||
periph_module_disable(PERIPH_I2S1_MODULE);
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
int i2s_write_bytes(i2s_port_t i2s_num, const char *src, size_t size, TickType_t ticks_to_wait)
|
||||
{
|
||||
char *data_ptr;
|
||||
int bytes_can_write, bytes_writen = 0;
|
||||
I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_FAIL);
|
||||
if (p_i2s_obj[i2s_num]->tx == NULL) {
|
||||
return 0;
|
||||
}
|
||||
xSemaphoreTake(p_i2s_obj[i2s_num]->tx->mux, (portTickType)portMAX_DELAY);
|
||||
while (size > 0) {
|
||||
if (p_i2s_obj[i2s_num]->tx->rw_pos == p_i2s_obj[i2s_num]->tx->buf_size || p_i2s_obj[i2s_num]->tx->curr_ptr == NULL) {
|
||||
if (xQueueReceive(p_i2s_obj[i2s_num]->tx->queue, &p_i2s_obj[i2s_num]->tx->curr_ptr, ticks_to_wait) == pdFALSE) {
|
||||
break;
|
||||
}
|
||||
p_i2s_obj[i2s_num]->tx->rw_pos = 0;
|
||||
}
|
||||
ESP_LOGD(I2S_TAG, "size: %d, rw_pos: %d, buf_size: %d, curr_ptr: %d", size, p_i2s_obj[i2s_num]->tx->rw_pos, p_i2s_obj[i2s_num]->tx->buf_size, (int)p_i2s_obj[i2s_num]->tx->curr_ptr);
|
||||
data_ptr = (char*)p_i2s_obj[i2s_num]->tx->curr_ptr;
|
||||
data_ptr += p_i2s_obj[i2s_num]->tx->rw_pos;
|
||||
bytes_can_write = p_i2s_obj[i2s_num]->tx->buf_size - p_i2s_obj[i2s_num]->tx->rw_pos;
|
||||
if (bytes_can_write > size) {
|
||||
bytes_can_write = size;
|
||||
}
|
||||
memcpy(data_ptr, src, bytes_can_write);
|
||||
size -= bytes_can_write;
|
||||
src += bytes_can_write;
|
||||
p_i2s_obj[i2s_num]->tx->rw_pos += bytes_can_write;
|
||||
bytes_writen += bytes_can_write;
|
||||
}
|
||||
xSemaphoreGive(p_i2s_obj[i2s_num]->tx->mux);
|
||||
return bytes_writen;
|
||||
}
|
||||
|
||||
int i2s_read_bytes(i2s_port_t i2s_num, char* dest, size_t size, TickType_t ticks_to_wait)
|
||||
{
|
||||
char *data_ptr;
|
||||
int bytes_can_read, byte_read = 0;
|
||||
I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_FAIL);
|
||||
if (p_i2s_obj[i2s_num]->rx == NULL) {
|
||||
return 0;
|
||||
}
|
||||
xSemaphoreTake(p_i2s_obj[i2s_num]->rx->mux, (portTickType)portMAX_DELAY);
|
||||
while (size > 0) {
|
||||
if (p_i2s_obj[i2s_num]->rx->rw_pos == p_i2s_obj[i2s_num]->rx->buf_size || p_i2s_obj[i2s_num]->rx->curr_ptr == NULL) {
|
||||
if (xQueueReceive(p_i2s_obj[i2s_num]->rx->queue, &p_i2s_obj[i2s_num]->rx->curr_ptr, ticks_to_wait) == pdFALSE) {
|
||||
break;
|
||||
}
|
||||
p_i2s_obj[i2s_num]->rx->rw_pos = 0;
|
||||
}
|
||||
data_ptr = (char*)p_i2s_obj[i2s_num]->rx->curr_ptr;
|
||||
data_ptr += p_i2s_obj[i2s_num]->rx->rw_pos;
|
||||
bytes_can_read = p_i2s_obj[i2s_num]->rx->buf_size - p_i2s_obj[i2s_num]->rx->rw_pos;
|
||||
if (bytes_can_read > size) {
|
||||
bytes_can_read = size;
|
||||
}
|
||||
memcpy(dest, data_ptr, bytes_can_read);
|
||||
size -= bytes_can_read;
|
||||
dest += bytes_can_read;
|
||||
p_i2s_obj[i2s_num]->rx->rw_pos += bytes_can_read;
|
||||
byte_read += bytes_can_read;
|
||||
}
|
||||
xSemaphoreGive(p_i2s_obj[i2s_num]->rx->mux);
|
||||
return byte_read;
|
||||
}
|
||||
int i2s_push_sample(i2s_port_t i2s_num, const char *sample, TickType_t ticks_to_wait)
|
||||
{
|
||||
int i, bytes_to_push = 0;
|
||||
char *data_ptr;
|
||||
I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_FAIL);
|
||||
if (p_i2s_obj[i2s_num]->tx->rw_pos == p_i2s_obj[i2s_num]->tx->buf_size || p_i2s_obj[i2s_num]->tx->curr_ptr == NULL) {
|
||||
if (xQueueReceive(p_i2s_obj[i2s_num]->tx->queue, &p_i2s_obj[i2s_num]->tx->curr_ptr, ticks_to_wait) == pdFALSE) {
|
||||
return 0;
|
||||
}
|
||||
ESP_LOGD(I2S_TAG, "rw_pos: %d, buf_size: %d, curr_ptr: %d", p_i2s_obj[i2s_num]->tx->rw_pos, p_i2s_obj[i2s_num]->tx->buf_size, (int)p_i2s_obj[i2s_num]->tx->curr_ptr);
|
||||
p_i2s_obj[i2s_num]->tx->rw_pos = 0;
|
||||
}
|
||||
data_ptr = (char*)p_i2s_obj[i2s_num]->tx->curr_ptr;
|
||||
data_ptr += p_i2s_obj[i2s_num]->tx->rw_pos;
|
||||
for (i = 0; i < p_i2s_obj[i2s_num]->bytes_per_sample; i++) {
|
||||
*data_ptr++ = *sample++;
|
||||
bytes_to_push ++;
|
||||
}
|
||||
if (p_i2s_obj[i2s_num]->channel_num == 2) {
|
||||
for (i = 0; i < p_i2s_obj[i2s_num]->bytes_per_sample; i++) {
|
||||
*data_ptr++ = *sample++;
|
||||
bytes_to_push ++;
|
||||
}
|
||||
}
|
||||
|
||||
p_i2s_obj[i2s_num]->tx->rw_pos += p_i2s_obj[i2s_num]->bytes_per_sample * p_i2s_obj[i2s_num]->channel_num;
|
||||
return bytes_to_push;
|
||||
}
|
||||
|
||||
int i2s_pop_sample(i2s_port_t i2s_num, char *sample, TickType_t ticks_to_wait)
|
||||
{
|
||||
int i, bytes_to_pop = 0;
|
||||
char *data_ptr;
|
||||
I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_FAIL);
|
||||
if (p_i2s_obj[i2s_num]->rx->rw_pos == p_i2s_obj[i2s_num]->rx->buf_size || p_i2s_obj[i2s_num]->rx->curr_ptr == NULL) {
|
||||
if (xQueueReceive(p_i2s_obj[i2s_num]->rx->queue, &p_i2s_obj[i2s_num]->rx->curr_ptr, ticks_to_wait) == pdFALSE) {
|
||||
return 0;
|
||||
}
|
||||
p_i2s_obj[i2s_num]->rx->rw_pos = 0;
|
||||
}
|
||||
data_ptr = (char*)p_i2s_obj[i2s_num]->rx->curr_ptr;
|
||||
data_ptr += p_i2s_obj[i2s_num]->rx->rw_pos;
|
||||
for (i = 0; i < p_i2s_obj[i2s_num]->bytes_per_sample; i++) {
|
||||
*sample++ = *data_ptr++;
|
||||
bytes_to_pop++;
|
||||
}
|
||||
if (p_i2s_obj[i2s_num]->channel_num == 2) {
|
||||
for (i = 0; i < p_i2s_obj[i2s_num]->bytes_per_sample; i++) {
|
||||
*sample++ = *data_ptr++;
|
||||
bytes_to_pop++;
|
||||
}
|
||||
}
|
||||
|
||||
p_i2s_obj[i2s_num]->rx->rw_pos += p_i2s_obj[i2s_num]->bytes_per_sample * p_i2s_obj[i2s_num]->channel_num;
|
||||
return bytes_to_pop;
|
||||
}
|
@ -156,6 +156,7 @@ typedef enum {
|
||||
GPIO_NUM_37 = 37, /*!< GPIO37, input mode only */
|
||||
GPIO_NUM_38 = 38, /*!< GPIO38, input mode only */
|
||||
GPIO_NUM_39 = 39, /*!< GPIO39, input mode only */
|
||||
GPIO_NUM_MAX = 40,
|
||||
} gpio_num_t;
|
||||
|
||||
typedef enum {
|
||||
@ -205,9 +206,8 @@ typedef enum {
|
||||
} gpio_pull_mode_t;
|
||||
|
||||
|
||||
|
||||
typedef void (*gpio_isr_t)(void*);
|
||||
typedef intr_handle_t gpio_isr_handle_t;
|
||||
typedef void (*gpio_event_callback)(gpio_num_t gpio_intr_num);
|
||||
|
||||
/**
|
||||
* @brief GPIO common configuration
|
||||
@ -269,7 +269,7 @@ esp_err_t gpio_intr_disable(gpio_num_t gpio_num);
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - GPIO_IS_VALID_GPIO GPIO number error
|
||||
* - ESP_ERR_INVALID_ARG GPIO number error
|
||||
*
|
||||
*/
|
||||
esp_err_t gpio_set_level(gpio_num_t gpio_num, uint32_t level);
|
||||
@ -357,8 +357,6 @@ esp_err_t gpio_wakeup_disable(gpio_num_t gpio_num);
|
||||
*/
|
||||
esp_err_t gpio_isr_register(void (*fn)(void*), void * arg, int intr_alloc_flags, gpio_isr_handle_t *handle);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief Enable pull-up on GPIO.
|
||||
*
|
||||
@ -403,93 +401,55 @@ esp_err_t gpio_pulldown_en(gpio_num_t gpio_num);
|
||||
*/
|
||||
esp_err_t gpio_pulldown_dis(gpio_num_t gpio_num);
|
||||
|
||||
|
||||
/**
|
||||
* *************** ATTENTION ********************/
|
||||
/**
|
||||
*@attention
|
||||
* Each GPIO has its own separate configuration register, so we do not use
|
||||
* a lock to serialize access to them. This works under the assumption that
|
||||
* no situation will occur where two tasks try to configure the same GPIO
|
||||
* pin simultaneously. It is up to the application developer to guarantee this.
|
||||
*/
|
||||
|
||||
/**
|
||||
*----------EXAMPLE TO CONFIGURE GPIO AS OUTPUT ------------ *
|
||||
* @code{c}
|
||||
* gpio_config_t io_conf;
|
||||
* io_conf.intr_type = GPIO_INTR_DISABLE; //disable interrupt
|
||||
* io_conf.mode = GPIO_MODE_OUTPUT; //set as output mode
|
||||
* io_conf.pin_bit_mask = GPIO_SEL_18 | GPIO_SEL_19; //bit mask of the pins that you want to set,e.g.GPIO18/19
|
||||
* io_conf.pull_down_en = 0; //disable pull-down mode
|
||||
* io_conf.pull_up_en = 0; //disable pull-up mode
|
||||
* gpio_config(&io_conf); //configure GPIO with the given settings
|
||||
* @endcode
|
||||
**/
|
||||
|
||||
/**
|
||||
*----------EXAMPLE TO CONFIGURE GPIO AS OUTPUT ------------ *
|
||||
* @code{c}
|
||||
* io_conf.intr_type = GPIO_INTR_POSEDGE; //set posedge interrupt
|
||||
* io_conf.mode = GPIO_MODE_INPUT; //set as input
|
||||
* io_conf.pin_bit_mask = GPIO_SEL_4 | GPIO_SEL_5; //bit mask of the pins that you want to set, e.g.,GPIO4/5
|
||||
* io_conf.pull_down_en = 0; //disable pull-down mode
|
||||
* io_conf.pull_up_en = 1; //enable pull-up mode
|
||||
* gpio_config(&io_conf); //configure GPIO with the given settings
|
||||
* @endcode
|
||||
*/
|
||||
/**
|
||||
*----------EXAMPLE TO SET ISR HANDLER ----------------------
|
||||
* @code{c}
|
||||
* gpio_isr_register(gpio_intr_test, 0, NULL); //hook the isr handler for GPIO interrupt
|
||||
* @endcode
|
||||
*/
|
||||
/**
|
||||
*-------------EXAMPLE OF HANDLER FUNCTION-------------------*
|
||||
* @code{c}
|
||||
* #include "esp_attr.h"
|
||||
* void IRAM_ATTR gpio_intr_test(void* arg)
|
||||
* {
|
||||
* //GPIO intr process
|
||||
* ets_printf("in gpio_intr\n");
|
||||
* uint32_t gpio_num = 0;
|
||||
* uint32_t gpio_intr_status = READ_PERI_REG(GPIO_STATUS_REG); //read status to get interrupt status for GPIO0-31
|
||||
* uint32_t gpio_intr_status_h = READ_PERI_REG(GPIO_STATUS1_REG);//read status1 to get interrupt status for GPIO32-39
|
||||
* SET_PERI_REG_MASK(GPIO_STATUS_W1TC_REG, gpio_intr_status); //Clear intr for gpio0-gpio31
|
||||
* SET_PERI_REG_MASK(GPIO_STATUS1_W1TC_REG, gpio_intr_status_h); //Clear intr for gpio32-39
|
||||
* do {
|
||||
* if(gpio_num < 32) {
|
||||
* if(gpio_intr_status & BIT(gpio_num)) { //gpio0-gpio31
|
||||
* ets_printf("Intr GPIO%d ,val: %d\n",gpio_num,gpio_get_level(gpio_num));
|
||||
* //This is an isr handler, you should post an event to process it in RTOS queue.
|
||||
* }
|
||||
* } else {
|
||||
* if(gpio_intr_status_h & BIT(gpio_num - 32)) {
|
||||
* ets_printf("Intr GPIO%d, val : %d\n",gpio_num,gpio_get_level(gpio_num));
|
||||
* //This is an isr handler, you should post an event to process it in RTOS queue.
|
||||
* }
|
||||
* }
|
||||
* } while(++gpio_num < GPIO_PIN_COUNT);
|
||||
* }
|
||||
* @endcode
|
||||
*/
|
||||
|
||||
/**
|
||||
*----EXAMPLE OF I2C CONFIG AND PICK SIGNAL FOR IO MATRIX---*
|
||||
* @code{c}
|
||||
* gpio_config_t io_conf;
|
||||
* io_conf.intr_type = GPIO_INTR_DISABLE; //disable interrupt
|
||||
* io_conf.mode = GPIO_MODE_INPUT_OUTPUT_OD; //set as output mode
|
||||
* io_conf.pin_bit_mask = GPIO_SEL_21 | GPIO_SEL_22; //bit mask of the pins that you want to set,e.g.GPIO21/22
|
||||
* io_conf.pull_down_en = 0; //disable pull-down mode
|
||||
* io_conf.pull_up_en = 1; //enable pull-up mode
|
||||
* gpio_config(&io_conf); //configure GPIO with the given settings
|
||||
* gpio_matrix_out(21, EXT_I2C_SCL_O_IDX, 0, 0); //set output signal for io_matrix
|
||||
* gpio_matrix_out(22, EXT_I2C_SDA_O_IDX, 0, 0); //set output signal for io_matrix
|
||||
* gpio_matrix_in( 22, EXT_I2C_SDA_I_IDX, 0); //set input signal for io_matrix
|
||||
* @endcode
|
||||
* @brief Install a GPIO ISR service, so we can assign different ISR handler for different pins
|
||||
*
|
||||
* @param intr_alloc_flags Flags used to allocate the interrupt. One or multiple (ORred)
|
||||
* ESP_INTR_FLAG_* values. See esp_intr_alloc.h for more info.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_FAIL Operation fail
|
||||
* - ESP_ERR_NO_MEM No memory to install this service
|
||||
*/
|
||||
esp_err_t gpio_install_isr_service(int intr_alloc_flags);
|
||||
|
||||
/**
|
||||
* @brief Un-install GPIO ISR service, free the resources.
|
||||
*/
|
||||
void gpio_uninstall_isr_service();
|
||||
|
||||
/**
|
||||
* @brief Add ISR handler for the corresponding GPIO.
|
||||
*
|
||||
* Interrupt handlers no longer need to be declared with IRAM_ATTR, unless you pass the ESP_INTR_FLAG_IRAM flag
|
||||
* when allocating the ISR in gpio_install_isr_service().
|
||||
* This ISR handler will be called from an ISR. So there probably is some stack size limit, and this limit
|
||||
* is smaller compared to a "raw" interrupt handler due to another level of indirection.
|
||||
*
|
||||
* @param gpio_num GPIO number
|
||||
* @param isr_handler ISR handler function for the corresponding GPIO number.
|
||||
* @param args parameter for ISR handler.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_STATE Wrong state, the ISR service has not been initialized.
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
*/
|
||||
esp_err_t gpio_isr_handler_add(gpio_num_t gpio_num, gpio_isr_t isr_handler, void* args);
|
||||
|
||||
/**
|
||||
* @brief Remove ISR handler for the corresponding GPIO.
|
||||
*
|
||||
* @param gpio_num GPIO number
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_STATE Wrong state, the ISR service has not been initialized.
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
*/
|
||||
esp_err_t gpio_isr_handler_remove(gpio_num_t gpio_num);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
514
components/driver/include/driver/i2c.h
Normal file
514
components/driver/include/driver/i2c.h
Normal file
@ -0,0 +1,514 @@
|
||||
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// 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 _DRIVER_I2C_H_
|
||||
#define _DRIVER_I2C_H_
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#include <esp_types.h>
|
||||
#include "esp_err.h"
|
||||
#include "esp_intr_alloc.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include "freertos/xtensa_api.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/queue.h"
|
||||
#include "freertos/ringbuf.h"
|
||||
#include "driver/gpio.h"
|
||||
|
||||
#define I2C_APB_CLK_FREQ APB_CLK_FREQ /*!< I2C source clock is APB clock, 80MHz */
|
||||
#define I2C_FIFO_LEN (32) /*!< I2C hardware fifo length */
|
||||
typedef enum{
|
||||
I2C_MODE_SLAVE = 0, /*!< I2C slave mode */
|
||||
I2C_MODE_MASTER, /*!< I2C master mode */
|
||||
I2C_MODE_MAX,
|
||||
}i2c_mode_t;
|
||||
|
||||
typedef enum {
|
||||
I2C_MASTER_WRITE = 0, /*!< I2C write data */
|
||||
I2C_MASTER_READ, /*!< I2C read data */
|
||||
} i2c_rw_t;
|
||||
|
||||
typedef enum {
|
||||
I2C_DATA_MODE_MSB_FIRST = 0, /*!< I2C data msb first */
|
||||
I2C_DATA_MODE_LSB_FIRST = 1, /*!< I2C data lsb first */
|
||||
I2C_DATA_MODE_MAX
|
||||
} i2c_trans_mode_t;
|
||||
|
||||
typedef enum{
|
||||
I2C_CMD_RESTART = 0, /*!<I2C restart command */
|
||||
I2C_CMD_WRITE, /*!<I2C write command */
|
||||
I2C_CMD_READ, /*!<I2C read command */
|
||||
I2C_CMD_STOP, /*!<I2C stop command */
|
||||
I2C_CMD_END /*!<I2C end command */
|
||||
}i2c_opmode_t;
|
||||
|
||||
typedef enum{
|
||||
I2C_NUM_0 = 0, /*!< I2C port 0 */
|
||||
I2C_NUM_1 , /*!< I2C port 1 */
|
||||
I2C_NUM_MAX
|
||||
} i2c_port_t;
|
||||
|
||||
typedef enum {
|
||||
I2C_ADDR_BIT_7 = 0, /*!< I2C 7bit address for slave mode */
|
||||
I2C_ADDR_BIT_10, /*!< I2C 10bit address for slave mode */
|
||||
I2C_ADDR_BIT_MAX,
|
||||
} i2c_addr_mode_t;
|
||||
|
||||
/**
|
||||
* @brief I2C initialization parameters
|
||||
*/
|
||||
typedef struct{
|
||||
i2c_mode_t mode; /*!< I2C mode */
|
||||
gpio_num_t sda_io_num; /*!< GPIO number for I2C sda signal */
|
||||
gpio_pullup_t sda_pullup_en; /*!< Internal GPIO pull mode for I2C sda signal*/
|
||||
gpio_num_t scl_io_num; /*!< GPIO number for I2C scl signal */
|
||||
gpio_pullup_t scl_pullup_en; /*!< Internal GPIO pull mode for I2C scl signal*/
|
||||
|
||||
union {
|
||||
struct {
|
||||
uint32_t clk_speed; /*!< I2C clock frequency for master mode, (no higher than 1MHz for now) */
|
||||
} master;
|
||||
struct {
|
||||
uint8_t addr_10bit_en; /*!< I2C 10bit address mode enable for slave mode */
|
||||
uint16_t slave_addr; /*!< I2C address for slave mode */
|
||||
} slave;
|
||||
|
||||
};
|
||||
}i2c_config_t;
|
||||
|
||||
typedef void* i2c_cmd_handle_t; /*!< I2C command handle */
|
||||
|
||||
/**
|
||||
* @brief I2C driver install
|
||||
*
|
||||
* @param i2c_num I2C port number
|
||||
* @param mode I2C mode( master or slave )
|
||||
* @param slv_rx_buf_len receiving buffer size for slave mode
|
||||
* @note
|
||||
* Only slave mode will use this value, driver will ignore this value in master mode.
|
||||
* @param slv_tx_buf_len sending buffer size for slave mode
|
||||
* @note
|
||||
* Only slave mode will use this value, driver will ignore this value in master mode.
|
||||
* @param intr_alloc_flags Flags used to allocate the interrupt. One or multiple (ORred)
|
||||
* ESP_INTR_FLAG_* values. See esp_intr_alloc.h for more info.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
* - ESP_FAIL Driver install error
|
||||
*/
|
||||
esp_err_t i2c_driver_install(i2c_port_t i2c_num, i2c_mode_t mode, size_t slv_rx_buf_len, size_t slv_tx_buf_len, int intr_alloc_flags);
|
||||
|
||||
/**
|
||||
* @brief I2C driver delete
|
||||
*
|
||||
* @param i2c_num I2C port number
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
*/
|
||||
esp_err_t i2c_driver_delete(i2c_port_t i2c_num);
|
||||
|
||||
/**
|
||||
* @brief I2C parameter initialization
|
||||
*
|
||||
* @param i2c_num I2C port number
|
||||
* @param i2c_conf pointer to I2C parameter settings
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
*/
|
||||
esp_err_t i2c_param_config(i2c_port_t i2c_num, i2c_config_t* i2c_conf);
|
||||
|
||||
/**
|
||||
* @brief reset I2C tx hardware fifo
|
||||
*
|
||||
* @param i2c_num I2C port number
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
*/
|
||||
esp_err_t i2c_reset_tx_fifo(i2c_port_t i2c_num);
|
||||
|
||||
/**
|
||||
* @brief reset I2C rx fifo
|
||||
*
|
||||
* @param i2c_num I2C port number
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
*/
|
||||
esp_err_t i2c_reset_rx_fifo(i2c_port_t i2c_num);
|
||||
|
||||
/**
|
||||
* @brief I2C isr handler register
|
||||
*
|
||||
* @param i2c_num I2C port number
|
||||
* @param fn isr handler function
|
||||
* @param arg parameter for isr handler function
|
||||
* @param intr_alloc_flags Flags used to allocate the interrupt. One or multiple (ORred)
|
||||
* ESP_INTR_FLAG_* values. See esp_intr_alloc.h for more info.
|
||||
* @param handle handle return from esp_intr_alloc.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
*/
|
||||
esp_err_t i2c_isr_register(i2c_port_t i2c_num, void (*fn)(void*), void * arg, int intr_alloc_flags, intr_handle_t *handle);
|
||||
|
||||
/**
|
||||
* @brief to delete and free I2C isr.
|
||||
*
|
||||
* @param handle handle of isr.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
*/
|
||||
esp_err_t i2c_isr_free(intr_handle_t handle);
|
||||
|
||||
/**
|
||||
* @brief Configure GPIO signal for I2C sck and sda
|
||||
*
|
||||
* @param i2c_num I2C port number
|
||||
* @param sda_io_num GPIO number for I2C sda signal
|
||||
* @param scl_io_num GPIO number for I2C scl signal
|
||||
* @param sda_pullup_en Whether to enable the internal pullup for sda pin
|
||||
* @param scl_pullup_en Whether to enable the internal pullup for scl pin
|
||||
* @param mode I2C mode
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
*/
|
||||
esp_err_t i2c_set_pin(i2c_port_t i2c_num, gpio_num_t sda_io_num, gpio_num_t scl_io_num,
|
||||
gpio_pullup_t sda_pullup_en, gpio_pullup_t scl_pullup_en, i2c_mode_t mode);
|
||||
|
||||
/**
|
||||
* @brief Create and init I2C command link
|
||||
* @note
|
||||
* Before we build I2C command link, we need to call i2c_cmd_link_create() to create
|
||||
* a command link.
|
||||
* After we finish sending the commands, we need to call i2c_cmd_link_delete() to
|
||||
* release and return the resources.
|
||||
*
|
||||
* @return i2c command link handler
|
||||
*/
|
||||
i2c_cmd_handle_t i2c_cmd_link_create();
|
||||
|
||||
/**
|
||||
* @brief Free I2C command link
|
||||
* @note
|
||||
* Before we build I2C command link, we need to call i2c_cmd_link_create() to create
|
||||
* a command link.
|
||||
* After we finish sending the commands, we need to call i2c_cmd_link_delete() to
|
||||
* release and return the resources.
|
||||
*
|
||||
* @param cmd_handle I2C command handle
|
||||
*/
|
||||
void i2c_cmd_link_delete(i2c_cmd_handle_t cmd_handle);
|
||||
|
||||
/**
|
||||
* @brief Queue command for I2C master to generate a start signal
|
||||
* @note
|
||||
* Only call this function in I2C master mode
|
||||
* Call i2c_master_cmd_begin() to send all queued commands
|
||||
*
|
||||
* @param cmd_handle I2C cmd link
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
*/
|
||||
esp_err_t i2c_master_start(i2c_cmd_handle_t cmd_handle);
|
||||
|
||||
/**
|
||||
* @brief Queue command for I2C master to write one byte to I2C bus
|
||||
* @note
|
||||
* Only call this function in I2C master mode
|
||||
* Call i2c_master_cmd_begin() to send all queued commands
|
||||
*
|
||||
* @param cmd_handle I2C cmd link
|
||||
* @param data I2C one byte command to write to bus
|
||||
* @param ack_en enable ack check for master
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
*/
|
||||
esp_err_t i2c_master_write_byte(i2c_cmd_handle_t cmd_handle, uint8_t data, bool ack_en);
|
||||
|
||||
/**
|
||||
* @brief Queue command for I2C master to write buffer to I2C bus
|
||||
* @note
|
||||
* Only call this function in I2C master mode
|
||||
* Call i2c_master_cmd_begin() to send all queued commands
|
||||
*
|
||||
* @param cmd_handle I2C cmd link
|
||||
* @param data data to send
|
||||
* @param data_len data length
|
||||
* @param ack_en enable ack check for master
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
*/
|
||||
esp_err_t i2c_master_write(i2c_cmd_handle_t cmd_handle, uint8_t* data, size_t data_len, bool ack_en);
|
||||
|
||||
/**
|
||||
* @brief Queue command for I2C master to read one byte from I2C bus
|
||||
* @note
|
||||
* Only call this function in I2C master mode
|
||||
* Call i2c_master_cmd_begin() to send all queued commands
|
||||
*
|
||||
* @param cmd_handle I2C cmd link
|
||||
* @param data pointer accept the data byte
|
||||
* @param ack ack value for read command
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
*/
|
||||
esp_err_t i2c_master_read_byte(i2c_cmd_handle_t cmd_handle, uint8_t* data, int ack);
|
||||
|
||||
/**
|
||||
* @brief Queue command for I2C master to read data from I2C bus
|
||||
* @note
|
||||
* Only call this function in I2C master mode
|
||||
* Call i2c_master_cmd_begin() to send all queued commands
|
||||
*
|
||||
* @param cmd_handle I2C cmd link
|
||||
* @param data data buffer to accept the data from bus
|
||||
* @param data_len read data length
|
||||
* @param ack ack value for read command
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
*/
|
||||
esp_err_t i2c_master_read(i2c_cmd_handle_t cmd_handle, uint8_t* data, size_t data_len, int ack);
|
||||
|
||||
/**
|
||||
* @brief Queue command for I2C master to generate a stop signal
|
||||
* @note
|
||||
* Only call this function in I2C master mode
|
||||
* Call i2c_master_cmd_begin() to send all queued commands
|
||||
*
|
||||
* @param cmd_handle I2C cmd link
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
*/
|
||||
esp_err_t i2c_master_stop(i2c_cmd_handle_t cmd_handle);
|
||||
|
||||
/**
|
||||
* @brief I2C master send queued commands.
|
||||
* This function will trigger sending all queued commands.
|
||||
* The task will be blocked until all the commands have been sent out.
|
||||
* The I2C APIs are not thread-safe, if you want to use one I2C port in different tasks,
|
||||
* you need to take care of the multi-thread issue.
|
||||
* @note
|
||||
* Only call this function in I2C master mode
|
||||
*
|
||||
* @param i2c_num I2C port number
|
||||
* @param cmd_handle I2C command handler
|
||||
* @param ticks_to_wait maximum wait ticks.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
* - ESP_FAIL Sending command error, slave doesn't ACK the transfer.
|
||||
* - ESP_ERR_INVALID_STATE I2C driver not installed or not in master mode.
|
||||
* - ESP_ERR_TIMEOUT Operation timeout because the bus is busy.
|
||||
*/
|
||||
esp_err_t i2c_master_cmd_begin(i2c_port_t i2c_num, i2c_cmd_handle_t cmd_handle, portBASE_TYPE ticks_to_wait);
|
||||
|
||||
/**
|
||||
* @brief I2C slave write data to internal ringbuffer, when tx fifo empty, isr will fill the hardware
|
||||
* fifo from the internal ringbuffer
|
||||
* @note
|
||||
* Only call this function in I2C slave mode
|
||||
*
|
||||
* @param i2c_num I2C port number
|
||||
* @param data data pointer to write into internal buffer
|
||||
* @param size data size
|
||||
* @param ticks_to_wait Maximum waiting ticks
|
||||
*
|
||||
* @return
|
||||
* - ESP_FAIL(-1) Parameter error
|
||||
* - Others(>=0) The number of data bytes that pushed to the I2C slave buffer.
|
||||
*/
|
||||
int i2c_slave_write_buffer(i2c_port_t i2c_num, uint8_t* data, int size, portBASE_TYPE ticks_to_wait);
|
||||
|
||||
/**
|
||||
* @brief I2C slave read data from internal buffer. When I2C slave receive data, isr will copy received data
|
||||
* from hardware rx fifo to internal ringbuffer. Then users can read from internal ringbuffer.
|
||||
* @note
|
||||
* Only call this function in I2C slave mode
|
||||
*
|
||||
* @param i2c_num I2C port number
|
||||
* @param data data pointer to write into internal buffer
|
||||
* @param max_size Maximum data size to read
|
||||
* @param ticks_to_wait Maximum waiting ticks
|
||||
*
|
||||
* @return
|
||||
* - ESP_FAIL(-1) Parameter error
|
||||
* - Others(>=0) The number of data bytes that read from I2C slave buffer.
|
||||
*/
|
||||
int i2c_slave_read_buffer(i2c_port_t i2c_num, uint8_t* data, size_t max_size, portBASE_TYPE ticks_to_wait);
|
||||
|
||||
/**
|
||||
* @brief set I2C master clock period
|
||||
*
|
||||
* @param i2c_num I2C port number
|
||||
* @param high_period clock cycle number during SCL is high level, high_period is a 14 bit value
|
||||
* @param low_period clock cycle number during SCL is low level, low_period is a 14 bit value
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
*/
|
||||
esp_err_t i2c_set_period(i2c_port_t i2c_num, int high_period, int low_period);
|
||||
|
||||
/**
|
||||
* @brief get I2C master clock period
|
||||
*
|
||||
* @param i2c_num I2C port number
|
||||
* @param high_period pointer to get clock cycle number during SCL is high level, will get a 14 bit value
|
||||
* @param low_period pointer to get clock cycle number during SCL is low level, will get a 14 bit value
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
*/
|
||||
esp_err_t i2c_get_period(i2c_port_t i2c_num, int* high_period, int* low_period);
|
||||
|
||||
/**
|
||||
* @brief set I2C master start signal timing
|
||||
*
|
||||
* @param i2c_num I2C port number
|
||||
* @param setup_time clock number between the falling-edge of SDA and rising-edge of SCL for start mark, it's a 10-bit value.
|
||||
* @param hold_time clock num between the falling-edge of SDA and falling-edge of SCL for start mark, it's a 10-bit value.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
*/
|
||||
esp_err_t i2c_set_start_timing(i2c_port_t i2c_num, int setup_time, int hold_time);
|
||||
|
||||
/**
|
||||
* @brief get I2C master start signal timing
|
||||
*
|
||||
* @param i2c_num I2C port number
|
||||
* @param setup_time pointer to get setup time
|
||||
* @param hold_time pointer to get hold time
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
*/
|
||||
esp_err_t i2c_get_start_timing(i2c_port_t i2c_num, int* setup_time, int* hold_time);
|
||||
|
||||
/**
|
||||
* @brief set I2C master stop signal timing
|
||||
*
|
||||
* @param i2c_num I2C port number
|
||||
* @param setup_time clock num between the rising-edge of SCL and the rising-edge of SDA, it's a 10-bit value.
|
||||
* @param hold_time clock number after the STOP bit's rising-edge, it's a 14-bit value.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
*/
|
||||
esp_err_t i2c_set_stop_timing(i2c_port_t i2c_num, int setup_time, int hold_time);
|
||||
|
||||
/**
|
||||
* @brief get I2C master stop signal timing
|
||||
*
|
||||
* @param i2c_num I2C port number
|
||||
* @param setup_time pointer to get setup time.
|
||||
* @param hold_time pointer to get hold time.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
*/
|
||||
esp_err_t i2c_get_stop_timing(i2c_port_t i2c_num, int* setup_time, int* hold_time);
|
||||
|
||||
/**
|
||||
* @brief set I2C data signal timing
|
||||
*
|
||||
* @param i2c_num I2C port number
|
||||
* @param sample_time clock number I2C used to sample data on SDA after the rising-edge of SCL, it's a 10-bit value
|
||||
* @param hold_time clock number I2C used to hold the data after the falling-edge of SCL, it's a 10-bit value
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
*/
|
||||
esp_err_t i2c_set_data_timing(i2c_port_t i2c_num, int sample_time, int hold_time);
|
||||
|
||||
/**
|
||||
* @brief get I2C data signal timing
|
||||
*
|
||||
* @param i2c_num I2C port number
|
||||
* @param sample_time pointer to get sample time
|
||||
* @param hold_time pointer to get hold time
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
*/
|
||||
esp_err_t i2c_get_data_timing(i2c_port_t i2c_num, int* sample_time, int* hold_time);
|
||||
|
||||
/**
|
||||
* @brief set I2C data transfer mode
|
||||
*
|
||||
* @param i2c_num I2C port number
|
||||
* @param tx_trans_mode I2C sending data mode
|
||||
* @param rx_trans_mode I2C receving data mode
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
*/
|
||||
esp_err_t i2c_set_data_mode(i2c_port_t i2c_num, i2c_trans_mode_t tx_trans_mode, i2c_trans_mode_t rx_trans_mode);
|
||||
|
||||
/**
|
||||
* @brief get I2C data transfer mode
|
||||
*
|
||||
* @param i2c_num I2C port number
|
||||
* @param tx_trans_mode pointer to get I2C sending data mode
|
||||
* @param rx_trans_mode pointer to get I2C receiving data mode
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
*/
|
||||
esp_err_t i2c_get_data_mode(i2c_port_t i2c_num, i2c_trans_mode_t *tx_trans_mode, i2c_trans_mode_t *rx_trans_mode);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /*_DRIVER_I2C_H_*/
|
380
components/driver/include/driver/i2s.h
Normal file
380
components/driver/include/driver/i2s.h
Normal file
@ -0,0 +1,380 @@
|
||||
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// 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 _DRIVER_I2S_H_
|
||||
#define _DRIVER_I2S_H_
|
||||
#include "esp_err.h"
|
||||
#include <esp_types.h>
|
||||
#include "soc/gpio_reg.h"
|
||||
#include "soc/soc.h"
|
||||
#include "soc/i2s_struct.h"
|
||||
#include "soc/i2s_reg.h"
|
||||
#include "soc/rtc_io_reg.h"
|
||||
#include "soc/io_mux_reg.h"
|
||||
#include "rom/gpio.h"
|
||||
#include "esp_attr.h"
|
||||
#include "esp_intr_alloc.h"
|
||||
#include "driver/periph_ctrl.h"
|
||||
#include "freertos/semphr.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define I2S_PIN_NO_CHANGE (-1)
|
||||
|
||||
|
||||
/**
|
||||
* @brief I2S bit width per sample.
|
||||
*
|
||||
*/
|
||||
typedef enum {
|
||||
I2S_BITS_PER_SAMPLE_8BIT = 8, /*!< I2S bits per sample: 8-bits*/
|
||||
I2S_BITS_PER_SAMPLE_16BIT = 16, /*!< I2S bits per sample: 16-bits*/
|
||||
I2S_BITS_PER_SAMPLE_24BIT = 24, /*!< I2S bits per sample: 24-bits*/
|
||||
I2S_BITS_PER_SAMPLE_32BIT = 32, /*!< I2S bits per sample: 32-bits*/
|
||||
} i2s_bits_per_sample_t;
|
||||
|
||||
/**
|
||||
* @brief I2S communication standard format
|
||||
*
|
||||
*/
|
||||
typedef enum {
|
||||
I2S_COMM_FORMAT_I2S = 0x01, /*!< I2S communication format I2S*/
|
||||
I2S_COMM_FORMAT_I2S_MSB = 0x02, /*!< I2S format MSB*/
|
||||
I2S_COMM_FORMAT_I2S_LSB = 0x04, /*!< I2S format LSB*/
|
||||
I2S_COMM_FORMAT_PCM = 0x08, /*!< I2S communication format PCM*/
|
||||
I2S_COMM_FORMAT_PCM_SHORT = 0x10, /*!< PCM Short*/
|
||||
I2S_COMM_FORMAT_PCM_LONG = 0x20, /*!< PCM Long*/
|
||||
} i2s_comm_format_t;
|
||||
|
||||
|
||||
/**
|
||||
* @brief I2S channel format type
|
||||
*/
|
||||
typedef enum {
|
||||
I2S_CHANNEL_FMT_RIGHT_LEFT = 0x00,
|
||||
I2S_CHANNEL_FMT_ALL_RIGHT,
|
||||
I2S_CHANNEL_FMT_ALL_LEFT,
|
||||
I2S_CHANNEL_FMT_ONLY_RIGHT,
|
||||
I2S_CHANNEL_FMT_ONLY_LEFT,
|
||||
} i2s_channel_fmt_t;
|
||||
|
||||
/**
|
||||
* @brief PDM sample rate ratio, measured in Hz.
|
||||
*
|
||||
*/
|
||||
typedef enum {
|
||||
PDM_SAMPLE_RATE_RATIO_64,
|
||||
PDM_SAMPLE_RATE_RATIO_128,
|
||||
} pdm_sample_rate_ratio_t;
|
||||
|
||||
/**
|
||||
* @brief PDM PCM convter enable/disable.
|
||||
*
|
||||
*/
|
||||
typedef enum {
|
||||
PDM_PCM_CONV_ENABLE,
|
||||
PDM_PCM_CONV_DISABLE,
|
||||
} pdm_pcm_conv_t;
|
||||
|
||||
|
||||
/**
|
||||
* @brief I2S Peripheral, 0 & 1.
|
||||
*
|
||||
*/
|
||||
typedef enum {
|
||||
I2S_NUM_0 = 0x0, /*!< I2S 0*/
|
||||
I2S_NUM_1 = 0x1, /*!< I2S 1*/
|
||||
I2S_NUM_MAX,
|
||||
} i2s_port_t;
|
||||
|
||||
/**
|
||||
* @brief I2S Mode, defaut is I2S_MODE_MASTER | I2S_MODE_TX
|
||||
*
|
||||
*/
|
||||
typedef enum {
|
||||
I2S_MODE_MASTER = 1,
|
||||
I2S_MODE_SLAVE = 2,
|
||||
I2S_MODE_TX = 4,
|
||||
I2S_MODE_RX = 8,
|
||||
I2S_MODE_DAC_BUILT_IN = 16
|
||||
} i2s_mode_t;
|
||||
|
||||
/**
|
||||
* @brief I2S configuration parameters for i2s_param_config function
|
||||
*
|
||||
*/
|
||||
typedef struct {
|
||||
i2s_mode_t mode; /*!< I2S work mode*/
|
||||
int sample_rate; /*!< I2S sample rate*/
|
||||
i2s_bits_per_sample_t bits_per_sample; /*!< I2S bits per sample*/
|
||||
i2s_channel_fmt_t channel_format; /*!< I2S channel format */
|
||||
i2s_comm_format_t communication_format; /*!< I2S communication format */
|
||||
int intr_alloc_flags; /*!< Flags used to allocate the interrupt. One or multiple (ORred) ESP_INTR_FLAG_* values. See esp_intr_alloc.h for more info */
|
||||
int dma_buf_count; /*!< I2S DMA Buffer Count */
|
||||
int dma_buf_len; /*!< I2S DMA Buffer Length */
|
||||
} i2s_config_t;
|
||||
|
||||
/**
|
||||
* @brief I2S event types
|
||||
*
|
||||
*/
|
||||
typedef enum {
|
||||
I2S_EVENT_DMA_ERROR,
|
||||
I2S_EVENT_TX_DONE, /*!< I2S DMA finish sent 1 buffer*/
|
||||
I2S_EVENT_RX_DONE, /*!< I2S DMA finish received 1 buffer*/
|
||||
I2S_EVENT_MAX, /*!< I2S event max index*/
|
||||
} i2s_event_type_t;
|
||||
|
||||
/**
|
||||
* @brief Event structure used in I2S event queue
|
||||
*
|
||||
*/
|
||||
typedef struct {
|
||||
i2s_event_type_t type; /*!< I2S event type */
|
||||
size_t size; /*!< I2S data size for I2S_DATA event*/
|
||||
} i2s_event_t;
|
||||
|
||||
/**
|
||||
* @brief I2S pin number for i2s_set_pin
|
||||
*
|
||||
*/
|
||||
typedef struct {
|
||||
int bck_io_num; /*!< BCK in out pin*/
|
||||
int ws_io_num; /*!< WS in out pin*/
|
||||
int data_out_num; /*!< DATA out pin*/
|
||||
int data_in_num; /*!< DATA in pin*/
|
||||
} i2s_pin_config_t;
|
||||
|
||||
typedef intr_handle_t i2s_isr_handle_t;
|
||||
/**
|
||||
* @brief Set I2S pin number
|
||||
*
|
||||
* @note
|
||||
* Internal signal can be output to multiple GPIO pads
|
||||
* Only one GPIO pad can connect with input signal
|
||||
*
|
||||
* @param i2s_num I2S_NUM_0 or I2S_NUM_1
|
||||
*
|
||||
* @param pin I2S Pin struct, or NULL for 2-channels, 8-bits DAC pin configuration (GPIO25 & GPIO26)
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_FAIL Parameter error
|
||||
*/
|
||||
esp_err_t i2s_set_pin(i2s_port_t i2s_num, const i2s_pin_config_t *pin);
|
||||
|
||||
/**
|
||||
* @brief i2s install and start driver
|
||||
*
|
||||
* @param i2s_num I2S_NUM_0, I2S_NUM_1
|
||||
*
|
||||
* @param i2s_config I2S configurations - see i2s_config_t struct
|
||||
*
|
||||
* @param queue_size I2S event queue size/depth.
|
||||
*
|
||||
* @param i2s_queue I2S event queue handle, if set NULL, driver will not use an event queue.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_FAIL Parameter error
|
||||
*/
|
||||
esp_err_t i2s_driver_install(i2s_port_t i2s_num, const i2s_config_t *i2s_config, int queue_size, void* i2s_queue);
|
||||
|
||||
/**
|
||||
* @brief Uninstall I2S driver.
|
||||
*
|
||||
* @param i2s_num I2S_NUM_0, I2S_NUM_1
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_FAIL Parameter error
|
||||
*/
|
||||
esp_err_t i2s_driver_uninstall(i2s_port_t i2s_num);
|
||||
|
||||
/**
|
||||
* @brief i2s read data buffer to i2s dma buffer
|
||||
*
|
||||
* @param i2s_num I2S_NUM_0, I2S_NUM_1
|
||||
*
|
||||
* @param src source address to write
|
||||
*
|
||||
* @param size size of data (size in bytes)
|
||||
*
|
||||
* @param ticks_to_wait Write timeout
|
||||
*
|
||||
* @return number of written bytes
|
||||
*/
|
||||
int i2s_write_bytes(i2s_port_t i2s_num, const char *src, size_t size, TickType_t ticks_to_wait);
|
||||
|
||||
/**
|
||||
* @brief i2s write data buffer to i2s dma buffer
|
||||
*
|
||||
* @param i2s_num I2S_NUM_0, I2S_NUM_1
|
||||
*
|
||||
* @param dest destination address to read
|
||||
*
|
||||
* @param size size of data (size in bytes)
|
||||
*
|
||||
* @param ticks_to_wait Read timeout
|
||||
*
|
||||
* @return number of read bytes
|
||||
*/
|
||||
int i2s_read_bytes(i2s_port_t i2s_num, char* dest, size_t size, TickType_t ticks_to_wait);
|
||||
|
||||
/**
|
||||
* @brief i2s push 1 sample to i2s dma buffer, with the size parameter equal to one sample's size in bytes = bits_per_sample/8.
|
||||
*
|
||||
* @param i2s_num I2S_NUM_0, I2S_NUM_1
|
||||
*
|
||||
* @param sample destination address to write (depend on bits_per_sample, size of sample (in bytes) = 2*bits_per_sample/8)
|
||||
*
|
||||
* @param ticks_to_wait Push timeout
|
||||
*
|
||||
* @return number of push bytes
|
||||
*/
|
||||
int i2s_push_sample(i2s_port_t i2s_num, const char *sample, TickType_t ticks_to_wait);
|
||||
|
||||
/**
|
||||
* @brief Pop 1 sample to i2s dma buffer, with the size parameter equal to one sample's size in bytes = bits_per_sample/8.
|
||||
*
|
||||
* @param i2s_num I2S_NUM_0, I2S_NUM_1
|
||||
*
|
||||
* @param sample destination address to write (depend on bits_per_sample, size of sample (in bytes) = 2*bits_per_sample/8)
|
||||
*
|
||||
* @param ticks_to_wait Pop timeout
|
||||
*
|
||||
* @return number of pop bytes
|
||||
*/
|
||||
int i2s_pop_sample(i2s_port_t i2s_num, char *sample, TickType_t ticks_to_wait);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set clock rate used for I2S RX and TX
|
||||
*
|
||||
* @param i2s_num I2S_NUM_0, I2S_NUM_1
|
||||
*
|
||||
* @param rate I2S clock (ex: 8000, 44100...)
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_FAIL Parameter error
|
||||
*/
|
||||
esp_err_t i2s_set_sample_rates(i2s_port_t i2s_num, uint32_t rate);
|
||||
|
||||
/**
|
||||
* @brief Start driver
|
||||
*
|
||||
* @param i2s_num I2S_NUM_0, I2S_NUM_1
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_FAIL Parameter error
|
||||
*/
|
||||
esp_err_t i2s_start(i2s_port_t i2s_num);
|
||||
|
||||
/**
|
||||
* @brief Stop driver
|
||||
*
|
||||
* @param i2s_num I2S_NUM_0, I2S_NUM_1
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_FAIL Parameter error
|
||||
*/
|
||||
esp_err_t i2s_stop(i2s_port_t i2s_num);
|
||||
|
||||
/**
|
||||
* @brief Set the TX DMA buffer contents to all zeroes
|
||||
*
|
||||
* @param i2s_num I2S_NUM_0, I2S_NUM_1
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_FAIL Parameter error
|
||||
*/
|
||||
esp_err_t i2s_zero_dma_buffer(i2s_port_t i2s_num);
|
||||
|
||||
/***************************EXAMPLE**********************************
|
||||
*
|
||||
*
|
||||
* ----------------EXAMPLE OF I2S SETTING ---------------------
|
||||
* @code{c}
|
||||
*
|
||||
* #include "freertos/queue.h"
|
||||
* #define I2S_INTR_NUM 17 //choose one interrupt number from soc.h
|
||||
* int i2s_num = 0; //i2s port number
|
||||
* i2s_config_t i2s_config = {
|
||||
* .mode = I2S_MODE_MASTER | I2S_MODE_TX,
|
||||
* .sample_rate = 44100,
|
||||
* .bits_per_sample = 16, //16, 32
|
||||
* .channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT, //format LEFT_RIGHT
|
||||
* .communication_format = I2S_COMM_FORMAT_I2S | I2S_COMM_FORMAT_I2S_MSB,
|
||||
* .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,
|
||||
* .dma_buf_count = 8,
|
||||
* .dma_buf_len = 64
|
||||
* };
|
||||
*
|
||||
* i2s_pin_config_t pin_config = {
|
||||
* .bck_io_num = 26,
|
||||
* .ws_io_num = 25,
|
||||
* .data_out_num = 22,
|
||||
* .data_in_num = I2S_PIN_NO_CHANGE
|
||||
* };
|
||||
*
|
||||
* i2s_driver_install(i2s_num, &i2s_config, 0, NULL); //install and start i2s driver
|
||||
*
|
||||
* i2s_set_pin(i2s_num, &pin_config);
|
||||
*
|
||||
* i2s_set_sample_rates(i2s_num, 22050); //set sample rates
|
||||
*
|
||||
*
|
||||
* i2s_driver_uninstall(i2s_num); //stop & destroy i2s driver
|
||||
*@endcode
|
||||
*
|
||||
* ----------------EXAMPLE USING I2S WITH DAC ---------------------
|
||||
* @code{c}
|
||||
*
|
||||
* #include "freertos/queue.h"
|
||||
* #define I2S_INTR_NUM 17 //choose one interrupt number from soc.h
|
||||
* int i2s_num = 0; //i2s port number
|
||||
* i2s_config_t i2s_config = {
|
||||
* .mode = I2S_MODE_MASTER | I2S_MODE_TX | I2S_MODE_DAC_BUILT_IN,
|
||||
* .sample_rate = 44100,
|
||||
* .bits_per_sample = 8, // Only 8-bit DAC support
|
||||
* .channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT, //
|
||||
* .communication_format = I2S_COMM_FORMAT_I2S_MSB,
|
||||
* .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,
|
||||
* .dma_buf_count = 8,
|
||||
* .dma_buf_len = 64
|
||||
* };
|
||||
*
|
||||
*
|
||||
* i2s_driver_install(i2s_num, &i2s_config, 0, NULL); //install and start i2s driver
|
||||
*
|
||||
* i2s_set_pin(i2s_num, NULL); //for internal DAC
|
||||
*
|
||||
* i2s_set_sample_rates(i2s_num, 22050); //set sample rates
|
||||
*
|
||||
* i2s_driver_uninstall(i2s_num); //stop & destroy i2s driver
|
||||
*@endcode
|
||||
*-----------------------------------------------------------------------------*
|
||||
***************************END OF EXAMPLE**********************************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _DRIVER_I2S_H_ */
|
@ -16,9 +16,6 @@
|
||||
#define _DRIVER_LEDC_H_
|
||||
#include "esp_err.h"
|
||||
#include "soc/soc.h"
|
||||
#include "soc/ledc_reg.h"
|
||||
#include "soc/ledc_reg.h"
|
||||
#include "soc/ledc_struct.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "driver/periph_ctrl.h"
|
||||
#include "esp_intr_alloc.h"
|
||||
@ -68,6 +65,7 @@ typedef enum {
|
||||
LEDC_CHANNEL_5, /*!< LEDC channel 5 */
|
||||
LEDC_CHANNEL_6, /*!< LEDC channel 6 */
|
||||
LEDC_CHANNEL_7, /*!< LEDC channel 7 */
|
||||
LEDC_CHANNEL_MAX,
|
||||
} ledc_channel_t;
|
||||
|
||||
typedef enum {
|
||||
@ -79,6 +77,11 @@ typedef enum {
|
||||
LEDC_TIMER_15_BIT = 15, /*!< LEDC PWM depth 15Bit */
|
||||
} ledc_timer_bit_t;
|
||||
|
||||
typedef enum {
|
||||
LEDC_FADE_NO_WAIT = 0, /*!< LEDC fade function will return immediately */
|
||||
LEDC_FADE_WAIT_DONE, /*!< LEDC fade function will block until fading to the target duty*/
|
||||
LEDC_FADE_MAX,
|
||||
} ledc_fade_mode_t;
|
||||
/**
|
||||
* @brief Configuration parameters of LEDC channel for ledc_channel_config function
|
||||
*/
|
||||
@ -105,41 +108,37 @@ typedef intr_handle_t ledc_isr_handle_t;
|
||||
|
||||
/**
|
||||
* @brief LEDC channel configuration
|
||||
*
|
||||
* User this Function, configure LEDC channel with the given channel/output gpio_num/interrupt/source timer/frequency(Hz)/LEDC depth
|
||||
* Configure LEDC channel with the given channel/output gpio_num/interrupt/source timer/frequency(Hz)/LEDC depth
|
||||
*
|
||||
* @param ledc_conf Pointer of LEDC channel configure struct
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
*
|
||||
*/
|
||||
esp_err_t ledc_channel_config(ledc_channel_config_t* ledc_conf);
|
||||
|
||||
/**
|
||||
* @brief LEDC timer configuration
|
||||
*
|
||||
* User this Function, configure LEDC timer with the given source timer/frequency(Hz)/bit_num
|
||||
* Configure LEDC timer with the given source timer/frequency(Hz)/bit_num
|
||||
*
|
||||
* @param timer_conf Pointer of LEDC timer configure struct
|
||||
*
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
* - ESP_FAIL Can not find a proper pre-divider number base on the given frequency and the current bit_num.
|
||||
*
|
||||
*/
|
||||
esp_err_t ledc_timer_config(ledc_timer_config_t* timer_conf);
|
||||
|
||||
/**
|
||||
* @brief LEDC update channel parameters
|
||||
*
|
||||
* Call this function to activate the LEDC updated parameters.
|
||||
* After ledc_set_duty, ledc_set_fade, we need to call this function to update the settings.
|
||||
*
|
||||
* @param speed_mode Select the LEDC speed_mode, high-speed mode and low-speed mode, now we only support high-speed mode. We will access low-speed mode in next version
|
||||
*
|
||||
* @param speed_mode Select the LEDC speed_mode, high-speed mode and low-speed mode,
|
||||
* now we only support high-speed mode.
|
||||
* We will access low-speed mode in next version
|
||||
* @param channel LEDC channel(0-7), select from ledc_channel_t
|
||||
*
|
||||
* @return
|
||||
@ -150,14 +149,11 @@ esp_err_t ledc_timer_config(ledc_timer_config_t* timer_conf);
|
||||
esp_err_t ledc_update_duty(ledc_mode_t speed_mode, ledc_channel_t channel);
|
||||
|
||||
/**
|
||||
* @brief LEDC stop
|
||||
*
|
||||
* @brief LEDC stop.
|
||||
* Disable LEDC output, and set idle level
|
||||
*
|
||||
* @param speed_mode Select the LEDC speed_mode, high-speed mode and low-speed mode, now we only support high-speed mode. We will access low-speed mode in next version
|
||||
*
|
||||
* @param channel LEDC channel(0-7), select from ledc_channel_t
|
||||
*
|
||||
* @param idle_level Set output idle level after LEDC stops.
|
||||
*
|
||||
* @return
|
||||
@ -169,12 +165,8 @@ esp_err_t ledc_stop(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t idl
|
||||
/**
|
||||
* @brief LEDC set channel frequency(Hz)
|
||||
*
|
||||
* Set LEDC frequency(Hz)
|
||||
*
|
||||
* @param speed_mode Select the LEDC speed_mode, high-speed mode and low-speed mode, now we only support high-speed mode. We will access low-speed mode in next version
|
||||
*
|
||||
* @param timer_num LEDC timer index(0-3), select from ledc_timer_t
|
||||
*
|
||||
* @param freq_hz Set the LEDC frequency
|
||||
*
|
||||
* @return
|
||||
@ -188,25 +180,20 @@ esp_err_t ledc_set_freq(ledc_mode_t speed_mode, ledc_timer_t timer_num, uint32_t
|
||||
* @brief LEDC get channel frequency(Hz)
|
||||
*
|
||||
* @param speed_mode Select the LEDC speed_mode, high-speed mode and low-speed mode, now we only support high-speed mode. We will access low-speed mode in next version
|
||||
*
|
||||
* @param timer_num LEDC timer index(0-3), select from ledc_timer_t
|
||||
*
|
||||
* @return
|
||||
* - 0 error
|
||||
* - Others Current LEDC frequency
|
||||
*
|
||||
*/
|
||||
uint32_t ledc_get_freq(ledc_mode_t speed_mode, ledc_timer_t timer_num);
|
||||
|
||||
/**
|
||||
* @brief LEDC set duty
|
||||
*
|
||||
* Set LEDC duty, After the function calls the ledc_update_duty function, the function can take effect.
|
||||
* Only after calling ledc_update_duty will the duty update.
|
||||
*
|
||||
* @param speed_mode Select the LEDC speed_mode, high-speed mode and low-speed mode, now we only support high-speed mode. We will access low-speed mode in next version
|
||||
*
|
||||
* @param channel LEDC channel(0-7), select from ledc_channel_t
|
||||
*
|
||||
* @param duty Set the LEDC duty, the duty range is [0, (2**bit_num) - 1]
|
||||
*
|
||||
* @return
|
||||
@ -219,45 +206,35 @@ esp_err_t ledc_set_duty(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t
|
||||
* @brief LEDC get duty
|
||||
*
|
||||
* @param speed_mode Select the LEDC speed_mode, high-speed mode and low-speed mode, now we only support high-speed mode. We will access low-speed mode in next version
|
||||
*
|
||||
* @param channel LEDC channel(0-7), select from ledc_channel_t
|
||||
*
|
||||
*
|
||||
* @return
|
||||
* - (-1) parameter error
|
||||
* - Others Current LEDC duty
|
||||
*
|
||||
*/
|
||||
int ledc_get_duty(ledc_mode_t speed_mode, ledc_channel_t channel);
|
||||
|
||||
/**
|
||||
* @brief LEDC set gradient
|
||||
*
|
||||
* Set LEDC gradient, After the function calls the ledc_update_duty function, the function can take effect.
|
||||
*
|
||||
* @param speed_mode Select the LEDC speed_mode, high-speed mode and low-speed mode, now we only support high-speed mode. We will access low-speed mode in next version
|
||||
*
|
||||
* @param channel LEDC channel(0-7), select from ledc_channel_t
|
||||
*
|
||||
* @param duty Set the start of the gradient duty, the duty range is [0, (2**bit_num) - 1]
|
||||
*
|
||||
* @param gradule_direction Set the direction of the gradient
|
||||
*
|
||||
* @param step_num Set the number of the gradient
|
||||
*
|
||||
* @param duty_cyle_num Set how many LEDC tick each time the gradient lasts
|
||||
*
|
||||
* @param duty_scale Set gradient change amplitude
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
*/
|
||||
esp_err_t ledc_set_fade(ledc_mode_t speed_mode, uint32_t channel, uint32_t duty, ledc_duty_direction_t gradule_direction,
|
||||
esp_err_t ledc_set_fade(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t duty, ledc_duty_direction_t gradule_direction,
|
||||
uint32_t step_num, uint32_t duty_cyle_num, uint32_t duty_scale);
|
||||
|
||||
/**
|
||||
* @brief register LEDC interrupt handler, the handler is an ISR.
|
||||
* @brief Register LEDC interrupt handler, the handler is an ISR.
|
||||
* The handler will be attached to the same CPU core that this function is running on.
|
||||
*
|
||||
* @param fn Interrupt handler function.
|
||||
@ -275,48 +252,38 @@ esp_err_t ledc_set_fade(ledc_mode_t speed_mode, uint32_t channel, uint32_t duty,
|
||||
esp_err_t ledc_isr_register(void (*fn)(void*), void * arg, int intr_alloc_flags, ledc_isr_handle_t *handle);
|
||||
|
||||
/**
|
||||
* @brief configure LEDC settings
|
||||
* @brief Configure LEDC settings
|
||||
*
|
||||
* @param speed_mode Select the LEDC speed_mode, high-speed mode and low-speed mode, now we only support high-speed mode. We will access low-speed mode in next version
|
||||
*
|
||||
* @param timer_sel Timer index(0-3), there are 4 timers in LEDC module
|
||||
*
|
||||
* @param div_num Timer clock divide number, the timer clock is divided from the selected clock source
|
||||
*
|
||||
* @param bit_num The count number of one period, counter range is 0 ~ ((2 ** bit_num) - 1)
|
||||
*
|
||||
* @param clk_src Select LEDC source clock.
|
||||
*
|
||||
* @return
|
||||
* - (-1) Parameter error
|
||||
* - Other Current LEDC duty
|
||||
*
|
||||
*/
|
||||
esp_err_t ledc_timer_set(ledc_mode_t speed_mode, ledc_timer_t timer_sel, uint32_t div_num, uint32_t bit_num, ledc_clk_src_t clk_src);
|
||||
|
||||
/**
|
||||
* @brief reset LEDC timer
|
||||
* @brief Reset LEDC timer
|
||||
*
|
||||
* @param speed_mode Select the LEDC speed_mode, high-speed mode and low-speed mode, now we only support high-speed mode. We will access low-speed mode in next version
|
||||
*
|
||||
* @param timer_sel LEDC timer index(0-3), select from ledc_timer_t
|
||||
*
|
||||
*
|
||||
* @return
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
* - ESP_OK Success
|
||||
*
|
||||
*/
|
||||
esp_err_t ledc_timer_rst(ledc_mode_t speed_mode, uint32_t timer_sel);
|
||||
|
||||
/**
|
||||
* @brief pause LEDC timer counter
|
||||
* @brief Pause LEDC timer counter
|
||||
*
|
||||
* @param speed_mode Select the LEDC speed_mode, high-speed mode and low-speed mode, now we only support high-speed mode. We will access low-speed mode in next version
|
||||
*
|
||||
* @param timer_sel LEDC timer index(0-3), select from ledc_timer_t
|
||||
*
|
||||
*
|
||||
* @return
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
* - ESP_OK Success
|
||||
@ -325,104 +292,96 @@ esp_err_t ledc_timer_rst(ledc_mode_t speed_mode, uint32_t timer_sel);
|
||||
esp_err_t ledc_timer_pause(ledc_mode_t speed_mode, uint32_t timer_sel);
|
||||
|
||||
/**
|
||||
* @brief pause LEDC timer resume
|
||||
* @brief Resume LEDC timer
|
||||
*
|
||||
* @param speed_mode Select the LEDC speed_mode, high-speed mode and low-speed mode, now we only support high-speed mode. We will access low-speed mode in next version
|
||||
*
|
||||
* @param timer_sel LEDC timer index(0-3), select from ledc_timer_t
|
||||
*
|
||||
*
|
||||
* @return
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
* - ESP_OK Success
|
||||
*
|
||||
*/
|
||||
esp_err_t ledc_timer_resume(ledc_mode_t speed_mode, uint32_t timer_sel);
|
||||
|
||||
/**
|
||||
* @brief bind LEDC channel with the selected timer
|
||||
* @brief Bind LEDC channel with the selected timer
|
||||
*
|
||||
* @param speed_mode Select the LEDC speed_mode, high-speed mode and low-speed mode, now we only support high-speed mode. We will access low-speed mode in next version
|
||||
*
|
||||
* @param channel LEDC channel index(0-7), select from ledc_channel_t
|
||||
*
|
||||
* @param timer_idx LEDC timer index(0-3), select from ledc_timer_t
|
||||
*
|
||||
*
|
||||
* @return
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
* - ESP_OK Success
|
||||
*
|
||||
*/
|
||||
esp_err_t ledc_bind_channel_timer(ledc_mode_t speed_mode, uint32_t channel, uint32_t timer_idx);
|
||||
|
||||
/***************************EXAMPLE**********************************
|
||||
/**
|
||||
* @brief Set LEDC fade function. Should call ledc_fade_func_install() before calling this function.
|
||||
* Call ledc_fade_start() after this to start fading.
|
||||
*
|
||||
* @param speed_mode Select the LEDC speed_mode, high-speed mode and low-speed mode,
|
||||
* For now we only support high-speed mode. We will access low-speed mode soon.
|
||||
* @param channel LEDC channel index(0-7), select from ledc_channel_t
|
||||
* @param target_duty Target duty of fading.( 0 - (2 ** bit_num - 1)))
|
||||
* @param scale Controls the increase or decrease step scale.
|
||||
* @param cycle_num increase or decrease the duty every cycle_num cycles
|
||||
*
|
||||
* ----------------EXAMPLE OF LEDC SETTING ---------------------
|
||||
* @code{c}
|
||||
* //1. enable LEDC
|
||||
* //enable LEDC module, or you can not set any register of it.
|
||||
* periph_module_enable(PERIPH_LEDC_MODULE);
|
||||
* @endcode
|
||||
*
|
||||
* @code{c}
|
||||
* //2. set LEDC timer
|
||||
* ledc_timer_config_t timer_conf = {
|
||||
* .bit_num = LEDC_TIMER_12_BIT, //set timer counter bit number
|
||||
* .freq_hz = 1000, //set frequency of pwm, here, 1000Hz
|
||||
* .speed_mode = LEDC_HIGH_SPEED_MODE, //timer mode,
|
||||
* .timer_num = LEDC_TIMER_0, //timer number
|
||||
* };
|
||||
* ledc_timer_config(&timer_conf); //setup timer.
|
||||
* @endcode
|
||||
*
|
||||
* @code{c}
|
||||
* //3. set LEDC channel
|
||||
* ledc_channel_config_t ledc_conf = {
|
||||
* .channel = LEDC_CHANNEL_0; //set LEDC channel 0
|
||||
* .duty = 1000; //set the duty for initialization.(duty range is 0 ~ ((2**bit_num)-1)
|
||||
* .gpio_num = 16; //GPIO number
|
||||
* .intr_type = LEDC_INTR_FADE_END; //GPIO INTR TYPE, as an example, we enable fade_end interrupt here.
|
||||
* .speed_mode = LEDC_HIGH_SPEED_MODE; //set LEDC mode, from ledc_mode_t
|
||||
* .timer_sel = LEDC_TIMER_0; //set LEDC timer source, if different channel use one timer, the frequency and bit_num of these channels should be the same
|
||||
* }
|
||||
* ledc_channel_config(&ledc_conf); //setup the configuration
|
||||
*
|
||||
* ----------------EXAMPLE OF SETTING DUTY --- -----------------
|
||||
* @code{c}
|
||||
* uint32_t ledc_channel = LEDC_CHANNEL_0; //LEDC channel(0-73)
|
||||
* uint32_t duty = 2000; //duty range is 0 ~ ((2**bit_num)-1)
|
||||
* LEDC_set_duty(LEDC_HIGH_SPEED_MODE, ledc_channel, duty); //set speed mode, channel, and duty.
|
||||
* ledc_update_duty(LEDC_HIGH_SPEED_MODE, ledc_channel); //after set duty, we need to call ledc_update_duty to update the settings.
|
||||
* @endcode
|
||||
*
|
||||
* ----------------EXAMPLE OF LEDC INTERRUPT ------------------
|
||||
* @code{c}
|
||||
* //we have fade_end interrupt and counter overflow interrupt. we just give an example of fade_end interrupt here.
|
||||
* ledc_isr_register(ledc_isr_handler, NULL, 0); //hook the isr handler for LEDC interrupt
|
||||
* @endcode
|
||||
*
|
||||
* ----------------EXAMPLE OF INTERRUPT HANDLER ---------------
|
||||
* @code{c}
|
||||
* #include "esp_attr.h"
|
||||
* void IRAM_ATTR ledc_isr_handler(void* arg) //we should add 'IRAM_ATTR' attribution when we declare the isr function
|
||||
* {
|
||||
* uint32_t intr_st = LEDC.int_st.val; //read LEDC interrupt status.
|
||||
*
|
||||
* //you will find which channels have triggered fade_end interrupt here,
|
||||
* //then, you can post some event to RTOS queue to process the event.
|
||||
* //later we will add a queue in the driver code.
|
||||
*
|
||||
* LEDC.int_clr.val = intr_st; //clear LEDC interrupt status.
|
||||
* }
|
||||
* @endcode
|
||||
*
|
||||
*--------------------------END OF EXAMPLE --------------------------
|
||||
* @return
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_STATE Fade function not installed.
|
||||
*/
|
||||
esp_err_t ledc_set_fade_with_step(ledc_mode_t speed_mode, ledc_channel_t channel, int target_duty, int scale, int cycle_num);
|
||||
|
||||
/**
|
||||
* @brief Set LEDC fade function, with a limited time. Should call ledc_fade_func_install() before calling this function.
|
||||
* Call ledc_fade_start() after this to start fading.
|
||||
*
|
||||
* @param speed_mode Select the LEDC speed_mode, high-speed mode and low-speed mode,
|
||||
* For now we only support high-speed mode. We will access low-speed mode soon.
|
||||
* @param channel LEDC channel index(0-7), select from ledc_channel_t
|
||||
* @param target_duty Target duty of fading.( 0 - (2 ** bit_num - 1)))
|
||||
* @param max_fade_time_ms The maximum time of the fading ( ms ).
|
||||
*
|
||||
* @return
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_STATE Fade function not installed.
|
||||
*/
|
||||
esp_err_t ledc_set_fade_with_time(ledc_mode_t speed_mode, ledc_channel_t channel, int target_duty, int max_fade_time_ms);
|
||||
|
||||
/**
|
||||
* @brief Install ledc fade function. This function will occupy interrupt of LEDC module.
|
||||
*
|
||||
* @param intr_alloc_flags Flags used to allocate the interrupt. One or multiple (ORred)
|
||||
* ESP_INTR_FLAG_* values. See esp_intr_alloc.h for more info.
|
||||
*
|
||||
* @return
|
||||
* - ESP_ERR_NO_MEM No enough memory
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_STATE Fade function already installed.
|
||||
*/
|
||||
esp_err_t ledc_fade_func_install(int intr_alloc_flags);
|
||||
|
||||
/**
|
||||
* @brief Uninstall LEDC fade function.
|
||||
*
|
||||
*/
|
||||
void ledc_fade_func_uninstall();
|
||||
|
||||
/**
|
||||
* @brief Start LEDC fading.
|
||||
*
|
||||
* @param channel LEDC channel number
|
||||
* @param wait_done Whether to block until fading done.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_STATE Fade function not installed.
|
||||
* - ESP_ERR_INVALID_ARG Parameter error.
|
||||
*/
|
||||
esp_err_t ledc_fade_start(ledc_channel_t channel, ledc_fade_mode_t wait_done);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -41,6 +41,9 @@ typedef enum {
|
||||
PERIPH_UHCI1_MODULE,
|
||||
PERIPH_RMT_MODULE,
|
||||
PERIPH_PCNT_MODULE,
|
||||
PERIPH_SPI_MODULE,
|
||||
PERIPH_HSPI_MODULE,
|
||||
PERIPH_VSPI_MODULE,
|
||||
} periph_module_t;
|
||||
|
||||
/**
|
||||
|
@ -524,7 +524,9 @@ esp_err_t rmt_set_err_intr_en(rmt_channel_t channel, bool en);
|
||||
esp_err_t rmt_set_tx_intr_en(rmt_channel_t channel, bool en);
|
||||
|
||||
/**
|
||||
* @brief Set RMT TX event interrupt enable
|
||||
* @brief Set RMT TX threshold event interrupt enable
|
||||
*
|
||||
* Causes an interrupt when a threshold number of items have been transmitted.
|
||||
*
|
||||
* @param channel RMT channel (0 - 7)
|
||||
*
|
||||
@ -536,7 +538,7 @@ esp_err_t rmt_set_tx_intr_en(rmt_channel_t channel, bool en);
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t rmt_set_evt_intr_en(rmt_channel_t channel, bool en, uint16_t evt_thresh);
|
||||
esp_err_t rmt_set_tx_thr_intr_en(rmt_channel_t channel, bool en, uint16_t evt_thresh);
|
||||
|
||||
/**
|
||||
* @brief Set RMT pins
|
||||
|
303
components/driver/include/driver/sdmmc_defs.h
Normal file
303
components/driver/include/driver/sdmmc_defs.h
Normal file
@ -0,0 +1,303 @@
|
||||
/*
|
||||
* Copyright (c) 2006 Uwe Stuehler <uwe@openbsd.org>
|
||||
* Adaptations to ESP-IDF Copyright (c) 2016 Espressif Systems (Shanghai) PTE LTD
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _SDMMC_DEFS_H_
|
||||
#define _SDMMC_DEFS_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <limits.h>
|
||||
|
||||
/* MMC commands */ /* response type */
|
||||
#define MMC_GO_IDLE_STATE 0 /* R0 */
|
||||
#define MMC_SEND_OP_COND 1 /* R3 */
|
||||
#define MMC_ALL_SEND_CID 2 /* R2 */
|
||||
#define MMC_SET_RELATIVE_ADDR 3 /* R1 */
|
||||
#define MMC_SWITCH 6 /* R1B */
|
||||
#define MMC_SELECT_CARD 7 /* R1 */
|
||||
#define MMC_SEND_EXT_CSD 8 /* R1 */
|
||||
#define MMC_SEND_CSD 9 /* R2 */
|
||||
#define MMC_STOP_TRANSMISSION 12 /* R1B */
|
||||
#define MMC_SEND_STATUS 13 /* R1 */
|
||||
#define MMC_SET_BLOCKLEN 16 /* R1 */
|
||||
#define MMC_READ_BLOCK_SINGLE 17 /* R1 */
|
||||
#define MMC_READ_BLOCK_MULTIPLE 18 /* R1 */
|
||||
#define MMC_SET_BLOCK_COUNT 23 /* R1 */
|
||||
#define MMC_WRITE_BLOCK_SINGLE 24 /* R1 */
|
||||
#define MMC_WRITE_BLOCK_MULTIPLE 25 /* R1 */
|
||||
#define MMC_APP_CMD 55 /* R1 */
|
||||
|
||||
/* SD commands */ /* response type */
|
||||
#define SD_SEND_RELATIVE_ADDR 3 /* R6 */
|
||||
#define SD_SEND_SWITCH_FUNC 6 /* R1 */
|
||||
#define SD_SEND_IF_COND 8 /* R7 */
|
||||
|
||||
/* SD application commands */ /* response type */
|
||||
#define SD_APP_SET_BUS_WIDTH 6 /* R1 */
|
||||
#define SD_APP_OP_COND 41 /* R3 */
|
||||
#define SD_APP_SEND_SCR 51 /* R1 */
|
||||
|
||||
/* OCR bits */
|
||||
#define MMC_OCR_MEM_READY (1<<31) /* memory power-up status bit */
|
||||
#define MMC_OCR_ACCESS_MODE_MASK 0x60000000 /* bits 30:29 */
|
||||
#define MMC_OCR_SECTOR_MODE (1<<30)
|
||||
#define MMC_OCR_BYTE_MODE (1<<29)
|
||||
#define MMC_OCR_3_5V_3_6V (1<<23)
|
||||
#define MMC_OCR_3_4V_3_5V (1<<22)
|
||||
#define MMC_OCR_3_3V_3_4V (1<<21)
|
||||
#define MMC_OCR_3_2V_3_3V (1<<20)
|
||||
#define MMC_OCR_3_1V_3_2V (1<<19)
|
||||
#define MMC_OCR_3_0V_3_1V (1<<18)
|
||||
#define MMC_OCR_2_9V_3_0V (1<<17)
|
||||
#define MMC_OCR_2_8V_2_9V (1<<16)
|
||||
#define MMC_OCR_2_7V_2_8V (1<<15)
|
||||
#define MMC_OCR_2_6V_2_7V (1<<14)
|
||||
#define MMC_OCR_2_5V_2_6V (1<<13)
|
||||
#define MMC_OCR_2_4V_2_5V (1<<12)
|
||||
#define MMC_OCR_2_3V_2_4V (1<<11)
|
||||
#define MMC_OCR_2_2V_2_3V (1<<10)
|
||||
#define MMC_OCR_2_1V_2_2V (1<<9)
|
||||
#define MMC_OCR_2_0V_2_1V (1<<8)
|
||||
#define MMC_OCR_1_65V_1_95V (1<<7)
|
||||
|
||||
#define SD_OCR_SDHC_CAP (1<<30)
|
||||
#define SD_OCR_VOL_MASK 0xFF8000 /* bits 23:15 */
|
||||
|
||||
/* R1 response type bits */
|
||||
#define MMC_R1_READY_FOR_DATA (1<<8) /* ready for next transfer */
|
||||
#define MMC_R1_APP_CMD (1<<5) /* app. commands supported */
|
||||
|
||||
/* 48-bit response decoding (32 bits w/o CRC) */
|
||||
#define MMC_R1(resp) ((resp)[0])
|
||||
#define MMC_R3(resp) ((resp)[0])
|
||||
#define SD_R6(resp) ((resp)[0])
|
||||
#define MMC_R1_CURRENT_STATE(resp) (((resp)[0] >> 9) & 0xf)
|
||||
|
||||
/* RCA argument and response */
|
||||
#define MMC_ARG_RCA(rca) ((rca) << 16)
|
||||
#define SD_R6_RCA(resp) (SD_R6((resp)) >> 16)
|
||||
|
||||
/* bus width argument */
|
||||
#define SD_ARG_BUS_WIDTH_1 0
|
||||
#define SD_ARG_BUS_WIDTH_4 2
|
||||
|
||||
/* EXT_CSD fields */
|
||||
#define EXT_CSD_BUS_WIDTH 183 /* WO */
|
||||
#define EXT_CSD_HS_TIMING 185 /* R/W */
|
||||
#define EXT_CSD_REV 192 /* RO */
|
||||
#define EXT_CSD_STRUCTURE 194 /* RO */
|
||||
#define EXT_CSD_CARD_TYPE 196 /* RO */
|
||||
#define EXT_CSD_SEC_COUNT 212 /* RO */
|
||||
|
||||
/* EXT_CSD field definitions */
|
||||
#define EXT_CSD_CMD_SET_NORMAL (1U << 0)
|
||||
#define EXT_CSD_CMD_SET_SECURE (1U << 1)
|
||||
#define EXT_CSD_CMD_SET_CPSECURE (1U << 2)
|
||||
|
||||
/* EXT_CSD_HS_TIMING */
|
||||
#define EXT_CSD_HS_TIMING_BC 0
|
||||
#define EXT_CSD_HS_TIMING_HS 1
|
||||
#define EXT_CSD_HS_TIMING_HS200 2
|
||||
#define EXT_CSD_HS_TIMING_HS400 3
|
||||
|
||||
/* EXT_CSD_BUS_WIDTH */
|
||||
#define EXT_CSD_BUS_WIDTH_1 0
|
||||
#define EXT_CSD_BUS_WIDTH_4 1
|
||||
#define EXT_CSD_BUS_WIDTH_8 2
|
||||
#define EXT_CSD_BUS_WIDTH_4_DDR 5
|
||||
#define EXT_CSD_BUS_WIDTH_8_DDR 6
|
||||
|
||||
/* EXT_CSD_CARD_TYPE */
|
||||
/* The only currently valid values for this field are 0x01, 0x03, 0x07,
|
||||
* 0x0B and 0x0F. */
|
||||
#define EXT_CSD_CARD_TYPE_F_26M (1 << 0)
|
||||
#define EXT_CSD_CARD_TYPE_F_52M (1 << 1)
|
||||
#define EXT_CSD_CARD_TYPE_F_52M_1_8V (1 << 2)
|
||||
#define EXT_CSD_CARD_TYPE_F_52M_1_2V (1 << 3)
|
||||
#define EXT_CSD_CARD_TYPE_26M 0x01
|
||||
#define EXT_CSD_CARD_TYPE_52M 0x03
|
||||
#define EXT_CSD_CARD_TYPE_52M_V18 0x07
|
||||
#define EXT_CSD_CARD_TYPE_52M_V12 0x0b
|
||||
#define EXT_CSD_CARD_TYPE_52M_V12_18 0x0f
|
||||
|
||||
/* MMC_SWITCH access mode */
|
||||
#define MMC_SWITCH_MODE_CMD_SET 0x00 /* Change the command set */
|
||||
#define MMC_SWITCH_MODE_SET_BITS 0x01 /* Set bits in value */
|
||||
#define MMC_SWITCH_MODE_CLEAR_BITS 0x02 /* Clear bits in value */
|
||||
#define MMC_SWITCH_MODE_WRITE_BYTE 0x03 /* Set target to value */
|
||||
|
||||
/* MMC R2 response (CSD) */
|
||||
#define MMC_CSD_CSDVER(resp) MMC_RSP_BITS((resp), 126, 2)
|
||||
#define MMC_CSD_CSDVER_1_0 1
|
||||
#define MMC_CSD_CSDVER_2_0 2
|
||||
#define MMC_CSD_CSDVER_EXT_CSD 3
|
||||
#define MMC_CSD_MMCVER(resp) MMC_RSP_BITS((resp), 122, 4)
|
||||
#define MMC_CSD_MMCVER_1_0 0 /* MMC 1.0 - 1.2 */
|
||||
#define MMC_CSD_MMCVER_1_4 1 /* MMC 1.4 */
|
||||
#define MMC_CSD_MMCVER_2_0 2 /* MMC 2.0 - 2.2 */
|
||||
#define MMC_CSD_MMCVER_3_1 3 /* MMC 3.1 - 3.3 */
|
||||
#define MMC_CSD_MMCVER_4_0 4 /* MMC 4 */
|
||||
#define MMC_CSD_READ_BL_LEN(resp) MMC_RSP_BITS((resp), 80, 4)
|
||||
#define MMC_CSD_C_SIZE(resp) MMC_RSP_BITS((resp), 62, 12)
|
||||
#define MMC_CSD_CAPACITY(resp) ((MMC_CSD_C_SIZE((resp))+1) << \
|
||||
(MMC_CSD_C_SIZE_MULT((resp))+2))
|
||||
#define MMC_CSD_C_SIZE_MULT(resp) MMC_RSP_BITS((resp), 47, 3)
|
||||
|
||||
/* MMC v1 R2 response (CID) */
|
||||
#define MMC_CID_MID_V1(resp) MMC_RSP_BITS((resp), 104, 24)
|
||||
#define MMC_CID_PNM_V1_CPY(resp, pnm) \
|
||||
do { \
|
||||
(pnm)[0] = MMC_RSP_BITS((resp), 96, 8); \
|
||||
(pnm)[1] = MMC_RSP_BITS((resp), 88, 8); \
|
||||
(pnm)[2] = MMC_RSP_BITS((resp), 80, 8); \
|
||||
(pnm)[3] = MMC_RSP_BITS((resp), 72, 8); \
|
||||
(pnm)[4] = MMC_RSP_BITS((resp), 64, 8); \
|
||||
(pnm)[5] = MMC_RSP_BITS((resp), 56, 8); \
|
||||
(pnm)[6] = MMC_RSP_BITS((resp), 48, 8); \
|
||||
(pnm)[7] = '\0'; \
|
||||
} while (0)
|
||||
#define MMC_CID_REV_V1(resp) MMC_RSP_BITS((resp), 40, 8)
|
||||
#define MMC_CID_PSN_V1(resp) MMC_RSP_BITS((resp), 16, 24)
|
||||
#define MMC_CID_MDT_V1(resp) MMC_RSP_BITS((resp), 8, 8)
|
||||
|
||||
/* MMC v2 R2 response (CID) */
|
||||
#define MMC_CID_MID_V2(resp) MMC_RSP_BITS((resp), 120, 8)
|
||||
#define MMC_CID_OID_V2(resp) MMC_RSP_BITS((resp), 104, 16)
|
||||
#define MMC_CID_PNM_V2_CPY(resp, pnm) \
|
||||
do { \
|
||||
(pnm)[0] = MMC_RSP_BITS((resp), 96, 8); \
|
||||
(pnm)[1] = MMC_RSP_BITS((resp), 88, 8); \
|
||||
(pnm)[2] = MMC_RSP_BITS((resp), 80, 8); \
|
||||
(pnm)[3] = MMC_RSP_BITS((resp), 72, 8); \
|
||||
(pnm)[4] = MMC_RSP_BITS((resp), 64, 8); \
|
||||
(pnm)[5] = MMC_RSP_BITS((resp), 56, 8); \
|
||||
(pnm)[6] = '\0'; \
|
||||
} while (0)
|
||||
#define MMC_CID_PSN_V2(resp) MMC_RSP_BITS((resp), 16, 32)
|
||||
|
||||
/* SD R2 response (CSD) */
|
||||
#define SD_CSD_CSDVER(resp) MMC_RSP_BITS((resp), 126, 2)
|
||||
#define SD_CSD_CSDVER_1_0 0
|
||||
#define SD_CSD_CSDVER_2_0 1
|
||||
#define SD_CSD_TAAC(resp) MMC_RSP_BITS((resp), 112, 8)
|
||||
#define SD_CSD_TAAC_1_5_MSEC 0x26
|
||||
#define SD_CSD_NSAC(resp) MMC_RSP_BITS((resp), 104, 8)
|
||||
#define SD_CSD_SPEED(resp) MMC_RSP_BITS((resp), 96, 8)
|
||||
#define SD_CSD_SPEED_25_MHZ 0x32
|
||||
#define SD_CSD_SPEED_50_MHZ 0x5a
|
||||
#define SD_CSD_CCC(resp) MMC_RSP_BITS((resp), 84, 12)
|
||||
#define SD_CSD_CCC_BASIC (1 << 0) /* basic */
|
||||
#define SD_CSD_CCC_BR (1 << 2) /* block read */
|
||||
#define SD_CSD_CCC_BW (1 << 4) /* block write */
|
||||
#define SD_CSD_CCC_ERASE (1 << 5) /* erase */
|
||||
#define SD_CSD_CCC_WP (1 << 6) /* write protection */
|
||||
#define SD_CSD_CCC_LC (1 << 7) /* lock card */
|
||||
#define SD_CSD_CCC_AS (1 << 8) /*application specific*/
|
||||
#define SD_CSD_CCC_IOM (1 << 9) /* I/O mode */
|
||||
#define SD_CSD_CCC_SWITCH (1 << 10) /* switch */
|
||||
#define SD_CSD_READ_BL_LEN(resp) MMC_RSP_BITS((resp), 80, 4)
|
||||
#define SD_CSD_READ_BL_PARTIAL(resp) MMC_RSP_BITS((resp), 79, 1)
|
||||
#define SD_CSD_WRITE_BLK_MISALIGN(resp) MMC_RSP_BITS((resp), 78, 1)
|
||||
#define SD_CSD_READ_BLK_MISALIGN(resp) MMC_RSP_BITS((resp), 77, 1)
|
||||
#define SD_CSD_DSR_IMP(resp) MMC_RSP_BITS((resp), 76, 1)
|
||||
#define SD_CSD_C_SIZE(resp) MMC_RSP_BITS((resp), 62, 12)
|
||||
#define SD_CSD_CAPACITY(resp) ((SD_CSD_C_SIZE((resp))+1) << \
|
||||
(SD_CSD_C_SIZE_MULT((resp))+2))
|
||||
#define SD_CSD_V2_C_SIZE(resp) MMC_RSP_BITS((resp), 48, 22)
|
||||
#define SD_CSD_V2_CAPACITY(resp) ((SD_CSD_V2_C_SIZE((resp))+1) << 10)
|
||||
#define SD_CSD_V2_BL_LEN 0x9 /* 512 */
|
||||
#define SD_CSD_VDD_R_CURR_MIN(resp) MMC_RSP_BITS((resp), 59, 3)
|
||||
#define SD_CSD_VDD_R_CURR_MAX(resp) MMC_RSP_BITS((resp), 56, 3)
|
||||
#define SD_CSD_VDD_W_CURR_MIN(resp) MMC_RSP_BITS((resp), 53, 3)
|
||||
#define SD_CSD_VDD_W_CURR_MAX(resp) MMC_RSP_BITS((resp), 50, 3)
|
||||
#define SD_CSD_VDD_RW_CURR_100mA 0x7
|
||||
#define SD_CSD_VDD_RW_CURR_80mA 0x6
|
||||
#define SD_CSD_C_SIZE_MULT(resp) MMC_RSP_BITS((resp), 47, 3)
|
||||
#define SD_CSD_ERASE_BLK_EN(resp) MMC_RSP_BITS((resp), 46, 1)
|
||||
#define SD_CSD_SECTOR_SIZE(resp) MMC_RSP_BITS((resp), 39, 7) /* +1 */
|
||||
#define SD_CSD_WP_GRP_SIZE(resp) MMC_RSP_BITS((resp), 32, 7) /* +1 */
|
||||
#define SD_CSD_WP_GRP_ENABLE(resp) MMC_RSP_BITS((resp), 31, 1)
|
||||
#define SD_CSD_R2W_FACTOR(resp) MMC_RSP_BITS((resp), 26, 3)
|
||||
#define SD_CSD_WRITE_BL_LEN(resp) MMC_RSP_BITS((resp), 22, 4)
|
||||
#define SD_CSD_RW_BL_LEN_2G 0xa
|
||||
#define SD_CSD_RW_BL_LEN_1G 0x9
|
||||
#define SD_CSD_WRITE_BL_PARTIAL(resp) MMC_RSP_BITS((resp), 21, 1)
|
||||
#define SD_CSD_FILE_FORMAT_GRP(resp) MMC_RSP_BITS((resp), 15, 1)
|
||||
#define SD_CSD_COPY(resp) MMC_RSP_BITS((resp), 14, 1)
|
||||
#define SD_CSD_PERM_WRITE_PROTECT(resp) MMC_RSP_BITS((resp), 13, 1)
|
||||
#define SD_CSD_TMP_WRITE_PROTECT(resp) MMC_RSP_BITS((resp), 12, 1)
|
||||
#define SD_CSD_FILE_FORMAT(resp) MMC_RSP_BITS((resp), 10, 2)
|
||||
|
||||
/* SD R2 response (CID) */
|
||||
#define SD_CID_MID(resp) MMC_RSP_BITS((resp), 120, 8)
|
||||
#define SD_CID_OID(resp) MMC_RSP_BITS((resp), 104, 16)
|
||||
#define SD_CID_PNM_CPY(resp, pnm) \
|
||||
do { \
|
||||
(pnm)[0] = MMC_RSP_BITS((resp), 96, 8); \
|
||||
(pnm)[1] = MMC_RSP_BITS((resp), 88, 8); \
|
||||
(pnm)[2] = MMC_RSP_BITS((resp), 80, 8); \
|
||||
(pnm)[3] = MMC_RSP_BITS((resp), 72, 8); \
|
||||
(pnm)[4] = MMC_RSP_BITS((resp), 64, 8); \
|
||||
(pnm)[5] = '\0'; \
|
||||
} while (0)
|
||||
#define SD_CID_REV(resp) MMC_RSP_BITS((resp), 56, 8)
|
||||
#define SD_CID_PSN(resp) MMC_RSP_BITS((resp), 24, 32)
|
||||
#define SD_CID_MDT(resp) MMC_RSP_BITS((resp), 8, 12)
|
||||
|
||||
/* SCR (SD Configuration Register) */
|
||||
#define SCR_STRUCTURE(scr) MMC_RSP_BITS((scr), 60, 4)
|
||||
#define SCR_STRUCTURE_VER_1_0 0 /* Version 1.0 */
|
||||
#define SCR_SD_SPEC(scr) MMC_RSP_BITS((scr), 56, 4)
|
||||
#define SCR_SD_SPEC_VER_1_0 0 /* Version 1.0 and 1.01 */
|
||||
#define SCR_SD_SPEC_VER_1_10 1 /* Version 1.10 */
|
||||
#define SCR_SD_SPEC_VER_2 2 /* Version 2.00 or Version 3.0X */
|
||||
#define SCR_DATA_STAT_AFTER_ERASE(scr) MMC_RSP_BITS((scr), 55, 1)
|
||||
#define SCR_SD_SECURITY(scr) MMC_RSP_BITS((scr), 52, 3)
|
||||
#define SCR_SD_SECURITY_NONE 0 /* no security */
|
||||
#define SCR_SD_SECURITY_1_0 1 /* security protocol 1.0 */
|
||||
#define SCR_SD_SECURITY_1_0_2 2 /* security protocol 1.0 */
|
||||
#define SCR_SD_BUS_WIDTHS(scr) MMC_RSP_BITS((scr), 48, 4)
|
||||
#define SCR_SD_BUS_WIDTHS_1BIT (1 << 0) /* 1bit (DAT0) */
|
||||
#define SCR_SD_BUS_WIDTHS_4BIT (1 << 2) /* 4bit (DAT0-3) */
|
||||
#define SCR_SD_SPEC3(scr) MMC_RSP_BITS((scr), 47, 1)
|
||||
#define SCR_EX_SECURITY(scr) MMC_RSP_BITS((scr), 43, 4)
|
||||
#define SCR_SD_SPEC4(scr) MMC_RSP_BITS((scr), 42, 1)
|
||||
#define SCR_RESERVED(scr) MMC_RSP_BITS((scr), 34, 8)
|
||||
#define SCR_CMD_SUPPORT_CMD23(scr) MMC_RSP_BITS((scr), 33, 1)
|
||||
#define SCR_CMD_SUPPORT_CMD20(scr) MMC_RSP_BITS((scr), 32, 1)
|
||||
#define SCR_RESERVED2(scr) MMC_RSP_BITS((scr), 0, 32)
|
||||
|
||||
/* Status of Switch Function */
|
||||
#define SFUNC_STATUS_GROUP(status, group) \
|
||||
(__bitfield((uint32_t *)(status), 400 + (group - 1) * 16, 16))
|
||||
|
||||
#define SD_ACCESS_MODE_SDR12 0
|
||||
#define SD_ACCESS_MODE_SDR25 1
|
||||
#define SD_ACCESS_MODE_SDR50 2
|
||||
#define SD_ACCESS_MODE_SDR104 3
|
||||
#define SD_ACCESS_MODE_DDR50 4
|
||||
|
||||
static inline uint32_t MMC_RSP_BITS(uint32_t *src, int start, int len)
|
||||
{
|
||||
uint32_t mask = (len % 32 == 0) ? UINT_MAX : UINT_MAX >> (32 - (len % 32));
|
||||
size_t word = 3 - start / 32;
|
||||
size_t shift = start % 32;
|
||||
uint32_t right = src[word] >> shift;
|
||||
uint32_t left = (len + shift <= 32) ? 0 : src[word - 1] << ((32 - shift) % 32);
|
||||
return (left | right) & mask;
|
||||
}
|
||||
|
||||
#endif //_SDMMC_DEFS_H_
|
165
components/driver/include/driver/sdmmc_host.h
Normal file
165
components/driver/include/driver/sdmmc_host.h
Normal file
@ -0,0 +1,165 @@
|
||||
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// 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.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include "esp_err.h"
|
||||
#include "sdmmc_types.h"
|
||||
#include "driver/gpio.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define SDMMC_HOST_SLOT_0 0 ///< SDMMC slot 0
|
||||
#define SDMMC_HOST_SLOT_1 1 ///< SDMMC slot 1
|
||||
|
||||
/**
|
||||
* @brief Default sdmmc_host_t structure initializer for SDMMC peripheral
|
||||
*
|
||||
* Uses SDMMC peripheral, with 4-bit mode enabled, and max frequency set to 20MHz
|
||||
*/
|
||||
#define SDMMC_HOST_DEFAULT() {\
|
||||
.flags = SDMMC_HOST_FLAG_4BIT, \
|
||||
.slot = SDMMC_HOST_SLOT_1, \
|
||||
.max_freq_khz = SDMMC_FREQ_DEFAULT, \
|
||||
.io_voltage = 3.3f, \
|
||||
.init = &sdmmc_host_init, \
|
||||
.set_bus_width = &sdmmc_host_set_bus_width, \
|
||||
.set_card_clk = &sdmmc_host_set_card_clk, \
|
||||
.do_transaction = &sdmmc_host_do_transaction, \
|
||||
.deinit = &sdmmc_host_deinit, \
|
||||
}
|
||||
|
||||
/**
|
||||
* Extra configuration for SDMMC peripheral slot
|
||||
*/
|
||||
typedef struct {
|
||||
gpio_num_t gpio_cd; ///< GPIO number of card detect signal
|
||||
gpio_num_t gpio_wp; ///< GPIO number of write protect signal
|
||||
} 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
|
||||
|
||||
/**
|
||||
* Macro defining default configuration of SDMMC host slot
|
||||
*/
|
||||
#define SDMMC_SLOT_CONFIG_DEFAULT() {\
|
||||
.gpio_cd = SDMMC_SLOT_NO_CD, \
|
||||
.gpio_wp = SDMMC_SLOT_NO_WP, \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initialize SDMMC host peripheral
|
||||
*
|
||||
* @note This function is not thread safe
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK on success
|
||||
* - ESP_ERR_INVALID_STATE if sdmmc_host_init was already called
|
||||
* - ESP_ERR_NO_MEM if memory can not be allocated
|
||||
*/
|
||||
esp_err_t sdmmc_host_init();
|
||||
|
||||
/**
|
||||
* @brief Initialize given slot of SDMMC peripheral
|
||||
*
|
||||
* On the ESP32, SDMMC peripheral has two slots:
|
||||
* - Slot 0: 8-bit wide, maps to HS1_* signals in PIN MUX
|
||||
* - Slot 1: 4-bit wide, maps to HS2_* signals in PIN MUX
|
||||
*
|
||||
* Card detect and write protect signals can be routed to
|
||||
* arbitrary GPIOs using GPIO matrix.
|
||||
*
|
||||
* @note This function is not thread safe
|
||||
*
|
||||
* @param slot slot number (SDMMC_HOST_SLOT_0 or SDMMC_HOST_SLOT_1)
|
||||
* @param slot_config additional configuration for the slot
|
||||
* @return
|
||||
* - ESP_OK on success
|
||||
* - ESP_ERR_INVALID_STATE if host has not been initialized using sdmmc_host_init
|
||||
*/
|
||||
esp_err_t sdmmc_host_init_slot(int slot, const sdmmc_slot_config_t* slot_config);
|
||||
|
||||
/**
|
||||
* @brief Select bus width to be used for data transfer
|
||||
*
|
||||
* SD/MMC card must be initialized prior to this command, and a command to set
|
||||
* bus width has to be sent to the card (e.g. SD_APP_SET_BUS_WIDTH)
|
||||
*
|
||||
* @note This function is not thread safe
|
||||
*
|
||||
* @param slot slot number (SDMMC_HOST_SLOT_0 or SDMMC_HOST_SLOT_1)
|
||||
* @param width bus width (1, 4, or 8 for slot 0; 1 or 4 for slot 1)
|
||||
* @return
|
||||
* - ESP_OK on success
|
||||
* - ESP_ERR_INVALID_ARG if slot number or width is not valid
|
||||
*/
|
||||
esp_err_t sdmmc_host_set_bus_width(int slot, size_t width);
|
||||
|
||||
/**
|
||||
* @brief Set card clock frequency
|
||||
*
|
||||
* Currently only integer fractions of 40MHz clock can be used.
|
||||
* For High Speed cards, 40MHz can be used.
|
||||
* For Default Speed cards, 20MHz can be used.
|
||||
*
|
||||
* @note This function is not thread safe
|
||||
*
|
||||
* @param slot slot number (SDMMC_HOST_SLOT_0 or SDMMC_HOST_SLOT_1)
|
||||
* @param freq_khz card clock frequency, in kHz
|
||||
* @return
|
||||
* - ESP_OK on success
|
||||
* - other error codes may be returned in the future
|
||||
*/
|
||||
esp_err_t sdmmc_host_set_card_clk(int slot, uint32_t freq_khz);
|
||||
|
||||
/**
|
||||
* @brief Send command to the card and get response
|
||||
*
|
||||
* This function returns when command is sent and response is received,
|
||||
* or data is transferred, or timeout occurs.
|
||||
*
|
||||
* @note This function is not thread safe w.r.t. init/deinit functions,
|
||||
* and bus width/clock speed configuration functions. Multiple tasks
|
||||
* can call sdmmc_host_do_transaction as long as other sdmmc_host_*
|
||||
* functions are not called.
|
||||
*
|
||||
* @param slot slot number (SDMMC_HOST_SLOT_0 or SDMMC_HOST_SLOT_1)
|
||||
* @param cmdinfo pointer to structure describing command and data to transfer
|
||||
* @return
|
||||
* - ESP_OK on success
|
||||
* - ESP_ERR_TIMEOUT if response or data transfer has timed out
|
||||
* - ESP_ERR_INVALID_CRC if response or data transfer CRC check has failed
|
||||
* - ESP_ERR_INVALID_RESPONSE if the card has sent an invalid response
|
||||
*/
|
||||
esp_err_t sdmmc_host_do_transaction(int slot, sdmmc_command_t* cmdinfo);
|
||||
|
||||
/**
|
||||
* @brief Disable SDMMC host and release allocated resources
|
||||
*
|
||||
* @note This function is not thread safe
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK on success
|
||||
* - ESP_ERR_INVALID_STATE if sdmmc_host_init function has not been called
|
||||
*/
|
||||
esp_err_t sdmmc_host_deinit();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
140
components/driver/include/driver/sdmmc_types.h
Normal file
140
components/driver/include/driver/sdmmc_types.h
Normal file
@ -0,0 +1,140 @@
|
||||
/*
|
||||
* Copyright (c) 2006 Uwe Stuehler <uwe@openbsd.org>
|
||||
* Adaptations to ESP-IDF Copyright (c) 2016 Espressif Systems (Shanghai) PTE LTD
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _SDMMC_TYPES_H_
|
||||
#define _SDMMC_TYPES_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include "esp_err.h"
|
||||
|
||||
/**
|
||||
* Decoded values from SD card Card Specific Data register
|
||||
*/
|
||||
typedef struct {
|
||||
int csd_ver; /*!< CSD structure format */
|
||||
int mmc_ver; /*!< MMC version (for CID format) */
|
||||
int capacity; /*!< total number of sectors */
|
||||
int sector_size; /*!< sector size in bytes */
|
||||
int read_block_len; /*!< block length for reads */
|
||||
int card_command_class; /*!< Card Command Class for SD */
|
||||
int tr_speed; /*!< Max transfer speed */
|
||||
} sdmmc_csd_t;
|
||||
|
||||
/**
|
||||
* Decoded values from SD card Card IDentification register
|
||||
*/
|
||||
typedef struct {
|
||||
int mfg_id; /*!< manufacturer identification number */
|
||||
int oem_id; /*!< OEM/product identification number */
|
||||
char name[8]; /*!< product name (MMC v1 has the longest) */
|
||||
int revision; /*!< product revision */
|
||||
int serial; /*!< product serial number */
|
||||
int date; /*!< manufacturing date */
|
||||
} sdmmc_cid_t;
|
||||
|
||||
/**
|
||||
* Decoded values from SD Configuration Register
|
||||
*/
|
||||
typedef struct {
|
||||
int sd_spec; /*!< SD Physical layer specification version, reported by card */
|
||||
int bus_width; /*!< bus widths supported by card: BIT(0) — 1-bit bus, BIT(2) — 4-bit bus */
|
||||
} sdmmc_scr_t;
|
||||
|
||||
/**
|
||||
* SD/MMC command response buffer
|
||||
*/
|
||||
typedef uint32_t sdmmc_response_t[4];
|
||||
|
||||
/**
|
||||
* SD/MMC command information
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t opcode; /*!< SD or MMC command index */
|
||||
uint32_t arg; /*!< SD/MMC command argument */
|
||||
sdmmc_response_t response; /*!< response buffer */
|
||||
void* data; /*!< buffer to send or read into */
|
||||
size_t datalen; /*!< length of data buffer */
|
||||
size_t blklen; /*!< block length */
|
||||
int flags; /*!< see below */
|
||||
#define SCF_ITSDONE 0x0001 /*!< command is complete */
|
||||
#define SCF_CMD(flags) ((flags) & 0x00f0)
|
||||
#define SCF_CMD_AC 0x0000
|
||||
#define SCF_CMD_ADTC 0x0010
|
||||
#define SCF_CMD_BC 0x0020
|
||||
#define SCF_CMD_BCR 0x0030
|
||||
#define SCF_CMD_READ 0x0040 /*!< read command (data expected) */
|
||||
#define SCF_RSP_BSY 0x0100
|
||||
#define SCF_RSP_136 0x0200
|
||||
#define SCF_RSP_CRC 0x0400
|
||||
#define SCF_RSP_IDX 0x0800
|
||||
#define SCF_RSP_PRESENT 0x1000
|
||||
/* response types */
|
||||
#define SCF_RSP_R0 0 /*!< none */
|
||||
#define SCF_RSP_R1 (SCF_RSP_PRESENT|SCF_RSP_CRC|SCF_RSP_IDX)
|
||||
#define SCF_RSP_R1B (SCF_RSP_PRESENT|SCF_RSP_CRC|SCF_RSP_IDX|SCF_RSP_BSY)
|
||||
#define SCF_RSP_R2 (SCF_RSP_PRESENT|SCF_RSP_CRC|SCF_RSP_136)
|
||||
#define SCF_RSP_R3 (SCF_RSP_PRESENT)
|
||||
#define SCF_RSP_R4 (SCF_RSP_PRESENT)
|
||||
#define SCF_RSP_R5 (SCF_RSP_PRESENT|SCF_RSP_CRC|SCF_RSP_IDX)
|
||||
#define SCF_RSP_R5B (SCF_RSP_PRESENT|SCF_RSP_CRC|SCF_RSP_IDX|SCF_RSP_BSY)
|
||||
#define SCF_RSP_R6 (SCF_RSP_PRESENT|SCF_RSP_CRC|SCF_RSP_IDX)
|
||||
#define SCF_RSP_R7 (SCF_RSP_PRESENT|SCF_RSP_CRC|SCF_RSP_IDX)
|
||||
esp_err_t error; /*!< error returned from transfer */
|
||||
} sdmmc_command_t;
|
||||
|
||||
/**
|
||||
* SD/MMC Host description
|
||||
*
|
||||
* This structure defines properties of SD/MMC host and functions
|
||||
* of SD/MMC host which can be used by upper layers.
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t flags; /*!< flags defining host properties */
|
||||
#define SDMMC_HOST_FLAG_1BIT BIT(0) /*!< host supports 1-line SD and MMC protocol */
|
||||
#define SDMMC_HOST_FLAG_4BIT BIT(1) /*!< host supports 4-line SD and MMC protocol */
|
||||
#define SDMMC_HOST_FLAG_8BIT BIT(2) /*!< host supports 8-line MMC protocol */
|
||||
#define SDMMC_HOST_FLAG_SPI BIT(3) /*!< host supports SPI protocol */
|
||||
int slot; /*!< slot number, to be passed to host functions */
|
||||
int max_freq_khz; /*!< max frequency supported by the host */
|
||||
#define SDMMC_FREQ_DEFAULT 20000 /*!< SD/MMC Default speed (limited by clock divider) */
|
||||
#define SDMMC_FREQ_HIGHSPEED 40000 /*!< SD High speed (limited by clock divider) */
|
||||
#define SDMMC_FREQ_PROBING 4000 /*!< SD/MMC probing speed */
|
||||
float io_voltage; /*!< I/O voltage used by the controller (voltage switching is not supported) */
|
||||
esp_err_t (*init)(void); /*!< Host function to initialize the driver */
|
||||
esp_err_t (*set_bus_width)(int slot, size_t width); /*!< host function to set bus width */
|
||||
esp_err_t (*set_card_clk)(int slot, uint32_t freq_khz); /*!< host function to set card clock frequency */
|
||||
esp_err_t (*do_transaction)(int slot, sdmmc_command_t* cmdinfo); /*!< host function to do a transaction */
|
||||
esp_err_t (*deinit)(void); /*!< host function to deinitialize the driver */
|
||||
} sdmmc_host_t;
|
||||
|
||||
/**
|
||||
* SD/MMC card information structure
|
||||
*/
|
||||
typedef struct {
|
||||
sdmmc_host_t host; /*!< Host with which the card is associated */
|
||||
uint32_t ocr; /*!< OCR (Operation Conditions Register) value */
|
||||
sdmmc_cid_t cid; /*!< decoded CID (Card IDentification) register value */
|
||||
sdmmc_csd_t csd; /*!< decoded CSD (Card-Specific Data) register value */
|
||||
sdmmc_scr_t scr; /*!< decoded SCR (SD card Configuration Register) value */
|
||||
uint16_t rca; /*!< RCA (Relative Card Address) */
|
||||
} sdmmc_card_t;
|
||||
|
||||
|
||||
|
||||
|
||||
#endif // _SDMMC_TYPES_H_
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user