diff --git a/README.md b/README.md index a710c0f3..b437314b 100644 --- a/README.md +++ b/README.md @@ -53,3 +53,21 @@ them to the [support forum](https://forum.arduino.cc/index.php?board=103). > "How do I use this library?" > "I can't get this example sketch to work. What am I doing wrong?" + +# Enable debug interface on Serail1 + +* Default disable the debug interface. + +If you want to enable debug trace on Serial1 to debug corelib, follow these instructions. + +1. Shut down the IDE +2. Go to Arduino15 directory + * Windows: `C:\Users\\AppData\Roaming\Arduino15` + * OS X: `~/Library/Arduino15` + * Linux: `~/.arduino15` +3. Modify the platform.txt + * Find `compiler.c.flags` and add `-DCONFIGURE_DEBUG_CORELIB_ENABLED` at the end of this line + * Find `compiler.cpp.flags` and add `-DCONFIGURE_DEBUG_CORELIB_ENABLED` at the end of this line +4. Initial Serial1 in your sketch + * Add `Serial1.begin(115200);` in your `setup()` +5. Adjust the output level at log_init function in log.c diff --git a/cores/arduino/i2c.c b/cores/arduino/i2c.c index 6b1b0aff..34bf3ecc 100644 --- a/cores/arduino/i2c.c +++ b/cores/arduino/i2c.c @@ -19,208 +19,242 @@ * */ -#include #include "i2c.h" #include "variant.h" #define TIMEOUT_MS 16 -static volatile uint8_t i2c_tx_complete; -static volatile uint8_t i2c_rx_complete; -static volatile uint8_t i2c_err_detect; -static volatile uint32_t i2c_err_source; +static volatile uint8_t i2c_tx_complete[NUM_SS_I2C]; +static volatile uint8_t i2c_rx_complete[NUM_SS_I2C]; +static volatile uint8_t i2c_err_detect[NUM_SS_I2C]; +static volatile uint32_t i2c_err_source[NUM_SS_I2C]; -static volatile uint8_t i2c_slave = 0; +static volatile uint8_t i2c_slave[NUM_SS_I2C]; -static void ss_i2c_rx(uint32_t dev_id) +static void ss_i2c_0_rx(uint32_t dev_id) { - i2c_rx_complete = 1; + i2c_rx_complete[I2C_SENSING_0] = 1; } -static void ss_i2c_tx(uint32_t dev_id) +static void ss_i2c_1_rx(uint32_t dev_id) { - i2c_tx_complete = 1; + i2c_rx_complete[I2C_SENSING_1] = 1; } -static void ss_i2c_err(uint32_t dev_id) +static void ss_i2c_0_tx(uint32_t dev_id) { - i2c_err_detect = 1; - i2c_err_source = dev_id; + i2c_tx_complete[I2C_SENSING_0] = 1; } -static int wait_rx_or_err() +static void ss_i2c_1_tx(uint32_t dev_id) { - uint64_t timeout = TIMEOUT_MS * 200; - while(timeout--) { - if (i2c_err_detect) { - if (i2c_err_source & I2C_ABRT_7B_ADDR_NOACK ) - { - return I2C_ERROR_ADDRESS_NOACK; // NACK on transmit of address - } - else if (i2c_err_source & I2C_ABRT_TXDATA_NOACK ) - { - return I2C_ERROR_DATA_NOACK; // NACK on transmit of data - } - else - { - return I2C_ERROR_OTHER; // other error - } - } - if (i2c_rx_complete) { - return I2C_OK; - } - delayMicroseconds(10); - } - - return I2C_TIMEOUT; + i2c_tx_complete[I2C_SENSING_1] = 1; } -static int wait_tx_or_err() +static void ss_i2c_0_err(uint32_t dev_id) { - uint64_t timeout = TIMEOUT_MS * 200; - while(timeout--) { - if (i2c_err_detect) { - if (i2c_err_source & I2C_ABRT_7B_ADDR_NOACK ) - { - return I2C_ERROR_ADDRESS_NOACK; // NACK on transmit of address - } - else if (i2c_err_source & I2C_ABRT_TXDATA_NOACK ) - { - return I2C_ERROR_DATA_NOACK; // NACK on transmit of data - } - else - { - return I2C_ERROR_OTHER; // other error - } - } - if (i2c_tx_complete) { - return I2C_OK; - } - delayMicroseconds(10); - } - return I2C_TIMEOUT; + i2c_err_detect[I2C_SENSING_0] = 1; + i2c_err_source[I2C_SENSING_0] = dev_id; } -static int wait_dev_ready(I2C_CONTROLLER controller_id, bool no_stop){ - uint64_t timeout = TIMEOUT_MS * 200; - int ret = 0; - while(timeout--) { - ret = ss_i2c_status(controller_id, no_stop); - if (ret == I2C_OK) { - return I2C_OK; - } - else if (ret == I2C_BUSY) { - delayMicroseconds(10); - } - else - { - return I2C_TIMEOUT - ret; - } - } - return I2C_TIMEOUT - ret; +static void ss_i2c_1_err(uint32_t dev_id) +{ + i2c_err_detect[I2C_SENSING_1] = 1; + i2c_err_source[I2C_SENSING_1] = dev_id; } - -int i2c_openadapter(void) +static int wait_rx_or_err(I2C_CONTROLLER controller_id) { - int ret; - - SET_PIN_MODE(24, I2C_MUX_MODE); // Rxd SOC PIN (Arduino header pin 18) - SET_PIN_MODE(25, I2C_MUX_MODE); // Txd SOC PIN (Arduino header pin 19) - - SET_PIN_PULLUP(24, 1); - SET_PIN_PULLUP(25, 1); - - i2c_cfg_data_t i2c_cfg; - memset(&i2c_cfg, 0, sizeof(i2c_cfg_data_t)); - - i2c_cfg.speed = I2C_SLOW; - i2c_cfg.addressing_mode = I2C_7_Bit; - i2c_cfg.mode_type = I2C_MASTER; - i2c_cfg.cb_tx = ss_i2c_tx; - i2c_cfg.cb_rx = ss_i2c_rx; - i2c_cfg.cb_err = ss_i2c_err; - - i2c_tx_complete = 0; - i2c_rx_complete = 0; - i2c_err_detect = 0; - i2c_err_source = 0; - - ss_i2c_set_config(I2C_SENSING_0, &i2c_cfg); - ss_i2c_clock_enable(I2C_SENSING_0); - ret = wait_dev_ready(I2C_SENSING_0, false); - - return ret; + uint64_t timeout = TIMEOUT_MS * 200; + + while (timeout--) { + if (i2c_err_detect[controller_id]) { + if (i2c_err_source[controller_id] & I2C_ABRT_7B_ADDR_NOACK) { + return I2C_ERROR_ADDRESS_NOACK; // NACK on transmit of address + } else if (i2c_err_source[controller_id] & I2C_ABRT_TXDATA_NOACK) { + return I2C_ERROR_DATA_NOACK; // NACK on transmit of data + } else { + return I2C_ERROR_OTHER; // other error + } + } + if (i2c_rx_complete[controller_id]) { + return I2C_OK; + } + delayMicroseconds(10); + } + + return I2C_TIMEOUT; } -int i2c_openadapter_speed(int i2c_speed) +static int wait_tx_or_err(I2C_CONTROLLER controller_id) { - int ret; - - SET_PIN_MODE(24, I2C_MUX_MODE); // Rxd SOC PIN (Arduino header pin 18) - SET_PIN_MODE(25, I2C_MUX_MODE); // Txd SOC PIN (Arduino header pin 19) - - SET_PIN_PULLUP(24, 1); - SET_PIN_PULLUP(25, 1); - - i2c_cfg_data_t i2c_cfg; - memset(&i2c_cfg, 0, sizeof(i2c_cfg_data_t)); - - i2c_cfg.speed = i2c_speed; - i2c_cfg.addressing_mode = I2C_7_Bit; - i2c_cfg.mode_type = I2C_MASTER; - i2c_cfg.cb_tx = ss_i2c_tx; - i2c_cfg.cb_rx = ss_i2c_rx; - i2c_cfg.cb_err = ss_i2c_err; - - i2c_tx_complete = 0; - i2c_rx_complete = 0; - i2c_err_detect = 0; + uint64_t timeout = TIMEOUT_MS * 200; + + while (timeout--) { + if (i2c_err_detect[controller_id]) { + if (i2c_err_source[controller_id] & I2C_ABRT_7B_ADDR_NOACK) { + return I2C_ERROR_ADDRESS_NOACK; // NACK on transmit of address + } else if (i2c_err_source[controller_id] & I2C_ABRT_TXDATA_NOACK) { + return I2C_ERROR_DATA_NOACK; // NACK on transmit of data + } else { + return I2C_ERROR_OTHER; // other error + } + } + if (i2c_tx_complete[controller_id]) { + return I2C_OK; + } + delayMicroseconds(10); + } + return I2C_TIMEOUT; +} - ss_i2c_set_config(I2C_SENSING_0, &i2c_cfg); - ss_i2c_clock_enable(I2C_SENSING_0); - ret = wait_dev_ready(I2C_SENSING_0, false); +static int wait_dev_ready(I2C_CONTROLLER controller_id, bool no_stop) +{ + uint64_t timeout = TIMEOUT_MS * 200; + int ret = 0; + + while (timeout--) { + ret = ss_i2c_status(controller_id, no_stop); + if (ret == I2C_OK) { + return I2C_OK; + } else if (ret == I2C_BUSY) { + delayMicroseconds(10); + } else { + return I2C_TIMEOUT - ret; + } + } + return I2C_TIMEOUT - ret; +} - return ret; +int i2c_openadapter(I2C_CONTROLLER controller_id) +{ + int ret; + + i2c_cfg_data_t i2c_cfg; + memset(&i2c_cfg, 0, sizeof(i2c_cfg_data_t)); + + i2c_cfg.speed = I2C_SLOW; + i2c_cfg.addressing_mode = I2C_7_Bit; + i2c_cfg.mode_type = I2C_MASTER; + + if (controller_id == I2C_SENSING_0) { + SET_PIN_MODE(24, I2C_MUX_MODE); // SOC PIN (Arduino header pin 18) + SET_PIN_MODE(25, I2C_MUX_MODE); // Txd SOC PIN (Arduino header pin 19) + + SET_PIN_PULLUP(24, 1); + SET_PIN_PULLUP(25, 1); + i2c_cfg.cb_tx = ss_i2c_0_tx; + i2c_cfg.cb_rx = ss_i2c_0_rx; + i2c_cfg.cb_err = ss_i2c_0_err; + } else if (controller_id == I2C_SENSING_1) { + SET_PIN_MODE(26, I2C_MUX_MODE); // Rxd SOC PIN (Arduino header pin 18) + SET_PIN_MODE(27, I2C_MUX_MODE); // Txd SOC PIN (Arduino header pin 19) + + SET_PIN_PULLUP(26, 1); + SET_PIN_PULLUP(27, 1); + i2c_cfg.cb_tx = ss_i2c_1_tx; + i2c_cfg.cb_rx = ss_i2c_1_rx; + i2c_cfg.cb_err = ss_i2c_1_err; + } else { + return I2C_ERROR; + } + + i2c_tx_complete[controller_id] = 0; + i2c_rx_complete[controller_id] = 0; + i2c_err_detect[controller_id] = 0; + i2c_err_source[controller_id] = 0; + + ss_i2c_set_config(controller_id, &i2c_cfg); + ss_i2c_clock_enable(controller_id); + ret = wait_dev_ready(controller_id, false); + + return ret; } +int i2c_openadapter_speed(I2C_CONTROLLER controller_id, int i2c_speed) +{ + int ret; + i2c_cfg_data_t i2c_cfg; + memset(&i2c_cfg, 0, sizeof(i2c_cfg_data_t)); + + i2c_cfg.speed = i2c_speed; + i2c_cfg.addressing_mode = I2C_7_Bit; + i2c_cfg.mode_type = I2C_MASTER; + + if (controller_id == I2C_SENSING_0) { + SET_PIN_MODE(24, I2C_MUX_MODE); // SOC PIN (Arduino header pin 18) + SET_PIN_MODE(25, I2C_MUX_MODE); // Txd SOC PIN (Arduino header pin 19) + + SET_PIN_PULLUP(24, 1); + SET_PIN_PULLUP(25, 1); + i2c_cfg.cb_tx = ss_i2c_0_tx; + i2c_cfg.cb_rx = ss_i2c_0_rx; + i2c_cfg.cb_err = ss_i2c_0_err; + } else if (controller_id == I2C_SENSING_1) { + SET_PIN_MODE(26, I2C_MUX_MODE); // Rxd SOC PIN (Arduino header pin 18) + SET_PIN_MODE(27, I2C_MUX_MODE); // Txd SOC PIN (Arduino header pin 19) + + SET_PIN_PULLUP(26, 1); + SET_PIN_PULLUP(27, 1); + i2c_cfg.cb_tx = ss_i2c_1_tx; + i2c_cfg.cb_rx = ss_i2c_1_rx; + i2c_cfg.cb_err = ss_i2c_1_err; + } else { + return I2C_ERROR; + } + + i2c_tx_complete[controller_id] = 0; + i2c_rx_complete[controller_id] = 0; + i2c_err_detect[controller_id] = 0; + i2c_err_source[controller_id] = 0; + + ss_i2c_set_config(controller_id, &i2c_cfg); + ss_i2c_clock_enable(controller_id); + ret = wait_dev_ready(controller_id, false); + + return ret; +} -void i2c_setslave(uint8_t addr) +void i2c_setslave(I2C_CONTROLLER controller_id, uint8_t addr) { - i2c_slave = addr; - return; + i2c_slave[controller_id] = addr; + return; } -int i2c_writebytes(uint8_t *bytes, uint8_t length, bool no_stop) +int i2c_writebytes(I2C_CONTROLLER controller_id, uint8_t *bytes, uint8_t length, + bool no_stop) { - int ret; - - i2c_tx_complete = 0; - i2c_err_detect = 0; - i2c_err_source = 0; - ss_i2c_transfer(I2C_SENSING_0, bytes, length, 0, 0, i2c_slave, no_stop); - ret = wait_tx_or_err(); - if (ret) - return ret; - ret = wait_dev_ready(I2C_SENSING_0, no_stop); - if (ret) - return ret; - return length; + int ret; + + i2c_tx_complete[controller_id] = 0; + i2c_err_detect[controller_id] = 0; + i2c_err_source[controller_id] = 0; + ss_i2c_transfer(controller_id, bytes, length, 0, 0, + i2c_slave[controller_id], no_stop); + ret = wait_tx_or_err(controller_id); + if (ret) + return ret; + ret = wait_dev_ready(controller_id, no_stop); + if (ret) + return ret; + return length; } -int i2c_readbytes(uint8_t *buf, int length, bool no_stop) +int i2c_readbytes(I2C_CONTROLLER controller_id, uint8_t *buf, int length, + bool no_stop) { - int ret; - - i2c_rx_complete = 0; - i2c_err_detect = 0; - i2c_err_source = 0; - ss_i2c_transfer(I2C_SENSING_0, 0, 0, buf, length, i2c_slave, no_stop); - ret = wait_rx_or_err(); - if (ret) - return ret; - ret = wait_dev_ready(I2C_SENSING_0, no_stop); - if (ret) - return ret; - return length; + int ret; + + i2c_rx_complete[controller_id] = 0; + i2c_err_detect[controller_id] = 0; + i2c_err_source[controller_id] = 0; + ss_i2c_transfer(controller_id, 0, 0, buf, length, i2c_slave[controller_id], + no_stop); + ret = wait_rx_or_err(controller_id); + if (ret) + return ret; + ret = wait_dev_ready(controller_id, no_stop); + if (ret) + return ret; + return length; } diff --git a/cores/arduino/i2c.h b/cores/arduino/i2c.h index f73906fa..870cb5c8 100644 --- a/cores/arduino/i2c.h +++ b/cores/arduino/i2c.h @@ -23,13 +23,16 @@ #define i2c_h #include +#include +#include "ss_i2c_iface.h" + #ifdef __cplusplus extern "C"{ #endif #define I2C_OK 0 #define I2C_TIMEOUT -10 -#define I2C_ERROR -11 +#define I2C_ERROR -20 /* Qi, 2016. */ #define I2C_ERROR_ADDRESS_NOACK (-2) #define I2C_ERROR_DATA_NOACK (-3) #define I2C_ERROR_OTHER (-4) @@ -37,11 +40,11 @@ extern "C"{ #define I2C_ABRT_7B_ADDR_NOACK (1 << 0) #define I2C_ABRT_TXDATA_NOACK (1 << 3) -int i2c_openadapter(void); -int i2c_openadapter_speed(int); -void i2c_setslave(uint8_t addr); -int i2c_writebytes(uint8_t *bytes, uint8_t length, bool no_stop); -int i2c_readbytes(uint8_t *buf, int length, bool no_stop); +int i2c_openadapter(I2C_CONTROLLER controller_id); +int i2c_openadapter_speed(I2C_CONTROLLER controller_id, int i2c_speed); +void i2c_setslave(I2C_CONTROLLER controller_id, uint8_t addr); +int i2c_writebytes(I2C_CONTROLLER controller_id, uint8_t *bytes, uint8_t length, bool no_stop); +int i2c_readbytes(I2C_CONTROLLER controller_id, uint8_t *buf, int length, bool no_stop); #ifdef __cplusplus } diff --git a/system/libarc32_arduino101/framework/src/nordic_interface.h b/cores/arduino/printk.cpp similarity index 79% rename from system/libarc32_arduino101/framework/src/nordic_interface.h rename to cores/arduino/printk.cpp index 1b187b16..babfc0ed 100644 --- a/system/libarc32_arduino101/framework/src/nordic_interface.h +++ b/cores/arduino/printk.cpp @@ -28,13 +28,25 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#ifndef NORDIC_INTERFACE_H -#define NORDIC_INTERFACE_H -#include "infra/ipc_uart.h" +#include +#include +#include "UARTClass.h" -void uart_ipc_message_cback(uint8_t cpu_id, int channel, int len, void * p_data); -int send_message_ipc_uart(struct message * message); -void free_message_ipc_uart(struct message * message); -int nordic_interface_init(T_QUEUE queue); +extern "C" void printk(const char *fmt, va_list args); +extern UARTClass Serial1; +#define PRINTK_BUFSIZ 256 + +void printk(const char *fmt, va_list args) +{ +#ifdef CONFIGURE_DEBUG_CORELIB_ENABLED + int len = 0; + + char tmp[PRINTK_BUFSIZ]; + + len = vsnprintf(tmp, PRINTK_BUFSIZ, fmt, args); + + tmp[len] = '\0'; + Serial1.println(tmp); +#endif +} -#endif // NORDIC_INTERFACE_H diff --git a/cores/arduino/soc_i2c.c b/cores/arduino/soc_i2c.c new file mode 100644 index 00000000..50ca7b48 --- /dev/null +++ b/cores/arduino/soc_i2c.c @@ -0,0 +1,331 @@ +/* + * soc_i2c.c - i2c library layer + * + * Copyright (C) 2015, 2016 Intel Corporation + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include +#include "intel_qrk_i2c.h" +#include "variant.h" +#include "soc_i2c.h" +#include "i2c.h" + +#define TIMEOUT_MS 16 + +static volatile uint8_t soc_i2c_master_tx_complete[NUM_SOC_I2C]; +static volatile uint8_t soc_i2c_master_rx_complete[NUM_SOC_I2C]; +static volatile uint8_t soc_i2c_err_detect[NUM_SOC_I2C]; +static volatile uint32_t soc_i2c_err_source[NUM_SOC_I2C]; + +static volatile uint32_t soc_i2c_slave_address[NUM_SOC_I2C] = {0, 0}; + +static void soc_i2c0_master_rx_callback(uint32_t dev_id) +{ + soc_i2c_master_rx_complete[SOC_I2C_0] = 1; +} + +static void soc_i2c1_master_rx_callback(uint32_t dev_id) +{ + soc_i2c_master_rx_complete[SOC_I2C_1] = 1; +} + +static void soc_i2c0_master_tx_callback(uint32_t dev_id) +{ + soc_i2c_master_tx_complete[SOC_I2C_0] = 1; +} + +static void soc_i2c1_master_tx_callback(uint32_t dev_id) +{ + soc_i2c_master_tx_complete[SOC_I2C_1] = 1; +} + +static void soc_i2c0_err_callback(uint32_t dev_id) +{ + soc_i2c_err_detect[SOC_I2C_0] = 1; + soc_i2c_err_source[SOC_I2C_0] = dev_id; +} + +static void soc_i2c1_err_callback(uint32_t dev_id) +{ + soc_i2c_err_detect[SOC_I2C_1] = 1; + soc_i2c_err_source[SOC_I2C_1] = dev_id; +} + +static void (*soc_i2c0_slave_rx_user_callback)(int, void *) = NULL; +static void *soc_i2c0_slave_rx_user_cb_data_ptr = NULL; + +static void (*soc_i2c1_slave_rx_user_callback)(int, void *) = NULL; +static void *soc_i2c1_slave_rx_user_cb_data_ptr = NULL; + +static void (*soc_i2c0_slave_tx_user_callback)(void *) = NULL; +static void *soc_i2c0_slave_tx_user_cb_data_ptr = NULL; + +static void (*soc_i2c1_slave_tx_user_callback)(void *) = NULL; +static void *soc_i2c1_slave_tx_user_cb_data_ptr = NULL; + +static void soc_i2c0_slave_rx_callback(uint32_t bytes) +{ + if (soc_i2c0_slave_rx_user_callback) { + soc_i2c0_slave_rx_user_callback((int)bytes, soc_i2c0_slave_rx_user_cb_data_ptr); + } +} + +static void soc_i2c1_slave_rx_callback(uint32_t bytes) +{ + if (soc_i2c1_slave_rx_user_callback) { + soc_i2c1_slave_rx_user_callback((int)bytes, soc_i2c1_slave_rx_user_cb_data_ptr); + } +} + +static void soc_i2c0_slave_tx_callback(uint32_t bytes) +{ + if (soc_i2c0_slave_tx_user_callback) { + soc_i2c0_slave_tx_user_callback(soc_i2c0_slave_tx_user_cb_data_ptr); + } +} + +static void soc_i2c1_slave_tx_callback(uint32_t bytes) +{ + if (soc_i2c1_slave_tx_user_callback) { + soc_i2c1_slave_tx_user_callback(soc_i2c1_slave_tx_user_cb_data_ptr); + } +} + +void soc_i2c_slave_set_rx_user_callback(SOC_I2C_CONTROLLER controller_id, void (*onReceiveCallback)(int, void *), void *callerDataPtr) +{ + if (controller_id == SOC_I2C_0) { + soc_i2c0_slave_rx_user_callback = onReceiveCallback; + soc_i2c0_slave_rx_user_cb_data_ptr = callerDataPtr; + } else { + soc_i2c1_slave_rx_user_callback = onReceiveCallback; + soc_i2c1_slave_rx_user_cb_data_ptr = callerDataPtr; + } +} + +void soc_i2c_slave_set_tx_user_callback(SOC_I2C_CONTROLLER controller_id, void (*onRequestCallback)(void *), void *callerDataPtr) +{ + if (controller_id == SOC_I2C_0) { + soc_i2c0_slave_tx_user_callback = onRequestCallback; + soc_i2c0_slave_tx_user_cb_data_ptr = callerDataPtr; + } else { + soc_i2c1_slave_tx_user_callback = onRequestCallback; + soc_i2c1_slave_tx_user_cb_data_ptr = callerDataPtr; + } +} + +static int soc_i2c_master_wait_rx_or_err(SOC_I2C_CONTROLLER controller_id) +{ + uint64_t timeout = TIMEOUT_MS * 200; + while (timeout--) { + if (soc_i2c_err_detect[controller_id]) { + if (soc_i2c_err_source[controller_id] & + (I2C_ABRT_7B_ADDR_NOACK | I2C_ABRT_10ADDR1_NOACK | I2C_ABRT_10ADDR2_NOACK)) { + return I2C_ERROR_ADDRESS_NOACK; // NACK on transmit of address + } + else if (soc_i2c_err_source[controller_id] & I2C_ABRT_TXDATA_NOACK) { + return I2C_ERROR_DATA_NOACK; // NACK on transmit of data + } else { + return I2C_ERROR_OTHER; // other error + } + } + if (soc_i2c_master_rx_complete[controller_id]) { + return I2C_OK; + } + delayMicroseconds(10); + } + return I2C_TIMEOUT; +} + +static int soc_i2c_master_wait_tx_or_err(SOC_I2C_CONTROLLER controller_id) +{ + uint64_t timeout = TIMEOUT_MS * 200; + while (timeout--) { + if (soc_i2c_err_detect[controller_id]) { + if (soc_i2c_err_source[controller_id] & + (I2C_ABRT_7B_ADDR_NOACK | I2C_ABRT_10ADDR1_NOACK | I2C_ABRT_10ADDR2_NOACK)) { + return I2C_ERROR_ADDRESS_NOACK; // NACK on transmit of address + } + else if (soc_i2c_err_source[controller_id] & I2C_ABRT_TXDATA_NOACK) { + return I2C_ERROR_DATA_NOACK; // NACK on transmit of data + } else { + return I2C_ERROR_OTHER; // other error + } + } + if (soc_i2c_master_tx_complete[controller_id]) { + return I2C_OK; + } + delayMicroseconds(10); + } + return I2C_TIMEOUT; +} + +static int soc_i2c_wait_dev_ready(SOC_I2C_CONTROLLER controller_id, + bool no_stop) +{ + uint64_t timeout = TIMEOUT_MS * 200; + int ret = 0; + while (timeout--) { + ret = soc_i2c_status(controller_id, no_stop); + if (ret == I2C_OK) { + return I2C_OK; + } + if (ret == I2C_BUSY) { + delayMicroseconds(10); + } + } + return I2C_TIMEOUT - ret; +} + +int soc_i2c_open_adapter(SOC_I2C_CONTROLLER controller_id, uint32_t address, int i2c_speed, int i2c_addr_mode) +{ + int ret = 0; + + if (controller_id == SOC_I2C_0) { + SET_PIN_MODE(20, I2C_MUX_MODE); + SET_PIN_MODE(21, I2C_MUX_MODE); + + SET_PIN_PULLUP(20, 1); + SET_PIN_PULLUP(21, 1); + } else { + SET_PIN_MODE(22, I2C_MUX_MODE); + SET_PIN_MODE(23, I2C_MUX_MODE); + + SET_PIN_PULLUP(22, 1); + SET_PIN_PULLUP(23, 1); + } + + i2c_cfg_data_t i2c_cfg; + memset(&i2c_cfg, 0, sizeof(i2c_cfg_data_t)); + + i2c_cfg.speed = i2c_speed; + i2c_cfg.addressing_mode = i2c_addr_mode; + if (address) { + i2c_cfg.mode_type = I2C_SLAVE; + if (controller_id == SOC_I2C_0) { + i2c_cfg.cb_err = soc_i2c0_err_callback; + i2c_cfg.cb_rx = soc_i2c0_slave_rx_callback; + i2c_cfg.cb_tx = soc_i2c0_slave_tx_callback; + } else { + i2c_cfg.cb_err = soc_i2c1_err_callback; + i2c_cfg.cb_rx = soc_i2c1_slave_rx_callback; + i2c_cfg.cb_tx = soc_i2c1_slave_tx_callback; + } + } else { + i2c_cfg.mode_type = I2C_MASTER; + + if (controller_id == SOC_I2C_0) { + i2c_cfg.cb_tx = soc_i2c0_master_tx_callback; + i2c_cfg.cb_rx = soc_i2c0_master_rx_callback; + i2c_cfg.cb_err = soc_i2c0_err_callback; + } else { + i2c_cfg.cb_tx = soc_i2c1_master_tx_callback; + i2c_cfg.cb_rx = soc_i2c1_master_rx_callback; + i2c_cfg.cb_err = soc_i2c1_err_callback; + } + soc_i2c_master_tx_complete[controller_id] = 0; + soc_i2c_master_rx_complete[controller_id] = 0; + } + i2c_cfg.slave_adr = address; + soc_i2c_err_detect[controller_id] = 0; + soc_i2c_err_source[controller_id] = 0; + + soc_i2c_set_config(controller_id, &i2c_cfg); + soc_i2c_clock_enable(controller_id); + + ret = soc_i2c_wait_dev_ready(controller_id, false); + + return ret; +} + +void soc_i2c_close_adapter(SOC_I2C_CONTROLLER controller_id) +{ + soc_i2c_deconfig(controller_id); + soc_i2c_clock_disable(controller_id); + + if (controller_id == SOC_I2C_0) { + SET_PIN_MODE(20, GPIO_MUX_MODE); + SET_PIN_MODE(21, GPIO_MUX_MODE); + } else { + SET_PIN_MODE(22, GPIO_MUX_MODE); + SET_PIN_MODE(23, GPIO_MUX_MODE); + } + + return; +} + +void soc_i2c_set_speed(SOC_I2C_CONTROLLER controller_id, uint32_t speed) +{ + soc_i2c_set_transfer_speed(controller_id, speed); +} + +void soc_i2c_set_address_mode(SOC_I2C_CONTROLLER controller_id, uint32_t mode) +{ + soc_i2c_set_transfer_mode(controller_id, mode); +} + +void soc_i2c_master_set_slave_address(SOC_I2C_CONTROLLER controller_id, uint32_t addr) +{ + soc_i2c_slave_address[controller_id] = addr; + return; +} + +void soc_i2c_slave_set_rx_user_buffer(SOC_I2C_CONTROLLER controller_id, uint8_t *buffer, uint8_t length) +{ + soc_i2c_slave_enable_rx(controller_id, buffer, length); +} + +void soc_i2c_slave_set_tx_user_buffer(SOC_I2C_CONTROLLER controller_id, uint8_t *buffer, uint8_t length) +{ + soc_i2c_slave_enable_tx(controller_id, buffer, length); +} + +int soc_i2c_master_witebytes(SOC_I2C_CONTROLLER controller_id, uint8_t *buf, uint8_t length, bool no_stop) +{ + int ret; + + soc_i2c_master_tx_complete[controller_id] = 0; + soc_i2c_err_detect[controller_id] = 0; + soc_i2c_err_source[controller_id] = 0; + soc_i2c_master_transfer(controller_id, buf, length, 0, 0, + soc_i2c_slave_address[controller_id], no_stop); + ret = soc_i2c_master_wait_tx_or_err(controller_id); + if (ret) + return ret; + ret = soc_i2c_wait_dev_ready(controller_id, no_stop); + if (ret) + return ret; + return length; +} + +int soc_i2c_master_readbytes(SOC_I2C_CONTROLLER controller_id, uint8_t *buf, int length, bool no_stop) +{ + int ret; + + soc_i2c_master_rx_complete[controller_id] = 0; + soc_i2c_err_detect[controller_id] = 0; + soc_i2c_err_source[controller_id] = 0; + soc_i2c_master_transfer(controller_id, 0, 0, buf, length, + soc_i2c_slave_address[controller_id], no_stop); + ret = soc_i2c_master_wait_rx_or_err(controller_id); + if (ret) + return ret; + ret = soc_i2c_wait_dev_ready(controller_id, no_stop); + if (ret) + return ret; + return length; +} diff --git a/cores/arduino/soc_i2c.h b/cores/arduino/soc_i2c.h new file mode 100644 index 00000000..989f9d1a --- /dev/null +++ b/cores/arduino/soc_i2c.h @@ -0,0 +1,51 @@ +/* + * soc_i2c.h + * + * Copyright (c) 2016 Intel Corporation + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General + * Public License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307 USA + */ + +#ifndef soc_i2c_h_ +#define soc_i2c_h_ + +#include +#include +#include "intel_qrk_i2c.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define I2C_ABRT_10ADDR1_NOACK (1 << 1) +#define I2C_ABRT_10ADDR2_NOACK (1 << 2) + +int soc_i2c_open_adapter(SOC_I2C_CONTROLLER controller_id, uint32_t address, int i2c_speed, int i2c_addr_mode); +void soc_i2c_close_adapter(SOC_I2C_CONTROLLER controller_id); +void soc_i2c_set_speed(SOC_I2C_CONTROLLER controller_id, uint32_t speed); +void soc_i2c_set_address_mode(SOC_I2C_CONTROLLER controller_id, uint32_t mode); +void soc_i2c_master_set_slave_address(SOC_I2C_CONTROLLER controller_id, uint32_t addr); +int soc_i2c_master_witebytes(SOC_I2C_CONTROLLER controller_id, uint8_t *bytes, uint8_t length, bool no_stop); +int soc_i2c_master_readbytes(SOC_I2C_CONTROLLER controller_id, uint8_t *buf, int length, bool no_stop); + void soc_i2c_slave_set_rx_user_callback(SOC_I2C_CONTROLLER controller_id, void (*onReceiveCallback)(int, void *), void *callerDataPtr); +void soc_i2c_slave_set_tx_user_callback(SOC_I2C_CONTROLLER controller_id, void (*onRequestCallback)(void *), void *callerDataPtr); +void soc_i2c_slave_set_rx_user_buffer(SOC_I2C_CONTROLLER controller_id, uint8_t *buffer, uint8_t length); +void soc_i2c_slave_set_tx_user_buffer(SOC_I2C_CONTROLLER controller_id, uint8_t *buffer, uint8_t length); + +#ifdef __cplusplus +} +#endif +#endif /* soc_i2c_h */ diff --git a/libraries/CurieBLE/examples/BatteryAdvChange/BatteryAdvChange.ino b/libraries/CurieBLE/examples/BatteryAdvChange/BatteryAdvChange.ino new file mode 100644 index 00000000..44a8055a --- /dev/null +++ b/libraries/CurieBLE/examples/BatteryAdvChange/BatteryAdvChange.ino @@ -0,0 +1,113 @@ +/* Please see code cpyright at the bottom of this example code */ +/* + This sketch illustrates how to change the advertising data so that it is visible but not + connectable. Then after 10 seconds it changes to being connectable + This sketch example partially implements the standard Bluetooth Low-Energy Battery service. + + This sketch is not paired with a specific central example sketch, + but to see how it works you need to use a BLE APP on your phone or central device + and try connecting when it is either a connectable or not connectable state + as displayed in the serial monitor. +*/ + +#include + +BLEPeripheral blePeripheral; // BLE Peripheral Device (the board you're programming) +BLEService batteryService("180F"); // BLE Battery Service +int count = 0; +// BLE Battery Level Characteristic" +BLEUnsignedCharCharacteristic batteryLevelChar("2A19", // standard 16-bit characteristic UUID + BLERead | BLENotify); // remote clients will be able to +// get notifications if this characteristic changes + +void setup() { + Serial.begin(9600); // initialize serial communication + pinMode(13, OUTPUT); // initialize the LED on pin 13 to indicate when a central is connected + while (!Serial) { + //wait for Serial to connect + } + /* Set a local name for the BLE device + This name will appear in advertising packets + and can be used by remote devices to identify this BLE device + The name can be changed but maybe be truncated based on space left in advertisement packet */ + blePeripheral.setLocalName("BatteryAdvChangeSketch"); + blePeripheral.setAdvertisedServiceUuid(batteryService.uuid()); // add the service UUID + blePeripheral.addAttribute(batteryService); // Add the BLE Battery service + blePeripheral.addAttribute(batteryLevelChar); // add the battery level characteristic + + /* Now activate the BLE device. It will start continuously transmitting BLE + advertising packets and will be visible to remote BLE central devices + until it receives a new connection */ + + blePeripheral.begin(); + Serial.println("Bluetooth device active, waiting for connections..."); + Serial.println("Starts in Connectable mode"); +} + +void loop() { + // listen for BLE peripherals to connect: + BLECentralHelper central = blePeripheral.central(); + // wait + Serial.print(". "); + if (count == 10) { + Serial.print("\nReached count "); + Serial.println(count); + + } + delay (1000); + count++; + // Switch from Connectable to Non Connectable and vice versa + if (count > 10 ) { + static bool change_discover = false; + Serial.println("Stop Adv and pausing for 10 seconds. Device should be invisible"); + // Some central devices (phones included) may cache previous scan inofrmation + // restart your central and it should not see this peripheral once stopAdvertising() is called + blePeripheral.stopAdvertising(); + delay(10000); + + if (change_discover) + { + + // Using the function setConnectable we specify that it now NOT connectable + // The loop is for 10 seconds. Your central device may timeout later than that + // and may eventually connect when we set it back to connectable mode below + blePeripheral.setConnectable(false); + Serial.println("In Non Connectable mode"); + + } + else + { + + //using the function setConnectable we specify that it now connectable + blePeripheral.setConnectable(true); + Serial.println("In Connectable mode"); + } + Serial.println("Start Adv"); + blePeripheral.startAdvertising(); + if (change_discover) { + Serial.println("Adding 5 second delay in Non Connect Mode"); + delay(5000); + } + change_discover = !change_discover; + count = 0; + } +} + +/* + Copyright (c) 2016 Intel Corporation. All rights reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + diff --git a/libraries/CurieBLE/examples/BatteryMonitor/BatteryMonitor.ino b/libraries/CurieBLE/examples/BatteryMonitor/BatteryMonitor.ino index 688b147f..96969888 100644 --- a/libraries/CurieBLE/examples/BatteryMonitor/BatteryMonitor.ino +++ b/libraries/CurieBLE/examples/BatteryMonitor/BatteryMonitor.ino @@ -6,7 +6,10 @@ #include /* - This sketch example partially implements the standard Bluetooth Low-Energy Battery service. + This sketch can work with UpdateConnectionInterval. + You can also use an android or IOS app that supports notifications + This sketch example partially implements the standard Bluetooth Low-Energy Battery service + and connection interval paramater update. For more information: https://developer.bluetooth.org/gatt/services/Pages/ServicesHome.aspx */ @@ -15,9 +18,9 @@ BLEPeripheral blePeripheral; // BLE Peripheral Device (the board you're pr BLEService batteryService("180F"); // BLE Battery Service // BLE Battery Level Characteristic" -BLEUnsignedCharCharacteristic batteryLevelChar("2A19", // standard 16-bit characteristic UUID +BLEUnsignedCharCharacteristic batteryLevelChar("2A19", // standard 16-bit characteristic UUID defined in the URL above BLERead | BLENotify); // remote clients will be able to -// get notifications if this characteristic changes + // get notifications if this characteristic changes int oldBatteryLevel = 0; // last battery level reading from analog input long previousMillis = 0; // last time the battery level was checked, in ms @@ -45,7 +48,7 @@ void setup() { void loop() { // listen for BLE peripherals to connect: - BLECentral central = blePeripheral.central(); + BLECentralHelper central = blePeripheral.central(); // if a central is connected to peripheral: if (central) { @@ -63,6 +66,14 @@ void loop() { if (currentMillis - previousMillis >= 200) { previousMillis = currentMillis; updateBatteryLevel(); + + static unsigned short count = 0; + count++; + // update the connection interval + if(count%5 == 0){ + delay(1000); + updateIntervalParams(central); + } } } // when the central disconnects, turn off the LED: @@ -87,6 +98,31 @@ void updateBatteryLevel() { } } +void updateIntervalParams(BLECentralHelper ¢ral) { + // read and update the connection interval that peer central device + static unsigned short interval = 0x60; + ble_conn_param_t m_conn_param; + // Get connection interval that peer central device wanted + central.getConnParams(m_conn_param); + Serial.print("min interval = " ); + Serial.println(m_conn_param.interval_min ); + Serial.print("max interval = " ); + Serial.println(m_conn_param.interval_max ); + Serial.print("latency = " ); + Serial.println(m_conn_param.latency ); + Serial.print("timeout = " ); + Serial.println(m_conn_param.timeout ); + + //Update connection interval + Serial.println("set Connection Interval"); + central.setConnectionInterval(interval,interval); + + interval++; + if(interval<0x06) + interval = 0x06; + if(interval>0x100) + interval = 0x06; +} /* Copyright (c) 2016 Intel Corporation. All rights reserved. diff --git a/libraries/CurieBLE/examples/ButtonLED/ButtonLED.ino b/libraries/CurieBLE/examples/ButtonLED/ButtonLED.ino index b4cd873a..9cb38a2c 100644 --- a/libraries/CurieBLE/examples/ButtonLED/ButtonLED.ino +++ b/libraries/CurieBLE/examples/ButtonLED/ButtonLED.ino @@ -3,19 +3,28 @@ * See the bottom of this file for the license terms. */ + /* This examples needs a button connected similarly as described here + https://www.arduino.cc/en/Tutorial/Button + The only difference is that instead of connecting to pin 2 connect to pin 4 + After the sketch starts connect to a BLE app on a phone and set notification to the Characteristic and you should see it update + whenever the button is pressed. This sketch is not written to pair with any of the central examples. + */ + #include const int ledPin = 13; // set ledPin to on-board LED const int buttonPin = 4; // set buttonPin to digital pin 4 BLEPeripheral blePeripheral; // create peripheral instance -BLEService ledService("19B10010-E8F2-537E-4F6C-D104768A1214"); // create service +BLEService ledService("19B10010-E8F2-537E-4F6C-D104768A1214"); // create service with a 128-bit UUID (32 characters exclusive of dashes). + // Long UUID denote custom user created UUID // create switch characteristic and allow remote device to read and write BLECharCharacteristic ledCharacteristic("19B10011-E8F2-537E-4F6C-D104768A1214", BLERead | BLEWrite); // create button characteristic and allow remote device to get notifications BLECharCharacteristic buttonCharacteristic("19B10012-E8F2-537E-4F6C-D104768A1214", BLERead | BLENotify); // allows remote device to get notifications +// Note use of Typed Characteristics. These previous 2 characeristics are of the type char void setup() { Serial.begin(9600); @@ -32,6 +41,7 @@ void setup() { blePeripheral.addAttribute(ledCharacteristic); blePeripheral.addAttribute(buttonCharacteristic); + // set initial values for led and button characteristic ledCharacteristic.setValue(0); buttonCharacteristic.setValue(0); @@ -59,10 +69,13 @@ void loop() { if (ledCharacteristic.written() || buttonChanged) { // update LED, either central has written to characteristic or button state has changed + // if you are using a phone or a BLE central device that is aware of this characteristic, writing a value of 0x40 for example + // Will be interpreted as written if (ledCharacteristic.value()) { Serial.println("LED on"); digitalWrite(ledPin, HIGH); } else { + // If central writes a 0 value then it is interpreted as no value and turns off the LED Serial.println("LED off"); digitalWrite(ledPin, LOW); } diff --git a/libraries/CurieBLE/examples/CallbackLED/CallbackLED.ino b/libraries/CurieBLE/examples/CallbackLED/CallbackLED.ino index f8788731..3f516ca5 100644 --- a/libraries/CurieBLE/examples/CallbackLED/CallbackLED.ino +++ b/libraries/CurieBLE/examples/CallbackLED/CallbackLED.ino @@ -2,13 +2,24 @@ * Copyright (c) 2016 Intel Corporation. All rights reserved. * See the bottom of this file for the license terms. */ + + // This example can work with LEDCentral + // You should see the LED blink on and off + // This example demonstrates the use of Callback or event Handlers responding to events + // BLECoonected, BLEDisconnected and BLEWritten are events. + // To test interactively use a Phone app like nrf Controller (Android) or Light Blue (iOS) + // Connect to BLE device named LEDCB and explore characteristic with UUID 19B10001-E8F2-537E-4F6C-D104768A1214 + // Writing a byte value such as 0x40 should turn on the LED + // Writng a byte value of 0x00 should turn off the LED #include const int ledPin = 13; // set ledPin to use on-board LED BLEPeripheral blePeripheral; // create peripheral instance +BLECentralHelper *bleCentral1 = NULL; // peer central device -BLEService ledService("19B10000-E8F2-537E-4F6C-D104768A1214"); // create service +BLEService ledService("19B10000-E8F2-537E-4F6C-D104768A1214"); // create service with a 128-bit UUID (32 characters exclusive of dashes). + // Long UUID denote custom user created UUID // create switch characteristic and allow remote device to read and write BLECharCharacteristic switchChar("19B10001-E8F2-537E-4F6C-D104768A1214", BLERead | BLEWrite); @@ -45,19 +56,25 @@ void loop() { blePeripheral.poll(); } -void blePeripheralConnectHandler(BLECentral& central) { +// The function parameter (BLEHelper& central) is for peripheral devices +// This enable us to have access to the central's data like its bluetooth address + +void blePeripheralConnectHandler(BLEHelper& central) { // central connected event handler + bleCentral1 = blePeripheral.getPeerCentralBLE(central); Serial.print("Connected event, central: "); - Serial.println(central.address()); + Serial.println(bleCentral1->address()); } -void blePeripheralDisconnectHandler(BLECentral& central) { +void blePeripheralDisconnectHandler(BLEHelper& central) { // central disconnected event handler Serial.print("Disconnected event, central: "); Serial.println(central.address()); } -void switchCharacteristicWritten(BLECentral& central, BLECharacteristic& characteristic) { +// In addtion to the BLECentral& central parameter, we also have to have to BLECharacteristic& characteristic parameter + +void switchCharacteristicWritten(BLEHelper& central, BLECharacteristic& characteristic) { // central wrote new value to characteristic, update LED Serial.print("Characteristic event, written: "); diff --git a/libraries/CurieBLE/examples/IMUBleCentral/IMUBleCentral.ino b/libraries/CurieBLE/examples/IMUBleCentral/IMUBleCentral.ino new file mode 100644 index 00000000..e14753db --- /dev/null +++ b/libraries/CurieBLE/examples/IMUBleCentral/IMUBleCentral.ino @@ -0,0 +1,172 @@ +/* + * Copyright (c) 2016 Intel Corporation. All rights reserved. + * See the bottom of this file for the license terms. + */ + +#include + +/* + This sketch example works with IMUBleNotification.ino + IMUBleNotification.ino will send notification to this sketch. + This sketch will receive the notifications and out put the received data in the serial monitor + It also illustrates using a non typed characteristic + Set the baud rate to 115200 on the serial monitor to accomodate the speed of constant data updates from IMU subsystem + +*/ + +#define MAX_IMU_RECORD 1 + +ble_conn_param_t conn_param = {30.0, // minimum interval in ms 7.5 - 4000 + 50.0, // maximum interval in ms 7.5 - + 0, // latency + 4000 // timeout in ms 100 - 32000ms + }; +// define a structure that will serve as buffer for holding IMU data + +typedef struct { + int index; + unsigned int slot[3]; +} imuFrameType; + +imuFrameType imuBuf[MAX_IMU_RECORD]; +BLECentral bleCentral; // BLE Central Device (the board you're programming) + +BLEService bleImuService("F7580001-153E-D4F6-F26D-43D8D98EEB13"); +BLECharacteristic bleImuChar("F7580003-153E-D4F6-F26D-43D8D98EEB13", // standard 128-bit characteristic UUID + BLERead | BLENotify, sizeof(imuBuf)); // remote clients will be able to + // get notifications if this characteristic changes + // We have a third parameter which is the size of imyBuffer. This is because it is a non-typed characteristic + // If we are only writing to this characteristic we can set this buffer to 512 bytes + // But because of the limitation of the Nordic FW, please do not set this to more than 128 if you intend to read it. + // MAX_IMU_RECORD value is 1 so we are safe +// function prototype for function that determines if the advertising data is found +bool adv_found(uint8_t type, + const uint8_t *dataPtr, + uint8_t data_len, + const bt_addr_le_t *addrPtr); + +void setup() +{ + // This is set to higher baud rate because accelerometer data changes very quickly + Serial.begin(115200); // initialize serial communication + pinMode(13, OUTPUT); // initialize the LED on pin 13 to indicate when a central is connected + // set the event handeler function for the bleImuChar characteristic + bleImuChar.setEventHandler(BLEWritten, bleImuCharacteristicWritten); + + bleCentral.addAttribute(bleImuService); // Add the BLE IMU service + bleCentral.addAttribute(bleImuChar); // Add the BLE IMU characteristic + + // Setup callback whenever a Peripheral advertising data is found) + bleCentral.setAdvertiseHandler(adv_found); + bleCentral.setEventHandler(BLEConnected, ble_connected); + + /* Now activate the BLE device. It will start continuously transmitting BLE + advertising packets and will be visible to remote BLE central devices + until it receives a new connection */ + bleCentral.begin(); +} + + +void loop() +{ + // we put a 2 second delay + // Even though this looks empty, since we setup 2 callbacks by setting the advertising handler adv_found + // and event handler for BLEConnected, we basically are lsitening for advertising data and connected events. + + delay(2000); +} + +void ble_connected(BLEHelper &role) +{ + // since we are a central device we create a BLEPeripheralHelper peripheral + BLEPeripheralHelper *peripheral = bleCentral.getPeerPeripheralBLE(role); + Serial.println("Connected"); + + // Start discovery the profiles in peripheral device + peripheral->discover(); +} + +void bleImuCharacteristicWritten(BLEHelper& peripheral, BLECharacteristic& characteristic) +{ + // Peripheral wrote new value to characteristic by Notification/Indication + // We have to use pointers because we are NOT using a type characteristic + // In other examples our charcteristics are typed so we not have to use pointers and can access the value directly + // The parent non typde characteristic class, the value method gives a pointer to the characteristic value + + const unsigned char *cvalue = characteristic.value(); + const imuFrameType *value = (const imuFrameType *)cvalue; + Serial.print("\r\nCharacteristic event, written: "); + Serial.print(value->index); + Serial.print("\t"); + Serial.print(value->slot[0]); + Serial.print("\t"); + Serial.print(value->slot[1]); + Serial.print("\t"); + Serial.println(value->slot[2]); +} + +bool adv_found(uint8_t type, + const uint8_t *dataPtr, + uint8_t data_len, + const bt_addr_le_t *addrPtr) +{ + int i; + + Serial.print("[AD]:"); + Serial.print(type); + Serial.print(" data_len "); + Serial.println(data_len); + // Please see https://www.bluetooth.org/en-us/specification/assigned-numbers/generic-access-profile + // To decode the data the central device cares. + // This example use UUID as identity. + switch (type) + { + case BT_DATA_UUID128_SOME: + case BT_DATA_UUID128_ALL: + { + if (data_len % UUID_SIZE_128 != 0) + { + Serial.println("AD malformed"); + return true; + } + for (i = 0; i < data_len; i += UUID_SIZE_128) + { + if (bleImuService.uuidCompare(dataPtr + i, UUID_SIZE_128) == false) + { + continue; + } + + // Accept the advertisement + if (!bleCentral.stopScan()) + { + Serial.println("Stop LE scan failed"); + continue; + } + Serial.println("Connecting"); + // Connect to peripheral + bleCentral.connect(addrPtr, &conn_param); + return false; + } + } + } + + return true; +} + +/* + Copyright (c) 2016 Intel Corporation. All rights reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ diff --git a/libraries/CurieBLE/examples/IMUBleNotification/IMUBleNotification.ino b/libraries/CurieBLE/examples/IMUBleNotification/IMUBleNotification.ino new file mode 100644 index 00000000..81ca3dec --- /dev/null +++ b/libraries/CurieBLE/examples/IMUBleNotification/IMUBleNotification.ino @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2016 Intel Corporation. All rights reserved. + * See the bottom of this file for the license terms. + */ + +#include +#include + +/* + This sketch example works with IMUBleCentral.ino + This sketch will read IMU data from sensor and send notification to IMUBleCentral.ino + IMUBleCentral.ino will receive the Notifications and output the received data. +*/ + +#define MAX_IMU_RECORD 1 + +typedef struct { + int index; + unsigned int slot[3]; +} imuFrameType; + +// Buffer to hold IMU data +imuFrameType imuBuf[MAX_IMU_RECORD]; + +unsigned seqNum = 0; + +BLEPeripheral blePeripheral; // BLE Peripheral Device (the board you're programming) +BLEService bleImuService("F7580001-153E-D4F6-F26D-43D8D98EEB13"); // Tx IMU data Characteristic +BLECharacteristic bleImuChar("F7580003-153E-D4F6-F26D-43D8D98EEB13", // standard 128-bit characteristic UUID + BLERead | BLENotify, sizeof(imuBuf)); // remote clients will be able to + // get notifications if this characteristic changes +void setup() +{ + Serial.begin(9600); // initialize serial communication + pinMode(13, OUTPUT); // initialize the LED on pin 13 to indicate when a central is connected + + + /* Set a local name for the BLE device + This name will appear in advertising packets + and can be used by remote devices to identify this BLE device + The name can be changed but maybe be truncated based on space left in advertisement packet */ + blePeripheral.setLocalName("Imu"); + blePeripheral.setAdvertisedServiceUuid(bleImuService.uuid()); // add the service UUID + blePeripheral.addAttribute(bleImuService); // Add the Imu service + blePeripheral.addAttribute(bleImuChar); // add the Imu characteristic + + /* Now activate the BLE device. It will start continuously transmitting BLE + advertising packets and will be visible to remote BLE central devices + until it receives a new connection */ + blePeripheral.begin(); + // Start the IMU + CurieIMU.begin(); +} + +void loop() +{ + // listen for BLE peripherals to connect: + // Since we are a peripheral we need a central object to connect to + BLECentralHelper central = blePeripheral.central(); + + // if a central is connected to peripheral: + if (central) + { + Serial.print("Connected to central: "); + // print the central's MAC address: + Serial.println(central.address()); + + Serial.print("IMU buffer size: "); + Serial.println(sizeof(imuBuf)); + + // turn on the LED to indicate the connection: + digitalWrite(13, HIGH); + + long currentMillis, sentTime; + + // Send IMU data as long as the central is still connected + currentMillis = sentTime = millis(); + while (central.connected()) + { + // Take IMU data every 100 msec + if ((millis() - sentTime) >= 100) + { + recordImuData(0); + sentTime = millis(); + bleImuChar.setValue((unsigned char *)&(imuBuf[0]), sizeof(imuBuf)); + } + } // end of while loop + + // when the central disconnects, turn off the LED: + digitalWrite(13, LOW); + Serial.print("Disconnected from central: "); + Serial.println(central.address()); + } +} + +// This function records the IMU data that we send to the central +void recordImuData(int index) +{ + /* Read IMU data. + */ + int ax, ay, az; + int gx, gy, gz; + + imuBuf[index].index = seqNum++; + CurieIMU.readMotionSensor(ax, ay, az, gx, gy, gz); + + // Encode the data into the buffer + imuBuf[index].slot[0] = (unsigned int)((ax << 16) | (ay & 0x0FFFF)); + imuBuf[index].slot[1] = (unsigned int)((az << 16) | (gx & 0x0FFFF)); + imuBuf[index].slot[2] = (unsigned int)((gy << 16) | (gz & 0x0FFFF)); + +} + + +/* + Copyright (c) 2016 Intel Corporation. All rights reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ diff --git a/libraries/CurieBLE/examples/LED/LED.ino b/libraries/CurieBLE/examples/LED/LED.ino index a55501dc..2c2c261d 100644 --- a/libraries/CurieBLE/examples/LED/LED.ino +++ b/libraries/CurieBLE/examples/LED/LED.ino @@ -2,7 +2,17 @@ * Copyright (c) 2016 Intel Corporation. All rights reserved. * See the bottom of this file for the license terms. */ - + + // This example can work with LEDCentral + // + // This example is similar to CallbackLED example in functionality + // It does not use callbacks. In the loop it interogates the connection state with central + // Checks if the characteristic is wriiten and turns the LED on or off accordingly + // To test interactively, use a phone app like nrf Controller (Android) or Light Blue (iOS) + // Connect to BLE device named LEDCB and explore characteristic with UUID 19B10001-E8F2-537E-4F6C-D104768A1214 + // Writing a byte value such as 0x40 should turn on the LED + // Writng a byte value of 0x00 should turn off the LED + #include BLEPeripheral blePeripheral; // BLE Peripheral Device (the board you're programming) @@ -38,7 +48,7 @@ void setup() { void loop() { // listen for BLE peripherals to connect: - BLECentral central = blePeripheral.central(); + BLECentralHelper central = blePeripheral.central(); // if a central is connected to peripheral: if (central) { diff --git a/libraries/CurieBLE/examples/LEDCentral/LEDCentral.ino b/libraries/CurieBLE/examples/LEDCentral/LEDCentral.ino new file mode 100644 index 00000000..b9b533b3 --- /dev/null +++ b/libraries/CurieBLE/examples/LEDCentral/LEDCentral.ino @@ -0,0 +1,178 @@ +/* + * Copyright (c) 2016 Intel Corporation. All rights reserved. + * See the bottom of this file for the license terms. + */ + +#include + +/* + This example can work with CallbackLED and LED + to show how a central device can do charcteristic read and write operations. + A third party serial terminal is recommended to see outputs from central and peripheral device +*/ + +// set up connection params + +ble_conn_param_t conn_param = {30.0, // minimum interval in ms 7.5 - 4000 + 50.0, // maximum interval in ms 7.5 - + 0, // latency + 4000 // timeout in ms 100 - 32000ms + }; + +const int ledPin = 13; // set ledPin to use on-board LED +BLECentral bleCentral; // create central instance +BLEPeripheralHelper *blePeripheral1 = NULL; // peer peripheral device + +BLEService ledService("19B10000-E8F2-537E-4F6C-D104768A1214"); // create service with a 128-bit UUID (32 characters exclusive of dashes). + // Long UUID denote custom user created UUID +BLECharCharacteristic switchChar("19B10001-E8F2-537E-4F6C-D104768A1214", BLERead | BLEWrite);// create switch characteristic and allow remote device to read and write + +// function prototype for function that determines if the advertising data is found +bool adv_found(uint8_t type, + const uint8_t *dataPtr, + uint8_t data_len, + const bt_addr_le_t *addrPtr); + +void setup() +{ + Serial.begin(9600); + pinMode(ledPin, OUTPUT); // use the LED on pin 13 as an output + + // add service and characteristic + bleCentral.addAttribute(ledService); + bleCentral.addAttribute(switchChar); + + // assign event handlers for connected, disconnected to central + bleCentral.setEventHandler(BLEConnected, bleCentralConnectHandler); + bleCentral.setEventHandler(BLEDisconnected, bleCentralDisconnectHandler); + + // advertise the service + bleCentral.setAdvertiseHandler(adv_found); + + // assign event handlers for characteristic + switchChar.setEventHandler(BLEWritten, switchCharacteristicWritten); + + bleCentral.begin(); + Serial.println(("Bluetooth device active, waiting for connections...")); +} + +void loop() +{ + static unsigned int counter = 0; + static char ledstate = 0; + delay(2000); + + if (blePeripheral1) + { + counter++; + if (counter % 3) + { + switchChar.read(*blePeripheral1); + } + else + { + ledstate = !ledstate; + switchChar.write(*blePeripheral1, ledstate); + } + } +} + +void bleCentralConnectHandler(BLEHelper& peripheral) +{ + // peripheral connected event handler + blePeripheral1 = bleCentral.getPeerPeripheralBLE(peripheral); + Serial.print("Connected event, peripheral: "); + Serial.println(blePeripheral1->address()); + // Start discovery the profiles in peripheral device + blePeripheral1->discover(); +} + +void bleCentralDisconnectHandler(BLEHelper& peripheral) +{ + // peripheral disconnected event handler + blePeripheral1 = NULL; + Serial.print("Disconnected event, peripheral: "); + Serial.println(peripheral.address()); + bleCentral.startScan(); +} + +void switchCharacteristicWritten(BLEHelper& peripheral, BLECharacteristic& characteristic) +{ + // Read response/Notification wrote new value to characteristic, update LED + Serial.print("Characteristic event, written: "); + + if (switchChar.value()) + { + Serial.println("LED on"); + digitalWrite(ledPin, HIGH); + } + else + { + Serial.println("LED off"); + digitalWrite(ledPin, LOW); + } +} + +bool adv_found(uint8_t type, + const uint8_t *dataPtr, + uint8_t data_len, + const bt_addr_le_t *addrPtr) +{ + int i; + + Serial.print("[AD]:"); + Serial.print(type); + Serial.print(" data_len "); + Serial.println(data_len); + + switch (type) + { + case BT_DATA_UUID128_SOME: + case BT_DATA_UUID128_ALL: + { + if (data_len % UUID_SIZE_128 != 0) + { + Serial.println("AD malformed"); + return true; + } + for (i = 0; i < data_len; i += UUID_SIZE_128) + { + if (ledService.uuidCompare(dataPtr + i, UUID_SIZE_128) == false) + { + continue; + } + + // Accept the advertisement + if (!bleCentral.stopScan()) + { + Serial.println("Stop LE scan failed"); + continue; + } + Serial.println("Connecting"); + // Connect to peripheral + bleCentral.connect(addrPtr, &conn_param); + return false; + } + } + } + + return true; +} + +/* + Copyright (c) 2016 Intel Corporation. All rights reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ diff --git a/libraries/CurieBLE/examples/MIDIBLE/MIDIBLE.ino b/libraries/CurieBLE/examples/MIDIBLE/MIDIBLE.ino index 2dbe9833..7d78df27 100644 --- a/libraries/CurieBLE/examples/MIDIBLE/MIDIBLE.ino +++ b/libraries/CurieBLE/examples/MIDIBLE/MIDIBLE.ino @@ -1,7 +1,8 @@ /* Written by Oren Levy (auxren.com; @auxren) while competing on America's Greatest Makers with help from Intel. MIDI over BLE info from: https://developer.apple.com/bluetooth/Apple-Bluetooth-Low-Energy-MIDI-Specification.pdf - + This sketch is not written to pair with any of the central examples. + This sketch plays a random MIDI note (between 0 and 127) every 400ms. For a 'smarter' sketch, check out my Airpeggiator example. The Airpeggiator uses the Curie's IMU to allow you to play @@ -25,6 +26,9 @@ Towards the bottom of advanced, you will see 'Bluetooth MIDI devices'. You should see your Arduino 101 advertising in the list. Connect to your device and it should be available to all other iOS MIDI apps you have. + + If you do not have iOS, you can still use a BLE app on Android and just subscribe + to the midiChar charcteristic and see the updates. To send data, you use the following line: char.setValue(d, n); where char is the BLE characteristic (in our case, midiCha), d is the data, and n is the @@ -98,6 +102,21 @@ void setup() { Serial.println(("Bluetooth device active, waiting for connections...")); } +void loop() { + + /*Simple randome note player to test MIDI output + Plays random note every 400ms + */ + int note = random(0, 127); + //readMIDI(); + noteOn(0, note, 127); //loads up midiData buffer + midiChar.setValue(midiData, 5);//midiData); //posts 5 bytes + delay(200); + noteOff(0, note); + midiChar.setValue(midiData, 5);//midiData); //posts 5 bytes + delay(200); +} + void BLESetup() { // set the local name peripheral advertises @@ -124,35 +143,19 @@ void BLESetup() midiDevice.begin(); } -void loop() { - - /*Simple randome note player to test MIDI output - Plays random note every 400ms - */ - int note = random(0, 127); - //readMIDI(); - noteOn(0, note, 127); //loads up midiData buffer - midiChar.setValue(midiData, 5);//midiData); //posts 5 bytes - delay(200); - noteOff(0, note); - midiChar.setValue(midiData, 5);//midiData); //posts 5 bytes - delay(200); -} - - -void midiDeviceConnectHandler(BLECentral& central) { +void midiDeviceConnectHandler(BLEHelper& central) { // central connected event handler Serial.print("Connected event, central: "); Serial.println(central.address()); } -void midiDeviceDisconnectHandler(BLECentral& central) { +void midiDeviceDisconnectHandler(BLEHelper& central) { // central disconnected event handler Serial.print("Disconnected event, central: "); Serial.println(central.address()); } -void midiCharacteristicWritten(BLECentral& central, BLECharacteristic& characteristic) { +void midiCharacteristicWritten(BLEHelper& central, BLECharacteristic& characteristic) { // central wrote new value to characteristic, update LED Serial.print("Characteristic event, written: "); } diff --git a/libraries/CurieBLE/examples/Scanning/Scanning.ino b/libraries/CurieBLE/examples/Scanning/Scanning.ino new file mode 100644 index 00000000..97ea222d --- /dev/null +++ b/libraries/CurieBLE/examples/Scanning/Scanning.ino @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2016 Intel Corporation. All rights reserved. + * See the bottom of this file for the license terms. + */ + +#include + +/* + This sketch try to show the scan function + The sketch will list the device's MAC address and device name to the console + The list will refresh every 3s + This sketch is meaningful if one or more BLE peripheral devices (any of the peripheral examples will do) + are present. +*/ + + +const int bleScanMaxCnt = 5; + +typedef struct{ + char macaddr[32]; // BLE MAC address. + char loacalname[22]; // Device's name +}ble_device_info_t; + +ble_device_info_t device_list[bleScanMaxCnt]; +uint8_t list_index = 0; + +BLECentral bleCentral; // BLE Central Device (the board you're programming) + +bool adv_found(uint8_t type, + const uint8_t *dataPtr, + uint8_t data_len, + const bt_addr_le_t *addrPtr); + +void setup() +{ + Serial.begin(115200); // initialize serial communication + + /* Setup callback */ + bleCentral.setAdvertiseHandler(adv_found); + + /* Now activate the BLE device. + It will start continuously scanning BLE advertising + */ + bleCentral.begin(); + Serial.println("Bluetooth device active, start scanning..."); +} + +void loop() +{ + // Output the scanned device per 3s + delay(3000); + Serial.print("\r\n\r\n\t\t\tScaning result\r\n \tMAC\t\t\t\tLocal Name\r\n"); + Serial.print("-------------------------------------------------------------\r\n"); + + for (int i = 0; i < list_index; i++) + { + + Serial.print(device_list[i].macaddr); + Serial.print(" | "); + Serial.println(device_list[i].loacalname); + } + if (list_index == 0) + { + Serial.print("No device found\r\n"); + } + Serial.print("-------------------------------------------------------------\r\n"); + adv_list_clear(); +} + +// Add the scanned BLE device into the global variables. +bool adv_list_add(ble_device_info_t &device) +{ + if (list_index >= bleScanMaxCnt) + { + return false; + } + for (int i = 0; i < list_index; i++) + { + if (0 == memcmp(device.macaddr, device_list[i].macaddr, sizeof (device.macaddr))) + { + // Found and update the item + return false; + } + } + // Add the device + memcpy(&device_list[list_index], &device, sizeof (ble_device_info_t)); + list_index++; + return true; +} + + +bool adv_list_update(ble_device_info_t &device) +{ + for (int i = 0; i < list_index; i++) + { + if (0 == memcmp(device.macaddr, device_list[i].macaddr, sizeof (device.macaddr))) + { + // Found and update the item + memcpy(device_list[i].loacalname, device.loacalname, sizeof(device.loacalname)); + return true; + } + } + return false; +} + +void adv_list_clear() +{ + list_index = 0; + memset(device_list, 0x00, sizeof(device_list)); +} + +// Process the Advertisement data +bool adv_found(uint8_t type, + const uint8_t *dataPtr, + uint8_t data_len, + const bt_addr_le_t *addrPtr) +{ + ble_device_info_t device; + bt_addr_le_to_str (addrPtr, device.macaddr, sizeof (device.macaddr)); + memcpy(device.loacalname, " -NA-", sizeof(" -NA-")); + // Please see https://www.bluetooth.org/en-us/specification/assigned-numbers/generic-access-profile + switch (type) { + case BT_DATA_NAME_SHORTENED: + case BT_DATA_NAME_COMPLETE: + memcpy(device.loacalname, dataPtr, data_len); + device.loacalname[data_len] = '\0'; + adv_list_update(device); + break; + } + adv_list_add(device); + return true; +} + +/* + Copyright (c) 2016 Intel Corporation. All rights reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ diff --git a/libraries/CurieBLE/examples/UpdateConnectionInterval/UpdateConnectionInterval.ino b/libraries/CurieBLE/examples/UpdateConnectionInterval/UpdateConnectionInterval.ino new file mode 100644 index 00000000..a25c2195 --- /dev/null +++ b/libraries/CurieBLE/examples/UpdateConnectionInterval/UpdateConnectionInterval.ino @@ -0,0 +1,205 @@ +/* + * Copyright (c) 2016 Intel Corporation. All rights reserved. + * See the bottom of this file for the license terms. + */ + +#include + +/* + This example can work with BatteryMonitor + to show how to control and response the connection intelval request. +*/ + +// set up connection params + +ble_conn_param_t conn_param = {30.0, // minimum interval in ms 7.5 - 4000 + 50.0, // maximum interval in ms 7.5 - + 0, // latency + 4000 // timeout in ms 100 - 32000ms + }; + +const int ledPin = 13; // set ledPin to use on-board LED +BLECentral bleCentral; // create central instance +BLEPeripheralHelper *blePeripheral1 = NULL; // // peer peripheral device + +BLEService batteryService("180F"); // create service with a 16-bit UUID +BLECharCharacteristic batteryLevelChar("2A19", BLERead | BLENotify);// create switch characteristic +//and allow remote device to read and notify + +bool adv_found(uint8_t type, + const uint8_t *dataPtr, + uint8_t data_len, + const bt_addr_le_t *addrPtr); + +void setup() +{ + Serial.begin(9600); + + // add service and characteristic + bleCentral.addAttribute(batteryService); + bleCentral.addAttribute(batteryLevelChar); + + // assign event handlers for connected, disconnected to central + bleCentral.setEventHandler(BLEConnected, bleCentralConnectHandler); + bleCentral.setEventHandler(BLEDisconnected, bleCentralDisconnectHandler); + bleCentral.setEventHandler(BLEUpdateParam, bleCentralUpdateParam); + + // advertise the service + bleCentral.setAdvertiseHandler(adv_found); + + // assign event handlers for characteristic + batteryLevelChar.setEventHandler(BLEWritten, switchCharacteristicWritten); + + bleCentral.begin(); + Serial.println(("Bluetooth device active, waiting for connections...")); +} + +void loop() +{ + static unsigned int counter = 0; + static char ledstate = 0; + delay(2000); + if (blePeripheral1) + { + counter++; + + if (counter % 3) + { + batteryLevelChar.read(*blePeripheral1); + } + else + { + ledstate = !ledstate; + batteryLevelChar.write(*blePeripheral1, ledstate); + } + } + +} + +void bleCentralConnectHandler(BLEHelper& peripheral) +{ + // peripheral connected event handler + blePeripheral1 = bleCentral.getPeerPeripheralBLE(peripheral); + Serial.print("Connected event, peripheral: "); + Serial.println(peripheral.address()); + // Start discovery the profiles in peripheral device + blePeripheral1->discover(); +} + +void bleCentralDisconnectHandler(BLEHelper& peripheral) +{ + // peripheral disconnected event handler + blePeripheral1 = NULL; + Serial.print("Disconnected event, peripheral: "); + Serial.println(peripheral.address()); + bleCentral.startScan(); +} + +void bleCentralUpdateParam(BLEHelper& peripheral) +{ + // peripheral update the connection interval event handler + Serial.print("UpdateParam event, peripheral: "); + blePeripheral1 = bleCentral.getPeerPeripheralBLE(peripheral);; + Serial.println(peripheral.address()); + + // Get connection interval that peer peripheral device wanted + ble_conn_param_t m_conn_param; + blePeripheral1->getConnParams(m_conn_param); + Serial.print("min interval = " ); + Serial.println(m_conn_param.interval_min ); + Serial.print("max interval = " ); + Serial.println(m_conn_param.interval_max ); + Serial.print("latency = " ); + Serial.println(m_conn_param.latency ); + Serial.print("timeout = " ); + Serial.println(m_conn_param.timeout ); + + //Update the connection interval + blePeripheral1->setConnectionInterval(m_conn_param.interval_min,m_conn_param.interval_max); +} + +void switchCharacteristicWritten(BLEHelper& peripheral, BLECharacteristic& characteristic) +{ + // Read response/Notification wrote new value to characteristic, update LED + Serial.print("Characteristic event, notify: "); + + int battery = batteryLevelChar.value(); + if (battery) + { + Serial.print("Battery Level % is now: "); // print it + Serial.println(battery); + delay(100); + + Serial.println("LED on"); + digitalWrite(ledPin, HIGH); + } + else + { + Serial.println("LED off"); + digitalWrite(ledPin, LOW); + } +} + +bool adv_found(uint8_t type, + const uint8_t *dataPtr, + uint8_t data_len, + const bt_addr_le_t *addrPtr) +{ + int i; + + Serial.print("[AD]:"); + Serial.print(type); + Serial.print(" data_len "); + Serial.println(data_len); + + switch (type) + { + case BT_DATA_UUID16_SOME: + case BT_DATA_UUID16_ALL: + { + if (data_len % UUID_SIZE_16 != 0) + { + Serial.println("AD malformed"); + return true; + } + for (i = 0; i < data_len; i += UUID_SIZE_16) + { + if (batteryService.uuidCompare(dataPtr + i, UUID_SIZE_16) == false) + { + continue; + } + + // Accept the advertisement + if (!bleCentral.stopScan()) + { + Serial.println("Stop LE scan failed"); + continue; + } + Serial.println("Connecting"); + // Connect to peripheral + bleCentral.connect(addrPtr, &conn_param); + return false; + } + } + } + + return true; +} + +/* + Copyright (c) 2016 Intel Corporation. All rights reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ diff --git a/libraries/CurieBLE/keywords.txt b/libraries/CurieBLE/keywords.txt index 85eccea2..bb0f37ea 100644 --- a/libraries/CurieBLE/keywords.txt +++ b/libraries/CurieBLE/keywords.txt @@ -13,7 +13,9 @@ BLEDescriptor KEYWORD1 BLEPeripheral KEYWORD1 BLEService KEYWORD1 BLETypedCharacteristic KEYWORD1 -BLEUuid KEYWORD1 +BLEHelper KEYWORD1 +BLECentralHelper KEYWORD1 +BLEPeripheralHelper KEYWORD1 BLECharCharacteristic KEYWORD1 BLEUnsignedCharCharacteristic KEYWORD1 @@ -31,13 +33,18 @@ BLEDoubleCharacteristic KEYWORD1 ####################################### uuid KEYWORD2 -type KEYWORD2 numAttributes KEYWORD2 connected KEYWORD2 address KEYWORD2 poll KEYWORD2 disconnect KEYWORD2 +discover KEYWORD2 +startScan KEYWORD2 +stopScan KEYWORD2 + +getConnParams KEYWORD2 +setConnectionInterval KEYWORD2 properties KEYWORD2 valueSize KEYWORD2 @@ -49,11 +56,14 @@ written KEYWORD2 subscribed KEYWORD2 begin KEYWORD2 -getAdvertisingLength KEYWORD2 -getAdvertising KEYWORD2 + +stopAdvertising KEYWORD2 +setConnectable KEYWORD2 +startAdvertising KEYWORD2 setAdvertisedServiceUuid KEYWORD2 setAdvertisedServiceData KEYWORD2 setLocalName KEYWORD2 +setDeviceName KEYWORD2 setAppearance KEYWORD2 setConnectionInterval KEYWORD2 addAttribute KEYWORD2 @@ -64,10 +74,9 @@ valueLE KEYWORD2 setValueBE KEYWORD2 valueBE KEYWORD2 -str KEYWORD2 -data KEYWORD2 -length KEYWORD2 - +getPeerPeripheralBLE KEYWORD2 +getPeerCentralBLE KEYWORD2 +uuidCompare KEYWORD2 ####################################### # Constants (LITERAL1) @@ -77,7 +86,6 @@ BLETypeService LITERAL1 BLETypeCharacteristic LITERAL1 BLETypeDescriptor LITERAL1 -BLEBroadcast LITERAL1 BLERead LITERAL1 BLEWriteWithoutResponse LITERAL1 BLEWrite LITERAL1 @@ -86,7 +94,14 @@ BLEIndicate LITERAL1 BLEConnected LITERAL1 BLEDisconnected LITERAL1 +BLEUpdateParam LITERAL1 BLEWritten LITERAL1 BLESubscribed LITERAL1 BLEUnsubscribed LITERAL1 + +ble_conn_param_t LITERAL1 +bt_uuid_t LITERAL1 +bt_uuid_16_t LITERAL1 +bt_uuid_128_t LITERAL1 +bt_addr_le_t LITERAL1 diff --git a/libraries/CurieBLE/src/BLEAttribute.cpp b/libraries/CurieBLE/src/BLEAttribute.cpp index d6f46591..dc49158f 100644 --- a/libraries/CurieBLE/src/BLEAttribute.cpp +++ b/libraries/CurieBLE/src/BLEAttribute.cpp @@ -19,24 +19,66 @@ #include "BLEAttribute.h" -#include "BLEUuid.h" - unsigned char BLEAttribute::_numAttributes = 0; -BLEAttribute::BLEAttribute(const char* uuid, enum BLEAttributeType type) : - _uuid(uuid), +BLEAttribute::BLEAttribute(const char* uuid, BLEAttributeType type) : + _uuid_cstr(uuid), _type(type), _handle(0) { + char temp[] = {0, 0, 0}; + int strLength = strlen(uuid); + int length = 0; + _numAttributes++; + + memset (&_uuid, 0x00, sizeof(_uuid)); + + for (int i = strLength - 1; i >= 0 && length < MAX_UUID_SIZE; i -= 2) + { + if (uuid[i] == '-') + { + i++; + continue; + } + + temp[0] = uuid[i - 1]; + temp[1] = uuid[i]; + + _uuid.val[length] = strtoul(temp, NULL, 16); + + length++; + } + + if (length == 2) + { + uint16_t temp = (_uuid.val[1] << 8)| _uuid.val[0]; + _uuid.uuid.type = BT_UUID_TYPE_16; + ((bt_uuid_16_t*)(&_uuid.uuid))->val = temp; + } + else + { + _uuid.uuid.type = BT_UUID_TYPE_128; + } } const char* BLEAttribute::uuid() const { - return _uuid; + return _uuid_cstr; +} + +const char* +BLEAttribute::uuid_cstr() const { + return _uuid_cstr; +} + +bt_uuid_t *BLEAttribute::uuid(void) +{ + return (bt_uuid_t *)&_uuid; } -enum BLEAttributeType + +BLEAttributeType BLEAttribute::type() const { return this->_type; } @@ -52,14 +94,29 @@ BLEAttribute::setHandle(uint16_t handle) { } -bt_uuid -BLEAttribute::btUuid() const { - BLEUuid bleUuid = BLEUuid(uuid()); - - return bleUuid.uuid(); -} - unsigned char BLEAttribute::numAttributes() { return _numAttributes; } + +bool BLEAttribute::discovering() +{ + return _discoverying; +} + +bool BLEAttribute::uuidCompare(const uint8_t *data, uint8_t uuidsize) +{ + bt_uuid_t * serviceuuid = this->uuid(); + + bool status = true; + if(serviceuuid->type == BT_UUID_TYPE_16 && uuidsize == UUID_SIZE_16) + { + status = memcmp (&((bt_uuid_16_t*)serviceuuid)->val, data, UUID_SIZE_16); + } + else if(serviceuuid->type == BT_UUID_TYPE_128 && uuidsize == UUID_SIZE_128) + { + status = memcmp (((bt_uuid_128_t*)serviceuuid)->val, data, UUID_SIZE_128); + } + + return !status; +} diff --git a/libraries/CurieBLE/src/BLEAttribute.h b/libraries/CurieBLE/src/BLEAttribute.h index 8aaca067..1de33613 100644 --- a/libraries/CurieBLE/src/BLEAttribute.h +++ b/libraries/CurieBLE/src/BLEAttribute.h @@ -22,13 +22,17 @@ #include "BLECommon.h" -enum BLEAttributeType { - BLETypeService = 0x2800, - BLETypeCharacteristic = 0x2803, - BLETypeDescriptor = 0x2900 -}; +/// BLE attribute tyep enum +typedef enum { + BLETypeService = 0x2800, ///< the service type + BLETypeCharacteristic = 0x2803, ///< the characteristic type + BLETypeDescriptor = 0x2900 ///< the descriptor type +}BLEAttributeType; +// Class declare +class BLEProfile; class BLEPeripheral; +class BLEPeripheralHelper; class BLEAttribute { public: @@ -39,25 +43,94 @@ class BLEAttribute { * @return const char* string representation of the Attribute */ const char* uuid(void) const; + + /** + * Get the string representation of the Attribute + * + * @return const char* string representation of the Attribute + */ + const char* uuid_cstr(void) const; + + /** + * @brief Get the UUID raw data + * + * @param none + * + * @return bt_uuid_t* The pointer of UUID + * + * @note none + */ + bt_uuid_t *uuid(void); + + /** + * @brief Compare the UUID with the paramater data + * + * @param[in] data The pointer of data + * + * @param[in] uuidsize The max size of UUID + * + * @return bool true - UUID is the same with data + * false- UUID is not the same with data + * + * @note none + */ + bool uuidCompare(const uint8_t *data, uint8_t uuidsize); protected: - friend BLEPeripheral; + //friend BLEPeripheral; + friend BLEProfile; - BLEAttribute(const char* uuid, enum BLEAttributeType type); + friend ssize_t profile_write_process(bt_conn_t *conn, + const bt_gatt_attr_t *attr, + const void *buf, uint16_t len, + uint16_t offset); + friend ssize_t profile_read_process(bt_conn_t *conn, + const bt_gatt_attr_t *attr, + void *buf, uint16_t len, + uint16_t offset); + + friend ssize_t profile_longwrite_process(struct bt_conn *conn, + const struct bt_gatt_attr *attr, + const void *buf, uint16_t len, + uint16_t offset); + friend int profile_longflush_process(struct bt_conn *conn, + const struct bt_gatt_attr *attr, + uint8_t flags); + + BLEAttribute(const char* uuid, BLEAttributeType type); BLEAttributeType type(void) const; - bt_uuid btUuid(void) const; uint16_t handle(void); void setHandle(uint16_t handle); static unsigned char numAttributes(void); - + // The below APIs are for central device to discover the + virtual void discover(bt_gatt_discover_params_t *params) = 0; + virtual void discover(const bt_gatt_attr_t *attr, + bt_gatt_discover_params_t *params) = 0; + + /** + * @brief Get attribute's discover state + * + * @param none + * + * @return bool true - In discovering state + * false- Not discovering + * + * @note none + */ + bool discovering(); + + bool _discoverying; private: static unsigned char _numAttributes; - const char* _uuid; - enum BLEAttributeType _type; + const char* _uuid_cstr; + bt_uuid_128_t _uuid; + + BLEAttributeType _type; uint16_t _handle; + }; #endif // _BLE_ATTRIBUTE_H_INCLUDED diff --git a/libraries/CurieBLE/src/BLECentral.cpp b/libraries/CurieBLE/src/BLECentral.cpp index 73d0326d..728b222c 100644 --- a/libraries/CurieBLE/src/BLECentral.cpp +++ b/libraries/CurieBLE/src/BLECentral.cpp @@ -17,87 +17,108 @@ * */ -#include "BLECentral.h" - -#include "BLEPeripheral.h" +#include "BLECentralRole.h" +#include "BLECentral.h" +#include "internal/ble_client.h" -BLECentral::BLECentral(BLEPeripheral* peripheral) : - _peripheral(peripheral) +bool BLECentral::startScan() { - clearAddress(); + return BLECentralRole::instance()->startScan(); } -BLECentral::operator bool() const { - ble_addr_t zero; - - memset(&zero, 0, sizeof(zero)); - - return (memcmp(&_address, &zero, sizeof(_address)) != 0); +bool BLECentral::startScan(float interval, float window) +{ + setScanParam(interval, window); + return BLECentralRole::instance()->startScan(); } -bool -BLECentral::operator==(const BLECentral& rhs) const { - return (memcmp(&_address, &rhs._address, sizeof(_address)) == 0); +bool BLECentral::stopScan() +{ + return BLECentralRole::instance()->stopScan(); } -bool -BLECentral::operator!=(const BLECentral& rhs) const { - return !(*this == rhs); +bool BLECentral::connect(const bt_addr_le_t *addr, const ble_conn_param_t *param) +{ + bt_le_conn_param_t conn_param; + + conn_param.latency = param->latency; + conn_param.interval_max = (uint16_t)MSEC_TO_UNITS(param->interval_max, UNIT_1_25_MS); + conn_param.interval_min = (uint16_t)MSEC_TO_UNITS(param->interval_min, UNIT_1_25_MS); + conn_param.timeout = MSEC_TO_UNITS(param->timeout, UNIT_10_MS); + + pr_debug(LOG_MODULE_BLE,"Latency-%d\r\nInterval min-%d, max-%d\r\ntimeout:%d", + conn_param.latency, + conn_param.interval_min, + conn_param.interval_max, + conn_param.timeout); + + return BLECentralRole::instance()->connect(addr, &conn_param); } -bool -BLECentral::connected() { - poll(); - - return (*this && *this == _peripheral->central()); +void BLECentral::discover(BLEPeripheralHelper &peripheral) +{ + peripheral.discover(); } -const char* -BLECentral::address() const { - static char address[18]; - - String addressStr = ""; - - for (int i = 5; i >= 0; i--) { - unsigned char a = _address.addr[i]; - - if (a < 0x10) { - addressStr += "0"; - } - - addressStr += String(a, 16); - - if (i > 0) { - addressStr += ":"; - } - } +void BLECentral::setEventHandler(BLERoleEvent event, BLERoleEventHandler callback) +{ + BLECentralRole::instance()->setEventHandler(event, callback); +} - strcpy(address, addressStr.c_str()); +void BLECentral::setAdvertiseHandler(ble_advertise_handle_cb_t advcb) +{ + BLECentralRole::instance()->setAdvertiseHandler(advcb); +} - return address; +void BLECentral::setScanParam(float interval, float window) +{ + bt_le_scan_param_t scan_param; + scan_param.type = BT_HCI_LE_SCAN_ACTIVE; + scan_param.filter_dup = BT_HCI_LE_SCAN_FILTER_DUP_ENABLE; + scan_param.interval = (uint16_t)MSEC_TO_UNITS(interval, UNIT_0_625_MS);; + scan_param.window = (uint16_t)MSEC_TO_UNITS(window, UNIT_0_625_MS);; + BLECentralRole::instance()->setScanParam(scan_param); } -void -BLECentral::poll() { - _peripheral->poll(); +BleStatus BLECentral::addAttribute(BLEAttribute& attribute) +{ + return BLECentralRole::instance()->addAttribute(attribute); } -bool -BLECentral::disconnect() { - if (connected()) { - return _peripheral->disconnect(); +bool BLECentral::begin(void) +{ + bool retval = BLECentralRole::instance()->begin(); + if (!retval) + { + pr_error(LOG_MODULE_BLE,"%s: Intit failed", __FUNCTION__); + return false; } - - return false; + + // Start scan + const bt_le_scan_param_t *scan_param = BLECentralRole::instance()->getScanParam(); + bt_le_scan_param_t zero_param; + memset(&zero_param, 0x00, sizeof (zero_param)); + if (0 == memcmp(&zero_param, scan_param, sizeof (zero_param))) + { + // Not set the scan parameter. + // Use the default scan parameter to scan + zero_param.type = BT_HCI_LE_SCAN_ACTIVE; + zero_param.filter_dup = BT_HCI_LE_SCAN_FILTER_DUP_ENABLE; + zero_param.interval = BT_GAP_SCAN_FAST_INTERVAL;//BT_GAP_SCAN_SLOW_INTERVAL_1;// + zero_param.window = BT_GAP_SCAN_FAST_WINDOW; //BT_GAP_SCAN_SLOW_WINDOW_1;// + retval = BLECentralRole::instance()->startScan(zero_param); + } + else + { + retval = BLECentralRole::instance()->startScan(); + } + return retval; } -void -BLECentral::setAddress(ble_addr_t address) { - _address = address; +BLEPeripheralHelper *BLECentral::getPeerPeripheralBLE(BLEHelper& peripheral) +{ + return (BLEPeripheralHelper *)(&peripheral); } -void -BLECentral::clearAddress() { - memset(&_address, 0x00, sizeof(_address)); -} + diff --git a/libraries/CurieBLE/src/BLECentral.h b/libraries/CurieBLE/src/BLECentral.h index c51250d9..09379b2b 100644 --- a/libraries/CurieBLE/src/BLECentral.h +++ b/libraries/CurieBLE/src/BLECentral.h @@ -21,50 +21,145 @@ #define _BLE_CENTRAL_H_INCLUDED #include "BLECommon.h" +#include "BLERoleBase.h" -class BLEPeripheral; +class BLEAttribute; -class BLECentral { - friend class BLEPeripheral; - - public: - /** - * Is the Central connected - * - * @return boolean_t true if the central is connected, otherwise false - */ - bool connected(void); - - /** - * Get the address of the Central in string form - * - * @return const char* address of the Central in string form - */ - const char* address(void) const; - - /** - * Disconnect the central if it is connected - * - */ - bool disconnect(void); - - /** - * Poll the central for events - */ - void poll(void); - - operator bool(void) const; - bool operator==(const BLECentral& rhs) const; - bool operator!=(const BLECentral& rhs) const; - - protected: - BLECentral(BLEPeripheral* peripheral); - void setAddress(ble_addr_t address); - void clearAddress(); - - private: - BLEPeripheral* _peripheral; - ble_addr_t _address; +/** + * @brief A class defining the BLE central function + * + * This class abstract the BLE central. + */ +class BLECentral{ +public: + /** + * @brief Start scan + * + * @param none + * + * @return bool Indicate the success or error + * + * @note none + */ + bool startScan(); + + /** + * @brief Start scan with scan parameter + * + * @param[in] interval The scan interval in ms + * + * @param[in] window The scan window in ms + * + * @return bool Indicate the success or error + * + * @note none + */ + bool startScan(float interval, float window); + + /** + * @brief Stop scan + * + * @param none + * + * @return bool Indicate the success or error + * + * @note none + */ + bool stopScan(); + + /** + * @brief Schedule a connect request to peripheral to establish a connection + * + * @param[in] addr The MAC address of peripheral device that want to establish connection + * + * @param[in] param The connetion parameters + * + * @return bool Indicate the success or error + * + * @note none + */ + bool connect(const bt_addr_le_t *addr, const ble_conn_param_t *param); + + /** + * @brief Discover the peripheral device profile + * + * @param[in] peripheral The Peripheral that need to discover the profile + * + * @return none + * + * @note none + */ + void discover(BLEPeripheralHelper &peripheral); + + /** + * @brief Set the scan parameter + * + * @param[in] interval The scan interval in ms + * + * @param[in] window The scan window in ms + * + * @return none + * + * @note 1. The scale of the interval and window are 2.5 - 10240ms + * 2. The scan interval and window are like below. + * The device can see the ADV packet in the window. + * window + * ---- ---- + * | | | | + * --- ------- ---- + * |interval| + */ + void setScanParam(float interval, float window); + + /** + * @brief Add an attribute to the BLE Central Device + * + * @param[in] attribute Attribute to add to Central + * + * @return BleStatus indicating success or error + * + * @note The attribute will used for discover the peripheral handler + * Only need check return value at first call. Memory only alloc at first call + */ + BleStatus addAttribute(BLEAttribute& attribute); + + /** + * Provide a function to be called when events related to this Device are raised + * + * @param[in] event Event type for callback + * @param[in] callback Pointer to callback function to invoke when an event occurs. + */ + void setEventHandler(BLERoleEvent event, BLERoleEventHandler callback); + + /** + * @brief Provide a function to be called when scanned the advertisement + * + * @param[in] advcb Pointer to callback function to invoke when advertisement received + * + * @return none + * + * @note none + */ + void setAdvertiseHandler(ble_advertise_handle_cb_t advcb); + + /** + * @brief Setup attributes and start scan + * + * @return bool indicating success or error + */ + bool begin(void); + + /** + * @brief Get peer peripheral device + * + *@param peripheral peer peripheral device of the central board + * + * @return pointer of peer peripheral device + */ + BLEPeripheralHelper *getPeerPeripheralBLE(BLEHelper& peripheral); +protected: +private: + }; #endif diff --git a/libraries/CurieBLE/src/BLEUuid.h b/libraries/CurieBLE/src/BLECentralHelper.cpp similarity index 58% rename from libraries/CurieBLE/src/BLEUuid.h rename to libraries/CurieBLE/src/BLECentralHelper.cpp index 39b8aff5..e48426aa 100644 --- a/libraries/CurieBLE/src/BLEUuid.h +++ b/libraries/CurieBLE/src/BLECentralHelper.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015 Intel Corporation. All rights reserved. + * Copyright (c) 2016 Intel Corporation. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -17,20 +17,35 @@ * */ -#ifndef _BLE_UUID_H_INCLUDED -#define _BLE_UUID_H_INCLUDED +#include "BLECentralHelper.h" -#include "BLECommon.h" +#include "BLEPeripheralRole.h" -class BLEUuid + +BLECentralHelper::BLECentralHelper(BLEPeripheralRole* peripheral) : + _peripheral(peripheral) { -public: - BLEUuid(const char * str); + clearAddress(); +} + +bool +BLECentralHelper::connected() { + poll(); + + return (*this && *this == _peripheral->central()); +} + +void +BLECentralHelper::poll() { + _peripheral->poll(); +} - bt_uuid uuid(void) const; +bool +BLECentralHelper::disconnect() { + if (connected()) { + return _peripheral->disconnect(); + } -private: - struct bt_uuid _uuid; -}; + return false; +} -#endif // _BLE_UUID_H_INCLUDED diff --git a/libraries/CurieBLE/src/BLECentralHelper.h b/libraries/CurieBLE/src/BLECentralHelper.h new file mode 100644 index 00000000..4a563d97 --- /dev/null +++ b/libraries/CurieBLE/src/BLECentralHelper.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2016 Intel Corporation. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef _BLE_CENTRAL_HELPER_H_INCLUDED +#define _BLE_CENTRAL_HELPER_H_INCLUDED + +#include "BLECommon.h" +#include "BLEHelper.h" + +class BLEPeripheralRole; + +class BLECentralHelper: public BLEHelper{ + friend class BLEPeripheralRole; + friend class BLECentralRole; + + public: + /** + * Is the Central connected + * + * @return boolean_t true if the central is connected, otherwise false + */ + bool connected(void); + + /** + * Disconnect the central if it is connected + * + */ + bool disconnect(void); + + /** + * Poll the central for events + */ + void poll(void); + + protected: + BLECentralHelper(BLEPeripheralRole* peripheral); + + private: + BLEPeripheralRole* _peripheral; +}; + +#endif diff --git a/libraries/CurieBLE/src/BLECentralRole.cpp b/libraries/CurieBLE/src/BLECentralRole.cpp new file mode 100644 index 00000000..011a4031 --- /dev/null +++ b/libraries/CurieBLE/src/BLECentralRole.cpp @@ -0,0 +1,298 @@ +/* + * Copyright (c) 2016 Intel Corporation. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include "BLECentralRole.h" + + +void ble_central_device_found(const bt_addr_le_t *addr, + int8_t rssi, + uint8_t type, + const uint8_t *ad, + uint8_t len) +{ + char dev[BT_ADDR_LE_STR_LEN]; + + bt_addr_le_to_str(addr, dev, sizeof(dev)); + pr_debug(LOG_MODULE_BLE, "[DEVICE]: %s, AD evt type %u, AD data len %u, RSSI %i\n", + dev, type, len, rssi); + + BLECentralRole::instance()->handleDeviceFound(addr, rssi, type, + ad, len); +} + + +BLECentralRole* BLECentralRole::_ble_central_ins = NULL; + +BLECentralRole *BLECentralRole::instance() +{ + if (NULL == _ble_central_ins) + { + _ble_central_ins = new BLECentralRole(); + } + return _ble_central_ins; +} + +BLECentralRole::BLECentralRole(): + _central(NULL), _adv_event_handle(NULL) +{ + memset(_peripherial, 0, sizeof (_peripherial)); + for (int i = 0; i < BLE_MAX_CONN_CFG; i++) + { + _peripherial[i] = new BLEPeripheralHelper(this); + } + memset (&_scan_param, 0x00, sizeof (_scan_param)); + _central.setAddress(_local_bda); +} + + +BLECentralRole::~BLECentralRole() +{ + for (int i = 0; i < BLE_MAX_CONN_CFG; i++) + { + delete (_peripherial[i]); + //_peripherial[i] = NULL; + } +} + +const BLECentralHelper *BLECentralRole::central(void) const +{ + return &_central; +} + +bool BLECentralRole::connect(const bt_addr_le_t *addr, const bt_le_conn_param_t *param) +{ + BLEPeripheralHelper* temp = NULL; + BLEPeripheralHelper* unused = NULL; + bool link_existed = false; + bool retval = false; + + // Find free peripheral Items + for (int i = 0; i < BLE_MAX_CONN_CFG; i++) + { + temp = _peripherial[i]; + if (true == *temp) + { + if (*temp == *addr) + { + // Connect request has scheduled but connection don't established. + // The central can see the ADV and no need to send connect request. + link_existed = true; + break; + } + } + else + { + if (NULL == unused) + { + unused = temp; + } + } + } + + if (!link_existed) + { + // Send connect request + bt_conn_t* conn = bt_conn_create_le(addr, param); + if (NULL != conn) + { + unused->setAddress(*addr); + retval = true; + bt_conn_unref(conn); + } + } + return retval; +} + +bool BLECentralRole::startScan() +{ + int err = bt_le_scan_start(&_scan_param, ble_central_device_found); + if (err) + { + pr_info(LOG_MODULE_BLE, "Scanning failed to start (err %d)\n", err); + return false; + } + return true; +} + +bool BLECentralRole::startScan(const bt_le_scan_param_t &scan_param) +{ + setScanParam(scan_param); + return startScan(); +} + +void BLECentralRole::setScanParam(const bt_le_scan_param_t &scan_param) +{ + memcpy(&_scan_param, &scan_param, sizeof (_scan_param)); +} + +const bt_le_scan_param_t* BLECentralRole::getScanParam() +{ + return &_scan_param; +} + + +bool BLECentralRole::stopScan() +{ + int err = bt_le_scan_stop(); + if (err) + { + pr_info(LOG_MODULE_BLE, "Stop LE scan failed (err %d)\n", err); + return false; + } + return true; +} + +BLEPeripheralHelper* BLECentralRole::peripheral(bt_conn_t *conn) +{ + BLEPeripheralHelper* temp = NULL; + const bt_addr_le_t *addr = bt_conn_get_dst(conn); + // Find free peripheral Items + for (int i = 0; i < BLE_MAX_CONN_CFG; i++) + { + temp = _peripherial[i]; + if (*temp == *addr) + { + return temp; + } + } + return NULL; +} + + +void BLECentralRole::handleDeviceFound(const bt_addr_le_t *addr, + int8_t rssi, + uint8_t type, + const uint8_t *ad, + uint8_t data_len) +{ + const uint8_t *data = ad; + + if (_adv_event_handle == NULL) + { + return; + } + + /* We're only interested in connectable events */ + if (type == BT_LE_ADV_IND || type == BT_LE_ADV_DIRECT_IND) + { + pr_debug(LOG_MODULE_BLE, "%s", __FUNCTION__); + + while (data_len > 1) + { + uint8_t len = data[0]; + + /* Check for early termination */ + if (len == 0) { + return; + } + + if ((len + 1 > data_len) || (data_len < 2)) { + pr_info(LOG_MODULE_BLE, "AD malformed\n"); + return; + } + + if (!_adv_event_handle(data[1], &data[2], len - 1, addr)) + { + return; + } + + data_len -= len + 1; + data += len + 1; + } + pr_debug(LOG_MODULE_BLE, "%s: done", __FUNCTION__); + } +} + +void BLECentralRole::handleConnectEvent(bt_conn_t *conn, uint8_t err) +{ + if (_event_handlers[BLEConnected]) + { + BLEPeripheralHelper *temp = peripheral(conn); + _event_handlers[BLEConnected](*temp); + } +} + +void BLECentralRole::handleDisconnectEvent(bt_conn_t *conn, uint8_t reason) +{ + if (_event_handlers[BLEDisconnected]) + { + BLEPeripheralHelper *temp = peripheral(conn); + _event_handlers[BLEDisconnected](*temp); + temp->linkLost(); + } +} + +void BLECentralRole::handleParamUpdated(bt_conn_t *conn, + uint16_t interval, + uint16_t latency, + uint16_t timeout) +{ + if (_event_handlers[BLEUpdateParam]) + { + BLEPeripheralHelper *temp = peripheral(conn); + temp->setConnectionParameters(interval, interval, latency, timeout); + _event_handlers[BLEUpdateParam](*temp); + } +} + +void BLECentralRole::setEventHandler(BLERoleEvent event, BLERoleEventHandler callback) +{ + + if (event < sizeof(_event_handlers)) + { + _event_handlers[event] = callback; + } +} + +void BLECentralRole::setAdvertiseHandler(ble_advertise_handle_cb_t advcb) +{ + _adv_event_handle = advcb; +} + +BleStatus BLECentralRole::addAttribute(BLEAttribute& attribute) +{ + BleStatus err = BLE_STATUS_SUCCESS; + for (int i = 0; i < BLE_MAX_CONN_CFG; i++) + { + err = _peripherial[i]->addAttribute(attribute); + if (err != BLE_STATUS_SUCCESS) + { + break; + } + } + return err; +} + +bool BLECentralRole::begin() +{ + BleStatus status; + status = _init(); + if (status != BLE_STATUS_SUCCESS) + { + return false; + } + return true; +} + +bool BLECentralRole::disconnect() +{ + return true; +} + + diff --git a/libraries/CurieBLE/src/BLECentralRole.h b/libraries/CurieBLE/src/BLECentralRole.h new file mode 100644 index 00000000..0ea6c008 --- /dev/null +++ b/libraries/CurieBLE/src/BLECentralRole.h @@ -0,0 +1,276 @@ +/* + * Copyright (c) 2016 Intel Corporation. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef _BLE_CENTRALROLE_H_INCLUDED +#define _BLE_CENTRALROLE_H_INCLUDED +#include "BLECommon.h" +#include "BLEPeripheralHelper.h" +#include "BLECentralHelper.h" +#include "BLERoleBase.h" + +class BLECentralRole: public BLERoleBase { +public: + /** + * @brief Start scan + * + * @param none + * + * @return bool Indicate the success or error + * + * @note none + */ + bool startScan(); + + /** + * @brief Start scan with scan parameter + * + * @param none + * + * @return bool Indicate the success or error + * + * @note none + */ + bool startScan(const bt_le_scan_param_t &scan_param); + + /** + * @brief Stop scan + * + * @param none + * + * @return bool Indicate the success or error + * + * @note none + */ + bool stopScan(); + + /** + * @brief Schedule a connect request to peripheral to establish a connection + * + * @param[in] addr The MAC address of peripheral device that want to establish connection + * + * @param[in] param The connetion parameters + * + * @return bool Indicate the success or error + * + * @note none + */ + bool connect(const bt_addr_le_t *addr, const bt_le_conn_param_t *param); + + /** + * @brief Set the scan parameter + * + * @param[in] scan_param The scan parameter want to be set + * + * @return none + * + * @note none + */ + void setScanParam(const bt_le_scan_param_t &scan_param); + + /** + * @brief Get the scan parameter + * + * @param none + * + * @return const bt_le_scan_param_t* The scan parameter that current used + * + * @note none + */ + const bt_le_scan_param_t* getScanParam(); + + /** + * @brief Discover the peripheral device profile + * + * @param peripheral The Peripheral that need to discover the profile + * + * @return none + * + * @note none + */ + void discover(BLEPeripheralHelper &peripheral); + + /** + * @brief Add an attribute to the BLE Central Device + * + * @param[in] attribute Attribute to add to Central + * + * @return BleStatus indicating success or error + * + * @note The attribute will used for discover the peripheral handler + */ + BleStatus addAttribute(BLEAttribute& attribute); + + /** + * @brief Provide a function to be called when events related to this Device are raised + * + * @param[in] event Event type for callback + * @param[in] callback Pointer to callback function to invoke when an event occurs. + */ + void setEventHandler(BLERoleEvent event, BLERoleEventHandler callback); + + /** + * @brief Provide a function to be called when scanned the advertisement + * + * @param[in] advcb Pointer to callback function to invoke when advertisement received + * + * @return none + * + * @note none + */ + void setAdvertiseHandler(ble_advertise_handle_cb_t advcb); + + /** + * @brief Get BLE peripheral helper by conntion + * + * @param[in] conn The connection object + * + * @return BLEPeripheralHelper* The BLE peripheral helper + * + * @note none + */ + BLEPeripheralHelper* peripheral(bt_conn_t *conn); + + /** + * @brief Get BLE central helper that for APP use + * + * @param none + * + * @return const BLECentralHelper * The BLE central helper + * + * @note none + */ + const BLECentralHelper *central(void) const; + + /** + * Setup attributes and start advertising + * + * @return bool indicating success or error + */ + bool begin(); + + /** + * @brief Disconnect the central connected if there is one connected + * + * @param none + * + * @return bool Indicating success or error + * + * @note none + */ + bool disconnect(); + + /** + * @brief Get BLE Central instance. + * + * @param none + * + * @return BLECentralRole* The BLE Central instance + * + * @note Singleton. Only have one object to communicate with + * stack and manage the device + */ + static BLECentralRole *instance(); + +protected: + friend void ble_central_device_found(const bt_addr_le_t *addr, + int8_t rssi, + uint8_t type, + const uint8_t *ad, + uint8_t len); + + /** + * @brief Handle the connected event + * + * @param[in] conn The object that established the connection + * + * @param[in] err The code of the process + * + * @return none + * + * @note none + */ + void handleConnectEvent(bt_conn_t *conn, uint8_t err); + + /** + * @brief Handle the disconnected event + * + * @param[in] conn The object that lost the connection + * + * @param[in] reason The link lost reason + * + * @return none + * + * @note none + */ + void handleDisconnectEvent(bt_conn_t *conn, uint8_t reason); + + /** + * @brief Handle the conntion update request + * + * @param[in] conn The connection object that need to process the update request + * + * @param[in] interval The connection interval (N*1.25)ms + * + * @param[in] latency The connection latency + * + * @param[in] timeout The connection timeout (N*10)ms + * + * @return none + * + * @note none + */ + void handleParamUpdated(bt_conn_t *conn, + uint16_t interval, + uint16_t latency, + uint16_t timeout); + /** + * @brief Handle the advertisement + * + * @param[in] addr The device's MAC address that send out ADV + * + * @param[in] rssi The antenna's RSSI + * + * @param[in] type The advertise type + * + * @param[in] ad The advertisement RAW data + * + * @param[in] len The RAW data's length + * + * @return none + * + * @note none + */ + void handleDeviceFound(const bt_addr_le_t *addr, + int8_t rssi, + uint8_t type, + const uint8_t *ad, + uint8_t len); +private: + BLECentralRole(); + ~BLECentralRole(); + BLEPeripheralHelper* _peripherial[BLE_MAX_CONN_CFG]; + BLECentralHelper _central; + bt_le_scan_param_t _scan_param; + + static BLECentralRole* _ble_central_ins; + ble_advertise_handle_cb_t _adv_event_handle; +}; + +#endif + diff --git a/libraries/CurieBLE/src/BLECharacteristic.cpp b/libraries/CurieBLE/src/BLECharacteristic.cpp index a6c46c07..3e46e0a1 100644 --- a/libraries/CurieBLE/src/BLECharacteristic.cpp +++ b/libraries/CurieBLE/src/BLECharacteristic.cpp @@ -18,28 +18,80 @@ */ #include "BLECharacteristic.h" +#include "BLEPeripheralHelper.h" #include "internal/ble_client.h" -#define BLE_CCCD_NOTIFY_EN_MASK 0x1 -#define BLE_CCCD_INDICATE_EN_MASK 0x2 +uint8_t profile_notify_process (bt_conn_t *conn, + bt_gatt_subscribe_params_t *params, + const void *data, uint16_t length); +uint8_t profile_read_rsp_process(bt_conn_t *conn, int err, + bt_gatt_read_params_t *params, + const void *data, + uint16_t length); + +unsigned char BLECharacteristic::_numNotifyAttributes = 0; + +bt_uuid_16_t BLECharacteristic::_gatt_chrc_uuid = {BT_UUID_TYPE_16, BT_UUID_GATT_CHRC_VAL}; +bt_uuid_16_t BLECharacteristic::_gatt_ccc_uuid = {BT_UUID_TYPE_16, BT_UUID_GATT_CCC_VAL}; BLECharacteristic::BLECharacteristic(const char* uuid, const unsigned char properties, const unsigned short maxLength) : BLEAttribute(uuid, BLETypeCharacteristic), - _properties(properties), _value_length(0), + _value_buffer(NULL), _written(false), - _cccd_value(0), - _value_handle(0), - _cccd_handle(0), _user_description(NULL), - _presentation_format(NULL) + _presentation_format(NULL), + _attr_chrc_declaration(NULL), + _attr_chrc_value(NULL), + _attr_cccd(NULL) { - _value_size = maxLength > BLE_MAX_ATTR_DATA_LEN ? BLE_MAX_ATTR_DATA_LEN : maxLength; + _value_size = maxLength > BLE_MAX_ATTR_LONGDATA_LEN ? BLE_MAX_ATTR_LONGDATA_LEN : maxLength; _value = (unsigned char*)malloc(_value_size); - + if (_value_size > BLE_MAX_ATTR_DATA_LEN) + { + _value_buffer = (unsigned char*)malloc(_value_size); + } + + memset(&_ccc_cfg, 0, sizeof(_ccc_cfg)); + memset(&_ccc_value, 0, sizeof(_ccc_value)); + memset(&_gatt_chrc, 0, sizeof(_gatt_chrc)); + memset(&_sub_params, 0, sizeof(_sub_params)); + + _ccc_value.cfg = &_ccc_cfg; + _ccc_value.cfg_len = 1; + if (BLERead & properties) + { + _gatt_chrc.properties |= BT_GATT_CHRC_READ; + } + if (BLEWrite & properties) + { + _gatt_chrc.properties |= BT_GATT_CHRC_WRITE; + } + if (BLEWriteWithoutResponse & properties) + { + _gatt_chrc.properties |= BT_GATT_CHRC_WRITE_WITHOUT_RESP; + } + if (BLENotify & properties) + { + _gatt_chrc.properties |= BT_GATT_CHRC_NOTIFY; + _sub_params.value |= BT_GATT_CCC_NOTIFY; + } + if (BLEIndicate & properties) + { + _gatt_chrc.properties |= BT_GATT_CHRC_INDICATE; + _sub_params.value |= BT_GATT_CCC_INDICATE; + } + _gatt_chrc.uuid = this->uuid(); memset(_event_handlers, 0, sizeof(_event_handlers)); + + _numNotifyAttributes++; + if (properties & (BT_GATT_CHRC_NOTIFY | BT_GATT_CHRC_INDICATE)) + { + _numNotifyAttributes++; + } + _sub_params.notify = profile_notify_process; } BLECharacteristic::BLECharacteristic(const char* uuid, @@ -61,44 +113,40 @@ BLECharacteristic::~BLECharacteristic() unsigned char BLECharacteristic::properties() const { - return _properties; + return _gatt_chrc.properties; } bool BLECharacteristic::setValue(const unsigned char value[], uint16_t length) { - BleStatus status; + int status; _setValue(value, length); - if (_value_handle) { - status = ble_client_gatts_set_attribute_value(_value_handle, _value_length, _value, 0); - if (BLE_STATUS_SUCCESS != status) { + if (_attr_chrc_value) + { + // TODO: Notify for peripheral. + // Write request for central. + status = bt_gatt_notify(NULL, _attr_chrc_value, value, length, NULL); + if (0 != status) + { return false; } - - if (subscribed()) { - boolean_t indication = (_cccd_value & BLE_CCCD_INDICATE_EN_MASK); - - status = ble_client_gatts_send_notif_ind(_value_handle, _value_length, _value, 0, indication); - if (BLE_STATUS_SUCCESS != status) { - return false; - } - } } - return true; } void -BLECharacteristic::setValue(BLECentral& central, const unsigned char* value, unsigned short length) +BLECharacteristic::setValue(BLEHelper& blehelper, const unsigned char* value, unsigned short length) { + //BLEHelper *bledevice = ¢ral; _setValue(value, length); _written = true; + _reading = false; if (_event_handlers[BLEWritten]) { - _event_handlers[BLEWritten](central, *this); + _event_handlers[BLEWritten](blehelper, *this); } } @@ -139,7 +187,7 @@ BLECharacteristic::written() bool BLECharacteristic::subscribed() { - return (_cccd_value & (BLE_CCCD_NOTIFY_EN_MASK | BLE_CCCD_INDICATE_EN_MASK)); + return (_gatt_chrc.properties & (BT_GATT_CHRC_NOTIFY | BT_GATT_CHRC_INDICATE)); } void @@ -152,114 +200,240 @@ BLECharacteristic::setEventHandler(BLECharacteristicEvent event, BLECharacterist interrupts(); } -bool -BLECharacteristic::add(uint16_t serviceHandle) +uint16_t +BLECharacteristic::valueHandle() { - bt_uuid uuid = btUuid(); + uint16_t handle = 0; + if (NULL != _attr_chrc_value) + { + handle = _attr_chrc_value->handle; + } + + return handle; +} - struct ble_gatts_characteristic char_data; - struct ble_gatts_char_handles handles; - struct ble_gatt_char_user_desc user_desc; - struct ble_gatt_pf_desc pf_desc; +uint16_t +BLECharacteristic::cccdHandle() +{ + uint16_t handle = 0; + if (NULL != _attr_cccd) + { + handle = _attr_cccd->handle; + } + return handle; +} - memset(&char_data, 0, sizeof(char_data)); +void +BLECharacteristic::setUserDescription(BLEDescriptor *descriptor) +{ + _user_description = descriptor; +} - char_data.p_uuid = &uuid; - char_data.props.props = _properties; +void +BLECharacteristic::setPresentationFormat(BLEDescriptor *descriptor) +{ + _presentation_format = descriptor; +} - if (_properties & (BLERead | BLENotify | BLEIndicate)) { - char_data.perms.rd = GAP_SEC_MODE_1 | GAP_SEC_LEVEL_1; - } else { - char_data.perms.rd = GAP_SEC_NO_PERMISSION; +void +BLECharacteristic::_setValue(const uint8_t value[], uint16_t length) +{ + if (length > _value_size) { + length = _value_size; } - if (_properties & (BLEWriteWithoutResponse | BLEWrite)) { - char_data.perms.wr = GAP_SEC_MODE_1 | GAP_SEC_LEVEL_1; - } else { - char_data.perms.wr = GAP_SEC_NO_PERMISSION; - } + memcpy(_value, value, length); + _value_length = length; +} - char_data.init_len = _value_length; - char_data.max_len = _value_size; - char_data.p_value = _value; +unsigned char +BLECharacteristic::numNotifyAttributes(void) { + return _numNotifyAttributes; +} - if (_user_description) { - user_desc.buffer = (uint8_t*)_user_description->value(); - user_desc.len = _user_description->valueLength(); +_bt_gatt_ccc_t* BLECharacteristic::getCccCfg(void) +{ + return &_ccc_value; +} - char_data.p_user_desc = &user_desc; - } +bt_gatt_chrc_t* BLECharacteristic::getCharacteristicAttValue(void) +{ + return &_gatt_chrc; +} - if (_presentation_format) { - const uint8_t* pfValue = _presentation_format->value(); +uint8_t BLECharacteristic::getPermission(void) +{ + uint8_t perm = 0; + if (_gatt_chrc.properties & BT_GATT_CHRC_READ) + { + perm |= BT_GATT_PERM_READ; + } + if (_gatt_chrc.properties & (BT_GATT_CHRC_WRITE | BT_GATT_CHRC_WRITE_WITHOUT_RESP)) + { + perm |= BT_GATT_PERM_WRITE; + } + return perm; +} - pf_desc.format = pfValue[0]; - pf_desc.exp = pfValue[1]; - pf_desc.unit = (pfValue[3] << 8) | pfValue[2]; - pf_desc.name_spc = pfValue[4]; - pf_desc.descr = (pfValue[6] << 8) | pfValue[5]; +bt_uuid_t* BLECharacteristic::getCharacteristicAttributeUuid(void) +{ + return (bt_uuid_t*) &_gatt_chrc_uuid; +} +bt_uuid_t* BLECharacteristic::getClientCharacteristicConfigUuid(void) +{ + return (bt_uuid_t*) &_gatt_ccc_uuid; +} - char_data.p_char_pf_desc = &pf_desc; - } - BleStatus status = ble_client_gatts_add_characteristic(serviceHandle, &char_data, &handles); - if (BLE_STATUS_SUCCESS == status) { - _value_handle = handles.value_handle; - _cccd_handle = handles.cccd_handle; - } +void BLECharacteristic::addCharacteristicDeclaration(bt_gatt_attr_t *gatt_attr) +{ + _attr_chrc_declaration = gatt_attr; +} - return (BLE_STATUS_SUCCESS == status); +void BLECharacteristic::addCharacteristicValue(bt_gatt_attr_t *gatt_attr) +{ + _attr_chrc_value = gatt_attr; } -uint16_t -BLECharacteristic::valueHandle() +void BLECharacteristic::addCharacteristicConfigDescriptor(bt_gatt_attr_t *gatt_attr) { - return _value_handle; + _attr_cccd = gatt_attr; } -uint16_t -BLECharacteristic::cccdHandle() +void BLECharacteristic::discover(bt_gatt_discover_params_t *params) { - return _cccd_handle; + params->type = BT_GATT_DISCOVER_CHARACTERISTIC; + params->uuid = this->uuid(); + // Start discovering + _discoverying = true; + // Re-Init the read/write parameter + _reading = false; } -void -BLECharacteristic::setCccdValue(BLECentral& central, uint16_t value) -{ - if (_cccd_value != value) { - _cccd_value = value; - - if (subscribed()) { - if (_event_handlers[BLESubscribed]) { - _event_handlers[BLESubscribed](central, *this); - } - } else { - if (_event_handlers[BLEUnsubscribed]) { - _event_handlers[BLEUnsubscribed](central, *this); - } + +void BLECharacteristic::discover(const bt_gatt_attr_t *attr, + bt_gatt_discover_params_t *params) +{ + if (!attr) + { + // Discovery complete + _discoverying = false; + return; + } + + // Chracteristic Char + if (params->uuid == this->uuid()) + { + // Set Discover CCCD parameter + params->start_handle = attr->handle + 2; + if (subscribed()) + { + // Include CCCD + params->type = BT_GATT_DISCOVER_DESCRIPTOR; + params->uuid = this->getClientCharacteristicConfigUuid(); + } + else + { + // Complete the discover + _discoverying = false; } } + else if (params->uuid == this->getClientCharacteristicConfigUuid()) + { + params->start_handle = attr->handle + 1; + _discoverying = false; + } } -void -BLECharacteristic::setUserDescription(BLEDescriptor *descriptor) +bt_gatt_subscribe_params_t *BLECharacteristic::getSubscribeParams() { - _user_description = descriptor; + return &_sub_params; } -void -BLECharacteristic::setPresentationFormat(BLEDescriptor *descriptor) +bool BLECharacteristic::read(BLEPeripheralHelper &peripheral) { - _presentation_format = descriptor; + int retval = 0; + bt_conn_t* conn = NULL; + if (_reading) + { + // Already in reading state + return false; + } + + _read_params.func = profile_read_rsp_process; + _read_params.handle_count = 1; + _read_params.single.handle = peripheral.valueHandle(this); + _read_params.single.offset = 0; + + if (0 == _read_params.single.handle) + { + // Discover not complete + return false; + } + + conn = bt_conn_lookup_addr_le(peripheral.bt_le_address()); + if (NULL == conn) + { + return false; + } + + // Send read request + retval = bt_gatt_read(conn, &_read_params); + bt_conn_unref(conn); + if (0 == retval) + { + _reading = true; + } + return _reading; } -void -BLECharacteristic::_setValue(const uint8_t value[], uint16_t length) +bool BLECharacteristic::write(BLEPeripheralHelper &peripheral, + const unsigned char value[], + uint16_t length) { - if (length > _value_size) { - length = _value_size; + int retval = 0; + bt_conn_t* conn = NULL; + + conn = bt_conn_lookup_addr_le(peripheral.bt_le_address()); + if (NULL == conn) + { + return false; } + + // Send read request + retval = bt_gatt_write_without_response(conn, + peripheral.valueHandle(this), + value, length, false); + bt_conn_unref(conn); + return (0 == retval); +} - memcpy(_value, value, length); - _value_length = length; +void BLECharacteristic::setBuffer(BLEHelper& blehelper, + const uint8_t value[], + uint16_t length, + uint16_t offset) +{ + if (length + offset > _value_size) { + // Ignore the data + return; + } + + memcpy(_value_buffer + offset, value, length); } + +void BLECharacteristic::syncupBuffer2Value(BLEHelper& blehelper) +{ + setValue(blehelper, _value_buffer, _value_size); +} + +void BLECharacteristic::discardBuffer() +{ + memcpy(_value_buffer, _value, _value_size); +} + +bool BLECharacteristic::longCharacteristic() +{ + return (_value_size > BLE_MAX_ATTR_DATA_LEN); +} + + diff --git a/libraries/CurieBLE/src/BLECharacteristic.h b/libraries/CurieBLE/src/BLECharacteristic.h index a5afaa36..58274f67 100644 --- a/libraries/CurieBLE/src/BLECharacteristic.h +++ b/libraries/CurieBLE/src/BLECharacteristic.h @@ -20,8 +20,10 @@ #ifndef _BLE_CHARACTERISTIC_H_INCLUDED #define _BLE_CHARACTERISTIC_H_INCLUDED +#include "BLECommon.h" + #include "BLEAttribute.h" -#include "BLECentral.h" +#include "BLECentralHelper.h" #include "BLEDescriptor.h" /** @@ -38,9 +40,10 @@ enum BLECharacteristicEvent { /* Forward declaration needed for callback function prototype below */ class BLECharacteristic; class BLEPeripheral; +class BLEHelper; /** Function prototype for BLE Characteristic event callback */ -typedef void (*BLECharacteristicEventHandler)(BLECentral ¢ral, BLECharacteristic &characteristic); +typedef void (*BLECharacteristicEventHandler)(BLEHelper &bleHelper, BLECharacteristic &characteristic); /** * BLE Characteristic Property types @@ -62,9 +65,9 @@ class BLECharacteristic : public BLEAttribute { /** * Constructor for BLE Characteristic * - * @param uuid 16-bit or 128-bit UUID (in string form) defined by BLE standard - * @param properties Characteristic property mask - * @param maxLength Maximum data length required for characteristic value (<= BLE_MAX_ATTR_DATA_LEN) + * @param[in] uuid 16-bit or 128-bit UUID (in string form) defined by BLE standard + * @param[in] properties Characteristic property mask + * @param[in] maxLength Maximum data length required for characteristic value (<= BLE_MAX_ATTR_DATA_LEN) */ BLECharacteristic(const char* uuid, const unsigned char properties, @@ -73,9 +76,9 @@ class BLECharacteristic : public BLEAttribute { /** * Constructor for BLE Characteristic * - * @param uuid 16-bit or 128-bit UUID (in string form) defined by BLE standard - * @param properties Characteristic property mask - * @param value String value for characteristic (string length (<= BLE_MAX_ATTR_DATA_LEN)) + * @param[in] uuid 16-bit or 128-bit UUID (in string form) defined by BLE standard + * @param[in] properties Characteristic property mask + * @param[in] value String value for characteristic (string length (<= BLE_MAX_ATTR_DATA_LEN)) */ BLECharacteristic(const char* uuid, const unsigned char properties, @@ -86,14 +89,26 @@ class BLECharacteristic : public BLEAttribute { /** * Set the current value of the Characteristic * - * @param value New value to set, as a byte array. Data is stored in internal copy. - * @param length Length, in bytes, of valid data in the array to write. + * @param[in] value New value to set, as a byte array. Data is stored in internal copy. + * @param[in] length Length, in bytes, of valid data in the array to write. * Must not exceed maxLength set for this characteristic. * * @return bool true set value success, false on error */ bool setValue(const unsigned char value[], unsigned short length); + /** + * Set the current value of the Characteristic + * + * @param[in] central The central device that update the value. + * @param[in] value New value to set, as a byte array. Data is stored in internal copy. + * @param[in] length Length, in bytes, of valid data in the array to write. + * Must not exceed maxLength set for this characteristic. + * + * @return bool true set value success, false on error + */ + void setValue(BLEHelper& blehelper, const uint8_t value[], uint16_t length); + /** * Get the property mask of the Characteristic * @@ -141,43 +156,183 @@ class BLECharacteristic : public BLEAttribute { /** * Provide a function to be called when events related to this Characteristic are raised * - * @param event Event type to set event handler for - * @param callback Pointer to callback function to invoke when the event occurs. + * @param[in] event Event type to set event handler for + * @param[in] callback Pointer to callback function to invoke when the event occurs. */ void setEventHandler(BLECharacteristicEvent event, BLECharacteristicEventHandler callback); -protected: - bool add(uint16_t serviceHandle); + /** + * @brief Get Notify Attribute counter that created + * + * @param none + * + * @return unsigned char The totla number of the notify attributes + * + * @note none + */ + static unsigned char numNotifyAttributes(void); + + /** + * @brief Schedule the read request to read the characteristic in peripheral + * + * @param[in] peripheral The peripheral device that want to read. + * + * @return bool Indicate the success or error + * + * @note Only for central device + */ + bool read(BLEPeripheralHelper &peripheral); + + /** + * @brief Schedule the write request to update the characteristic in peripheral + * + * @param[in] peripheral The peripheral device that want to be updated + * @param[in] value New value to set, as a byte array. Data is stored in internal copy. + * @param[in] length Length, in bytes, of valid data in the array to write. + * Must not exceed maxLength set for this characteristic. + * + * @return bool true set value success, false on error + * + * @note none + */ + bool write(BLEPeripheralHelper &peripheral, + const unsigned char value[], + uint16_t length); +protected: + friend class BLEProfile; + friend int profile_longflush_process(struct bt_conn *conn, + const struct bt_gatt_attr *attr, + uint8_t flags); + friend ssize_t profile_longwrite_process(struct bt_conn *conn, + const struct bt_gatt_attr *attr, + const void *buf, uint16_t len, + uint16_t offset); + + void addCharacteristicDeclaration(bt_gatt_attr_t *gatt_attr); + void addCharacteristicValue(bt_gatt_attr_t *gatt_attr); + void addCharacteristicConfigDescriptor(bt_gatt_attr_t *gatt_attr); + + bool longCharacteristic(); + + void setBuffer(BLEHelper& blehelper, + const uint8_t value[], + uint16_t length, + uint16_t offset); + void discardBuffer(); + void syncupBuffer2Value(BLEHelper& blehelper); + + /** + * @brief Get the characteristic value handle + * + * @param none + * + * @return none + * + * @note Only for peripheral + */ uint16_t valueHandle(void); - + + /** + * @brief Get characteristic configuration descriptor value handle + * + * @param none + * + * @return uint16_t The value handle + * 0 is invalid handle + * + * @note Only for peripheral + */ uint16_t cccdHandle(void); - void setValue(BLECentral& central, const uint8_t value[], uint16_t length); - void setCccdValue(BLECentral& central, uint16_t value); - + void setUserDescription(BLEDescriptor *descriptor); void setPresentationFormat(BLEDescriptor *descriptor); - - friend class BLEPeripheral; + + _bt_gatt_ccc_t* getCccCfg(void); + bt_gatt_chrc_t* getCharacteristicAttValue(void); + static bt_uuid_t* getCharacteristicAttributeUuid(void); + static bt_uuid_t* getClientCharacteristicConfigUuid(void); + + /** + * @brief Get the characteristic permission + * + * @param none + * + * @return uint8_t The characteristic permission + * + * @note none + */ + uint8_t getPermission(void); + + /** + * @brief For central to discover the peripherial profile + * + * @param[in] attr The discover response + * + * @param[in] params The discover parameter that need to fill + * + * @return none + * + * @note Only for central + */ + void discover(const bt_gatt_attr_t *attr, + bt_gatt_discover_params_t *params); + + /** + * @brief For central to discover the peripherial profile + * + * @param[in] params The discover parameter that need to fill + * + * @return none + * + * @note Only for central + */ + void discover(bt_gatt_discover_params_t *params); + + /** + * @brief Get the subscribe parameter + * + * @param none + * + * @return bt_gatt_subscribe_params_t * the subscribe parameter + * + * @note Only for central + */ + bt_gatt_subscribe_params_t* getSubscribeParams(); private: void _setValue(const uint8_t value[], uint16_t length); private: - unsigned char _properties; + + static unsigned char _numNotifyAttributes; + static bt_uuid_16_t _gatt_chrc_uuid; + static bt_uuid_16_t _gatt_ccc_uuid; + unsigned short _value_size; unsigned short _value_length; unsigned char* _value; + unsigned char* _value_buffer; bool _written; - uint16_t _cccd_value; uint16_t _value_handle; - uint16_t _cccd_handle; + bt_gatt_ccc_cfg_t _ccc_cfg; + _bt_gatt_ccc_t _ccc_value; + bt_gatt_chrc_t _gatt_chrc; BLEDescriptor* _user_description; BLEDescriptor* _presentation_format; + bt_gatt_attr_t *_attr_chrc_declaration; + bt_gatt_attr_t *_attr_chrc_value; + bt_gatt_attr_t *_attr_cccd; + + // For central device to subscribe the Notification/Indication + bt_gatt_subscribe_params_t _sub_params; + + bool _reading; + bt_gatt_read_params_t _read_params; BLECharacteristicEventHandler _event_handlers[BLECharacteristicEventLast]; }; diff --git a/libraries/CurieBLE/src/BLECommon.h b/libraries/CurieBLE/src/BLECommon.h index 20bf0e23..9c26bad3 100644 --- a/libraries/CurieBLE/src/BLECommon.h +++ b/libraries/CurieBLE/src/BLECommon.h @@ -22,15 +22,29 @@ #include "Arduino.h" -#include "../src/services/ble/ble_protocol.h" -#include "services/ble/ble_service_gatt.h" -#include "services/ble/ble_service_gatts_api.h" +#include "../src/services/ble_service/ble_protocol.h" + + +#include "infra/log.h" + + +#include +#include +#include +#include + +#define BLE_ADDR_LEN 6 + +#define UUID_SIZE_128 16 +#define UUID_SIZE_16 2 +#define MAX_UUID_SIZE UUID_SIZE_128 /* Theoretically we should be able to support attribute lengths up to 512 bytes * but this involves splitting it across multiple packets. For simplicity, * we will just limit this to 20 bytes for now, which will fit in a single packet */ -#define BLE_MAX_ATTR_DATA_LEN 20 +#define BLE_MAX_ATTR_DATA_LEN 20 +#define BLE_MAX_ATTR_LONGDATA_LEN 512 /* Default device name prefix, applied only if user does not provide a name * If a factory-configured MAC address is defined, the last 2 bytes of the @@ -40,6 +54,61 @@ /* Invalid BLE Address type */ #define BLE_DEVICE_ADDR_INVALID 0xFF +/** BLE response/event status codes. */ +enum BLE_STATUS { + BLE_STATUS_SUCCESS = 0, /**< General BLE Success code */ + BLE_STATUS_PENDING, /**< Request received and execution started, response pending */ + BLE_STATUS_TIMEOUT, /**< Request timed out */ + BLE_STATUS_NOT_SUPPORTED, /**< Request/feature/parameter not supported */ + BLE_STATUS_NOT_ALLOWED, /**< Request not allowed */ + BLE_STATUS_LINK_TIMEOUT, /**< Link timeout (link loss) */ + BLE_STATUS_NOT_ENABLED, /**< BLE not enabled, @ref ble_enable */ + BLE_STATUS_ERROR, /**< Generic Error */ + BLE_STATUS_ALREADY_REGISTERED, /**< BLE service already registered */ + BLE_STATUS_WRONG_STATE, /**< Wrong state for request */ + BLE_STATUS_ERROR_PARAMETER, /**< Parameter in request is wrong */ + BLE_STATUS_NO_MEMORY, /**< System doesn't have memory */ + BLE_STATUS_GAP_BASE = 0x100, /**< GAP specific error base */ + BLE_STATUS_GATT_BASE = 0x200, /**< GATT specific Error base */ +}; + +typedef uint16_t ble_status_t; /**< Response and event BLE service status type @ref BLE_STATUS */ + typedef ble_status_t BleStatus; +#define BLE_MAX_CONN_CFG 2 + +typedef bool (*ble_advertise_handle_cb_t)(uint8_t type, const uint8_t *dataPtr, + uint8_t data_len, const bt_addr_le_t *addrPtr); + + +typedef struct ble_conn_param { + float interval_min; // millisecond 7.5 - 4000ms + float interval_max; // millisecond 7.5 - 4000ms + uint16_t latency; // 0x0000 - 0x01F4 + uint16_t timeout; // millisecond 100 - 32000ms +}ble_conn_param_t; +#ifdef __cplusplus +extern "C" { +#endif + +/// Define the structure for app +typedef struct bt_uuid bt_uuid_t; +typedef struct bt_uuid_16 bt_uuid_16_t; +typedef struct bt_uuid_128 bt_uuid_128_t; +typedef struct bt_conn bt_conn_t; +typedef struct bt_gatt_attr bt_gatt_attr_t; +typedef struct bt_gatt_discover_params bt_gatt_discover_params_t; +typedef struct bt_le_scan_param bt_le_scan_param_t; +typedef struct bt_le_conn_param bt_le_conn_param_t; +typedef struct bt_gatt_subscribe_params bt_gatt_subscribe_params_t; +typedef struct bt_gatt_read_params bt_gatt_read_params_t; +typedef struct _bt_gatt_ccc _bt_gatt_ccc_t; +typedef struct bt_gatt_chrc bt_gatt_chrc_t; +typedef struct bt_gatt_ccc_cfg bt_gatt_ccc_cfg_t; +typedef struct bt_data bt_data_t; + +#ifdef __cplusplus +} +#endif #endif // _BLE_COMMON_H_INCLUDED diff --git a/libraries/CurieBLE/src/BLEDescriptor.cpp b/libraries/CurieBLE/src/BLEDescriptor.cpp index 8e50120b..889cd58d 100644 --- a/libraries/CurieBLE/src/BLEDescriptor.cpp +++ b/libraries/CurieBLE/src/BLEDescriptor.cpp @@ -46,7 +46,7 @@ BLEDescriptor::BLEDescriptor(const char* uuid, const char* value) : } const unsigned char* -BLEDescriptor::BLEDescriptor::value() const +BLEDescriptor::value() const { return _value; } @@ -63,23 +63,34 @@ BLEDescriptor::operator[] (int offset) const return _value[offset]; } -bool -BLEDescriptor::add(uint16_t serviceHandle) +void BLEDescriptor::discover(const bt_gatt_attr_t *attr, + bt_gatt_discover_params_t *params) { - bt_uuid uuid = btUuid(); - struct ble_gatts_descriptor desc; - uint16_t handle = 0; + if (!attr) + { + // Discovery complete + _discoverying = false; + return; + } + + // Chracteristic Char + if (params->uuid == this->uuid()) + { + // Set Discover CCCD parameter + params->start_handle = attr->handle + 1; + // Complete the discover + _discoverying = false; + } - memset(&desc, 0, sizeof(desc)); +} - desc.p_uuid = &uuid; - desc.p_value = _value; - desc.length = _value_length; +void BLEDescriptor::discover(bt_gatt_discover_params_t *params) +{ + params->type = BT_GATT_DISCOVER_DESCRIPTOR; + params->uuid = this->uuid(); + // Start discovering + _discoverying = true; +} - // this class only supports read-only descriptors - desc.perms.rd = GAP_SEC_MODE_1 | GAP_SEC_LEVEL_1; - desc.perms.wr = GAP_SEC_NO_PERMISSION; - return (ble_client_gatts_add_descriptor(serviceHandle, &desc, &handle) == BLE_STATUS_SUCCESS); -} diff --git a/libraries/CurieBLE/src/BLEDescriptor.h b/libraries/CurieBLE/src/BLEDescriptor.h index 08e53f13..95f75ed5 100644 --- a/libraries/CurieBLE/src/BLEDescriptor.h +++ b/libraries/CurieBLE/src/BLEDescriptor.h @@ -30,9 +30,9 @@ class BLEDescriptor : public BLEAttribute { /** * Constructor for BLE Descriptor * - * @param uuid 16-bit UUID (in string form) defined by BLE standard - * @param value Value of descriptor, as a byte array. Data is stored in internal copy. - * @param valueLength Data length required for descriptor value (<= BLE_MAX_ATTR_DATA_LEN) + * @param[in] uuid 16-bit UUID (in string form) defined by BLE standard + * @param[in] value Value of descriptor, as a byte array. Data is stored in internal copy. + * @param[in] valueLength Data length required for descriptor value (<= BLE_MAX_ATTR_DATA_LEN) */ BLEDescriptor(const char* uuid, const unsigned char value[], unsigned short valueLength); @@ -41,8 +41,8 @@ class BLEDescriptor : public BLEAttribute { /** * Constructor for BLE Descriptor * - * @param uuid 16-bit UUID (in string form) defined by BLE standard - * @param value String value of descriptor. Data is stored in internal copy. + * @param[in] uuid 16-bit UUID (in string form) defined by BLE standard + * @param[in] value String value of descriptor. Data is stored in internal copy. * (String length <= BLE_MAX_ATTR_DATA_LEN) */ BLEDescriptor(const char* uuid, const char* value); @@ -62,10 +62,35 @@ class BLEDescriptor : public BLEAttribute { unsigned short valueLength(void) const; + /** + * @brief For central to discover the peripherial profile + * + * @param[in] attr The discover response + * + * @param[in] params The discover parameter that need to fill + * + * @return none + * + * @note Only for central + */ + void discover(const bt_gatt_attr_t *attr, + bt_gatt_discover_params_t *params); + + /** + * @brief For central to discover the peripherial profile + * + * @param[in] params The discover parameter that need to fill + * + * @return none + * + * @note Only for central + */ + void discover(bt_gatt_discover_params_t *params); + + unsigned char operator[] (int offset) const; protected: - bool add(uint16_t serviceHandle); friend BLEPeripheral; diff --git a/libraries/CurieBLE/src/BLEHelper.cpp b/libraries/CurieBLE/src/BLEHelper.cpp new file mode 100644 index 00000000..e3e1caa6 --- /dev/null +++ b/libraries/CurieBLE/src/BLEHelper.cpp @@ -0,0 +1,160 @@ + +#include "BLECentralHelper.h" + +#include "BLEPeripheral.h" + + +BLEHelper::BLEHelper() +{ + clearAddress(); + memset(&_conn_params, 0x00, sizeof(_conn_params)); + _conn_params.interval_max = BT_GAP_INIT_CONN_INT_MAX; + _conn_params.interval_min = BT_GAP_INIT_CONN_INT_MIN; + _conn_params.latency = 0; + _conn_params.timeout = 400; +} + +BLEHelper::~BLEHelper() +{ +} + +BLEHelper::operator bool() const +{ + bt_addr_le_t zero; + + memset(&zero, 0, sizeof(zero)); + + return (memcmp(&_address, &zero, sizeof(_address)) != 0); +} + +bool BLEHelper::operator==(const BLEHelper& rhs) const +{ + return (memcmp(&_address, &rhs._address, sizeof(_address)) == 0); +} + +bool +BLEHelper::operator==(const bt_addr_le_t& address) const { + return (memcmp(&_address, &address, sizeof(_address)) == 0); +} + +bool +BLEHelper::operator!=(const BLEHelper& rhs) const { + return !(*this == rhs); +} + +const char* +BLEHelper::address() const { + static char address[18]; + + String addressStr = ""; + + for (int i = 5; i >= 0; i--) { + unsigned char a = _address.val[i]; + + if (a < 0x10) { + addressStr += "0"; + } + + addressStr += String(a, 16); + + if (i > 0) { + addressStr += ":"; + } + } + + strcpy(address, addressStr.c_str()); + + return address; +} +/* +const bt_addr_t *BLEHelper::address(void) const +{ + return (bt_addr_t *)_address.val; +} +*/ + +const bt_addr_le_t *BLEHelper::bt_le_address(void) const +{ + return &_address; +} + +void +BLEHelper::poll() { + delay(1); +} + +void +BLEHelper::setAddress(const bt_addr_le_t &address) { + memcpy(&_address, &address, sizeof(bt_addr_le_t)); +} + +void +BLEHelper::clearAddress() { + memset(&_address, 0x00, sizeof(_address)); +} + +void BLEHelper::getConnParams(ble_conn_param_t &user_conn_params) +{ + user_conn_params.interval_min = UNITS_TO_MSEC(_conn_params.interval_min, UNIT_1_25_MS); + user_conn_params.interval_max = UNITS_TO_MSEC(_conn_params.interval_max, UNIT_1_25_MS); + user_conn_params.timeout = UNITS_TO_MSEC(_conn_params.timeout, UNIT_10_MS); + user_conn_params.latency = _conn_params.latency; +} + +void BLEHelper::setConnectionParameters(uint16_t intervalmin, + uint16_t intervalmax, + uint16_t latency, + uint16_t timeout) +{ + _conn_params.interval_max = intervalmin; + _conn_params.interval_min = intervalmax; + _conn_params.latency = latency; + _conn_params.timeout = timeout; +} + +void BLEHelper::updateConnectionInterval(uint16_t intervalmin, + uint16_t intervalmax, + uint16_t latency, + uint16_t timeout) +{ + setConnectionParameters(intervalmin, intervalmax, latency, timeout); + updateConnectionInterval(); +} + +void BLEHelper::updateConnectionInterval() +{ + bt_conn_t* conn = bt_conn_lookup_addr_le(&_address); + int ret = 0; + if (NULL != conn) + { + ret = bt_conn_le_param_update(conn, &_conn_params); + pr_debug(LOG_MODULE_BLE, "%s-ret:%d",__FUNCTION__, ret); + bt_conn_unref(conn); + } +} + +void BLEHelper::setConnectionInterval(float minInterval, + float maxInterval) +{ + uint16_t minVal = (uint16_t)MSEC_TO_UNITS(minInterval, UNIT_1_25_MS); + uint16_t maxVal = (uint16_t)MSEC_TO_UNITS(maxInterval, UNIT_1_25_MS); + _conn_params.interval_min = minVal; + _conn_params.interval_max = maxVal; + updateConnectionInterval(); +} + +void BLEHelper::setConnectionInterval(float minInterval, + float maxInterval, + uint16_t latency, + uint16_t timeout) +{ + uint16_t minVal = (uint16_t)MSEC_TO_UNITS(minInterval, UNIT_1_25_MS); + uint16_t maxVal = (uint16_t)MSEC_TO_UNITS(maxInterval, UNIT_1_25_MS); + uint16_t timeoutVal = MSEC_TO_UNITS(timeout, UNIT_10_MS); + _conn_params.interval_min = minVal; + _conn_params.interval_max = maxVal; + _conn_params.timeout = timeoutVal; + updateConnectionInterval(); +} + + diff --git a/libraries/CurieBLE/src/BLEHelper.h b/libraries/CurieBLE/src/BLEHelper.h new file mode 100644 index 00000000..f0c6bc21 --- /dev/null +++ b/libraries/CurieBLE/src/BLEHelper.h @@ -0,0 +1,181 @@ +/* + * Copyright (c) 2016 Intel Corporation. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef _BLE_HELPER_H_ +#define _BLE_HELPER_H_ + + +class BLEHelper { + public: + /** + * Is the Central connected + * + * @return boolean_t true if the central is connected, otherwise false + */ + virtual bool connected(void) = 0; + + /** + * Get the address of the BLE in string format + * + * @return const char* address of the BLE in string format + */ + const char* address(void) const; + + /** + * @brief Get the address of the BLE in raw format + * + * @param none + * + * @return const bt_addr_le_t * address of the BLE in raw format + * + * @note none + */ + const bt_addr_le_t *bt_le_address(void) const; + /** + * Disconnect the central if it is connected + * + */ + virtual bool disconnect(void) = 0; + + /** + * Poll the central for events + */ + void poll(void); + + operator bool(void) const; + bool operator==(const BLEHelper& rhs) const; + bool operator==(const bt_addr_le_t& rhs) const; + bool operator!=(const BLEHelper& rhs) const; + + /** + * @brief Get the connection paramter + * + * @param[out] user_conn_params connection paramter + * Minimum Connection Interval (ms) + * Maximum Connection Interval (ms) + * Connection Latency + * Supervision Timeout (ms) + * + * @return none + * + * @note none + */ + void getConnParams(ble_conn_param_t &user_conn_params); + + /** + * @brief Set the connection paramter and send connection + * update request + * + * @param[in] intervalmin Minimum Connection Interval (ms) + * + * @param[in] intervalmax Maximum Connection Interval (ms) + * + * @return none + * + * @note none + */ + void setConnectionInterval(float minInterval, + float maxInterval); + + /** + * @brief Set the connection paramter and send connection + * update request + * + * @param[in] intervalmin Minimum Connection Interval (ms) + * + * @param[in] intervalmax Maximum Connection Interval (ms) + * + * @param[in] latency Connection Latency + * + * @param[in] timeout Supervision Timeout (ms) + * + * @return none + * + * @note none + */ + void setConnectionInterval(float minInterval, + float maxInterval, + uint16_t latency, + uint16_t timeout); + + /** + * @brief Just set the connection parameter. + * Not send out connection update request. + * + * @param[in] intervalmin Minimum Connection Interval (N * 1.25 ms) + * + * @param[in] intervalmax Maximum Connection Interval (N * 1.25 ms) + * + * @param[in] latency Connection Latency + * + * @param[in] timeout Supervision Timeout (N * 10 ms) + * + * @return none + * + * @note The user should care the unit + */ + void setConnectionParameters(uint16_t intervalmin, + uint16_t intervalmax, + uint16_t latency, + uint16_t timeout); + + /** + * @brief Schedule the link connection update request + * + * @param[in] intervalmin Minimum Connection Interval (N * 1.25 ms) + * + * @param[in] intervalmax Maximum Connection Interval (N * 1.25 ms) + * + * @param[in] latency Connection Latency + * + * @param[in] timeout Supervision Timeout (N * 10 ms) + * + * @return none + * + * @note The user should care the unit + */ + void updateConnectionInterval(uint16_t intervalmin, + uint16_t intervalmax, + uint16_t latency, + uint16_t timeout); + + /** + * @brief Schedule the link connection update request + * + * @return none + * + * @note The connection update request will not send if + * parameter doesn't changed + */ + void updateConnectionInterval(); + + protected: + void setAddress(const bt_addr_le_t &address); + void clearAddress(); + BLEHelper(); + virtual ~BLEHelper(); + + private: + bt_addr_le_t _address; /// BT low energy address + bt_le_conn_param_t _conn_params; /// Connection parameter +}; + +#endif + + diff --git a/libraries/CurieBLE/src/BLEPeripheral.cpp b/libraries/CurieBLE/src/BLEPeripheral.cpp index f1218bcd..efbb77f6 100644 --- a/libraries/CurieBLE/src/BLEPeripheral.cpp +++ b/libraries/CurieBLE/src/BLEPeripheral.cpp @@ -18,112 +18,40 @@ */ #include "BLEPeripheral.h" +#include "BLEPeripheralRole.h" -#include "BLECharacteristic.h" -#include "BLEDescriptor.h" -#include "BLEService.h" -#include "BLEUuid.h" - - -#define BLE_DISCONNECT_REASON_LOCAL_TERMINATION 0x16 - -void -blePeripheralGapEventHandler(ble_client_gap_event_t event, struct ble_gap_event *event_data, void *param) -{ - BLEPeripheral* p = (BLEPeripheral*)param; - - p->handleGapEvent(event, event_data); -} - -void -blePeripheralGattsEventHandler(ble_client_gatts_event_t event, struct ble_gatts_evt_msg *event_data, void *param) -{ - BLEPeripheral* p = (BLEPeripheral*)param; - - p->handleGattsEvent(event, event_data); -} +//#include "BLECharacteristic.h" BLEPeripheral::BLEPeripheral(void) : - _state(BLE_PERIPH_STATE_NOT_READY), - _advertise_service_uuid(NULL), _local_name(NULL), - _service_data_uuid(NULL), - _service_data(NULL), - _service_data_length(0), _appearance(0), - _min_conn_interval(DEFAULT_MIN_CONN_INTERVAL), - _max_conn_interval(DEFAULT_MAX_CONN_INTERVAL), - _central(this), - _attributes(NULL), - _num_attributes(0), - _last_added_characteritic(NULL) + _adv_data_idx(0) { - memset(_event_handlers, 0x00, sizeof(_event_handlers)); - - ble_client_get_factory_config(&_local_bda, _device_name); + memset(_adv_data, 0x00, sizeof(_adv_data)); + + // Default Advertising parameter + setConnectable(true); } BLEPeripheral::~BLEPeripheral(void) { - if (this->_attributes) { - free(this->_attributes); - } } bool BLEPeripheral::begin() { - BleStatus status; - - status = _init(); - if (status != BLE_STATUS_SUCCESS) { - return false; - } - - /* Populate advertising data - */ - _advDataInit(); - - status = ble_client_gap_wr_adv_data(_adv_data, _adv_data_len); - if (BLE_STATUS_SUCCESS != status) { + bool ret = false; + + pr_info(LOG_MODULE_BLE, "%s: %d", __FUNCTION__, 1); + + ret = BLEPeripheralRole::instance()->begin(); + if (!ret) + { return false; } - - uint16_t lastServiceHandle = 0; - - for (int i = 0; i < _num_attributes; i++) { - BLEAttribute* attribute = _attributes[i]; - BLEAttributeType type = attribute->type(); - bool addResult = false; - - if (BLETypeService == type) { - BLEService* service = (BLEService*)attribute; - - addResult = service->add(); - - lastServiceHandle = service->handle(); - } else if (BLETypeCharacteristic == type) { - BLECharacteristic* characteristic = (BLECharacteristic*)attribute; - - addResult = characteristic->add(lastServiceHandle); - } else if (BLETypeDescriptor == type) { - BLEDescriptor *descriptor = (BLEDescriptor*)attribute; - - if (strcmp(descriptor->uuid(), "2901") == 0 || - strcmp(descriptor->uuid(), "2902") == 0 || - strcmp(descriptor->uuid(), "2903") == 0 || - strcmp(descriptor->uuid(), "2904") == 0) { - continue; // skip - } - - addResult = descriptor->add(lastServiceHandle); - } - - if (!addResult) { - return false; - } - } - - return (_startAdvertising() == BLE_STATUS_SUCCESS); + + pr_info(LOG_MODULE_BLE, "%s: %d", __FUNCTION__, 2); + + return (startAdvertising() == BLE_STATUS_SUCCESS); } void @@ -136,23 +64,11 @@ BLEPeripheral::poll() void BLEPeripheral::end() { - _stop(); -} - -uint8_t -BLEPeripheral::getAdvertisingLength() -{ - return _adv_data_len; -} - -uint8_t* -BLEPeripheral::getAdvertising() -{ - return _adv_data; + BLEPeripheralRole::instance()->stop(); } void -BLEPeripheral::setAdvertisedServiceUuid(const char* advertisedServiceUuid) +BLEPeripheral::setAdvertisedServiceUuid(const bt_uuid_t* advertisedServiceUuid) { _advertise_service_uuid = advertisedServiceUuid; } @@ -164,314 +80,215 @@ BLEPeripheral::setLocalName(const char* localName) } void -BLEPeripheral::setAdvertisedServiceData(const char* serviceDataUuid, uint8_t* serviceData, uint8_t serviceDataLength) +BLEPeripheral::setAdvertisedServiceData(const bt_uuid_t* serviceDataUuid, + uint8_t* serviceData, + uint8_t serviceDataLength) { _service_data_uuid = serviceDataUuid; _service_data = serviceData; _service_data_length = serviceDataLength; } -void -BLEPeripheral::setDeviceName(const char deviceName[]) +void +BLEPeripheral::setAdvertisingInterval(float interval_min, + float interval_max) { - memset(_device_name, 0, sizeof(_device_name)); - if (deviceName && deviceName[0]) { - int len = strlen(deviceName); - if (len > BLE_MAX_DEVICE_NAME) - len = BLE_MAX_DEVICE_NAME; - memcpy(_device_name, deviceName, len); - } + uint16_t max = (uint16_t) MSEC_TO_UNITS(interval_max, UNIT_0_625_MS); + uint16_t min = (uint16_t) MSEC_TO_UNITS(interval_min, UNIT_0_625_MS); + BLEPeripheralRole::instance()->setAdvertisingInterval(min, max); } -void -BLEPeripheral::setAppearance(const uint16_t appearance) +void +BLEPeripheral::setAdvertisingInterval(float advertisingInterval) { - _appearance = appearance; + setAdvertisingInterval(advertisingInterval, advertisingInterval); } void -BLEPeripheral::setConnectionInterval(const unsigned short minConnInterval, const unsigned short maxConnInterval) +BLEPeripheral::setConnectable(bool connectable) { - _min_conn_interval = minConnInterval; - _max_conn_interval = maxConnInterval; - - if (_min_conn_interval < MIN_CONN_INTERVAL) { - _min_conn_interval = MIN_CONN_INTERVAL; - } else if (_min_conn_interval > MAX_CONN_INTERVAL) { - _min_conn_interval = MAX_CONN_INTERVAL; - } - - if (_max_conn_interval < _min_conn_interval) { - _max_conn_interval = _min_conn_interval; - } else if (_max_conn_interval > MAX_CONN_INTERVAL) { - _max_conn_interval = MAX_CONN_INTERVAL; + uint8_t type = BT_LE_ADV_IND; + if (connectable == false) + { + type = BT_LE_ADV_NONCONN_IND; } + BLEPeripheralRole::instance()->setAdvertisingType(type); } void -BLEPeripheral::setEventHandler(BLEPeripheralEvent event, BLEPeripheralEventHandler callback) +BLEPeripheral::setDeviceName(const char deviceName[]) { - if (event < sizeof(_event_handlers)) { - _event_handlers[event] = callback; - } + BLEPeripheralRole::instance()->setDeviceName(deviceName); } void -BLEPeripheral::addAttribute(BLEAttribute& attribute) +BLEPeripheral::setAppearance(const uint16_t appearance) { - if (_attributes == NULL) { - _attributes = (BLEAttribute**)malloc(BLEAttribute::numAttributes() * sizeof(BLEAttribute*)); - } - - _attributes[_num_attributes] = &attribute; - _num_attributes++; - - BLEAttributeType type = attribute.type(); + _appearance = appearance; +} - if (BLETypeCharacteristic == type) { - _last_added_characteritic = (BLECharacteristic*)&attribute; - } else if (BLETypeDescriptor == type) { - if (_last_added_characteritic) { - BLEDescriptor* descriptor = (BLEDescriptor*)&attribute; +void +BLEPeripheral::setConnectionInterval(const unsigned short minConnInterval, const unsigned short maxConnInterval) +{ + BLEPeripheralRole::instance()->setConnectionInterval(minConnInterval, + maxConnInterval); +} - if (strcmp("2901", descriptor->uuid()) == 0) { - _last_added_characteritic->setUserDescription(descriptor); - } else if (strcmp("2904", descriptor->uuid()) == 0) { - _last_added_characteritic->setPresentationFormat(descriptor); - } - } - } +void +BLEPeripheral::setEventHandler(BLERoleEvent event, BLERoleEventHandler callback) +{ + BLEPeripheralRole::instance()->setEventHandler(event, callback); } bool BLEPeripheral::disconnect() { - BleStatus status; - - if (BLE_PERIPH_STATE_CONNECTED == _state) { - status = ble_client_gap_disconnect(BLE_DISCONNECT_REASON_LOCAL_TERMINATION); - } else { - status = BLE_STATUS_WRONG_STATE; - } - - return (status == BLE_STATUS_SUCCESS); + return BLEPeripheralRole::instance()->disconnect(); } -BLECentral +BLECentralHelper BLEPeripheral::central() { - poll(); - - return _central; + return BLEPeripheralRole::instance()->central(); } bool BLEPeripheral::connected() { - poll(); - - return _central; + return BLEPeripheralRole::instance()->connected(); } BleStatus -BLEPeripheral::_init() +BLEPeripheral::addAttribute(BLEAttribute& attribute) { - BleStatus status; - int8_t txPower = 127; - - if (BLE_PERIPH_STATE_NOT_READY != _state) - return BLE_STATUS_WRONG_STATE; - - status = ble_client_init(blePeripheralGapEventHandler, this, - blePeripheralGattsEventHandler, this); - if (BLE_STATUS_SUCCESS != status) { - return status; - } - - status = ble_client_gap_set_enable_config(_device_name, &_local_bda, _appearance, txPower, _min_conn_interval, _max_conn_interval); - if (BLE_STATUS_SUCCESS != status) { - return status; - } - - _state = BLE_PERIPH_STATE_READY; - return BLE_STATUS_SUCCESS; + return BLEPeripheralRole::instance()->addAttribute(attribute); } -void + +BleStatus BLEPeripheral::_advDataInit(void) { - uint8_t *adv_tmp = _adv_data; - - memset(_adv_data, 0, sizeof(_adv_data)); - + uint8_t lengthTotal = 2; // Flags data length + _adv_data_idx = 0; + /* Add flags */ - *adv_tmp++ = 2; - *adv_tmp++ = BLE_ADV_TYPE_FLAGS; - *adv_tmp++ = BLE_SVC_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE; - _adv_data_len = 3; - - if (_advertise_service_uuid) { - BLEUuid bleUuid = BLEUuid(_advertise_service_uuid); - struct bt_uuid uuid = bleUuid.uuid(); - - if (BT_UUID16 == uuid.type) { - uint8_t *adv_tmp = &_adv_data[_adv_data_len]; - *adv_tmp++ = (1 + sizeof(uint16_t)); /* Segment data length */ - *adv_tmp++ = BLE_ADV_TYPE_COMP_16_UUID; /* Needed for Eddystone */ - UINT16_TO_LESTREAM(adv_tmp, uuid.uuid16); - _adv_data_len += (2 + sizeof(uint16_t)); - } else if (BT_UUID128 == uuid.type) { - uint8_t *adv_tmp = &_adv_data[_adv_data_len]; - *adv_tmp++ = (1 + MAX_UUID_SIZE); /* Segment data length */ - *adv_tmp++ = BLE_ADV_TYPE_INC_128_UUID; - memcpy(adv_tmp, uuid.uuid128, MAX_UUID_SIZE); - _adv_data_len += (2 + MAX_UUID_SIZE); + _adv_type = (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR); + _adv_data[_adv_data_idx].type = BT_DATA_FLAGS; + _adv_data[_adv_data_idx].data = &_adv_type; + _adv_data[_adv_data_idx].data_len = 1; + _adv_data_idx++; + + if (_advertise_service_uuid) + { + uint8_t type; + uint8_t length; + uint8_t *data = NULL; + + pr_info(LOG_MODULE_BLE, "ADV Type-%d", _advertise_service_uuid->type); + if (BT_UUID_TYPE_16 == _advertise_service_uuid->type) + { + //UINT16_TO_LESTREAM(adv_tmp, uuid.uuid16); + data = (uint8_t *)&(((bt_uuid_16_t *)_advertise_service_uuid)->val); + length = UUID_SIZE_16; + type = BT_DATA_UUID16_ALL; + } + else if (BT_UUID_TYPE_128 == _advertise_service_uuid->type) + { + data = ((bt_uuid_128_t *)_advertise_service_uuid)->val; + length = UUID_SIZE_128; + type = BT_DATA_UUID128_ALL; + } + if (NULL != data) + { + _adv_data[_adv_data_idx].type = type; + _adv_data[_adv_data_idx].data = data; + _adv_data[_adv_data_idx].data_len = length; + _adv_data_idx++; + lengthTotal += length; + + pr_info(LOG_MODULE_BLE, "Service UUID Len -%d", length); } } - if (_local_name) { + if (_local_name) + { /* Add device name (truncated if too long) */ - uint8_t calculated_len; - - adv_tmp = &_adv_data[_adv_data_len]; - if (_adv_data_len + strlen(_local_name) + 2 <= BLE_MAX_ADV_SIZE) { - *adv_tmp++ = strlen(_local_name) + 1; - *adv_tmp++ = BLE_ADV_TYPE_COMP_LOCAL_NAME; - calculated_len = strlen(_local_name); - } else { - *adv_tmp++ = BLE_MAX_ADV_SIZE - _adv_data_len - 1; - *adv_tmp++ = BLE_ADV_TYPE_SHORT_LOCAL_NAME; - calculated_len = BLE_MAX_ADV_SIZE - _adv_data_len - 2; - } - - memcpy(adv_tmp, _local_name, calculated_len); - _adv_data_len += calculated_len + 2; + _adv_data[_adv_data_idx].type = BT_DATA_NAME_COMPLETE; + _adv_data[_adv_data_idx].data = (const uint8_t*)_local_name; + _adv_data[_adv_data_idx].data_len = strlen(_local_name); + _adv_data_idx++; + + lengthTotal += strlen(_local_name); + pr_info(LOG_MODULE_BLE, "Local Name -%s", _local_name); + pr_info(LOG_MODULE_BLE, "Local Name Len -%d", strlen(_local_name)); } - if (_service_data) { + if (_service_data) + { /* Add Service Data (if it will fit) */ - BLEUuid bleUuid = BLEUuid(_service_data_uuid); - struct bt_uuid uuid = bleUuid.uuid(); - /* A 128-bit Service Data UUID won't fit in an Advertising packet */ - if (BT_UUID16 != uuid.type) { - return; /* We support service data only for 16-bit service UUID */ + if (BT_UUID_TYPE_16 != _service_data_uuid->type) + { + /* We support service data only for 16-bit service UUID */ + return BLE_STATUS_NOT_SUPPORTED; } - uint8_t block_len = 1 + sizeof(uint16_t) + _service_data_length; - if (_adv_data_len + 1 + block_len > BLE_MAX_ADV_SIZE) { - return; // Service data block is too large. + uint8_t block_len = sizeof(uint16_t) + _service_data_length; + if (1 + block_len > BLE_MAX_ADV_SIZE) + { + // Service data block is too large. + return BLE_STATUS_ERROR_PARAMETER; } + + _adv_data[_adv_data_idx].type = BT_DATA_SVC_DATA16; + _adv_data[_adv_data_idx].data = _service_data_buf; + _adv_data[_adv_data_idx].data_len = block_len; + _adv_data_idx++; - adv_tmp = &_adv_data[_adv_data_len]; - - *adv_tmp++ = block_len; - _adv_data_len++; + uint8_t *adv_tmp = _service_data_buf; - *adv_tmp++ = BLE_ADV_TYPE_SERVICE_DATA_16_UUID; - UINT16_TO_LESTREAM(adv_tmp, uuid.uuid16); + UINT16_TO_LESTREAM(adv_tmp, (((bt_uuid_16_t *)_service_data_uuid)->val)); memcpy(adv_tmp, _service_data, _service_data_length); - - _adv_data_len += block_len; + + lengthTotal += block_len; + pr_info(LOG_MODULE_BLE, "SVC Len -%d", block_len); + } + if (lengthTotal > BLE_MAX_ADV_SIZE) + { + pr_error(LOG_MODULE_BLE, "ADV Total length-%d", lengthTotal); + // Service data block is too large. + return BLE_STATUS_ERROR_PARAMETER; } -} - -BleStatus -BLEPeripheral::_startAdvertising() -{ - BleStatus status; - - if (_state != BLE_PERIPH_STATE_READY) - return BLE_STATUS_WRONG_STATE; - - status = ble_client_gap_start_advertise(0); // 0 = no timeout - if (BLE_STATUS_SUCCESS != status) - return status; - - _state = BLE_PERIPH_STATE_ADVERTISING; return BLE_STATUS_SUCCESS; } BleStatus -BLEPeripheral::_stop(void) +BLEPeripheral::startAdvertising() { - BleStatus status; - - if (BLE_PERIPH_STATE_ADVERTISING == _state) - status = ble_client_gap_stop_advertise(); - else - status = disconnect(); - + BleStatus status = BLE_STATUS_SUCCESS; + status = _advDataInit(); if (BLE_STATUS_SUCCESS != status) + { return status; - - _state = BLE_PERIPH_STATE_READY; - return BLE_STATUS_SUCCESS; + } + status = BLEPeripheralRole::instance()->startAdvertising(_adv_data, + _adv_data_idx, + NULL, + 0); + return status; } -void -BLEPeripheral::handleGapEvent(ble_client_gap_event_t event, struct ble_gap_event *event_data) +BleStatus +BLEPeripheral::stopAdvertising() { - if (BLE_CLIENT_GAP_EVENT_CONNECTED == event) { - _state = BLE_PERIPH_STATE_CONNECTED; - _central.setAddress(event_data->connected.peer_bda); - - if (_event_handlers[BLEConnected]) { - _event_handlers[BLEConnected](_central); - } - } else if (BLE_CLIENT_GAP_EVENT_DISCONNECTED == event) { - - for (int i = 0; i < _num_attributes; i++) { - BLEAttribute* attribute = _attributes[i]; - - if (attribute->type() == BLETypeCharacteristic) { - BLECharacteristic* characteristic = (BLECharacteristic*)attribute; - - characteristic->setCccdValue(_central, 0x0000); // reset CCCD - } - } - - if (_event_handlers[BLEDisconnected]) - _event_handlers[BLEDisconnected](_central); - - _state = BLE_PERIPH_STATE_READY; - _central.clearAddress(); - - _startAdvertising(); - } else if (BLE_CLIENT_GAP_EVENT_CONN_TIMEOUT == event) { - _state = BLE_PERIPH_STATE_READY; - - _startAdvertising(); - } + BleStatus status = BLE_STATUS_SUCCESS; + + status = BLEPeripheralRole::instance()->stopAdvertising(); + return status; } -void -BLEPeripheral::handleGattsEvent(ble_client_gatts_event_t event, struct ble_gatts_evt_msg *event_data) +BLECentralHelper *BLEPeripheral::getPeerCentralBLE(BLEHelper& central) { - if (BLE_CLIENT_GATTS_EVENT_WRITE == event) { - uint16_t handle = event_data->wr.attr_handle; - - for (int i = 0; i < _num_attributes; i++) { - BLEAttribute* attribute = _attributes[i]; - - if (attribute->type() != BLETypeCharacteristic) { - continue; - } - - BLECharacteristic* characteristic = (BLECharacteristic*)attribute; - - if (characteristic->valueHandle() == handle) { - characteristic->setValue(_central, event_data->wr.data, event_data->wr.len); - break; - } else if (characteristic->cccdHandle() == handle) { - uint16_t cccdValue = 0; - - memcpy(&cccdValue, event_data->wr.data, event_data->wr.len); - - characteristic->setCccdValue(_central, cccdValue); - break; - } - } - } + return (BLECentralHelper *)(¢ral); } diff --git a/libraries/CurieBLE/src/BLEPeripheral.h b/libraries/CurieBLE/src/BLEPeripheral.h index 054af330..33b8bef7 100644 --- a/libraries/CurieBLE/src/BLEPeripheral.h +++ b/libraries/CurieBLE/src/BLEPeripheral.h @@ -22,28 +22,17 @@ #include "internal/ble_client.h" -#include "BLEAttribute.h" -#include "BLECentral.h" -#include "BLECharacteristic.h" #include "BLECommon.h" - -/** - * BLE Peripheral Events - */ -enum BLEPeripheralEvent { - BLEConnected = 0, - BLEDisconnected = 1, - - BLEPeripheralEventLast = 2 -}; +#include "BLERoleBase.h" +#include "BLEPeripheralHelper.h" /** Function prototype for BLE Peripheral Device event callback */ -typedef void (*BLEPeripheralEventHandler)(BLECentral ¢ral); +typedef void (*BLEPeripheralEventHandler)(BLECentralHelper ¢ral); /** * BLE Peripheral */ -class BLEPeripheral { +class BLEPeripheral{ public: /** * Default Constructor for BLE Peripheral Device @@ -55,37 +44,20 @@ class BLEPeripheral { */ virtual ~BLEPeripheral(void); - /** - * Return the number of bytes in the advertising block. - * Useful for debugging advertising problems. - * - * @note Call only after calling begin(). - */ - uint8_t getAdvertisingLength(); - - /** - * Returns a pointer to the advertising block - * of length getAdvertisingLength(). - * Useful for debugging advertising problems. - * - * @note Call only after calling begin(). - */ - uint8_t* getAdvertising(); - /** * Set the service UUID that the BLE Peripheral Device advertises * - * @param advertisedServiceUuid 16-bit or 128-bit UUID to advertis + * @param[in] advertisedServiceUuid 16-bit or 128-bit UUID to advertis * (in string form) * * @note This method must be called before the begin method */ - void setAdvertisedServiceUuid(const char* advertisedServiceUuid); + void setAdvertisedServiceUuid(const bt_uuid_t* advertisedServiceUuid); /** * Set the local name that the BLE Peripheral Device advertises * - * @param localName local name to advertise + * @param[in] localName local name to advertise * * @note This method must be called before the begin method */ @@ -94,14 +66,14 @@ class BLEPeripheral { /** * Set the Service Data that the BLE Peripheral Device advertises * - * @param serviceDataUuid 16-bit Service UUID for this Service Data + * @param[in] serviceDataUuid 16-bit Service UUID for this Service Data * (in string form). Must match the UUID parameter * of setAdvertisedServiceUuid(). To fit into BLE_MAX_ADV_SIZE, * the UUID must be a 16-bit UUID. * - * @param serviceData binary array of Service Data. + * @param[in] serviceData binary array of Service Data. * - * @param serviceDataLength length (bytes) of serviceData[] + * @param[in] serviceDataLength length (bytes) of serviceData[] * * @note the entire advertising packet must be no more than * BLE_MAX_ADV_SIZE bytes, which is currently 31. @@ -113,14 +85,53 @@ class BLEPeripheral { * the service data will silently not be copied * into the advertising block. */ - void setAdvertisedServiceData(const char* serviceDataUuid, uint8_t* serviceData, uint8_t serviceDataLength); - + void setAdvertisedServiceData(const bt_uuid_t* serviceDataUuid, + uint8_t* serviceData, + uint8_t serviceDataLength); + + /** + * @brief Set advertising interval + * + * @param[in] advertisingInterval Advertising Interval (N * 0.625) + * + * @return none + * + * @note none + */ + void setAdvertisingInterval(float advertisingInterval); + + /** + * @brief Set advertising interval + * + * @param[in] interval_min Minimum Advertising Interval (millisecond) + * + * @param[in] interval_max Maximum Advertising Interval (millisecond) + * + * @return none + * + * @note none + */ + void setAdvertisingInterval(float interval_min, + float interval_max); + + /** + * @brief Set advertising type as connectable/non-connectable + * + * @param[in] connectable true - The device connectable + * false - The device non-connectable + * + * @return none + * + * @note none + */ + void setConnectable(bool connectable); + /** * Set the device name for the BLE Peripheral Device * * If device name is not set, a default name will be used instead * - * @param device User-defined name string for this device. Truncated if + * @param[in] device User-defined name string for this device. Truncated if * more than maximum allowed string length (20 bytes). * * @note This method must be called before the begin method @@ -133,7 +144,7 @@ class BLEPeripheral { * See https://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.gap.appearance.xml * for available options. * - * @param appearance Appearance category identifier as defined by BLE Standard + * @param[in] appearance Appearance category identifier as defined by BLE Standard * * @return BleStatus indicating success or error * @@ -144,8 +155,8 @@ class BLEPeripheral { /** * Set the min and max connection interval BLE Peripheral Device * - * @param minConnInterval Minimum connection interval (1.25 ms units), minimum 0x0006 (7.5ms) - * @param maxConnInterval Maximum connection interval (1.25 ms units), maximum 0x095f (2998.75ms) + * @param[in] minConnInterval Minimum connection interval (1.25 ms units), minimum 0x0006 (7.5ms) + * @param[in] maxConnInterval Maximum connection interval (1.25 ms units), maximum 0x095f (2998.75ms) * * @note This method must be called before the begin method */ @@ -154,21 +165,22 @@ class BLEPeripheral { /** * Add an attribute to the BLE Peripheral Device * - * @param attribute Attribute to add to Peripheral + * @param[in] attribute Attribute to add to Peripheral * * @return BleStatus indicating success or error * * @note This method must be called before the begin method + * Only need check return value at first call. Memory only alloc at first call */ - void addAttribute(BLEAttribute& attribute); + BleStatus addAttribute(BLEAttribute& attribute); /** * Provide a function to be called when events related to this Device are raised * - * @param event Event type for callback - * @param callback Pointer to callback function to invoke when an event occurs. + * @param[in] event Event type for callback + * @param[in] callback Pointer to callback function to invoke when an event occurs. */ - void setEventHandler(BLEPeripheralEvent event, BLEPeripheralEventHandler callback); + void setEventHandler(BLERoleEvent event, BLERoleEventHandler callback); /** * Setup attributes and start advertising @@ -199,7 +211,7 @@ class BLEPeripheral { * * @return BleStatus indicating success or error */ - BLECentral central(void); + BLECentralHelper central(void); /** * Is a central connected? @@ -207,52 +219,61 @@ class BLEPeripheral { * @return boolean_t true if central connected, otherwise false */ bool connected(void); - + + /** + * @brief Init the ADV data and start send advertisement + * + * @param none + * + * @return BleStatus 0 - Success. Others - error code + * + * @note none + */ + BleStatus startAdvertising(void); + + /** + * @brief Stop send advertisement + * + * @param none + * + * @return BleStatus 0 - Success. Others - error code + * + * @note none + */ + BleStatus stopAdvertising(void); + + /** + * Get peer central device + * + *@param central peer central device of the peripheral board + * + * @return pointer of peer central device + */ + BLECentralHelper *getPeerCentralBLE(BLEHelper& central); + protected: - friend void blePeripheralGapEventHandler(ble_client_gap_event_t event, struct ble_gap_event *event_data, void *param); - friend void blePeripheralGattsEventHandler(ble_client_gatts_event_t event, struct ble_gatts_evt_msg *event_data, void *param); - - void handleGapEvent(ble_client_gap_event_t event, struct ble_gap_event *event_data); - void handleGattsEvent(ble_client_gatts_event_t event, struct ble_gatts_evt_msg *event_data); private: - BleStatus _init(void); - BleStatus _startAdvertising(void); + BleStatus _stop(void); - void _advDataInit(void); + BleStatus _advDataInit(void); private: - - enum BLEPeripheralState { - BLE_PERIPH_STATE_NOT_READY = 0, - BLE_PERIPH_STATE_READY, - BLE_PERIPH_STATE_ADVERTISING, - BLE_PERIPH_STATE_CONNECTED, - }; - - BLEPeripheralState _state; - - const char* _advertise_service_uuid; const char* _local_name; - const char* _service_data_uuid; + + const bt_uuid_t* _service_data_uuid; uint8_t* _service_data; - uint8_t _service_data_length; - char _device_name[BLE_MAX_DEVICE_NAME+1]; + uint8_t _service_data_length; + uint8_t _service_data_buf[BLE_MAX_ADV_SIZE]; + uint16_t _appearance; - uint16_t _min_conn_interval; - uint16_t _max_conn_interval; - uint8_t _adv_data[BLE_MAX_ADV_SIZE]; - uint8_t _adv_data_len; - ble_addr_t _local_bda; - BLECentral _central; - - BLEPeripheralEventHandler _event_handlers[BLEPeripheralEventLast]; - - BLEAttribute** _attributes; - uint16_t _num_attributes; - - BLECharacteristic* _last_added_characteritic; + + const bt_uuid_t* _advertise_service_uuid; + + uint8_t _adv_type; + bt_data_t _adv_data[4]; + size_t _adv_data_idx; }; #endif // _BLE_DEVICE_H_INCLUDED diff --git a/libraries/CurieBLE/src/BLEPeripheralHelper.cpp b/libraries/CurieBLE/src/BLEPeripheralHelper.cpp new file mode 100644 index 00000000..2a13c03c --- /dev/null +++ b/libraries/CurieBLE/src/BLEPeripheralHelper.cpp @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2016 Intel Corporation. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include "BLEPeripheralHelper.h" + +BLEAttribute *BLEPeripheralHelper::attribute(uint16_t handle) +{ + return _profile.attribute(handle); +} + +BLEAttribute *BLEPeripheralHelper::attribute(bt_gatt_subscribe_params_t *params) +{ + return _profile.attribute(params); +} + +uint8_t BLEPeripheralHelper::discover(const bt_gatt_attr_t *attr) +{ + // Not allow to call the discover + if (NULL == _central) + { + return BT_GATT_ITER_STOP; + } + return _profile.discover(attr); +} + +void BLEPeripheralHelper::discover() +{ + if (NULL == _central) + { + return; + } + _profile.discover(); +} + +BLEPeripheralHelper::BLEPeripheralHelper(BLECentralRole* central): + _profile(this), + _central(central) +{ + ; +} +BLEPeripheralHelper::~BLEPeripheralHelper() +{ + +} + +bool BLEPeripheralHelper::disconnect(void) +{ + int err = 0; + bt_conn_t* conn = bt_conn_lookup_addr_le(this->bt_le_address()); + if (NULL == conn) + { + return false; + } + + err = bt_conn_disconnect (conn, BT_HCI_ERR_REMOTE_USER_TERM_CONN); + bt_conn_unref(conn); + return (err == 0); +} + +bool BLEPeripheralHelper::connected(void) +{ + bt_conn_t* conn = bt_conn_lookup_addr_le(this->bt_le_address()); + if (NULL == conn) + { + return false; + } + bt_conn_unref(conn); + return true; +} + +void BLEPeripheralHelper::linkLost(void) +{ + clearAddress(); + if (NULL != _central) + { + // Only central role need to do + _profile.clearHandles(); + } +} + +BleStatus BLEPeripheralHelper::addAttribute(BLEAttribute& attribute) +{ + return _profile.addAttribute(attribute); +} + +int BLEPeripheralHelper::registerProfile() +{ + return _profile.registerProfile(); +} + +uint16_t BLEPeripheralHelper::valueHandle(BLEAttribute *attr) +{ + return _profile.valueHandle(attr); +} + +uint16_t BLEPeripheralHelper::cccdHandle(BLEAttribute *attr) +{ + return _profile.cccdHandle(attr); +} + + diff --git a/libraries/CurieBLE/src/BLEPeripheralHelper.h b/libraries/CurieBLE/src/BLEPeripheralHelper.h new file mode 100644 index 00000000..bdb7c719 --- /dev/null +++ b/libraries/CurieBLE/src/BLEPeripheralHelper.h @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2016 Intel Corporation. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef _BLE_PERIPHERAL_HELPER_H_ +#define _BLE_PERIPHERAL_HELPER_H_ + +#include "BLECommon.h" +#include "BLEHelper.h" +#include "BLEProfile.h" + +class BLEAttribute; +class BLECentralRole; + +class BLEPeripheralHelper : public BLEHelper { + friend class BLECentralRole; + friend class BLEPeripheralRole; + public: + /** + * Is the Central connected + * + * @return boolean_t true if the central is connected, otherwise false + */ + bool connected(void); + + /** + * Disconnect the central if it is connected + * + */ + bool disconnect(void); + + /** + * Add an attribute to the BLE Peripheral helper + * + * @param[in] attribute Attribute to add to Peripheral + * + * @return BleStatus indicating success or error + * + * @note This method must be called before the begin method + */ + BleStatus addAttribute(BLEAttribute& attribute); + + /** + * @brief Get BLEAttribute by subscribe parameter + * + * @param[in] params Subscribe parameter + * + * @return BLEAttribute * NULL - Not found + * Not NULL - The BLEAttribute object + * + * @note none + */ + BLEAttribute *attribute(bt_gatt_subscribe_params_t *params); + + /** + * @brief Get BLEAttribute by characteristic handle + * + * @param[in] handle The characteristic handle + * + * @return BLEAttribute * NULL - Not found + * Not NULL - The BLEAttribute object + * + * @note none + */ + BLEAttribute *attribute(uint16_t handle); + + /** + * @brief Discover the BLE peripheral profile for central + * + * @param none + * + * @return none + * + * @note This function only for the central device. + * + * @note The central deivce didn't know the connected BLE's profile. + * Need send discover request to search the attribute in the BLE peripheral + */ + void discover(); + + /** + * @brief Process the discover response and + * discover the BLE peripheral profile + * + * @param[in] const bt_gatt_attr_t * The gatt attribute response + * + * @return uint8_t BT_GATT_ITER_STOP Stop discover the profile + * BT_GATT_ITER_CONTINUE Continue to send the discover request + * + * @note This function only for the central device. + */ + uint8_t discover(const bt_gatt_attr_t *attr); + + /** + * @brief For peripheral to register the profile tree + * + * @param none + * + * @return int 0 - success + * other - error code + * + * @note none + */ + int registerProfile(); + + /** + * @brief Process the link lost event + * + * @param none + * + * @return none + * + * @note none + */ + void linkLost(void); + + /** + * @brief Get the characteristic value handle + * + * @param[in] attr Attribute object + * + * @return uint16_t The value hander of attribute + * 0 is invalid + * + * @note Only for central mode + */ + uint16_t valueHandle(BLEAttribute *attr); + + /** + * @brief Get characteristic configuration descriptor value handle + * + * @param[in] attr Attribute object + * + * @return uint16_t The value hander of attribute + * 0 is invalid + * + * @note Only for central mode + */ + uint16_t cccdHandle(BLEAttribute *attr); + + protected: + BLEPeripheralHelper(BLECentralRole* central); + ~BLEPeripheralHelper(); + + private: + BLEProfile _profile; + BLECentralRole* _central; +}; + +#endif + diff --git a/libraries/CurieBLE/src/BLEPeripheralRole.cpp b/libraries/CurieBLE/src/BLEPeripheralRole.cpp new file mode 100644 index 00000000..ff5baad6 --- /dev/null +++ b/libraries/CurieBLE/src/BLEPeripheralRole.cpp @@ -0,0 +1,304 @@ +/* + * Copyright (c) 2015 Intel Corporation. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include "BLEPeripheralRole.h" + +#include "BLECharacteristic.h" +#include "BLEDescriptor.h" +#include "BLEService.h" + +BLEPeripheralRole* BLEPeripheralRole::_ins = NULL; + +BLEPeripheralRole* BLEPeripheralRole::instance() +{ + if (NULL == _ins) + { + _ins = new BLEPeripheralRole(); + } + return _ins; +} + +BLEPeripheralRole::BLEPeripheralRole(void) : + _state(BLE_PERIPH_STATE_NOT_READY), + _min_conn_interval(DEFAULT_MIN_CONN_INTERVAL), + _max_conn_interval(DEFAULT_MAX_CONN_INTERVAL), + _peripheral(NULL), + _central(this) +{ + memset(_event_handlers, 0x00, sizeof(_event_handlers)); + _peripheral.setAddress(_local_bda); + + _adv_param.type = BT_LE_ADV_IND; + _adv_param.addr_type = _local_bda.type; + _adv_param.interval_min = 0xA0; + _adv_param.interval_max = 0xF0; +} + +BLEPeripheralRole::~BLEPeripheralRole(void) +{ +} + +bool BLEPeripheralRole::begin() +{ + BleStatus status; + + if (BLE_PERIPH_STATE_NOT_READY != _state) + return BLE_STATUS_WRONG_STATE; + + status = _init(); + if (status != BLE_STATUS_SUCCESS) { + return false; + } + _state = BLE_PERIPH_STATE_READY; + + // Set device name + setDeviceName(); + delay(4); + // Register profile + _peripheral.registerProfile(); + delay(8); // Temp solution for send data fast will makes ADV data set failed + return true; +} + +void +BLEPeripheralRole::poll() +{ + // no-op for now + delay(1); +} + +void +BLEPeripheralRole::setDeviceName(const char deviceName[]) +{ + memset(_device_name, 0, sizeof(_device_name)); + if (deviceName && deviceName[0]) { + int len = strlen(deviceName); + if (len > BLE_MAX_DEVICE_NAME) + len = BLE_MAX_DEVICE_NAME; + memcpy(_device_name, deviceName, len); + setDeviceName(); + } +} + +void +BLEPeripheralRole::setDeviceName() +{ + int len = strlen(_device_name); + bt_le_set_device_name(_device_name, len); +} + +void +BLEPeripheralRole::setConnectionInterval(const unsigned short minConnInterval, const unsigned short maxConnInterval) +{ + _min_conn_interval = minConnInterval; + _max_conn_interval = maxConnInterval; + + if (_min_conn_interval < MIN_CONN_INTERVAL) { + _min_conn_interval = MIN_CONN_INTERVAL; + } else if (_min_conn_interval > MAX_CONN_INTERVAL) { + _min_conn_interval = MAX_CONN_INTERVAL; + } + + if (_max_conn_interval < _min_conn_interval) { + _max_conn_interval = _min_conn_interval; + } else if (_max_conn_interval > MAX_CONN_INTERVAL) { + _max_conn_interval = MAX_CONN_INTERVAL; + } +} + +void +BLEPeripheralRole::setEventHandler(BLERoleEvent event, BLERoleEventHandler callback) +{ + if (event < sizeof(_event_handlers)) { + _event_handlers[event] = callback; + } +} + +bool +BLEPeripheralRole::disconnect() +{ + BleStatus status = BLE_STATUS_WRONG_STATE; + int err; + + if (BLE_PERIPH_STATE_CONNECTED == _state) + { + bt_conn_t *central_conn = bt_conn_lookup_addr_le(_central.bt_le_address()); + if (NULL != central_conn) + { + err = bt_conn_disconnect (central_conn, + BT_HCI_ERR_REMOTE_USER_TERM_CONN); + status = errorno_to_ble_status(err); + bt_conn_unref(central_conn); + } + } + return (status == BLE_STATUS_SUCCESS); +} + +BLECentralHelper +BLEPeripheralRole::central() +{ + poll(); + + return _central; +} + +bool +BLEPeripheralRole::connected() +{ + poll(); + + return _central; +} + +BleStatus +BLEPeripheralRole::addAttribute(BLEAttribute& attribute) +{ + return _peripheral.addAttribute(attribute); +} + +BleStatus +BLEPeripheralRole::stopAdvertising() +{ + int err_code = 0; + BleStatus status = BLE_STATUS_WRONG_STATE; + + if (BLE_PERIPH_STATE_ADVERTISING == _state) + { + err_code = bt_le_adv_stop(); + status = errorno_to_ble_status(err_code); + } + + if (BLE_STATUS_SUCCESS != status) + return status; + + _state = BLE_PERIPH_STATE_READY; + return BLE_STATUS_SUCCESS; +} + +BleStatus +BLEPeripheralRole::startAdvertising(const bt_data_t *ad, + size_t ad_len, + const bt_data_t *sd, + size_t sd_len) +{ + int ret; + + pr_info(LOG_MODULE_BLE, "%s-ad_len%d", __FUNCTION__, ad_len); + if (_state != BLE_PERIPH_STATE_READY) + return BLE_STATUS_WRONG_STATE; + + ret = bt_le_adv_start(&_adv_param, ad, ad_len, sd, sd_len); + if (0 != ret) + { + pr_error(LOG_MODULE_APP, "[ADV] Start failed. Error: %d", ret); + return BLE_STATUS_WRONG_STATE; + } + _state = BLE_PERIPH_STATE_ADVERTISING; + return BLE_STATUS_SUCCESS; +} + +void BLEPeripheralRole::setAdvertisingInterval(uint16_t advertisingInterval) +{ + setAdvertisingInterval(advertisingInterval, advertisingInterval); +} + +void BLEPeripheralRole::setAdvertisingInterval(uint16_t interval_min, + uint16_t interval_max) +{ + _adv_param.interval_min = interval_min; + _adv_param.interval_max = interval_max; +} + +void +BLEPeripheralRole::setAdvertisingType(uint8_t type) +{ + _adv_param.type = type; +} + +BleStatus +BLEPeripheralRole::stop(void) +{ + int err_code; + BleStatus status; + + if (BLE_PERIPH_STATE_ADVERTISING == _state) + { + err_code = bt_le_adv_stop(); + status = errorno_to_ble_status(err_code); + } + else + status = disconnect(); + + if (BLE_STATUS_SUCCESS != status) + return status; + + _state = BLE_PERIPH_STATE_READY; + return BLE_STATUS_SUCCESS; +} + +void BLEPeripheralRole::handleConnectEvent(bt_conn_t *conn, uint8_t err) +{ + // Update the central address + const bt_addr_le_t *central_addr = bt_conn_get_dst(conn); + _central.setAddress(*central_addr); + + pr_info(LOG_MODULE_BLE, "Connected: %d", err); + // Call the CB + if (_event_handlers[BLEConnected]) + _event_handlers[BLEConnected](_central); + + if (BLE_PERIPH_STATE_ADVERTISING == _state) + _state = BLE_PERIPH_STATE_CONNECTED; +} + + +void BLEPeripheralRole::handleDisconnectEvent(bt_conn_t *conn, uint8_t reason) +{ + bt_conn_t *central_conn = bt_conn_lookup_addr_le(_central.bt_le_address()); + if (conn == central_conn) + { + pr_info(LOG_MODULE_BLE, "Peripheral Disconnect reason: %d", reason); + if (_event_handlers[BLEDisconnected]) + _event_handlers[BLEDisconnected](_central); + } + _central.clearAddress(); + if (NULL != central_conn) + { + bt_conn_unref(central_conn); + } + + if (BLE_PERIPH_STATE_CONNECTED == _state) + _state = BLE_PERIPH_STATE_ADVERTISING; +} + +void BLEPeripheralRole::handleParamUpdated(bt_conn_t *conn, + uint16_t interval, + uint16_t latency, + uint16_t timeout) +{ + pr_info(LOG_MODULE_BLE, "Parameter updated\r\n\tConn: %p\r\n\tinterval: %d\r\n\tlatency: %d\r\n\ttimeout: %d", + conn, interval, latency, timeout); + if (_event_handlers[BLEUpdateParam]) + { + _central.setConnectionParameters(interval, interval, latency, timeout); + _event_handlers[BLEUpdateParam](_central); + } +} + + diff --git a/libraries/CurieBLE/src/BLEPeripheralRole.h b/libraries/CurieBLE/src/BLEPeripheralRole.h new file mode 100644 index 00000000..87c311b5 --- /dev/null +++ b/libraries/CurieBLE/src/BLEPeripheralRole.h @@ -0,0 +1,282 @@ +/* + * Copyright (c) 2015 Intel Corporation. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef _BLE_PERIPHERALROLE_H_INCLUDED +#define _BLE_PERIPHERALROLE_H_INCLUDED + +#include "internal/ble_client.h" + +#include "BLECommon.h" +#include "BLERoleBase.h" +#include "BLEPeripheralHelper.h" + +/** + * BLE Peripheral Role + */ +class BLEPeripheralRole: public BLERoleBase{ +public: + /** + * Default Constructor for BLE Peripheral Device + */ + BLEPeripheralRole(void); + + /** + * Destructor for BLE Peripheral Device + */ + virtual ~BLEPeripheralRole(void); + + /** + * Set the device name for the BLE Peripheral Device + * + * If device name is not set, a default name will be used instead + * + * @param[in] deviceName User-defined name string for this device. Truncated if + * more than maximum allowed string length (20 bytes). + * + * @note This method must be called before the begin method + */ + void setDeviceName(const char *deviceName); + + /** + * Set the min and max connection interval BLE Peripheral Device + * + * @param[in] minConnInterval Minimum connection interval (1.25 ms units), minimum 0x0006 (7.5ms) + * @param[in] maxConnInterval Maximum connection interval (1.25 ms units), maximum 0x0C80 (4000ms) + * + * @note This method must be called before the begin method + */ + void setConnectionInterval(const unsigned short minConnInterval, const unsigned short maxConnInterval); + + /** + * Add an attribute to the BLE Peripheral Device + * + * @param[in] attribute Attribute to add to Peripheral + * + * @return BleStatus indicating success or error + * + * @note This method must be called before the begin method + */ + BleStatus addAttribute(BLEAttribute& attribute); + + /** + * Provide a function to be called when events related to this Device are raised + * + * @param[in] event Event type for callback + * @param[in] callback Pointer to callback function to invoke when an event occurs. + */ + void setEventHandler(BLERoleEvent event, BLERoleEventHandler callback); + + /** + * Setup attributes and start advertising + * + * @return bool indicating success or error + */ + bool begin(void); + + /** + * Poll the peripheral for events + */ + void poll(void); + + /** + * Stop advertising and disconnect a central if connected + */ + BleStatus stop(void); + + /** + * Disconnect the central connected if there is one connected + * + * @return bool indicating success or error + */ + bool disconnect(void); + + /** + * Setup attributes and start advertising + * + * @return BleStatus indicating success or error + */ + BLECentralHelper central(void); + + /** + * Is a central connected? + * + * @return boolean_t true if central connected, otherwise false + */ + bool connected(void); + + /** + * @brief Start peripheral advertising + * + * @param[in] ad The ADV data array + * + * @param[in] ad_len The ADV data array length + * + * @param[in] sd The Scan response data array + * + * @param[in] sd_len The Scan response data array length + * + * @return BleStatus + * + * @note none + */ + BleStatus startAdvertising(const bt_data_t *ad, + size_t ad_len, + const bt_data_t *sd, + size_t sd_len); + + /** + * @brief Stop send advertisement + * + * @param none + * + * @return none + * + * @note none + */ + BleStatus stopAdvertising(); + + /** + * @brief Set advertising parameter + * + * @param[in] advertisingInterval Advertising Interval (N * 0.625) + * + * @return none + * + * @note none + */ + void setAdvertisingInterval(uint16_t advertisingInterval); + + /** + * @brief Set advertising parameter + * + * @param[in] interval_min Minimum Advertising Interval (N * 0.625) + * + * @param[in] interval_max Maximum Advertising Interval (N * 0.625) + * + * @return none + * + * @note none + */ + void setAdvertisingInterval(uint16_t interval_min, + uint16_t interval_max); + + /** + * @brief Set advertising type + * + * @param[in] type Advertising type + * BT_LE_ADV_IND, BT_LE_ADV_NONCONN_IND + * + * @return none + * + * @note none + */ + void setAdvertisingType(uint8_t type); + + /** + * @brief Get BLE Peripheral instance. + * + * @param none + * + * @return BLEPeripheralRole* The BLE perpheral instance + * + * @note Singleton. Only have one object to communicate with + * stack and manage the device + */ + static BLEPeripheralRole* instance(); + +protected: + /** + * @brief Handle the connected event + * + * @param[in] conn The object that established the connection + * + * @param[in] err The code of the process + * + * @return none + * + * @note none + */ + void handleConnectEvent(bt_conn_t *conn, uint8_t err); + + /** + * @brief Handle the disconnected event + * + * @param[in] conn The object that lost the connection + * + * @param[in] reason The link lost reason + * + * @return none + * + * @note none + */ + void handleDisconnectEvent(bt_conn_t *conn, uint8_t reason); + + /** + * @brief Handle the conntion update request + * + * @param[in] conn The connection object that need to process the update request + * + * @param[in] interval The connection interval (N*1.25)ms + * + * @param[in] latency The connection latency + * + * @param[in] timeout The connection timeout (N*10)ms + * + * @return none + * + * @note none + */ + void handleParamUpdated(bt_conn_t *conn, + uint16_t interval, + uint16_t latency, + uint16_t timeout); + +private: + + /** + * Set the device name to Nordic BLE's profile + * + * @param none + * + * @note none + */ + void setDeviceName(); + + enum BLEPeripheralState { + BLE_PERIPH_STATE_NOT_READY = 0, + BLE_PERIPH_STATE_READY, + BLE_PERIPH_STATE_ADVERTISING, + BLE_PERIPH_STATE_CONNECTED, + }; + + BLEPeripheralState _state; + + uint16_t _min_conn_interval; + uint16_t _max_conn_interval; + + struct bt_le_adv_param _adv_param; + + BLEPeripheralHelper _peripheral; + BLECentralHelper _central; + + BLERoleEventHandler _event_handlers[BLERoleEventLast]; + static BLEPeripheralRole *_ins; +}; + +#endif // _BLE_DEVICE_H_INCLUDED diff --git a/libraries/CurieBLE/src/BLEProfile.cpp b/libraries/CurieBLE/src/BLEProfile.cpp new file mode 100644 index 00000000..10f0c91e --- /dev/null +++ b/libraries/CurieBLE/src/BLEProfile.cpp @@ -0,0 +1,726 @@ +/* + * Copyright (c) 2016 Intel Corporation. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include +#include "BLEProfile.h" +#include "BLEPeripheral.h" +#include "BLECentralRole.h" +#include "BLEPeripheralRole.h" + +// Only for peripheral +ssize_t profile_read_process(bt_conn_t *conn, + const bt_gatt_attr_t *attr, + void *buf, uint16_t len, + uint16_t offset) +{ + const unsigned char *pvalue; + BLEAttribute *bleattr = (BLEAttribute *)attr->user_data; + BLEAttributeType type = bleattr->type(); + if (BLETypeCharacteristic == type) + { + BLECharacteristic* blecharacteritic; + blecharacteritic = (BLECharacteristic*)bleattr; + pvalue = blecharacteritic->value(); + return bt_gatt_attr_read(conn, attr, buf, len, offset, pvalue, + blecharacteritic->valueLength()); + } + else if (BLETypeDescriptor == type) + { + BLEDescriptor *bledescriptor = (BLEDescriptor *)bleattr; + pvalue = bledescriptor->value(); + return bt_gatt_attr_read(conn, attr, buf, len, offset, pvalue, bledescriptor->valueLength()); + } + return 0; +} + +// Only for peripheral +ssize_t profile_write_process(bt_conn_t *conn, + const bt_gatt_attr_t *attr, + const void *buf, uint16_t len, + uint16_t offset) +{ + pr_info(LOG_MODULE_BLE, "%s1", __FUNCTION__); + BLEAttribute *bleattr = (BLEAttribute *)attr->user_data; + BLECharacteristic* blecharacteritic; + BLEAttributeType type = bleattr->type(); + BLECentralHelper central = BLEPeripheralRole::instance()->central(); + if ((BLETypeCharacteristic != type) || 0 != offset) + { + return 0; + } + + blecharacteritic = (BLECharacteristic*)bleattr; + blecharacteritic->setValue(*((BLEHelper *)¢ral), (const uint8_t *) buf, len); + + return len; +} + +ssize_t profile_longwrite_process(struct bt_conn *conn, + const struct bt_gatt_attr *attr, + const void *buf, uint16_t len, + uint16_t offset) +{ + pr_info(LOG_MODULE_BLE, "%s1", __FUNCTION__); + BLEAttribute *bleattr = (BLEAttribute *)attr->user_data; + BLECharacteristic* blecharacteritic; + BLEAttributeType type = bleattr->type(); + BLECentralHelper central = BLEPeripheralRole::instance()->central(); + if (BLETypeCharacteristic != type) + { + return 0; + } + + blecharacteritic = (BLECharacteristic*)bleattr; + blecharacteritic->setBuffer(*((BLEHelper *)¢ral), (const uint8_t *) buf, len, offset); + + return len; +} + +int profile_longflush_process(struct bt_conn *conn, + const struct bt_gatt_attr *attr, + uint8_t flags) +{ + BLEAttribute *bleattr = (BLEAttribute *)attr->user_data; + BLECharacteristic* blecharacteritic; + BLEAttributeType type = bleattr->type(); + BLECentralHelper central = BLEPeripheralRole::instance()->central(); + if (BLETypeCharacteristic != type) + { + return 0; + } + + blecharacteritic = (BLECharacteristic*)bleattr; + + switch (flags) { + case BT_GATT_FLUSH_DISCARD: + /* Discard buffer reseting it back with data */ + blecharacteritic->discardBuffer(); + return 0; + case BT_GATT_FLUSH_SYNC: + /* Sync buffer to data */ + blecharacteritic->syncupBuffer2Value(*((BLEHelper *)¢ral)); + return 0; + } + + return -EINVAL; +} + + +// Only for central +uint8_t profile_notify_process (bt_conn_t *conn, + bt_gatt_subscribe_params_t *params, + const void *data, uint16_t length) +{ + BLEPeripheralHelper* peripheral = BLECentralRole::instance()->peripheral(conn);// Find peripheral by bt_conn + BLEAttribute* notifyatt = peripheral->attribute(params); // Find attribute by params + BLECharacteristic *chrc = (BLECharacteristic *)notifyatt; + + //assert(notifyatt->type() == BLETypeCharacteristic); + pr_debug(LOG_MODULE_APP, "%s1", __FUNCTION__); + chrc->setValue(*((BLEHelper *)peripheral),(const unsigned char *)data, length); + return BT_GATT_ITER_CONTINUE; +} + +// Only for central +uint8_t profile_discover_process(bt_conn_t *conn, + const bt_gatt_attr_t *attr, + bt_gatt_discover_params_t *params) +{ + BLEPeripheralHelper* peripheral = BLECentralRole::instance()->peripheral(conn);// Find peripheral by bt_conn + return peripheral->discover(attr); +} + +// Only for central +uint8_t profile_read_rsp_process(bt_conn_t *conn, int err, + bt_gatt_read_params_t *params, + const void *data, + uint16_t length) +{ + if (NULL == data) + { + return BT_GATT_ITER_STOP; + } + BLEPeripheralHelper* peripheral = BLECentralRole::instance()->peripheral(conn);// Find peripheral by bt_conn + BLEAttribute* readatt = peripheral->attribute(params->single.handle); + BLECharacteristic *chrc = (BLECharacteristic *)readatt; + + //assert(readatt->type() == BLETypeCharacteristic); + chrc->setValue(*((BLEHelper *)peripheral), (const unsigned char *)data, length); + return BT_GATT_ITER_STOP; +} + +BLEProfile::BLEProfile (BLEPeripheralHelper *peripheral): + _attr_base(NULL), + _attr_index(0), + _attributes(NULL), + _num_attributes(0), + _sub_param(NULL), + _sub_param_idx(0) +{ + _peripheral = peripheral; + memset(&_discover_params, 0, sizeof(_discover_params)); + _discover_params.end_handle = 0xFFFF; + _discover_params.start_handle = 0x0001; + _discover_params.func = profile_discover_process; +} + +BLEProfile::~BLEProfile (void) +{ + if (this->_attributes) { + free(this->_attributes); + } + if (this->_attr_base) + { + free(this->_attr_base); + } + if (this->_sub_param) + { + free(this->_sub_param); + } +} + +BleStatus +BLEProfile::addAttribute (BLEAttribute& attribute) +{ + bt_gatt_attr_t *start; + BleStatus err_code = BLE_STATUS_SUCCESS; + + if (NULL == _attributes) + { + _attributes = (BLEAttribute**)malloc(BLEAttribute::numAttributes() * sizeof(BLEAttribute*)); + memset(_attributes, 0x00, BLEAttribute::numAttributes() * sizeof(BLEAttribute*)); + if (NULL == _attributes) + { + err_code = BLE_STATUS_NO_MEMORY; + } + } + if (NULL == _attr_base) + { + _attr_base = (bt_gatt_attr_t *)malloc((BLEAttribute::numAttributes() + BLECharacteristic::numNotifyAttributes()) * sizeof(bt_gatt_attr_t)); + memset(_attr_base, 0x00, ((BLEAttribute::numAttributes() + BLECharacteristic::numNotifyAttributes()) * sizeof(bt_gatt_attr_t))); + pr_info(LOG_MODULE_BLE, "_attr_base_-%p, size-%d", _attr_base, sizeof(_attr_base)); + if (NULL == _attr_base) + { + err_code = BLE_STATUS_NO_MEMORY; + } + } + if (NULL == _sub_param) + { + _sub_param = (bt_gatt_subscribe_params_t *)malloc((BLECharacteristic::numNotifyAttributes()) * sizeof(bt_gatt_subscribe_params_t)); + memset(_sub_param, 0x00, ((BLECharacteristic::numNotifyAttributes()) * sizeof(bt_gatt_subscribe_params_t))); + if (NULL == _sub_param) + { + err_code = BLE_STATUS_NO_MEMORY; + } + } + + if (BLE_STATUS_SUCCESS != err_code) + { + if (NULL != _attributes) + { + free(_attributes); + } + if (NULL != _attr_base) + { + free(_attr_base); + } + if (NULL != _sub_param) + { + free(_sub_param); + } + return err_code; + } + + _attributes[_num_attributes] = &attribute; + _num_attributes++; + start = _attr_base + _attr_index; + pr_info(LOG_MODULE_BLE, "_attr_base_-%p", _attr_base); + + BLEAttributeType type = attribute.type(); + pr_info(LOG_MODULE_BLE, "%s: idx-%d, %p, %d", __FUNCTION__,_num_attributes, &attribute ,attribute.uuid()->type); + + + if (BLETypeCharacteristic == type) + { + BLECharacteristic* characteritic = (BLECharacteristic*) &attribute; + + // Characteristic + memset(start, 0, sizeof(bt_gatt_attr_t)); + start->uuid = BLECharacteristic::getCharacteristicAttributeUuid(); + start->perm = BT_GATT_PERM_READ; + start->read = bt_gatt_attr_read_chrc; + start->user_data = characteritic->getCharacteristicAttValue(); + characteritic->addCharacteristicDeclaration(start); + + pr_info(LOG_MODULE_BLE, "chrc-%p, uuid type-%d", start, start->uuid->type); + + start++; + _attr_index++; + + // Descriptor + memset(start, 0, sizeof(bt_gatt_attr_t)); + start->uuid = characteritic->uuid(); + start->perm = characteritic->getPermission(); + start->user_data = (void*)&attribute; + characteritic->addCharacteristicValue(start); + start->read = profile_read_process; + + if (characteritic->longCharacteristic() == false) + { + // Normal characteristic MAX. 20 + start->write = profile_write_process; + } + else + { + // Long characteristic. MAX. 512 + start->write = profile_longwrite_process; + start->flush = profile_longflush_process; + } + pr_info(LOG_MODULE_BLE, "desc-%p, uuid: 0x%x", start, ((bt_uuid_16_t*) start->uuid)->val); + + start++; + _attr_index++; + // CCCD + if (characteritic->subscribed()) + { + // Descriptor + memset(start, 0, sizeof(bt_gatt_attr_t)); + start->uuid = characteritic->getClientCharacteristicConfigUuid(); + start->perm = BT_GATT_PERM_READ | BT_GATT_PERM_WRITE; + start->read = bt_gatt_attr_read_ccc; + start->write = bt_gatt_attr_write_ccc; + start->user_data = characteritic->getCccCfg(); + characteritic->addCharacteristicConfigDescriptor(start); + + pr_info(LOG_MODULE_BLE, "cccd-%p", start); + + start++; + _attr_index++; + } + } + else if (BLETypeService == type) + { + start->uuid = BLEService::getPrimayUuid(); + start->perm = BT_GATT_PERM_READ; + start->read = bt_gatt_attr_read_service; + start->user_data = attribute.uuid(); + + pr_debug(LOG_MODULE_BLE, "service-%p", start); + start++; + _attr_index++; + } + else if (BLETypeDescriptor == type) + { + start->uuid = attribute.uuid(); + start->perm = BT_GATT_PERM_READ; + start->read = profile_read_process; + start->user_data = (void*)&attribute; + + pr_debug(LOG_MODULE_BLE, "Descriptor-%p", start); + start++; + _attr_index++; + } + return err_code; +} + +int BLEProfile::registerProfile() +{ + int ret = 0; + +#if 0 + // Start debug + int i; + + for (i = 0; i < _attr_index; i++) { + { + pr_info(LOG_MODULE_APP, "gatt-: i %d, type %d, u16 0x%x", + i, + _attr_base[i].uuid->type, + BT_UUID_16(_attr_base[i].uuid)->val); + } + } + + delay(1000); + // End for debug +#endif + + ret = bt_gatt_register(_attr_base, + _attr_index); + pr_debug(LOG_MODULE_APP, "%s: ret, %d", __FUNCTION__, ret); + + return ret; +} + +void BLEProfile::characteristicDiscoverRsp(const bt_gatt_attr_t *attr, BLEAttribute* bleattr) +{ + bt_gatt_attr_t *attr_dec = declarationAttr(bleattr); + if ((NULL != attr) && (NULL != attr_dec)) + { + if (bt_uuid_cmp (attr_dec->uuid, attr->uuid) == 0) + { + attr_dec++; + attr_dec->handle = attr->handle + 1; + } + } + bleattr->discover(attr, &_discover_params); +} + +void BLEProfile::descriptorDiscoverRsp(const bt_gatt_attr_t *attr, BLEAttribute* bleattr) +{ + int err; + bt_gatt_attr_t *attr_dec = declarationAttr(bleattr); + if (BLETypeCharacteristic == bleattr->type()) + { + BLECharacteristic *chrc = (BLECharacteristic *)bleattr; + if (bt_uuid_cmp (chrc->getClientCharacteristicConfigUuid(), attr->uuid) == 0) + { + //CCCD + bt_gatt_attr_t *attr_chrc = attr_dec + 1; + bt_gatt_attr_t *attr_cccd = attr_dec + 2; + bt_gatt_subscribe_params_t *sub_param_tmp = chrc->getSubscribeParams(); + bt_gatt_subscribe_params_t *sub_param = _sub_param + _sub_param_idx; + bt_conn_t *conn = bt_conn_lookup_addr_le(_peripheral->bt_le_address()); + if (NULL == conn) + { + // Link lost + return; + } + + _sub_param_idx++; + attr_cccd->handle = attr->handle; + memcpy(sub_param, sub_param_tmp, sizeof(bt_gatt_subscribe_params_t)); + sub_param->ccc_handle = attr_cccd->handle; + sub_param->value_handle = attr_chrc->handle; + + // Enable CCCD to allow peripheral send Notification/Indication + err = bt_gatt_subscribe(conn, sub_param); + bt_conn_unref(conn); + if (err && err != -EALREADY) + { + pr_debug(LOG_MODULE_APP, "Subscribe failed (err %d)\n", err); + } + bleattr->discover(attr, &_discover_params); + } + else + { + // Not CCCD + // If want to support more descriptor, + // change the offset 3 as a loop to search the ATTR + bt_gatt_attr_t *attr_descriptor = attr_dec + 3; + if (attr_descriptor->uuid != NULL && + bt_uuid_cmp (attr_descriptor->uuid, attr->uuid) == 0) + { + attr_descriptor->handle = attr->handle; + } + } + } + else if (BLETypeDescriptor == bleattr->type()) + { + bt_gatt_attr_t *attr_descriptor = attr_dec++; // The descriptor is separate + if (bt_uuid_cmp (attr_dec->uuid, attr->uuid) == 0) + { + attr_descriptor->handle = attr->handle; + } + bleattr->discover(attr, &_discover_params); + } +} + +uint8_t BLEProfile::discover(const bt_gatt_attr_t *attr) +{ + BLEAttribute* attribute_tmp = NULL; + int i; + int err; + uint8_t ret = BT_GATT_ITER_STOP; + bool send_discover = false; + + for (i = 0; i < _num_attributes; i++) + { + // Find the discovering attribute + attribute_tmp = _attributes[i]; + if (attribute_tmp->discovering()) + { + if (NULL == attr) + { + attribute_tmp->discover(attr, &_discover_params); + break; + } + // Discover success + switch (_discover_params.type) + { + case BT_GATT_DISCOVER_CHARACTERISTIC: + { + characteristicDiscoverRsp(attr, attribute_tmp); + send_discover = true; + break; + } + case BT_GATT_DISCOVER_DESCRIPTOR: + { + descriptorDiscoverRsp(attr, attribute_tmp); + break; + } + case BT_GATT_DISCOVER_PRIMARY: + send_discover = true; + default: + { + attribute_tmp->discover(attr, &_discover_params); + break; + } + } + break; + } + } + + // Find next attribute to discover + if (attribute_tmp->discovering() == false) + { + // Current attribute complete discovery + i++; + while (i < _num_attributes) + { + attribute_tmp = _attributes[i]; + if (attribute_tmp->type() == BLETypeDescriptor) + { + // The descriptor may have been discovered by previous descriptor + bt_gatt_attr_t *attr_gatt = NULL; + for (int j = 0; j < _attr_index; j++) + { + attr_gatt = _attr_base + i; + if (attribute_tmp->uuid() == attr_gatt->uuid) + { + break; + } + } + + if (attr_gatt->handle != 0) + { + // Skip discovered descriptor + i++; + continue; + } + } + + attribute_tmp->discover(&_discover_params); + ret = BT_GATT_ITER_CONTINUE; + break; + } + } + else + { + ret = BT_GATT_ITER_CONTINUE; + } + + // Send the discover request if necessary + if (send_discover && attribute_tmp->discovering()) + { + bt_conn_t *conn = bt_conn_lookup_addr_le(_peripheral->bt_le_address()); + + ret = BT_GATT_ITER_STOP; + if (NULL == conn) + { + // Link lost + pr_debug(LOG_MODULE_APP, "Can't find connection\n"); + return ret; + } + err = bt_gatt_discover(conn, &_discover_params); + bt_conn_unref(conn); + if (err) + { + pr_debug(LOG_MODULE_APP, "Discover failed(err %d)\n", err); + return ret; + } + } + return ret; +} + + +void BLEProfile::discover() +{ + int err; + BLEService *serviceattr = (BLEService *)_attributes[0]; + bt_conn_t *conn = bt_conn_lookup_addr_le(_peripheral->bt_le_address()); + + if (NULL == conn) + { + // Link lost + pr_debug(LOG_MODULE_APP, "Can't find connection\n"); + return; + } + + // Reset start handle + _discover_params.start_handle = 0x0001; + serviceattr->discover(&_discover_params); + + err = bt_gatt_discover(conn, &_discover_params); + bt_conn_unref(conn); + if (err) + { + pr_debug(LOG_MODULE_APP, "Discover failed(err %d)\n", err); + return; + } +} + +BLEAttribute *BLEProfile::attribute(bt_gatt_subscribe_params_t *params) +{ + return attribute(params->value_handle); +} + +BLEAttribute *BLEProfile::attribute(const bt_uuid_t* uuid) +{ + int i; + BLEAttribute *attr_tmp = NULL; + BLECharacteristic *chrc_tmp = NULL; + bool att_found = false; + + for (i = 0; i < _num_attributes; i++) + { + attr_tmp = _attributes[i]; + if ((NULL == attr_tmp) || (attr_tmp->type() != BLETypeCharacteristic)) + { + continue; + } + chrc_tmp = (BLECharacteristic *)attr_tmp; + if (chrc_tmp->uuid() == uuid); + { + att_found = true; + break; + } + } + + if (false == att_found) + { + pr_debug(LOG_MODULE_APP, "Attributes not found"); + // Didn't found the characteristic + chrc_tmp = NULL; + } + return chrc_tmp; +} + + +BLEAttribute *BLEProfile::attribute(uint16_t handle) +{ + int i; + bt_gatt_attr_t *attr_gatt = NULL; + for (i = 0; i < _attr_index; i++) + { + attr_gatt = _attr_base + i; + if (handle == attr_gatt->handle) + { + break; + } + } + + if (i < _attr_index && i > 1) + { + // Found the GATT ATTR + // Serach the attribute + // Characteristic Declaration + // Characteristic Descriptor + // CCCD + attr_gatt--; + if (attr_gatt->uuid == BLECharacteristic::getCharacteristicAttributeUuid()) + { + attr_gatt++; + } + else + { + attr_gatt--; + if (attr_gatt->uuid == BLECharacteristic::getCharacteristicAttributeUuid()) + { + attr_gatt++; + } + else + { + attr_gatt = NULL; + } + } + } + else + { + attr_gatt = NULL; + } + + if (NULL != attr_gatt) + { + return attribute(attr_gatt->uuid); + } + return NULL; +} + + +void BLEProfile::clearHandles(void) +{ + int i; + bt_gatt_attr_t *attr = NULL; + // Didn't need to unsubscribe + // The stack will unsubscribe the notify when disconnected. + // The sub_param has some pointer. So can't call memset. Just reset the index. + _sub_param_idx = 0; + + for (i = 0; i < _attr_index; i++) + { + // Clear the handle + attr = _attr_base + i; + attr->handle = 0; + } +} + +bt_gatt_attr_t* BLEProfile::declarationAttr(BLEAttribute *attr) +{ + int i; + bt_gatt_attr_t *attr_gatt = NULL; + + for (i = 0; i < _attr_index; i++) + { + // Clear the handle + attr_gatt = _attr_base + i; + if (attr->uuid() == attr_gatt->uuid) + { + attr_gatt--; + return attr_gatt; + } + } + return NULL; +} + +uint16_t BLEProfile::valueHandle(BLEAttribute *attr) +{ + uint16_t handle = 0; + bt_gatt_attr_t *attr_gatt = declarationAttr(attr); + attr_gatt++; + if (attr_gatt->uuid == attr->uuid()) + { + handle = attr_gatt->handle; + } + return handle; +} + +uint16_t BLEProfile::cccdHandle(BLEAttribute *attr) +{ + uint16_t handle = 0; + bt_gatt_attr_t *attr_gatt = declarationAttr(attr); + attr_gatt+= 2; + if (attr_gatt->uuid == BLECharacteristic::getClientCharacteristicConfigUuid()) + { + handle = attr_gatt->handle; + } + return handle; +} + + + diff --git a/libraries/CurieBLE/src/BLEProfile.h b/libraries/CurieBLE/src/BLEProfile.h new file mode 100644 index 00000000..300d54e8 --- /dev/null +++ b/libraries/CurieBLE/src/BLEProfile.h @@ -0,0 +1,216 @@ +/* + * Copyright (c) 2016 Intel Corporation. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef __BLE_PROFILE_H__ +#define __BLE_PROFILE_H__ + +#include "BLECommon.h" +#include "BLEAttribute.h" +#include "BLECentralHelper.h" +#include "BLECharacteristic.h" +#include "BLEService.h" + +class BLEProfile{ +public: + BLEProfile(BLEPeripheralHelper *peripheral); + ~BLEProfile (void); + + /** + * @brief Add an attribute to the BLE Peripheral Device + * + * @param[in] attribute Attribute to add to Peripheral + * + * @return BleStatus indicating success or error + * + * @note This method must be called before the begin method + */ + BleStatus addAttribute(BLEAttribute& attribute); + + /** + * @brief Register the profile to Nordic BLE stack + * + * @param none + * + * @return int std C errno + * + * @note none + */ + int registerProfile(); + + /** + * @brief Get BLEAttribute by subscribe parameter + * + * @param[in] params Subscribe parameter + * + * @return BLEAttribute * NULL - Not found + * Not NULL - The BLEAttribute object + * + * @note none + */ + BLEAttribute *attribute(bt_gatt_subscribe_params_t *params); + + /** + * @brief Get BLEAttribute by characteristic handle + * + * @param[in] handle The characteristic handle + * + * @return BLEAttribute * NULL - Not found + * Not NULL - The BLEAttribute object + * + * @note none + */ + BLEAttribute *attribute(uint16_t handle); + + /** + * @brief Process the discover response and + * discover the BLE peripheral profile + * + * @param[in] const bt_gatt_attr_t * The gatt attribute response + * + * @return uint8_t BT_GATT_ITER_STOP Stop discover the profile + * BT_GATT_ITER_CONTINUE Continue to send the discover request + * + * @note This function only for the central device. + */ + uint8_t discover(const bt_gatt_attr_t *attr); + + /** + * @brief Discover the BLE peripheral profile + * + * @param none + * + * @return none + * + * @note This function only for the central device. + * + * @note The central deivce didn't know the connected BLE's profile. + * Need send discover request to search the attribute in the BLE peripheral + */ + void discover(); + + /** + * @brief Clear the handle in central mode + * + * @param none + * + * @return none + * + * @note The peripheral can't call this. + * Because the central need discover the handles. + * Peripheral device only get the handle when register the profile. + */ + void clearHandles(void); + + /** + * @brief Get the characteristic value handle + * + * @param[in] attr Attribute object + * + * @return uint16_t The value handle + * 0 is invalid handle + * + * @note none + */ + uint16_t valueHandle(BLEAttribute *attr); + + /** + * @brief Get characteristic configuration descriptor value handle + * + * @param[in] attr Attribute object + * + * @return uint16_t The value handle + * 0 is invalid handle + * + * @note none + */ + uint16_t cccdHandle(BLEAttribute *attr); +protected: + friend ssize_t profile_write_process(bt_conn_t *conn, + const bt_gatt_attr_t *attr, + const void *buf, uint16_t len, + uint16_t offset); +private: + /** + * @brief Get BLEAttribute by UUID + * + * @param[in] const bt_uuid_t* The UUID + * + * @return BLEAttribute * NULL - Not found + * Not NULL - The BLEAttribute object + * + * @note Use the pointer value instead the UUID value. + * Because the uuid pointer in bt_gatt_attr is got from BLEAttribute + * So set this as private. + */ + BLEAttribute *attribute(const bt_uuid_t* uuid); + + /** + * @brief Get bt_gatt_attr by BLEAttribute class + * + * @param[in] BLEAttribute * The BLEAttribute object + * + * @return bt_gatt_attr_t* NULL - Not found + * Not NULL - The bt_gatt_attr in the stack + * + * @note none + */ + bt_gatt_attr_t* declarationAttr(BLEAttribute *attr); + + /** + * @brief Process the descriptor discover response + * + * @param[in] const bt_gatt_attr_t * The discover response + * + * @param[in] BLEAttribute * The BLEAttribute object in discovering + * + * @return none + * + * @note none + */ + void descriptorDiscoverRsp(const bt_gatt_attr_t *attr, BLEAttribute* bleattr); + + /** + * @brief Process the characteristic discover response + * + * @param[in] const bt_gatt_attr_t * The discover response + * + * @param[in] BLEAttribute * The BLEAttribute object in discovering + * + * @return none + * + * @note none + */ + void characteristicDiscoverRsp(const bt_gatt_attr_t *attr, BLEAttribute* bleattr); + +private: + BLEPeripheralHelper *_peripheral; + bt_gatt_attr_t *_attr_base; + int _attr_index; + + BLEAttribute** _attributes; + uint16_t _num_attributes; + + bt_gatt_subscribe_params_t *_sub_param; + int _sub_param_idx; + + bt_gatt_discover_params_t _discover_params; +}; + +#endif + diff --git a/libraries/CurieBLE/src/BLERoleBase.cpp b/libraries/CurieBLE/src/BLERoleBase.cpp new file mode 100644 index 00000000..0285b857 --- /dev/null +++ b/libraries/CurieBLE/src/BLERoleBase.cpp @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2016 Intel Corporation. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include "internal/ble_client.h" + +#include "BLERoleBase.h" + +void bleConnectEventHandler(bt_conn_t *conn, + uint8_t err, + void *param) +{ + BLERoleBase* p = (BLERoleBase*)param; + + p->handleConnectEvent(conn, err); +} + + +void bleDisconnectEventHandler(bt_conn_t *conn, + uint8_t reason, + void *param) +{ + BLERoleBase* p = (BLERoleBase*)param; + + pr_info(LOG_MODULE_BLE, "Connect lost. Reason: %d", reason); + + p->handleDisconnectEvent(conn, reason); +} + +void bleParamUpdatedEventHandler(bt_conn_t *conn, + uint16_t interval, + uint16_t latency, + uint16_t timeout, + void *param) +{ + BLERoleBase* p = (BLERoleBase*)param; + + p->handleParamUpdated(conn, interval, latency, timeout); +} + +uint8_t BLERoleBase::m_init_cnt = 0; + +void BLERoleBase::setTxPower (int8_t tx_power) +{ + ble_gap_set_tx_power(tx_power); +} + + +BleStatus +BLERoleBase::_init() +{ + // Curie may support multi-role at same time in future. + // Make sure the BLE only init once. + if (this->m_init_cnt == 0) + { + ble_client_init (bleConnectEventHandler, this, + bleDisconnectEventHandler, this, + bleParamUpdatedEventHandler, this); + } + this->m_init_cnt++; + + return BLE_STATUS_SUCCESS; +} + +BLERoleBase::BLERoleBase(): m_connected(false) +{ + memset (_event_handlers, 0x00, sizeof (_event_handlers)); + ble_client_get_factory_config(&_local_bda, _device_name); +} + + diff --git a/libraries/CurieBLE/src/BLERoleBase.h b/libraries/CurieBLE/src/BLERoleBase.h new file mode 100644 index 00000000..b8fc5169 --- /dev/null +++ b/libraries/CurieBLE/src/BLERoleBase.h @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2016 Intel Corporation. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef __BLEROLEBASE_H__ +#define __BLEROLEBASE_H__ + +#include "BLECommon.h" + +/** + * BLE Events + */ +enum BLERoleEvent { + BLEConnected = 0, + BLEDisconnected = 1, + BLEUpdateParam, + + BLERoleEventLast +}; + +class BLEHelper; + +typedef void (*BLERoleEventHandler)(BLEHelper &role); + + +class BLERoleBase{ +public: + virtual bool begin()=0; + virtual bool disconnect()=0; + BLERoleBase(); + + /** + * Is connected? + * + * @return boolean_t true if established connection, otherwise false + */ + bool connected (void) {return m_connected;} + + /** + * Set TX output power + * + * @param[in] tx_power The antenna TX power + * + * @return boolean_t true if established connection, otherwise false + */ + void setTxPower (int8_t tx_power); +protected: + virtual BleStatus _init(void); + + friend void bleConnectEventHandler(bt_conn_t *conn, + uint8_t err, + void *param); + friend void bleDisconnectEventHandler(bt_conn_t *conn, + uint8_t reason, + void *param); + friend void bleParamUpdatedEventHandler(bt_conn_t *conn, + uint16_t interval, + uint16_t latency, + uint16_t timeout, + void *param); + + /** + * @brief Handle the connected event + * + * @param[in] conn The object that established the connection + * + * @param[in] err The code of the process + * + * @return none + * + * @note virtual function. Just define the interface and the children need to implement + */ + virtual void handleConnectEvent(bt_conn_t *conn, uint8_t err) = 0; + + /** + * @brief Handle the disconnected event + * + * @param[in] conn The object that lost the connection + * + * @param[in] reason The link lost reason + * + * @return none + * + * @note virtual function. Just define the interface and the children need to implement + */ + virtual void handleDisconnectEvent(bt_conn_t *conn, uint8_t reason) = 0; + + /** + * @brief Handle the conntion update request + * + * @param[in] conn The connection object that need to process the update request + * + * @param[in] interval The connection interval (N*1.25)ms + * + * @param[in] latency The connection latency + * + * @param[in] timeout The connection timeout (N*10)ms + * + * @return none + * + * @note virtual function. Just define the interface and the children need to implement + */ + virtual void handleParamUpdated (bt_conn_t *conn, + uint16_t interval, + uint16_t latency, + uint16_t timeout) = 0; + + char _device_name[BLE_MAX_DEVICE_NAME+1]; + bt_addr_le_t _local_bda; + BLERoleEventHandler _event_handlers[BLERoleEventLast]; + +private: + bool m_connected; + static uint8_t m_init_cnt; // Reserved for support multi-role at same time +}; + +#endif + diff --git a/libraries/CurieBLE/src/BLEService.cpp b/libraries/CurieBLE/src/BLEService.cpp index f7569e3b..906dc17d 100644 --- a/libraries/CurieBLE/src/BLEService.cpp +++ b/libraries/CurieBLE/src/BLEService.cpp @@ -20,21 +20,33 @@ #include "internal/ble_client.h" #include "BLEService.h" +bt_uuid_16_t BLEService::_gatt_primary_uuid = {BT_UUID_TYPE_16, BT_UUID_GATT_PRIMARY_VAL}; +bt_uuid_t *BLEService::getPrimayUuid(void) +{ + return (bt_uuid_t *)&_gatt_primary_uuid; +} BLEService::BLEService(const char* uuid) : BLEAttribute(uuid, BLETypeService) { } -bool -BLEService::add() { - bt_uuid uuid = btUuid(); - uint16_t handle = 0; - BleStatus status = ble_client_gatts_add_service(&uuid, BLE_GATT_SVC_PRIMARY, &handle); - if (BLE_STATUS_SUCCESS == status) { - setHandle(handle); - } +void BLEService::discover(bt_gatt_discover_params_t *params) +{ + params->type = BT_GATT_DISCOVER_PRIMARY; + + params->uuid = this->uuid(); + // Start discovering + _discoverying = true; +} - return (BLE_STATUS_SUCCESS == status); +void BLEService::discover(const bt_gatt_attr_t *attr, + bt_gatt_discover_params_t *params) +{ + params->start_handle = attr->handle + 1; + + // Complete the discover + _discoverying = false; } + diff --git a/libraries/CurieBLE/src/BLEService.h b/libraries/CurieBLE/src/BLEService.h index 17311f72..24f468ef 100644 --- a/libraries/CurieBLE/src/BLEService.h +++ b/libraries/CurieBLE/src/BLEService.h @@ -22,6 +22,10 @@ #include "BLEAttribute.h" #include "BLECommon.h" +#include "BLEProfile.h" + +class BLEPeripheral; +class BLEProfile; /** * BLE GATT Service @@ -31,14 +35,20 @@ class BLEService : public BLEAttribute { /** * Constructor for BLE Service * - * @param uuid 16-bit or 128-bit UUID (in string form) defined by BLE standard + * @param[in] uuid 16-bit or 128-bit UUID (in string form) defined by BLE standard */ BLEService(const char* uuid); protected: friend BLEPeripheral; - - bool add(void); + friend BLEProfile; + void discover(const bt_gatt_attr_t *attr, + bt_gatt_discover_params_t *params); + void discover(bt_gatt_discover_params_t *params); + + static bt_uuid_t *getPrimayUuid(void); +private: + static bt_uuid_16 _gatt_primary_uuid; }; #endif // _BLE_SERVICE_H_INCLUDED diff --git a/libraries/CurieBLE/src/BLETypedCharacteristic.h b/libraries/CurieBLE/src/BLETypedCharacteristic.h index 77828aae..65842d0f 100644 --- a/libraries/CurieBLE/src/BLETypedCharacteristic.h +++ b/libraries/CurieBLE/src/BLETypedCharacteristic.h @@ -27,18 +27,110 @@ template class BLETypedCharacteristic : public BLECharacteristic { public: + /** + * @brief The constructor of the template BLE Characteristic + * + * @param[in] uuid The characteristic UUID 16/128 bits + * + * @param[in] properties The property of the characteristic (BLERead, + * BLEWrite or BLE Notify. Combine with | ) + * + * @return none + * + * @note none + */ BLETypedCharacteristic(const char* uuid, unsigned char properties); + /** + * @brief Set the characteristic value + * + * @param[in] value New value to set + * + * @return bool true - set value success, + * false - on error + * + * @note none + */ bool setValue(T value); + /** + * @brief Get the value of the Characteristic + * + * @param none + * + * @return T The value of characteristic + * + * @note none + */ T value(void); + /** + * @brief Set the characteristic value in Little Endian + * + * @param[in] value New value to set + * + * @return bool true - set value success, + * false - on error + * + * @note none + */ bool setValueLE(T value); + /** + * @brief Get the value of the Characteristic in Little Endian + * + * @param none + * + * @return T The value of characteristic + * + * @note none + */ T valueLE(void); + /** + * @brief Set the characteristic value in Big Endian + * + * @param[in] value New value to set + * + * @return bool true - set value success, + * false - on error + * + * @note none + */ bool setValueBE(T value); + /** + * @brief Get the value of the Characteristic in Big Endian + * + * @param none + * + * @return T The value of characteristic + * + * @note none + */ T valueBE(void); + + /** + * @brief Set the peer peripheral device's characteristic value + * + * @param[in] Peripheral The peer peripheral device that want to set the characteristic value + * + * @param[in] value New value to set + * + * @return bool true - set value success, + * false - on error + * + * @note none + */ + bool write(BLEPeripheralHelper &Peripheral, T value); private: + /** + * @brief Swap the bytes + * + * @param value The typed value + * + * @return T The swapped value + * + * @note none + */ T byteSwap(T value); }; @@ -79,6 +171,10 @@ template T BLETypedCharacteristic::valueBE() { return byteSwap(value()); } +template bool BLETypedCharacteristic::write(BLEPeripheralHelper &Peripheral, T value){ + return BLECharacteristic::write(Peripheral, (unsigned char *)(&value), sizeof(T)); +} + template T BLETypedCharacteristic::byteSwap(T value) { T result; unsigned char* src = (unsigned char*)&value; diff --git a/libraries/CurieBLE/src/BLETypedCharacteristics.h b/libraries/CurieBLE/src/BLETypedCharacteristics.h index fb76cfce..1ecd2a6c 100644 --- a/libraries/CurieBLE/src/BLETypedCharacteristics.h +++ b/libraries/CurieBLE/src/BLETypedCharacteristics.h @@ -24,56 +24,199 @@ class BLEBoolCharacteristic : public BLETypedCharacteristic { public: + /** + * @brief Instantiate a bool Typed Characteristic. + * Default constructor for BLE bool Characteristic + * + * @param[in] uuid The characteristic UUID 16/128 bits + * + * @param[in] properties The property of the characteristic (BLERead, + * BLEWrite or BLE Notify. Combine with | ) + * + * @return none + * + * @note none + */ BLEBoolCharacteristic(const char* uuid, unsigned char properties); }; class BLECharCharacteristic : public BLETypedCharacteristic { public: + /** + * @brief Instantiate a Char Typed Characteristic. + * Default constructor for BLE Char Characteristic + * + * @param[in] uuid The characteristic UUID 16/128 bits + * + * @param[in] properties The property of the characteristic (BLERead, + * BLEWrite or BLE Notify. Combine with | ) + * + * @return none + * + * @note none + */ BLECharCharacteristic(const char* uuid, unsigned char properties); }; class BLEUnsignedCharCharacteristic : public BLETypedCharacteristic { public: + /** + * @brief Instantiate a Unsigned Char Typed Characteristic. + * Default constructor for BLE Unsigned Char Characteristic + * + * @param[in] uuid The characteristic UUID 16/128 bits + * + * @param[in] properties The property of the characteristic (BLERead, + * BLEWrite or BLE Notify. Combine with | ) + * + * @return none + * + * @note none + */ BLEUnsignedCharCharacteristic(const char* uuid, unsigned char properties); }; class BLEShortCharacteristic : public BLETypedCharacteristic { public: + /** + * @brief Instantiate a Short Typed Characteristic. + * Default constructor for BLE short Characteristic + * + * @param[in] uuid The characteristic UUID 16/128 bits + * + * @param[in] properties The property of the characteristic (BLERead, + * BLEWrite or BLE Notify. Combine with | ) + * + * @return none + * + * @note none + */ BLEShortCharacteristic(const char* uuid, unsigned char properties); }; class BLEUnsignedShortCharacteristic : public BLETypedCharacteristic { public: + /** + * @brief Instantiate a Unsigned Short Typed Characteristic. + * Default constructor for BLE Unsigned Short Characteristic + * + * @param[in] uuid The characteristic UUID 16/128 bits + * + * @param[in] properties The property of the characteristic (BLERead, + * BLEWrite or BLE Notify. Combine with | ) + * + * @return none + * + * @note none + */ BLEUnsignedShortCharacteristic(const char* uuid, unsigned char properties); }; class BLEIntCharacteristic : public BLETypedCharacteristic { public: + /** + * @brief Instantiate a Int Typed Characteristic. + * Default constructor for BLE Int Characteristic + * + * @param[in] uuid The characteristic UUID 16/128 bits + * + * @param[in] properties The property of the characteristic (BLERead, + * BLEWrite or BLE Notify. Combine with | ) + * + * @return none + * + * @note none + */ BLEIntCharacteristic(const char* uuid, unsigned char properties); }; class BLEUnsignedIntCharacteristic : public BLETypedCharacteristic { public: + /** + * @brief Instantiate a Unsigned Int Typed Characteristic. + * Default constructor for BLE Unsigned Int Characteristic + * + * @param[in] uuid The characteristic UUID 16/128 bits + * + * @param[in] properties The property of the characteristic (BLERead, + * BLEWrite or BLE Notify. Combine with | ) + * + * @return none + * + * @note none + */ BLEUnsignedIntCharacteristic(const char* uuid, unsigned char properties); }; class BLELongCharacteristic : public BLETypedCharacteristic { public: + /** + * @brief Instantiate a Long Typed Characteristic. + * Default constructor for BLE Long Characteristic + * + * @param[in] uuid The characteristic UUID 16/128 bits + * + * @param[in] properties The property of the characteristic (BLERead, + * BLEWrite or BLE Notify. Combine with | ) + * + * @return none + * + * @note none + */ BLELongCharacteristic(const char* uuid, unsigned char properties); }; class BLEUnsignedLongCharacteristic : public BLETypedCharacteristic { public: + /** + * @brief Instantiate a Unsigned Long Typed Characteristic. + * Default constructor for BLE Unsigned Long Characteristic + * + * @param[in] uuid The characteristic UUID 16/128 bits + * + * @param[in] properties The property of the characteristic (BLERead, + * BLEWrite or BLE Notify. Combine with | ) + * + * @return none + * + * @note none + */ BLEUnsignedLongCharacteristic(const char* uuid, unsigned char properties); }; class BLEFloatCharacteristic : public BLETypedCharacteristic { public: + /** + * @brief Instantiate a Float Typed Characteristic. + * Default constructor for BLE Float Characteristic + * + * @param[in] uuid The characteristic UUID 16/128 bits + * + * @param[in] properties The property of the characteristic (BLERead, + * BLEWrite or BLE Notify. Combine with | ) + * + * @return none + * + * @note none + */ BLEFloatCharacteristic(const char* uuid, unsigned char properties); }; class BLEDoubleCharacteristic : public BLETypedCharacteristic { public: + /** + * @brief Instantiate a Double Typed Characteristic. + * Default constructor for BLE Double Characteristic + * + * @param[in] uuid The characteristic UUID 16/128 bits + * + * @param[in] properties The property of the characteristic (BLERead, + * BLEWrite or BLE Notify. Combine with | ) + * + * @return none + * + * @note none + */ BLEDoubleCharacteristic(const char* uuid, unsigned char properties); }; diff --git a/libraries/CurieBLE/src/BLEUuid.cpp b/libraries/CurieBLE/src/BLEUuid.cpp deleted file mode 100644 index f0764383..00000000 --- a/libraries/CurieBLE/src/BLEUuid.cpp +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (c) 2015 Intel Corporation. All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#include "BLEUuid.h" - -BLEUuid::BLEUuid(const char * str) -{ - char temp[] = {0, 0, 0}; - int strLength = strlen(str); - int length = 0; - - memset(&_uuid, 0x00, sizeof(_uuid)); - - for (int i = strLength - 1; i >= 0 && length < MAX_UUID_SIZE; i -= 2) { - if (str[i] == '-') { - i++; - continue; - } - - temp[0] = str[i - 1]; - temp[1] = str[i]; - - _uuid.uuid128[length] = strtoul(temp, NULL, 16); - - length++; - } - - if (length == 2) { - _uuid.type = BT_UUID16; - } else { - _uuid.type = BT_UUID128; - } -} - -bt_uuid BLEUuid::uuid() const -{ - return _uuid; -} diff --git a/libraries/CurieBLE/src/CurieBLE.h b/libraries/CurieBLE/src/CurieBLE.h index fb51dd58..bc1be251 100644 --- a/libraries/CurieBLE/src/CurieBLE.h +++ b/libraries/CurieBLE/src/CurieBLE.h @@ -23,3 +23,5 @@ #include "BLEService.h" #include "BLEPeripheral.h" #include "BLETypedCharacteristics.h" + +#include "BLECentral.h" diff --git a/libraries/CurieBLE/src/internal/ble_client.c b/libraries/CurieBLE/src/internal/ble_client.c index a4f4cbc6..78afa966 100644 --- a/libraries/CurieBLE/src/internal/ble_client.c +++ b/libraries/CurieBLE/src/internal/ble_client.c @@ -27,6 +27,8 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ + +#include #include #include "cfw/cfw.h" @@ -48,327 +50,71 @@ #include "ble_client.h" #include "platform.h" -/* Advertising parameters */ -#define BLE_GAP_ADV_TYPE_ADV_IND 0x00 /**< Connectable undirected. */ -#define BLE_GAP_ADV_FP_ANY 0x00 /**< Allow scan requests and connect requests from any device. */ -/** options see \ref BLE_ADV_OPTIONS */ -/* options: BLE_NO_ADV_OPT */ -#define APP_ULTRA_FAST_ADV_INTERVAL 32 -#define APP_ULTRA_FAST_ADV_TIMEOUT_IN_SECONDS 180 -/* options: BLE_SLOW_ADV */ -#define APP_DISC_ADV_INTERVAL 160 -#define APP_DISC_ADV_TIMEOUT_IN_SECONDS 180 -/* options: BLE_NON_DISC_ADV */ -#define APP_NON_DISC_ADV_FAST_INTERVAL 160 -#define APP_NON_DISC_ADV_FAST_TIMEOUT_IN_SECONDS 30 -/* options: BLE_SLOW_ADV | BLE_NON_DISC_ADV */ -#define APP_NON_DISC_ADV_SLOW_INTERVAL 2056 -#define APP_NON_DISC_ADV_SLOW_TIMEOUT_IN_SECONDS 0 +#include "infra/log.h" -struct cfw_msg_rsp_sync { - volatile unsigned response; - volatile ble_status_t status; - void *param; -}; - -#define TIMEOUT_TICKS_1SEC 32768 /* ~1 second in RTC timer ticks */ -#define TIMEOUT_TICKS_1MS 32 /* ~1 millisecond in RTC timer ticks */ -#define wait_for_condition(cond, status) \ -do { \ - unsigned timeout = get_uptime_32k() + TIMEOUT_TICKS_1SEC; \ - status = BLE_STATUS_SUCCESS; \ - while (!(cond)) { \ - if (get_uptime_32k() > timeout) { \ - status = BLE_STATUS_TIMEOUT; \ - break; \ - } \ - } \ -} while(0) - -static cfw_handle_t client_handle; -static svc_client_handle_t *service_handle; -static uint16_t conn_handle; -static bool connected; - -static ble_client_gap_event_cb_t ble_client_gap_event_cb; -static void *ble_client_gap_event_param; - -static ble_client_gatts_event_cb_t ble_client_gatts_event_cb; -static void *ble_client_gatts_event_param; - -volatile struct cfw_msg_rsp_sync sync; - - -static void handle_msg_id_cfw_svc_avail_evt(cfw_svc_available_evt_msg_t *evt, void *param) -{ - if (evt->service_id == BLE_CORE_SERVICE_ID) { - sync.status = BLE_STATUS_SUCCESS; - sync.response = 1; - } -} - -static void handle_msg_id_cfw_open_svc(cfw_open_conn_rsp_msg_t *rsp, void *param) -{ - service_handle = (svc_client_handle_t *)(rsp->client_handle); - - sync.status = BLE_STATUS_SUCCESS; - sync.response = 1; -} - -static void handle_msg_id_ble_gap_wr_conf_rsp(struct ble_rsp *rsp, void *param) -{ - sync.status = rsp->status; - sync.response = 1; -} - -static void handle_msg_id_ble_gap_rd_bda_rsp(ble_bda_rd_rsp_t *rsp, void *param) -{ - ble_addr_t *p_bda = (ble_addr_t *)sync.param; - - if (p_bda && BLE_STATUS_SUCCESS == rsp->status) - memcpy(p_bda, &rsp->bd, sizeof(*p_bda)); - - sync.status = rsp->status; - sync.response = 1; -} - -static void handle_msg_id_ble_gap_sm_config_rsp(struct ble_rsp *rsp, void *param) -{ - sync.status = rsp->status; - sync.response = 1; -} - -static void handle_msg_id_ble_gap_wr_adv_data_rsp(struct ble_rsp *rsp, void *param) -{ - sync.status = rsp->status; - sync.response = 1; -} - -static void handle_msg_id_ble_gap_enable_adv_rsp(struct ble_rsp *rsp, void *param) -{ - /* No waiting for this response, so nothing to do here */ -} +// APP callback +static ble_client_connect_event_cb_t ble_client_connect_event_cb = NULL; +static void *ble_client_connect_event_param; -static void handle_msg_id_ble_gap_disable_adv_rsp(struct ble_rsp *rsp, void *param) -{ - /* No waiting for this response, so nothing to do here */ -} - -static void handle_msg_id_gatts_add_service_rsp(struct ble_gatts_add_svc_rsp *rsp, void *param) -{ - uint16_t *p_svc_handle = (uint16_t *)sync.param; - - if (p_svc_handle && BLE_STATUS_SUCCESS == rsp->status) - *p_svc_handle = rsp->svc_handle; - - sync.status = rsp->status; - sync.response = 1; -} - -static void handle_msg_id_gatts_add_characteristic_rsp(struct ble_gatts_add_char_rsp *rsp, void *param) -{ - struct ble_gatts_char_handles *p_handles = (struct ble_gatts_char_handles *)sync.param; - - if (p_handles && BLE_STATUS_SUCCESS == rsp->status) - memcpy(p_handles, &rsp->char_h, sizeof(*p_handles)); - - sync.status = rsp->status; - sync.response = 1; -} - -static void handle_msg_id_gatts_add_desc_rsp(struct ble_gatts_add_desc_rsp *rsp, void *param) -{ - uint16_t *p_handle = (uint16_t *)sync.param; - - if (p_handle && BLE_STATUS_SUCCESS == rsp->status) - *p_handle = rsp->handle; - - sync.status = rsp->status; - sync.response = 1; -} - -static void handle_msg_id_ble_gatts_set_attribute_value_rsp(struct ble_gatts_set_attr_rsp_msg *rsp, void *param) -{ - sync.status = rsp->status; - sync.response = 1; -} - -static void handle_msg_id_ble_gap_connect_evt_msg(struct ble_gap_event *evt, void *param) -{ - conn_handle = evt->conn_handle; - connected = true; - - if (ble_client_gap_event_cb) - ble_client_gap_event_cb(BLE_CLIENT_GAP_EVENT_CONNECTED, evt, ble_client_gap_event_param); -} +static ble_client_disconnect_event_cb_t ble_client_disconnect_event_cb = NULL; +static void *ble_client_disconnect_event_param; -static void handle_msg_id_ble_gap_disconnect_evt_msg(struct ble_gap_event *evt, void *param) -{ - connected = false; - - if (ble_client_gap_event_cb) - ble_client_gap_event_cb(BLE_CLIENT_GAP_EVENT_DISCONNECTED, evt, ble_client_gap_event_param); -} - -static void handle_msg_id_ble_gap_timeout_evt_msg(struct ble_gap_event *evt, void *param) -{ - connected = false; - - if (!ble_client_gap_event_cb) - return; +static ble_client_update_param_event_cb_t ble_client_update_param_event_cb = NULL; +static void *ble_client_update_param_event_param; - switch (evt->timeout.reason) { - case BLE_SVC_GAP_TO_ADV: - ble_client_gap_event_cb(BLE_CLIENT_GAP_EVENT_ADV_TIMEOUT, evt, ble_client_gap_event_param); - break; - case BLE_SVC_GAP_TO_CONN: - ble_client_gap_event_cb(BLE_CLIENT_GAP_EVENT_CONN_TIMEOUT, evt, ble_client_gap_event_param); - break; - }; -} -static void handle_msg_id_ble_gap_rssi_evt_msg(struct ble_gap_event *evt, void *param) -{ - if (ble_client_gap_event_cb) - ble_client_gap_event_cb(BLE_CLIENT_GAP_EVENT_RSSI, evt, ble_client_gap_event_param); -} +#define NIBBLE_TO_CHAR(n) \ + ((n) >= 0xA ? ('A' + (n) - 0xA) : ('0' + (n))) -static void handle_msg_id_ble_gatts_write_evt_msg(struct ble_gatts_evt_msg *evt, void *param) -{ - if (ble_client_gatts_event_cb) - ble_client_gatts_event_cb(BLE_CLIENT_GATTS_EVENT_WRITE, evt, ble_client_gatts_event_param); -} +#define BYTE_TO_STR(s, byte) \ + do { \ + *s++ = NIBBLE_TO_CHAR(byte >> 4); \ + *s++ = NIBBLE_TO_CHAR(byte & 0xF); \ + }while(0) -static void handle_msg_id_ble_gatts_send_notif_ind_rsp(ble_gatts_rsp_t *rsp, void *param) -{ - sync.status = rsp->status; - sync.response = 1; -} -static void handle_msg_id_ble_gap_disconnect_rsp(struct ble_rsp *rsp, void *param) -{ - sync.status = rsp->status; - sync.response = 1; -} +#ifdef __cplusplus +extern "C" { +#endif -static void handle_msg_id_ble_gap_set_rssi_report_rsp(struct ble_rsp *rsp, void *param) +static void on_connected(bt_conn_t *conn, uint8_t err) { - sync.status = rsp->status; - sync.response = 1; + if (ble_client_connect_event_cb) + { + ble_client_connect_event_cb(conn, err, ble_client_connect_event_param); + } } -static void handle_msg_id_ble_gap_dtm_init_rsp(struct ble_generic_msg *rsp, void *param) +static void on_disconnected(bt_conn_t *conn, uint8_t reason) { - sync.status = rsp->status; - sync.response = 1; + if (ble_client_disconnect_event_cb) + { + ble_client_disconnect_event_cb(conn, reason, ble_client_disconnect_event_param); + } } -static void ble_core_client_handle_message(struct cfw_message *msg, void *param) +static void on_le_param_updated(bt_conn_t *conn, uint16_t interval, + uint16_t latency, uint16_t timeout) { - switch (CFW_MESSAGE_ID(msg)) { - - case MSG_ID_CFW_SVC_AVAIL_EVT: - handle_msg_id_cfw_svc_avail_evt((cfw_svc_available_evt_msg_t *)msg, param); - break; - - case MSG_ID_CFW_OPEN_SERVICE: - handle_msg_id_cfw_open_svc((cfw_open_conn_rsp_msg_t *)msg, param); - break; - - case MSG_ID_BLE_GAP_WR_CONF_RSP: - handle_msg_id_ble_gap_wr_conf_rsp((struct ble_rsp *)msg, param); - break; - - case MSG_ID_BLE_GAP_RD_BDA_RSP: - handle_msg_id_ble_gap_rd_bda_rsp((ble_bda_rd_rsp_t *)msg, param); - break; - - case MSG_ID_BLE_GAP_SM_CONFIG_RSP: - handle_msg_id_ble_gap_sm_config_rsp((struct ble_rsp *)msg, param); - break; - - case MSG_ID_BLE_GAP_WR_ADV_DATA_RSP: - handle_msg_id_ble_gap_wr_adv_data_rsp((struct ble_rsp *)msg, param); - break; - - case MSG_ID_BLE_GAP_ENABLE_ADV_RSP: - handle_msg_id_ble_gap_enable_adv_rsp((struct ble_rsp *)msg, param); - break; - - case MSG_ID_BLE_GAP_DISABLE_ADV_RSP: - handle_msg_id_ble_gap_disable_adv_rsp((struct ble_rsp *)msg, param); - break; - - case MSG_ID_BLE_GATTS_ADD_SERVICE_RSP: - handle_msg_id_gatts_add_service_rsp((struct ble_gatts_add_svc_rsp *)msg, param); - break; - - case MSG_ID_BLE_GATTS_ADD_CHARACTERISTIC_RSP: - handle_msg_id_gatts_add_characteristic_rsp((struct ble_gatts_add_char_rsp *)msg, param); - break; - - case MSG_ID_BLE_GATTS_ADD_DESCRIPTOR_RSP: - handle_msg_id_gatts_add_desc_rsp((struct ble_gatts_add_desc_rsp *)msg, param); - break; - - case MSG_ID_BLE_GATTS_SET_ATTRIBUTE_VALUE_RSP: - handle_msg_id_ble_gatts_set_attribute_value_rsp((struct ble_gatts_set_attr_rsp_msg *)msg, param); - break; - - case MSG_ID_BLE_GATTS_SEND_NOTIF_RSP: - case MSG_ID_BLE_GATTS_SEND_IND_RSP: - handle_msg_id_ble_gatts_send_notif_ind_rsp((ble_gatts_rsp_t *)msg, param); - break; - - case MSG_ID_BLE_GAP_CONNECT_EVT: - handle_msg_id_ble_gap_connect_evt_msg((struct ble_gap_event *)msg, param); - break; - - case MSG_ID_BLE_GAP_DISCONNECT_EVT: - handle_msg_id_ble_gap_disconnect_evt_msg((struct ble_gap_event *)msg, param); - break; - - case MSG_ID_BLE_GAP_TO_EVT: - handle_msg_id_ble_gap_timeout_evt_msg((struct ble_gap_event *)msg, param); - break; - - case MSG_ID_BLE_GAP_RSSI_EVT: - handle_msg_id_ble_gap_rssi_evt_msg((struct ble_gap_event *)msg, param); - break; - - case MSG_ID_BLE_GATTS_WRITE_EVT: - handle_msg_id_ble_gatts_write_evt_msg((struct ble_gatts_evt_msg *)msg, param); - break; - - case MSG_ID_BLE_GAP_DISCONNECT_RSP: - handle_msg_id_ble_gap_disconnect_rsp((struct ble_rsp *)msg, param); - break; - - case MSG_ID_BLE_GAP_SET_RSSI_REPORT_RSP: - handle_msg_id_ble_gap_set_rssi_report_rsp((struct ble_rsp *)msg, param); - break; - - case MSG_ID_BLE_GAP_DTM_INIT_RSP: - handle_msg_id_ble_gap_dtm_init_rsp((struct ble_generic_msg *)msg, param); - break; + if (ble_client_update_param_event_cb) + { + ble_client_update_param_event_cb (conn, + interval, + latency, + timeout, + ble_client_update_param_event_param); } - cfw_msg_free(msg); } -#ifdef __cplusplus -extern "C" { -#endif +static struct bt_conn_cb conn_callbacks = { + .connected = on_connected, + .disconnected = on_disconnected, + .le_param_updated = on_le_param_updated +}; -#define NIBBLE_TO_CHAR(n) \ - ((n) >= 0xA ? ('A' + (n) - 0xA) : ('0' + (n))) -#define BYTE_TO_STR(s, byte) \ - do { \ - *s++ = NIBBLE_TO_CHAR(byte >> 4); \ - *s++ = NIBBLE_TO_CHAR(byte & 0xF); \ - }while(0) -void ble_client_get_factory_config(ble_addr_t *bda, char *name) +void ble_client_get_factory_config(bt_addr_le_t *bda, char *name) { struct curie_oem_data *p_oem = NULL; unsigned i; @@ -382,7 +128,7 @@ void ble_client_get_factory_config(ble_addr_t *bda, char *name) if (p_oem->bt_mac_address_type < 2) { bda->type = p_oem->bt_mac_address_type; for (i = 0; i < BLE_ADDR_LEN; i++) - bda->addr[i] = p_oem->bt_address[BLE_ADDR_LEN - 1 - i]; + bda->val[i] = p_oem->bt_address[BLE_ADDR_LEN - 1 - i]; } } } @@ -419,466 +165,72 @@ void ble_client_get_factory_config(ble_addr_t *bda, char *name) if (bda && bda->type != BLE_DEVICE_ADDR_INVALID) { *suffix++ = '-'; - BYTE_TO_STR(suffix, p_oem->bt_address[4]); - BYTE_TO_STR(suffix, p_oem->bt_address[5]); - *suffix = 0; /* NULL-terminate the string. Note the macro BYTE_TO_STR + BYTE_TO_STR(suffix, p_oem->bt_address[4]); + BYTE_TO_STR(suffix, p_oem->bt_address[5]); + *suffix = 0; /* NULL-terminate the string. Note the macro BYTE_TO_STR automatically move the pointer */ } else { - /* This code segment will be only reached if Curie module was not + /* This code segment will be only reached if Curie module was not provisioned properly with a BLE MAC address*/ *suffix++ = 0; /* NULL-terminate the string */ } } } -BleStatus ble_client_init(ble_client_gap_event_cb_t gap_event_cb, void *gap_event_param, - ble_client_gatts_event_cb_t gatts_event_cb, void *gatts_event_param) -{ - BleStatus status; - uint32_t delay_until; - - cfw_platform_nordic_init(); - - client_handle = cfw_init(cfw_get_service_queue(), - ble_core_client_handle_message, - NULL); - - sync.response = 0; - if (cfw_register_svc_available(client_handle, - BLE_CORE_SERVICE_ID, - NULL)) - return BLE_STATUS_ERROR; - - /* Wait for response messages */ - wait_for_condition(sync.response, status); - if (status != BLE_STATUS_SUCCESS) - return status; - - /* We need to wait for ~1 ms before continuing */ - delay_until = get_uptime_32k() + TIMEOUT_TICKS_1MS; - while (get_uptime_32k() < delay_until); - - sync.response = 0; - cfw_open_service(client_handle, - BLE_CORE_SERVICE_ID, - NULL); - - /* Wait for response messages */ - wait_for_condition(sync.response, status); - if (status != BLE_STATUS_SUCCESS) - return status; - - ble_client_gap_event_cb = gap_event_cb; - ble_client_gap_event_param = gap_event_param; - - ble_client_gatts_event_cb = gatts_event_cb; - ble_client_gatts_event_param = gatts_event_param; - - return sync.status; -} - -BleStatus ble_client_gap_set_enable_config(const char *name, - const ble_addr_t *bda, - const uint16_t appearance, - const int8_t tx_power, - const uint16_t min_conn_interval, - const uint16_t max_conn_interval) -{ - struct ble_wr_config config; - BleStatus status; - - config.p_bda = (bda && bda->type != BLE_DEVICE_ADDR_INVALID) ? (ble_addr_t *)bda : NULL; - config.p_name = (uint8_t *)name; - config.appearance = appearance; - config.tx_power = tx_power; - config.peripheral_conn_params.interval_min = min_conn_interval; - config.peripheral_conn_params.interval_max = max_conn_interval; - config.peripheral_conn_params.slave_latency = SLAVE_LATENCY; - config.peripheral_conn_params.link_sup_to = CONN_SUP_TIMEOUT; - config.central_conn_params.interval_min = min_conn_interval; - config.central_conn_params.interval_max = max_conn_interval; - config.central_conn_params.slave_latency = SLAVE_LATENCY; - config.central_conn_params.link_sup_to = CONN_SUP_TIMEOUT; - - sync.response = 0; - if (ble_gap_set_enable_config(service_handle, &config, NULL)) - return BLE_STATUS_ERROR; - /* Wait for response message */ - wait_for_condition(sync.response, status); - if (status != BLE_STATUS_SUCCESS) - return status; - if (sync.status) - return sync.status; - - struct ble_gap_sm_config_params sm_params = { - .options = BLE_GAP_BONDING, - .io_caps = BLE_GAP_IO_NO_INPUT_NO_OUTPUT, - .key_size = 16, - }; - sync.response = 0; - if (ble_gap_sm_config(service_handle, &sm_params, NULL)) - return BLE_STATUS_ERROR; - /* Wait for response message */ - wait_for_condition(sync.response, status); - if (status != BLE_STATUS_SUCCESS) - return status; - - return sync.status; -} - -BleStatus ble_client_gap_get_bda(ble_addr_t *p_bda) -{ - BleStatus status; - - sync.response = 0; - sync.param = (void *)p_bda; - if (ble_gap_read_bda(service_handle, NULL)) - return BLE_STATUS_ERROR; - /* Wait for response message */ - wait_for_condition(sync.response, status); - if (status != BLE_STATUS_SUCCESS) - return status; - - return sync.status; -} - -BleStatus ble_client_gap_wr_adv_data(uint8_t *adv_data, const uint8_t adv_data_len) -{ - BleStatus status; - - struct ble_gap_adv_rsp_data adv_rsp_data = { - .p_data = adv_data, - .len = adv_data_len, - }; - - /* write advertisement data */ - sync.response = 0; - if (ble_gap_wr_adv_data(service_handle, &adv_rsp_data, NULL, NULL)) - return BLE_STATUS_ERROR; - - /* Wait for response messages */ - wait_for_condition(sync.response, status); - if (status != BLE_STATUS_SUCCESS) - return status; - - return sync.status; -} - -BleStatus ble_client_gap_start_advertise(uint16_t timeout) -{ - /* Hard-coding these advertising parameters for now - * Could be changed to support advanced features such as: - * - slow advertising - * - directed advertising - * - whitelist filtering - * - etc. - */ - ble_gap_adv_param_t adv_params = { - .timeout = timeout, - .interval_min = APP_ULTRA_FAST_ADV_INTERVAL, - .interval_max = APP_ULTRA_FAST_ADV_INTERVAL, - .type = BLE_GAP_ADV_TYPE_ADV_IND, - .filter_policy = BLE_GAP_ADV_FP_ANY, - .p_peer_bda = NULL, - .options = BLE_GAP_OPT_ADV_DEFAULT, - }; - - /* For this message, we don't wait for the response, just fire - * and forget. This allows us to invoke it within the - * disconnect event handler to restart the connection - */ - return ble_gap_start_advertise(service_handle, &adv_params, NULL); -} - -BleStatus ble_client_gap_stop_advertise(void) -{ - /* For this message, we don't wait for the response, just fire - * and forget. - */ - return ble_gap_stop_advertise(service_handle, NULL); -} - -BleStatus ble_client_gatts_add_service(const struct bt_uuid *uuid, - const uint8_t type, - uint16_t *svc_handle) -{ - BleStatus status; - - sync.response = 0; - sync.param = (void *)svc_handle; - if (ble_gatts_add_service(service_handle, uuid, type, NULL, NULL)) - return BLE_STATUS_ERROR; - - /* Wait for response messages */ - wait_for_condition(sync.response, status); - if (status != BLE_STATUS_SUCCESS) - return status; - - return sync.status; -} - -BleStatus ble_client_gatts_include_service(const uint16_t primary_svc_handle, - const uint16_t included_svc_handle) +void ble_client_init(ble_client_connect_event_cb_t connect_cb, void* connect_param, + ble_client_disconnect_event_cb_t disconnect_cb, void* disconnect_param, + ble_client_update_param_event_cb_t update_param_cb, void* update_param_param) { - BleStatus status; - - sync.response = 0; - if (ble_gatts_add_included_svc(service_handle, - primary_svc_handle, - included_svc_handle, - NULL)) - return BLE_STATUS_ERROR; - - /* Wait for response messages */ - wait_for_condition(sync.response, status); - if (status != BLE_STATUS_SUCCESS) - return status; - - return sync.status; + //uint32_t delay_until; + pr_info(LOG_MODULE_BLE, "%s", __FUNCTION__); + ble_client_connect_event_cb = connect_cb; + ble_client_connect_event_param = connect_param; + + ble_client_disconnect_event_cb = disconnect_cb; + ble_client_disconnect_event_param = disconnect_param; + + ble_client_update_param_event_cb = update_param_cb; + ble_client_update_param_event_param = update_param_param; + + bt_conn_cb_register(&conn_callbacks); + return; } -BleStatus ble_client_gatts_add_characteristic(const uint16_t svc_handle, - struct ble_gatts_characteristic *char_data, - struct ble_gatts_char_handles *handles) +BleStatus errorno_to_ble_status(int err) { - BleStatus status; - - sync.response = 0; - sync.param = (void *)handles; - - if (ble_gatts_add_characteristic(service_handle, svc_handle, char_data, - NULL, NULL)) - return BLE_STATUS_ERROR; - - /* Wait for response messages */ - wait_for_condition(sync.response, status); - if (status != BLE_STATUS_SUCCESS) - return status; - - return sync.status; -} - -BleStatus ble_client_gatts_add_descriptor(const uint16_t svc_handle, - struct ble_gatts_descriptor *desc, - uint16_t *handle) -{ - BleStatus status; - - sync.response = 0; - sync.param = (void *)handle; - - if (ble_gatts_add_descriptor(service_handle, desc, NULL, NULL)) - return BLE_STATUS_ERROR; - - /* Wait for response messages */ - wait_for_condition(sync.response, status); - if (status != BLE_STATUS_SUCCESS) - return status; - - return sync.status; -} - -BleStatus ble_client_gatts_set_attribute_value(const uint16_t value_handle, - const uint16_t len, const uint8_t * p_value, - const uint16_t offset) -{ - BleStatus status; - - sync.response = 0; - if (ble_gatts_set_attribute_value(service_handle, value_handle, - len, p_value, offset, NULL)) - return BLE_STATUS_ERROR; - - /* Wait for response messages */ - wait_for_condition(sync.response, status); - if (status != BLE_STATUS_SUCCESS) - return status; - - return sync.status; -} - -BleStatus ble_client_gatts_send_notif_ind(const uint16_t value_handle, - const uint16_t len, uint8_t * p_value, - const uint16_t offset, - const bool indication) -{ - BleStatus status; - - ble_gatts_ind_params_t ind_params = { - .val_handle = value_handle, - .len = len, - .p_data = p_value, - .offset = offset, - }; - - sync.response = 0; - if (indication) - status = ble_gatts_send_ind(service_handle, conn_handle, &ind_params, NULL, NULL); - else - status = ble_gatts_send_notif(service_handle, conn_handle, &ind_params, NULL, NULL); - - if (status) - return BLE_STATUS_ERROR; - - /* Wait for response messages */ - wait_for_condition(sync.response, status); - if (status != BLE_STATUS_SUCCESS) - return status; - - return sync.status; -} - -BleStatus ble_client_gap_disconnect(const uint8_t reason) -{ - BleStatus status; - - if (!connected) - return BLE_STATUS_WRONG_STATE; - - sync.response = 0; - if (ble_gap_disconnect(service_handle, conn_handle, reason, NULL)) - return BLE_STATUS_ERROR; - - /* Wait for response messages */ - wait_for_condition(sync.response, status); - if (status != BLE_STATUS_SUCCESS) - return status; - - return sync.status; -} - -BleStatus ble_client_gap_set_rssi_report(boolean_t enable) -{ - BleStatus status; - struct rssi_report_params params; - - if (!connected) - return BLE_STATUS_WRONG_STATE; - - params.conn_hdl = conn_handle; - params.op = enable ? BLE_GAP_RSSI_ENABLE_REPORT : BLE_GAP_RSSI_DISABLE_REPORT; - /* TODO - pick sensible defaults for these and/or allow user to specify */ - params.delta_dBm = 5; - params.min_count = 3; - - sync.response = 0; - if (ble_gap_set_rssi_report(service_handle, ¶ms, NULL)) - return BLE_STATUS_ERROR; - - /* Wait for response messages */ - wait_for_condition(sync.response, status); - if (status != BLE_STATUS_SUCCESS) - return status; - - return sync.status; -} - -BleStatus ble_client_dtm_init(void) -{ - BleStatus status; - - /* Ensure that the ble_client_init() has been called already */ - if (!service_handle) - return BLE_STATUS_WRONG_STATE; - - /* Instruct the Nordic to enter Direct Test Mode */ - sync.response = 0; - ble_gap_dtm_init_req(service_handle, NULL); - - /* Wait for response messages */ - wait_for_condition(sync.response, status); - if (status != BLE_STATUS_SUCCESS) - return status; - - /* DTM is active. Detach UART IPC driver to allow direct access */ - if (BLE_STATUS_SUCCESS == sync.status) - uart_ipc_disable(IPC_UART); - - return sync.status; -} - -static int uart_raw_ble_core_tx_rx(uint8_t * send_data, uint8_t send_no, - uint8_t * rcv_data, uint8_t rcv_no) -{ - int i; - uint8_t rx_byte; - int res; - /* send command */ - for (i = 0; i < send_no; i++) - uart_poll_out(IPC_UART, send_data[i]); - /* answer */ - i = 0; - do { - res = uart_poll_in(IPC_UART, &rx_byte); - if (res == 0) { - rcv_data[i++] = rx_byte; - } - } while (i < rcv_no); - return i; + BleStatus err_code; + err = 0 - err; + + switch(err) { + case 0: + err_code = BLE_STATUS_SUCCESS; + break; + case EIO: + err_code = BLE_STATUS_WRONG_STATE; + break; + case EBUSY: + err_code = BLE_STATUS_TIMEOUT; + break; + case EFBIG: + case ENOTSUP: + err_code = BLE_STATUS_NOT_SUPPORTED; + break; + case EPERM: + case EACCES: + err_code = BLE_STATUS_NOT_ALLOWED; + break; + case ENOMEM: // No memeory + err_code = BLE_STATUS_NO_MEMORY; + break; + default: + err_code = BLE_STATUS_ERROR; + break; + } + return err_code; } -BleStatus ble_client_dtm_cmd(const struct ble_test_cmd *test_cmd, - struct ble_dtm_test_result *test_result) -{ - BleStatus status; - - uint8_t send_data[7]; - uint8_t rcv_data[9] = {}; - int send_no; - int rcv_no; - - send_data[0] = DTM_HCI_CMD; - send_data[1] = test_cmd->mode; - send_data[2] = DTM_HCI_OPCODE2; - - switch (test_cmd->mode) { - case BLE_TEST_START_DTM_RX: - send_data[3] = 1; /* length */ - send_data[4] = test_cmd->rx.freq; - send_no = 5; - rcv_no = 7; - break; - case BLE_TEST_START_DTM_TX: - send_data[3] = 3; /* length */ - send_data[4] = test_cmd->tx.freq; - send_data[5] = test_cmd->tx.len; - send_data[6] = test_cmd->tx.pattern; - send_no = 7; - rcv_no = 7; - break; - case BLE_TEST_SET_TXPOWER: - send_data[3] = 1; /* length */ - send_data[4] = test_cmd->tx_pwr.dbm; - send_no = 5; - rcv_no = 7; - break; - case BLE_TEST_END_DTM: - send_data[3] = 0; /* length */ - send_no = 4; - rcv_no = 9; - break; - default: - return BLE_STATUS_NOT_SUPPORTED; - } - - uart_raw_ble_core_tx_rx(send_data, send_no, rcv_data, rcv_no); - - status = rcv_data[DTM_HCI_STATUS_IDX]; - - test_result->mode = test_cmd->mode; - - uint8_t *p; - switch (test_cmd->mode) { - case BLE_TEST_END_DTM: - p = &rcv_data[DTM_HCI_LE_END_IDX]; - LESTREAM_TO_UINT16(p, test_result->nb); - break; - } - - return status; -} #ifdef __cplusplus } diff --git a/libraries/CurieBLE/src/internal/ble_client.h b/libraries/CurieBLE/src/internal/ble_client.h index 3fe47bd4..30a33a98 100644 --- a/libraries/CurieBLE/src/internal/ble_client.h +++ b/libraries/CurieBLE/src/internal/ble_client.h @@ -40,12 +40,13 @@ enum { }; #define MSEC_TO_UNITS(TIME, RESOLUTION) (((TIME) * 1000) / (RESOLUTION)) +#define UNITS_TO_MSEC(TIME, RESOLUTION) (((TIME) * RESOLUTION) / 1000) /* Connection parameters used for Peripheral Preferred Connection Parameterss (PPCP) and update request */ #define DEFAULT_MIN_CONN_INTERVAL MSEC_TO_UNITS(80, UNIT_1_25_MS) #define DEFAULT_MAX_CONN_INTERVAL MSEC_TO_UNITS(150, UNIT_1_25_MS) #define MIN_CONN_INTERVAL 0x0006 -#define MAX_CONN_INTERVAL 0x095f +#define MAX_CONN_INTERVAL 0x0C80 #define SLAVE_LATENCY 0 #define CONN_SUP_TIMEOUT MSEC_TO_UNITS(6000, UNIT_10_MS) @@ -87,63 +88,27 @@ enum { uuid.type = BT_UUID128; \ } while(0) -typedef enum { - BLE_CLIENT_GAP_EVENT_CONNECTED = 0, - BLE_CLIENT_GAP_EVENT_DISCONNECTED, - BLE_CLIENT_GAP_EVENT_ADV_TIMEOUT, - BLE_CLIENT_GAP_EVENT_CONN_TIMEOUT, - BLE_CLIENT_GAP_EVENT_RSSI, -} ble_client_gap_event_t; -typedef enum { - BLE_CLIENT_GATTS_EVENT_WRITE = 0, -} ble_client_gatts_event_t; +typedef void (*ble_client_connect_event_cb_t)(struct bt_conn *conn, uint8_t err, void *param); +typedef void (*ble_client_disconnect_event_cb_t)(struct bt_conn *conn, uint8_t reason, void *param); +typedef void (*ble_client_update_param_event_cb_t)(struct bt_conn *conn, + uint16_t interval, + uint16_t latency, + uint16_t timeout, + void *param); -typedef void (*ble_client_gap_event_cb_t)(ble_client_gap_event_t event, struct ble_gap_event *event_data, void *param); -typedef void (*ble_client_gatts_event_cb_t)(ble_client_gatts_event_t event, struct ble_gatts_evt_msg *event_data, void *param); #ifdef __cplusplus extern "C" { #endif -void ble_client_get_factory_config(ble_addr_t *bda, char *name); -BleStatus ble_client_init(ble_client_gap_event_cb_t gap_event_cb, - void *gap_event_param, - ble_client_gatts_event_cb_t gatts_event_cb, - void *gatts_event_param); -BleStatus ble_client_gap_set_enable_config(const char *name, - const ble_addr_t *bda, - const uint16_t appearance, - const int8_t tx_power, - const uint16_t min_conn_interval, - const uint16_t max_conn_interval); -BleStatus ble_client_gap_get_bda(ble_addr_t *p_bda); -BleStatus ble_client_gap_wr_adv_data(uint8_t *adv_data, - const uint8_t adv_data_len); -BleStatus ble_client_gap_start_advertise(uint16_t timeout); -BleStatus ble_client_gap_stop_advertise(void); -BleStatus ble_client_gatts_add_service(const struct bt_uuid *uuid, const uint8_t type, uint16_t *svc_handle); -BleStatus ble_client_gatts_include_service(const uint16_t primary_svc_handle, uint16_t included_svc_handle); -BleStatus ble_client_gatts_add_characteristic(const uint16_t svc_handle, - struct ble_gatts_characteristic *char_data, - struct ble_gatts_char_handles *handles); -BleStatus ble_client_gatts_add_descriptor(const uint16_t svc_handle, - struct ble_gatts_descriptor *desc, - uint16_t *handle); -BleStatus ble_client_gatts_set_attribute_value(const uint16_t value_handle, - const uint16_t len, const uint8_t *value, - const uint16_t offset); -BleStatus ble_client_gatts_send_notif_ind(const uint16_t value_handle, - const uint16_t len, uint8_t * p_value, - const uint16_t offset, - const bool indication); -BleStatus ble_client_gap_disconnect(const uint8_t reason); -BleStatus ble_client_gap_set_rssi_report(boolean_t enable); - -/* Direct Test Mode (DTM) API - for internal use only */ -BleStatus ble_client_dtm_init(void); -BleStatus ble_client_dtm_cmd(const struct ble_test_cmd *test_cmd, - struct ble_dtm_test_result *test_result); +void ble_client_init(ble_client_connect_event_cb_t connect_cb, void* connect_param, + ble_client_disconnect_event_cb_t disconnect_cb, void* disconnect_param, + ble_client_update_param_event_cb_t update_param_cb, void* update_param_param); +void ble_client_get_factory_config(bt_addr_le_t *bda, char *name); +void ble_gap_set_tx_power(int8_t tx_power); +BleStatus errorno_to_ble_status(int err); + #ifdef __cplusplus } diff --git a/libraries/CurieIMU/src/CurieIMU.cpp b/libraries/CurieIMU/src/CurieIMU.cpp index 635f9026..94dc4f80 100644 --- a/libraries/CurieIMU/src/CurieIMU.cpp +++ b/libraries/CurieIMU/src/CurieIMU.cpp @@ -18,7 +18,7 @@ */ #include "CurieIMU.h" -#include "internal/ss_spi.h" +#include "ss_spi.h" #include "interrupt.h" #define CURIE_IMU_CHIP_ID 0xD1 @@ -34,14 +34,7 @@ */ bool CurieIMUClass::begin() { - /* Configure pin-mux settings on the Intel Curie module to - * enable SPI mode usage */ - SET_PIN_MODE(35, QRK_PMUX_SEL_MODEA); // SPI1_SS_MISO - SET_PIN_MODE(36, QRK_PMUX_SEL_MODEA); // SPI1_SS_MOSI - SET_PIN_MODE(37, QRK_PMUX_SEL_MODEA); // SPI1_SS_SCK - SET_PIN_MODE(38, QRK_PMUX_SEL_MODEA); // SPI1_SS_CS_B[0] - - ss_spi_init(); + ss_spi_init(SPI_SENSING_1, 2000, SPI_BUSMODE_0, SPI_8_BIT, SPI_SE_1); /* Perform a dummy read from 0x7f to switch to spi interface */ uint8_t dummy_reg = 0x7F; @@ -59,14 +52,14 @@ bool CurieIMUClass::begin() void CurieIMUClass::end() { - ss_spi_disable(); + ss_spi_disable(SPI_SENSING_1); } int CurieIMUClass::getGyroRate() { int rate; - switch(BMI160Class::getGyroRate()) { + switch (BMI160Class::getGyroRate()) { case BMI160_GYRO_RATE_25HZ: rate = 25; break; @@ -133,7 +126,7 @@ float CurieIMUClass::getAccelerometerRate() { float rate; - switch(BMI160Class::getAccelRate()) { + switch (BMI160Class::getAccelRate()) { case BMI160_ACCEL_RATE_25_2HZ: rate = 12.5; break; @@ -875,8 +868,6 @@ float CurieIMUClass::getMotionDetectionDuration() int bmiDuration = BMI160Class::getMotionDetectionDuration(); return (bmiDuration / getAccelerometerRate()); - - } void CurieIMUClass::setMotionDetectionDuration(float duration) { @@ -1454,7 +1445,7 @@ void CurieIMUClass::enableInterrupt(int feature, bool enabled) setIntZeroMotionEnabled(enabled); break; - case CURIE_IMU_TAP: + case CURIE_IMU_TAP: setIntTapEnabled(enabled); break; @@ -1493,7 +1484,7 @@ bool CurieIMUClass::interruptsEnabled(int feature) case CURIE_IMU_ZERO_MOTION: return getIntZeroMotionEnabled(); - case CURIE_IMU_TAP: + case CURIE_IMU_TAP: return getIntTapEnabled(); case CURIE_IMU_DOUBLE_TAP: @@ -1562,12 +1553,13 @@ float CurieIMUClass::convertRaw(int16_t raw, float range_abs) /* Input range will be -32768 to 32767 * Output range must be -range_abs to range_abs */ - val = (float) raw; + val = (float)raw; slope = (range_abs * 2.0f) / BMI160_SENSOR_RANGE; return -(range_abs) + slope * (val + BMI160_SENSOR_LOW); } -void CurieIMUClass::readMotionSensor(int& ax, int& ay, int& az, int& gx, int& gy, int& gz) +void CurieIMUClass::readMotionSensor(int &ax, int &ay, int &az, int &gx, + int &gy, int &gz) { short sax, say, saz, sgx, sgy, sgz; @@ -1581,8 +1573,8 @@ void CurieIMUClass::readMotionSensor(int& ax, int& ay, int& az, int& gx, int& gy gz = sgz; } -void CurieIMUClass::readMotionSensorScaled(float& ax, float& ay, float& az, - float& gx, float& gy, float& gz) +void CurieIMUClass::readMotionSensorScaled(float &ax, float &ay, float &az, + float &gx, float &gy, float &gz) { int16_t sax, say, saz, sgx, sgy, sgz; @@ -1596,7 +1588,7 @@ void CurieIMUClass::readMotionSensorScaled(float& ax, float& ay, float& az, gz = convertRaw(sgz, gyro_range); } -void CurieIMUClass::readAccelerometer(int& x, int& y, int& z) +void CurieIMUClass::readAccelerometer(int &x, int &y, int &z) { short sx, sy, sz; @@ -1607,7 +1599,7 @@ void CurieIMUClass::readAccelerometer(int& x, int& y, int& z) z = sz; } -void CurieIMUClass::readAccelerometerScaled(float& x, float& y, float& z) +void CurieIMUClass::readAccelerometerScaled(float &x, float &y, float &z) { int16_t sx, sy, sz; @@ -1618,7 +1610,7 @@ void CurieIMUClass::readAccelerometerScaled(float& x, float& y, float& z) z = convertRaw(sz, accel_range); } -void CurieIMUClass::readGyro(int& x, int& y, int& z) +void CurieIMUClass::readGyro(int &x, int &y, int &z) { short sx, sy, sz; @@ -1629,7 +1621,7 @@ void CurieIMUClass::readGyro(int& x, int& y, int& z) z = sz; } -void CurieIMUClass::readGyroScaled(float& x, float& y, float& z) +void CurieIMUClass::readGyroScaled(float &x, float &y, float &z) { int16_t sx, sy, sz; @@ -1650,7 +1642,7 @@ int CurieIMUClass::readAccelerometer(int axis) return getAccelerationZ(); } - return 0; + return 0; } float CurieIMUClass::readAccelerometerScaled(int axis) @@ -1783,7 +1775,8 @@ bool CurieIMUClass::stepsDetected() * to use for accessing device registers. This implementation uses the SPI * bus on the Intel Curie module to communicate with the BMI160. */ -int CurieIMUClass::serial_buffer_transfer(uint8_t *buf, unsigned tx_cnt, unsigned rx_cnt) +int CurieIMUClass::serial_buffer_transfer(uint8_t *buf, unsigned tx_cnt, + unsigned rx_cnt) { int flags, status; @@ -1795,7 +1788,7 @@ int CurieIMUClass::serial_buffer_transfer(uint8_t *buf, unsigned tx_cnt, unsigne * - avoid delays in SPI transfer due to unrelated interrupts */ flags = interrupt_lock(); - status = ss_spi_xfer(buf, tx_cnt, rx_cnt); + status = ss_spi_xfer(SPI_SENSING_1, buf, tx_cnt, rx_cnt); interrupt_unlock(flags); return status; @@ -1831,8 +1824,8 @@ void CurieIMUClass::attachInterrupt(void (*callback)(void)) cfg.gpio_cb = bmi160_pin1_isr; soc_gpio_set_config(SOC_GPIO_AON, BMI160_GPIN_AON_PIN, &cfg); - setInterruptMode(1); // Active-Low - setInterruptDrive(0); // Push-Pull + setInterruptMode(1); // Active-Low + setInterruptDrive(0); // Push-Pull setInterruptLatch(BMI160_LATCH_MODE_10_MS); // 10ms pulse setIntEnabled(true); } diff --git a/libraries/CurieIMU/src/internal/ss_spi.c b/libraries/CurieIMU/src/internal/ss_spi.c deleted file mode 100644 index 5905aad5..00000000 --- a/libraries/CurieIMU/src/internal/ss_spi.c +++ /dev/null @@ -1,135 +0,0 @@ -/******************************************************************************* - * - * Synopsys DesignWare Sensor and Control IP Subsystem IO Software Driver and - * documentation (hereinafter, "Software") is an Unsupported proprietary work - * of Synopsys, Inc. unless otherwise expressly agreed to in writing between - * Synopsys and you. - * - * The Software IS NOT an item of Licensed Software or Licensed Product under - * any End User Software License Agreement or Agreement for Licensed Product - * with Synopsys or any supplement thereto. You are permitted to use and - * redistribute this Software in source and binary forms, with or without - * modification, provided that redistributions of source code must retain this - * notice. You may not view, use, disclose, copy or distribute this file or - * any information contained herein except pursuant to this license grant from - * Synopsys. If you do not agree with this notice, including the disclaimer - * below, then you are not authorized to use the Software. - * - * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH - * DAMAGE. - * - ******************************************************************************/ - -/******************************************************************************* - * - * Modifications Copyright (c) 2015, Intel Corporation. All rights reserved. - * - ******************************************************************************/ - -#include - -#include "eiaextensions.h" -#include "spi_priv.h" -#include "common_spi.h" -#include "soc_gpio.h" -#include "portable.h" - -#include "ss_spi.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#define SPI_FIFO_DEPTH (8UL) - -#define SS_SPI_REG_WRITE(reg, x) \ - WRITE_ARC_REG((x), AR_IO_SPI_MST1_CTRL + (reg)) -#define SS_SPI_REG_READ(reg) \ - READ_ARC_REG(AR_IO_SPI_MST1_CTRL + (reg)) - -void ss_spi_init() -{ - SET_ARC_BIT(AR_IO_CREG_MST0_CTRL, CREG_CLK_CTRL_SPI1); - - /* disable SPI controller */ - SS_SPI_REG_WRITE(SPIEN, SPI_DISABLE); - /* enable controller clock to allow register writes */ - SS_SPI_REG_WRITE(CTRL, SPI_CLK_ENABLED); - - /* SPI Mode-0, 8-bit frame size */ - SS_SPI_REG_WRITE(CTRL, SPI_CLK_ENABLED | SPI_8_BIT | (SPI_EPROM_RD << 8)); - SS_SPI_REG_WRITE(TIMING, 16); /* 2MHz (32MHz/16) */ - - /* Disable interrupts */ - SS_SPI_REG_WRITE(INTR_MASK, SPI_DISABLE_INT); -} - -void ss_spi_disable() -{ - /* gate SPI controller clock */ - SS_SPI_REG_WRITE(CTRL, 0); -} - -static inline -void spi_transmit(uint8_t *buf, size_t count, boolean_t waitCompletion) { - while (count--) - SS_SPI_REG_WRITE(DR, *buf++ | SPI_PUSH_DATA); - /* Wait for transfer to complete */ - if (waitCompletion) - while ((SS_SPI_REG_READ(TXFLR) > 0) || (SS_SPI_REG_READ(SR) & SPI_STATUS_BUSY)); -} - -static inline -void spi_receive(uint8_t *buf, size_t count) { - while (count) { - if (SS_SPI_REG_READ(RXFLR) > 0) { - SS_SPI_REG_WRITE(DR, SPI_POP_DATA); - *buf++ = SS_SPI_REG_READ(DR); - count--; - } - SS_SPI_REG_READ(RXFLR); /* Extra read of RXFLR, apparently necessary */ - } -} - -/* Polling-based SPI transfer to allow use within an ISR */ -int ss_spi_xfer(uint8_t *buf, unsigned tx_cnt, unsigned rx_cnt) -{ - uint32_t ctrl = SS_SPI_REG_READ(CTRL) & SPI_NDF_SET_MASK & SPI_TMOD_SET_MASK; - - if (rx_cnt == 0) - ctrl |= (SPI_TX_ONLY << 8); - else if (tx_cnt == 0) - ctrl |= (SPI_RX_ONLY << 8) | ((rx_cnt - 1) << 16); - else - ctrl |= (SPI_EPROM_RD << 8) | ((rx_cnt - 1) << 16); - SS_SPI_REG_WRITE(CTRL, ctrl); - - // Assert the slave-select and start the SPI transfer - SS_SPI_REG_WRITE(SPIEN, (SPI_SE_1 << 4) | SPI_ENABLE); - - if (tx_cnt) - spi_transmit(buf, tx_cnt, !(rx_cnt)); // No wait for TX-RX transfers - else - SS_SPI_REG_WRITE(DR, SPI_PUSH_DATA | 0x56); // start rx-only transfer - - if (rx_cnt) - spi_receive(buf, rx_cnt); - - // De-assert the slave-select and end the SPI transfer - SS_SPI_REG_WRITE(SPIEN, 0); - - return 0; -} - -#ifdef __cplusplus -} -#endif diff --git a/libraries/Wire/examples/master_reader/master_reader.ino b/libraries/Wire/examples/master_reader/master_reader.ino index b6748b18..5b43c4b8 100644 --- a/libraries/Wire/examples/master_reader/master_reader.ino +++ b/libraries/Wire/examples/master_reader/master_reader.ino @@ -14,20 +14,20 @@ void setup() { - Wire.begin(); // join i2c bus (address optional for master) Serial.begin(9600); // start serial for output + while(!Serial); + Wire.begin(); // join i2c bus (address optional for master) } void loop() { - Wire.requestFrom(8, 6,false); // request 6 bytes from slave device #8 + Wire.requestFrom(8, 6, true); // request 6 bytes from slave device #8 while (Wire.available()) // slave may send less than requested { char c = Wire.read(); // receive a byte as character - Serial.print(c); // print the character + Serial.print(c, HEX); // print the character Serial.println(); - } delay(500); diff --git a/libraries/Wire/examples/master_writer/master_writer.ino b/libraries/Wire/examples/master_writer/master_writer.ino index 5304fd81..1b883504 100644 --- a/libraries/Wire/examples/master_writer/master_writer.ino +++ b/libraries/Wire/examples/master_writer/master_writer.ino @@ -16,6 +16,7 @@ void setup() { Wire.begin(); // join i2c bus (address optional for master) Serial.begin(9600); + while(!Serial); } byte x = 1; @@ -26,9 +27,12 @@ void loop() //Wire.write("x is "); // sends five bytes Wire.write(x); // sends one byte int result = Wire.endTransmission(); // stop transmitting - Serial.println(); - Serial.print("x = "); - Serial.print(x); + if (result == 0) + { + Serial.println(); + Serial.print("x = "); + Serial.print(x); + } x++; delay(500); } diff --git a/libraries/Wire/src/Wire.cpp b/libraries/Wire/src/Wire.cpp index b2b557f6..2f8601f7 100644 --- a/libraries/Wire/src/Wire.cpp +++ b/libraries/Wire/src/Wire.cpp @@ -22,90 +22,91 @@ */ extern "C" { -#include #include +#include } #include "Wire.h" #include "variant.h" - -TwoWire::TwoWire(void) : rxBufferIndex(0), rxBufferLength(0), - txBufferLength(0), init_status(-1) +TwoWire::TwoWire(I2C_CONTROLLER _controller_id) + : rxBufferIndex(0), rxBufferLength(0), init_status(-1), + controller_id(_controller_id) { - // Empty + // Empty } void TwoWire::begin(void) { - init_status = i2c_openadapter(); + init_status = i2c_openadapter(controller_id); } void TwoWire::begin(int i2c_speed) { - init_status = i2c_openadapter_speed(i2c_speed); + init_status = i2c_openadapter_speed(controller_id, i2c_speed); } void TwoWire::setClock(long speed) { - if(speed == 400000L) { - init_status = i2c_openadapter_speed(I2C_SPEED_FAST); - } else if(speed == 100000L) { - init_status = i2c_openadapter_speed(I2C_SPEED_SLOW); - } else if(speed == I2C_SPEED_FAST) { - init_status = i2c_openadapter_speed(I2C_SPEED_FAST); - }else { - init_status = i2c_openadapter(); + if (speed == 400000L) { + init_status = i2c_openadapter_speed(controller_id, I2C_SPEED_FAST); + } else if (speed == 100000L) { + init_status = i2c_openadapter_speed(controller_id, I2C_SPEED_SLOW); + } else if (speed == I2C_SPEED_FAST) { + init_status = i2c_openadapter_speed(controller_id, I2C_SPEED_FAST); + } else { + init_status = i2c_openadapter(controller_id); } } -uint8_t TwoWire::requestFrom(uint8_t address, uint8_t quantity, uint8_t sendStop) +uint8_t TwoWire::requestFrom(uint8_t address, uint8_t quantity, + uint8_t sendStop) { - int ret; - if (quantity > BUFFER_LENGTH) - quantity = BUFFER_LENGTH; + int ret; + if (quantity > BUFFER_LENGTH) + quantity = BUFFER_LENGTH; - /* Set slave address via ioctl */ - i2c_setslave(address); - ret = i2c_readbytes(rxBuffer, quantity, !sendStop); - if (ret < 0) { - return 0; - } - // set rx buffer iterator vars - rxBufferIndex = 0; - rxBufferLength = quantity; + /* Set slave address via ioctl */ + i2c_setslave(controller_id, address); + ret = i2c_readbytes(controller_id, rxBuffer, quantity, !sendStop); + if (ret < 0) { + return 0; + } + // set rx buffer iterator vars + rxBufferIndex = 0; + rxBufferLength = quantity; - return quantity; + return quantity; } uint8_t TwoWire::requestFrom(uint8_t address, uint8_t quantity) { - return requestFrom((uint8_t) address, (uint8_t) quantity, (uint8_t) true); + return requestFrom((uint8_t)address, (uint8_t)quantity, (uint8_t) true); } uint8_t TwoWire::requestFrom(int address, int quantity) { - return requestFrom((uint8_t) address, (uint8_t) quantity, (uint8_t) true); + return requestFrom((uint8_t)address, (uint8_t)quantity, (uint8_t) true); } uint8_t TwoWire::requestFrom(int address, int quantity, int sendStop) { - return requestFrom((uint8_t) address, (uint8_t) quantity, (uint8_t) sendStop); + return requestFrom((uint8_t)address, (uint8_t)quantity, (uint8_t)sendStop); } void TwoWire::beginTransmission(uint8_t address) { - if (init_status < 0) - return; - // set slave address - i2c_setslave(address); - // reset transmit buffer - txBufferLength = 0; + if (init_status < 0) + return; + // set slave address + i2c_setslave(controller_id, address); + // reset transmit buffer + txBufferLength = 0; } void TwoWire::beginTransmission(int address) { - beginTransmission((uint8_t) address); + beginTransmission((uint8_t)address); } // @@ -123,22 +124,23 @@ void TwoWire::beginTransmission(int address) // uint8_t TwoWire::endTransmission(uint8_t sendStop) { - int err; - // transmit buffer (blocking) - if (txBufferLength >= 1) { - err = i2c_writebytes(txBuffer, txBufferLength, !sendStop); - } else { - uint8_t temp = 0; - // Workaround: I2C bus scan is currently implemented by reading, - // so set the read length to 0 to inform the lower I2C driver that we are doing bus scan - err = i2c_readbytes(&temp, 0, 0); - } - // empty buffer - txBufferLength = 0; - if (err < 0) { - return -err; - } - return 0; // success + int err; + // transmit buffer (blocking) + if (txBufferLength >= 1) { + err = + i2c_writebytes(controller_id, txBuffer, txBufferLength, !sendStop); + } else { + uint8_t temp = 0; + // Workaround: I2C bus scan is currently implemented by reading, + // so set the read length to 0 to inform the lower I2C driver that we are doing bus scan + err = i2c_readbytes(controller_id, &temp, 0, 0); + } + // empty buffer + txBufferLength = 0; + if (err < 0) { + return -err; + } + return 0; // success } // This provides backwards compatibility with the original @@ -146,52 +148,52 @@ uint8_t TwoWire::endTransmission(uint8_t sendStop) // uint8_t TwoWire::endTransmission(void) { - return endTransmission(true); + return endTransmission(true); } size_t TwoWire::write(uint8_t data) { - if (txBufferLength >= BUFFER_LENGTH) - return 0; - txBuffer[txBufferLength++] = data; - return 1; + if (txBufferLength >= BUFFER_LENGTH) + return 0; + txBuffer[txBufferLength++] = data; + return 1; } size_t TwoWire::write(const uint8_t *data, size_t quantity) { - for (size_t i = 0; i < quantity; ++i) { - if (txBufferLength >= BUFFER_LENGTH) - return i; - txBuffer[txBufferLength++] = data[i]; - } - return quantity; + for (size_t i = 0; i < quantity; ++i) { + if (txBufferLength >= BUFFER_LENGTH) + return i; + txBuffer[txBufferLength++] = data[i]; + } + return quantity; } int TwoWire::available(void) { - return rxBufferLength - rxBufferIndex; + return rxBufferLength - rxBufferIndex; } int TwoWire::read(void) { - if (rxBufferIndex < rxBufferLength) - return rxBuffer[rxBufferIndex++]; - return -1; + if (rxBufferIndex < rxBufferLength) + return rxBuffer[rxBufferIndex++]; + return -1; } int TwoWire::peek(void) { - if (rxBufferIndex < rxBufferLength) - return rxBuffer[rxBufferIndex]; - return -1; + if (rxBufferIndex < rxBufferLength) + return rxBuffer[rxBufferIndex]; + return -1; } void TwoWire::flush(void) { - // Do nothing, use endTransmission(..) to force - // data transfer. + // Do nothing, use endTransmission(..) to force + // data transfer. } // Preinstantiate Objects ////////////////////////////////////////////////////// -TwoWire Wire = TwoWire(); +TwoWire Wire = TwoWire(I2C_SENSING_0); diff --git a/libraries/Wire/src/Wire.h b/libraries/Wire/src/Wire.h index f1488f41..a18e1f19 100644 --- a/libraries/Wire/src/Wire.h +++ b/libraries/Wire/src/Wire.h @@ -23,6 +23,7 @@ #include "Stream.h" #include "variant.h" +#include "ss_i2c_iface.h" #define BUFFER_LENGTH 32 #define I2C_SPEED_SLOW 1 @@ -30,9 +31,9 @@ class TwoWire : public Stream { public: - TwoWire(void); - void begin(); - void begin(int); + TwoWire(I2C_CONTROLLER _controller_id); + void begin(void); + void begin(int speed); void setClock(long speed); void beginTransmission(uint8_t); void beginTransmission(int); @@ -67,6 +68,8 @@ class TwoWire : public Stream { uint8_t txBufferLength; int init_status; + + I2C_CONTROLLER controller_id; }; #if WIRE_INTERFACES_COUNT > 0 diff --git a/platform.txt b/platform.txt index e5493cb2..e0ff63ce 100644 --- a/platform.txt +++ b/platform.txt @@ -5,7 +5,7 @@ # https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5---3rd-party-Hardware-specification name=Intel Curie (32-bit) Boards -version=1.0.7 +version=2.0.0 # Arduino 101 compile variables # ---------------------- @@ -14,12 +14,12 @@ compiler.prefix=arc-elf32 compiler.path={runtime.tools.arc-elf32.path}/bin/ compiler.c.cmd=arc-elf32-gcc -compiler.c.flags=-c -std=gnu11 -mcpu=quarkse_em -mlittle-endian -g -Os -Wall -fno-reorder-functions -fno-asynchronous-unwind-tables -fno-omit-frame-pointer -fno-defer-pop -Wno-unused-but-set-variable -Wno-main -ffreestanding -fno-stack-protector -mno-sdata -ffunction-sections -fdata-sections -fsigned-char -MMD -D__ARDUINO_ARC__ +compiler.c.flags=-c -std=gnu11 -mcpu=quarkse_em -mlittle-endian -g -Os -Wall -fno-reorder-functions -fno-asynchronous-unwind-tables -fno-omit-frame-pointer -fno-defer-pop -Wno-unused-but-set-variable -Wno-main -ffreestanding -fno-stack-protector -mno-sdata -ffunction-sections -fdata-sections -fsigned-char -MMD -D__ARDUINO_ARC__ -DCONFIG_BLUETOOTH_PERIPHERAL -DCONFIG_BLUETOOTH_CENTRAL -DCONFIG_BLUETOOTH_GATT_CLIENT compiler.c.elf.cmd=arc-elf32-gcc compiler.c.elf.flags=-nostartfiles -nodefaultlibs -nostdlib -static -Wl,-X -Wl,-N -Wl,-mcpu=quarkse_em -Wl,-marcelf -Wl,--gc-sections compiler.S.flags=-c -g -x assembler-with-cpp compiler.cpp.cmd=arc-elf32-g++ -compiler.cpp.flags=-c -mcpu=quarkse_em -mlittle-endian -g -Os -Wall -fno-reorder-functions -fno-asynchronous-unwind-tables -fno-omit-frame-pointer -fno-defer-pop -Wno-unused-but-set-variable -Wno-main -ffreestanding -fno-stack-protector -mno-sdata -ffunction-sections -fdata-sections -fsigned-char -MMD -fno-rtti -fno-exceptions -D__ARDUINO_ARC__ -std=c++11 +compiler.cpp.flags=-c -mcpu=quarkse_em -mlittle-endian -g -Os -Wall -fno-reorder-functions -fno-asynchronous-unwind-tables -fno-omit-frame-pointer -fno-defer-pop -Wno-unused-but-set-variable -Wno-main -ffreestanding -fno-stack-protector -mno-sdata -ffunction-sections -fdata-sections -fsigned-char -MMD -fno-rtti -fno-exceptions -D__ARDUINO_ARC__ -std=c++11 -DCONFIG_BLUETOOTH_PERIPHERAL -DCONFIG_BLUETOOTH_CENTRAL -DCONFIG_BLUETOOTH_GATT_CLIENT compiler.ar.cmd=arc-elf32-ar compiler.ar.flags=rcs compiler.objcopy.cmd=arc-elf32-objcopy @@ -93,8 +93,8 @@ recipe.size.regex=^(?:text|ctors|rodata|datas)\s+([0-9]+).* # BLE firmware check # ------------------- -tools.arduino101load.ble.fw.string="ATP1BLE000-1541C5635" -tools.arduino101load.ble.fw.position=141312 +tools.arduino101load.ble.fw.string="ATP1BLE00R-1631C4439" +tools.arduino101load.ble.fw.position=169984 # Arc Uploader/Programmers tools # ------------------- diff --git a/system/libarc32_arduino101/Makefile b/system/libarc32_arduino101/Makefile index 9602e3ad..2e947bc9 100644 --- a/system/libarc32_arduino101/Makefile +++ b/system/libarc32_arduino101/Makefile @@ -3,10 +3,12 @@ ASM_SRC+=$(wildcard $(PWD)/drivers/*.S) ASM_SRC+=$(wildcard $(PWD)/common/*.S) C_SRC+=$(wildcard $(PWD)/bootcode/*.c) C_SRC+=$(wildcard $(PWD)/drivers/*.c) +C_SRC+=$(wildcard $(PWD)/drivers/rpc/*.c) C_SRC+=$(wildcard $(PWD)/common/*.c) C_SRC+=$(wildcard $(PWD)/framework/src/*.c) C_SRC+=$(wildcard $(PWD)/framework/src/services/*.c) C_SRC+=$(wildcard $(PWD)/framework/src/services/ble/*.c) +C_SRC+=$(wildcard $(PWD)/framework/src/services/ble_service/*.c) C_SRC+=$(wildcard $(PWD)/framework/src/cfw/*.c) C_SRC+=$(wildcard $(PWD)/framework/src/infra/*.c) C_SRC+=$(wildcard $(PWD)/framework/src/util/*.c) @@ -25,8 +27,21 @@ HWFLAGS=-mARCv2EM -mav2em -mlittle-endian CFGFLAGS=-DCONFIG_SOC_GPIO_32 -DCONFIG_SOC_GPIO_AON -DINFRA_MULTI_CPU_SUPPORT -DCFW_MULTI_CPU_SUPPORT -DCONFIG_HAS_SHARED_MEM -DCONFIG_INFRA_IS_MASTER OPTFLAGS=-g -Os -Wall -Werror +CFGFLAGS+=-DCONFIG_SOC_QUARK_SE +#CFGFLAGS+=-DTRACK_ALLOCS +#CFGFLAGS+=-DIPC_UART_DBG_RX +#CFGFLAGS+=-DIPC_UART_DBG_TX +CFGFLAGS+=-DBT_GATT_DEBUG +CFGFLAGS+=-DCONFIG_RPC_IN +CFGFLAGS+=-DCONFIG_IPC_UART_NS16550 CFGFLAGS+=-DCONFIG_IPC_UART_BAUDRATE=1000000 -INCLUDES=-I. -Icommon -Idrivers -Ibootcode -Iframework/include -Iframework/src/services/ble +CFGFLAGS+=-DCONFIG_BLUETOOTH_MAX_CONN=2 +CFGFLAGS+=-DCONFIG_BT_GATT_BLE_MAX_SERVICES=10 +CFGFLAGS+=-DCONFIG_BLUETOOTH_GATT_CLIENT +CFGFLAGS+=-DCONFIG_BLUETOOTH_CENTRAL -DCONFIG_BLUETOOTH_PERIPHERAL +INCLUDES=-I. -Icommon -Idrivers -Ibootcode -Iframework/include -Iframework/include/services/ble -Iframework/src/services/ble_service +#-Iframework/src/services/ble -Iframework/include/services/ble +INCLUDES+= -Idrivers/rpc -Iframework/src EXTRA_CFLAGS=-D__CPU_ARC__ -DCLOCK_SPEED=32 -std=c99 -fno-reorder-functions -fno-asynchronous-unwind-tables -fno-omit-frame-pointer -fno-defer-pop -Wno-unused-but-set-variable -Wno-main -ffreestanding -fno-stack-protector -mno-sdata -ffunction-sections -fdata-sections CFLAGS=$(HWFLAGS) $(OPTFLAGS) $(EXTRA_CFLAGS) $(CFGFLAGS) $(INCLUDES) @@ -39,7 +54,7 @@ lib: $(TARGET_LIB) $(TARGET_LIB): $(C_OBJ) $(ASM_OBJ) @echo "Link $@" - $(AR) rcs $@ $^ + @$(AR) rcs $@ $^ %.o: %.S @echo "Assembling $<" @@ -47,7 +62,7 @@ $(TARGET_LIB): $(C_OBJ) $(ASM_OBJ) %.o: %.c @echo "Compiling $<" - $(CC) -c $(CFLAGS) $< -o $@ + @$(CC) -c $(CFLAGS) $< -o $@ lib_install: lib @if test "$(LIB_INSTALL_PATH)" = "" ; then \ diff --git a/system/libarc32_arduino101/common/atomic.h b/system/libarc32_arduino101/common/atomic.h new file mode 100644 index 00000000..d30cfbe4 --- /dev/null +++ b/system/libarc32_arduino101/common/atomic.h @@ -0,0 +1,156 @@ +/* atomic operations */ + +/* + * Copyright (c) 1997-2015, Wind River Systems, Inc. + * + * 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 __ATOMIC_H__ +#define __ATOMIC_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef int atomic_t; +typedef atomic_t atomic_val_t; + +extern atomic_val_t atomic_add(atomic_t *target, atomic_val_t value); +extern atomic_val_t atomic_and(atomic_t *target, atomic_val_t value); +extern atomic_val_t atomic_dec(atomic_t *target); +extern atomic_val_t atomic_inc(atomic_t *target); +extern atomic_val_t atomic_nand(atomic_t *target, atomic_val_t value); +extern atomic_val_t atomic_or(atomic_t *target, atomic_val_t value); +extern atomic_val_t atomic_sub(atomic_t *target, atomic_val_t value); +extern atomic_val_t atomic_xor(atomic_t *target, atomic_val_t value); +extern atomic_val_t atomic_clear(atomic_t *target); +extern atomic_val_t atomic_get(const atomic_t *target); +extern atomic_val_t atomic_set(atomic_t *target, atomic_val_t value); +extern int atomic_cas(atomic_t *target, + atomic_val_t oldValue, atomic_val_t newValue); + + +#define ATOMIC_INIT(i) {(i)} + +#define ATOMIC_BITS (sizeof(atomic_val_t) * 8) +#define ATOMIC_MASK(bit) (1 << ((bit) & (ATOMIC_BITS - 1))) +#define ATOMIC_ELEM(addr, bit) ((addr) + ((bit) / ATOMIC_BITS)) + +/** @brief Test whether a bit is set + * + * Test whether bit number bit is set or not. + * + * Also works for an array of multiple atomic_t variables, in which + * case the bit number may go beyond the number of bits in a single + * atomic_t variable. + * + * @param addr base address to start counting from + * @param bit bit number counted from the base address + * + * @return 1 if the bit was set, 0 if it wasn't + */ +static inline int atomic_test_bit(const atomic_t *addr, int bit) +{ + atomic_val_t val = atomic_get(ATOMIC_ELEM(addr, bit)); + + return (1 & (val >> (bit & (ATOMIC_BITS - 1)))); +} + +/** @brief Clear a bit and return its old value + * + * Atomically clear a bit and return its old value. + * + * Also works for an array of multiple atomic_t variables, in which + * case the bit number may go beyond the number of bits in a single + * atomic_t variable. + * + * @param addr base address to start counting from + * @param bit bit number counted from the base address + * + * @return 1 if the bit was set, 0 if it wasn't + */ +static inline int atomic_test_and_clear_bit(atomic_t *addr, int bit) +{ + atomic_val_t mask = ATOMIC_MASK(bit); + atomic_val_t old; + + old = atomic_and(ATOMIC_ELEM(addr, bit), ~mask); + + return (old & mask) != 0; +} + +/** @brief Set a bit and return its old value + * + * Atomically set a bit and return its old value. + * + * Also works for an array of multiple atomic_t variables, in which + * case the bit number may go beyond the number of bits in a single + * atomic_t variable. + * + * @param addr base address to start counting from + * @param bit bit number counted from the base address + * + * @return 1 if the bit was set, 0 if it wasn't + */ +static inline int atomic_test_and_set_bit(atomic_t *addr, int bit) +{ + atomic_val_t mask = ATOMIC_MASK(bit); + atomic_val_t old; + + old = atomic_or(ATOMIC_ELEM(addr, bit), mask); + + return (old & mask) != 0; +} + +/** @brief Clear a bit + * + * Atomically clear a bit. + * + * Also works for an array of multiple atomic_t variables, in which + * case the bit number may go beyond the number of bits in a single + * atomic_t variable. + * + * @param addr base address to start counting from + * @param bit bit number counted from the base address + */ +static inline void atomic_clear_bit(atomic_t *addr, int bit) +{ + atomic_val_t mask = ATOMIC_MASK(bit); + + atomic_and(ATOMIC_ELEM(addr, bit), ~mask); +} + +/** @brief Set a bit + * + * Atomically set a bit. + * + * Also works for an array of multiple atomic_t variables, in which + * case the bit number may go beyond the number of bits in a single + * atomic_t variable. + * + * @param addr base address to start counting from + * @param bit bit number counted from the base address + */ +static inline void atomic_set_bit(atomic_t *addr, int bit) +{ + atomic_val_t mask = ATOMIC_MASK(bit); + + atomic_or(ATOMIC_ELEM(addr, bit), mask); +} + +#ifdef __cplusplus +} +#endif + +#endif /* __ATOMIC_H__ */ diff --git a/system/libarc32_arduino101/common/misc/byteorder.h b/system/libarc32_arduino101/common/misc/byteorder.h new file mode 100644 index 00000000..67cecbc3 --- /dev/null +++ b/system/libarc32_arduino101/common/misc/byteorder.h @@ -0,0 +1,44 @@ +/* byteorder.h - Byte order helpers */ + +/* + * Copyright (c) 2015, Intel Corporation. + * + * 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. + */ + +#define bswap_16(x) ((uint16_t) ((((x) >> 8) & 0xff) | (((x) & 0xff) << 8))) + +#define bswap_32(x) ((uint32_t) ((((x) >> 24) & 0xff) | (((x) >> 8) & 0xff00) \ + | (((x) & 0xff00) << 8) | (((x) & 0xff) << 24))) + +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ +#define sys_le16_to_cpu(val) (val) +#define sys_cpu_to_le16(val) (val) +#define sys_be16_to_cpu(val) bswap_16(val) +#define sys_cpu_to_be16(val) bswap_16(val) +#define sys_le32_to_cpu(val) (val) +#define sys_cpu_to_le32(val) (val) +#define sys_be32_to_cpu(val) bswap_32(val) +#define sys_cpu_to_be32(val) bswap_32(val) +#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ +#define sys_le16_to_cpu(val) bswap_16(val) +#define sys_cpu_to_le16(val) bswap_16(val) +#define sys_be16_to_cpu(val) (val) +#define sys_cpu_to_be16(val) (val) +#define sys_le32_to_cpu(val) bswap_32(val) +#define sys_cpu_to_le32(val) bswap_32(val) +#define sys_be32_to_cpu(val) (val) +#define sys_cpu_to_be32(val) (val) +#else +#error "Unknown byte order" +#endif diff --git a/system/libarc32_arduino101/common/misc/util.h b/system/libarc32_arduino101/common/misc/util.h index 626c2b69..ab45bbb1 100644 --- a/system/libarc32_arduino101/common/misc/util.h +++ b/system/libarc32_arduino101/common/misc/util.h @@ -44,6 +44,11 @@ extern "C" { #ifndef _ASMLANGUAGE +#define ARRAY_SIZE(array) ((unsigned long)(sizeof(array) / sizeof((array)[0]))) +#define CONTAINER_OF(ptr, type, field) \ + ((type *)(((char *)(ptr)) - offsetof(type, field))) + + /* round "x" up/down to next multiple of "align" (which must be a power of 2) */ #define ROUND_UP(x, align) \ (((unsigned long)(x) + ((unsigned long)align - 1)) & \ diff --git a/system/libarc32_arduino101/common/scss_registers.h b/system/libarc32_arduino101/common/scss_registers.h index 600459a4..33f08633 100644 --- a/system/libarc32_arduino101/common/scss_registers.h +++ b/system/libarc32_arduino101/common/scss_registers.h @@ -456,4 +456,8 @@ #define I2C0_CLK_GATE_MASK 0x00080004 #define I2C1_CLK_GATE_MASK 0x00100008 #define I2S_CLK_GATE_MASK 0x00200200 +#define SS_SPI0_CLK_GATE_MASK 0x00000008 +#define SS_SPI1_CLK_GATE_MASK 0x00000010 +#define SS_I2C0_CLK_GATE_MASK 0x00000002 +#define SS_I2C1_CLK_GATE_MASK 0x00000004 #endif /* SCSS_REGISTERS_H_ */ diff --git a/system/libarc32_arduino101/common/ss_i2c_iface.h b/system/libarc32_arduino101/common/ss_i2c_iface.h index ee5e8a8b..e85e3ae7 100644 --- a/system/libarc32_arduino101/common/ss_i2c_iface.h +++ b/system/libarc32_arduino101/common/ss_i2c_iface.h @@ -48,7 +48,8 @@ typedef enum { I2C_SENSING_0 = 0, /*!< Sensing I2C controller 0, accessibly by Sensor Subsystem Core only */ - I2C_SENSING_1 /*!< Sensing I2C controller 1, accessible by Sensor Subsystem Core only */ + I2C_SENSING_1, /*!< Sensing I2C controller 1, accessible by Sensor Subsystem Core only */ + NUM_SS_I2C /*!< Number of Sensor Subsystem I2C controllers */ } I2C_CONTROLLER; #ifdef __cplusplus diff --git a/system/libarc32_arduino101/drivers/atomic_native.c b/system/libarc32_arduino101/drivers/atomic_native.c new file mode 100644 index 00000000..41bed7d4 --- /dev/null +++ b/system/libarc32_arduino101/drivers/atomic_native.c @@ -0,0 +1,370 @@ +/* + * Copyright (c) 2016 Intel Corporation + * Copyright (c) 2011-2014 Wind River Systems, Inc. + * + * 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. + */ + +/** + * @file Atomic ops for ARC EM + * + * This module provides the atomic operators for ARC EM family processors + * which do not support native atomic operations. + * + * The atomic operations are guaranteed to be atomic with respect + * to interrupt service routines, and to operations performed by peer + * processors. + * + * (originally from x86's atomic.c) + */ + +#include +//#include +//#include +#include +#define irq_lock() interrupt_lock() +#define irq_unlock(key) interrupt_unlock(key) + +#if defined(__clang__) +#define FUNC_NO_FP +#else +#define FUNC_NO_FP __attribute__((optimize("-fomit-frame-pointer"))) +#endif +/** + * + * @brief Atomic compare-and-set primitive + * + * This routine provides the compare-and-set operator. If the original value at + * equals , then is stored at and the + * function returns 1. + * + * If the original value at does not equal , then the store + * is not done and the function returns 0. + * + * The reading of the original value at , the comparison, + * and the write of the new value (if it occurs) all happen atomically with + * respect to both interrupts and accesses of other processors to . + * + * @param target address to be tested + * @param old_value value to compare against + * @param new_value value to compare against + * @return Returns 1 if is written, 0 otherwise. + */ +FUNC_NO_FP int atomic_cas(atomic_t *target, atomic_val_t old_value, + atomic_val_t new_value) +{ + unsigned int key; + int ret = 0; + + key = irq_lock(); + + if (*target == old_value) { + *target = new_value; + ret = 1; + } + + irq_unlock(key); + + return ret; +} + +/** + * + * @brief Atomic addition primitive + * + * This routine provides the atomic addition operator. The is + * atomically added to the value at , placing the result at , + * and the old value from is returned. + * + * @param target memory location to add to + * @param value the value to add + * + * @return The previous value from + */ +FUNC_NO_FP atomic_val_t atomic_add(atomic_t *target, atomic_val_t value) +{ + unsigned int key; + atomic_val_t ret; + + key = irq_lock(); + + ret = *target; + *target += value; + + irq_unlock(key); + + return ret; +} + +/** + * + * @brief Atomic subtraction primitive + * + * This routine provides the atomic subtraction operator. The is + * atomically subtracted from the value at , placing the result at + * , and the old value from is returned. + * + * @param target the memory location to subtract from + * @param value the value to subtract + * + * @return The previous value from + */ +FUNC_NO_FP atomic_val_t atomic_sub(atomic_t *target, atomic_val_t value) +{ + unsigned int key; + atomic_val_t ret; + + key = irq_lock(); + + ret = *target; + *target -= value; + + irq_unlock(key); + + return ret; +} + +/** + * + * @brief Atomic increment primitive + * + * @param target memory location to increment + * + * This routine provides the atomic increment operator. The value at + * is atomically incremented by 1, and the old value from is returned. + * + * @return The value from before the increment + */ +FUNC_NO_FP atomic_val_t atomic_inc(atomic_t *target) +{ + unsigned int key; + atomic_val_t ret; + + key = irq_lock(); + + ret = *target; + (*target)++; + + irq_unlock(key); + + return ret; +} + +/** + * + * @brief Atomic decrement primitive + * + * @param target memory location to decrement + * + * This routine provides the atomic decrement operator. The value at + * is atomically decremented by 1, and the old value from is returned. + * + * @return The value from prior to the decrement + */ +FUNC_NO_FP atomic_val_t atomic_dec(atomic_t *target) +{ + unsigned int key; + atomic_val_t ret; + + key = irq_lock(); + + ret = *target; + (*target)--; + + irq_unlock(key); + + return ret; +} + +/** + * + * @brief Atomic get primitive + * + * @param target memory location to read from + * + * This routine provides the atomic get primitive to atomically read + * a value from . It simply does an ordinary load. Note that + * is expected to be aligned to a 4-byte boundary. + * + * @return The value read from + */ +FUNC_NO_FP atomic_val_t atomic_get(const atomic_t *target) +{ + return *target; +} + +/** + * + * @brief Atomic get-and-set primitive + * + * This routine provides the atomic set operator. The is atomically + * written at and the previous value at is returned. + * + * @param target the memory location to write to + * @param value the value to write + * + * @return The previous value from + */ +FUNC_NO_FP atomic_val_t atomic_set(atomic_t *target, atomic_val_t value) +{ + unsigned int key; + atomic_val_t ret; + + key = irq_lock(); + + ret = *target; + *target = value; + + irq_unlock(key); + + return ret; +} + +/** + * + * @brief Atomic clear primitive + * + * This routine provides the atomic clear operator. The value of 0 is atomically + * written at and the previous value at is returned. (Hence, + * atomic_clear(pAtomicVar) is equivalent to atomic_set(pAtomicVar, 0).) + * + * @param target the memory location to write + * + * @return The previous value from + */ +FUNC_NO_FP atomic_val_t atomic_clear(atomic_t *target) +{ + unsigned int key; + atomic_val_t ret; + + key = irq_lock(); + + ret = *target; + *target = 0; + + irq_unlock(key); + + return ret; +} + +/** + * + * @brief Atomic bitwise inclusive OR primitive + * + * This routine provides the atomic bitwise inclusive OR operator. The + * is atomically bitwise OR'ed with the value at , placing the result + * at , and the previous value at is returned. + * + * @param target the memory location to be modified + * @param value the value to OR + * + * @return The previous value from + */ +FUNC_NO_FP atomic_val_t atomic_or(atomic_t *target, atomic_val_t value) +{ + unsigned int key; + atomic_val_t ret; + + key = irq_lock(); + + ret = *target; + *target |= value; + + irq_unlock(key); + + return ret; +} + +/** + * + * @brief Atomic bitwise exclusive OR (XOR) primitive + * + * This routine provides the atomic bitwise exclusive OR operator. The + * is atomically bitwise XOR'ed with the value at , placing the result + * at , and the previous value at is returned. + * + * @param target the memory location to be modified + * @param value the value to XOR + * + * @return The previous value from + */ +FUNC_NO_FP atomic_val_t atomic_xor(atomic_t *target, atomic_val_t value) +{ + unsigned int key; + atomic_val_t ret; + + key = irq_lock(); + + ret = *target; + *target ^= value; + + irq_unlock(key); + + return ret; +} + +/** + * + * @brief Atomic bitwise AND primitive + * + * This routine provides the atomic bitwise AND operator. The is + * atomically bitwise AND'ed with the value at , placing the result + * at , and the previous value at is returned. + * + * @param target the memory location to be modified + * @param value the value to AND + * + * @return The previous value from + */ +FUNC_NO_FP atomic_val_t atomic_and(atomic_t *target, atomic_val_t value) +{ + unsigned int key; + atomic_val_t ret; + + key = irq_lock(); + + ret = *target; + *target &= value; + + irq_unlock(key); + + return ret; +} + +/** + * + * @brief Atomic bitwise NAND primitive + * + * This routine provides the atomic bitwise NAND operator. The is + * atomically bitwise NAND'ed with the value at , placing the result + * at , and the previous value at is returned. + * + * @param target the memory location to be modified + * @param value the value to NAND + * + * @return The previous value from + */ +FUNC_NO_FP atomic_val_t atomic_nand(atomic_t *target, atomic_val_t value) +{ + unsigned int key; + atomic_val_t ret; + + key = irq_lock(); + + ret = *target; + *target = ~(*target & value); + + irq_unlock(key); + + return ret; +} diff --git a/system/libarc32_arduino101/drivers/bluetooth/att.h b/system/libarc32_arduino101/drivers/bluetooth/att.h new file mode 100644 index 00000000..5752a079 --- /dev/null +++ b/system/libarc32_arduino101/drivers/bluetooth/att.h @@ -0,0 +1,55 @@ +/** @file + * @brief Attribute Protocol handling. + */ + +/* + * Copyright (c) 2016 Intel Corporation + * + * 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 __BT_ATT_H +#define __BT_ATT_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Error codes for Error response PDU */ +#define BT_ATT_ERR_INVALID_HANDLE 0x01 +#define BT_ATT_ERR_READ_NOT_PERMITTED 0x02 +#define BT_ATT_ERR_WRITE_NOT_PERMITTED 0x03 +#define BT_ATT_ERR_INVALID_PDU 0x04 +#define BT_ATT_ERR_AUTHENTICATION 0x05 +#define BT_ATT_ERR_NOT_SUPPORTED 0x06 +#define BT_ATT_ERR_INVALID_OFFSET 0x07 +#define BT_ATT_ERR_AUTHORIZATION 0x08 +#define BT_ATT_ERR_PREPARE_QUEUE_FULL 0x09 +#define BT_ATT_ERR_ATTRIBUTE_NOT_FOUND 0x0a +#define BT_ATT_ERR_ATTRIBUTE_NOT_LONG 0x0b +#define BT_ATT_ERR_ENCRYPTION_KEY_SIZE 0x0c +#define BT_ATT_ERR_INVALID_ATTRIBUTE_LEN 0x0d +#define BT_ATT_ERR_UNLIKELY 0x0e +#define BT_ATT_ERR_INSUFFICIENT_ENCRYPTION 0x0f +#define BT_ATT_ERR_UNSUPPORTED_GROUP_TYPE 0x10 +#define BT_ATT_ERR_INSUFFICIENT_RESOURCES 0x11 + +/* Common Profile Error Codes (from CSS) */ +#define BT_ATT_ERR_CCC_IMPROPER_CONF 0xfd +#define BT_ATT_ERR_PROCEDURE_IN_PROGRESS 0xfe +#define BT_ATT_ERR_OUT_OF_RANGE 0xff + +#ifdef __cplusplus +} +#endif + +#endif /* __BT_ATT_H */ diff --git a/system/libarc32_arduino101/drivers/bluetooth/bluetooth.h b/system/libarc32_arduino101/drivers/bluetooth/bluetooth.h new file mode 100644 index 00000000..e87cf2ab --- /dev/null +++ b/system/libarc32_arduino101/drivers/bluetooth/bluetooth.h @@ -0,0 +1,353 @@ +/** @file + * @brief Bluetooth subsystem core APIs. + */ + +/* + * Copyright (c) 2015 Intel Corporation + * + * 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 __BT_BLUETOOTH_H +#define __BT_BLUETOOTH_H + +#include +#include +#include + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** @brief Callback for notifying that Bluetooth has been enabled. + * + * @param err zero on success or (negative) error code otherwise. + */ +typedef void (*bt_ready_cb_t)(int err); + +/** @brief Enable Bluetooth + * + * Enable Bluetooth. Must be the called before any calls that + * require communication with the local Bluetooth hardware. + * + * @param cb Callback to notify completion or NULL to perform the + * enabling synchronously. + * + * @return Zero on success or (negative) error code otherwise. + */ +int bt_enable(bt_ready_cb_t cb); + +/* Advertising API */ + +/** Description of different data types that can be encoded into + * advertising data. Used to form arrays that are passed to the + * bt_le_adv_start() function. + */ +struct bt_data { + uint8_t type; + uint8_t data_len; + const uint8_t *data; +}; + +/** @brief Helper to declare elements of bt_data arrays + * + * This macro is mainly for creating an array of struct bt_data + * elements which is then passed to bt_le_adv_start(). + * + * @param _type Type of advertising data field + * @param _data Pointer to the data field payload + * @param _data_len Number of bytes behind the _data pointer + */ +#define BT_DATA(_type, _data, _data_len) \ + { \ + .type = (_type), \ + .data_len = (_data_len), \ + .data = (_data), \ + } + +/** @brief Helper to declare elements of bt_data arrays + * + * This macro is mainly for creating an array of struct bt_data + * elements which is then passed to bt_le_adv_start(). + * + * @param _type Type of advertising data field + * @param _bytes Variable number of single-byte parameters + */ +#define BT_DATA_BYTES(_type, _bytes...) \ + BT_DATA(_type, ((uint8_t []) { _bytes }), \ + sizeof((uint8_t []) { _bytes })) + +/** Local advertising address type */ +enum { + /** Use local identity address for advertising. Unless a static + * random address has been configured this will be the public + * address. + */ + BT_LE_ADV_ADDR_IDENTITY, + + /** Use local Non-resolvable Private Address (NRPA) for advertising */ + BT_LE_ADV_ADDR_NRPA, +}; + +/** LE Advertising Parameters. */ +struct bt_le_adv_param { + /** Advertising type */ + uint8_t type; + + /** Which type of own address to use for advertising */ + uint8_t addr_type; + + /** Minimum Advertising Interval (N * 0.625) */ + uint16_t interval_min; + + /** Maximum Advertising Interval (N * 0.625) */ + uint16_t interval_max; +}; + +/** Helper to declare advertising parameters inline + * + * @param _type Advertising Type + * @param _addr_type Local address type to use for advertising + * @param _int_min Minimum advertising interval + * @param _int_max Maximum advertising interval + */ +#define BT_LE_ADV_PARAM(_type, _addr_type, _int_min, _int_max) \ + (&(struct bt_le_adv_param) { \ + .type = (_type), \ + .addr_type = (_addr_type), \ + .interval_min = (_int_min), \ + .interval_max = (_int_max), \ + }) + +#define BT_LE_ADV(t) BT_LE_ADV_PARAM(t, BT_LE_ADV_ADDR_IDENTITY, \ + BT_GAP_ADV_FAST_INT_MIN_2, \ + BT_GAP_ADV_FAST_INT_MAX_2) + +/** @brief Start advertising + * + * Set advertisement data, scan response data, advertisement parameters + * and start advertising. + * + * @param param Advertising parameters. + * @param ad Data to be used in advertisement packets. + * @param ad_len Number of elements in ad + * @param sd Data to be used in scan response packets. + * @param sd_len Number of elements in sd + * + * @return Zero on success or (negative) error code otherwise. + */ +int bt_le_adv_start(const struct bt_le_adv_param *param, + const struct bt_data *ad, size_t ad_len, + const struct bt_data *sd, size_t sd_len); + +/** @brief Stop advertising + * + * Stops ongoing advertising. + * + * @return Zero on success or (negative) error code otherwise. + */ +int bt_le_adv_stop(void); + +/** @brief Define a type allowing user to implement a function that can + * be used to get back active LE scan results. + * + * A function of this type will be called back when user application + * triggers active LE scan. The caller will populate all needed + * parameters based on data coming from scan result. + * Such function can be set by user when LE active scan API is used. + * + * @param addr Advertiser LE address and type. + * @param rssi Strength of advertiser signal. + * @param adv_type Type of advertising response from advertiser. + * @param adv_data Address of buffer containig advertiser data. + * @param len Length of advertiser data contained in buffer. + */ +typedef void bt_le_scan_cb_t(const bt_addr_le_t *addr, int8_t rssi, + uint8_t adv_type, const uint8_t *adv_data, + uint8_t len); + +/** LE scan parameters */ +struct bt_le_scan_param { + /** Scan type (BT_HCI_LE_SCAN_ACTIVE or BT_HCI_LE_SCAN_PASSIVE) */ + uint8_t type; + + /** Duplicate filtering (BT_HCI_LE_SCAN_FILTER_DUP_ENABLE or + * BT_HCI_LE_SCAN_FILTER_DUP_DISABLE) + */ + uint8_t filter_dup; + + /** Scan interval (N * 0.625 ms) */ + uint16_t interval; + + /** Scan window (N * 0.625 ms) */ + uint16_t window; +}; + +/** Helper to declare scan parameters inline + * + * @param _type Scan Type (BT_HCI_LE_SCAN_ACTIVE/BT_HCI_LE_SCAN_PASSIVE) + * @param _filter Filter Duplicates + * @param _interval Scan Interval (N * 0.625 ms) + * @param _window Scan Window (N * 0.625 ms) + */ +#define BT_LE_SCAN_PARAM(_type, _filter, _interval, _window) \ + (&(struct bt_le_scan_param) { \ + .type = (_type), \ + .filter_dup = (_filter), \ + .interval = (_interval), \ + .window = (_window), \ + }) + +/** Helper macro to enable active scanning to discover new devices. */ +#define BT_LE_SCAN_ACTIVE BT_LE_SCAN_PARAM(BT_HCI_LE_SCAN_ACTIVE, \ + BT_HCI_LE_SCAN_FILTER_DUP_ENABLE, \ + BT_GAP_SCAN_FAST_INTERVAL, \ + BT_GAP_SCAN_FAST_WINDOW) + +/** Helper macro to enable passive scanning to discover new devices. + * + * This macro should be used if information required for device identification + * (eg UUID) are known to be placed in Advertising Data. + */ +#define BT_LE_SCAN_PASSIVE BT_LE_SCAN_PARAM(BT_HCI_LE_SCAN_PASSIVE, \ + BT_HCI_LE_SCAN_FILTER_DUP_ENABLE, \ + BT_GAP_SCAN_FAST_INTERVAL, \ + BT_GAP_SCAN_FAST_WINDOW) + +/** @brief Start (LE) scanning + * + * Start LE scanning with and provide results through the specified + * callback. + * + * @param param Scan parameters. + * @param cb Callback to notify scan results. + * + * @return Zero on success or error code otherwise, positive in case + * of protocol error or negative (POSIX) in case of stack internal error + */ +int bt_le_scan_start(const struct bt_le_scan_param *param, bt_le_scan_cb_t cb); + +/** @brief Stop (LE) scanning. + * + * Stops ongoing LE scanning. + * + * @return Zero on success or error code otherwise, positive in case + * of protocol error or negative (POSIX) in case of stack internal error + */ +int bt_le_scan_stop(void); + +/** @def BT_ADDR_STR_LEN + * + * @brief Recommended length of user string buffer for Bluetooth address + * + * @details The recommended length guarantee the output of address + * conversion will not lose valuable information about address being + * processed. + */ +#define BT_ADDR_STR_LEN 18 + +/** @def BT_ADDR_LE_STR_LEN + * + * @brief Recommended length of user string buffer for Bluetooth LE address + * + * @details The recommended length guarantee the output of address + * conversion will not lose valuable information about address being + * processed. + */ +#define BT_ADDR_LE_STR_LEN 27 + +/** @brief Converts binary Bluetooth address to string. + * + * @param addr Address of buffer containing binary Bluetooth address. + * @param str Address of user buffer with enough room to store formatted + * string containing binary address. + * @param len Length of data to be copied to user string buffer. Refer to + * BT_ADDR_STR_LEN about recommended value. + * + * @return Number of successfully formatted bytes from binary address. + */ +static inline int bt_addr_to_str(const bt_addr_t *addr, char *str, size_t len) +{ + return snprintf(str, len, "%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X", + addr->val[5], addr->val[4], addr->val[3], + addr->val[2], addr->val[1], addr->val[0]); +} + +/** @brief Converts binary LE Bluetooth address to string. + * + * @param addr Address of buffer containing binary LE Bluetooth address. + * @param str Address of user buffer with enough room to store + * formatted string containing binary LE address. + * @param len Length of data to be copied to user string buffer. Refer to + * BT_ADDR_LE_STR_LEN about recommended value. + * + * @return Number of successfully formatted bytes from binary address. + */ +static inline int bt_addr_le_to_str(const bt_addr_le_t *addr, char *str, + size_t len) +{ + char type[7]; + + switch (addr->type) { + case BT_ADDR_LE_PUBLIC: + strcpy(type, "public"); + break; + case BT_ADDR_LE_RANDOM: + strcpy(type, "random"); + break; + default: + sprintf(type, "0x%02x", addr->type); + break; + } + + return snprintf(str, len, "%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X (%s)", + addr->val[5], addr->val[4], addr->val[3], + addr->val[2], addr->val[1], addr->val[0], type); +} + +#if defined(CONFIG_BLUETOOTH_BREDR) +/** @brief Enable/disable set controller in discoverable state. + * + * Allows make local controller to listen on INQUIRY SCAN channel and responds + * to devices making general inquiry. To enable this state it's mandatory + * to first be in connectable state. + * + * @param enable Value allowing/disallowing controller to become discoverable. + * + * @return Negative if fail set to requested state or requested state has been + * already set. Zero if done successfully. + */ +int bt_br_set_discoverable(bool enable); + +/** @brief Enable/disable set controller in connectable state. + * + * Allows make local controller to be connectable. It means the controller + * start listen to devices requests on PAGE SCAN channel. If disabled also + * resets discoverability if was set. + * + * @param enable Value allowing/disallowing controller to be connectable. + * + * @return Negative if fail set to requested state or requested state has been + * already set. Zero if done successfully. + */ +int bt_br_set_connectable(bool enable); +#endif + +void bt_le_set_device_name(char *device_name, int len); + +#ifdef __cplusplus +} +#endif + +#endif /* __BT_BLUETOOTH_H */ diff --git a/system/libarc32_arduino101/drivers/bluetooth/conn.h b/system/libarc32_arduino101/drivers/bluetooth/conn.h new file mode 100644 index 00000000..1b710d6f --- /dev/null +++ b/system/libarc32_arduino101/drivers/bluetooth/conn.h @@ -0,0 +1,399 @@ +/** @file + * @brief Bluetooth connection handling + */ + +/* + * Copyright (c) 2015 Intel Corporation + * + * 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 __BT_CONN_H +#define __BT_CONN_H + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(CONFIG_BLUETOOTH_CENTRAL) || defined(CONFIG_BLUETOOTH_PERIPHERAL) +#include + +#include +#include + +/** Opaque type representing a connection to a remote device */ +struct bt_conn; + +/** Connection parameters for LE connections */ +struct bt_le_conn_param { + uint16_t interval_min; + uint16_t interval_max; + uint16_t latency; + uint16_t timeout; +}; + +/** Helper to declare connection parameters inline + * + * @param int_min Minimum Connection Interval (N * 1.25 ms) + * @param int_max Maximum Connection Interval (N * 1.25 ms) + * @param lat Connection Latency + * @param timeout Supervision Timeout (N * 10 ms) + */ +#define BT_LE_CONN_PARAM(int_min, int_max, lat, to) \ + (&(struct bt_le_conn_param) { \ + .interval_min = (int_min), \ + .interval_max = (int_max), \ + .latency = (lat), \ + .timeout = (to), \ + }) + +/** Default LE connection parameters: + * Connection Interval: 30-50 ms + * Latency: 0 + * Timeout: 4 s + */ +#define BT_LE_CONN_PARAM_DEFAULT BT_LE_CONN_PARAM(BT_GAP_INIT_CONN_INT_MIN, \ + BT_GAP_INIT_CONN_INT_MAX, \ + 0, 400) + +/** @brief Increment a connection's reference count. + * + * Increment the reference count of a connection object. + * + * @param conn Connection object. + * + * @return Connection object with incremented reference count. + */ +struct bt_conn *bt_conn_ref(struct bt_conn *conn); + +/** @brief Decrement a connection's reference count. + * + * Decrement the reference count of a connection object. + * + * @param conn Connection object. + */ +void bt_conn_unref(struct bt_conn *conn); + +/** @brief Look up an existing connection by address. + * + * Look up an existing connection based on the remote address. + * + * @param peer Remote address. + * + * @return Connection object or NULL if not found. The caller gets a + * new reference to the connection object which must be released with + * bt_conn_unref() once done using the object. + */ +struct bt_conn *bt_conn_lookup_addr_le(const bt_addr_le_t *peer); + +/** @brief Get destination (peer) address of a connection. + * + * @param conn Connection object. + * + * @return Destination address. + */ +const bt_addr_le_t *bt_conn_get_dst(const struct bt_conn *conn); + +/** Connection Type */ +enum { + BT_CONN_TYPE_LE, /** LE Connection Type */ +#if defined(CONFIG_BLUETOOTH_BREDR) + BT_CONN_TYPE_BR, /** BR/EDR Connection Type */ +#endif +}; + +/** LE Connection Info Structure */ +struct bt_conn_le_info { + const bt_addr_le_t *src; /** Source Address */ + const bt_addr_le_t *dst; /** Destination Address */ + uint16_t interval; /** Connection interval */ + uint16_t latency; /** Connection slave latency */ + uint16_t timeout; /** Connection supervision timeout */ +}; + +#if defined(CONFIG_BLUETOOTH_BREDR) +/** BR/EDR Connection Info Structure */ +struct bt_conn_br_info { + const bt_addr_t *dst; /** Destination BR/EDR address */ +}; +#endif + +/** Connection role (master or slave) */ +enum { + BT_CONN_ROLE_MASTER, + BT_CONN_ROLE_SLAVE, +}; + +/** Connection Info Structure */ +struct bt_conn_info { + /** Connection Type */ + uint8_t type; + + /** Connection Role */ + uint8_t role; + + union { + /** LE Connection specific Info */ + struct bt_conn_le_info le; +#if defined(CONFIG_BLUETOOTH_BREDR) + struct bt_conn_br_info br; +#endif + }; +}; + +/** @brief Get connection info + * + * @param conn Connection object. + * @param info Connection info object. + * + * @return Zero on success or (negative) error code on failure. + */ +int bt_conn_get_info(const struct bt_conn *conn, struct bt_conn_info *info); + +/** @brief Update the connection parameters. + * + * @param conn Connection object. + * @param param Updated connection parameters. + * + * @return Zero on success or (negative) error code on failure. + */ +int bt_conn_le_param_update(struct bt_conn *conn, + const struct bt_le_conn_param *param); + +/** @brief Disconnect from a remote device or cancel pending connection. + * + * Disconnect an active connection with the specified reason code or cancel + * pending outgoing connection. + * + * @param conn Connection to disconnect. + * @param reason Reason code for the disconnection. + * + * @return Zero on success or (negative) error code on failure. + */ +int bt_conn_disconnect(struct bt_conn *conn, uint8_t reason); + +#if defined(CONFIG_BLUETOOTH_CENTRAL) +/** @brief Initiate an LE connection to a remote device. + * + * Allows initiate new LE link to remote peer using its address. + * Returns a new reference that the the caller is responsible for managing. + * + * @param peer Remote address. + * @param param Initial connection parameters. + * + * @return Valid connection object on success or NULL otherwise. + */ +struct bt_conn *bt_conn_create_le(const bt_addr_le_t *peer, + const struct bt_le_conn_param *param); + +/** @brief Automatically connect to remote device if it's in range. + * + * This function enables/disables automatic connection initiation. + * Everytime the device looses the connection with peer, this connection + * will be re-established if connectable advertisement from peer is received. + * + * @param addr Remote Bluetooth address. + * @param param If non-NULL, auto connect is enabled with the given + * parameters. If NULL, auto connect is disabled. + * + * @return Zero on success or error code otherwise. + */ +int bt_le_set_auto_conn(bt_addr_le_t *addr, + const struct bt_le_conn_param *param); +#endif /* CONFIG_BLUETOOTH_CENTRAL */ + +#if defined(CONFIG_BLUETOOTH_PERIPHERAL) +/** @brief Initiate directed advertising to a remote device + * + * Allows initiating a new LE connection to remote peer with the remote + * acting in central role and the local device in peripheral role. + * + * The advertising type must be either BT_LE_ADV_DIRECT_IND or + * BT_LE_ADV_DIRECT_IND_LOW_DUTY. + * + * In case of high duty cycle this will result in a callback with + * connected() with a new connection or with an error. + * + * The advertising may be cancelled with bt_conn_disconnect(). + * + * Returns a new reference that the the caller is responsible for managing. + * + * @param peer Remote address. + * @param param Directed advertising parameters. + * + * @return Valid connection object on success or NULL otherwise. + */ +struct bt_conn *bt_conn_create_slave_le(const bt_addr_le_t *peer, + const struct bt_le_adv_param *param); +#endif /* CONFIG_BLUETOOTH_PERIPHERAL */ + +/** Security level. */ +typedef enum __packed { + BT_SECURITY_LOW, /** No encryption and no authentication. */ + BT_SECURITY_MEDIUM, /** encryption and no authentication (no MITM). */ + BT_SECURITY_HIGH, /** encryption and authentication (MITM). */ + BT_SECURITY_FIPS, /** Authenticated LE Secure Connections and + * encryption. + */ +} bt_security_t; + +#if defined(CONFIG_BLUETOOTH_SMP) +/** @brief Set security level for a connection. + * + * This function enable security (encryption) for a connection. If device is + * already paired with sufficiently strong key encryption will be enabled. If + * link is already encrypted with sufficiently strong key this function does + * nothing. + * + * If device is not paired pairing will be initiated. If device is paired and + * keys are too weak but input output capabilities allow for strong enough keys + * pairing will be initiated. + * + * This function may return error if required level of security is not possible + * to achieve due to local or remote device limitation (eg input output + * capabilities). + * + * @param conn Connection object. + * @param sec Requested security level. + * + * @return 0 on success or negative error + */ +int bt_conn_security(struct bt_conn *conn, bt_security_t sec); + +/** @brief Get encryption key size. + * + * This function gets encryption key size. + * If there is no security (encryption) enabled 0 will be returned. + * + * @param conn Existing connection object. + * + * @return Encryption key size. + */ +uint8_t bt_conn_enc_key_size(struct bt_conn *conn); + +/** @brief Clear device information (bonding, keys). + * + * Clears all a bonding information (keys, etc). A bonded connection is + * disconnected. + * BT_ADDR_LE_ANY removes the of all bonded devices + * + * @param addr identity address of a bonded device + * + * @return 0 in success, error code otherwise + * + */ +int bt_conn_remove_info(const bt_addr_le_t *addr); +#endif /* CONFIG_BLUETOOTH_SMP */ + +/** Connection callback structure */ +struct bt_conn_cb { + void (*connected)(struct bt_conn *conn, uint8_t err); + void (*disconnected)(struct bt_conn *conn, uint8_t reason); + void (*le_param_updated)(struct bt_conn *conn, uint16_t interval, + uint16_t latency, uint16_t timeout); +#if defined(CONFIG_BLUETOOTH_SMP) + void (*identity_resolved)(struct bt_conn *conn, + const bt_addr_le_t *rpa, + const bt_addr_le_t *identity); + void (*security_changed)(struct bt_conn *conn, bt_security_t level); +#endif + struct bt_conn_cb *_next; +}; + +/** @brief Register connection callbacks. + * + * Register callbacks to monitor the state of connections. + * + * @param cb Callback struct. + */ +void bt_conn_cb_register(struct bt_conn_cb *cb); + +#endif /* CONFIG_BLUETOOTH_CENTRAL || CONFIG_BLUETOOTH_PERIPHERAL */ + +#if defined(CONFIG_BLUETOOTH_SMP) || defined(CONFIG_BLUETOOTH_BREDR) +/** Authenticated pairing callback structure */ +struct bt_conn_auth_cb { + void (*passkey_display)(struct bt_conn *conn, unsigned int passkey); + void (*passkey_entry)(struct bt_conn *conn); + void (*passkey_confirm)(struct bt_conn *conn, unsigned int passkey); + void (*cancel)(struct bt_conn *conn); +#if defined(CONFIG_BLUETOOTH_BREDR) + void (*pincode_entry)(struct bt_conn *conn, bool highsec); +#endif +}; + +/** @brief Register authentication callbacks. + * + * Register callbacks to handle authenticated pairing. Passing NULL unregisters + * previous callbacks structure. + * + * @param cb Callback struct. + * + * @return Zero on success or negative error code otherwise + */ +int bt_conn_auth_cb_register(const struct bt_conn_auth_cb *cb); + +/** @brief Reply with entered passkey. + * + * This function should be called only after passkey_entry callback from + * bt_conn_auth_cb structure was called. + * + * @param conn Connection object. + * @param passkey Entered passkey. + * + * @return Zero on success or negative error code otherwise + */ +int bt_conn_auth_passkey_entry(struct bt_conn *conn, unsigned int passkey); + +/** @brief Cancel ongoing authenticated pairing. + * + * This function allows to cancel ongoing authenticated pairing. + * + * @param conn Connection object. + * + * @return Zero on success or negative error code otherwise + */ +int bt_conn_auth_cancel(struct bt_conn *conn); + +/** @brief Reply if passkey was confirmed by user. + * + * This function should be called only after passkey_confirm callback from + * bt_conn_auth_cb structure was called. If passkey is confirmed to match + * then match should be true. Otherwise match should be false. + * + * @param conn Connection object. + * @param match True if passkey was confirmed to match, false otherwise. + * + * @return Zero on success or negative error code otherwise + */ +int bt_conn_auth_passkey_confirm(struct bt_conn *conn, bool match); + +#if defined(CONFIG_BLUETOOTH_BREDR) +/** @brief Reply with entered PIN code. + * + * This function should be called only after PIN code callback from + * bt_conn_auth_cb structure was called. It's for legacy 2.0 devices. + * + * @param conn Connection object. + * @param pin Entered PIN code. + * + * @return Zero on success or negative error code otherwise + */ +int bt_conn_auth_pincode_entry(struct bt_conn *conn, const char *pin); +#endif /* CONFIG_BLUETOOTH_BREDR */ +#endif /* CONFIG_BLUETOOTH_SMP || CONFIG_BLUETOOTH_BREDR */ + +#ifdef __cplusplus +} +#endif + +#endif /* __BT_CONN_H */ diff --git a/system/libarc32_arduino101/drivers/bluetooth/gatt.h b/system/libarc32_arduino101/drivers/bluetooth/gatt.h new file mode 100644 index 00000000..e9eac613 --- /dev/null +++ b/system/libarc32_arduino101/drivers/bluetooth/gatt.h @@ -0,0 +1,1045 @@ +/** @file + * @brief Generic Attribute Profile handling. + */ + +/* + * Copyright (c) 2015 Intel Corporation + * + * 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 __BT_GATT_H +#define __BT_GATT_H + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(CONFIG_BLUETOOTH_CENTRAL) || defined(CONFIG_BLUETOOTH_PERIPHERAL) +#include +#include +#include +#include +#include +#include + +/* GATT attribute permission bit field values */ + +/** @def BT_GATT_PERM_READ + * @brief Attribute read permission. + */ +#define BT_GATT_PERM_READ 0x01 +/** @def BT_GATT_PERM_WRITE + * @brief Attribute write permission. + */ +#define BT_GATT_PERM_WRITE 0x02 +/** @def BT_GATT_PERM_READ_ENCRYPT + * @brief Attribute read permission with encryption. + * + * If set, requires encryption for read access. + */ +#define BT_GATT_PERM_READ_ENCRYPT 0x04 +/** @def BT_GATT_PERM_WRITE_ENCRYPT + * @brief Attribute write permission with encryption. + * + * If set, requires encryption for write access. + */ +#define BT_GATT_PERM_WRITE_ENCRYPT 0x08 +/** @def BT_GATT_PERM_READ_AUTHEN + * @brief Attribute read permission with authentication. + * + * If set, requires encryption using authenticated link-key for read access. + */ +#define BT_GATT_PERM_READ_AUTHEN 0x10 +/** @def BT_GATT_PERM_WRITE_AUTHEN + * @brief Attribute write permission with authentication. + * + * If set, requires encryption using authenticated link-key for write access. + */ +#define BT_GATT_PERM_WRITE_AUTHEN 0x20 +/** @def BT_GATT_PERM_READ_AUTHOR + * @brief Attribute read permission with authorization. + * + * If set, requires authorization for read access. + */ +#define BT_GATT_PERM_READ_AUTHOR 0x40 +/** @def BT_GATT_PERM_WRITE_AUTHOR + * @brief Attribute write permission with authorization. + * + * If set, requires authorization for write access. + */ +#define BT_GATT_PERM_WRITE_AUTHOR 0x80 + +/* GATT attribute flush flags */ +/** @def BT_GATT_FLUSH_DISCARD + * @brief Attribute flush discard flag. + */ +#define BT_GATT_FLUSH_DISCARD 0x00 +/** @def BT_GATT_FLUSH_DISCARD + * @brief Attribute flush synchronize flag. + */ +#define BT_GATT_FLUSH_SYNC 0x01 + +/** @def BT_GATT_ERR + * @brief Construct error return value for attribute read, write and + * flush callbacks. + * + * @param _att_err ATT error code + * + * @return Appropriate error code for the attribute callbacks. + * + */ +#define BT_GATT_ERR(_att_err) (-(_att_err)) + +/** @brief GATT Attribute structure. */ +struct bt_gatt_attr { + /** Attribute UUID */ + const struct bt_uuid *uuid; + + /** Attribute read callback + * + * @param conn The connection that is requesting to read + * @param attr The attribute that's being read + * @param buf Buffer to place the read result in + * @param len Length of data to read + * @param offset Offset to start reading from + * + * @return Number fo bytes read, or in case of an error + * BT_GATT_ERR() with a specific ATT error code. + */ + ssize_t (*read)(struct bt_conn *conn, + const struct bt_gatt_attr *attr, + void *buf, uint16_t len, + uint16_t offset); + + /** Attribute write callback + * + * @param conn The connection that is requesting to write + * @param attr The attribute that's being read + * @param buf Buffer with the data to write + * @param len Number of bytes in the buffer + * @param offset Offset to start writing from + * + * @return Number of bytes written, or in case of an error + * BT_GATT_ERR() with a specific ATT error code. + */ + ssize_t (*write)(struct bt_conn *conn, + const struct bt_gatt_attr *attr, + const void *buf, uint16_t len, + uint16_t offset); + + /** Attribute flush callback + * + * If this callback is provided (non-NULL) every write + * operation will be followed by a call to it. The expectation + * is for the attribute implementation to only commit the write + * result once this is called. + * + * @param conn The connection that is requesting to write + * @param attr The attribute that's being read + * @param flags Flags (BT_GATT_FLUSH_*) + * + * @return Number of bytes flushed, or in case of an error + * BT_GATT_ERR() with a specific ATT error code. + */ + ssize_t (*flush)(struct bt_conn *conn, + const struct bt_gatt_attr *attr, + uint8_t flags); + + /** Attribute user data */ + void *user_data; + /** Attribute handle */ + uint16_t handle; + /** Attribute permissions */ + uint8_t perm; +#if defined(CONFIG_BLUETOOTH_GATT_DYNAMIC_DB) + struct bt_gatt_attr *_next; +#endif /* CONFIG_BLUETOOTH_GATT_DYNAMIC_DB */ +}; + +/** @brief Service Attribute Value. */ +struct bt_gatt_service { + /** Service UUID. */ + const struct bt_uuid *uuid; + /** Service end handle. */ + uint16_t end_handle; +}; + +/** @brief Include Attribute Value. */ +struct bt_gatt_include { + /** Service UUID. */ + const struct bt_uuid *uuid; + /** Service start handle. */ + uint16_t start_handle; + /** Service end handle. */ + uint16_t end_handle; +}; + +/* Characteristic Properties Bit field values */ + +/** @def BT_GATT_CHRC_BROADCAST + * @brief Characteristic broadcast property. + * + * If set, permits broadcasts of the Characteristic Value using Server + * Characteristic Configuration Descriptor. + */ +#define BT_GATT_CHRC_BROADCAST 0x01 +/** @def BT_GATT_CHRC_READ + * @brief Characteristic read property. + * + * If set, permits reads of the Characteristic Value. + */ +#define BT_GATT_CHRC_READ 0x02 +/** @def BT_GATT_CHRC_WRITE_WITHOUT_RESP + * @brief Characteristic write without response property. + * + * If set, permits write of the Characteristic Value without response. + */ +#define BT_GATT_CHRC_WRITE_WITHOUT_RESP 0x04 +/** @def BT_GATT_CHRC_WRITE + * @brief Characteristic write with response property. + * + * If set, permits write of the Characteristic Value with response. + */ +#define BT_GATT_CHRC_WRITE 0x08 +/** @def BT_GATT_CHRC_NOTIFY + * @brief Characteristic notify property. + * + * If set, permits notifications of a Characteristic Value without + * acknowledgment. + */ +#define BT_GATT_CHRC_NOTIFY 0x10 +/** @def BT_GATT_CHRC_INDICATE + * @brief Characteristic indicate property. + * + * If set, permits indications of a Characteristic Value with acknowledgment. + */ +#define BT_GATT_CHRC_INDICATE 0x20 +/** @def BT_GATT_CHRC_AUTH + * @brief Characteristic Authenticated Signed Writes property. + * + * If set, permits signed writes to the Characteristic Value. + */ +#define BT_GATT_CHRC_AUTH 0x40 +/** @def BT_GATT_CHRC_EXT_PROP + * @brief Characteristic Extended Properties property. + * + * If set, additional characteristic properties are defined in the + * Characteristic Extended Properties Descriptor. + */ +#define BT_GATT_CHRC_EXT_PROP 0x80 + +/** @brief Characteristic Attribute Value. */ +struct bt_gatt_chrc { + /** Characteristic UUID. */ + const struct bt_uuid *uuid; + /** Characteristic properties. */ + uint8_t properties; +}; + +/* Characteristic Extended Properties Bit field values */ +#define BT_GATT_CEP_RELIABLE_WRITE 0x0001 +#define BT_GATT_CEP_WRITABLE_AUX 0x0002 + +/** @brief Characteristic Extended Properties Attribute Value. */ +struct bt_gatt_cep { + /** Characteristic Extended properties */ + uint16_t properties; +}; + +/* Client Characteristic Configuration Values */ + +/** @def BT_GATT_CCC_NOTIFY + * @brief Client Characteristic Configuration Notification. + * + * If set, changes to Characteristic Value shall be notified. + */ +#define BT_GATT_CCC_NOTIFY 0x0001 +/** @def BT_GATT_CCC_INDICATE + * @brief Client Characteristic Configuration Indication. + * + * If set, changes to Characteristic Value shall be indicated. + */ +#define BT_GATT_CCC_INDICATE 0x0002 + +/* Client Characteristic Configuration Attribute Value */ +struct bt_gatt_ccc { + /** Client Characteristic Configuration flags */ + uint16_t flags; +}; + +/** @brief GATT Characteristic Presentation Format Attribute Value. */ +struct bt_gatt_cpf { + /** Format of the value of the characteristic */ + uint8_t format; + /** Exponent field to determine how the value of this characteristic is further formatted */ + int8_t exponent; + /** Unit of the characteristic */ + uint16_t unit; + /** Name space of the description */ + uint8_t name_space; + /** Description of the characteristic as defined in a higher layer profile */ + uint16_t description; +} __packed; + +/* Server API */ + +/** @brief Register attribute database. + * + * Register GATT attribute database table. Applications can make use of + * macros such as BT_GATT_PRIMARY_SERVICE, BT_GATT_CHARACTERISTIC, + * BT_GATT_DESCRIPTOR, etc. + * + * @param attrs Database table containing the available attributes. + * @param count Size of the database table. + * + * @return 0 in case of success or negative value in case of error. + */ +int bt_gatt_register(struct bt_gatt_attr *attrs, size_t count); + +enum { + BT_GATT_ITER_STOP = 0, + BT_GATT_ITER_CONTINUE, +}; + +/** @brief Attribute iterator callback. + * + * @param attr Attribute found. + * @param user_data Data given. + * + * @return BT_GATT_ITER_CONTINUE if should continue to the next attribute + * or BT_GATT_ITER_STOP to stop. + */ +typedef uint8_t (*bt_gatt_attr_func_t)(const struct bt_gatt_attr *attr, + void *user_data); + +/** @brief Attribute iterator. + * + * Iterate attributes in the given range. + * + * @param start_handle Start handle. + * @param end_handle End handle. + * @param func Callback function. + * @param user_data Data to pass to the callback. + */ +void bt_gatt_foreach_attr(uint16_t start_handle, uint16_t end_handle, + bt_gatt_attr_func_t func, void *user_data); + +/** @brief Iterate to the next attribute + * + * Iterate to the next attribute following a given attribute. + * + * @param attr Current Attribute. + * + * @return The next attribute or NULL if it cannot be found. + */ +struct bt_gatt_attr *bt_gatt_attr_next(const struct bt_gatt_attr *attr); + +/** @brief Generic Read Attribute value helper. + * + * Read attribute value storing the result into buffer. + * + * @param conn Connection object. + * @param attr Attribute to read. + * @param buf Buffer to store the value. + * @param buf_len Buffer length. + * @param offset Start offset. + * @param value Attribute value. + * @param value_len Length of the attribute value. + * + * @return int number of bytes read in case of success or negative values in + * case of error. + */ +ssize_t bt_gatt_attr_read(struct bt_conn *conn, const struct bt_gatt_attr *attr, + void *buf, uint16_t buf_len, uint16_t offset, + const void *value, uint16_t value_len); + +/** @brief Read Service Attribute helper. + * + * Read service attribute value storing the result into buffer after + * enconding it. + * NOTE: Only use this with attributes which user_data is a bt_uuid. + * + * @param conn Connection object. + * @param attr Attribute to read. + * @param buf Buffer to store the value read. + * @param len Buffer length. + * @param offset Start offset. + * + * @return int number of bytes read in case of success or negative values in + * case of error. + */ +ssize_t bt_gatt_attr_read_service(struct bt_conn *conn, + const struct bt_gatt_attr *attr, + void *buf, uint16_t len, uint16_t offset); + +/** @def BT_GATT_SERVICE + * @brief Generic Service Declaration Macro. + * + * Helper macro to declare a service attribute. + * + * @param _uuid Service attribute type. + * @param _data Service attribute value. + */ +#define BT_GATT_SERVICE(_uuid, _service) \ +{ \ + .uuid = _uuid, \ + .perm = BT_GATT_PERM_READ, \ + .read = bt_gatt_attr_read_service, \ + .user_data = _service, \ +} + +/** @def BT_GATT_PRIMARY_SERVICE + * @brief Primary Service Declaration Macro. + * + * Helper macro to declare a primary service attribute. + * + * @param _service Service attribute value. + */ +#define BT_GATT_PRIMARY_SERVICE(_service) \ +{ \ + .uuid = BT_UUID_GATT_PRIMARY, \ + .perm = BT_GATT_PERM_READ, \ + .read = bt_gatt_attr_read_service, \ + .user_data = _service, \ +} + +/** @def BT_GATT_SECONDARY_SERVICE + * @brief Secondary Service Declaration Macro. + * + * Helper macro to declare a secondary service attribute. + * + * @param _service Service attribute value. + */ +#define BT_GATT_SECONDARY_SERVICE(_service) \ +{ \ + .uuid = BT_UUID_GATT_SECONDARY, \ + .perm = BT_GATT_PERM_READ, \ + .read = bt_gatt_attr_read_service, \ + .user_data = _service, \ +} + +/** @brief Read Include Attribute helper. + * + * Read include service attribute value storing the result into buffer after + * enconding it. + * NOTE: Only use this with attributes which user_data is a bt_gatt_include. + * + * @param conn Connection object. + * @param attr Attribute to read. + * @param buf Buffer to store the value read. + * @param len Buffer length. + * @param offset Start offset. + * + * @return int number of bytes read in case of success or negative values in + * case of error. + */ +ssize_t bt_gatt_attr_read_included(struct bt_conn *conn, + const struct bt_gatt_attr *attr, + void *buf, uint16_t len, uint16_t offset); + +/** @def BT_GATT_INCLUDE_SERVICE + * @brief Include Service Declaration Macro. + * + * Helper macro to declare a include service attribute. + * + * @param _service Service attribute value. + */ +#define BT_GATT_INCLUDE_SERVICE(_service) \ +{ \ + .uuid = BT_UUID_GATT_INCLUDE, \ + .perm = BT_GATT_PERM_READ, \ + .read = bt_gatt_attr_read_included, \ + .user_data = _service, \ +} + +/** @brief Read Characteristic Attribute helper. + * + * Read characteristic attribute value storing the result into buffer after + * enconding it. + * NOTE: Only use this with attributes which user_data is a bt_gatt_chrc. + * + * @param conn Connection object. + * @param attr Attribute to read. + * @param buf Buffer to store the value read. + * @param len Buffer length. + * @param offset Start offset. + * + * @return number of bytes read in case of success or negative values in + * case of error. + */ +ssize_t bt_gatt_attr_read_chrc(struct bt_conn *conn, + const struct bt_gatt_attr *attr, void *buf, + uint16_t len, uint16_t offset); + +/** @def BT_GATT_CHARACTERISTIC + * @brief Characteristic Declaration Macro. + * + * Helper macro to declare a characteristic attribute. + * + * @param _uuid Characteristic attribute uuid. + * @param _props Characteristic attribute properties. + */ +#define BT_GATT_CHARACTERISTIC(_uuid, _props) \ +{ \ + .uuid = BT_UUID_GATT_CHRC, \ + .perm = BT_GATT_PERM_READ, \ + .read = bt_gatt_attr_read_chrc, \ + .user_data = (&(struct bt_gatt_chrc) { .uuid = _uuid, \ + .properties = _props, }),\ +} + +/** @brief GATT CCC configuration entry. */ +struct bt_gatt_ccc_cfg { + /** Config peer address. */ + bt_addr_le_t peer; + /** Config peer value. */ + uint16_t value; + /** Config valid flag. */ + uint8_t valid; +}; + +/* Internal representation of CCC value */ +struct _bt_gatt_ccc { + struct bt_gatt_ccc_cfg *cfg; + size_t cfg_len; + uint16_t value; + void (*cfg_changed)(uint16_t value); +}; + +/** @brief Read Client Characteristic Configuration Attribute helper. + * + * Read CCC attribute value storing the result into buffer after + * enconding it. + * NOTE: Only use this with attributes which user_data is a _bt_gatt_ccc. + * + * @param conn Connection object. + * @param attr Attribute to read. + * @param buf Buffer to store the value read. + * @param len Buffer length. + * @param offset Start offset. + * + * @return number of bytes read in case of success or negative values in + * case of error. + */ +ssize_t bt_gatt_attr_read_ccc(struct bt_conn *conn, + const struct bt_gatt_attr *attr, void *buf, + uint16_t len, uint16_t offset); + +/** @brief Write Client Characteristic Configuration Attribute helper. + * + * Write value in the buffer into CCC attribute. + * NOTE: Only use this with attributes which user_data is a _bt_gatt_ccc. + * + * @param conn Connection object. + * @param attr Attribute to read. + * @param buf Buffer to store the value read. + * @param len Buffer length. + * @param offset Start offset. + * + * @return number of bytes written in case of success or negative values in + * case of error. + */ +ssize_t bt_gatt_attr_write_ccc(struct bt_conn *conn, + const struct bt_gatt_attr *attr, const void *buf, + uint16_t len, uint16_t offset); + +/** @def BT_GATT_CCC + * @brief Client Characteristic Configuration Declaration Macro. + * + * Helper macro to declare a CCC attribute. + * + * @param _cfg Initial configuration. + * @param _cfg_changed Configuration changed callback. + */ +#define BT_GATT_CCC(_cfg, _cfg_changed) \ +{ \ + .uuid = BT_UUID_GATT_CCC, \ + .perm = BT_GATT_PERM_READ | BT_GATT_PERM_WRITE, \ + .read = bt_gatt_attr_read_ccc, \ + .write = bt_gatt_attr_write_ccc, \ + .user_data = (&(struct _bt_gatt_ccc) { .cfg = _cfg, \ + .cfg_len = ARRAY_SIZE(_cfg), \ + .cfg_changed = _cfg_changed, }),\ +} + +/** @brief Read Characteristic Extended Properties Attribute helper + * + * Read CEP attribute value storing the result into buffer after + * encoding it. + * NOTE: Only use this with attributes which user_data is a bt_gatt_cep. + * + * @param conn Connection object + * @param attr Attribute to read + * @param buf Buffer to store the value read + * @param len Buffer length + * @param offset Start offset + * + * @return number of bytes read in case of success or negative values in + * case of error. + */ +ssize_t bt_gatt_attr_read_cep(struct bt_conn *conn, + const struct bt_gatt_attr *attr, void *buf, + uint16_t len, uint16_t offset); + +/** @def BT_GATT_CEP + * @brief Characteristic Extended Properties Declaration Macro. + * + * Helper macro to declare a CEP attribute. + * + * @param _value Descriptor attribute value. + */ +#define BT_GATT_CEP(_value) \ +{ \ + .uuid = BT_UUID_GATT_CEP, \ + .perm = BT_GATT_PERM_READ, \ + .read = bt_gatt_attr_read_cep, \ + .user_data = _value, \ +} + +/** @brief Read Characteristic User Description Descriptor Attribute helper + * + * Read CUD attribute value storing the result into buffer after + * encoding it. + * NOTE: Only use this with attributes which user_data is a NULL-terminated C string. + * + * @param conn Connection object + * @param attr Attribute to read + * @param buf Buffer to store the value read + * @param len Buffer length + * @param offset Start offset + * + * @return number of bytes read in case of success or negative values in + * case of error. + */ +ssize_t bt_gatt_attr_read_cud(struct bt_conn *conn, + const struct bt_gatt_attr *attr, void *buf, + uint16_t len, uint16_t offset); + +/** @def BT_GATT_CUD + * @brief Characteristic User Format Descriptor Declaration Macro. + * + * Helper macro to declare a CUD attribute. + * + * @param _value User description NULL-terminated C string. + * @param _perm Descriptor attribute access permissions. + */ +#define BT_GATT_CUD(_value, _perm) \ +{ \ + .uuid = BT_UUID_GATT_CUD, \ + .perm = _perm, \ + .read = bt_gatt_attr_read_cud, \ + .user_data = _value, \ +} + +/** @brief Read Characteristic Presentation format Descriptor Attribute helper + * + * Read CPF attribute value storing the result into buffer after + * encoding it. + * NOTE: Only use this with attributes which user_data is a bt_gatt_pf. + * + * @param conn Connection object + * @param attr Attribute to read + * @param buf Buffer to store the value read + * @param len Buffer length + * @param offset Start offset + * + * @return number of bytes read in case of success or negative values in + * case of error. + */ +ssize_t bt_gatt_attr_read_cpf(struct bt_conn *conn, + const struct bt_gatt_attr *attr, void *buf, + uint16_t len, uint16_t offset); + +/** @def BT_GATT_CPF + * @brief Characteristic Presentation Format Descriptor Declaration Macro. + * + * Helper macro to declare a CPF attribute. + * + * @param _value Descriptor attribute value. + */ +#define BT_GATT_CPF(_value) \ +{ \ + .uuid = BT_UUID_GATT_CPF, \ + .perm = BT_GATT_PERM_READ, \ + .read = bt_gatt_attr_read_cpf, \ + .user_data = _value, \ +} + +/** @def BT_GATT_DESCRIPTOR + * @brief Descriptor Declaration Macro. + * + * Helper macro to declare a descriptor attribute. + * + * @param _uuid Descriptor attribute uuid. + * @param _perm Descriptor attribute access permissions. + * @param _read Descriptor attribute read callback. + * @param _write Descriptor attribute write callback. + * @param _value Descriptor attribute value. + */ +#define BT_GATT_DESCRIPTOR(_uuid, _perm, _read, _write, _value) \ +{ \ + .uuid = _uuid, \ + .perm = _perm, \ + .read = _read, \ + .write = _write, \ + .user_data = _value, \ +} + +/** @def BT_GATT_LONG_DESCRIPTOR + * @brief Descriptor Declaration Macro. + * + * Helper macro to declare a descriptor attribute. + * + * @param _uuid Descriptor attribute uuid. + * @param _perm Descriptor attribute access permissions. + * @param _read Descriptor attribute read callback. + * @param _write Descriptor attribute write callback. + * @param _flush Descriptor attribute flush callback. + * @param _value Descriptor attribute value. + */ +#define BT_GATT_LONG_DESCRIPTOR(_uuid, _perm, _read, _write, _flush, _value) \ +{ \ + .uuid = _uuid, \ + .perm = _perm, \ + .read = _read, \ + .write = _write, \ + .flush = _flush, \ + .user_data = _value, \ +} + +/** @brief Notify sent callback + * + * This means that the complete attribute has been sent. This does not mean it + * has been received however (use indicate for this). + * This shall be used to flow control the callee to avoid flooding the ble + * controller. + * + * @param conn Connection object. + * @param attr Attribute object. + * @param err 0 if none + */ +typedef void (*bt_gatt_notify_sent_func_t)(struct bt_conn *conn, struct bt_gatt_attr *attr, + uint8_t err); + +/** @brief Notify attribute value change. + * + * Send notification of attribute value change, if connection is NULL notify + * all peer that have notification enabled via CCC otherwise do a direct + * notification only the given connection. + * + * @param conn Connection object. + * @param attr Attribute object. + * @param value Attribute value. + * @param len Attribute value length. + * @param cb callback function called when send is complete (or NULL) + */ +int bt_gatt_notify(struct bt_conn *conn, const struct bt_gatt_attr *attr, + const void *data, uint16_t len, + bt_gatt_notify_sent_func_t cb); + +/** @brief Indication complete result callback. + * + * @param conn Connection object. + * @param attr Attribute object. + * @param err: 0 success, error in the other case + */ +typedef void (*bt_gatt_indicate_func_t)(struct bt_conn *conn, + const struct bt_gatt_attr *attr, + int err); + +/** @brief GATT Indicate Value parameters */ +struct bt_gatt_indicate_params { + /** Indicate Attribute object*/ + const struct bt_gatt_attr *attr; + /** Indicate Value callback */ + bt_gatt_indicate_func_t func; + /** Indicate Value data*/ + const void *data; + /** Indicate Value length*/ + uint16_t len; +}; + +/** @brief Indicate attribute value change. + * + * Send an indication of attribute value change. + * Note: This function should only be called if CCC is declared with + * BT_GATT_CCC otherwise it cannot find a valid peer configuration. + * + * Note: This procedure is asynchronous therefore the parameters need to + * remains valid while it is active. + * + * @param conn Connection object. + * @param params Indicate parameters. + * + * @return 0 in case of success or negative value in case of error. + */ +int bt_gatt_indicate(struct bt_conn *conn, + struct bt_gatt_indicate_params *params); + +#if defined(CONFIG_BLUETOOTH_GATT_CLIENT) +/* Client API */ + +/** @brief Response callback function + * + * @param conn Connection object. + * @param err Error code. + */ +typedef void (*bt_gatt_rsp_func_t)(struct bt_conn *conn, uint8_t err); + +/** @brief Exchange MTU + * + * This client procedure can be used to set the MTU to the maximum possible + * size the buffers can hold. + * NOTE: Shall only be used once per connection. + * + * @param conn Connection object. + * @param func Exchange MTU Response callback function. + */ +int bt_gatt_exchange_mtu(struct bt_conn *conn, bt_gatt_rsp_func_t func); + +struct bt_gatt_discover_params; + +/** @brief Discover attribute callback function. + * + * @param conn Connection object. + * @param attr Attribute found. + * @param params Discovery parameters given. + * + * If discovery procedure has completed this callback will be called with + * attr set to NULL. This will not happen if procedure was stopped by returning + * BT_GATT_ITER_STOP. + * + * @return BT_GATT_ITER_CONTINUE if should continue attribute discovery + * or BT_GATT_ITER_STOP to stop discovery procedure. + */ +typedef uint8_t (*bt_gatt_discover_func_t)(struct bt_conn *conn, + const struct bt_gatt_attr *attr, + struct bt_gatt_discover_params *params); + +enum { + BT_GATT_DISCOVER_PRIMARY, + BT_GATT_DISCOVER_SECONDARY, + BT_GATT_DISCOVER_INCLUDE, + BT_GATT_DISCOVER_CHARACTERISTIC, + BT_GATT_DISCOVER_DESCRIPTOR, +}; + +/** @brief GATT Discover Attributes parameters */ +struct bt_gatt_discover_params { + /** Discover UUID type */ + struct bt_uuid *uuid; + /** Discover attribute callback */ + bt_gatt_discover_func_t func; + /** Discover start handle */ + uint16_t start_handle; + /** Discover end handle */ + uint16_t end_handle; + /** Discover type */ + uint8_t type; +}; + +/** @brief GATT Discover function + * + * This procedure is used by a client to discover attributes on a server. + * + * Primary Service Discovery: Procedure allows to discover specific Primary + * Service based on UUID. + * Include Service Discovery: Procedure allows to discover all Include Services + * within specified range. + * Characteristic Discovery: Procedure allows to discover all characteristics + * within specified handle range as well as + * discover characteristics with specified UUID. + * Descriptors Discovery: Procedure allows to discover all characteristic + * descriptors within specified range. + * + * For each attribute found the callback is called which can then decide + * whether to continue discovering or stop. + * + * Note: This procedure is asynchronous therefore the parameters need to + * remains valid while it is active. + * + * @param conn Connection object. + * @param params Discover parameters. + * + * @return 0 in case of success or negative value in case of error. + */ +int bt_gatt_discover(struct bt_conn *conn, + struct bt_gatt_discover_params *params); + +struct bt_gatt_read_params; + +/** @brief Read callback function + * + * @param conn Connection object. + * @param err Error code. + * @param params Read parameters used. + * @param data Attribute value data. NULL means read has completed. + * @param length Attribute value length. + */ +typedef uint8_t (*bt_gatt_read_func_t)(struct bt_conn *conn, int err, + struct bt_gatt_read_params *params, + const void *data, uint16_t length); + +/** @brief GATT Read parameters */ +struct bt_gatt_read_params { + /** Read attribute callback */ + bt_gatt_read_func_t func; + /** Handles count. + * If equals to 1 single.handle and single.offset are used. + * If >1 Read Multiple Characteristic Values is performed and handles + * are used. + */ + size_t handle_count; + union { + struct { + /** Attribute handle */ + uint16_t handle; + /** Attribute data offset */ + uint16_t offset; + } single; + /** Handles to read in Read Multiple Characteristic Values */ + uint16_t *handles; + }; +}; + +/** @brief Read Attribute Value by handle + * + * This procedure read the attribute value and return it to the callback. + * + * Note: This procedure is asynchronous therefore the parameters need to + * remains valid while it is active. + * + * @param conn Connection object. + * @param params Read parameters. + * + * @return 0 in case of success or negative value in case of error. + */ +int bt_gatt_read(struct bt_conn *conn, struct bt_gatt_read_params *params); + +/** @brief Write Response callback function + * + * @param conn Connection object. + * @param err Error code. + * @param data Data pointer in the write request. + */ +typedef void (*bt_gatt_write_rsp_func_t)(struct bt_conn *conn, uint8_t err, const void *data); + +/** @brief Write Attribute Value by handle + * + * This procedure write the attribute value and return the result in the + * callback. + * + * @param conn Connection object. + * @param handle Attribute handle. + * @param offset Attribute data offset. + * @param data Data to be written. + * @param length Data length. + * @param func Callback function. + * + * @return 0 in case of success or negative value in case of error. + */ +int bt_gatt_write(struct bt_conn *conn, uint16_t handle, uint16_t offset, + const void *data, uint16_t length, bt_gatt_write_rsp_func_t func); + +/** @brief Write Attribute Value by handle without response + * + * This procedure write the attribute value without requiring an + * acknowledgement that the write was successfully performed + * + * @param conn Connection object. + * @param handle Attribute handle. + * @param data Data to be written. + * @param length Data length. + * @param sign Whether to sign data + * + * @return 0 in case of success or negative value in case of error. + */ +int bt_gatt_write_without_response(struct bt_conn *conn, uint16_t handle, + const void *data, uint16_t length, + bool sign); + +struct bt_gatt_subscribe_params; + +/** @brief Notification callback function + * + * @param conn Connection object. + * @param params Subscription parameters. + * @param data Attribute value data. If NULL then subscription was removed. + * @param length Attribute value length. + */ +typedef uint8_t (*bt_gatt_notify_func_t)(struct bt_conn *conn, + struct bt_gatt_subscribe_params *params, + const void *data, uint16_t length); + +/** @brief GATT Subscribe parameters */ +struct bt_gatt_subscribe_params { + bt_addr_le_t _peer; + /** Notification value callback */ + bt_gatt_notify_func_t notify; + /** Subscribe value handle */ + uint16_t value_handle; + /** Subscribe CCC handle */ + uint16_t ccc_handle; + /** Subscribe value */ + uint16_t value; + struct bt_gatt_subscribe_params *_next; +}; + +/** @brief Subscribe Attribute Value Notification + * + * This procedure subscribe to value notification using the Client + * Characteristic Configuration handle. + * If notification received subscribe value callback is called to return + * notified value. One may then decide whether to unsubscribe directly from + * this callback. Notification callback with NULL data will not be called if + * subscription was removed by this method. + * + * Note: This procedure is asynchronous therefore the parameters need to + * remains valid while it is active. + * + * @param conn Connection object. + * @param params Subscribe parameters. + * + * @return 0 in case of success or negative value in case of error. + */ +int bt_gatt_subscribe(struct bt_conn *conn, + struct bt_gatt_subscribe_params *params); + +/** @brief Unsubscribe Attribute Value Notification + * + * This procedure unsubscribe to value notification using the Client + * Characteristic Configuration handle. Notification callback with NULL data + * will not be called if subscription was removed by this call. + * + * @param conn Connection object. + * @param params Subscribe parameters. + * + * @return 0 in case of success or negative value in case of error. + */ +int bt_gatt_unsubscribe(struct bt_conn *conn, + struct bt_gatt_subscribe_params *params); + +/** @brief Cancel GATT pending request + * + * @param conn Connection object. + */ +void bt_gatt_cancel(struct bt_conn *conn); + +#endif /* CONFIG_BLUETOOTH_GATT_CLIENT */ +#endif /* CONFIG_BLUETOOTH_CENTRAL || CONFIG_BLUETOOTH_PERIPHERAL */ + +#ifdef __cplusplus +} +#endif + +#endif /* __BT_GATT_H */ diff --git a/system/libarc32_arduino101/drivers/bluetooth/hci.h b/system/libarc32_arduino101/drivers/bluetooth/hci.h new file mode 100644 index 00000000..f7ff52c1 --- /dev/null +++ b/system/libarc32_arduino101/drivers/bluetooth/hci.h @@ -0,0 +1,683 @@ +/* hci.h - Bluetooth Host Control Interface definitions */ + +/* + * Copyright (c) 2015 Intel Corporation + * + * 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 __BT_HCI_H +#define __BT_HCI_H + +//#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define BT_ADDR_LE_PUBLIC 0x00 +#define BT_ADDR_LE_RANDOM 0x01 + +typedef struct { + uint8_t val[6]; +} bt_addr_t; + +typedef struct { + uint8_t type; + uint8_t val[6]; +} bt_addr_le_t; + +#define BT_ADDR_ANY (&(bt_addr_t) {{0, 0, 0, 0, 0, 0} }) +#define BT_ADDR_LE_ANY (&(bt_addr_le_t) { 0, {0, 0, 0, 0, 0, 0} }) + +static inline int bt_addr_cmp(const bt_addr_t *a, const bt_addr_t *b) +{ + return memcmp(a, b, sizeof(*a)); +} + +static inline int bt_addr_le_cmp(const bt_addr_le_t *a, const bt_addr_le_t *b) +{ + return memcmp(a, b, sizeof(*a)); +} + +static inline void bt_addr_copy(bt_addr_t *dst, const bt_addr_t *src) +{ + memcpy(dst, src, sizeof(*dst)); +} + +static inline void bt_addr_le_copy(bt_addr_le_t *dst, const bt_addr_le_t *src) +{ + memcpy(dst, src, sizeof(*dst)); +} + +/* HCI Error Codes */ +#define BT_HCI_ERR_UNKNOWN_CONN_ID 0x02 +#define BT_HCI_ERR_AUTHENTICATION_FAIL 0x05 +#define BT_HCI_ERR_INSUFFICIENT_RESOURCES 0x0d +#define BT_HCI_ERR_REMOTE_USER_TERM_CONN 0x13 +#define BT_HCI_ERR_PAIRING_NOT_ALLOWED 0x18 +#define BT_HCI_ERR_UNSUPP_REMOTE_FEATURE 0x1a +#define BT_HCI_ERR_INVALID_LL_PARAMS 0x1e +#define BT_HCI_ERR_UNSPECIFIED 0x1f +#define BT_HCI_ERR_PAIRING_NOT_SUPPORTED 0x29 +#define BT_HCI_ERR_UNACCEPT_CONN_PARAMS 0x3b +#define BT_HCI_ERR_DIRECTED_ADV_TIMEOUT 0x3c + +/* EIR/AD data type definitions */ +#define BT_DATA_FLAGS 0x01 /* AD flags */ +#define BT_DATA_UUID16_SOME 0x02 /* 16-bit UUID, more available */ +#define BT_DATA_UUID16_ALL 0x03 /* 16-bit UUID, all listed */ +#define BT_DATA_UUID32_SOME 0x04 /* 32-bit UUID, more available */ +#define BT_DATA_UUID32_ALL 0x05 /* 32-bit UUID, all listed */ +#define BT_DATA_UUID128_SOME 0x06 /* 128-bit UUID, more available */ +#define BT_DATA_UUID128_ALL 0x07 /* 128-bit UUID, all listed */ +#define BT_DATA_NAME_SHORTENED 0x08 /* Shortened name */ +#define BT_DATA_NAME_COMPLETE 0x09 /* Complete name */ +#define BT_DATA_TX_POWER 0x0a /* Tx Power */ +#define BT_DATA_SOLICIT16 0x14 /* Solicit UUIDs, 16-bit */ +#define BT_DATA_SOLICIT128 0x15 /* Solicit UUIDs, 128-bit */ +#define BT_DATA_SVC_DATA16 0x16 /* Service data, 16-bit UUID */ +#define BT_DATA_GAP_APPEARANCE 0x19 /* GAP appearance */ +#define BT_DATA_SOLICIT32 0x1f /* Solicit UUIDs, 32-bit */ +#define BT_DATA_SVC_DATA32 0x20 /* Service data, 32-bit UUID */ +#define BT_DATA_SVC_DATA128 0x21 /* Service data, 128-bit UUID */ +#define BT_DATA_MANUFACTURER_DATA 0xff /* Manufacturer Specific Data */ + +#define BT_LE_AD_LIMITED 0x01 /* Limited Discoverable */ +#define BT_LE_AD_GENERAL 0x02 /* General Discoverable */ +#define BT_LE_AD_NO_BREDR 0x04 /* BR/EDR not supported */ + +struct bt_hci_evt_hdr { + uint8_t evt; + uint8_t len; +} __packed; + +#define BT_ACL_START_NO_FLUSH 0x00 +#define BT_ACL_CONT 0x01 +#define BT_ACL_START 0x02 + +#define bt_acl_handle(h) ((h) & 0x0fff) +#define bt_acl_flags(h) ((h) >> 12) +#define bt_acl_handle_pack(h, f) ((h) | ((f) << 12)) + +struct bt_hci_acl_hdr { + uint16_t handle; + uint16_t len; +} __packed; + +struct bt_hci_cmd_hdr { + uint16_t opcode; + uint8_t param_len; +} __packed; + +/* LMP features */ +#define BT_LMP_NO_BREDR 0x20 +#define BT_LMP_LE 0x40 + +/* LE features */ +#define BT_HCI_LE_ENCRYPTION 0x01 +#define BT_HCI_LE_CONN_PARAM_REQ_PROC 0x02 +#define BT_HCI_LE_SLAVE_FEATURES 0x08 + +/* Bonding/authentication types */ +#define BT_HCI_NO_BONDING 0x00 +#define BT_HCI_NO_BONDING_MITM 0x01 +#define BT_HCI_DEDICATED_BONDING 0x02 +#define BT_HCI_DEDICATED_BONDING_MITM 0x03 +#define BT_HCI_GENERAL_BONDING 0x04 +#define BT_HCI_GENERAL_BONDING_MITM 0x05 + +/* I/O capabilities */ +#define BT_IO_DISPLAY_ONLY 0x00 +#define BT_IO_DISPLAY_YESNO 0x01 +#define BT_IO_KEYBOARD_ONLY 0x02 +#define BT_IO_NO_INPUT_OUTPUT 0x03 + +/* Defined GAP timers */ +#define BT_GAP_SCAN_FAST_INTERVAL 0x0060 /* 60 ms */ +#define BT_GAP_SCAN_FAST_WINDOW 0x0030 /* 30 ms */ +#define BT_GAP_SCAN_SLOW_INTERVAL_1 0x0800 /* 1.28 s */ +#define BT_GAP_SCAN_SLOW_WINDOW_1 0x0012 /* 11.25 ms */ +#define BT_GAP_SCAN_SLOW_INTERVAL_2 0x1000 /* 2.56 s */ +#define BT_GAP_SCAN_SLOW_WINDOW_2 0x0012 /* 11.25 ms */ +#define BT_GAP_ADV_FAST_INT_MIN_1 0x0030 /* 30 ms */ +#define BT_GAP_ADV_FAST_INT_MAX_1 0x0060 /* 60 ms */ +#define BT_GAP_ADV_FAST_INT_MIN_2 0x00a0 /* 100 ms */ +#define BT_GAP_ADV_FAST_INT_MAX_2 0x00f0 /* 150 ms */ +#define BT_GAP_ADV_SLOW_INT_MIN 0x0640 /* 1 s */ +#define BT_GAP_ADV_SLOW_INT_MAX 0x0780 /* 1.2 s */ +#define BT_GAP_INIT_CONN_INT_MIN 0x0018 /* 30 ms */ +#define BT_GAP_INIT_CONN_INT_MAX 0x0028 /* 50 ms */ + +/* HCI BR/EDR link types */ +#define BT_HCI_SCO 0x00 +#define BT_HCI_ACL 0x01 +#define BT_HCI_ESCO 0x02 + +/* OpCode Group Fields */ +#define BT_OGF_LINK_CTRL 0x01 +#define BT_OGF_BASEBAND 0x03 +#define BT_OGF_INFO 0x04 +#define BT_OGF_LE 0x08 + +/* Construct OpCode from OGF and OCF */ +#define BT_OP(ogf, ocf) ((ocf) | ((ogf) << 10)) + +#define BT_HCI_OP_DISCONNECT BT_OP(BT_OGF_LINK_CTRL, 0x0006) +struct bt_hci_cp_disconnect { + uint16_t handle; + uint8_t reason; +} __packed; + +#define BT_HCI_OP_ACCEPT_CONN_REQ BT_OP(BT_OGF_LINK_CTRL, 0x0009) +struct bt_hci_cp_accept_conn_req { + bt_addr_t bdaddr; + uint8_t role; +} __packed; + +#define BT_HCI_OP_REJECT_CONN_REQ BT_OP(BT_OGF_LINK_CTRL, 0x000a) +struct bt_hci_cp_reject_conn_req { + bt_addr_t bdaddr; + uint8_t reason; +} __packed; + +#define BT_HCI_OP_LINK_KEY_REPLY BT_OP(BT_OGF_LINK_CTRL, 0x000b) +struct bt_hci_cp_link_key_reply { + bt_addr_t bdaddr; + uint8_t link_key[16]; +} __packed; + +#define BT_HCI_OP_LINK_KEY_NEG_REPLY BT_OP(BT_OGF_LINK_CTRL, 0x000c) +struct bt_hci_cp_link_key_neg_reply { + bt_addr_t bdaddr; +} __packed; + +#define BT_HCI_OP_PIN_CODE_REPLY BT_OP(BT_OGF_LINK_CTRL, 0x000d) +struct bt_hci_cp_pin_code_reply { + bt_addr_t bdaddr; + uint8_t pin_len; + uint8_t pin_code[16]; +} __packed; +struct bt_hci_rp_pin_code_reply { + uint8_t status; + bt_addr_t bdaddr; +} __packed; + +#define BT_HCI_OP_PIN_CODE_NEG_REPLY BT_OP(BT_OGF_LINK_CTRL, 0x000e) +struct bt_hci_cp_pin_code_neg_reply { + bt_addr_t bdaddr; +} __packed; +struct bt_hci_rp_pin_code_neg_reply { + uint8_t status; + bt_addr_t bdaddr; +} __packed; + +#define BT_HCI_OP_IO_CAPABILITY_REPLY BT_OP(BT_OGF_LINK_CTRL, 0x002b) +struct bt_hci_cp_io_capability_reply { + bt_addr_t bdaddr; + uint8_t capability; + uint8_t oob_data; + uint8_t authentication; +} __packed; + +#define BT_HCI_OP_IO_CAPABILITY_NEG_REPLY BT_OP(BT_OGF_LINK_CTRL, 0x0034) +struct bt_hci_cp_io_capability_neg_reply { + bt_addr_t bdaddr; + uint8_t reason; +} __packed; + +#define BT_HCI_OP_SET_EVENT_MASK BT_OP(BT_OGF_BASEBAND, 0x0001) +struct bt_hci_cp_set_event_mask { + uint8_t events[8]; +} __packed; + +#define BT_HCI_OP_RESET BT_OP(BT_OGF_BASEBAND, 0x0003) + +#define BT_HCI_OP_WRITE_SCAN_ENABLE BT_OP(BT_OGF_BASEBAND, 0x001a) +#define BT_BREDR_SCAN_DISABLED 0x00 +#define BT_BREDR_SCAN_INQUIRY 0x01 +#define BT_BREDR_SCAN_PAGE 0x02 + +#define BT_HCI_CTL_TO_HOST_FLOW_ENABLE 0x01 +#define BT_HCI_OP_SET_CTL_TO_HOST_FLOW BT_OP(BT_OGF_BASEBAND, 0x0031) + +#define BT_HCI_OP_HOST_BUFFER_SIZE BT_OP(BT_OGF_BASEBAND, 0x0033) +struct bt_hci_cp_host_buffer_size { + uint16_t acl_mtu; + uint8_t sco_mtu; + uint16_t acl_pkts; + uint16_t sco_pkts; +} __packed; + +struct bt_hci_handle_count { + uint16_t handle; + uint16_t count; +} __packed; + +#define BT_HCI_OP_HOST_NUM_COMPLETED_PACKETS BT_OP(BT_OGF_BASEBAND, 0x0035) +struct bt_hci_cp_host_num_completed_packets { + uint8_t num_handles; + struct bt_hci_handle_count h[0]; +} __packed; + +#define BT_HCI_OP_WRITE_SSP_MODE BT_OP(BT_OGF_BASEBAND, 0x0056) +struct bt_hci_cp_write_ssp_mode { + uint8_t mode; +} __packed; + +#define BT_HCI_OP_LE_WRITE_LE_HOST_SUPP BT_OP(BT_OGF_BASEBAND, 0x006d) +struct bt_hci_cp_write_le_host_supp { + uint8_t le; + uint8_t simul; +} __packed; + +#define BT_HCI_OP_READ_LOCAL_VERSION_INFO BT_OP(BT_OGF_INFO, 0x0001) +struct bt_hci_rp_read_local_version_info { + uint8_t status; + uint8_t hci_version; + uint16_t hci_revision; + uint8_t lmp_version; + uint16_t manufacturer; + uint16_t lmp_subversion; +} __packed; + +#define BT_HCI_OP_READ_SUPPORTED_COMMANDS BT_OP(BT_OGF_INFO, 0x0002) +struct bt_hci_rp_read_supported_commands { + uint8_t status; + uint8_t commands[36]; +} __packed; + +#define BT_HCI_OP_READ_LOCAL_FEATURES BT_OP(BT_OGF_INFO, 0x0003) +struct bt_hci_rp_read_local_features { + uint8_t status; + uint8_t features[8]; +} __packed; + +#define BT_HCI_OP_READ_BUFFER_SIZE BT_OP(BT_OGF_INFO, 0x0005) +struct bt_hci_rp_read_buffer_size { + uint8_t status; + uint16_t acl_max_len; + uint8_t sco_max_len; + uint16_t acl_max_num; + uint16_t sco_max_num; +} __packed; + +#define BT_HCI_OP_READ_BD_ADDR BT_OP(BT_OGF_INFO, 0x0009) +struct bt_hci_rp_read_bd_addr { + uint8_t status; + bt_addr_t bdaddr; +} __packed; + +#define BT_HCI_OP_LE_SET_EVENT_MASK BT_OP(BT_OGF_LE, 0x0001) +struct bt_hci_cp_le_set_event_mask { + uint8_t events[8]; +} __packed; +struct bt_hci_rp_le_set_event_mask { + uint8_t status; +} __packed; + +#define BT_HCI_OP_LE_READ_BUFFER_SIZE BT_OP(BT_OGF_LE, 0x0002) +struct bt_hci_rp_le_read_buffer_size { + uint8_t status; + uint16_t le_max_len; + uint8_t le_max_num; +} __packed; + +#define BT_HCI_OP_LE_READ_LOCAL_FEATURES BT_OP(BT_OGF_LE, 0x0003) +struct bt_hci_rp_le_read_local_features { + uint8_t status; + uint8_t features[8]; +} __packed; + +#define BT_HCI_OP_LE_SET_RANDOM_ADDRESS BT_OP(BT_OGF_LE, 0x0005) + +/* Advertising types */ +#define BT_LE_ADV_IND 0x00 +#define BT_LE_ADV_DIRECT_IND 0x01 +#define BT_LE_ADV_SCAN_IND 0x02 +#define BT_LE_ADV_NONCONN_IND 0x03 +#define BT_LE_ADV_DIRECT_IND_LOW_DUTY 0x04 +/* Needed in advertising reports when getting info about */ +#define BT_LE_ADV_SCAN_RSP 0x04 + +#define BT_HCI_OP_LE_SET_ADV_PARAMETERS BT_OP(BT_OGF_LE, 0x0006) +struct bt_hci_cp_le_set_adv_parameters { + uint16_t min_interval; + uint16_t max_interval; + uint8_t type; + uint8_t own_addr_type; + bt_addr_le_t direct_addr; + uint8_t channel_map; + uint8_t filter_policy; +} __packed; + +#define BT_HCI_OP_LE_SET_ADV_DATA BT_OP(BT_OGF_LE, 0x0008) +struct bt_hci_cp_le_set_adv_data { + uint8_t len; + uint8_t data[31]; +} __packed; + +#define BT_HCI_OP_LE_SET_SCAN_RSP_DATA BT_OP(BT_OGF_LE, 0x0009) +struct bt_hci_cp_le_set_scan_rsp_data { + uint8_t len; + uint8_t data[31]; +} __packed; + +#define BT_HCI_LE_ADV_DISABLE 0x00 +#define BT_HCI_LE_ADV_ENABLE 0x01 + +#define BT_HCI_OP_LE_SET_ADV_ENABLE BT_OP(BT_OGF_LE, 0x000a) +struct bt_hci_cp_le_set_adv_enable { + uint8_t enable; +} __packed; + +/* Scan types */ +#define BT_HCI_OP_LE_SET_SCAN_PARAMS BT_OP(BT_OGF_LE, 0x000b) +#define BT_HCI_LE_SCAN_PASSIVE 0x00 +#define BT_HCI_LE_SCAN_ACTIVE 0x01 + +struct bt_hci_cp_le_set_scan_params { + uint8_t scan_type; + uint16_t interval; + uint16_t window; + uint8_t addr_type; + uint8_t filter_policy; +} __packed; + +#define BT_HCI_OP_LE_SET_SCAN_ENABLE BT_OP(BT_OGF_LE, 0x000c) + +#define BT_HCI_LE_SCAN_DISABLE 0x00 +#define BT_HCI_LE_SCAN_ENABLE 0x01 + +#define BT_HCI_LE_SCAN_FILTER_DUP_DISABLE 0x00 +#define BT_HCI_LE_SCAN_FILTER_DUP_ENABLE 0x01 + +struct bt_hci_cp_le_set_scan_enable { + uint8_t enable; + uint8_t filter_dup; +} __packed; + +#define BT_HCI_OP_LE_CREATE_CONN BT_OP(BT_OGF_LE, 0x000d) +struct bt_hci_cp_le_create_conn { + uint16_t scan_interval; + uint16_t scan_window; + uint8_t filter_policy; + bt_addr_le_t peer_addr; + uint8_t own_addr_type; + uint16_t conn_interval_min; + uint16_t conn_interval_max; + uint16_t conn_latency; + uint16_t supervision_timeout; + uint16_t min_ce_len; + uint16_t max_ce_len; +} __packed; + +#define BT_HCI_OP_LE_CREATE_CONN_CANCEL BT_OP(BT_OGF_LE, 0x000e) + +#define BT_HCI_OP_LE_CONN_UPDATE BT_OP(BT_OGF_LE, 0x0013) +struct hci_cp_le_conn_update { + uint16_t handle; + uint16_t conn_interval_min; + uint16_t conn_interval_max; + uint16_t conn_latency; + uint16_t supervision_timeout; + uint16_t min_ce_len; + uint16_t max_ce_len; +} __packed; + +#define BT_HCI_OP_LE_READ_REMOTE_FEATURES BT_OP(BT_OGF_LE, 0x0016) +struct bt_hci_cp_le_read_remote_features { + uint16_t handle; +} __packed; + +#define BT_HCI_OP_LE_ENCRYPT BT_OP(BT_OGF_LE, 0x0017) +struct bt_hci_cp_le_encrypt { + uint8_t key[16]; + uint8_t plaintext[16]; +} __packed; +struct bt_hci_rp_le_encrypt { + uint8_t status; + uint8_t enc_data[16]; +} __packed; + +#define BT_HCI_OP_LE_RAND BT_OP(BT_OGF_LE, 0x0018) +struct bt_hci_rp_le_rand { + uint8_t status; + uint8_t rand[8]; +} __packed; + +#define BT_HCI_OP_LE_START_ENCRYPTION BT_OP(BT_OGF_LE, 0x0019) +struct bt_hci_cp_le_start_encryption { + uint16_t handle; + uint64_t rand; + uint16_t ediv; + uint8_t ltk[16]; +} __packed; + +#define BT_HCI_OP_LE_LTK_REQ_REPLY BT_OP(BT_OGF_LE, 0x001a) +struct bt_hci_cp_le_ltk_req_reply { + uint16_t handle; + uint8_t ltk[16]; +} __packed; + +#define BT_HCI_OP_LE_LTK_REQ_NEG_REPLY BT_OP(BT_OGF_LE, 0x001b) +struct bt_hci_cp_le_ltk_req_neg_reply { + uint16_t handle; +} __packed; + +#define BT_HCI_OP_LE_CONN_PARAM_REQ_REPLY BT_OP(BT_OGF_LE, 0x0020) +struct bt_hci_cp_le_conn_param_req_reply { + uint16_t handle; + uint16_t interval_min; + uint16_t interval_max; + uint16_t latency; + uint16_t timeout; + uint16_t min_ce_len; + uint16_t max_ce_len; +} __packed; + +#define BT_HCI_OP_LE_CONN_PARAM_REQ_NEG_REPLY BT_OP(BT_OGF_LE, 0x0021) +struct bt_hci_cp_le_conn_param_req_neg_reply { + uint16_t handle; + uint8_t reason; +} __packed; + +#define BT_HCI_OP_LE_P256_PUBLIC_KEY BT_OP(BT_OGF_LE, 0x0025) + +#define BT_HCI_OP_LE_GENERATE_DHKEY BT_OP(BT_OGF_LE, 0x0026) +struct bt_hci_cp_le_generate_dhkey { + uint8_t key[64]; +} __packed; + +/* Event definitions */ + +#define BT_HCI_EVT_CONN_COMPLETE 0x03 +struct bt_hci_evt_conn_complete { + uint8_t status; + uint16_t handle; + bt_addr_t bdaddr; + uint8_t link_type; + uint8_t encr_enabled; +} __packed; + +#define BT_HCI_EVT_CONN_REQUEST 0x04 +struct bt_hci_evt_conn_request { + bt_addr_t bdaddr; + uint8_t dev_class[3]; + uint8_t link_type; +} __packed; + +#define BT_HCI_EVT_DISCONN_COMPLETE 0x05 +struct bt_hci_evt_disconn_complete { + uint8_t status; + uint16_t handle; + uint8_t reason; +} __packed; + +#define BT_HCI_EVT_ENCRYPT_CHANGE 0x08 +struct bt_hci_evt_encrypt_change { + uint8_t status; + uint16_t handle; + uint8_t encrypt; +} __packed; + +#define BT_HCI_EVT_CMD_COMPLETE 0x0e +struct hci_evt_cmd_complete { + uint8_t ncmd; + uint16_t opcode; +} __packed; + +#define BT_HCI_EVT_CMD_STATUS 0x0f +struct bt_hci_evt_cmd_status { + uint8_t status; + uint8_t ncmd; + uint16_t opcode; +} __packed; + +#define BT_HCI_EVT_NUM_COMPLETED_PACKETS 0x13 +struct bt_hci_evt_num_completed_packets { + uint8_t num_handles; + struct bt_hci_handle_count h[0]; +} __packed; + +#define BT_HCI_EVT_PIN_CODE_REQ 0x16 +struct bt_hci_evt_pin_code_req { + bt_addr_t bdaddr; +} __packed; + +#define BT_HCI_EVT_LINK_KEY_REQ 0x17 +struct bt_hci_evt_link_key_req { + bt_addr_t bdaddr; +} __packed; + +/* Link Key types */ +#define BT_LK_COMBINATION 0x00 +#define BT_LK_LOCAL_UNIT 0x01 +#define BT_LK_REMOTE_UNIT 0x02 +#define BT_LK_DEBUG_COMBINATION 0x03 +#define BT_LK_UNAUTH_COMBINATION_P192 0x04 +#define BT_LK_AUTH_COMBINATION_P192 0x05 +#define BT_LK_CHANGED_COMBINATION 0x06 +#define BT_LK_UNAUTH_COMBINATION_P256 0x07 +#define BT_LK_AUTH_COMBINATION_P256 0x08 + +#define BT_HCI_EVT_LINK_KEY_NOTIFY 0x18 +struct bt_hci_ev_link_key_notify { + bt_addr_t bdaddr; + uint8_t link_key[16]; + uint8_t key_type; +} __packed; + +#define BT_HCI_EVT_ENCRYPT_KEY_REFRESH_COMPLETE 0x30 +struct bt_hci_evt_encrypt_key_refresh_complete { + uint8_t status; + uint16_t handle; +} __packed; + +#define BT_HCI_EVT_IO_CAPA_REQ 0x31 +struct bt_hci_evt_io_capa_req { + bt_addr_t bdaddr; +} __packed; + +#define BT_HCI_EVT_IO_CAPA_RESP 0x32 +struct bt_hci_evt_io_capa_resp { + bt_addr_t bdaddr; + uint8_t capability; + uint8_t oob_data; + uint8_t authentication; +} __packed; + +#define BT_HCI_EVT_SSP_COMPLETE 0x36 +struct bt_hci_evt_ssp_complete { + uint8_t status; + bt_addr_t bdaddr; +} __packed; + +#define BT_HCI_EVT_LE_META_EVENT 0x3e +struct bt_hci_evt_le_meta_event { + uint8_t subevent; +} __packed; + +#define BT_HCI_ROLE_MASTER 0x00 +#define BT_HCI_ROLE_SLAVE 0x01 + +#define BT_HCI_EVT_LE_CONN_COMPLETE 0x01 +struct bt_hci_evt_le_conn_complete { + uint8_t status; + uint16_t handle; + uint8_t role; + bt_addr_le_t peer_addr; + uint16_t interval; + uint16_t latency; + uint16_t supv_timeout; + uint8_t clock_accuracy; +} __packed; + +#define BT_HCI_EVT_LE_ADVERTISING_REPORT 0x02 +struct bt_hci_ev_le_advertising_info { + uint8_t evt_type; + bt_addr_le_t addr; + uint8_t length; + uint8_t data[0]; +} __packed; + +#define BT_HCI_EVT_LE_CONN_UPDATE_COMPLETE 0x03 +struct bt_hci_evt_le_conn_update_complete { + uint8_t status; + uint16_t handle; + uint16_t interval; + uint16_t latency; + uint16_t supv_timeout; +} __packed; + +#define BT_HCI_EV_LE_REMOTE_FEAT_COMPLETE 0x04 +struct bt_hci_ev_le_remote_feat_complete { + uint8_t status; + uint16_t handle; + uint8_t features[8]; +} __packed; + +#define BT_HCI_EVT_LE_LTK_REQUEST 0x05 +struct bt_hci_evt_le_ltk_request { + uint16_t handle; + uint64_t rand; + uint16_t ediv; +} __packed; + +#define BT_HCI_EVT_LE_CONN_PARAM_REQ 0x06 +struct bt_hci_evt_le_conn_param_req { + uint16_t handle; + uint16_t interval_min; + uint16_t interval_max; + uint16_t latency; + uint16_t timeout; +} __packed; + +#define BT_HCI_EVT_LE_P256_PUBLIC_KEY_COMPLETE 0x08 +struct bt_hci_evt_le_p256_public_key_complete { + uint8_t status; + uint8_t key[64]; +} __packed; + +#define BT_HCI_EVT_LE_GENERATE_DHKEY_COMPLETE 0x09 +struct bt_hci_evt_le_generate_dhkey_complete { + uint8_t status; + uint8_t dhkey[32]; +} __packed; + +#ifdef __cplusplus +} +#endif + +#endif /* __BT_HCI_H */ diff --git a/system/libarc32_arduino101/drivers/bluetooth/uuid.h b/system/libarc32_arduino101/drivers/bluetooth/uuid.h new file mode 100644 index 00000000..a54108ba --- /dev/null +++ b/system/libarc32_arduino101/drivers/bluetooth/uuid.h @@ -0,0 +1,463 @@ +/** @file + * @brief Bluetooth UUID handling + */ + +/* + * Copyright (c) 2015 Intel Corporation + * + * 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 __BT_UUID_H +#define __BT_UUID_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** @brief Bluetooth UUID types */ +enum { + BT_UUID_TYPE_16, + BT_UUID_TYPE_128, +}; + +/** @brief This is a 'tentative' type and should be used as a pointer only */ +struct bt_uuid { + uint8_t type; +}; + +struct bt_uuid_16 { + struct bt_uuid uuid; + uint16_t val; +}; + +struct bt_uuid_128 { + struct bt_uuid uuid; + uint8_t val[16]; +}; + +#define BT_UUID_INIT_16(value) \ +{ \ + .uuid.type = BT_UUID_TYPE_16, \ + .val = (value), \ +} + +#define BT_UUID_INIT_128(value...) \ +{ \ + .uuid.type = BT_UUID_TYPE_128, \ + .val = { value }, \ +} + +#define BT_UUID_DECLARE_16(value) \ + ((struct bt_uuid *) (&(struct bt_uuid_16) BT_UUID_INIT_16(value))) +#define BT_UUID_DECLARE_128(value...) \ + ((struct bt_uuid *) (&(struct bt_uuid_128) BT_UUID_INIT_128(value))) + +#define BT_UUID_16(__u) CONTAINER_OF(__u, struct bt_uuid_16, uuid) +#define BT_UUID_128(__u) CONTAINER_OF(__u, struct bt_uuid_128, uuid) + +/** @def BT_UUID_GAP + * @brief Generic Access + */ +#define BT_UUID_GAP BT_UUID_DECLARE_16(0x1800) +#define BT_UUID_GAP_VAL 0x1800 +/** @def BT_UUID_GATT + * @brief Generic Attribute + */ +#define BT_UUID_GATT BT_UUID_DECLARE_16(0x1801) +#define BT_UUID_GATT_VAL 0x1801 +/** @def BT_UUID_CTS + * @brief Current Time Service + */ +#define BT_UUID_CTS BT_UUID_DECLARE_16(0x1805) +#define BT_UUID_CTS_VAL 0x1805 +/** @def BT_UUID_DIS + * @brief Device Information Service + */ +#define BT_UUID_DIS BT_UUID_DECLARE_16(0x180a) +#define BT_UUID_DIS_VAL 0x180a +/** @def BT_UUID_HRS + * @brief Heart Rate Service + */ +#define BT_UUID_HRS BT_UUID_DECLARE_16(0x180d) +#define BT_UUID_HRS_VAL 0x180d +/** @def BT_UUID_BAS + * @brief Battery Service + */ +#define BT_UUID_BAS BT_UUID_DECLARE_16(0x180f) +#define BT_UUID_BAS_VAL 0x180f +/** @def BT_UUID_RSCS + * @brief Running Speed and Cadence Service + */ +#define BT_UUID_RSCS BT_UUID_DECLARE_16(0x1814) +#define BT_UUID_RSCS_VAL 0x1814 +/** @def BT_UUID_CSC + * @brief Cycling Speed and Cadence Service + */ +#define BT_UUID_CSC BT_UUID_DECLARE_16(0x1816) +#define BT_UUID_CSC_VAL 0x1816 +/** @def BT_UUID_ESS + * @brief Environmental Sensing Service + */ +#define BT_UUID_ESS BT_UUID_DECLARE_16(0x181a) +#define BT_UUID_ESS_VAL 0x181a +/** @def BT_UUID_IPSS + * @brief IP Support Service + */ +#define BT_UUID_IPSS BT_UUID_DECLARE_16(0x1820) +#define BT_UUID_IPSS_VAL 0x1820 +/** @def BT_UUID_LNS + * @brief Location and Navigation Support Service + */ +#define BT_UUID_LNS BT_UUID_DECLARE_16(0x1819) +#define BT_UUID_LNS_VAL 0x1819 +/** @def BT_UUID_GATT_PRIMARY + * @brief GATT Primary Service + */ +#define BT_UUID_GATT_PRIMARY BT_UUID_DECLARE_16(0x2800) +#define BT_UUID_GATT_PRIMARY_VAL 0x2800 +/** @def BT_UUID_GATT_SECONDARY + * @brief GATT Secondary Service + */ +#define BT_UUID_GATT_SECONDARY BT_UUID_DECLARE_16(0x2801) +#define BT_UUID_GATT_SECONDARY_VAL 0x2801 +/** @def BT_UUID_GATT_INCLUDE + * @brief GATT Include Service + */ +#define BT_UUID_GATT_INCLUDE BT_UUID_DECLARE_16(0x2802) +#define BT_UUID_GATT_INCLUDE_VAL 0x2802 +/** @def BT_UUID_GATT_CHRC + * @brief GATT Characteristic + */ +#define BT_UUID_GATT_CHRC BT_UUID_DECLARE_16(0x2803) +#define BT_UUID_GATT_CHRC_VAL 0x2803 +/** @def BT_UUID_GATT_CEP + * @brief GATT Characteristic Extended Properties + */ +#define BT_UUID_GATT_CEP BT_UUID_DECLARE_16(0x2900) +#define BT_UUID_GATT_CEP_VAL 0x2900 +/** @def BT_UUID_GATT_CUD + * @brief GATT Characteristic User Description + */ +#define BT_UUID_GATT_CUD BT_UUID_DECLARE_16(0x2901) +#define BT_UUID_GATT_CUD_VAL 0x2901 +/** @def BT_UUID_GATT_CCC + * @brief GATT Client Characteristic Configuration + */ +#define BT_UUID_GATT_CCC BT_UUID_DECLARE_16(0x2902) +#define BT_UUID_GATT_CCC_VAL 0x2902 +/** @def BT_UUID_GATT_SCC + * @brief GATT Server Characteristic Configuration + */ +#define BT_UUID_GATT_SCC BT_UUID_DECLARE_16(0x2903) +#define BT_UUID_GATT_SCC_VAL 0x2903 +/** @def BT_UUID_GATT_CPF + * @brief GATT Characteristic Presentation Format + */ +#define BT_UUID_GATT_CPF BT_UUID_DECLARE_16(0x2904) +#define BT_UUID_GATT_CPF_VAL 0x2904 +/** @def BT_UUID_VALID_RANGE + * @brief Valid Range Descriptor + */ +#define BT_UUID_VALID_RANGE BT_UUID_DECLARE_16(0x2906) +#define BT_UUID_VALID_RANGE_VAL 0x2906 +/** @def BT_UUID_ES_CONFIGURATION + * @brief Environmental Sensing Configuration Descriptor + */ +#define BT_UUID_ES_CONFIGURATION BT_UUID_DECLARE_16(0x290b) +#define BT_UUID_ES_CONFIGURATION_VAL 0x290b +/** @def BT_UUID_ES_MEASUREMENT + * @brief Environmental Sensing Measurement Descriptor + */ +#define BT_UUID_ES_MEASUREMENT BT_UUID_DECLARE_16(0x290c) +#define BT_UUID_ES_MEASUREMENT_VAL 0x290c +/** @def BT_UUID_ES_TRIGGER_SETTING + * @brief Environmental Sensing Trigger Setting Descriptor + */ +#define BT_UUID_ES_TRIGGER_SETTING BT_UUID_DECLARE_16(0x290d) +#define BT_UUID_ES_TRIGGER_SETTING_VAL 0x290d +/** @def BT_UUID_GAP_DEVICE_NAME + * @brief GAP Characteristic Device Name + */ +#define BT_UUID_GAP_DEVICE_NAME BT_UUID_DECLARE_16(0x2a00) +#define BT_UUID_GAP_DEVICE_NAME_VAL 0x2a00 +/** @def BT_UUID_GAP_APPEARANCE + * @brief GAP Characteristic Appearance + */ +#define BT_UUID_GAP_APPEARANCE BT_UUID_DECLARE_16(0x2a01) +#define BT_UUID_GAP_APPEARANCE_VAL 0x2a01 +/** @def BT_UUID_GAP_PPCP + * @brief GAP Characteristic Peripheral Preferred Connection Parameters + */ +#define BT_UUID_GAP_PPCP BT_UUID_DECLARE_16(0x2a04) +#define BT_UUID_GAP_PPCP_VAL 0x2a04 +/** @def BT_UUID_BAS_BATTERY_LEVEL + * @brief BAS Characteristic Battery Level + */ +#define BT_UUID_BAS_BATTERY_LEVEL BT_UUID_DECLARE_16(0x2a19) +#define BT_UUID_BAS_BATTERY_LEVEL_VAL 0x2a19 +/** @def BT_UUID_DIS_SYSTEM_ID + * @brief DIS Characteristic System ID + */ +#define BT_UUID_DIS_SYSTEM_ID BT_UUID_DECLARE_16(0x2a23) +#define BT_UUID_DIS_SYSTEM_ID_VAL 0x2a23 +/** @def BT_UUID_DIS_MODEL_NUMBER + * @brief DIS Characteristic Model Number String + */ +#define BT_UUID_DIS_MODEL_NUMBER BT_UUID_DECLARE_16(0x2a24) +#define BT_UUID_DIS_MODEL_NUMBER_VAL 0x2a24 +/** @def BT_UUID_DIS_SERIAL_NUMBER + * @brief DIS Characteristic Serial Number String + */ +#define BT_UUID_DIS_SERIAL_NUMBER BT_UUID_DECLARE_16(0x2a25) +#define BT_UUID_DIS_SERIAL_NUMBER_VAL 0x2a25 +/** @def BT_UUID_DIS_FIRMWARE_REVISION + * @brief DIS Characteristic Firmware Revision String + */ +#define BT_UUID_DIS_FIRMWARE_REVISION BT_UUID_DECLARE_16(0x2a26) +#define BT_UUID_DIS_FIRMWARE_REVISION_VAL 0x2a26 +/** @def BT_UUID_DIS_HARDWARE_REVISION + * @brief DIS Characteristic Hardware Revision String + */ +#define BT_UUID_DIS_HARDWARE_REVISION BT_UUID_DECLARE_16(0x2a27) +#define BT_UUID_DIS_HARDWARE_REVISION_VAL 0x2a27 +/** @def BT_UUID_DIS_SOFTWARE_REVISION + * @brief DIS Characteristic Software Revision String + */ +#define BT_UUID_DIS_SOFTWARE_REVISION BT_UUID_DECLARE_16(0x2a28) +#define BT_UUID_DIS_SOFTWARE_REVISION_VAL 0x2a28 +/** @def BT_UUID_DIS_MANUFACTURER_NAME + * @brief DIS Characteristic Manufacturer Name String + */ +#define BT_UUID_DIS_MANUFACTURER_NAME BT_UUID_DECLARE_16(0x2a29) +#define BT_UUID_DIS_MANUFACTURER_NAME_VAL 0x2a29 +/** @def BT_UUID_DIS_PNP_ID + * @brief DIS Characteristic PnP ID + */ +#define BT_UUID_DIS_PNP_ID BT_UUID_DECLARE_16(0x2a50) +#define BT_UUID_DIS_PNP_ID_VAL 0x2a50 +/** @def BT_UUID_RSC_MEASUREMENT + * @brief RSC Characteristic measurement ID + */ +#define BT_UUID_RSC_MEASUREMENT BT_UUID_DECLARE_16(0x2a53) +#define BT_UUID_RSC_MEASUREMENT_VAL 0x2a53 +/** @def BT_UUID_RSC_FEATURE + * @brief RSC Characteristic feature ID + */ +#define BT_UUID_RSC_FEATURE BT_UUID_DECLARE_16(0x2a54) +#define BT_UUID_RSC_FEATURE_VAL 0x2a54 +/** @def BT_UUID_CTS_CURRENT_TIME + * @brief CTS Characteristic Current Time + */ +#define BT_UUID_CTS_CURRENT_TIME BT_UUID_DECLARE_16(0x2a2b) +#define BT_UUID_CTS_CURRENT_TIME_VAL 0x2a2b +/** @def BT_UUID_MAGN_DECLINATION + * @brief Magnetic Declination Characteristic + */ +#define BT_UUID_MAGN_DECLINATION BT_UUID_DECLARE_16(0x2a2c) +#define BT_UUID_MAGN_DECLINATION_VAL 0x2a2c +/** @def BT_UUID_HRS_MEASUREMENT + * @brief HRS Characteristic Measurement Interval + */ +#define BT_UUID_HRS_MEASUREMENT BT_UUID_DECLARE_16(0x2a37) +#define BT_UUID_HRS_MEASUREMENT_VAL 0x2a37 +/** @def BT_UUID_HRS_BODY_SENSOR + * @brief HRS Characteristic Body Sensor Location + */ +#define BT_UUID_HRS_BODY_SENSOR BT_UUID_DECLARE_16(0x2a38) +#define BT_UUID_HRS_BODY_SENSOR_VAL 0x2a38 +/** @def BT_UUID_HRS_CONTROL_POINT + * @brief HRS Characteristic Control Point + */ +#define BT_UUID_HRS_CONTROL_POINT BT_UUID_DECLARE_16(0x2a39) +#define BT_UUID_HRS_CONTROL_POINT_VAL 0x2a39 +/** @def BT_UUID_CSC_MEASUREMENT + * @brief CSC Measurement Characteristic + */ +#define BT_UUID_CSC_MEASUREMENT BT_UUID_DECLARE_16(0x2a5b) +#define BT_UUID_CSC_MEASUREMENT_VAL 0x2a5b +/** @def BT_UUID_CSC_FEATURE + * @brief CSC Feature Characteristic + */ +#define BT_UUID_CSC_FEATURE BT_UUID_DECLARE_16(0x2a5c) +#define BT_UUID_CSC_FEATURE_VAL 0x2a5c +/** @def BT_UUID_SENSOR_LOCATION + * @brief Sensor Location Characteristic + */ +#define BT_UUID_SENSOR_LOCATION BT_UUID_DECLARE_16(0x2a5d) +#define BT_UUID_SENSOR_LOCATION_VAL 0x2a5d +/** @def BT_UUID_SC_CONTROL_POINT + * @brief SC Control Point Characteristic + */ +#define BT_UUID_SC_CONTROL_POINT BT_UUID_DECLARE_16(0x2a55) +#define BT_UUID_SC_CONTROL_POINT_VAl 0x2a55 +/** @def BT_UUID_LNS_CONTROL_POINT + * @brief LNS Control Point Characteristic + */ +#define BT_UUID_LNS_CONTROL_POINT BT_UUID_DECLARE_16(0x2a6B) +#define BT_UUID_LNS_CONTROL_POINT_VAL 0x2a6B +/** @def BT_UUID_LNS_LOCATION_SPEED + * @brief LNS Characteristic Location and Speed + */ +#define BT_UUID_LNS_LOCATION_SPEED BT_UUID_DECLARE_16(0x2a67) +#define BT_UUID_LNS_LOCATION_SPEED_VAL 0x2a67 +/** @def BT_UUID_LNS_FEATURE + * @brief LNS Characteristic Feature + */ +#define BT_UUID_LNS_FEATURE BT_UUID_DECLARE_16(0x2a6a) +#define BT_UUID_LNS_FEATURE_VAL 0x2a6a +/** @def BT_UUID_ELEVATION + * @brief Elevation Characteristic + */ +#define BT_UUID_ELEVATION BT_UUID_DECLARE_16(0x2a6c) +#define BT_UUID_ELEVATION_VAL 0x2a6c +/** @def BT_UUID_PRESSURE + * @brief Pressure Characteristic + */ +#define BT_UUID_PRESSURE BT_UUID_DECLARE_16(0x2a6d) +#define BT_UUID_PRESSURE_VAL 0x2a6d +/** @def BT_UUID_TEMPERATURE + * @brief Temperature Characteristic + */ +#define BT_UUID_TEMPERATURE BT_UUID_DECLARE_16(0x2a6e) +#define BT_UUID_TEMPERATURE_VAL 0x2a6e +/** @def BT_UUID_HUMIDITY + * @brief Humidity Characteristic + */ +#define BT_UUID_HUMIDITY BT_UUID_DECLARE_16(0x2a6f) +#define BT_UUID_HUMIDITY_VAL 0x2a6f +/** @def BT_UUID_TRUE_WIND_SPEED + * @brief True Wind Speed Characteristic + */ +#define BT_UUID_TRUE_WIND_SPEED BT_UUID_DECLARE_16(0x2a70) +#define BT_UUID_TRUE_WIND_SPEED_VAL 0x2a70 +/** @def BT_UUID_TRUE_WIND_DIR + * @brief True Wind Direction Characteristic + */ +#define BT_UUID_TRUE_WIND_DIR BT_UUID_DECLARE_16(0x2a71) +#define BT_UUID_TRUE_WIND_DIR_VAL 0x2a71 +/** @def BT_UUID_APPARENT_WIND_SPEED + * @brief Apparent Wind Speed Characteristic + */ +#define BT_UUID_APPARENT_WIND_SPEED BT_UUID_DECLARE_16(0x2a72) +#define BT_UUID_APPARENT_WIND_SPEED_VAL 0x2a72 +/** @def BT_UUID_APPARENT_WIND_DIR + * @brief Apparent Wind Direction Characteristic + */ +#define BT_UUID_APPARENT_WIND_DIR BT_UUID_DECLARE_16(0x2a73) +#define BT_UUID_APPARENT_WIND_DIR_VAL 0x2a73 +/** @def BT_UUID_GUST_FACTOR + * @brief Gust Factor Characteristic + */ +#define BT_UUID_GUST_FACTOR BT_UUID_DECLARE_16(0x2a74) +#define BT_UUID_GUST_FACTOR_VAL 0x2a74 +/** @def BT_UUID_POLLEN_CONCENTRATION + * @brief Pollen Concentration Characteristic + */ +#define BT_UUID_POLLEN_CONCENTRATION BT_UUID_DECLARE_16(0x2a75) +#define BT_UUID_POLLEN_CONCENTRATION_VAL 0x2a75 +/** @def BT_UUID_UV_INDEX + * @brief UV Index Characteristic + */ +#define BT_UUID_UV_INDEX BT_UUID_DECLARE_16(0x2a76) +#define BT_UUID_UV_INDEX_VAL 0x2a76 +/** @def BT_UUID_IRRADIANCE + * @brief Irradiance Characteristic + */ +#define BT_UUID_IRRADIANCE BT_UUID_DECLARE_16(0x2a77) +#define BT_UUID_IRRADIANCE_VAL 0x2a77 +/** @def BT_UUID_RAINFALL + * @brief Rainfall Characteristic + */ +#define BT_UUID_RAINFALL BT_UUID_DECLARE_16(0x2a78) +#define BT_UUID_RAINFALL_VAL 0x2a78 +/** @def BT_UUID_WIND_CHILL + * @brief Wind Chill Characteristic + */ +#define BT_UUID_WIND_CHILL BT_UUID_DECLARE_16(0x2a79) +#define BT_UUID_WIND_CHILL_VAL 0x2a79 +/** @def BT_UUID_HEAT_INDEX + * @brief Heat Index Characteristic + */ +#define BT_UUID_HEAT_INDEX BT_UUID_DECLARE_16(0x2a7a) +#define BT_UUID_HEAT_INDEX_VAL 0x2a7a +/** @def BT_UUID_DEW_POINT + * @brief Dew Point Characteristic + */ +#define BT_UUID_DEW_POINT BT_UUID_DECLARE_16(0x2a7b) +#define BT_UUID_DEW_POINT_VAL 0x2a7b +/** @def BT_UUID_DESC_VALUE_CHANGED + * @brief Descriptor Value Changed Characteristic + */ +#define BT_UUID_DESC_VALUE_CHANGED BT_UUID_DECLARE_16(0x2a7d) +#define BT_UUID_DESC_VALUE_CHANGED_VAL 0x2a7d +/** @def BT_UUID_MAGN_FLUX_DENSITY_2D + * @brief Magnetic Flux Density - 2D Characteristic + */ +#define BT_UUID_MAGN_FLUX_DENSITY_2D BT_UUID_DECLARE_16(0x2aa0) +#define BT_UUID_MAGN_FLUX_DENSITY_2D_VAL 0x2aa0 +/** @def BT_UUID_MAGN_FLUX_DENSITY_3D + * @brief Magnetic Flux Density - 3D Characteristic + */ +#define BT_UUID_MAGN_FLUX_DENSITY_3D BT_UUID_DECLARE_16(0x2aa1) +#define BT_UUID_MAGN_FLUX_DENSITY_3D_VAL 0x2aa1 +/** @def BT_UUID_BAR_PRESSURE_TREND + * @brief Barometric Pressure Trend Characteristic + */ +#define BT_UUID_BAR_PRESSURE_TREND BT_UUID_DECLARE_16(0x2aa3) +#define BT_UUID_BAR_PRESSURE_TREND_VAL 0x2aa3 + +/** @brief Compare Bluetooth UUIDs. + * + * Compares 2 Bluetooth UUIDs, if the types are different both UUIDs are + * first converted to 128 bits format before comparing. + * + * @param u1 First Bluetooth UUID to compare + * @param u2 Second Bluetooth UUID to compare + * + * @return negative value if @a u1 < @a u2, 0 if @a u1 == @a u2, else positive + */ +int bt_uuid_cmp(const struct bt_uuid *u1, const struct bt_uuid *u2); + +#if defined(CONFIG_BLUETOOTH_DEBUG) +/** @brief Convert Bluetooth UUID to string. + * + * Converts Bluetooth UUID to string. UUID has to be in 16 bits or 128 bits + * format. + * + * @param uuid Bluetooth UUID + * @param str pointer where to put converted string + * @param len length of str + * + * @return N/A + */ +void bt_uuid_to_str(const struct bt_uuid *uuid, char *str, size_t len); + +/** @brief Convert Bluetooth UUID to string in place. + * + * Converts Bluetooth UUID to string in place. UUID has to be in 16 bits or + * 128 bits format. + * + * @param uuid Bluetooth UUID + * + * @return String representation of the UUID given + */ +const char *bt_uuid_str(const struct bt_uuid *uuid); +#endif /* CONFIG_BLUETOOTH_DEBUG */ + +#ifdef __cplusplus +} +#endif + +#endif /* __BT_UUID_H */ diff --git a/system/libarc32_arduino101/drivers/intel_qrk_i2c.c b/system/libarc32_arduino101/drivers/intel_qrk_i2c.c new file mode 100644 index 00000000..1b9cb274 --- /dev/null +++ b/system/libarc32_arduino101/drivers/intel_qrk_i2c.c @@ -0,0 +1,838 @@ +/* -------------------------------------------------------------------- +** +** Synopsys DesignWare AMBA Software Driver Kit and +** documentation (hereinafter, "Software") is an Unsupported +** proprietary work of Synopsys, Inc. unless otherwise expressly +** agreed to in writing between Synopsys and you. +** +** The Software IS NOT an item of Licensed Software or Licensed +** Product under any End User Software License Agreement or Agreement +** for Licensed Product with Synopsys or any supplement thereto. You +** are permitted to use and redistribute this Software in source and +** binary forms, with or without modification, provided that +** redistributions of source code must retain this notice. You may not +** view, use, disclose, copy or distribute this file or any information +** contained herein except pursuant to this license grant from Synopsys. +** If you do not agree with this notice, including the disclaimer +** below, then you are not authorized to use the Software. +** +** THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" +** BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +** FOR A PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL +** SYNOPSYS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +** EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +** PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +** OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE +** USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +** DAMAGE. +** +** -------------------------------------------------------------------- +*/ + +/**************************************************************************************** + * + * Modifications Copyright (c) 2015, Intel Corporation. All rights reserved. + * + ***************************************************************************************/ + +#include "intel_qrk_i2c.h" + +#include +#include +#include +#include + +#include "clk_system.h" +#include "platform.h" +#include "portable.h" +#include "scss_registers.h" + +#include "soc_i2c_priv.h" + +typedef uint8_t DATA_BUFF; +typedef void (*MY_ISR)(); + +typedef struct { + uint32_t BASE; // base address of device register set + + volatile uint8_t + state; /* last direction of transfer - used by ISR to call right + callback */ + uint16_t fifo_depth; + /* Transmitted bytes. */ + uint32_t total_read_bytes; + uint32_t total_write_bytes; + uint32_t tx_len; + uint32_t rx_len; + uint32_t rx_tx_len; // tx_len + rx_len + uint8_t *i2c_write_buff; + uint8_t *i2c_read_buff; + + volatile uint8_t tx_watermark; /* TX watermark level */ + volatile uint8_t rx_watermark; /* RX watermark level */ + + /* Callbacks */ + MY_ISR ISR; /* pointer to ISR function */ + i2c_callback tx_cb; /* Write callback */ + i2c_callback rx_cb; /* Read callback */ + i2c_callback err_cb; /* Error callback */ + uint32_t cb_rx_data; /* pass data back for callbacks above (aligned to + callbacks) */ + uint32_t cb_tx_data; + uint32_t cb_err_data; + + uint8_t send_restart; + uint8_t send_stop; + + struct clk_gate_info_s clk_gate_info; /*!< clock gate data */ + + /* Config params */ + I2C_SPEED speed; + I2C_ADDR_MODE addr_mode; + I2C_MODE_TYPE mode; + uint32_t slave_addr; + /* Slave specific */ + SOC_I2C_SLAVE_MODE slave_mode; +} i2c_internal_data_t; + +/* device config keeper */ +static i2c_internal_data_t devices[2]; + +static void soc_i2c_abort_transfer(i2c_internal_data_t *dev) +{ + volatile uint64_t timeout = 1000000 * 32; + do { + MMIO_REG_VAL_FROM_BASE(dev->BASE, IC_ENABLE) = IC_ABORT_BIT; + + if ((MMIO_REG_VAL_FROM_BASE(dev->BASE, IC_ENABLE) & IC_ABORT_BIT) == 0) + return; + } while (timeout-- > 0); + + return; +} + +static void soc_i2c_enable_device(i2c_internal_data_t *dev, bool enable) +{ + volatile uint64_t timeout = 1000000 * 32; + do { + MMIO_REG_VAL_FROM_BASE(dev->BASE, IC_ENABLE) = + enable ? IC_ENABLE_BIT : 0; + + if ((MMIO_REG_VAL_FROM_BASE(dev->BASE, IC_ENABLE_STATUS) & + IC_ENABLE_BIT) == (enable ? IC_ENABLE_BIT : 0)) + return; + } while (timeout-- > 0); + + return; +} + +static void soc_end_data_transfer(i2c_internal_data_t *dev) +{ + uint32_t state = dev->state; + + if ((dev->mode == I2C_MASTER) && (dev->send_stop)) { + soc_i2c_enable_device(dev, false); + } + + dev->state = I2C_STATE_READY; + + if (I2C_CMD_RECV == state) { + if (NULL != dev->rx_cb) { + dev->cb_rx_data = dev->total_read_bytes; + dev->total_read_bytes = 0; + dev->rx_cb(dev->cb_rx_data); + } + } else if (I2C_CMD_SEND == state) { + if (NULL != dev->tx_cb) { + dev->tx_cb(dev->cb_tx_data); + } + } else if (I2C_CMD_SLAVE_SEND == state) { + dev->tx_len = dev->total_write_bytes = 0; + } else if (I2C_CMD_ERROR == state) { + if (NULL != dev->err_cb) { + dev->err_cb(dev->cb_err_data); + } + } +} + +static void soc_i2c_recv_data(i2c_internal_data_t *dev) +{ + uint32_t rx_valid = 0; + + rx_valid = MMIO_REG_VAL_FROM_BASE(dev->BASE, IC_RXFLR); + + for (; dev->total_read_bytes < dev->rx_len && rx_valid > 0; rx_valid--) { + dev->i2c_read_buff[dev->total_read_bytes++] = + MMIO_REG_VAL_FROM_BASE(dev->BASE, IC_DATA_CMD); + } + + return; +} + +static void soc_i2c_xmit_data(i2c_internal_data_t *dev) +{ + uint32_t tx_limit, rx_limit; + + if (dev->mode == I2C_SLAVE) { + if (dev->total_write_bytes == dev->tx_len) { + if (NULL != dev->tx_cb) { + dev->tx_cb(dev->cb_tx_data); + } + } + } + + if (!dev->rx_tx_len) { + return; + } + + tx_limit = dev->fifo_depth - MMIO_REG_VAL_FROM_BASE(dev->BASE, IC_TXFLR); + rx_limit = dev->fifo_depth - MMIO_REG_VAL_FROM_BASE(dev->BASE, IC_RXFLR); + + while (dev->total_write_bytes < dev->rx_tx_len && tx_limit > 0 && + rx_limit > 0) { + uint32_t cmd = 0; + if (dev->send_restart) { + cmd |= IC_RESTART_BIT; + dev->send_restart = false; + } + + if (((dev->total_write_bytes + 1) == dev->rx_tx_len) && + dev->send_stop) { + cmd |= IC_STOP_BIT; + } + + if (dev->tx_len > 0) { // something to transmit + cmd |= dev->i2c_write_buff[dev->total_write_bytes]; + } else { + cmd |= IC_CMD_BIT; + rx_limit--; + } + MMIO_REG_VAL_FROM_BASE(dev->BASE, IC_DATA_CMD) = cmd; + tx_limit--; + dev->total_write_bytes++; + } +} + +/* SOC I2C interrupt handler */ +static void soc_i2c_isr(i2c_internal_data_t *dev) +{ + volatile uint32_t stat = 0; + stat = MMIO_REG_VAL_FROM_BASE(dev->BASE, IC_INTR_STAT); + + dev->cb_err_data = 0; + + if (stat & IC_INTR_RX_UNDER) + MMIO_REG_VAL_FROM_BASE(dev->BASE, IC_CLR_RX_UNDER); + + if (stat & IC_INTR_RX_OVER) + MMIO_REG_VAL_FROM_BASE(dev->BASE, IC_CLR_RX_OVER); + + if (stat & IC_INTR_TX_OVER) + MMIO_REG_VAL_FROM_BASE(dev->BASE, IC_CLR_TX_OVER); + + if (stat & IC_INTR_RD_REQ) + MMIO_REG_VAL_FROM_BASE(dev->BASE, IC_CLR_RD_REQ); + + if (stat & IC_INTR_TX_ABRT) { + dev->cb_err_data = MMIO_REG_VAL_FROM_BASE(dev->BASE, IC_TX_ABRT_SOURCE); + MMIO_REG_VAL_FROM_BASE(dev->BASE, IC_CLR_TX_ABRT); + } + + if (stat & IC_INTR_RX_DONE) + MMIO_REG_VAL_FROM_BASE(dev->BASE, IC_CLR_RX_DONE); + + if (stat & IC_INTR_ACTIVITY) + MMIO_REG_VAL_FROM_BASE(dev->BASE, IC_CLR_ACTIVITY); + + if (stat & IC_INTR_STOP_DET) + MMIO_REG_VAL_FROM_BASE(dev->BASE, IC_CLR_STOP_DET); + + if (stat & IC_INTR_START_DET) + MMIO_REG_VAL_FROM_BASE(dev->BASE, IC_CLR_START_DET); + + if (stat & IC_INTR_GEN_CALL) + MMIO_REG_VAL_FROM_BASE(dev->BASE, IC_CLR_GEN_CALL); + + if (stat & (IC_INTR_TX_ABRT | IC_INTR_TX_OVER | IC_INTR_RX_OVER | + IC_INTR_RX_UNDER)) { + dev->state = I2C_CMD_ERROR; + dev->send_stop = true; + goto done; + } + + if (!dev->send_stop && dev->total_write_bytes == dev->rx_tx_len && + dev->total_read_bytes == dev->rx_len) { + int mask = MMIO_REG_VAL_FROM_BASE(dev->BASE, IC_INTR_MASK); + mask &= ~IC_INTR_TX_EMPTY; + MMIO_REG_VAL_FROM_BASE(dev->BASE, IC_INTR_MASK) = mask; + goto done; + } + + if (stat & IC_INTR_RX_FULL) { + dev->state = I2C_CMD_RECV; + soc_i2c_recv_data(dev); + } + + if (stat & IC_INTR_TX_EMPTY) { + soc_i2c_xmit_data(dev); + } + + if (stat & IC_INTR_RD_REQ) { + dev->state = I2C_CMD_SLAVE_SEND; + soc_i2c_xmit_data(dev); + } + + if (stat & IC_INTR_RX_DONE) { + goto done; + } + + if (stat & IC_INTR_STOP_DET) { + goto done; + } + + return; + +done: + soc_end_data_transfer(dev); +} + +DECLARE_INTERRUPT_HANDLER void isr_dev_0() +{ + soc_i2c_isr(&devices[0]); +} + +DECLARE_INTERRUPT_HANDLER void isr_dev_1() +{ + soc_i2c_isr(&devices[1]); +} + +static void soc_i2c_master_init_transfer(i2c_internal_data_t *dev) +{ + volatile uint32_t ic_con = 0, ic_tar = 0; + + soc_i2c_enable_device(dev, false); + + /* Setup IC_CON */ + ic_con = MMIO_REG_VAL_FROM_BASE(dev->BASE, IC_CON); + + /* Set addressing mode - (initialisation = 7 bit) */ + if (I2C_10_Bit == dev->addr_mode) { + ic_con |= IC_MASTER_ADDR_MODE_BIT; + ic_tar = IC_TAR_10BITADDR_MASTER; + } else { + ic_con &= ~IC_MASTER_ADDR_MODE_BIT; + } + + MMIO_REG_VAL_FROM_BASE(dev->BASE, IC_CON) = ic_con; + + /* Set slave address */ + MMIO_REG_VAL_FROM_BASE(dev->BASE, IC_TAR) = ic_tar | dev->slave_addr; + + /* Disable interrupts */ + MMIO_REG_VAL_FROM_BASE(dev->BASE, IC_INTR_MASK) = SOC_DISABLE_ALL_I2C_INT; + + /* Clear interrupts */ + MMIO_REG_VAL_FROM_BASE(dev->BASE, IC_CLR_INTR); + + soc_i2c_enable_device(dev, true); + + /* Enable necesary interrupts */ + MMIO_REG_VAL_FROM_BASE(dev->BASE, IC_INTR_MASK) = SOC_ENABLE_RX_TX_INT_I2C; + + return; +} + +static DRIVER_API_RC soc_i2c_init(i2c_internal_data_t *dev) +{ + volatile uint32_t ic_con = 0; + DRIVER_API_RC rc = DRV_RC_OK; + uint32_t i = 0; + + dev->send_stop = true; + + soc_i2c_enable_device(dev, false); + + /* Setup IC_CON */ + ic_con = IC_STOP_DET_IFADDRESSED; + + /* Set master or slave mode - (initialisation = slave) */ + if (I2C_MASTER == dev->mode) { + ic_con |= IC_SLAVE_DISABLE_BIT; /* SET TRUE */ + ic_con |= IC_MASTER_EN_BIT; + } else { + ic_con &= (~IC_SLAVE_DISABLE_BIT); /* SET TRUE */ + ic_con &= (~IC_MASTER_EN_BIT); + } + + /* Set restart - so far compile time option - (initialisation = OFF) */ + ic_con |= IC_RESTART_EN_BIT; + + /* Set addressing mode - (initialisation = 7 bit) */ + if (I2C_10_Bit == dev->addr_mode) { + ic_con |= IC_MASTER_ADDR_MODE_BIT; + ic_con |= IC_SLAVE_ADDR_MODE_BIT; + } + + /* Set speed */ + ic_con |= (dev->speed << 1); + + /* Set TX interrupt mode */ + ic_con |= IC_TX_INTR_MODE; + + /* Set the IC_CON register */ + MMIO_REG_VAL_FROM_BASE(dev->BASE, IC_CON) = ic_con; + + /* Wait for register to set */ + while (MMIO_REG_VAL_FROM_BASE(dev->BASE, IC_CON) != ic_con) { + i++; + if (i >= STATUS_DELAY) { + rc = DRV_RC_FAIL; + } /* Registers wasn't set successfuly - indicate I2C malfunction */ + } + + /* END of setup IC_CON */ + + if (I2C_SLOW == + dev->speed) /* This is setter so prefering readability above speed */ + { + /* Set HCNT */ + MMIO_REG_VAL_FROM_BASE(dev->BASE, IC_STD_SCL_HCNT) = I2C_STD_HCNT; + /* Set LCNT */ + MMIO_REG_VAL_FROM_BASE(dev->BASE, IC_STD_SCL_LCNT) = I2C_STD_LCNT; + } else if (I2C_FAST == dev->speed) { + /* Set HCNT */ + MMIO_REG_VAL_FROM_BASE(dev->BASE, IC_FS_SCL_HCNT) = I2C_FS_HCNT; + /* Set LCNT */ + MMIO_REG_VAL_FROM_BASE(dev->BASE, IC_FS_SCL_LCNT) = I2C_FS_LCNT; + } else if (I2C_HS == dev->speed) { + /* Set HCNT */ + MMIO_REG_VAL_FROM_BASE(dev->BASE, IC_HS_SCL_HCNT) = I2C_HS_HCNT; + /* Set LCNT */ + MMIO_REG_VAL_FROM_BASE(dev->BASE, IC_HS_SCL_LCNT) = I2C_HS_LCNT; + } else { + rc = DRV_RC_FAIL; + } + + /* Set RX fifo threshold level */ + MMIO_REG_VAL_FROM_BASE(dev->BASE, IC_RX_TL) = dev->rx_watermark; + /* Set TX fifo threshold level */ + MMIO_REG_VAL_FROM_BASE(dev->BASE, IC_TX_TL) = dev->tx_watermark; + + dev->tx_len = dev->total_write_bytes = 0; + dev->rx_len = dev->total_read_bytes = 0; + + if (dev->mode == I2C_SLAVE) { + /* Set slave address */ + MMIO_REG_VAL_FROM_BASE(dev->BASE, IC_SAR) = dev->slave_addr; + + /* Disable interrupts */ + MMIO_REG_VAL_FROM_BASE(dev->BASE, IC_INTR_MASK) = + SOC_DISABLE_ALL_I2C_INT; + + /* Clear interrupts */ + MMIO_REG_VAL_FROM_BASE(dev->BASE, IC_CLR_INTR); + + soc_i2c_enable_device(dev, true); + + /* Enable necesary interrupts */ + MMIO_REG_VAL_FROM_BASE(dev->BASE, IC_INTR_MASK) = + SOC_ENABLE_INT_I2C_SLAVE; + + soc_i2c_enable_device(dev, true); + } + + return rc; +} + +DRIVER_API_RC soc_i2c_set_config(SOC_I2C_CONTROLLER controller_id, + i2c_cfg_data_t *config) +{ + i2c_internal_data_t *dev; + + /* set current base based on config */ + if (controller_id == SOC_I2C_0) { + dev = &devices[0]; + dev->ISR = &isr_dev_0; + dev->BASE = SOC_I2C_0_BASE; + dev->clk_gate_info.clk_gate_register = PERIPH_CLK_GATE_CTRL; + dev->clk_gate_info.bits_mask = I2C0_CLK_GATE_MASK; + } else if (controller_id == SOC_I2C_1) { + dev = &devices[1]; + dev->ISR = &isr_dev_1; + dev->BASE = SOC_I2C_1_BASE; + dev->clk_gate_info.clk_gate_register = PERIPH_CLK_GATE_CTRL; + dev->clk_gate_info.bits_mask = I2C1_CLK_GATE_MASK; + } else { + return DRV_RC_FAIL; + } + + /* Copy passed in config data locally */ + dev->speed = config->speed; + dev->addr_mode = config->addressing_mode; + dev->mode = config->mode_type; + dev->slave_addr = config->slave_adr; + dev->rx_cb = config->cb_rx; + dev->cb_rx_data = config->cb_rx_data; + dev->tx_cb = config->cb_tx; + dev->cb_tx_data = config->cb_tx_data; + dev->err_cb = config->cb_err; + dev->cb_err_data = config->cb_err_data; + + /* Clear interrupts */ + MMIO_REG_VAL_FROM_BASE(dev->BASE, IC_CLR_INTR); + + if (controller_id == SOC_I2C_0) { + SET_INTERRUPT_HANDLER(SOC_I2C0_INTERRUPT, dev->ISR); + /* Unmask interrupts */ + SOC_UNMASK_INTERRUPTS(INT_I2C_0_MASK); + } else { + SET_INTERRUPT_HANDLER(SOC_I2C1_INTERRUPT, dev->ISR); + /* Unmask interrupts */ + SOC_UNMASK_INTERRUPTS(INT_I2C_1_MASK); + } + + if (I2C_SLAVE == dev->mode) { + /* Set reset values (moved from reset dev - was called only once) */ + dev->rx_watermark = 0; // TODO test different watermark levels + dev->tx_watermark = 0; + dev->fifo_depth = 1; + } else { + /* Set reset values (moved from reset dev - was called only once) */ + dev->rx_watermark = 0; // TODO test different watermark levels + dev->tx_watermark = 0; + dev->fifo_depth = 16; + } + + return DRV_RC_OK; +} + +DRIVER_API_RC soc_i2c_get_config(SOC_I2C_CONTROLLER controller_id, + i2c_cfg_data_t *config) +{ + /* TODO implement */ + controller_id = controller_id; + config = config; + return DRV_RC_FAIL; +} + +DRIVER_API_RC soc_i2c_deconfig(SOC_I2C_CONTROLLER controller_id) +{ + i2c_internal_data_t *dev = NULL; + DRIVER_API_RC rc = DRV_RC_OK; + + /* Controller we are using */ + if (controller_id == SOC_I2C_0) { + dev = &devices[0]; + } else if (controller_id == SOC_I2C_1) { + dev = &devices[1]; + } else { + return DRV_RC_FAIL; + } + + if (!dev->send_stop) { + soc_i2c_abort_transfer(dev); + } + + soc_i2c_enable_device(dev, false); + + /* Disable interrupts */ + MMIO_REG_VAL_FROM_BASE(dev->BASE, IC_INTR_MASK) = SOC_DISABLE_ALL_I2C_INT; + + /* Clear interrupts */ + MMIO_REG_VAL_FROM_BASE(dev->BASE, IC_CLR_INTR); + + return rc; +} + +DRIVER_API_RC soc_i2c_clock_enable(SOC_I2C_CONTROLLER controller_id) +{ + i2c_internal_data_t *dev = NULL; + + if (controller_id == SOC_I2C_0) { + dev = &devices[0]; + } else if (controller_id == SOC_I2C_1) { + dev = &devices[1]; + } else { + return DRV_RC_FAIL; + } + + set_clock_gate(&dev->clk_gate_info, CLK_GATE_ON); + + soc_i2c_init(dev); + + return DRV_RC_OK; +} + +DRIVER_API_RC soc_i2c_clock_disable(SOC_I2C_CONTROLLER controller_id) +{ + i2c_internal_data_t *dev = NULL; + + if (controller_id == SOC_I2C_0) { + dev = &devices[0]; + } else if (controller_id == SOC_I2C_1) { + dev = &devices[1]; + } else { + return DRV_RC_FAIL; + } + + set_clock_gate(&dev->clk_gate_info, CLK_GATE_OFF); + + return DRV_RC_OK; +} + +DRIVER_API_RC soc_i2c_set_transfer_speed(SOC_I2C_CONTROLLER controller_id, + uint32_t speed) +{ + volatile uint32_t ic_con = 0; + i2c_internal_data_t *dev = NULL; + + if (controller_id == SOC_I2C_0) { + dev = &devices[0]; + } else if (controller_id == SOC_I2C_1) { + dev = &devices[1]; + } else { + return DRV_RC_FAIL; + } + + dev->speed = speed; + + soc_i2c_enable_device(dev, false); + + /* Setup IC_CON */ + ic_con = MMIO_REG_VAL_FROM_BASE(dev->BASE, IC_CON); + + ic_con |= (dev->speed << 1); + + MMIO_REG_VAL_FROM_BASE(dev->BASE, IC_CON) = ic_con; + + if (I2C_SLOW == + dev->speed) /* This is setter so prefering readability above speed */ + { + /* Set HCNT */ + MMIO_REG_VAL_FROM_BASE(dev->BASE, IC_STD_SCL_HCNT) = I2C_STD_HCNT; + /* Set LCNT */ + MMIO_REG_VAL_FROM_BASE(dev->BASE, IC_STD_SCL_LCNT) = I2C_STD_LCNT; + } else if (I2C_FAST == dev->speed) { + /* Set HCNT */ + MMIO_REG_VAL_FROM_BASE(dev->BASE, IC_FS_SCL_HCNT) = I2C_FS_HCNT; + /* Set LCNT */ + MMIO_REG_VAL_FROM_BASE(dev->BASE, IC_FS_SCL_LCNT) = I2C_FS_LCNT; + } else if (I2C_HS == dev->speed) { + /* Set HCNT */ + MMIO_REG_VAL_FROM_BASE(dev->BASE, IC_HS_SCL_HCNT) = I2C_HS_HCNT; + /* Set LCNT */ + MMIO_REG_VAL_FROM_BASE(dev->BASE, IC_HS_SCL_LCNT) = I2C_HS_LCNT; + } else { + return DRV_RC_FAIL; + } + + return DRV_RC_OK; +} + +DRIVER_API_RC soc_i2c_set_transfer_mode(SOC_I2C_CONTROLLER controller_id, + uint32_t mode) +{ + i2c_internal_data_t *dev = NULL; + + if (controller_id == SOC_I2C_0) { + dev = &devices[0]; + } else if (controller_id == SOC_I2C_1) { + dev = &devices[1]; + } else { + return DRV_RC_FAIL; + } + + dev->addr_mode = mode; + + if (dev->mode == I2C_SLAVE) { + volatile uint32_t ic_con = 0; + + soc_i2c_enable_device(dev, false); + + /* Setup IC_CON */ + ic_con = MMIO_REG_VAL_FROM_BASE(dev->BASE, IC_CON); + + if (I2C_10_Bit == dev->addr_mode) { + ic_con |= IC_SLAVE_ADDR_MODE_BIT; + } else { + ic_con &= ~IC_SLAVE_ADDR_MODE_BIT; + } + + MMIO_REG_VAL_FROM_BASE(dev->BASE, IC_CON) = ic_con; + + soc_i2c_enable_device(dev, true); + } + + return DRV_RC_OK; +} + +DRIVER_API_RC soc_i2c_slave_enable_tx(SOC_I2C_CONTROLLER controller_id, + uint8_t *data_write, + uint32_t data_write_len) +{ + i2c_internal_data_t *dev = NULL; + + /* Controller we are using */ + if (controller_id == SOC_I2C_0) { + dev = &devices[0]; + } else if (controller_id == SOC_I2C_1) { + dev = &devices[1]; + } else { + return DRV_RC_FAIL; + } + + dev->tx_len = data_write_len; + dev->rx_tx_len = data_write_len; + dev->i2c_write_buff = data_write; + dev->total_write_bytes = 0; + + return DRV_RC_OK; +} + +DRIVER_API_RC soc_i2c_slave_enable_rx(SOC_I2C_CONTROLLER controller_id, + uint8_t *data_read, + uint32_t data_read_len) +{ + i2c_internal_data_t *dev = NULL; + + /* Controller we are using */ + if (controller_id == SOC_I2C_0) { + dev = &devices[0]; + } else if (controller_id == SOC_I2C_1) { + dev = &devices[1]; + } else { + return DRV_RC_FAIL; + } + + dev->rx_len = data_read_len; + dev->rx_tx_len = data_read_len; + dev->i2c_read_buff = data_read; + dev->total_read_bytes = 0; + + return DRV_RC_OK; +} + +DRIVER_API_RC soc_i2c_master_write(SOC_I2C_CONTROLLER controller_id, + uint8_t *data, uint32_t data_len, + uint32_t slave_addr, bool no_stop) +{ + return soc_i2c_master_transfer(controller_id, data, data_len, 0, 0, + slave_addr, no_stop); +} + +DRIVER_API_RC soc_i2c_master_read(SOC_I2C_CONTROLLER controller_id, + uint8_t *data, uint32_t data_len, + uint32_t slave_addr, bool no_stop) +{ + return soc_i2c_master_transfer(controller_id, 0, 0, data, data_len, + slave_addr, no_stop); +} + +DRIVER_API_RC soc_i2c_master_transfer(SOC_I2C_CONTROLLER controller_id, + uint8_t *data_write, + uint32_t data_write_len, + uint8_t *data_read, + uint32_t data_read_len, + uint32_t slave_addr, bool no_stop) +{ + bool need_init = true; + i2c_internal_data_t *dev = NULL; + + /* Controller we are using */ + if (controller_id == SOC_I2C_0) { + dev = &devices[0]; + } else if (controller_id == SOC_I2C_1) { + dev = &devices[1]; + } else { + return DRV_RC_FAIL; + } + + /* Check for activity */ + if (I2C_OK != soc_i2c_status(controller_id, !dev->send_stop)) { + return DRV_RC_FAIL; + } + + if ((data_read_len == 0) && (data_write_len == 0)) { + // Workaround: we know that we are doing I2C bus scan. + data_read_len = 1; + dev->send_restart = true; + } + + if (data_read_len > 0) { + dev->state = I2C_CMD_RECV; + } else { + dev->state = I2C_CMD_SEND; + } + dev->rx_len = data_read_len; + dev->tx_len = data_write_len; + dev->rx_tx_len = data_read_len + data_write_len; + dev->i2c_write_buff = data_write; + dev->i2c_read_buff = data_read; + dev->total_read_bytes = 0; + dev->total_write_bytes = 0; + + if (dev->slave_addr != slave_addr) { + dev->send_restart = true; + } + + dev->slave_addr = slave_addr; + + need_init = dev->send_stop || dev->send_restart; + + if (!no_stop) { + dev->send_stop = true; + } else { + dev->send_stop = false; + } + + if (need_init) { + soc_i2c_master_init_transfer(dev); + } else { + /* Enable necesary interrupts */ + MMIO_REG_VAL_FROM_BASE(dev->BASE, IC_INTR_MASK) = + SOC_ENABLE_RX_TX_INT_I2C; + } + + return DRV_RC_OK; +} + +DRIVER_I2C_STATUS_CODE soc_i2c_status(SOC_I2C_CONTROLLER controller_id, + bool no_stop) +{ + uint32_t status = 0; + DRIVER_I2C_STATUS_CODE rc = I2C_OK; + i2c_internal_data_t *dev = NULL; + + if (controller_id == SOC_I2C_0) { + dev = &devices[0]; + } else if (controller_id == SOC_I2C_1) { + dev = &devices[1]; + } else { + return DRV_RC_FAIL; + } + + status = MMIO_REG_VAL_FROM_BASE(dev->BASE, IC_STATUS); + if (((!no_stop) && (status & IC_STATUS_ACTIVITY)) || + (status & IC_STATUS_RFNE) || !(status & IC_STATUS_TFE)) { + rc = I2C_BUSY; + } else { + uint32_t int_status = MMIO_REG_VAL_FROM_BASE(dev->BASE, IC_INTR_STAT); + if (int_status & IC_INTR_TX_ABRT) { + rc = I2C_TX_ABORT; + } + if (int_status & IC_INTR_TX_OVER) { + rc = I2C_TX_OVER; + } + if (int_status & IC_INTR_RX_OVER) { + rc = I2C_RX_OVER; + } + if (int_status & IC_INTR_RX_UNDER) { + rc = I2C_RX_UNDER; + } + } + + return rc; +} diff --git a/system/libarc32_arduino101/drivers/intel_qrk_i2c.h b/system/libarc32_arduino101/drivers/intel_qrk_i2c.h new file mode 100644 index 00000000..8b55339f --- /dev/null +++ b/system/libarc32_arduino101/drivers/intel_qrk_i2c.h @@ -0,0 +1,284 @@ +/* + * Copyright (c) 2015, Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef QRK_SOC_I2C_H_ +#define QRK_SOC_I2C_H_ + +#include "common_i2c.h" +#include "data_type.h" +#include "platform.h" +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup common_drivers Common Drivers + * Definition of the drivers APIs accessible from any processor. + * @ingroup drivers + */ + +/** + * @defgroup soc_i2c Atlaspeak SOC I2C + * Atlaspeak SOC Inter-Integrated Circuit drivers API. + * @ingroup common_drivers + * @{ + */ + +#define SOC_I2C_CONTROLLER int + +typedef enum { + SLAVE_WRITE = 0, /*!< SLAVE WRITE MODE */ + SLAVE_READ, /*!< SLAVE READ MODE */ +} SOC_I2C_SLAVE_MODE; + +/** + * Configure the specified I2C controller. + * + * Configuration parameters must be valid or an error is returned - see return values below. + * + * @param controller_id I2C controller identifier + * @param config Pointer to configuration structure + * + * @return + * - DRV_RC_OK on success + * - DRV_RC_DEVICE_TYPE_NOT_SUPPORTED - if device type is not supported by this controller + * - DRV_RC_INVALID_CONFIG - if any configuration parameters are not valid + * - DRV_RC_CONTROLLER_IN_USE, - if controller is in use + * - DRV_RC_CONTROLLER_NOT_ACCESSIBLE - if controller is not accessible from this core + * - DRV_RC_FAIL otherwise + */ +DRIVER_API_RC soc_i2c_set_config(SOC_I2C_CONTROLLER controller_id, + i2c_cfg_data_t * config); + + +/** + * Retrieve configuration of the specified I2C controller + * + * @param controller_id I2C controller identifier + * @param config Pointer to configuration structure to store current setup + * + * @return + * - DRV_RC_OK on success + * - DRV_RC_FAIL otherwise + */ +DRIVER_API_RC soc_i2c_get_config(SOC_I2C_CONTROLLER controller_id, + i2c_cfg_data_t * config); + + +/** + * Place the I2C controller into a disabled and default state (as if hardware reset occurred). + * + * This function assumes that there is no pending transaction on the I2C interface in question. + * It is the responsibility of the calling application to do so. + * Upon success, the specified controller configuration is reset to default. + * + * @param controller_id I2C controller identifier + * + * @return + * - DRV_RC_OK on success + * - DRV_RC_FAIL otherwise + */ +DRIVER_API_RC soc_i2c_deconfig(SOC_I2C_CONTROLLER controller_id); + + +/** + * Enable the clock for the specified I2C controller. + * + * Upon success, the specified I2C interface is no longer clock gated in hardware, it is now + * capable of transmitting and receiving on the I2C bus, and generating interrupts. + * + * @param sba_dev Pointer to bus configuration data + * + * @return + * - DRV_RC_OK on success + * - DRV_RC_FAIL otherwise + */ +DRIVER_API_RC soc_i2c_clock_enable(SOC_I2C_CONTROLLER controller_id); + + +/** + * Disable the clock for the specified I2C controller. + * + * This function assumes that there is no pending transaction on the I2C interface in question. + * It is the responsibility of the calling application to do so. + * Upon success, the specified I2C interface is clock gated in hardware, + * it is no longer capable of generating interrupts. + * + * @param sba_dev Pointer to bus configuration data + * + * @return + * - DRV_RC_OK on success + * - DRV_RC_FAIL otherwise + */ +DRIVER_API_RC soc_i2c_clock_disable(SOC_I2C_CONTROLLER controller_id); + + +/** + * Send a block of data to the specified I2C slave. + * + * @param controller_id I2C controller identifier + * @param data Pointer to data to write + * @param data_len Length of data to write + * @param slave_addr I2C address of the slave to write data to + * + * @return + * - DRV_RC_OK on success + * - DRV_RC_FAIL otherwise + */ +DRIVER_API_RC soc_i2c_master_write(SOC_I2C_CONTROLLER controller_id, + uint8_t *data, uint32_t data_len, + uint32_t slave_addr, bool no_stop); + +/** + * Receive a block of data from the specified I2C slave. + * + * If set as a master, this will receive 'data_len' bytes transmitted from slave. + * If set as a slave, this will receive any data sent by a master addressed to the I2C address as + * configured in the "slave_adr" for this controller configuration, in which case 'data_len' + * indicates the amount of data received and 'data' holds the data. + * + * @param controller_id I2C controller identifier + * @param data Pointer where to store read data + * @param data_len Length of data to read + * @param slave_addr I2C address of the slave + * + * @return + * - DRV_RC_OK on success + * - DRV_RC_FAIL otherwise + */ +DRIVER_API_RC soc_i2c_master_read(SOC_I2C_CONTROLLER controller_id, + uint8_t *data, uint32_t data_len, + uint32_t slave_addr, bool no_stop); + +/** + * Send and receive a block of data to the specified I2C slave + * with repeated start + * + * @param controller_id I2C controller identifier + * @param data_write Pointer to data to write + * @param data_write_len Length of data to write + * @param data_read Pointer where to store read data + * @param data_read_len Length of data to read + * @param slave_addr I2C address of the slave + * + * @return + * - DRV_RC_OK on success + * - DRV_RC_FAIL otherwise + */ +DRIVER_API_RC soc_i2c_master_transfer(SOC_I2C_CONTROLLER controller_id, + uint8_t *data_write, uint32_t data_write_len, + uint8_t *data_read, uint32_t data_read_len, + uint32_t slave_addr, bool no_stop); + +/** +* Function to determine controllers current state +* +* @param controller_id : I2C controller identifier +* +* @return +* - I2C_OK - controller ready +* - I2C_BUSY - controller busy +*/ +DRIVER_I2C_STATUS_CODE soc_i2c_status(SOC_I2C_CONTROLLER controller_id, bool stop); + +/** +* Function to set I2C slave device receive buffer +* +* @param controller_id : I2C controller_id identifier +* @param data_read : pointer to data to read +* @param data_read_len : length of data to read +* +* @return +* - DRV_RC_OK on success +* - DRV_RC_FAIL otherwise +*/ +DRIVER_API_RC soc_i2c_slave_enable_rx(SOC_I2C_CONTROLLER controller_id, + uint8_t *data_read, + uint32_t data_read_len); + +/** +* Function to set I2C slave device transmit buffer +* +* @param controller_id : I2C controller_id identifier +* @param data_write : pointer to data to write +* @param data_write_len : length of data to write +* +* @return +* - DRV_RC_OK on success +* - DRV_RC_FAIL otherwise +*/ +DRIVER_API_RC soc_i2c_slave_enable_tx(SOC_I2C_CONTROLLER controller_id, + uint8_t *data_write, + uint32_t data_write_len); + +/** +* Function to set I2C address mode +* +* @param controller_id : I2C controller_id identifier +* @param speed : I2C speed +* +* @return +* - DRV_RC_OK on success +* - DRV_RC_FAIL otherwise +*/ +DRIVER_API_RC soc_i2c_set_transfer_speed(SOC_I2C_CONTROLLER controller_id, + uint32_t speed); +/** +* Function to set I2C address mode +* +* @param controller_id : I2C controller_id identifier +* @param mode : address mode +* +* @return +* - DRV_RC_OK on success +* - DRV_RC_FAIL otherwise +*/ +DRIVER_API_RC soc_i2c_set_transfer_mode(SOC_I2C_CONTROLLER controller_id, + uint32_t mode); +/** +* Function to set I2C address mode +* +* @param controller_id : I2C controller_id identifier +* @param mode : address mode +* +* @return +* - DRV_RC_OK on success +* - DRV_RC_FAIL otherwise +*/ +DRIVER_API_RC soc_i2c_set_transfer_mode(SOC_I2C_CONTROLLER controller_id, + uint32_t mode); +/** @} */ + +#ifdef __cplusplus +} +#endif +#endif diff --git a/system/libarc32_arduino101/drivers/ipc_uart_ns16550.c b/system/libarc32_arduino101/drivers/ipc_uart_ns16550.c index a497b6cf..b2f6c08f 100644 --- a/system/libarc32_arduino101/drivers/ipc_uart_ns16550.c +++ b/system/libarc32_arduino101/drivers/ipc_uart_ns16550.c @@ -49,14 +49,38 @@ #define IPC_UART_HDR_REQUEST_LEN (IPC_HEADER_LEN+sizeof(uint32_t)) /* ipc header + request len */ -struct ipc_uart_channels channels[IPC_UART_MAX_CHANNEL] = { {0, 0, NULL},}; -static uint16_t send_counter = 0; -static uint16_t received_counter = 0; -static uint8_t * ipc_uart_tx = NULL; -static uint8_t * ipc_uart_rx = NULL; -static uint8_t ipc_uart_tx_state = 0; +enum { + STATUS_TX_IDLE = 0, + STATUS_TX_BUSY, + STATUS_TX_DONE, +}; + +enum { + STATUS_RX_IDLE = 0, + STATUS_RX_HDR, + STATUS_RX_DATA +}; + +struct ipc_uart { + uint8_t *tx_data; + uint8_t *rx_ptr; + struct ipc_uart_channels channels[IPC_UART_MAX_CHANNEL]; + struct ipc_uart_header tx_hdr; + struct ipc_uart_header rx_hdr; + uint16_t send_counter; + uint16_t rx_size; + uint8_t tx_state; + uint8_t rx_state; + uint8_t uart_enabled; + /* protect against multiple wakelock and wake assert calls */ + uint8_t tx_wakelock_acquired; + /* TODO: remove once IRQ will take a parameter */ + //struct td_device *device; + void (*tx_cb)(bool wake_state, void *); /*!< Callback to be called to set wake state when TX is starting or ending */ + void *tx_cb_param; /*!< tx_cb function parameter */ +}; -static void * ble_cfw_channel; +static struct ipc_uart ipc = {}; static const struct uart_init_info uart_dev_info[] = { { @@ -79,187 +103,246 @@ static const struct uart_init_info uart_dev_info[] = { }, }; -void uart_ipc_close_channel(int channel_id) +void ipc_uart_close_channel(int channel_id) { - channels[channel_id].state = IPC_CHANNEL_STATE_CLOSED; - channels[channel_id].cb = NULL; - channels[channel_id].index = channel_id; + ipc.channels[channel_id].state = IPC_CHANNEL_STATE_CLOSED; + ipc.channels[channel_id].cb = NULL; + ipc.channels[channel_id].index = channel_id; + + ipc.uart_enabled = 0; + ipc.tx_wakelock_acquired = 0; } -void uart_ipc_disable(int num) +void ipc_uart_ns16550_disable(int num) { int i; for (i = 0; i < IPC_UART_MAX_CHANNEL; i++) - uart_ipc_close_channel(i); + ipc_uart_close_channel(i); + if (ipc.tx_cb) + ipc.tx_cb(0, ipc.tx_cb_param); + UART_IRQ_TX_DISABLE(num); UART_IRQ_RX_DISABLE(num); } -void uart_ipc_init(int num) +void ipc_uart_init(int num) { int i; (void)num; - uint8_t c; for (i = 0; i < IPC_UART_MAX_CHANNEL; i++) - uart_ipc_close_channel(i); + ipc_uart_close_channel(i); - pr_info(LOG_MODULE_IPC, "uart_ipc_init(nr: %d), baudrate %d, options:" - "0x%x, irq: %d",IPC_UART, + pr_info(LOG_MODULE_IPC, "%s(nr: %d), baudrate %d, options:" + "0x%x, irq: %d",__FUNCTION__, IPC_UART, uart_dev_info[IPC_UART].baud_rate, uart_dev_info[IPC_UART].options, uart_dev_info[IPC_UART].irq); uart_init(IPC_UART, &uart_dev_info[IPC_UART]); - /* Drain RX FIFOs (no need to disable IRQ at this stage) */ - while (uart_poll_in(IPC_UART, &c) != -1); - uart_int_connect(IPC_UART, uart_ipc_isr, NULL, NULL); - - UART_IRQ_RX_ENABLE(IPC_UART); + + ipc.uart_enabled = 0; + ipc.tx_wakelock_acquired = 0; + + /* Initialize the reception pointer */ + ipc.rx_size = sizeof(ipc.rx_hdr); + ipc.rx_ptr = (uint8_t *)&ipc.rx_hdr; + ipc.rx_state = STATUS_RX_IDLE; } -void uart_ipc_set_channel(void * ipc_channel) +static void ipc_uart_push_frame(uint16_t len, uint8_t *p_data) { - ble_cfw_channel = ipc_channel; -} - -void * uart_ipc_get_channel(void) -{ - return ble_cfw_channel; -} - -void uart_ipc_push_frame(void) { - void * frame; - OS_ERR_TYPE error = E_OS_OK; - - if (NULL == ipc_uart_rx) - return; - int len = IPC_FRAME_GET_LEN(ipc_uart_rx); - int channel = IPC_FRAME_GET_CHANNEL(ipc_uart_rx); - uint8_t cpu_id = IPC_FRAME_GET_SRC(ipc_uart_rx); - - pr_debug(LOG_MODULE_IPC, "%s: received frame: len %d, channel %d, src " - "%d", __func__, len, channel, cpu_id); - - if (channels[channel].cb != NULL) { - frame = balloc(len, &error); - if (error != E_OS_OK) { - pr_error(LOG_MODULE_IPC, "NO MEM: error: %d size: %d", - error, len); - } else { - memcpy(frame, &ipc_uart_rx[IPC_HEADER_LEN], len); - - channels[channel].cb(cpu_id, channel, len, frame); - } + //pr_debug(LOG_MODULE_IPC, "push_frame: received:frame len: %d, p_data: " + // "len %d, src %d, channel %d", ipc.rx_hdr.len, len, + // ipc.rx_hdr.src_cpu_id, + // ipc.rx_hdr.channel); + pr_debug(LOG_MODULE_IPC,"data[0 - 1]: %x-%x", p_data[0], p_data[1]); + + if ((ipc.rx_hdr.channel < IPC_UART_MAX_CHANNEL) && + (ipc.channels[ipc.rx_hdr.channel].cb != NULL)) { + ipc.channels[ipc.rx_hdr.channel].cb(ipc.rx_hdr.channel, + IPC_MSG_TYPE_MESSAGE, + len, + p_data); + } else { + bfree(p_data); + pr_error(LOG_MODULE_IPC, "uart_ipc: bad channel %d", + ipc.rx_hdr.channel); } - if (ipc_uart_rx) - bfree(ipc_uart_rx); - ipc_uart_rx = NULL; } -void uart_ipc_isr() +void ipc_uart_isr() { - uint8_t *p_rx; + /* TODO: remove once IRQ supports parameter */ uint8_t *p_tx; - while (UART_IRQ_HW_UPDATE(IPC_UART) && UART_IRQ_IS_PENDING(IPC_UART)) { - if (UART_IRQ_ERR_DETECTED(IPC_UART)) { + while (UART_IRQ_HW_UPDATE(IPC_UART) && + UART_IRQ_IS_PENDING(IPC_UART)) { + if (UART_IRQ_ERR_DETECTED(IPC_UART)) + { uint8_t c; - if (UART_BREAK_CHECK(IPC_UART)){ - panic(); + if (UART_BREAK_CHECK(IPC_UART)) { + panic(-1); } UART_POLL_IN(IPC_UART, &c); - } else if (UART_IRQ_RX_READY(IPC_UART)) { - int received; - if (received_counter < 2) { - if (NULL == ipc_uart_rx) - ipc_uart_rx = - balloc(IPC_UART_MAX_PAYLOAD, NULL); - p_rx = ipc_uart_rx; - received = UART_FIFO_READ(IPC_UART, - &p_rx[received_counter], - 1); - received_counter += received; - } else { - p_rx = ipc_uart_rx; - received = UART_FIFO_READ(IPC_UART, - &p_rx[received_counter], - IPC_FRAME_GET_LEN(p_rx) + - IPC_HEADER_LEN - - received_counter); - received_counter += received; - if (received_counter == IPC_FRAME_GET_LEN(p_rx) - + IPC_HEADER_LEN) { + } + if (UART_IRQ_RX_READY(IPC_UART)) { + int rx_cnt; + + while ((rx_cnt = + UART_FIFO_READ(IPC_UART, + ipc.rx_ptr, + ipc.rx_size)) != 0) + { + if ((ipc.uart_enabled) && + (ipc.rx_state == STATUS_RX_IDLE)) { + /* acquire wakelock until frame is fully received */ + //pm_wakelock_acquire(&info->rx_wl); + ipc.rx_state = STATUS_RX_HDR; + } + + /* Until UART has enabled at least one channel, data should be discarded */ + if (ipc.uart_enabled) { + ipc.rx_size -= rx_cnt; + ipc.rx_ptr += rx_cnt; + } + + if (ipc.rx_size == 0) { + if (ipc.rx_state == STATUS_RX_HDR) { + pr_error(0, "%s-%d", __FUNCTION__, ipc.rx_hdr.len); + ipc.rx_ptr = balloc( + ipc.rx_hdr.len, NULL); + + //pr_debug( + // LOG_MODULE_IPC, + // "ipc_uart_isr: rx_ptr is %p", + // ipc.rx_ptr); + ipc.rx_size = ipc.rx_hdr.len; + ipc.rx_state = STATUS_RX_DATA; + } else { #ifdef IPC_UART_DBG_RX - for(int i = 0; i < received_counter; i++) { - pr_debug(LOG_MODULE_IPC, "%s: %d byte is %d", __func__, i, p_rx[i]); - } + uint8_t *p_rx = ipc.rx_ptr - + ipc.rx_hdr.len; + for (int i = 0; + i < ipc.rx_hdr.len; + i++) { + pr_debug( + LOG_MODULE_IPC, + "ipc_uart_isr: %d byte is %d", + i, p_rx[i]); + } #endif - received_counter = 0; - uart_ipc_push_frame(); + + ipc_uart_push_frame( + ipc.rx_hdr.len, + ipc.rx_ptr - + ipc.rx_hdr.len); + ipc.rx_size = sizeof(ipc.rx_hdr); + ipc.rx_ptr = + (uint8_t *)&ipc.rx_hdr; + ipc.rx_state = STATUS_RX_IDLE; + } } } - } else if (UART_IRQ_TX_READY(IPC_UART)) { - int transmitted; - if (ipc_uart_tx_state == STATUS_TX_IDLE) { + } + if (UART_IRQ_TX_READY(IPC_UART)) { + int tx_len; + + if (ipc.tx_state == STATUS_TX_DONE) { uint8_t lsr = UART_LINE_STATUS(IPC_UART); + ipc.tx_state = STATUS_TX_IDLE; UART_IRQ_TX_DISABLE(IPC_UART); - - pr_debug(LOG_MODULE_IPC, "ipc_isr_tx: disable TXint, LSR: 0x%2x\n", - lsr); + /* wait for FIFO AND THR being empty! */ while ((lsr & BOTH_EMPTY) != BOTH_EMPTY) { lsr = UART_LINE_STATUS(IPC_UART); } + + /* No more TX activity, send event and release wakelock */ + if (ipc.tx_cb) { + ipc.tx_cb(0, ipc.tx_cb_param); + } + //pm_wakelock_release(&info->tx_wl); + ipc.tx_wakelock_acquired = 0; return; } - if(NULL == ipc_uart_tx){ - pr_warning(LOG_MODULE_IPC, "%s: Bad Tx data",__func__); + if (NULL == ipc.tx_data) { + pr_warning(LOG_MODULE_IPC, + "ipc_uart_isr: Bad Tx data"); return; } - p_tx = ipc_uart_tx; - transmitted = UART_FIFO_FILL(IPC_UART, &p_tx[send_counter], - IPC_FRAME_GET_LEN(p_tx) + - IPC_HEADER_LEN - send_counter); - send_counter += transmitted; - if (send_counter == IPC_FRAME_GET_LEN(p_tx) + - IPC_HEADER_LEN) { - send_counter = 0; -#ifdef IPC_UART_DBG_TX - pr_debug(LOG_MODULE_IPC, "%s: sent IPC FRAME " - "len %d", __func__, - IPC_FRAME_GET_LEN(p_tx)); - for (int i = 0; i < send_counter; i++) { - pr_debug(LOG_MODULE_IPC, "%s: %d sent " - "byte is %d", - __func__, i, p_tx[i]); + + if (!ipc.tx_wakelock_acquired) { + ipc.tx_wakelock_acquired = 1; + /* Starting TX activity, send wake assert event and acquire wakelock */ + if (ipc.tx_cb) { + ipc.tx_cb(1, ipc.tx_cb_param); } + //pm_wakelock_acquire(&info->tx_wl); + } + if (ipc.send_counter < sizeof(ipc.tx_hdr)) { + p_tx = (uint8_t *)&ipc.tx_hdr + + ipc.send_counter; + tx_len = sizeof(ipc.tx_hdr) - ipc.send_counter; + } else { + p_tx = ipc.tx_data + + (ipc.send_counter - sizeof(ipc.tx_hdr)); + tx_len = ipc.tx_hdr.len - + (ipc.send_counter - sizeof(ipc.tx_hdr)); + } + ipc.send_counter += UART_FIFO_FILL(IPC_UART, + p_tx, + tx_len); + + if (ipc.send_counter == + (ipc.tx_hdr.len + sizeof(ipc.tx_hdr))) { + ipc.send_counter = 0; +#ifdef IPC_UART_DBG_TX + pr_debug( + LOG_MODULE_IPC, + "ipc_uart_isr: sent IPC FRAME " + "len %d", ipc.tx_hdr.len); #endif - bfree(ipc_uart_tx); - ipc_uart_tx = NULL; - ipc_uart_tx_state = STATUS_TX_IDLE; + p_tx = ipc.tx_data; + ipc.tx_data = NULL; + ipc.tx_state = STATUS_TX_DONE; + + /* free sent message and pull send next frame one in the queue */ + if (ipc.channels[ipc.tx_hdr.channel].cb) + { + ipc.channels[ipc.tx_hdr.channel].cb( + ipc.tx_hdr.channel, + IPC_MSG_TYPE_FREE, + ipc.tx_hdr.len, + p_tx); + } + else + { + bfree(p_tx); + } + #ifdef IPC_UART_DBG_TX - uint8_t lsr = UART_LINE_STATUS(IPC_UART); - pr_info(LOG_MODULE_IPC, "ipc_isr_tx: tx_idle LSR: 0x%2x\n", - lsr); + uint8_t lsr = UART_LINE_STATUS(IPC_UART);//(info->uart_num); + pr_debug(LOG_MODULE_IPC, + "ipc_isr_tx: tx_idle LSR: 0x%2x\n", + lsr); #endif } - } else { - pr_warning(LOG_MODULE_IPC, "%s: Unknown ISR src", - __func__); } + } } -void *uart_ipc_channel_open(int channel_id, - void (*cb) (uint8_t, int, int, void *)) +void *ipc_uart_channel_open(int channel_id, + int (*cb)(int, int, int, void *)) { struct ipc_uart_channels *chan; + uint8_t c; - if (channel_id > IPC_UART_MAX_CHANNEL - 1) + if (channel_id > (IPC_UART_MAX_CHANNEL - 1)) return NULL; - chan = &channels[channel_id]; + chan = &ipc.channels[channel_id]; if (chan->state != IPC_CHANNEL_STATE_CLOSED) return NULL; @@ -267,74 +350,48 @@ void *uart_ipc_channel_open(int channel_id, chan->state = IPC_CHANNEL_STATE_OPEN; chan->cb = cb; + ipc.uart_enabled = 1; + ipc.tx_wakelock_acquired = 0; + + pr_debug(LOG_MODULE_IPC, "%s: open chan success", __FUNCTION__); + + /* Drain RX FIFOs (no need to disable IRQ at this stage) */ + while (uart_poll_in(IPC_UART, &c) != -1); + uart_int_connect(IPC_UART, ipc_uart_isr, NULL, NULL); + + UART_IRQ_RX_ENABLE(IPC_UART); + return chan; } -int uart_ipc_send_message(void *handle, int len, void *p_data) +int ipc_uart_ns16550_send_pdu(void *handle, int len, void *p_data) { - struct ipc_uart_channels *chan = (struct ipc_uart_channels *) handle; - - int flags = interrupt_lock(); - if (ipc_uart_tx_state == STATUS_TX_BUSY) { - interrupt_unlock(flags); - return IPC_UART_ERROR_WRONG_STATE; - } - ipc_uart_tx_state = STATUS_TX_BUSY; - interrupt_unlock(flags); - - uint8_t *p_tx = ipc_uart_tx = balloc(len + IPC_UART_HDR_REQUEST_LEN, - NULL); + struct ipc_uart_channels *chan = (struct ipc_uart_channels *)handle; - /* Adding size of the message request field*/ - int size = len + sizeof(uint32_t); + pr_debug(LOG_MODULE_IPC, "%s: %d", __FUNCTION__, ipc.tx_state); - /* length = cfw_message size + message request field*/ - IPC_FRAME_SET_LEN(p_tx, size); - IPC_FRAME_SET_CHANNEL(p_tx, chan->index); - IPC_FRAME_SET_SRC(p_tx, get_cpu_id()); - IPC_FRAME_SET_REQUEST(p_tx, IPC_MSG_TYPE_MESSAGE); - - /* IPC_HEADER + request_ID + cfw_message */ - /* copy cfw_message within IPC frame*/ - memcpy(IPC_FRAME_DATA(p_tx), p_data, len); + if (ipc.tx_state == STATUS_TX_BUSY) { + return IPC_UART_TX_BUSY; + } + + /* It is eventually possible to be in DONE state (sending last bytes of previous message), + * so we move immediately to BUSY and configure the next frame */ + ipc.tx_state = STATUS_TX_BUSY; - pr_debug(LOG_MODULE_IPC, "%s: tx: channel %d, len %d, request 0x%x", - __func__, p_tx[2], len, p_tx[4]); + ipc.tx_hdr.len = len; + ipc.tx_hdr.channel = chan->index; + ipc.tx_hdr.src_cpu_id = 0; + ipc.tx_data = p_data; + /* Enable the interrupt (ready will expire if it was disabled) */ UART_IRQ_TX_ENABLE(IPC_UART); return IPC_UART_ERROR_OK; } -int uart_ipc_send_sync_resp(int channel, int request_id, int param1, int param2, - void * ptr) +void ipc_uart_ns16550_set_tx_cb(void (*cb)(bool, void *), void *param) { - if (ipc_uart_tx_state == STATUS_TX_BUSY) - return IPC_UART_ERROR_WRONG_STATE; - ipc_uart_tx_state = STATUS_TX_BUSY; - - uint8_t *p_tx = ipc_uart_tx = balloc(IPC_UART_HDR_REQUEST_LEN + 12, - NULL); - - IPC_FRAME_SET_LEN(p_tx, 16); - IPC_FRAME_SET_CHANNEL(p_tx, channel); - IPC_FRAME_SET_SRC(ipc_uart_tx, get_cpu_id()); - - IPC_FRAME_SET_REQUEST(p_tx, request_id); - SYNC_FRAME_SET_PARAM1(p_tx, param1); - SYNC_FRAME_SET_PARAM2(p_tx, param2); - SYNC_FRAME_SET_PTR(p_tx, ptr); - -#ifdef IPC_UART_DBG_SYNC_RESP - for (int i = 0; i < 20; i++) { - pr_debug(LOG_MODULE_IPC, "%s: IPC sync resp %d byte : %d", - __func__,i, p_tx[i]); - } - pr_debug(LOG_MODULE_IPC, "%s: tx: channel %d, request %xh", __func__, - p_tx[2], p_tx[4]); -#endif - - UART_IRQ_TX_ENABLE(IPC_UART); - - return IPC_UART_ERROR_OK; + ipc.tx_cb = cb; + ipc.tx_cb_param = param; } + diff --git a/system/libarc32_arduino101/drivers/ipc_uart_ns16550.h b/system/libarc32_arduino101/drivers/ipc_uart_ns16550.h index 7fc04670..d71a61b9 100644 --- a/system/libarc32_arduino101/drivers/ipc_uart_ns16550.h +++ b/system/libarc32_arduino101/drivers/ipc_uart_ns16550.h @@ -33,19 +33,71 @@ #define IPC_UART 0 -enum { - STATUS_TX_IDLE = 0, - STATUS_TX_BUSY, -}; -enum { +/** IPC UART return codes */ +enum IPC_UART_RESULT_CODES { IPC_UART_ERROR_OK = 0, - IPC_UART_ERROR_WRONG_STATE, IPC_UART_ERROR_DATA_TO_BIG, + IPC_UART_TX_BUSY /**< A transmission is already ongoing, message is NOT sent */ +}; + + +/** + * Channel list + */ +enum ipc_channels { + RPC_CHANNEL=0, /**< RPC channel */ + IPC_UART_MAX_CHANNEL = 4 +}; + +/** + * Channel state + */ +enum ipc_channel_state { + IPC_CHANNEL_STATE_CLOSED = 0, + IPC_CHANNEL_STATE_OPEN +}; + +/** + * Definitions valid for NONE sync IPC UART headers + * |len|channel|cpu_id|request|payload| + * + * len = len(request)+len(payload) + */ + +/** + * @note this structure must be self-aligned and self-packed + */ +struct ipc_uart_header { + uint16_t len; /**< Length of IPC message, (request + payload) */ + uint8_t channel; /**< Channel number of IPC message. */ + uint8_t src_cpu_id; /**< CPU id of IPC sender. */ }; -void uart_ipc_isr(); -void uart_ipc_push_frame(void); -void uart_ipc_close_channel(int channel_id); +/** + * IPC channel description + */ +struct ipc_uart_channels { + uint16_t index; /**< Channel number */ + uint16_t state; /**< @ref ipc_channel_state */ + int (*cb)(int chan, int request, int len, void *data); + /**< Callback of the channel. + * @param chan Channel index used + * @param request Request id (defined in ipc_requests.h) + * @param len Payload size + * @param data Pointer to data + */ +}; + +void ipc_uart_init(int num); +void ipc_uart_isr(); +//static void ipc_uart_push_frame(uint16_t len, uint8_t *p_data); +void ipc_uart_ns16550_disable(int num); +void ipc_uart_close_channel(int channel_id); +void ipc_uart_ns16550_set_tx_cb(void (*cb)(bool, void *), void *param); +int ipc_uart_ns16550_send_pdu(void *handle, int len, void *p_data); +void *ipc_uart_channel_open(int channel_id, + int (*cb)(int, int, int, void *)); + #endif /* _IPC_UART_NS16550_H_ */ diff --git a/system/libarc32_arduino101/drivers/rpc/rpc.h b/system/libarc32_arduino101/drivers/rpc/rpc.h new file mode 100644 index 00000000..5d45d463 --- /dev/null +++ b/system/libarc32_arduino101/drivers/rpc/rpc.h @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2016 Intel Corporation + * + * 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 RPC_H_ +#define RPC_H_ + +#include + +/** Identifiers of the signature supported by the RPC */ +enum { + SIG_TYPE_NONE = 1, + SIG_TYPE_S, + SIG_TYPE_P, + SIG_TYPE_S_B, + SIG_TYPE_B_B_P, + SIG_TYPE_S_P, + SIG_TYPE_S_B_P, + SIG_TYPE_S_B_B_P +}; + +/** + * RPC memory allocation function, must be implemented by the user of the RPC. + * + * This function is called by the RPC mechanism to allocate a buffer for transmission + * of a serialized function. The function should not fail. + * + * @param length Length of the buffer to allocate + * + * @return Pointer to the allocated buffer, the allocation shall not fail, error must + * be handled internally + */ +uint8_t * rpc_alloc_cb(uint16_t length); + +/** + * RPC transmission function, must be implemented by the user of the RPC. + * + * @param p_buf Pointer to the buffer allocated for transmission by @ref rpc_alloc_cb + * @param length Length of the buffer to transmit + */ +void rpc_transmit_cb(uint8_t * p_buf, uint16_t length); + +/** + * RPC serialization function to serialize a function that does not require any parameter. + * + * @param fn_index Index of the function + */ +void rpc_serialize_none(uint8_t fn_index); + +/** + * RPC serialization function to serialize a function that expects a structure as parameter. + * + * @param fn_index Index of the function + * @param struct_data Pointer to the structure to serialize + * @param struct_length Length of the structure to serialize + */ +void rpc_serialize_s(uint8_t fn_index, const void * struct_data, uint8_t struct_length); + +/** + * RPC serialization function to serialize a function that expects a structure as parameter. + * + * @param fn_index Index of the function + * @param struct_data Pointer to the structure to serialize + * @param struct_length Length of the structure to serialize + * @param p_priv Pointer to serialize + */ +void rpc_serialize_s_p(uint8_t fn_index, const void * struct_data, uint8_t struct_length, void * p_priv); + +/** + * RPC serialization function to serialize a function that expects a pointer as parameter. + * + * @param fn_index Index of the function + * @param p_priv Pointer to serialize + */ +void rpc_serialize_p(uint8_t fn_index, void * p_priv); + +/** + * RPC serialization function to serialize a function that expects a structure + * and a buffer as parameters. + * + * @param fn_index Index of the function + * @param struct_data Pointer to the structure to serialize + * @param struct_length Length of the structure to serialize + * @param vbuf Pointer to the buffer to serialize + * @param vbuf_length Length of the buffer to serialize + */ +void rpc_serialize_s_b(uint8_t fn_index, const void * struct_data, uint8_t struct_length, const void * vbuf, uint16_t vbuf_length); + +/** + * RPC serialization function to serialize a function that expects a structure + * and a buffer as parameters. + * + * @param fn_index Index of the function + * @param vbuf1 Pointer to the buffer1 to serialize + * @param vbuf1_length Length of the buffer1 to serialize + * @param vbuf2 Pointer to the buffer2 to serialize + * @param vbuf2_length Length of the buffer2 to serialize + * @param p_priv Pointer to serialize + */ +void rpc_serialize_b_b_p(uint8_t fn_index, const void * vbuf1, uint16_t vbuf1_length, + const void * vbuf2, uint16_t vbuf2_length, void * p_priv); + +/** + * RPC serialization function to serialize a function that expects a structure + * and a buffer as parameters. + * + * @param fn_index Index of the function + * @param struct_data Pointer to the structure to serialize + * @param struct_length Length of the structure to serialize + * @param vbuf Pointer to the buffer to serialize + * @param vbuf_length Length of the buffer to serialize + * @param p_priv Pointer to serialize + */ +void rpc_serialize_s_b_p(uint8_t fn_index, const void * struct_data, uint8_t struct_length, + const void * vbuf, uint16_t vbuf_length, void * p_priv); + +/** + * RPC serialization function to serialize a function that expects a structure + * and a buffer as parameters. + * + * @param fn_index Index of the function + * @param struct_data Pointer to the structure to serialize + * @param struct_length Length of the structure to serialize + * @param vbuf1 Pointer to the buffer1 to serialize + * @param vbuf1_length Length of the buffer1 to serialize + * @param vbuf2 Pointer to the buffer2 to serialize + * @param vbuf2_length2 Length of the buffer2 to serialize + * @param p_priv Pointer to serialize + */ +void rpc_serialize_s_b_b_p(uint8_t fn_index, const void * struct_data, uint8_t struct_length, + const void * vbuf1, uint16_t vbuf1_length, const void * vbuf2, uint16_t vbuf2_length, void * p_priv); + +/** RPC deserialization function, shall be invoked when a buffer is received over the transport interface. + * + * @param p_buf Pointer to the received buffer + * @param length Length of the received buffer + */ +void rpc_deserialize(const uint8_t * p_buf, uint16_t length); + +#endif /* RPC_H_*/ diff --git a/system/libarc32_arduino101/drivers/rpc/rpc_deserialize.c b/system/libarc32_arduino101/drivers/rpc/rpc_deserialize.c new file mode 100644 index 00000000..e3f568d0 --- /dev/null +++ b/system/libarc32_arduino101/drivers/rpc/rpc_deserialize.c @@ -0,0 +1,457 @@ +/* + * Copyright (c) 2016 Intel Corporation + * + * 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 +#include + +#include "rpc.h" + +extern void panic(int err); + +/* Include the functions offered */ +#if defined(CONFIG_QUARK_SE_BLE_CORE) +#include "rpc_functions_to_ble_core.h" +#elif defined(CONFIG_SOC_QUARK_SE) +#include "rpc_functions_to_quark.h" +#elif defined(LINUX_HOST_RUNTIME) +// for the host compilation (to simulate connection to BLE controller) +#include "rpc_functions_to_ble_core.h" +#else +#error "File is compiled but should not" +#endif + +/* Build the list of prototypes and check that list are made only of matching signatures */ +#define FN_SIG_NONE(__fn) void __fn(void); +LIST_FN_SIG_NONE +#undef FN_SIG_NONE + +#define FN_SIG_S(__fn, __s) void __fn(__s p_s); +LIST_FN_SIG_S +#undef FN_SIG_S + +#define FN_SIG_P(__fn, __type) void __fn(__type p_priv); +LIST_FN_SIG_P +#undef FN_SIG_P + +#define FN_SIG_S_B(__fn, __s, __type, __length) void __fn(__s p_s, __type p_buf, __length length); +LIST_FN_SIG_S_B +#undef FN_SIG_S_B + +#define FN_SIG_B_B_P(__fn, __type1, __length1, __type2, __length2, __type3) \ + void __fn(__type1 p_buf1, __length1 length1, __type2 p_buf2, __length2 length2, __type3 p_priv); +LIST_FN_SIG_B_B_P +#undef FN_SIG_B_B_P + +#define FN_SIG_S_P(__fn, __s, __type) void __fn(__s p_s, __type p_priv); +LIST_FN_SIG_S_P +#undef FN_SIG_S_P + +#define FN_SIG_S_B_P(__fn, __s, __type, __length, __type_ptr) \ + void __fn(__s p_s, __type p_buf, __length length, __type_ptr p_priv); +LIST_FN_SIG_S_B_P +#undef FN_SIG_S_B_P + +#define FN_SIG_S_B_B_P(__fn, __s, __type1, __length1, __type2, __length2, __type_ptr) \ + void __fn(__s p_s, __type1 p_buf1, __length1 length1, __type2 p_buf2, __length2 length2, __type_ptr p_priv); +LIST_FN_SIG_S_B_B_P +#undef FN_SIG_S_B_B_P + + + +/* 1 - define the size check arrays */ +#define FN_SIG_NONE(__fn) + +#define FN_SIG_S(__fn, __s) sizeof(*((__s)0)), + +#define FN_SIG_P(__fn, __type) + +#define FN_SIG_S_B(__fn, __s, __type, __length) sizeof(*((__s)0)), + +#define FN_SIG_B_B_P(__fn, __type1, __length1, __type2, __length2, __type3) sizeof(*((__s)0)), + +#define FN_SIG_S_P(__fn, __s, __type) sizeof(*((__s)0)), + +#define FN_SIG_S_B_P(__fn, __s, __type, __length, __type_ptr) sizeof(*((__s)0)), + +#define FN_SIG_S_B_B_P(__fn, __s, __type1, __length1, __type2, __length2, __type3) sizeof(*((__s)0)), + +static uint8_t m_size_s[] = { LIST_FN_SIG_S }; +static uint8_t m_size_s_b[] = { LIST_FN_SIG_S_B }; +static uint8_t m_size_s_p[] = { LIST_FN_SIG_S_P }; +static uint8_t m_size_s_b_p[] = { LIST_FN_SIG_S_B_P }; +static uint8_t m_size_s_b_b_p[] = { LIST_FN_SIG_S_B_B_P }; + +#undef FN_SIG_NONE +#undef FN_SIG_S +#undef FN_SIG_P +#undef FN_SIG_S_B +#undef FN_SIG_B_B_P +#undef FN_SIG_S_P +#undef FN_SIG_S_B_P +#undef FN_SIG_S_B_B_P + +/* 2- build the enumerations list */ +#define FN_SIG_NONE(__fn) fn_index_##__fn, +#define FN_SIG_S(__fn, __s) FN_SIG_NONE(__fn) +#define FN_SIG_P(__fn, __type) FN_SIG_NONE(__fn) +#define FN_SIG_S_B(__fn, __s, __type, __length) FN_SIG_NONE(__fn) +#define FN_SIG_B_B_P(__fn, __type1, __length1, __type2, __length2, __type3) FN_SIG_NONE(__fn) +#define FN_SIG_S_P(__fn, __s, __type) FN_SIG_NONE(__fn) +#define FN_SIG_S_B_P(__fn, __s, __type, __length, __type_ptr) FN_SIG_NONE(__fn) +#define FN_SIG_S_B_B_P(__fn, __s, __type1, __length1, __type2, __length2, __type3) FN_SIG_NONE(__fn) + +/* Build the list of function indexes in the deserialization array */ +enum { LIST_FN_SIG_NONE fn_none_index_max }; +enum { LIST_FN_SIG_S fn_s_index_max }; +enum { LIST_FN_SIG_P fn_p_index_max }; +enum { LIST_FN_SIG_S_B fn_s_b_index_max }; +enum { LIST_FN_SIG_B_B_P fn_b_b_p_index_max }; +enum { LIST_FN_SIG_S_P fn_s_p_index_max }; +enum { LIST_FN_SIG_S_B_P fn_s_b_p_index_max }; +enum { LIST_FN_SIG_S_B_B_P fn_s_b_b_p_index_max }; + +#undef FN_SIG_NONE +#undef FN_SIG_S +#undef FN_SIG_P +#undef FN_SIG_S_B +#undef FN_SIG_B_B_P +#undef FN_SIG_S_P +#undef FN_SIG_S_B_P +#undef FN_SIG_S_B_B_P + +/* 3- build the array */ +#define FN_SIG_NONE(__fn) [fn_index_##__fn] = (void*)__fn, +#define FN_SIG_S(__fn, __s) FN_SIG_NONE(__fn) +#define FN_SIG_P(__fn, __type) FN_SIG_NONE(__fn) +#define FN_SIG_S_B(__fn, __s, __type, __length) FN_SIG_NONE(__fn) +#define FN_SIG_B_B_P(__fn, __type1, __length1, __type2, __length2, __type3) FN_SIG_NONE(__fn) +#define FN_SIG_S_P(__fn, __s, __type) FN_SIG_NONE(__fn) +#define FN_SIG_S_B_P(__fn, __s, __type, __length, __type_ptr) FN_SIG_NONE(__fn) +#define FN_SIG_S_B_B_P(__fn, __s, __type1, __length1, __type2, __length2, __type3) FN_SIG_NONE(__fn) + +static void (*m_fct_none[])(void) = { LIST_FN_SIG_NONE }; +static void (*m_fct_s[])(void * structure) = { LIST_FN_SIG_S }; +static void (*m_fct_p[])(void * pointer) = { LIST_FN_SIG_P }; +static void (*m_fct_s_b[])(void * structure, void * buffer, uint8_t length) = { LIST_FN_SIG_S_B }; +static void (*m_fct_b_b_p[])(void * buffer1, uint8_t length1, void * buffer2, uint8_t length2, void * pointer) = { LIST_FN_SIG_B_B_P }; +static void (*m_fct_s_p[])(void * structure, void * pointer) = { LIST_FN_SIG_S_P }; +static void (*m_fct_s_b_p[])(void * structure, void * buffer, uint8_t length, void * pointer) = { LIST_FN_SIG_S_B_P }; +static void (*m_fct_s_b_b_p[])(void * structure, void * buffer1, uint8_t length1, void * buffer2, uint8_t length2, void * pointer) = { LIST_FN_SIG_S_B_B_P }; + +static const uint8_t * deserialize_struct(const uint8_t *p, const uint8_t **pp_struct, uint8_t *p_struct_length) { + uint8_t struct_length; + + struct_length = *p++; + *pp_struct = p; + *p_struct_length = struct_length; + + return p + struct_length; +} + +static const uint8_t * deserialize_buf(const uint8_t *p, const uint8_t **pp_buf, uint16_t *p_buflen) { + uint8_t b; + uint16_t buflen; + + /* Get the current byte */ + b = *p++; + buflen = b & 0x7F; + if (b & 0x80) { + /* Get the current byte */ + b = *p++; + buflen += (uint16_t)b << 7; + } + + /* Return the values */ + *pp_buf = p; + *p_buflen = buflen; + p += buflen; + return p; +} + +static void deserialize_none(uint8_t fn_index, const uint8_t * p_buf, uint16_t length) { + (void)p_buf; + if (length != 0) + panic(-1); + m_fct_none[fn_index](); +} + +static void deserialize_s(uint8_t fn_index, const uint8_t * p_buf, uint16_t length) { + const uint8_t *p_struct_data; + uint8_t struct_length; + const uint8_t *p; + + p = deserialize_struct(p_buf, &p_struct_data, &struct_length); + + if ((length != (p - p_buf)) || + (struct_length != m_size_s[fn_index])) + panic(-1); + + { + /* Always align structures on word boundary */ + uintptr_t struct_data[(struct_length + (sizeof(uintptr_t) - 1))/(sizeof(uintptr_t))]; + + memcpy(struct_data, p_struct_data, struct_length); + + m_fct_s[fn_index](struct_data); + } +} + +static void deserialize_p(uint8_t fn_index, const uint8_t * p_buf, uint16_t length) { + uintptr_t p_priv; + + if (length != 4) + panic(-1); + + /* little endian conversion */ + p_priv = p_buf[0] | (p_buf[1] << 8) | (p_buf[2] << 16) | (p_buf[3] << 24); + + m_fct_p[fn_index]((void *)p_priv); +} + +static void deserialize_s_b(uint8_t fn_index, const uint8_t * p_buf, uint16_t length) { + const uint8_t *p_struct_data; + uint8_t struct_length; + const uint8_t *p_vbuf; + uint16_t vbuf_length; + const uint8_t *p; + + p = deserialize_struct(p_buf, &p_struct_data, &struct_length); + p = deserialize_buf(p, &p_vbuf, &vbuf_length); + + if ((length != (p - p_buf)) || + (struct_length != m_size_s_b[fn_index])) + panic(-1); + + { + /* Always align structures on word boundary */ + uintptr_t struct_data[(struct_length + (sizeof(uintptr_t) - 1))/(sizeof(uintptr_t))]; + uintptr_t vbuf[(vbuf_length + (sizeof(uintptr_t) - 1))/(sizeof(uintptr_t))]; + void * buf = NULL; + + memcpy(struct_data, p_struct_data, struct_length); + + if (vbuf_length) { + memcpy(vbuf, p_vbuf, vbuf_length); + buf = vbuf; + } + + m_fct_s_b[fn_index](struct_data, buf, vbuf_length); + } +} + +static void deserialize_b_b_p(uint8_t fn_index, const uint8_t * p_buf, uint16_t length) { + const uint8_t *p_vbuf1; + uint16_t vbuf1_length; + const uint8_t *p_vbuf2; + uint16_t vbuf2_length; + uintptr_t p_priv; + const uint8_t *p; + + p = deserialize_buf(p_buf, &p_vbuf1, &vbuf1_length); + p = deserialize_buf(p, &p_vbuf2, &vbuf2_length); + p += 4; + + if (length != (p - p_buf)) + panic(-1); + + { + /* Always align structures on word boundary */ + uintptr_t vbuf1[(vbuf1_length + (sizeof(uintptr_t) - 1))/(sizeof(uintptr_t))]; + uintptr_t vbuf2[(vbuf2_length + (sizeof(uintptr_t) - 1))/(sizeof(uintptr_t))]; + void * buf1 = NULL; + void * buf2 = NULL; + + if (vbuf1_length) { + memcpy(vbuf1, p_vbuf1, vbuf1_length); + buf1 = vbuf1; + } + + if (vbuf2_length) { + memcpy(vbuf2, p_vbuf2, vbuf2_length); + buf2 = vbuf2; + } + p = p_vbuf2 + vbuf2_length; + + /* little endian conversion */ + p_priv = p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24); + + m_fct_b_b_p[fn_index](buf1, vbuf1_length, buf2, vbuf2_length, (void *)p_priv); + } +} + +static void deserialize_s_p(uint8_t fn_index, const uint8_t * p_buf, uint16_t length) +{ + const uint8_t *p_struct_data; + uint8_t struct_length; + uintptr_t p_priv; + const uint8_t *p; + + p = deserialize_struct(p_buf, &p_struct_data, &struct_length); + p += 4; + + if ((length != (p - p_buf)) || + (struct_length != m_size_s_p[fn_index])) + panic(-1); + + { + /* Always align structures on word boundary */ + uintptr_t struct_data[(struct_length + (sizeof(uintptr_t) - 1))/(sizeof(uintptr_t))]; + + memcpy(struct_data, p_struct_data, struct_length); + p = p_struct_data + struct_length; + + /* little endian conversion */ + p_priv = p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24); + + m_fct_s_p[fn_index](struct_data, (void *)p_priv); + } +} + +static void deserialize_s_b_p(uint8_t fn_index, const uint8_t * p_buf, uint16_t length) +{ + const uint8_t *p_struct_data; + uint8_t struct_length; + const uint8_t *p_vbuf; + uint16_t vbuf_length; + uintptr_t p_priv; + const uint8_t *p; + + p = deserialize_struct(p_buf, &p_struct_data, &struct_length); + p = deserialize_buf(p, &p_vbuf, &vbuf_length); + p += 4; + + if ((length != (p - p_buf)) || + (struct_length != m_size_s_b_p[fn_index])) + panic(-1); + + { + /* Always align structures on word boundary */ + uintptr_t struct_data[(struct_length + (sizeof(uintptr_t) - 1))/(sizeof(uintptr_t))]; + uintptr_t vbuf[(vbuf_length + (sizeof(uintptr_t) - 1))/(sizeof(uintptr_t))]; + void * buf = NULL; + + memcpy(struct_data, p_struct_data, struct_length); + + if (vbuf_length) { + memcpy(vbuf, p_vbuf, vbuf_length); + buf = vbuf; + } + p = p_vbuf + vbuf_length; + + /* little endian conversion */ + p_priv = p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24); + + m_fct_s_b_p[fn_index](struct_data, buf, vbuf_length, (void *)p_priv); + } +} + +static void deserialize_s_b_b_p(uint8_t fn_index, const uint8_t * p_buf, uint16_t length) { + const uint8_t *p_struct_data; + uint8_t struct_length; + const uint8_t *p_vbuf1; + uint16_t vbuf1_length; + const uint8_t *p_vbuf2; + uint16_t vbuf2_length; + uintptr_t p_priv; + const uint8_t *p; + + p = deserialize_struct(p_buf, &p_struct_data, &struct_length); + p = deserialize_buf(p, &p_vbuf1, &vbuf1_length); + p = deserialize_buf(p, &p_vbuf2, &vbuf2_length); + p += 4; + if ((length != (p - p_buf)) || + (struct_length != m_size_s_b_b_p[fn_index])) + panic(-1); + + { + /* Always align structures on word boundary */ + uintptr_t struct_data[(struct_length + (sizeof(uintptr_t) - 1))/(sizeof(uintptr_t))]; + uintptr_t vbuf1[(vbuf1_length + (sizeof(uintptr_t) - 1))/(sizeof(uintptr_t))]; + uintptr_t vbuf2[(vbuf2_length + (sizeof(uintptr_t) - 1))/(sizeof(uintptr_t))]; + void * buf1 = NULL; + void * buf2 = NULL; + + memcpy(struct_data, p_struct_data, struct_length); + + if (vbuf1_length) { + memcpy(vbuf1, p_vbuf1, vbuf1_length); + buf1 = vbuf1; + } + if (vbuf2_length) { + memcpy(vbuf2, p_vbuf2, vbuf2_length); + buf2 = vbuf2; + } + + p = p_vbuf2 + vbuf2_length; + + /* little endian conversion */ + p_priv = p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24); + + m_fct_s_b_b_p[fn_index](struct_data, buf1, vbuf1_length, buf2, vbuf2_length, (void *)p_priv); + } +} + +void rpc_deserialize(const uint8_t * p_buf, uint16_t length) { + + uint8_t fn_index; + uint8_t sig_type; + + if (NULL != p_buf) { + sig_type = p_buf[0]; + fn_index = p_buf[1]; + + p_buf += 2; + length -= 2; + + switch(sig_type) { + case SIG_TYPE_NONE: + if (sizeof(m_fct_none)) + deserialize_none(fn_index, p_buf, length); + break; + case SIG_TYPE_S: + if (sizeof(m_fct_s)) + deserialize_s(fn_index, p_buf, length); + break; + case SIG_TYPE_P: + if (sizeof(m_fct_p)) + deserialize_p(fn_index, p_buf, length); + break; + case SIG_TYPE_S_B: + if (sizeof(m_fct_s_b)) + deserialize_s_b(fn_index, p_buf, length); + break; + case SIG_TYPE_B_B_P: + if (sizeof(m_fct_b_b_p)) + deserialize_b_b_p(fn_index, p_buf, length); + break; + case SIG_TYPE_S_P: + if (sizeof(m_fct_s_p)) + deserialize_s_p(fn_index, p_buf, length); + break; + case SIG_TYPE_S_B_P: + if (sizeof(m_fct_s_b_p)) + deserialize_s_b_p(fn_index, p_buf, length); + break; + case SIG_TYPE_S_B_B_P: + if (sizeof(m_fct_s_b_b_p)) + deserialize_s_b_b_p(fn_index, p_buf, length); + break; + default: + panic(-1); + break; + } + } +} diff --git a/system/libarc32_arduino101/drivers/rpc/rpc_functions_to_ble_core.h b/system/libarc32_arduino101/drivers/rpc/rpc_functions_to_ble_core.h new file mode 100644 index 00000000..5f742208 --- /dev/null +++ b/system/libarc32_arduino101/drivers/rpc/rpc_functions_to_ble_core.h @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2016 Intel Corporation + * + * 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 RPC_FUNCTIONS_TO_BLE_CORE_H_ +#define RPC_FUNCTIONS_TO_BLE_CORE_H_ + +#include "gap_internal.h" +#include "gatt_internal.h" + +/* declare the list of functions sorted by signature */ +#define LIST_FN_SIG_NONE \ + FN_SIG_NONE(nble_gap_start_adv_req) \ + FN_SIG_NONE(nble_gap_stop_scan_req) + +#define LIST_FN_SIG_S \ + FN_SIG_S(nble_gap_set_adv_data_req, \ + struct nble_gap_ad_data_params *) \ + FN_SIG_S(nble_gap_set_adv_params_req, \ + struct nble_gap_adv_params *) \ + FN_SIG_S(nble_gap_start_scan_req, \ + const struct nble_gap_scan_params *) \ + FN_SIG_S(nble_gap_sm_config_req, \ + const struct nble_gap_sm_config_params *) \ + FN_SIG_S(nble_gap_sm_passkey_reply_req, \ + const struct nble_gap_sm_key_reply_req_params *) \ + FN_SIG_S(nble_gap_sm_bond_info_req, \ + const struct nble_gap_sm_bond_info_param *) \ + FN_SIG_S(nble_gap_sm_security_req, \ + const struct nble_gap_sm_security_params *) \ + FN_SIG_S(nble_gap_sm_clear_bonds_req, \ + const struct nble_gap_sm_clear_bond_req_params *) \ + FN_SIG_S(nble_set_bda_req, const struct nble_set_bda_params *) \ + FN_SIG_S(nble_gap_conn_update_req, \ + const struct nble_gap_connect_update_params *) \ + FN_SIG_S(nble_gattc_discover_req, \ + const struct nble_discover_params *) \ + FN_SIG_S(nble_gatts_wr_reply_req, \ + const struct nble_gatts_wr_reply_params *) \ + FN_SIG_S(nble_uas_rssi_calibrate_req, \ + const struct nble_uas_rssi_calibrate *) \ + FN_SIG_S(nble_gap_service_write_req, \ + const struct nble_gap_service_write_params *) \ + FN_SIG_S(nble_gap_disconnect_req, \ + const struct nble_gap_disconnect_req_params *) \ + FN_SIG_S(nble_gattc_read_req, \ + const struct ble_gattc_read_params *) \ + FN_SIG_S(nble_gap_tx_power_req, \ + const struct nble_gap_tx_power_params *) \ + FN_SIG_S(nble_get_version_req, \ + const struct nble_gap_get_version_param *) + +#define LIST_FN_SIG_P \ + FN_SIG_P(nble_gap_dtm_init_req, void *) \ + FN_SIG_P(nble_gap_read_bda_req, void *) \ + FN_SIG_P(nble_gap_stop_adv_req, void *) \ + FN_SIG_P(nble_gap_cancel_connect_req, void *) + +#define LIST_FN_SIG_S_B \ + FN_SIG_S_B(nble_gatt_register_req, \ + const struct nble_gatt_register_req *, \ + uint8_t *, uint16_t) \ + FN_SIG_S_B(nble_gatt_send_notif_req, \ + const struct nble_gatt_send_notif_params *, \ + const uint8_t *, uint16_t) \ + FN_SIG_S_B(nble_gatt_send_ind_req, \ + const struct nble_gatt_send_ind_params *, \ + const uint8_t *, uint8_t) \ + FN_SIG_S_B(nble_gatts_rd_reply_req, \ + const struct nble_gatts_rd_reply_params *, \ + uint8_t *, uint16_t) \ + FN_SIG_S_B(nble_gattc_write_req, \ + const struct ble_gattc_write_params *, \ + const uint8_t *, uint8_t) \ + FN_SIG_S_B(nble_gattc_read_multiple_req, \ + const struct ble_gattc_read_multiple_params *, \ + const uint16_t *, uint16_t) + +#define LIST_FN_SIG_B_B_P + +#define LIST_FN_SIG_S_P \ + FN_SIG_S_P(nble_gap_connect_req, \ + const struct nble_gap_connect_req_params *, void *) \ + FN_SIG_S_P(nble_gap_set_rssi_report_req, \ + const struct nble_rssi_report_params *, void *) \ + FN_SIG_S_P(nble_gap_dbg_req, \ + const struct nble_debug_params *, \ + void *) + +#define LIST_FN_SIG_S_B_P + +#define LIST_FN_SIG_S_B_B_P + +#endif /* RPC_FUNCTIONS_TO_BLE_CORE_H_ */ diff --git a/system/libarc32_arduino101/drivers/rpc/rpc_functions_to_quark.h b/system/libarc32_arduino101/drivers/rpc/rpc_functions_to_quark.h new file mode 100644 index 00000000..b08005e6 --- /dev/null +++ b/system/libarc32_arduino101/drivers/rpc/rpc_functions_to_quark.h @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2016 Intel Corporation + * + * 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 RPC_FUNCTIONS_TO_QUARK_H_ +#define RPC_FUNCTIONS_TO_QUARK_H_ + +#include "gap_internal.h" +#include "gatt_internal.h" +#include "gap_internal.h" + +/* declare the list of functions sorted by signature */ +#define LIST_FN_SIG_NONE \ + FN_SIG_NONE(on_nble_up) + +#define LIST_FN_SIG_S \ + FN_SIG_S(on_nble_get_version_rsp, \ + const struct nble_version_response *) \ + FN_SIG_S(on_nble_gap_connect_evt, \ + const struct nble_gap_connect_evt *) \ + FN_SIG_S(on_nble_gap_disconnect_evt, \ + const struct nble_gap_disconnect_evt *) \ + FN_SIG_S(on_nble_gap_conn_update_evt, \ + const struct nble_gap_conn_update_evt *) \ + FN_SIG_S(on_nble_gap_sm_status_evt, \ + const struct nble_gap_sm_status_evt *) \ + FN_SIG_S(on_nble_gap_sm_passkey_display_evt, \ + const struct nble_gap_sm_passkey_disp_evt *) \ + FN_SIG_S(on_nble_gap_sm_passkey_req_evt, \ + const struct nble_gap_sm_passkey_req_evt *) \ + FN_SIG_S(on_nble_gap_rssi_evt, \ + const struct nble_gap_rssi_evt *) \ + FN_SIG_S(on_nble_common_rsp, \ + const struct nble_response *) \ + FN_SIG_S(on_nble_gap_connect_rsp, \ + const struct nble_response *) \ + FN_SIG_S(on_nble_gap_cancel_connect_rsp, \ + const struct nble_response *) \ + FN_SIG_S(on_nble_gap_read_bda_rsp, \ + const struct nble_service_read_bda_response *) \ + FN_SIG_S(on_nble_gap_sm_config_rsp, \ + struct nble_gap_sm_config_rsp *) \ + FN_SIG_S(on_nble_gap_sm_common_rsp, \ + const struct nble_gap_sm_response *) \ + FN_SIG_S(on_nble_set_bda_rsp, \ + const struct nble_set_bda_rsp *) \ + FN_SIG_S(on_nble_gap_set_rssi_report_rsp, \ + const struct nble_response *) \ + FN_SIG_S(on_nble_gap_dbg_rsp, \ + const struct nble_debug_resp *) \ + FN_SIG_S(on_nble_gap_dir_adv_timeout_evt, \ + const struct nble_gap_dir_adv_timeout_evt *) \ + FN_SIG_S(on_nble_gatts_send_notif_rsp, \ + const struct nble_gatt_notif_rsp *) \ + FN_SIG_S(on_nble_gatts_send_ind_rsp, \ + const struct nble_gatt_ind_rsp *) \ + FN_SIG_S(on_nble_gap_start_advertise_rsp, \ + const struct nble_response *) \ + FN_SIG_S(on_nble_gap_scan_start_stop_rsp, \ + const struct nble_response *) \ + FN_SIG_S(on_nble_gatts_read_evt, \ + const struct nble_gatt_rd_evt *) \ + FN_SIG_S(on_nble_gatts_write_exec_evt, \ + const struct nble_gatt_wr_exec_evt *) \ + FN_SIG_S(on_nble_uas_bucket_change, \ + const struct nble_uas_bucket_change *) \ + FN_SIG_S(on_nble_gattc_write_rsp, \ + const struct ble_gattc_write_rsp *) \ + FN_SIG_S(on_nble_gap_tx_power_rsp, \ + const struct nble_response *) + +#define LIST_FN_SIG_P \ + FN_SIG_P(on_nble_gap_dtm_init_rsp, void *) + +#define LIST_FN_SIG_S_B \ + FN_SIG_S_B(nble_log, const struct nble_log_s *, char *, \ + uint8_t) \ + FN_SIG_S_B(on_nble_gattc_value_evt, \ + const struct ble_gattc_value_evt *, \ + uint8_t *, uint8_t) \ + FN_SIG_S_B(on_nble_gatts_write_evt, \ + const struct nble_gatt_wr_evt *, \ + const uint8_t *, uint8_t) \ + FN_SIG_S_B(on_nble_gatt_register_rsp, \ + const struct nble_gatt_register_rsp *, \ + const struct nble_gatt_attr_handles *, \ + uint8_t) \ + FN_SIG_S_B(on_nble_gattc_discover_rsp, \ + const struct nble_gattc_discover_rsp *, \ + const uint8_t *, uint8_t) \ + FN_SIG_S_B(on_nble_gap_adv_report_evt, \ + const struct nble_gap_adv_report_evt *, \ + const uint8_t *, uint8_t) \ + FN_SIG_S_B(on_nble_gap_sm_bond_info_rsp, \ + const struct nble_gap_sm_bond_info_rsp*, \ + const bt_addr_le_t *, uint16_t) \ + FN_SIG_S_B(on_nble_gattc_read_rsp, \ + const struct ble_gattc_read_rsp *, \ + uint8_t *, uint8_t) \ + FN_SIG_S_B(on_nble_gattc_read_multiple_rsp, \ + const struct ble_gattc_read_rsp *, \ + uint8_t *, uint8_t) + +#define LIST_FN_SIG_B_B_P + +#define LIST_FN_SIG_S_P + +#define LIST_FN_SIG_S_B_P + +#define LIST_FN_SIG_S_B_B_P + +#endif /* RPC_FUNCTIONS_TO_QUARK_H_ */ diff --git a/system/libarc32_arduino101/drivers/rpc/rpc_serialize.c b/system/libarc32_arduino101/drivers/rpc/rpc_serialize.c new file mode 100644 index 00000000..e2144ee3 --- /dev/null +++ b/system/libarc32_arduino101/drivers/rpc/rpc_serialize.c @@ -0,0 +1,323 @@ +/* + * Copyright (c) 2016 Intel Corporation + * + * 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 + +#include "rpc.h" + +/* Include the functions called */ +#if defined(CONFIG_QUARK_SE_BLE_CORE) +#include "rpc_functions_to_quark.h" +#elif defined(CONFIG_SOC_QUARK_SE) +#include "rpc_functions_to_ble_core.h" +#elif defined(LINUX_HOST_RUNTIME) +// for the host compilation (to simulate connection to BLE controller) +#include "rpc_functions_to_ble_core.h" +#else +#error "File is compiled but should not" +#endif + +/* Build the functions exposed */ +/* Define the functions identifiers per signature */ +#define FN_SIG_NONE(__fn) fn_index_##__fn, +#define FN_SIG_S(__fn, __s) FN_SIG_NONE(__fn) +#define FN_SIG_P(__fn, __type) FN_SIG_NONE(__fn) +#define FN_SIG_S_B(__fn, __s, __type, __length) FN_SIG_NONE(__fn) +#define FN_SIG_B_B_P(__fn, __type1, __length1, __type2, __length2,__type3) FN_SIG_NONE(__fn) +#define FN_SIG_S_P(__fn, __s, __type) FN_SIG_NONE(__fn) +#define FN_SIG_S_B_P(__fn, __s, __type, __length, __type_ptr) FN_SIG_NONE(__fn) +#define FN_SIG_S_B_B_P(__fn, __s, __type1, __length1, __type2, __length2,__type3) FN_SIG_NONE(__fn) + +/* Build the list of function indexes -> this should match the array at deserialization */ +enum { LIST_FN_SIG_NONE fn_none_index_max }; +enum { LIST_FN_SIG_S fn_s_index_max }; +enum { LIST_FN_SIG_P fn_p_index_max }; +enum { LIST_FN_SIG_S_B fn_s_b_index_max }; +enum { LIST_FN_SIG_B_B_P fn_b_b_p_index_max }; +enum { LIST_FN_SIG_S_P fn_s_p_index_max }; +enum { LIST_FN_SIG_S_B_P fn_s_b_p_index_max }; +enum { LIST_FN_SIG_S_B_B_P fn_s_b_b_p_index_max }; + +/* Implement the functions using serialization API */ +#undef FN_SIG_NONE +#undef FN_SIG_S +#undef FN_SIG_P +#undef FN_SIG_S_B +#undef FN_SIG_B_B_P +#undef FN_SIG_S_P +#undef FN_SIG_S_B_P +#undef FN_SIG_S_B_B_P + +#define FN_SIG_NONE(__fn) \ + void __fn(void) { \ + rpc_serialize_none(fn_index_##__fn); \ + } \ + +#define FN_SIG_S(__fn, __s) \ + void __fn(__s p_s) { \ + rpc_serialize_s(fn_index_##__fn, p_s, sizeof(*p_s)); \ + } \ + +#define FN_SIG_P(__fn, __type) \ + void __fn(__type p_priv) { \ + rpc_serialize_p(fn_index_##__fn, p_priv); \ + } \ + +#define FN_SIG_S_B(__fn, __s, __type, __length) \ + void __fn(__s p_s, __type p_buf, __length length) { \ + rpc_serialize_s_b(fn_index_##__fn, p_s, sizeof(*p_s), p_buf, length); \ + } \ + +#define FN_SIG_B_B_P(__fn, __type1, __length1, __type2, __length2, __type3) \ + void __fn(__type1 p_buf1, __length1 length1, __type2 p_buf2, __length2 length2, __type3 p_priv) { \ + rpc_serialize_b_b_p(fn_index_##__fn, p_buf1, length1, p_buf2, length2, p_priv); \ + } \ + +#define FN_SIG_S_P(__fn, __s, __type) \ + void __fn(__s p_s, __type p_priv) { \ + rpc_serialize_s_p(fn_index_##__fn, p_s, sizeof(*p_s), p_priv); \ + } \ + +#define FN_SIG_S_B_P(__fn, __s, __type, __length, __type_ptr) \ + void __fn(__s p_s, __type p_buf, __length length, __type_ptr p_priv) { \ + rpc_serialize_s_b_p(fn_index_##__fn, p_s, sizeof(*p_s), p_buf, length, p_priv); \ + } + +#define FN_SIG_S_B_B_P(__fn, __s, __type1, __length1, __type2, __length2, __type3) \ + void __fn(__s p_s, __type1 p_buf1, __length1 length1, __type2 p_buf2, __length2 length2, __type3 p_priv) { \ + rpc_serialize_s_b_b_p(fn_index_##__fn, p_s, sizeof(*p_s), p_buf1, length1, p_buf2, length2, p_priv); \ + } \ + + +/* Build the functions */ +LIST_FN_SIG_NONE +LIST_FN_SIG_S +LIST_FN_SIG_P +LIST_FN_SIG_S_B +LIST_FN_SIG_B_B_P +LIST_FN_SIG_S_P +LIST_FN_SIG_S_B_P +LIST_FN_SIG_S_B_B_P + +#define SIG_TYPE_SIZE 1 +#define FN_INDEX_SIZE 1 +#define POINTER_SIZE 4 + +static void _send(uint8_t *buf, uint16_t length) { + rpc_transmit_cb(buf, length); +} + +static uint16_t encoded_structlen(uint8_t structlen) { + return 1 + structlen; +} + +static uint8_t *serialize_struct(uint8_t *p, const uint8_t *struct_data, uint8_t struct_length) { + *p++ = struct_length; + memcpy(p, struct_data, struct_length); + p += struct_length; + return p; +} + +static uint16_t encoded_buflen(const uint8_t *buf, uint16_t buflen) { + if (NULL == buf) + return 1; + else { + if (buflen < (1 << 7)) { + return 1 + buflen; + } + else + return 2 + buflen; + } +} + +static uint8_t *serialize_buf(uint8_t *p, const uint8_t *buf, uint16_t buflen) { + uint16_t varint; + + if (NULL == buf) + buflen = 0; + + varint = buflen; + + *p = varint & 0x7F; + if (varint >= (1 << 7)) { + *p |= 0x80; + p++; + *p = varint >> 7; + } + p++; + memcpy(p, buf, buflen); + p += buflen; + return p; +} + +static uint8_t *serialize_p(uint8_t *p, uintptr_t priv) { + *p++ = priv; + *p++ = (priv >> 8); + *p++ = (priv >> 16); + *p++ = (priv >> 24); + return p; +} + +void rpc_serialize_none(uint8_t fn_index) { + uint16_t length; + uint8_t * buf; + uint8_t * p; + + length = SIG_TYPE_SIZE + FN_INDEX_SIZE; + + p = buf = rpc_alloc_cb(length); + + *p++ = SIG_TYPE_NONE; + *p = fn_index; + + _send(buf, length); +} + +void rpc_serialize_s(uint8_t fn_index, const void * struct_data, uint8_t struct_length) { + uint16_t length; + uint8_t * buf; + uint8_t * p; + + length = SIG_TYPE_SIZE + FN_INDEX_SIZE + encoded_structlen(struct_length); + + p = buf = rpc_alloc_cb(length); + + *p++ = SIG_TYPE_S; + *p++ = fn_index; + p = serialize_struct(p, struct_data, struct_length); + + _send(buf, length); +} + + +void rpc_serialize_p(uint8_t fn_index, void * p_priv) { + uint16_t length; + uint8_t * buf; + uint8_t * p; + uintptr_t priv = (uintptr_t) p_priv; + + length = SIG_TYPE_SIZE + FN_INDEX_SIZE + POINTER_SIZE; + + p = buf = rpc_alloc_cb(length); + + *p++ = SIG_TYPE_P; + *p++ = fn_index; + p = serialize_p(p, priv); + + _send(buf, length); +} + +void rpc_serialize_s_b(uint8_t fn_index, const void * struct_data, uint8_t struct_length, const void * vbuf, uint16_t vbuf_length) { + uint16_t length; + uint8_t * buf; + uint8_t * p; + + length = SIG_TYPE_SIZE + FN_INDEX_SIZE + encoded_structlen(struct_length) + + encoded_buflen(vbuf, vbuf_length); + + p = buf = rpc_alloc_cb(length); + + *p++ = SIG_TYPE_S_B; + *p++ = fn_index; + p = serialize_struct(p, struct_data, struct_length); + p = serialize_buf(p, vbuf, vbuf_length); + + _send(buf, length); +} + +void rpc_serialize_b_b_p(uint8_t fn_index, const void * vbuf1, uint16_t vbuf1_length, const void * vbuf2, uint16_t vbuf2_length, void * p_priv) { + uint16_t length; + uint8_t * buf; + uint8_t * p; + uintptr_t priv = (uintptr_t) p_priv; + + length = SIG_TYPE_SIZE + FN_INDEX_SIZE + encoded_buflen(vbuf1, vbuf1_length) + + encoded_buflen(vbuf2, vbuf2_length) + POINTER_SIZE; + + p = buf = rpc_alloc_cb(length); + + *p++ = SIG_TYPE_B_B_P; + *p++ = fn_index; + p = serialize_buf(p, vbuf1, vbuf1_length); + p = serialize_buf(p, vbuf2, vbuf2_length); + p = serialize_p(p, priv); + + _send(buf, length); +} + +void rpc_serialize_s_p(uint8_t fn_index, const void * struct_data, uint8_t struct_length, void * p_priv) { + uint16_t length; + uint8_t * buf; + uint8_t * p; + uintptr_t priv = (uintptr_t) p_priv; + + length = SIG_TYPE_SIZE + FN_INDEX_SIZE + encoded_structlen(struct_length) + + POINTER_SIZE; + + p = buf = rpc_alloc_cb(length); + + *p++ = SIG_TYPE_S_P; + *p++ = fn_index; + p = serialize_struct(p, struct_data, struct_length); + p = serialize_p(p, priv); + + _send(buf, length); +} + +void rpc_serialize_s_b_p(uint8_t fn_index, const void * struct_data, uint8_t struct_length, + const void * vbuf, uint16_t vbuf_length, void * p_priv) { + uint16_t length; + uint8_t * buf; + uint8_t * p; + uintptr_t priv = (uintptr_t) p_priv; + + length = SIG_TYPE_SIZE + FN_INDEX_SIZE + encoded_structlen(struct_length) + + encoded_buflen(vbuf, vbuf_length) + POINTER_SIZE; + + p = buf = rpc_alloc_cb(length); + + *p++ = SIG_TYPE_S_B_P; + *p++ = fn_index; + p = serialize_struct(p, struct_data, struct_length); + p = serialize_buf(p, vbuf, vbuf_length); + p = serialize_p(p, priv); + + _send(buf, length); +} + +void rpc_serialize_s_b_b_p(uint8_t fn_index, const void * struct_data, uint8_t struct_length, + const void * vbuf1, uint16_t vbuf1_length, const void * vbuf2, uint16_t vbuf2_length, void * p_priv) { + + uint16_t length; + uint8_t * buf; + uint8_t * p; + uintptr_t priv = (uintptr_t) p_priv; + + length = SIG_TYPE_SIZE + FN_INDEX_SIZE + encoded_structlen(struct_length) + + encoded_buflen(vbuf1, vbuf1_length) + + encoded_buflen(vbuf2, vbuf2_length) + POINTER_SIZE; + + p = buf = rpc_alloc_cb(length); + + *p++ = SIG_TYPE_S_B_B_P; + *p++ = fn_index; + p = serialize_struct(p, struct_data, struct_length); + p = serialize_buf(p, vbuf1, vbuf1_length); + p = serialize_buf(p, vbuf2, vbuf2_length); + p = serialize_p(p, priv); + + _send(buf, length); +} diff --git a/system/libarc32_arduino101/drivers/soc_i2c_priv.h b/system/libarc32_arduino101/drivers/soc_i2c_priv.h new file mode 100644 index 00000000..0e1973bf --- /dev/null +++ b/system/libarc32_arduino101/drivers/soc_i2c_priv.h @@ -0,0 +1,198 @@ +/* + * Copyright (c) 2015, Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef SOC_I2C_PRIV_H_ +#define SOC_I2C_PRIV_H_ + + +#define INT_I2C_0_MASK (0x448) +#define INT_I2C_1_MASK (0x44C) + +#define SCSS_BASE SCSS_REGISTER_BASE + +#define INT_I2C_MASK_RW (uint32_t)(0xb0800448) + +/* QRK interrupt values */ +#define QRK_I2C_INT_MASK (0x01010100) + +/* QRK interrupt values */ + +#define SOC_ENABLE_RX_TX_INT_I2C \ + (IC_INTR_RX_UNDER | IC_INTR_RX_OVER | IC_INTR_RX_FULL | IC_INTR_TX_OVER | \ + IC_INTR_TX_EMPTY | IC_INTR_TX_ABRT | IC_INTR_STOP_DET) +#define SOC_ENABLE_TX_INT_I2C \ + (IC_INTR_TX_OVER | IC_INTR_TX_EMPTY | IC_INTR_TX_ABRT | IC_INTR_STOP_DET) +#define SOC_ENABLE_INT_I2C_SLAVE \ + (IC_INTR_TX_OVER | IC_INTR_TX_ABRT | IC_INTR_RD_REQ | IC_INTR_RX_DONE | \ + IC_INTR_RX_FULL | IC_INTR_RX_OVER | IC_INTR_RX_UNDER | IC_INTR_STOP_DET) + +#define SOC_ENABLE_TX_INT_I2C_SLAVE (0x00000260) +#define SOC_ENABLE_RX_INT_I2C_SLAVE (0x00000204) +#define SOC_DISABLE_ALL_I2C_INT (0x00000000) + +/* IC_CON speed settings (bit 1:2) */ + +#define I2C_STD_SPEED 01 +#define I2C_FAST_SPEED 10 +#define I2C_HIGH_SPEED 11 + +/* IC_CON addressing settings (bit 4) */ + +#define I2C_7BIT_ADDR 0 +#define I2C_10BIT_ADDR 1 + +/* IC_CON Low count and high count default values */ +// TODO verify values for high and fast speed +#define I2C_STD_HCNT (CLOCK_SPEED * 4) +#define I2C_STD_LCNT (CLOCK_SPEED * 5) +#define I2C_FS_HCNT ((CLOCK_SPEED * 6) / 8) +#define I2C_FS_LCNT ((CLOCK_SPEED * 7) / 8) +#define I2C_HS_HCNT ((CLOCK_SPEED * 6) / 8) +#define I2C_HS_LCNT ((CLOCK_SPEED * 7) / 8) + +/* IC_DATA_CMD Data transfer mode settings (bit 8) */ +#define I2C_STATE_READY (0) +#define I2C_CMD_SEND (1 << 0) +#define I2C_CMD_RECV (1 << 1) +#define I2C_CMD_SLAVE_RECV I2C_CMD_RECV +#define I2C_CMD_SLAVE_SEND (1 << 2) +#define I2C_CMD_ERROR (1 << 3) + +/* Reset vectors for configuration registers */ +#define IC_CON_RST ((uint32_t)0x7e) +#define IC_TAR_RST ((uint32_t)0x55) + +/* FIFO size */ +#define FIFO_SIZE 16 + +/* APB I2C register offsets */ +#define IC_CON (0x00) +#define IC_TAR (0x04) +#define IC_SAR (0x08) +#define IC_HS_MADDR (0x0c) +#define IC_DATA_CMD (0x10) +#define IC_STD_SCL_HCNT (0x14) +#define IC_STD_SCL_LCNT (0x18) +#define IC_FS_SCL_HCNT (0x1c) +#define IC_FS_SCL_LCNT (0x20) +#define IC_HS_SCL_HCNT (0x24) +#define IC_HS_SCL_LCNT (0x28) +#define IC_INTR_STAT (0x2c) +#define IC_INTR_MASK (0x30) +#define IC_RAW_INTR_STAT (0x34) +#define IC_RX_TL (0x38) +#define IC_TX_TL (0x3c) +#define IC_CLR_INTR (0x40) +#define IC_CLR_RX_UNDER (0x44) +#define IC_CLR_RX_OVER (0x48) +#define IC_CLR_TX_OVER (0x4c) +#define IC_CLR_RD_REQ (0x50) +#define IC_CLR_TX_ABRT (0x54) +#define IC_CLR_RX_DONE (0x58) +#define IC_CLR_ACTIVITY (0x5c) +#define IC_CLR_STOP_DET (0x60) +#define IC_CLR_START_DET (0x64) +#define IC_CLR_GEN_CALL (0x68) +#define IC_ENABLE (0x6c) +#define IC_STATUS (0x70) +#define IC_TXFLR (0x74) +#define IC_RXFLR (0x78) +#define IC_SDA_HOLD (0x7c) +#define IC_TX_ABRT_SOURCE (0x80) +#define IC_SLV_DATA_NACK_ONLY (0x84) +#define IC_DMA_CR (0x88) +#define IC_DMA_TDLR (0x8c) +#define IC_DMA_RDLR (0x90) +#define IC_SDA_SETUP (0x94) +#define IC_ACK_GENERAL_CALL (0x98) +#define IC_ENABLE_STATUS (0x9c) +#define IC_FS_SPKLEN (0xa0) +#define IC_HS_SPKLEN (0xa4) +#define IC_CLR_RESTART_DET (0xa8) +#define IC_COMP_PARAM_1 (0xf4) +#define IC_COMP_VERSION (0xf8) +#define IC_COMP_TYPE (0xfc) + +#define RESTART_ALLOWED 0 // WARNING TODO Check whether this will be compile time or driver option + +/* Specific bits used to set certain regs */ +#define IC_RESTART_BIT (1 << 10) +#define IC_CMD_BIT (1 << 8) /* part of IC_DATA_CMD register, sets direction of current byte - set (1) = read, unset (0) = write */ +#define IC_STOP_BIT (1 << 9) /* part of IC_DATA_CMD, by setting this bit last byte of transfer is indicated */ +#define IC_TX_INTR_MODE (1 << 8) /* part of IC_CON registers - set TX interrupt mode*/ +#define IC_ENABLE_BIT (1 << 0) +#define IC_ABORT_BIT (1 << 1) +#define IC_SLAVE_DISABLE_BIT (1 << 6) +#define IC_STOP_DET_IFADDRESSED (1 << 7) +#define IC_MASTER_EN_BIT (1 << 0) +#define IC_RESTART_EN_BIT (1 << 5) +#define IC_MASTER_ADDR_MODE_BIT (1 << 4) +#define IC_SLAVE_ADDR_MODE_BIT (1 << 3) +#define IC_ACTIVITY (1 << 0) +#define IC_TAR_10BITADDR_MASTER (1 << 12) + +/* Out of convention */ +#define IC_SPEED_POS 2 + +#define ZERO_REG ((uint32_t)(0x00000000)) + +/* Clock gating */ +#define CLK_I2C_0_ENABLE (1 << 19) +#define CLK_I2C_1_ENABLE (1 << 20) +#define CLK_I2C_0_DISABLE (~CLK_I2C_0_ENABLE) +#define CLK_I2C_1_DISABLE (~CLK_I2C_1_ENABLE) + +#define STATUS_DELAY 1000 /* User configurable option - waits for controller status change (no interrupt available - occurs only when two transactions are initiated in short time) - normally shouldn't take more than 2-3 cycles, cycle is exited when set */ + +/* Interrupt handler statuses - bit masking for IC_RAW_INTR_STATUS register - passed by callbacks */ +#define IC_INTR_RX_UNDER (1 << 0) +#define IC_INTR_RX_OVER (1 << 1) /* RX fifo overflow */ +#define IC_INTR_RX_FULL (1 << 2) /* RX fifo full */ +#define IC_INTR_TX_OVER (1 << 3) /* TX fifo overflow */ +#define IC_INTR_TX_EMPTY (1 << 4) /* TX fifo empty */ +#define IC_INTR_RD_REQ (1 << 5) /* SLAVE - read request received */ +#define IC_INTR_TX_ABRT (1 << 6) /* TX aborted - TODO reason */ +#define IC_INTR_RX_DONE (1 << 7) /* SLAVE - read on master over */ +#define IC_INTR_ACTIVITY (1 << 8) /* Activity on I2C - automatically cleared by ISR */ +#define IC_INTR_STOP_DET (1 << 9) /* STOP condition on line */ +#define IC_INTR_START_DET (1 << 10) /* START condition on line */ +#define IC_INTR_GEN_CALL (1 << 11) /* General call issued - disabled */ +#define IC_INTR_RESTART_DET (1 << 12) /* SLAVE - restart condition - disabled */ +#define IC_INTR_MST_ON_HOLD (1 << 13) /* Master on hold - disabled */ + +#define IC_STATUS_ACTIVITY (1 << 0) +#define IC_STATUS_TFNF (1 << 1) +#define IC_STATUS_TFE (1 << 2) +#define IC_STATUS_RFNE (1 << 3) +#define IC_STATUS_RFF (1 << 4) +#define IC_STATUS_MST_ACTIVITY (1 << 5) +#define IC_STATUS_SLV_ACTIVITY (1 << 6) + +#endif diff --git a/system/libarc32_arduino101/drivers/spi_priv.h b/system/libarc32_arduino101/drivers/spi_priv.h index 9dd9e3fb..d46127d9 100644 --- a/system/libarc32_arduino101/drivers/spi_priv.h +++ b/system/libarc32_arduino101/drivers/spi_priv.h @@ -96,7 +96,7 @@ #define SPI_ENABLE_INT (SPI_ENABLE_TX_INT | SPI_ENABLE_RX_INT) #define SPI_RX_CLR_INTR (RXFIS) -#define SPI_ERR_CLR_INTR (RXOIS | RXUIS | TXOIS) +#define SPI_ERR_CLR_INTR (RXOIS |?RXUIS | TXOIS) #define SPI_TX_CLR_INTR (TXEIS) // DR @@ -155,6 +155,8 @@ typedef struct spi_info_struct uint32_t spi_err_mask; /* CREG Master clock gate bit location */ uint8_t creg_spi_clk_ctrl; + SPI_SLAVE_ENABLE slave; + struct clk_gate_info_s *clk_gate_info; } spi_info_t, *spi_info_pt; diff --git a/system/libarc32_arduino101/drivers/ss_spi.c b/system/libarc32_arduino101/drivers/ss_spi.c new file mode 100644 index 00000000..20689aba --- /dev/null +++ b/system/libarc32_arduino101/drivers/ss_spi.c @@ -0,0 +1,248 @@ +/******************************************************************************* + * + * Synopsys DesignWare Sensor and Control IP Subsystem IO Software Driver and + * documentation (hereinafter, "Software") is an Unsupported proprietary work + * of Synopsys, Inc. unless otherwise expressly agreed to in writing between + * Synopsys and you. + * + * The Software IS NOT an item of Licensed Software or Licensed Product under + * any End User Software License Agreement or Agreement for Licensed Product + * with Synopsys or any supplement thereto. You are permitted to use and + * redistribute this Software in source and binary forms, with or without + * modification, provided that redistributions of source code must retain this + * notice. You may not view, use, disclose, copy or distribute this file or + * any information contained herein except pursuant to this license grant from + * Synopsys. If you do not agree with this notice, including the disclaimer + * below, then you are not authorized to use the Software. + * + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + ******************************************************************************/ + +/******************************************************************************* + * + * Modifications Copyright (c) 2015, Intel Corporation. All rights reserved. + * + ******************************************************************************/ + +#include + +#include "common_spi.h" +#include "eiaextensions.h" +#include "portable.h" +#include "soc_gpio.h" +#include "spi_priv.h" +#include "clk_system.h" + +#include "ss_spi.h" + +#define SPI_MAX_CNT (2) + +/** + * Clock speed into SPI peripheral + */ +#define FREQ_SPI_CLOCK_IN \ + (CLOCK_SPEED * 1000 * 1000) /* CONFIG_CLOCK_SPEED in MHz */ + +static spi_info_t ss_spi_master_devs[SPI_MAX_CNT] = { + {.instID = 0, + .reg_base = AR_IO_SPI_MST0_CTRL, + .creg_spi_clk_ctrl = CREG_CLK_CTRL_SPI0, + .clk_gate_info = + &(struct clk_gate_info_s){ + .clk_gate_register = SS_PERIPH_CLK_GATE_CTL, + .bits_mask = SS_SPI0_CLK_GATE_MASK, + }}, + {.instID = 1, + .reg_base = AR_IO_SPI_MST1_CTRL, + .creg_spi_clk_ctrl = CREG_CLK_CTRL_SPI1, + .clk_gate_info = + &(struct clk_gate_info_s){ + .clk_gate_register = SS_PERIPH_CLK_GATE_CTL, + .bits_mask = SS_SPI1_CLK_GATE_MASK, + }}, +}; + +void ss_spi_set_clock_divider(SPI_CONTROLLER controller_id, uint8_t clockDiv) +{ + uint32_t spien, timing; + spi_info_pt dev = &ss_spi_master_devs[controller_id]; + + spien = READ_ARC_REG(dev->reg_base + SPIEN); + /* disable controller */ + WRITE_ARC_REG(SPI_DISABLE, dev->reg_base + SPIEN); + + /* Set SPI Clock Divider */ + timing = READ_ARC_REG(dev->reg_base + TIMING); + timing &= SPI_SCKDEV_SET_MASK; + timing |= clockDiv; + WRITE_ARC_REG(timing, dev->reg_base + TIMING); + + /* re-enable controller */ + WRITE_ARC_REG(spien | SPI_ENABLE, dev->reg_base + SPIEN); +} + +void ss_spi_set_data_mode(SPI_CONTROLLER controller_id, uint8_t dataMode) +{ + uint32_t spien, ctrl; + spi_info_pt dev = &ss_spi_master_devs[controller_id]; + + spien = READ_ARC_REG(dev->reg_base + SPIEN); + /* disable controller */ + WRITE_ARC_REG(SPI_DISABLE, dev->reg_base + SPIEN); + + /* Set frame size, bus mode and transfer mode */ + ctrl = READ_ARC_REG(dev->reg_base + CTRL); + ctrl &= (SPI_SCPL_SET_MASK & SPI_SCPH_SET_MASK); + ctrl = (dataMode << 6); + WRITE_ARC_REG(ctrl, dev->reg_base + CTRL); + + /* re-enable controller */ + WRITE_ARC_REG(spien | SPI_ENABLE, dev->reg_base + SPIEN); +} + +void ss_spi_init(SPI_CONTROLLER controller_id, uint32_t speed, + SPI_BUS_MODE mode, SPI_DATA_FRAME_SIZE data_frame_size, + SPI_SLAVE_ENABLE slave) +{ + uint32_t reg = 0; + uint32_t cs = 0; + spi_info_pt dev = &ss_spi_master_devs[controller_id]; + + dev->slave = slave; + if (dev->slave == SPI_SE_1) { + cs = 0; + } else if (dev->slave == SPI_SE_2) { + cs = 1; + } else if (dev->slave == SPI_SE_3) { + cs = 2; + } else if (dev->slave == SPI_SE_4) { + cs = 3; + } + + /* Configure pin-mux settings on the Intel Curie module to + * enable SPI mode usage */ + if (controller_id == SPI_SENSING_0) { + SET_PIN_MODE(28, QRK_PMUX_SEL_MODEA); // SPI0_SS_MISO + SET_PIN_MODE(29, QRK_PMUX_SEL_MODEA); // SPI0_SS_MOSI + SET_PIN_MODE(30, QRK_PMUX_SEL_MODEA); // SPI0_SS_SCK + SET_PIN_MODE(31 + cs, QRK_PMUX_SEL_MODEA); // SPI0_SS_CS_B[0] + } else if (controller_id == SPI_SENSING_1) { + SET_PIN_MODE(35, QRK_PMUX_SEL_MODEA); // SPI1_SS_MISO + SET_PIN_MODE(36, QRK_PMUX_SEL_MODEA); // SPI1_SS_MOSI + SET_PIN_MODE(37, QRK_PMUX_SEL_MODEA); // SPI1_SS_SCK + SET_PIN_MODE(38 + cs, QRK_PMUX_SEL_MODEA); // SPI0_SS_CS_B[0] + } + + /* enable clock to peripheral */ + set_clock_gate(dev->clk_gate_info, CLK_GATE_ON); + SET_ARC_BIT(AR_IO_CREG_MST0_CTRL, dev->creg_spi_clk_ctrl); + + /* disable controller */ + WRITE_ARC_REG(SPI_DISABLE, dev->reg_base + SPIEN); + /* enable clock to controller to allow reg writes */ + WRITE_ARC_REG(SPI_CLK_ENABLED, dev->reg_base + CTRL); + + /* Set frame size, bus mode and transfer mode */ + reg = SPI_CLK_ENABLED | data_frame_size | (mode << 6) | (SPI_TX_RX << 8); + WRITE_ARC_REG(reg, dev->reg_base + CTRL); + WRITE_ARC_REG((7 << 16) | 0, dev->reg_base + FTLR); + + reg = READ_ARC_REG(dev->reg_base + TIMING); + reg &= SPI_SCKDEV_SET_MASK; + reg |= FREQ_SPI_CLOCK_IN / (speed * BAUD_DIVISOR); + WRITE_ARC_REG(reg, dev->reg_base + TIMING); + + /* Disable interrupts */ + WRITE_ARC_REG(SPI_DISABLE_INT, dev->reg_base + INTR_MASK); +} + +void ss_spi_disable(SPI_CONTROLLER controller_id) +{ + spi_info_pt dev = &ss_spi_master_devs[controller_id]; + /* gate SPI controller clock */ + WRITE_ARC_REG(0, dev->reg_base + CTRL); +} + +static inline void spi_transmit(spi_info_pt dev, uint8_t *buf, size_t count, + boolean_t waitCompletion) +{ + while (count--) { + if (READ_ARC_REG(dev->reg_base + SR) & SPI_STATUS_TFNF) { + WRITE_ARC_REG(SPI_PUSH_DATA | *buf++, dev->reg_base + DR); + } + } + + /* Wait for transfer to complete */ + if (waitCompletion) + while (READ_ARC_REG(dev->reg_base + SR) & SPI_STATUS_BUSY) + ; +} + +static inline void spi_receive(spi_info_pt dev, uint8_t *buf, size_t count) +{ + while (count) { + if (READ_ARC_REG(dev->reg_base + RXFLR) > 0) { + WRITE_ARC_REG(SPI_POP_DATA, dev->reg_base + DR); + *buf++ = READ_ARC_REG(dev->reg_base + DR); + count--; + } + READ_ARC_REG(dev->reg_base + + RXFLR); /* Extra read of RXFLR, apparently necessary */ + } +} + +/* Polling-based SPI transfer to allow use within an ISR */ +int ss_spi_xfer(SPI_CONTROLLER controller_id, uint8_t *buf, unsigned tx_cnt, + unsigned rx_cnt) +{ + uint32_t spien = 0; + uint32_t ctrl = 0; + spi_info_pt dev = &ss_spi_master_devs[controller_id]; + + spien = READ_ARC_REG(dev->reg_base + SPIEN); + spien &= SPI_ENB_SET_MASK; + spien &= SPI_SER_SET_MASK; + spien |= (dev->slave << 4); + WRITE_ARC_REG(spien, dev->reg_base + SPIEN); + + ctrl = READ_ARC_REG(dev->reg_base + CTRL) & SPI_NDF_SET_MASK & + SPI_TMOD_SET_MASK; + ctrl |= (rx_cnt - 1) << 16; + if (tx_cnt == 0) { + ctrl |= (SPI_RX_ONLY << 8); + } else if (rx_cnt == 0) { + ctrl |= (SPI_TX_ONLY << 8); + } else { + ctrl |= (SPI_EPROM_RD << 8); + } + WRITE_ARC_REG(ctrl, dev->reg_base + CTRL); + + // Assert the slave-select and start the SPI transfer + WRITE_ARC_REG(spien | SPI_ENABLE, dev->reg_base + SPIEN); + + if (tx_cnt) + spi_transmit(dev, buf, tx_cnt, + !(rx_cnt)); // No wait for TX-RX transfers + else + WRITE_ARC_REG(SPI_PUSH_DATA | 0x56, + dev->reg_base + DR); // start rx-only transfert + + if (rx_cnt) + spi_receive(dev, buf, rx_cnt); + + // De-assert the slave-select and end the SPI transfer + WRITE_ARC_REG(0, dev->reg_base + SPIEN); + + return 0; +} diff --git a/libraries/CurieIMU/src/internal/ss_spi.h b/system/libarc32_arduino101/drivers/ss_spi.h similarity index 55% rename from libraries/CurieIMU/src/internal/ss_spi.h rename to system/libarc32_arduino101/drivers/ss_spi.h index f41d8f92..33c90c69 100644 --- a/libraries/CurieIMU/src/internal/ss_spi.h +++ b/system/libarc32_arduino101/drivers/ss_spi.h @@ -24,9 +24,24 @@ extern "C" { #endif -void ss_spi_init(); -void ss_spi_disable(); -int ss_spi_xfer(uint8_t *buf, unsigned tx_cnt, unsigned rx_cnt); +#include "common_spi.h" + +/** + * List of all controllers + */ +typedef enum { + SPI_SENSING_0, /* Sensing SPI controller 0, accessible by Sensor Subsystem Core only */ + SPI_SENSING_1 /* Sensing SPI controller 1, accessible by Sensor Subsystem Core only */ +} SPI_CONTROLLER; + +void ss_spi_init(SPI_CONTROLLER controller_id, uint32_t speed, + SPI_BUS_MODE mode, SPI_DATA_FRAME_SIZE data_frame_size, + SPI_SLAVE_ENABLE slave); +void ss_spi_disable(SPI_CONTROLLER controller_id); +int ss_spi_xfer(SPI_CONTROLLER controller_id, uint8_t *buf, unsigned tx_cnt, + unsigned rx_cnt); +void ss_spi_set_data_mode(SPI_CONTROLLER controller_id, uint8_t dataMode); +void ss_spi_set_clock_divider(SPI_CONTROLLER controller_id, uint8_t clockDiv); #ifdef __cplusplus } diff --git a/system/libarc32_arduino101/framework/include/cfw/cfw.h b/system/libarc32_arduino101/framework/include/cfw/cfw.h index 9c9f040f..311dcf7b 100644 --- a/system/libarc32_arduino101/framework/include/cfw/cfw.h +++ b/system/libarc32_arduino101/framework/include/cfw/cfw.h @@ -113,7 +113,7 @@ typedef struct svc_client_handle_ { * Passed in the conn field of struct cfw_message for request messages */ void * server_handle; -} svc_client_handle_t; +} svc_client_handle_t, cfw_service_conn_t; struct cfw_message * cfw_alloc_message(int size, OS_ERR_TYPE * err); diff --git a/system/libarc32_arduino101/framework/include/cfw/cfw_client.h b/system/libarc32_arduino101/framework/include/cfw/cfw_client.h index 2a1ae2ba..2154208f 100644 --- a/system/libarc32_arduino101/framework/include/cfw/cfw_client.h +++ b/system/libarc32_arduino101/framework/include/cfw/cfw_client.h @@ -40,22 +40,6 @@ * @{ */ -/** - * Create a handle to the component framework. - * This handle is to be used for all other requests - * to the component framework - * - * Implementation is different in the master and the slave contexts. - * The master context will be pseudo-synchronous, while the slave - * implementation will actually pass a message to the master context - * in order to register a new client. - * - * \param queue pointer to service queue - * \param cb the callback that will be called for each message reception - * \param param the param passed along with the message to the callback - */ -cfw_handle_t cfw_init(void * queue, handle_msg_cb_t cb, void * param); - /** * Allocate a request message for a service. diff --git a/system/libarc32_arduino101/framework/include/cfw_platform.h b/system/libarc32_arduino101/framework/include/cfw_platform.h index 4e361961..aa5cb29e 100644 --- a/system/libarc32_arduino101/framework/include/cfw_platform.h +++ b/system/libarc32_arduino101/framework/include/cfw_platform.h @@ -39,7 +39,6 @@ extern "C" { #endif void cfw_platform_init(void); -void cfw_platform_nordic_init(void); T_QUEUE cfw_get_service_queue(void); #ifdef __cplusplus diff --git a/system/libarc32_arduino101/framework/include/infra/ipc_uart.h b/system/libarc32_arduino101/framework/include/infra/ipc_uart.h index 5f5cbe76..6c8eab4f 100644 --- a/system/libarc32_arduino101/framework/include/infra/ipc_uart.h +++ b/system/libarc32_arduino101/framework/include/infra/ipc_uart.h @@ -78,25 +78,6 @@ /* optional sync frame payload */ #define SYNC_FRAME_DATA(_frame_) ((unsigned char *)&(_frame_)[20]) -#define IPC_CHANNEL_STATE_CLOSED 0 -#define IPC_CHANNEL_STATE_OPEN 1 - -#define IPC_UART_MAX_CHANNEL 4 - -struct ipc_uart_channels { - uint16_t index; - uint16_t state; - void (*cb) (uint8_t cpu_id, int chan, int len, void * data); -}; - -void * uart_ipc_channel_open(int channel, void(*cb)(uint8_t cpu_id, int chan, int len, void * data)); -int uart_ipc_send_message(void * handle, int len, void *p_data); -void uart_ipc_set_channel(void * ipc_channel); -void * uart_ipc_get_channel(void); -int uart_ipc_send_sync_resp(int channel, int request_id, int param1, int param2, void * ptr); -void uart_ipc_init(int num); -void uart_ipc_disable(int num); - /** @} */ #endif /* _IPC_UART_H_ */ diff --git a/system/libarc32_arduino101/framework/include/infra/log.h b/system/libarc32_arduino101/framework/include/infra/log.h index 528b0d99..07848310 100644 --- a/system/libarc32_arduino101/framework/include/infra/log.h +++ b/system/libarc32_arduino101/framework/include/infra/log.h @@ -36,6 +36,10 @@ #include #include +#ifdef __cplusplus +extern "C" { +#endif + /** * @defgroup infra_log Log * @ingroup infra @@ -260,7 +264,11 @@ void log_resume(); * @param module the ID of the log module related to this message * @param format the printf-like string format */ -#define pr_debug(module, format,...) pr_debug_ ## module(format, ##__VA_ARGS__) +#define pr_debug(module, format,...) log_printk(LOG_LEVEL_DEBUG, module, format, ##__VA_ARGS__) + +#ifdef __cplusplus +} +#endif /** @} */ diff --git a/system/libarc32_arduino101/framework/include/log_modules b/system/libarc32_arduino101/framework/include/log_modules index c7246635..401bbae9 100644 --- a/system/libarc32_arduino101/framework/include/log_modules +++ b/system/libarc32_arduino101/framework/include/log_modules @@ -25,3 +25,4 @@ DEFINE_LOGGER_MODULE(LOG_MODULE_DRV, "DRV", 0) DEFINE_LOGGER_MODULE(LOG_MODULE_CUNIT, "CUNIT", 0) DEFINE_LOGGER_MODULE(LOG_MODULE_CFW, "CFW", 0) DEFINE_LOGGER_MODULE(LOG_MODULE_GPIO_SVC, "GPIO_SVC", 0) +DEFINE_LOGGER_MODULE(LOG_MODULE_APP, "APP", 0) diff --git a/system/libarc32_arduino101/framework/include/panic_api.h b/system/libarc32_arduino101/framework/include/panic_api.h index 70aea89c..5a579280 100644 --- a/system/libarc32_arduino101/framework/include/panic_api.h +++ b/system/libarc32_arduino101/framework/include/panic_api.h @@ -29,5 +29,5 @@ */ // TODO - replace with a proper implementation of panic() -#define panic(x) _do_fault(); +//#define panic(x) _do_fault(); #define force_panic() panic(-1) diff --git a/system/libarc32_arduino101/framework/include/platform.h b/system/libarc32_arduino101/framework/include/platform.h index 86b70ae9..0bd3830b 100644 --- a/system/libarc32_arduino101/framework/include/platform.h +++ b/system/libarc32_arduino101/framework/include/platform.h @@ -145,6 +145,7 @@ unsigned int get_timestamp(void); typedef enum { SOC_I2C_0 = 0, /*!< General Purpose I2C controller 0, accessible by both processing entities */ SOC_I2C_1, /*!< General Purpose I2C controller 1, accessible by both processing entities */ + NUM_SOC_I2C /*!< Number of SOC I2C connections */ } SOC_I2C_CONTROLLER_PF; /* SPI */ diff --git a/system/libarc32_arduino101/framework/include/services/ble/ble_service.h b/system/libarc32_arduino101/framework/include/services/ble/ble_service.h index fa14941b..8917e61c 100644 --- a/system/libarc32_arduino101/framework/include/services/ble/ble_service.h +++ b/system/libarc32_arduino101/framework/include/services/ble/ble_service.h @@ -33,29 +33,205 @@ #include +/* For MSG_ID_BLE_SERVICE_BASE */ +#include "services/services_ids.h" + +/* For bt_uuid */ +#include "bluetooth/gatt.h" + +#include "bluetooth/bluetooth.h" + +#include "cfw/cfw.h" + +/* Forward declarations */ +struct _ble_service_cb; +struct bt_conn; + /** - * @addtogroup ble_service + * @cond + * @defgroup ble_service BLE Service + * + * Bluetooth Low Energy (BLE) application level service. + * + * This service provides BLE service, abstracting most of the complexity of the underlying BLE services/profiles. + * + * @ingroup services + * * @{ + */ + +/* + * CFW Message ID base definitions for BLE services. + */ + +/* BLE Service Message ID definitions. */ +#define MSG_ID_BLE_SERVICE_RSP (MSG_ID_BLE_SERVICE_BASE + 0x40) +#define MSG_ID_BLE_SERVICE_EVT (MSG_ID_BLE_SERVICE_BASE + 0x80) + +/** BLE High level Message IDs used for request, response, events. */ +enum BLE_MSG_ID { + MSG_ID_BLE_ENABLE_RSP = MSG_ID_BLE_SERVICE_RSP, /**< Message ID for enable response, of type @ref ble_enable_rsp */ + MSG_ID_BLE_INIT_SVC_RSP, /**< Message ID for init service response, of type @ref ble_init_svc_rsp */ + + /* BLE direct test mode command */ + MSG_ID_BLE_DBG_RSP, /**< Message ID for DTM command response, of type @ref ble_dbg_req_rsp */ + + MSG_ID_BLE_SERVICE_RSP_LAST, + + /* events */ + MSG_ID_BLE_ADV_TO_EVT = MSG_ID_BLE_SERVICE_EVT, /**< Message ID for struct @ref ble_adv_to_evt */ + MSG_ID_BLE_SERVICE_EVT_LAST +}; + +/** Macro to convert milliseconds to a specific unit */ +#define MSEC_TO_1_25_MS_UNITS(TIME) (((TIME) * 1000) / 1250) +#define MSEC_TO_10_MS_UNITS(TIME) ((TIME) / 10) + +#define BLE_GAP_SEC_RAND_LEN 8 /**< Random Security number length (64 bits) */ +#define BLE_GAP_SEC_MAX_KEY_LEN 16 /**< Maximum security key len (LTK, CSRK) */ + +/** + * Advertisement options. + */ +enum BLE_GAP_ADV_OPTIONS { + BLE_GAP_OPT_ADV_DEFAULT = 0, /**< no specific option */ + BLE_GAP_OPT_ADV_WHITE_LISTED = 0x02 /**< use white list and only report whitelisted devices */ +}; + +/** + * LE security modes. * + * see BT spec PART C, 10.2 + * + * - Security mode 1 + * - Level 1: No security at all (service may use data signing) + * - Level 2: Unauthenticated (no MITM protection pairing with encryption + * - Level 3: Authenticated (MITM protection) pairing with encryption + * - Level 4: Authenticated (MITM protection) LE Secure Connection wi + * + * - Security mode 2 (data signing) + * - Level 1: Unauthenticated pairing with data signing + * - Level 2: Authenticated (MITM protection) with data signing */ +enum BLE_GAP_SEC_MODES { + GAP_SEC_NO_PERMISSION = 0, /**< No access permitted. */ + GAP_SEC_LEVEL_1, + GAP_SEC_LEVEL_2, + GAP_SEC_LEVEL_3, + GAP_SEC_LEVEL_4, + GAP_SEC_MODE_1 = 0x10, + GAP_SEC_MODE_2 = 0x20 /**< only used for data signing, level 1 or 2 */ +}; -/** BLE response/event status codes. */ -enum BLE_STATUS { - BLE_STATUS_SUCCESS = 0, /**< General BLE Success code */ - BLE_STATUS_PENDING, /**< Request received and execution started, response pending */ - BLE_STATUS_TIMEOUT, /**< Request timed out */ - BLE_STATUS_NOT_SUPPORTED, /**< Request/feature/parameter not supported */ - BLE_STATUS_NOT_ALLOWED, /**< Request not allowed */ - BLE_STATUS_LINK_TIMEOUT, /**< Link timeout (link loss) */ - BLE_STATUS_NOT_ENABLED, /**< BLE not enabled, @ref ble_enable */ - BLE_STATUS_ERROR, /**< Generic Error */ - BLE_STATUS_ALREADY_REGISTERED, /**< BLE service already registered */ - BLE_STATUS_WRONG_STATE, /**< Wrong state for request */ - BLE_STATUS_ERROR_PARAMETER, /**< Parameter in request is wrong */ - BLE_STATUS_GAP_BASE = 0x100, /**< GAP specific error base */ - BLE_STATUS_GATT_BASE = 0x200, /**< GATT specific Error base */ +/** + * Security manager passkey type. + */ +enum BLE_GAP_SM_PASSKEY_TYPE { + BLE_GAP_SM_PK_NONE = 0, /**< No key (may be used to reject). */ + BLE_GAP_SM_PK_PASSKEY, /**< Security data is a 6-digit passkey. */ + BLE_GAP_SM_PK_OOB, /**< Security data is 16 bytes of OOB data */ }; -typedef uint16_t ble_status_t; /**< Response and event BLE service status type @ref BLE_STATUS */ +/** + * Connection Parameter update request event. + */ +struct ble_gap_conn_param_update_req_evt { + struct bt_le_conn_param param; +}; + +/* - BLE_SERVICE_GAP_API.H */ + + +/** Generic BLE status response message. */ +struct ble_rsp { + struct cfw_message header; /**< Component framework message header (@ref cfw), MUST be first element of structure */ + int status; /**< Response status */ +}; + +/** Generic BLE response with connection reference and status. */ +struct ble_conn_rsp { + struct cfw_message header; /**< Component framework message header (@ref cfw), MUST be first element of structure */ + struct bt_conn *conn; /**< Connection reference */ + int status; /**< Status */ +}; + +/** BLE Enable configuration options. */ +struct ble_enable_config { + bt_addr_le_t * p_bda; /**< Optional BT device address. If NULL, internal unique static random will be used */ + struct bt_le_conn_param central_conn_params; /**< Central supported range */ +}; + +/** Parameters of MSG_ID_BLE_ENABLE_RSP. */ +struct ble_enable_rsp { + struct cfw_message header; /**< Component framework message header (@ref cfw), MUST be first element of structure */ + int status; /**< Response status */ + uint8_t enable; /**< Enable state: 0:Disabled, 1:Enabled */ + bt_addr_le_t bd_addr; +}; + +/** + * Attribute handle range definition. + */ +struct ble_gatt_handle_range { + uint16_t start_handle; + uint16_t end_handle; +}; + +/** Parameters of the current connection. */ +struct ble_connection_values { + uint16_t interval; /**< Connection interval (unit 1.25 ms) */ + uint16_t latency; /**< Connection latency (unit interval) */ + uint16_t supervision_to; /**< Connection supervision timeout (unit 10ms)*/ +}; + +/** Parameters for @ref MSG_ID_BLE_INIT_SVC_RSP. */ +struct ble_init_svc_rsp { + struct cfw_message header; /**< Component framework message header (@ref cfw), MUST be first element of structure */ + int status; +}; + +/** Authentication data. */ +struct ble_auth_data { + union { + uint8_t passkey[6]; /**< 6 digit key (000000 - 999999) */ + uint8_t obb_data[16]; /**< 16 byte of OBB data */ + }; + uint8_t type; /**< @ref BLE_GAP_SM_PASSKEY_TYPE */ +}; + +/** Parameters for @ref MSG_ID_BLE_ADV_TO_EVT. */ +struct ble_adv_to_evt { + struct cfw_message header; /**< Component framework message header (@ref cfw), MUST be first element of structure */ +}; + +/** + * BLE debug rsp message. + */ + +/* + * BLE debug req message. + */ +struct ble_dbg_req_rsp { + struct cfw_message header; + uint32_t u0; + uint32_t u1; +}; + +/** Enable/Disable BLE stack. To be called before any BLE service related call. + * + * @param p_service_conn client service connection (cfw service connection) + * @param enable 1: enable BLE stack 0: disable BLE stack + * @param p_config configuration parameters when enabling BLE. shall be null in case of BLE disable. @ref ble_enable_config + * @param p_priv pointer to private structure returned in a response + * + * @return @ref OS_ERR_TYPE + * @note Expected notification: + * - Message with @ref MSG_ID_BLE_ENABLE_RSP and type @ref ble_enable_rsp. + */ +int ble_service_enable(cfw_service_conn_t * p_service_conn, uint8_t enable, + const struct ble_enable_config * p_config, + void *p_priv); + +/** @endcond */ /** @}*/ #endif diff --git a/system/libarc32_arduino101/framework/include/services/ble/ble_service_gap_api.h b/system/libarc32_arduino101/framework/include/services/ble/ble_service_gap_api.h deleted file mode 100644 index 6fd62cec..00000000 --- a/system/libarc32_arduino101/framework/include/services/ble/ble_service_gap_api.h +++ /dev/null @@ -1,1036 +0,0 @@ -/* - * Copyright (c) 2015, Intel Corporation. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its contributors - * may be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __BLE_SERVICE_GAP_H__ -#define __BLE_SERVICE_GAP_H__ - -#include "cfw/cfw.h" -#include "cfw/cfw_client.h" -#include "infra/version.h" -#include "ble_service_msg.h" -#include "ble_service.h" - -/** - * @defgroup ble_core_service BLE Core Service GAP/GATT APIs - * - * BLE Core service GAP/GATT APIs used by BLE service. - * - * @ingroup ble_service - * @{ - */ - -/** Macro to convert milliseconds to a specific unit */ -#define MSEC_TO_0_625_MS_UNITS(TIME) (((TIME) * 1000) / 625) -#define MSEC_TO_1_25_MS_UNITS(TIME) (((TIME) * 1000) / 1250) -#define MSEC_TO_10_MS_UNITS(TIME) ((TIME) / 10) - -/** - * BLE GAP Status return codes. - */ -enum BLE_SVC_GAP_STATUS_CODES { - BLE_SVC_GAP_STATUS_SUCCESS = BLE_STATUS_SUCCESS, /**< GAP success */ - BLE_SVC_GAP_STATUS_ERROR = BLE_STATUS_GATT_BASE, /**< Generic GAP error */ - BLE_SVC_GAP_STATUS_INVALID_UUID_LIST, /**< Invalid UUID list provided (e.g. advertisement) */ - /* TODO: add more status codes */ -}; - -/** - * BLE GAP addr types. - * - * BLE GAP supported address types - */ -enum BLE_ADDR_TYPES { - BLE_ADDR_PUBLIC = 0, /**< BD address assigned by IEEE */ - BLE_ADDR_PRIVATE_RANDOM_STATIC, /**< Random address */ - BLE_ADDR_RRIVATE_RANDOM_PRIVATE_RESOLVABLE, /**< Resolvable Private Random address */ - BLE_ADDR_PRIVATE_RANDOM_PRIVATE_NONRESOLVABLE /**< Non-resolvable Private Random address */ -}; - -/** - * BT/BLE address Length. - */ -#define BLE_ADDR_LEN 6 - -#define BLE_GAP_SEC_RAND_LEN 8 /**< Random Security number length (64 bits) */ -#define BLE_GAP_SEC_MAX_KEY_LEN 16 /**< Maximum security key len (LTK, CSRK) */ - -#define BLE_SVC_GAP_HANDLE_INVALID 0xffff /**< Invalid GAP connection handle */ - -/** - * Device GAP name characteristic write permission. - * - * If the characteristic shall be writable, use a combination of the values - * defined in @ref BLE_GAP_SEC_MODES - */ -#define BLE_DEVICE_NAME_WRITE_PERM GAP_SEC_NO_PERMISSION - -typedef struct { - uint8_t type; /**< BLE Address type @ref BLE_ADDR_TYPES */ - uint8_t addr[BLE_ADDR_LEN]; - /**< BD address, little endian format */ -} ble_addr_t; - -/** - * GAP device roles. - */ -enum BLE_ROLES { - BLE_ROLE_INVALID = 0, - BLE_ROLE_PERIPHERAL = 0x01, - BLE_ROLE_CENTRAL = 0x02 -}; - -typedef uint8_t ble_role_t; - -/** - * BLE core (GAP, GATT) Message IDs used for request, response, events and indications. - */ -enum BLE_GAP_MSG_ID { - MSG_ID_BLE_GAP_WR_CONF_REQ = MSG_ID_BLE_GAP_BASE, - MSG_ID_BLE_GAP_RD_BDA_REQ, - MSG_ID_BLE_GAP_WR_ADV_DATA_REQ, - MSG_ID_BLE_GAP_WR_WHITE_LIST_REQ, - MSG_ID_BLE_GAP_CLR_WHITE_LIST_REQ, - MSG_ID_BLE_GAP_ENABLE_ADV_REQ, - MSG_ID_BLE_GAP_DISABLE_ADV_REQ, - MSG_ID_BLE_GAP_CONN_UPDATE_REQ, - MSG_ID_BLE_GAP_DISCONNECT_REQ, - MSG_ID_BLE_GAP_SERVICE_WRITE_REQ, - MSG_ID_BLE_GAP_SERVICE_READ_REQ, - MSG_ID_BLE_GAP_SM_CONFIG_REQ, - MSG_ID_BLE_GAP_SM_PAIRING_REQ, - MSG_ID_BLE_GAP_SM_PASSKEY_REQ, - MSG_ID_BLE_GAP_SET_RSSI_REPORT_REQ, - MSG_ID_BLE_GAP_SCAN_START_REQ, - MSG_ID_BLE_GAP_SCAN_STOP_REQ, - MSG_ID_BLE_GAP_CONNECT_REQ, - MSG_ID_BLE_GAP_CONNECT_CANCEL_REQ, - MSG_ID_BLE_GAP_SET_OPTIONS_REQ, - MSG_ID_BLE_GAP_GENERIC_CMD_REQ, - MSG_ID_BLE_GAP_GET_VERSION_REQ, - MSG_ID_BLE_GAP_DTM_INIT_REQ, - MSG_ID_BLE_CTRL_LOG_REQ, - MSG_ID_BLE_GAP_REQ_LAST, - - /** BLE GAP Response Messages IDs. */ - MSG_ID_BLE_GAP_WR_CONF_RSP = MSG_ID_BLE_GAP_RSP, - /**< Write controller config: own Bluetooth Device Address, tx power */ - MSG_ID_BLE_GAP_RD_BDA_RSP, /**< Read own Bluetooth Device Address */ - MSG_ID_BLE_GAP_WR_ADV_DATA_RSP, /**< Write Advertising Data and Scan response data */ - MSG_ID_BLE_GAP_WR_WHITE_LIST_RSP, /**< Write white list to controller */ - MSG_ID_BLE_GAP_CLR_WHITE_LIST_RSP, /**< Clear current white list */ - MSG_ID_BLE_GAP_ENABLE_ADV_RSP, /**< Enable Advertising */ - MSG_ID_BLE_GAP_DISABLE_ADV_RSP, /**< Disable Advertising */ - MSG_ID_BLE_GAP_CONN_UPDATE_RSP, /**< Update Connection */ - MSG_ID_BLE_GAP_DISCONNECT_RSP, /**< Disconnect */ - MSG_ID_BLE_GAP_SERVICE_WRITE_RSP, /**< Write GAP Service specific like device name, appearance and PPCPparameters */ - MSG_ID_BLE_GAP_SERVICE_READ_RSP, /**< Read GAP Service specific like device name, appearance and PPCPparameters */ - MSG_ID_BLE_GAP_SM_CONFIG_RSP, /**< Response to @ref ble_gap_sm_config */ - MSG_ID_BLE_GAP_SM_PAIRING_RSP, /**< Response to @ref ble_gap_sm_pairing_req */ - MSG_ID_BLE_GAP_SM_PASSKEY_RSP, /**< Response to @ref ble_gap_sm_passkey_reply */ - MSG_ID_BLE_GAP_SET_RSSI_REPORT_RSP, /**< Enable/Disable reporting of changes in RSSI */ - MSG_ID_BLE_GAP_SCAN_START_RSP, /**< Start Scanning */ - MSG_ID_BLE_GAP_SCAN_STOP_RSP, /**< Stop Scanning */ - MSG_ID_BLE_GAP_CONNECT_RSP, /**< Start Connection procedure */ - MSG_ID_BLE_GAP_CONNECT_CANCEL_RSP, /**< Cancel ongoing connection procedure */ - MSG_ID_BLE_GAP_SET_OPTIONS_RSP, /**< Set gap options (e.g. co-ex, master/central role) */ - MSG_ID_BLE_GAP_GENERIC_CMD_RSP, /**< Generic non connection related requests */ - MSG_ID_BLE_GAP_GET_VERSION_RSP, - MSG_ID_BLE_GAP_DTM_INIT_RSP, - MSG_ID_BLE_CTRL_LOG_RSP, /**< BLE controller logging message */ - MSG_ID_BLE_GAP_RSP_LAST, - - /** GAP related events. */ - MSG_ID_BLE_GAP_CONNECT_EVT = MSG_ID_BLE_GAP_EVT, /**< Connection established */ - MSG_ID_BLE_GAP_DISCONNECT_EVT, /**< Disconnect from peer */ - MSG_ID_BLE_GAP_CONN_UPDATE_EVT, /**< Connection Parameters update event (in central, they have been updated, in peripheral, also includes the status of the request) */ - MSG_ID_BLE_GAP_SM_PAIRING_STATUS_EVT, /**< Pairing request status event */ - MSG_ID_BLE_GAP_SM_PASSKEY_REQ_EVT, /**< Pairing passkey request (6 digits or 16 byte OOB data) */ - MSG_ID_BLE_GAP_TO_EVT, /**< GAP Timeout event */ - MSG_ID_BLE_GAP_ADV_DATA_EVT, /**< Advertising raw data event (central role) */ - MSG_ID_BLE_GAP_RSSI_EVT, /**< Signal strength change event */ - MSG_ID_BLE_GAP_GENERIC_CMD_EVT, /**< Generic command request event */ - MSG_ID_BLE_CTRL_LOG_EVT, /**< BLE Controller Logging Events */ - MSG_ID_BLE_GAP_EVT_LAST, -}; - -/** - * Generic BLE Status Response. - * Short status response for commands not returning any additional data - */ -struct ble_rsp { - struct cfw_message header; /**< Component framework message header (@ref cfw), MUST be first element of structure */ - ble_status_t status; /**< Response status @ref BLE_STATUS */ -}; - -/** - * Connection requested parameters. - */ -struct ble_gap_connection_params { - uint16_t interval_min; /**< minimal connection interval: range 0x0006 to 0x0c80 (unit 1.25ms) */ - uint16_t interval_max; /**< maximum connection interval: range 0x0006 to 0x0c80 must be bigger then min! */ - uint16_t slave_latency; /**< maximum connection slave latency: 0x0000 to 0x01f3 */ - uint16_t link_sup_to; /**< link supervision timeout: 0x000a to 0x0c80 (unit 10ms) */ -}; - -/** - * Connection values. - */ -struct ble_gap_connection_values { - uint16_t interval; /**< Connection interval (unit 1.25 ms) */ - uint16_t latency; /**< Connection latency (unit interval) */ - uint16_t supervision_to; /**< Connection supervision timeout (unit 10ms)*/ -}; - -/** - * Initial GAP configuration - */ -struct ble_wr_config { - ble_addr_t *p_bda; - uint8_t *p_name; /**< GAP Device name, NULL terminated! */ - uint16_t appearance; /**< see BLE spec */ - int8_t tx_power; - struct ble_gap_connection_params peripheral_conn_params; /**< Peripheral preferred */ - struct ble_gap_connection_params central_conn_params; /**< Central supported range */ -}; - -/** Read BD address response. */ -typedef struct { - struct cfw_message header; /**< Component framework message header (@ref cfw), MUST be first element of structure */ - ble_status_t status; /**< Response status @ref BLE_STATUS */ - ble_addr_t bd; /**< if status ok @ref ble_addr_t */ -} ble_bda_rd_rsp_t; - -struct ble_gap_adv_rsp_data { - uint8_t *p_data; /**< max 31 bytes! */ - uint8_t len; -}; - -/** - * Advertising types, see BT spec vol 6, Part B, chapter 2.3. - */ -enum GAP_ADV_TYPES { - ADV_IND = 0x00, /**< Connectable undirected advertising */ - ADV_DIRECT_IND = 0x01, /**< Connectable high duty cycle advertising */ - ADV_NONCONN_IND = 0x02, /**< Non connectable undirected advertising */ - ADV_SCAN_IND = 0x06, /**< Scannable undirected advertising */ - ADV_SCAN_RSP = 0x81, /**< Scan response, only a return value in @ref ble_gap_adv_data_evt_t */ - ADV_RESERVED /* keep last */ -}; - -typedef struct { - uint8_t irk[BLE_GAP_SEC_MAX_KEY_LEN]; - /**< Identity Resolving Key (IRK) */ -} ble_gap_irk_info_t; - -struct ble_gap_whitelist_info { - ble_addr_t **pp_bd; /**< list of bd addresses */ - ble_gap_irk_info_t **pp_key; /**< list of irk keys (for address resolution offload) */ - uint8_t bd_count; /**< number of bd addresses */ - uint8_t key_count; /**< number of keys */ -}; - -/** - * Advertisement options. - */ -enum BLE_GAP_ADV_OPTIONS { - BLE_GAP_OPT_ADV_DEFAULT = 0, /**< no specific option */ - BLE_GAP_OPT_ADV_WHITE_LISTED = 0x02 /**< use white list and only report whitelisted devices */ -}; - -/** - * Advertisement parameters. - */ -typedef struct { - uint16_t timeout; - uint16_t interval_min; /**< min interval 0xffff: use default 0x0800 */ - uint16_t interval_max; /**< max interval 0xffff: use default 0x0800 */ - uint8_t type; /**< advertisement types @ref GAP_ADV_TYPES */ - uint8_t filter_policy; /**< filter policy to apply with white list */ - ble_addr_t *p_peer_bda; /**< bd address of peer device in case of directed advertisement */ - uint8_t options; /**< options see @ref BLE_GAP_ADV_OPTIONS (to be ORed) */ -} ble_gap_adv_param_t; - -/** - * Generic BLE Status. Response - * Short status response for commands not returning any additional data - */ -typedef struct { - struct cfw_message header; /**< Component framework message header (@ref cfw), MUST be first element of structure */ - ble_status_t status; /**< Response status @ref BLE_STATUS */ - uint32_t wl_handle; /**< reference handle. to be used for clearing it later */ -} ble_gap_wr_white_list_rsp_t; - - -/** - * Appearance read response message. - */ -typedef struct { - struct cfw_message header; /**< Component framework message header (@ref cfw), MUST be first element of structure */ - ble_status_t status; /**< Response status @ref BLE_STATUS */ - uint16_t uuid; /**< value of GAP appearance characteristic */ -} ble_rd_appearance_rsp_t; - -/** - * LE security modes. - * - * see BT spec PART C, 10.2 - * - * - Security mode 1 - * - Level 1: No security at all (service may use data signing) - * - Level 2: Unauthenticated (no MITM protection pairing with encryption - * - Level 3: Authenticated (MITM protection) pairing with encryption - * - Level 4: Authenticated (MITM protection) LE Secure Connection wi - * - * - Security mode 2 (data signing) - * - Level 1: Unauthenticated pairing with data signing - * - Level 2: Authenticated (MITM protection) with data signing - */ -enum BLE_GAP_SEC_MODES { - GAP_SEC_NO_PERMISSION = 0, /**< No access permitted. */ - GAP_SEC_LEVEL_1, - GAP_SEC_LEVEL_2, - GAP_SEC_LEVEL_3, - GAP_SEC_LEVEL_4, - GAP_SEC_MODE_1 = 0x10, - GAP_SEC_MODE_2 = 0x20 /**< only used for data signing, level 1 or 2 */ -}; - -struct ble_gap_svc_local_name { - uint8_t sec_mode; /**< security mode for writing device name, @ref BLE_GAP_SEC_MODES */ - uint8_t authorization; /**< 0: no authorization, 1: authorization required */ - uint8_t len; /**< device name length (0-248) */ - const uint8_t *p_name; /**< name to to write */ -}; - -enum BLE_GAP_SVC_ATTR_TYPE { - GAP_SVC_ATTR_NAME = 0, /**< Device Name, UUID 0x2a00 */ - GAP_SVC_ATTR_APPEARANCE, /**< Appearance, UUID 0x2a01 */ - GAP_SVC_ATTR_PPCP = 4, /**< Peripheral Preferred Connection Parameters (PPCP), UUID 0x2a04 */ - GAP_SVC_ATTR_CAR = 0xa6, /**< Central Address Resolution (CAR), UUID 0x2aa6, BT 4.2 */ -}; - -struct ble_gap_service_write_params { - uint16_t attr_type; /**< GAP Characteristics attribute type @ref BLE_GAP_SVC_ATTR_TYPE */ - union { - struct ble_gap_svc_local_name name; - uint16_t appearance; /**< Appearance UUID */ - struct ble_gap_connection_params conn_params; - /**< Preferred Peripheral Connection Parameters */ - uint8_t car; /**< Central Address Resolution support 0: no, 1: yes */ - }; -}; - -struct ble_gap_service_read_rsp { - struct cfw_message header; /**< Component framework message header (@ref cfw), MUST be first element of structure */ - ble_status_t status; /**< status of read operation @ref BLE_STATUS, in case failure union shall be empty */ - uint16_t attr_type; /**< type of attribute returned (valid even in failure case! */ - union { - struct ble_gap_svc_local_name name; - uint16_t appearance; /**< Appearance UUID */ - struct ble_gap_connection_params conn_params; /**< Preferred Peripheral Connection Parameters */ - uint8_t car; /** Central Address Resolution support 0: no, 1: yes */ - }; -}; - -/** - * GAP security manager options for bonding/authentication procedures, see Vol 3: Part H, 3.5. - */ -enum BLE_GAP_SM_OPTIONS { - BLE_GAP_BONDING = 0x01, /**< SMP supports bonding */ - BLE_GAP_MITM = 0x04, /**< SMP requires Man In The Middle protection */ - BLE_GAP_OOB = 0x08 /**< SMP supports Out Of Band data */ -}; - -/** - * IO capabilities, see Vol 3: PART H, 3.5. - */ -enum BLE_GAP_IO_CAPABILITIES { - BLE_GAP_IO_DISPLAY_ONLY = 0, - BLE_GAP_IO_DISPLAY_YESNO = 1, - BLE_GAP_IO_KEYBOARD_ONLY = 2, - BLE_GAP_IO_NO_INPUT_NO_OUTPUT = 3, - BLE_GAP_IO_KEYBOARD_DISPLAY = 4 -}; - -/** - * Security manager configuration parameters. - * - * options and io_caps will define there will be a passkey request or not. - * It is assumed that io_caps and options are compatible. - */ -struct ble_gap_sm_config_params { - uint8_t options; /**< Security options (@ref BLE_GAP_SM_OPTIONS) */ - uint8_t io_caps; /**< I/O Capabilities to allow passkey exchange (@ref BLE_GAP_IO_CAPABILITIES) */ - uint8_t key_size; /**< Maximum encryption key size (7-16) */ -}; - -/** - * Security manager pairing parameters. - */ -struct ble_gap_sm_pairing_params { - uint8_t auth_level; /**< authentication level see @ref BLE_GAP_SM_OPTIONS */ -}; - -/** - * Security manager passkey type. - */ -enum BLE_GAP_SM_PASSKEY_TYPE { - BLE_GAP_SM_PASSKEY = 0, /**< Security data is a passkey. */ - BLE_GAP_SM_OBB, /**< Security data is 16 bytes of OOB data */ -}; -/** - * Security reply to incoming security request. - */ -struct ble_gap_sm_passkey { - uint8_t type; /**< Security data type in this reply @ref BLE_GAP_SM_PASSKEY_TYPE */ - union { - uint8_t passkey[6]; /**< 6 digits (string) */ - uint8_t oob[16]; /**< 16 bytes of OOB security data */ - }; -}; - -/** - * RSSI operation definition. - */ -enum BLE_GAP_RSSI_OPS { - BLE_GAP_RSSI_DISABLE_REPORT = 0, - BLE_GAP_RSSI_ENABLE_REPORT -}; - -enum BLE_GAP_SCAN_OPTIONS { - BLE_GAP_SCAN_DEFAULT = 0, /**< no specific option */ - BLE_GAP_SCAN_ACTIVE = 0x01, /**< do an active scan (request scan response */ - BLE_GAP_SCAN_WHITE_LISTED = 0x02 /**< Use white list and only report whitelisted devices */ -}; - -enum BLE_GAP_SET_OPTIONS { - BLE_GAP_SET_CH_MAP = 0, /**< Set channel map */ -}; - -typedef struct { - uint16_t conn_handle; /**< connection on which to change channel map */ - uint8_t map[5]; /**< 37 bits are used of the 40 bits (LSB) */ -} ble_gap_channel_map_t; - -/** - * GAP option data structure. - */ -typedef union { - ble_gap_channel_map_t ch_map; /**< BLE channel map to set see BT spec */ -} ble_gap_option_t; - -/** - * Scan parameters. - * - * @note Check BT core spec for high low duty cycle interval & window size! - */ -typedef struct { - uint16_t timeout; /**< scan timeout in s, 0 never */ - uint16_t interval; /**< interval: 0x4 - 0x4000. (unit: 0.625ms), use default: 0xffff (0x0010) */ - uint16_t window; /**< Window: 0x4 - 0x4000. (unit: 0.625ms), use default 0xffff (= 0x0010) */ - uint8_t options; /**< scan options, ORed options from @ref BLE_GAP_SCAN_OPTIONS */ -} ble_gap_scan_param_t; - -/** - * Connect event @ref MSG_ID_BLE_GAP_CONNECT_EVT. - */ -struct ble_gap_connect_evt { - struct ble_gap_connection_values conn_values; /**< Connection values */ - uint8_t role; /**< role in this connection @ref */ - ble_addr_t peer_bda; /**< address of peer device */ -}; - -/** - * Disconnect event @ref MSG_ID_BLE_GAP_DISCONNECT_EVT. - */ -struct ble_gap_disconnected_evt { - uint8_t hci_reason; /**< HCI disconnect reason */ -}; - -/** - * Updated connection event @ref MSG_ID_BLE_GAP_CONN_UPDATE_EVT. - */ -struct ble_gap_conn_update_evt { - struct ble_gap_connection_values conn_values; -}; - -/** - * Security manager pairing status event @ref MSG_ID_BLE_GAP_SM_PAIRING_STATUS_EVT. - */ -struct ble_gap_sm_pairing_status_evt { - uint16_t conn_handle; - uint16_t status; -}; - -/** - * Security manager passkey request event @ref MSG_ID_BLE_GAP_SM_PASSKEY_REQ_EVT. - */ -struct ble_gap_sm_passkey_req_evt { - uint8_t dummy; -}; - -/** - * GAP/SMP security result status code. - * see Vol 3: Part H, chapter 3.5.5. - */ -enum BLE_GAP_SEC_RESULT_STATUS { - BLE_GAP_SEC_STATUS_SUCCESS = 0, - /**< bonding/pairing completed successfully */ - BLE_GAP_SEC_STATUS_PASSKEY_ENTRY_FAILED,/**< passkey entry failed */ - BLE_GAP_SEC_STATUS_OOB_NOT_AVAILABLE, /**< Out of Band data is not available */ - BLE_GAP_SEC_STATUS_AUTH_REQUIREMENTS, /**< Authentication requirements not met due to IO cap */ - BLE_GAP_SEC_STATUS_CONFIRM_VALUE, /**< Confirm value does not match calculated value */ - BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPPORTED, - /**< Pairing not supported by the device */ - BLE_GAP_SEC_STATUS_ENC_KEY_SIZE, /**< Encryption key size insufficient */ - BLE_GAP_SEC_STATUS_SMP_CMD_UNSUPPORTED, /**< Unsupported SMP command on this device */ - BLE_GAP_SEC_STATUS_UNSPECIFIED, /**< Failure due to unspecified reason */ - BLE_GAP_SEC_STATUS_REPEATED_ATTEMPTS, /**< Pairing/authent disallowed due to too little time elapsed since last attempt */ - BLE_GAP_SEC_STATUS_INVALID_PARAMS, /**< Invalid parameters due to length or parameters */ - /* 4.2 spec only ? */ - BLE_GAP_SEC_STATUS_DHKEY_CHECK_FAILED, /**< Remote device indicates that DHKey does not match local calculated key */ - BLE_GAP_SEC_STATUS_NUMERIC_COMP_FAILED, /**< values in numeric key comparison protocol do not match */ - BLE_GAP_SEC_STATUS_BREDR_PAIRING_INPROGRESS,/**< Failure due to BR/EDR pairing request */ - BLE_GAP_SEC_STATUS_CROSS_TSPRT_KEY_GEN_DIS, - /**< BR/EDR link key generation can not be use for LE keys handling */ -}; - -enum BLE_SVC_GAP_TIMEOUT_REASON { - BLE_SVC_GAP_TO_ADV, /**< Advertisement Stopped. */ - BLE_SVC_GAP_TO_SEC_REQ, /**< Security Request took too long. */ - BLE_SVC_GAP_TO_SCAN, /**< Scanning stopped. */ - BLE_SVC_GAP_TO_CONN, /**< Connection Link timeout. */ -}; - -/** - * GAP timeout event (e.g. protocol error) MSG_ID_BLE_GAP_TO_EVT. - */ -struct ble_gap_timout_evt { - int reason; /**< reason for timeout @ref BLE_SVC_GAP_TIMEOUT_REASON */ -}; - -/** - * Advertisement data structure (central role) @ref MSG_ID_BLE_GAP_ADV_DATA_EVT. - */ -struct ble_gap_adv_data_evt { - ble_addr_t remote_bda; /**< address of remote device */ - int8_t rssi; /**< signal strength compared to 0 dBm */ - uint8_t type; /**< type of advertisement data or scan response @ref GAP_ADV_TYPES */ - uint8_t len; /**< length of advertisement data or scap response data */ - uint8_t data[]; /**< Advertisement or scan response data */ -}; - -/** - * Connection Parameter update request event @ref MSG_ID_BLE_GAP_CONN_PARAM_UPDATE_REQ_EVT. - * - * @note reply with @ref ble_gap_conn_update_params - */ -struct ble_gap_conn_param_update_req_evt { - struct ble_gap_connection_params param; -}; - -/** - * RSSI signal strength event @ref MSG_ID_BLE_GAP_RSSI_EVT. - */ -struct ble_gap_rssi_evt { - int8_t rssi_lvl; /**< RSSI level (compared to 0 dBm) */ -}; - -/** - * RSSI report parameters @ref MSG_ID_BLE_GAP_SET_RSSI_REPORT_REQ. - */ -struct rssi_report_params { - uint16_t conn_hdl; /**< Connection handle */ - uint8_t op; /**< RSSI operation @ref BLE_GAP_RSSI_OPS */ - uint8_t delta_dBm; /**< minimum RSSI dBm change to report a new RSSI value */ - uint8_t min_count; /**< number of delta_dBm changes before sending a new RSSI report */ -}; - -/** Test Mode opcodes. */ -enum TEST_OPCODE { - BLE_TEST_INIT_DTM = 0x01, /**< Put BLE controller in HCI UART DTM test mode */ - BLE_TEST_START_DTM_RX = 0x1d, /**< LE receiver test HCI opcode */ - BLE_TEST_START_DTM_TX = 0x1e, /**< LE transmitter test HCI opcode */ - BLE_TEST_END_DTM = 0x1f, /**< End LE DTM TEST */ - /* vendor specific commands start at 0x80 */ - BLE_TEST_SET_TXPOWER = 0x80, /**< Set Tx power. To be called before start of tx test */ - BLE_TEST_START_TX_CARRIER, /**< Start Tx Carrier Test */ -}; - -/** - * Rx direct test mode data structure. - */ -struct ble_dtm_rx_test { - uint8_t freq; /**< rf channel 0x00 - 0x27, resulting F = 2402 MHz + [freq * 2 MHz] */ -}; - -/** - * Tx direct test mode data structure - */ -struct ble_dtm_tx_test { - uint8_t freq; /**< rf channel 0x00 - 0x27 where resulting F = 2402 + [freq * 2 MHz] */ - uint8_t len; /**< length of test data payload for each packet */ - uint8_t pattern; /**< packet payload pattern type, 0x00 - 0x02 mandatory */ -}; - -/** - * Tx power settings data structure. - */ -struct ble_set_txpower { - int8_t dbm; /**< Tx power level to set (e.g. -30: -30 dBm). Depends on BLE Controller */ -}; - -/** - * RX test result data. - */ -struct ble_dtm_test_result { - uint16_t mode; - uint16_t nb; -}; - -/** - * Direct Test mode command params - */ -struct ble_test_cmd { - uint8_t mode; /**< test mode to execute @ref TEST_OPCODE */ - union { - struct ble_dtm_rx_test rx; - struct ble_dtm_tx_test tx; - struct ble_set_txpower tx_pwr; /**< Tx power to use for Tx tests. */ - }; -}; - -/** - * BLE GAP event structure. - */ -struct ble_gap_event { - struct cfw_message header; /**< Component framework message header (@ref cfw), MUST be first element of structure */ - uint16_t conn_handle; /**< connection handle */ - union { - struct ble_gap_connect_evt connected; /**< connected event parameters */ - struct ble_gap_disconnected_evt disconnected; /**< disconnected reason */ - struct ble_gap_conn_update_evt conn_updated; /**< connection updated */ - struct ble_gap_sm_pairing_status_evt sm_pairing_status; /**< Security Manager pairing status */ - struct ble_gap_sm_passkey_req_evt sm_passkey_req; /**< Security Manager passkey request */ - /**< connection related security update */ - struct ble_gap_timout_evt timeout; /**< gap timeout occurred */ - struct ble_gap_adv_data_evt adv_data; /**< advertisement data */ - struct ble_gap_conn_param_update_req_evt conn_param_req; - /**< update request from remote for connection parameters */ - struct ble_gap_rssi_evt rssi; /**< new rssi level if rssi reporting is enabled */ - }; -}; - -/** Generic request op codes. - * This allows to access some non connection related commands like DTM. - */ -enum BLE_GAP_GEN_OPS { - DUMMY_VALUE = 0, /**< Not used now. */ -}; - -/** - * Generic command parameters. - * - * @note Independent of connection! - */ -struct ble_gap_gen_cmd_params { - uint8_t op_code; /**< @ref BLE_GAP_GEN_OPS */ -}; - -struct ble_version_msg { - struct cfw_message header; /**< Component framework message header (@ref cfw), MUST be first element of structure */ - ble_status_t status; - struct version_header version; /**< Nordic version header */ -}; - -struct ble_dtm_init_msg { - struct cfw_message header; /**< Component framework message header (@ref cfw), MUST be first element of structure */ - ble_status_t status; -}; - -struct ble_dtm_result_msg { - struct cfw_message header; /**< Component framework message header (@ref cfw), MUST be first element of structure */ - ble_status_t status; - struct ble_dtm_test_result result; /**< Result data of DTM RX test */ -}; - -/** - * Generic request message response or event. - */ -struct ble_generic_msg { - struct cfw_message header; /**< Component framework message header (@ref cfw), MUST be first element of structure */ - ble_status_t status; - uint8_t op_code; /**< Opcode to which this message is applicable @ref BLE_GAP_GEN_OPS */ -}; - -/** - * Set Enable configuration parameters (BD address, etc). - * - * This shall put the controller stack into a usable (enabled) state. - * Hence this should be called first! - * - * @param p_svc_handle service handle - * @param p_config BLE write configuration - * @param p_priv pointer to private data - * - * @return @ref OS_ERR_TYPE - * @return MSG_ID_BLE_GAP_WR_CONF_RSP @ref ble_rsp, TODO: return maybe more info? - */ -int ble_gap_set_enable_config(svc_client_handle_t * p_svc_handle, - const struct ble_wr_config * p_config, void *p_priv); - -/** - * Read BD address from Controller. - * - * - * @param p_svc_handle service handle - * @param p_priv pointer to private data - * - * @return @ref OS_ERR_TYPE - * @return MSG: @ref MSG_ID_BLE_GAP_RD_BDA_RSP @ref ble_bda_rd_rsp_t - */ -int ble_gap_read_bda(svc_client_handle_t * p_svc_handle, void *p_priv); - -/** - * Write Advertisement data to BLE controller. - * - * Store advertisement data in BLE controller. It needs to be done BEFORE starting advertisement - * - * @param p_svc_handle service handle - * @param p_adv_data adv data to store in BLE controller - * @param p_scan_data scan response data to store in controller, can be NULL - * @param p_priv pointer to private data - * - * @return @ref OS_ERR_TYPE, - * @return MSG: MSG_ID_BLE_GAP_WR_ADV_DATA_RSP @ref ble_rsp - */ -int ble_gap_wr_adv_data(svc_client_handle_t * p_svc_handle, - const struct ble_gap_adv_rsp_data * p_adv_data, - const struct ble_gap_adv_rsp_data * p_scan_data, - void *p_priv); - -/** - * Write white list to the BLE controller. - * - * Store white in BLE controller. It needs to be done BEFORE starting advertisement or - * start scanning - * - * @param p_svc_handle service handle - * @param p_white_list white list to store in the controller - * @param p_priv pointer to private data - * - * @return @ref OS_ERR_TYPE, - * @return MSG: MSG_ID_BLE_GAP_WR_WHITE_LIST @ref ble_gap_wr_white_list_rsp_t - */ -int ble_gap_wr_white_list(svc_client_handle_t * p_svc_handle, - const struct ble_gap_whitelist_info * p_white_list, - void *p_priv); - -/** - * Clear previously stored white list. - * - * @param p_svc_handle service handle - * @param wl_handle handle to the white list previously stored - * @param p_priv pointer to private data - * - * @return @ref OS_ERR_TYPE - * @return MSG: MSG_ID_BLE_GAP_CLR_WHITE_LIST @ref ble_rsp - */ -int ble_gap_clr_white_list(svc_client_handle_t * p_svc_handle, - uint32_t wl_handle, void *p_priv); - -/** - * Start advertising. - * - * @param p_svc_handle service handle - * @param p_adv_param advertisement - * @param p_priv pointer to private data - * - * @return @ref OS_ERR_TYPE - * @return MSG: MSG_ID_BLE_GAP_ENABLE_ADV @ref ble_rsp - */ -int ble_gap_start_advertise(svc_client_handle_t * p_svc_handle, - const ble_gap_adv_param_t * p_adv_param, - void *p_priv); - -/** - * Stop advertising. - * - * @param p_svc_handle service handle - * @param p_priv pointer to private data - * - * @return @ref OS_ERR_TYPE - * @return MSG: MSG_ID_BLE_GAP_DISABLE_ADV @ref ble_rsp - */ -int ble_gap_stop_advertise(svc_client_handle_t * p_svc_handle, void *p_priv); - -/** - * Update connection. - * - * This function's behavior depends on the role of the connection: - * - in peripheral mode, it sends an L2CAP signaling connection parameter - * update request based the values in @ref p_conn_param - * and the action can be taken by the central at link layer - * - in central mode, it will send a link layer command to change the - * connection values based on the values in @ref p_conn_param where the - * connection interval is interval_min - * - * When the connection is updated, the event @ref MSG_ID_BLE_GAP_CONN_UPDATE_EVT will - * be received. - * - * @param conn_handle Connection handle - * @param p_conn_param Connection parameters - * @param p_priv pointer to private data - * - * @return @ref OS_ERR_TYPE - * @return MSG: @ref MSG_ID_BLE_GAP_CONN_UPDATE_RSP @ref ble_rsp - */ -int ble_gap_conn_update(svc_client_handle_t * p_svc_handle, - uint16_t conn_handle, - const struct ble_gap_connection_params * p_conn_param, - void *p_priv); - -/** - * Disconnect connection (peripheral or central role). - * - * @param p_svc_handle service handle - * @param conn_hhdl connection to terminate - * @param reason HCI reason for connection termination, most often 0x16 (connection terminated by local host) - * @param p_priv pointer to private data - * - * @return @ref OS_ERR_TYPE - * @return MSG: MSG_ID_BLE_GAP_DISCONNECT @ref ble_rsp, MSG_ID_BLE_GAP_DISCONNECT_EVT @ref ble_gap_disconnected_evt_t - */ -int ble_gap_disconnect(svc_client_handle_t * p_svc_handle, - uint16_t conn_hhdl, uint8_t reason, - void *p_priv); -/** - * Write GAP Service Attribute Characteristics. - * - * @param p_svc_handle service handle - * @param p_params data of characteristic to write - * @param p_priv pointer to private data - * - * @return @ref OS_ERR_TYPE - * @return MSG: MSG_ID_BLE_GAP_SERVICE_WRITE_RSP @ref ble_rsp - */ -int ble_gap_service_write(svc_client_handle_t * p_svc_handle, - const struct ble_gap_service_write_params * p_params, - void *p_priv); - -/** - * Read GAP Service Characteristics. - * - * @param p_svc_handle service handle - * @param type type of GAP service data characteristic to read @ref BLE_GAP_SVC_ATTR_TYPE - * @param p_priv pointer to private data - * - * @return @ref OS_ERR_TYPE, - * @return MSG: MSG_ID_BLE_GAP_SERVICE_READ_RSP @ref ble_gap_service_read_rsp - */ -int ble_gap_service_read(svc_client_handle_t * p_svc_handle, - uint16_t type, void * p_priv); - -/** - * Function for configuring the security manager. - * - * @param h Service client - * @param p_params local authentication/bonding parameters - * @param p_priv pointer to private data - * - * @return @ref OS_ERR_TYPE - * - * @note Upon completion of the procedure, the client will receive - * a message @ref MSG_ID_BLE_GAP_SM_CONFIG_RSP - */ -int ble_gap_sm_config(const svc_client_handle_t * h, - const struct ble_gap_sm_config_params * p_params, - void *p_priv); - -/** - * Initiate the bonding procedure (central). - * - * @param h Service client - * @param conn_handle connection on which bonding procedure is executed - * @param p_params local authentication/bonding parameters - * @param p_priv pointer to private data - * - * @return @ref OS_ERR_TYPE - * - * @note Upon completion of the procedure, the client receives - * @ref MSG_ID_BLE_GAP_SM_PAIRING_RSP - */ -int ble_gap_sm_pairing_req(const svc_client_handle_t * h, - uint16_t conn_handle, - const struct ble_gap_sm_pairing_params * p_params, - void *p_priv); - -/** - * Reply to an incoming passkey request event (@ref MSG_ID_BLE_GAP_SM_PASSKEY_REQ_EVT). - * - * @param p_svc_handle service handle - * @param conn_handle connection on which bonding is going on - * @param p_params bonding security reply - * @param p_priv pointer to private data - * - * @return @ref OS_ERR_TYPE - * - * @note Upon completion of the procedure, the client receives - * @ref MSG_ID_BLE_GAP_SM_PASSKEY_RSP - */ -int ble_gap_sm_passkey_reply(svc_client_handle_t * p_svc_handle, - uint16_t conn_handle, - const struct ble_gap_sm_passkey * p_params, - void *p_priv); - -/** - * Enable disable the reporting of the RSSI value. - * - * @param p_svc_handle service handle - * @param conf RSSI report parameters @ref MSG_ID_BLE_GAP_SET_RSSI_REPORT_REQ - * @param p_priv pointer to private data - * - * @return @ref OS_ERR_TYPE, - * @return MSG: MSG_ID_BLE_GAP_SET_RSSI_REPORT_RSP @ref ble_rsp - */ -int ble_gap_set_rssi_report(svc_client_handle_t * p_svc_handle, - const struct rssi_report_params *params, - void *p_priv); - -/** - * Start scanning for BLE devices doing advertisement. - * - * @param p_svc_handle service handle - * @param p_scan_params scan parameters to use @ref ble_gap_scan_param_t - * @param p_priv pointer to private data - * - * @return @ref OS_ERR_TYPE, - * @return MSG: MSG_ID_BLE_GAP_SCAN_START_RSP @ref ble_rsp - */ -int ble_gap_start_scan(svc_client_handle_t * p_svc_handle, - const ble_gap_scan_param_t * p_scan_params, - void *p_priv); - -/** - * Stop scanning. - * - * @param p_svc_handle service handle - * @param p_priv pointer to private data - * - * @return @ref OS_ERR_TYPE, - * @return MSG: MSG_ID_BLE_GAP_STOP_START_RSP @ref ble_rsp - */ -int ble_gap_stop_scan(svc_client_handle_t * p_svc_handle, void *p_priv); - -/** - * Connect to a Remote Device. - * - * @param p_svc_handle service handle - * @param p_bd bd to connect to. shall be null if BLE_GAP_SCAN_WHITE_LISTED option is set in @ref ble_gap_scan_param_t - * @param p_scan_params scan parameters - * @param p_conn_params connection parameters - * @param p_priv pointer to private data - * - * @return @ref OS_ERR_TYPE, - * @return MSG: MSG_ID_BLE_GAP_CONNECT_RSP @ref ble_rsp, - * @return MSG: MSG_ID_BLE_GAP_CONNECT_EVT @ref ble_gap_connect_evt_t - */ -int ble_gap_connect(svc_client_handle_t * p_svc_handle, const ble_addr_t * p_bd, - const ble_gap_scan_param_t * p_scan_params, - const struct ble_gap_connection_params * p_conn_params, - void *p_priv); - -/** - * Cancel an ongoing connection attempt. - * - * @param p_svc_handle service handle - * @param p_bd bd address of device for which the connection shall be canceled - * @param p_priv pointer to private data - * - * @return @ref OS_ERR_TYPE, - * @return MSG: MSG_ID_BLE_GAP_CONNECT @ref ble_rsp - */ -int ble_gap_cancel_connect(svc_client_handle_t * p_svc_handle, - const ble_addr_t * p_bd, void *p_priv); - -/** - * Set a gap option (channel map etc) on a connection. - * - * @param p_svc_handle service handle - * @param op option to set @ref BLE_GAP_SET_OPTIONS - * @param p_opt bd address of device for which the connection shall be canceled ble_gap_option_t - * @param p_priv pointer to private data - * - * @return @ref OS_ERR_TYPE, - * @return MSG: MSG_ID_BLE_GAP_SET_OPTIONS @ref ble_rsp - */ -int ble_gap_set_option(svc_client_handle_t * p_svc_handle, uint8_t op, - const ble_gap_option_t * p_opt, void *p_priv); - -/** - * Set a gap option (channel map etc) on a connection. - * - * @param p_svc_handle service handle - * @param p_params bd address of device for which the connection shall be canceled ble_gap_option_t - * @param p_priv pointer to private data - * - * @return @ref OS_ERR_TYPE, - * @return MSG: MSG_ID_BLE_GAP_GENERIC_CMD_RSP @ref ble_rsp or @ref ble_generic_msg - */ -int ble_gap_generic_cmd_req(svc_client_handle_t * p_svc_handle, - const struct ble_gap_gen_cmd_params *p_params, - void *p_priv); - -/** - * Get nordic version. - * - * @param p_svc_handle service handle - * @param p_priv pointer to private data - * - * @return @ref OS_ERR_TYPE, - * @return MSG: MSG_ID_BLE_GAP_GET_VERSION_RSP @ref ble_rsp or @ref ble_generic_msg - */ -int ble_gap_get_version_req(svc_client_handle_t * p_svc_handle, - void *p_priv); - -/** - * Init dtm mode. - * - * @param p_svc_handle service handle - * @param p_params bd address of device for which the connection shall be canceled ble_gap_option_t - * - * @return @ref OS_ERR_TYPE, - * @return MSG: MSG_ID_BLE_GAP_DTM_INIT_RSP @ref ble_rsp or @ref ble_generic_msg - */ -int ble_gap_dtm_init_req(svc_client_handle_t * p_svc_handle, - void *p_priv); -/** @} */ - -#endif /* __BLE_SVC_API_H__ */ diff --git a/system/libarc32_arduino101/framework/include/services/ble/ble_service_gatt.h b/system/libarc32_arduino101/framework/include/services/ble/ble_service_gatt.h deleted file mode 100644 index 23c65b73..00000000 --- a/system/libarc32_arduino101/framework/include/services/ble/ble_service_gatt.h +++ /dev/null @@ -1,325 +0,0 @@ -/* - * Copyright (c) 2015, Intel Corporation. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its contributors - * may be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __BLE_SERVICE_GATT_H__ -#define __BLE_SERVICE_GATT_H__ - -#include "ble_service.h" -#include "ble_service_gap_api.h" - -/** GATT common definitions. - * - * @ingroup ble_core_service - * - * @addtogroup ble_core_service_gatt BLE core service common GATT definitions - * @{ - */ - -/** - * GATT Success code and error codes. - */ -enum BLE_SVC_GATT_STATUS_CODES { - BLE_SVC_GATT_STATUS_SUCCESS = BLE_STATUS_SUCCESS, /**< GATT success @ref BLE_STATUS_SUCCESS */ - BLE_SVC_GATT_STATUS_ENCRYPTED_MITM = BLE_SVC_GATT_STATUS_SUCCESS, - BLE_SVC_GATT_STATUS_INVALID_HANDLE = BLE_STATUS_GATT_BASE + 0x01,/**< 0x01 see BT Spec Vol 3: Part F (ATT), chapter 3.4.1.1 */ - BLE_SVC_GATT_STATUS_READ_NOT_PERMIT, - BLE_SVC_GATT_STATUS_WRITE_NOT_PERMIT, - BLE_SVC_GATT_STATUS_INVALID_PDU, - BLE_SVC_GATT_STATUS_INSUF_AUTHENTICATION, - BLE_SVC_GATT_STATUS_REQ_NOT_SUPPORTED, - BLE_SVC_GATT_STATUS_INVALID_OFFSET, - BLE_SVC_GATT_STATUS_INSUF_AUTHORIZATION, - BLE_SVC_GATT_STATUS_PREPARE_Q_FULL, - BLE_SVC_GATT_STATUS_NOT_FOUND, - BLE_SVC_GATT_STATUS_NOT_LONG, - BLE_SVC_GATT_STATUS_INSUF_KEY_SIZE, - BLE_SVC_GATT_STATUS_INVALID_ATTR_LEN, - BLE_SVC_GATT_STATUS_ERR_UNLIKELY, - BLE_SVC_GATT_STATUS_INSUF_ENCRYPTION, - BLE_SVC_GATT_STATUS_UNSUPPORT_GRP_TYPE, - BLE_SVC_GATT_STATUS_INSUF_RESOURCE, - - /**< TODO: maybe be not needed, to be covered by generic GAP status */ - BLE_SVC_GATT_STATUS_NO_RESOURCES = BLE_STATUS_GATT_BASE | 0x80, - BLE_SVC_GATT_STATUS_INTERNAL_ERROR, - BLE_SVC_GATT_STATUS_WRONG_STATE, - BLE_SVC_GATT_STATUS_DB_FULL, - BLE_SVC_GATT_STATUS_BUSY, - BLE_SVC_GATT_STATUS_ERROR, - BLE_SVC_GATT_STATUS_CMD_STARTED, - BLE_SVC_GATT_STATUS_ILLEGAL_PARAMETER, - BLE_SVC_GATT_STATUS_PENDING, - BLE_SVC_GATT_STATUS_AUTH_FAIL, - BLE_SVC_GATT_STATUS_MORE, - BLE_SVC_GATT_STATUS_INVALID_CFG, - BLE_SVC_GATT_STATUS_SERVICE_STARTED, - BLE_SVC_GATT_STATUS_ENCRYPTED_NO_MITM, - BLE_SVC_GATT_STATUS_NOT_ENCRYPTED, - BLE_SVC_GATT_STATUS_CONGESTED, -}; - -/** - * GATT Server Message ID definitions. - */ -enum BLE_GATTS_MSG_ID { - /**< GATT Server Requests */ - MSG_ID_BLE_GATTS_ADD_SERVICE_REQ = MSG_ID_BLE_GAP_REQ_LAST, - MSG_ID_BLE_GATTS_ADD_INCL_SVC_REQ, - MSG_ID_BLE_GATTS_ADD_CHARACTERISTIC_REQ, - MSG_ID_BLE_GATTS_ADD_DESCRIPTOR_REQ, - MSG_ID_BLE_GATTS_START_SERVICE_REQ, - MSG_ID_BLE_GATTS_REMOVE_SERVICE_REQ, - MSG_ID_BLE_GATTS_INDICATE_SERVICE_CHANGE_REQ, - MSG_ID_BLE_GATTS_SET_ATTRIBUTE_VALUE_REQ, - MSG_ID_BLE_GATTS_GET_ATTRIBUTE_VALUE_REQ, - MSG_ID_BLE_GATTS_SEND_NOTIF_REQ, - MSG_ID_BLE_GATTS_SEND_IND_REQ, - MSG_ID_BLE_GATTS_SEND_RW_AUTHORIZATION_REQ, - MSG_ID_BLE_GATTS_WR_CONN_ATTRIBUTES_REQ, - MSG_ID_BLE_GATTS_RD_CONN_ATTRIBUTES_REQ /* 37 */ , - MSG_ID_BLE_GATTS_REQ_LAST, - - /**< GATT Server Requests */ - MSG_ID_BLE_GATTS_ADD_SERVICE_RSP = MSG_ID_BLE_GAP_RSP_LAST, - /**< create new service */ - MSG_ID_BLE_GATTS_ADD_INCL_SVC_RSP, - MSG_ID_BLE_GATTS_ADD_CHARACTERISTIC_RSP, - MSG_ID_BLE_GATTS_ADD_DESCRIPTOR_RSP, - MSG_ID_BLE_GATTS_START_SERVICE_RSP, /**< enable created service */ - MSG_ID_BLE_GATTS_REMOVE_SERVICE_RSP, /**< stop and remove service */ - MSG_ID_BLE_GATTS_INDICATE_SERVICE_CHANGE_RSP, /**< indicate a service change */ - MSG_ID_BLE_GATTS_SET_ATTRIBUTE_VALUE_RSP, - MSG_ID_BLE_GATTS_GET_ATTRIBUTE_VALUE_RSP, - MSG_ID_BLE_GATTS_SEND_NOTIF_RSP, /**< send notification */ - MSG_ID_BLE_GATTS_SEND_IND_RSP, /**< send indication */ - MSG_ID_BLE_GATTS_SEND_RW_AUTHORIZATION_RSP, /**< authorize a R/W request from remote */ - MSG_ID_BLE_GATTS_WR_CONN_ATTRIBUTES_RSP, /**< write connection related attributes (previously bonded!) */ - MSG_ID_BLE_GATTS_RD_CONN_ATTRIBUTES_RSP /* 37 */ , /**< read connection related attributes (only for bonded connections!*/ - MSG_ID_BLE_GATTS_RSP_LAST, - - /**< GATT Server Events */ - MSG_ID_BLE_GATTS_WRITE_EVT = MSG_ID_BLE_GAP_EVT_LAST, /**< remote client write happened */ - MSG_ID_BLE_GATTS_RW_AUTHORIZATION_REQ_EVT, /**< remote client R/W authorization request */ - MSG_ID_BLE_GATTS_CONN_ATTRIB_MISSING_EVT, /**< connection related attributes have not been set, access pending */ - MSG_ID_BLE_GATTS_INDICATION_CONF_EVT, /**< indication confirmation event */ - MSG_ID_BLE_GATTS_SVC_CHG_CONF_EVT, /**< confirmation of service change indication (no params) */ - MSG_ID_BLE_GATTS_TO_EVT, /**< GATTS timeout indication */ - MSG_ID_BLE_GATTS_EVT_LAST -}; - -/** - * GATT Client Message ID definitions. - */ -enum BLE_GATTC_MSG_ID { - /**< GATT Client Requests, responses, events and indications */ - MSG_ID_BLE_GATTC_DISCOVER_PRIMARY_SERVICE_REQ = - MSG_ID_BLE_GATTS_REQ_LAST, - MSG_ID_BLE_GATTC_DISCOVER_INCLUDED_SERVICES_REQ, - MSG_ID_BLE_GATTC_DISCOVER_CHAR_REQ, - MSG_ID_BLE_GATTC_DISCOVER_DESCRIPTOR_REQ, - MSG_ID_BLE_GATTC_RD_CHARS_REQ, - MSG_ID_BLE_GATTC_WR_OP_REQ, - MSG_ID_BLE_GATTC_SEND_HANDLE_VALUE_REQ /* 44 */ , - - /** GATT Client Requests, responses, events and indications */ - MSG_ID_BLE_GATTC_DISCOVER_PRIMARY_SERVICE_RSP = MSG_ID_BLE_GATTS_RSP_LAST, /**< discover primary service */ - MSG_ID_BLE_GATTC_DISCOVER_INCLUDED_SERVICES_RSP,/**< find included service procedure */ - MSG_ID_BLE_GATTC_DISCOVER_CHAR_RSP, /**< discover characteristics of a service */ - MSG_ID_BLE_GATTC_DISCOVER_DESCRIPTOR_RSP, /**< discover descriptor of a characteristic */ - MSG_ID_BLE_GATTC_RD_CHARS_RSP, /**< read characteristic or long characteristics */ - MSG_ID_BLE_GATTC_WR_OP_RSP, /**< different types of write operations */ - MSG_ID_BLE_GATTC_SEND_HANDLE_VALUE_RSP /* 44 */ , /**< send attribute handle to server */ - - /** GATT Client Events */ - MSG_ID_BLE_GATTC_DISC_PRIM_SVC_EVT = MSG_ID_BLE_GATTS_EVT_LAST, /**< primary service discovery response */ - MSG_ID_BLE_GATTC_DISC_INCL_SVC_EVT, /**< include service discovery response */ - MSG_ID_BLE_GATTC_DISC_CHAR_EVT, /**< characteristic discovery response */ - MSG_ID_BLE_GATTC_DISC_DESCR_EVT, /**< descriptor discovery response */ - MSG_ID_BLE_GATTC_RD_EVT, /**< data read response */ - MSG_ID_BLE_GATTC_WR_EVT, /**< data write response */ - MSG_ID_BLE_GATTC_HDL_NOTIF_EVT, /**< handle indication/notification event */ - MSG_ID_BLE_GATTC_TO_EVT, /**< GATT Client timeout event */ - MSG_ID_BLE_GATTC_LAST -}; - -/** - * Maximum UUID size - 16 bytes, and structure to hold any type of UUID. - */ -#define MAX_UUID_SIZE 16 - -#define BLE_GATT_INVALID_HANDLE 0x0000 /**< reserved invalid attribute handle */ -#define BLE_GATT_MAX_HANDLE 0xffff /**< maximum handle in a BLE server */ -#define BLE_GATT_START_HANDLE_DISCOVER 0x0001 /**< Value of start handle during discovery. */ - -/** BT uuid types defined as length. */ -enum BT_UUID_TYPES { - BT_UUID16 = 2, /**< 16 bit UUID type */ - BT_UUID32 = 4, /**< 32 bit UUID type */ - BT_UUID128 = 16 /**< 128 bit UUID type */ -}; - -/** - * Generic uuid structure specific to BT/BLE. - */ -struct bt_uuid { - uint8_t type; /**< UUID type (encoded as length of the union element) @ref BT_UUID_TYPES */ - union { - uint16_t uuid16; - uint32_t uuid32; - uint8_t uuid128[MAX_UUID_SIZE]; - }; -}; - -/** - * UUID and Handle combination for services and characteristics - * - * Make sure this is 32 bit aligned! - */ -struct bt_uuid_handle_tuple { - void *p_priv; /**< Service private reference handle. */ - uint16_t handle; /** Service or characteristic handle. */ -}; - -/** - * GATT service types, primary versus secondary/included one. - */ -enum BLE_GATT_SVC_TYPES { - BLE_GATT_SVC_PRIMARY = 0, /**< primary service */ - BLE_GATT_SVC_INCLUDED /**< include service (must be referenced by a primary) */ -}; - -/** - * Characteristic properties. - */ -enum BLE_GATT_CHAR_PROPS { - BLE_GATT_CHAR_PROP_BIT_NONE = 0, - BLE_GATT_CHAR_PROP_BIT_BROADCAST = 0x01, - BLE_GATT_CHAR_PROP_BIT_READ = 0x02, - BLE_GATT_CHAR_PROP_BIT_WRITE_NR = 0x04, - BLE_GATT_CHAR_PROP_BIT_WRITE = 0x08, - BLE_GATT_CHAR_PROP_BIT_NOTIFY = 0x10, - BLE_GATT_CHAR_PROP_BIT_INDICATE = 0x20, - BLE_GATT_CHAR_PROP_BIT_AUTH = 0x40, - BLE_GATT_CHAR_PROP_BIT_EXTEND = 0x80/**< if set the extend property @ref BLE_GATT_CHAR_EXT_PROPS is present! */ -}; - -/** - * Extended characteristic properties. - */ -enum BLE_GATT_CHAR_EXT_PROPS { - BLE_GATT_CHAR_EXT_PROP_BIT_NONE = 0, - BLE_GATT_CHAR_EXT_PROP_RELIABLE_WR = 0x0001, /**< Reliable write procedure is supported */ - BLE_GATT_CHAR_EXT_PROP_WR_AUX = 0x0002, /**< User Descriptor Writes are permitted */ -}; - -struct ble_gatt_char_properties { - uint8_t props; /**< properties, @ref BLE_GATT_CHAR_PROPS */ - uint16_t ext_props; /**< extended properties, @ref BLE_GATT_CHAR_EXT_PROPS, valid if BLE_GATT_CHAR_PROP_BIT_EXTEND set */ -}; - -/** - * Format of the value of a characteristic, enumeration type. - */ -enum BLE_GATT_FORMATS { - BLE_GATT_FORMAT_RES, /* rfu */ - BLE_GATT_FORMAT_BOOL, /* 0x01 boolean */ - BLE_GATT_FORMAT_2BITS, /* 0x02 2 bit */ - BLE_GATT_FORMAT_NIBBLE, /* 0x03 nibble */ - BLE_GATT_FORMAT_UINT8, /* 0x04 uint8 */ - BLE_GATT_FORMAT_UINT12, /* 0x05 uint12 */ - BLE_GATT_FORMAT_UINT16, /* 0x06 uint16 */ - BLE_GATT_FORMAT_UINT24, /* 0x07 uint24 */ - BLE_GATT_FORMAT_UINT32, /* 0x08 uint32 */ - BLE_GATT_FORMAT_UINT48, /* 0x09 uint48 */ - BLE_GATT_FORMAT_UINT64, /* 0x0a uint64 */ - BLE_GATT_FORMAT_UINT128,/* 0x0B uint128 */ - BLE_GATT_FORMAT_SINT8, /* 0x0C signed 8 bit integer */ - BLE_GATT_FORMAT_SINT12, /* 0x0D signed 12 bit integer */ - BLE_GATT_FORMAT_SINT16, /* 0x0E signed 16 bit integer */ - BLE_GATT_FORMAT_SINT24, /* 0x0F signed 24 bit integer */ - BLE_GATT_FORMAT_SINT32, /* 0x10 signed 32 bit integer */ - BLE_GATT_FORMAT_SINT48, /* 0x11 signed 48 bit integer */ - BLE_GATT_FORMAT_SINT64, /* 0x12 signed 64 bit integer */ - BLE_GATT_FORMAT_SINT128,/* 0x13 signed 128 bit integer */ - BLE_GATT_FORMAT_FLOAT32,/* 0x14 float 32 */ - BLE_GATT_FORMAT_FLOAT64,/* 0x15 float 64 */ - BLE_GATT_FORMAT_SFLOAT, /* 0x16 IEEE-11073 16 bit SFLOAT */ - BLE_GATT_FORMAT_FLOAT, /* 0x17 IEEE-11073 32 bit SFLOAT */ - BLE_GATT_FORMAT_DUINT16,/* 0x18 IEEE-20601 format */ - BLE_GATT_FORMAT_UTF8S, /* 0x19 UTF-8 string */ - BLE_GATT_FORMAT_UTF16S, /* 0x1a UTF-16 string */ - BLE_GATT_FORMAT_STRUCT, /* 0x1b Opaque structure */ - BLE_GATT_FORMAT_MAX /* 0x1c or above reserved */ -}; - -/** - * GATT characteristic user description. - */ -struct ble_gatt_char_user_desc { - uint8_t *buffer; /**< Pointer to a UTF-8 string. */ - uint8_t len; /**< The size in bytes of the user description. */ -}; - -/** - * GATT characteristic presentation format description. - */ -struct ble_gatt_pf_desc { - uint16_t unit; /**< as UUIUD defined by SIG */ - uint16_t descr; /**< as UUID as defined by SIG */ - uint8_t format; /**< @ref BLE_GATT_FORMATS */ - int8_t exp; /**< see Unit from Bluetooth Assigned Numbers, https://developer.bluetooth.org/gatt/units/Pages/default.aspx */ - uint8_t name_spc; /**< name space of the description */ -} ; - -/** - * GATT indication types. - */ -enum BLE_GATT_IND_TYPES { - BLE_GATT_IND_TYPE_NONE = 0, - BLE_GATT_IND_TYPE_NOTIFICATION, - BLE_GATT_IND_TYPES_INDICATION, -}; - -/** - * GATT Write operation types - * - * (BT spec Vol 3, Part G, chapter. 4.9) - * @note long char write, Prepare & Exe request are handled internally to the controller stack - */ -enum BLE_GATT_WR_OP_TYPES { - BLE_GATT_WR_OP_NOP = 0, /**< normally not used except to cancel BLE_GATT_WR_OP_REQ long char write procedure */ - BLE_GATT_WR_OP_CMD, /**< Write Command, (no response) */ - BLE_GATT_WR_OP_REQ, /**< Write Request, Write response is received , if length is longer then ATT MTU, Prepare write procedure */ - BLE_GATT_WR_OP_SIGNED_CMD, /**< Signed Write Command */ -}; - -/** @} */ - -#endif diff --git a/system/libarc32_arduino101/framework/include/services/ble/ble_service_gattc_api.h b/system/libarc32_arduino101/framework/include/services/ble/ble_service_gattc_api.h deleted file mode 100644 index d7b42df9..00000000 --- a/system/libarc32_arduino101/framework/include/services/ble/ble_service_gattc_api.h +++ /dev/null @@ -1,372 +0,0 @@ -/* - * Copyright (c) 2015, Intel Corporation. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its contributors - * may be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __BLE_SERVICE_GATTC_H__ -#define __BLE_SERVICE_GATTC_H__ - -#include "ble_service.h" -#include "ble_service_gap_api.h" -#include "ble_service_gatt.h" - -/** - * @defgroup ble_core_service_gattc BLE Core Service GATTC - * @ingroup ble_core_service - * - * BLE Core Service GATTC APIs used to implement GATT Clients. - * - * This is typically only used to add new client services to BLE service. - * - * It provides the following services: - * - Discover remote \b primary services or a specific service - * - Discover remote characteristics - * - Discover remote descriptors - * - read/write remote characteristics - * - Getting notified on characteristic changes - * - * @{ - */ - -/** - * Generic GATTC response message. - */ -struct ble_gattc_rsp { - struct cfw_message header; /**< Component framework message header (@ref cfw), MUST be first element of structure */ - ble_status_t status; - uint16_t conn_handle; /**< GAP connection handle */ -}; - -/** - * Generic GATTC error event. - */ -struct ble_gattc_err_rsp_evt { - uint16_t err_handle; /**< handle of char attribute causing the failure */ -}; - -/** - * Handle range for a service operation. - */ -struct ble_gattc_handle_range { - uint16_t start_handle; - uint16_t end_handle; -}; - -typedef struct { - struct ble_gattc_handle_range handle_range; /**< range of characteristic handles within a service */ - struct bt_uuid uuid; /**< service uuid */ -} ble_gattc_svc_t; - -/** - * Primary Service discovery Indication message @ref MSG_ID_BLE_GATTC_DISC_PRIM_SVC_EVT. - */ -typedef struct { - uint16_t svc_count; /**< number of service included into this indication */ - ble_gattc_svc_t service_found[];/**< array on fouTnd services */ -} ble_gattc_primary_svc_disc_evt_t; - -/** - * Included service. - */ -typedef struct { - uint16_t incl_handle; /**< handle of included service */ - ble_gattc_svc_t svc; /**< included service */ -} ble_gattc_incl_svc_t; - -/** - * Discovered included services @ref MSG_ID_BLE_GATTC_DISC_INCL_SVC_EVT. - */ -typedef struct { - uint16_t incl_count; /**< Number of included services */ - ble_gattc_incl_svc_t included[]; /**< Array on found services */ -} ble_gattc_incl_svc_disc_evt_t; - -typedef struct { - struct ble_gatt_char_properties char_properties; /**< characteristic properties */ - uint16_t decl_handle; /**< Characteristic declaration handle */ - uint16_t value_handle; /**< Char's value handle */ - struct bt_uuid uuid; /**< Characteristic's UUID */ -} ble_gattc_characteristic_t; - -/** - * Discovered characteristics indication @ref MSG_ID_BLE_GATTC_DISC_CHAR_EVT. - */ -typedef struct { - uint16_t char_count; /**< number of characteristics in this message */ - ble_gattc_characteristic_t chars[]; /**< characteristics data as per char_count */ -} ble_gattc_char_disc_evt_t; - -/** - * GATTC descriptor. - */ -typedef struct { - uint16_t handle; /**< descriptor handle */ - struct bt_uuid uuid; /**< uuid of the descriptor */ -} ble_gattc_descriptor_t; - -/** - * Descriptor discover indication. - */ -typedef struct { - uint16_t desc_count; /**< number of descriptors in this message */ - ble_gattc_descriptor_t descs[]; /**< found descriptors */ -} ble_gattc_desc_disc_evt_t; - -enum BLE_GATTC_RD_CHAR_TYPES { - BLE_GATTC_RD_CHAR_BY_UUID = 0, /**< Read characteristic by UUID */ - BLE_GATTC_RD_CHAR, /**< Read (Long) characteristic or (Long) descriptor. Maybe called multiple times in case of long */ - BLE_GATTC_RD_CHAR_MULTIPLE /**< Read multiple characteristic attributes */ -}; - -/** - * Characteristic read by using UUID. - */ -typedef struct { - struct ble_gattc_handle_range handle_range; /**< characteristic or descriptor handle range */ - struct bt_uuid *p_uuid; /**< uuid of characteristic to read */ -} ble_gattc_rd_char_by_uuid_t; - -/** - * Characteristic or descriptor read. - * - * Maybe used for long too. - */ -typedef struct { - uint16_t handle; /**< attribute handle for reading */ - uint16_t offset; /**< offset into attribute data to read */ -} ble_gattc_rd_char_t; - -/** - * Read multiple characteristics values. - */ -typedef struct { - uint16_t handle_count; /**< number of handles in this structure */ - uint16_t handle[]; /**< handles of attributes to read from */ -} ble_gattc_rd_multi_char_t; - -typedef struct { - union { - ble_gattc_rd_char_by_uuid_t char_by_uuid; - ble_gattc_rd_char_t char_desc; /**< (Long) characteristic or descriptor to read */ - ble_gattc_rd_multi_char_t multi_char; - /**< read multiple characteristics */ - }; -} ble_gattc_rd_characteristic_t; - -typedef struct { - uint16_t char_handle; /**< handle of characteristic */ - uint16_t len; /**< if len is bigger then ATT MTU size, the controller fragment buffer itself */ - uint8_t *p_value; /**< characteristic value to write */ - uint8_t wr_type; /**< type of write operation @ref BLE_GATT_WR_OP_TYPES */ -} ble_gattc_wr_characteristic_t; - -/** - * Read characteristic response indication (@ref MSG_ID_BLE_GATTC_RD_EVT). - */ -typedef struct { - uint16_t handle; /**< handle of characteristic attribute read */ - uint16_t offset; /**< offset of data returned */ - uint16_t len; /**< length of data returned */ - uint8_t data[]; /**< characteristic attribute data */ -} ble_gattc_rd_char_evt_t; - -/** - * Characteristic write response indication @ref MSG_ID_BLE_GATTC_WR_EVT. - */ -typedef struct { - uint16_t char_handle; - uint16_t len; -} ble_gattc_wr_char_evt_t; - -/** - * Handle value indication or notification indication/event (@ref MSG_ID_BLE_GATTC_HDL_NOTIF_EVT). - */ -typedef struct { - uint16_t handle; /**< handle of characteristic being notified/indicated */ - uint16_t len; /**< length of value included into this indication */ - uint8_t type; /**< notification versus indication, @ref BLE_GATT_IND_TYPES */ - uint8_t data[]; /**< value data received */ -} ble_gattc_value_evt_t; - -/** - * GATT timeout reason. - */ -typedef struct { - uint16_t reason; /**< GATT timeout reason */ -} ble_gattc_to_evt_t; - -/** - * GATTC indication or response message structure applicable to most indications/events/responses. - */ -struct ble_gattc_evt_msg { - struct cfw_message header; /**< Component framework message header (@ref cfw), MUST be first element of structure */ - ble_status_t status; - uint16_t conn_handle; - union { - struct ble_gattc_err_rsp_evt err_rsp; /**< returned only if status != BLE_GATT_STATUS_SUCCESS */ - ble_gattc_primary_svc_disc_evt_t prim_svc_disc; - /**< primary service discovery indication event */ - ble_gattc_incl_svc_disc_evt_t incl_svc_disc; /**< included services discovered */ - ble_gattc_char_disc_evt_t char_disc; /**< characteristic discover event/indication */ - ble_gattc_desc_disc_evt_t desc_disc; /**< discovered descriptors indication/event */ - ble_gattc_rd_char_evt_t char_rd; /**< read characteristic indication/event */ - ble_gattc_wr_char_evt_t char_wr; /**< characteristic write indication event */ - ble_gattc_value_evt_t val_ind; /**< value indication or notification */ - ble_gattc_to_evt_t timeout_ind; /**< gattc timeout protocol error */ - }; /**< in case for responses, union is not used! */ -}; - -/** - * Discover primary service. - * - * @param p_svc_handle service handle - * @param conn_handle connection to use - * @param p_svc_uuid points to service UUID. if NULL, all services found are returned - * @param p_priv pointer to private data - * - * @return @ref OS_ERR_TYPE - * @return MSG: MSG_ID_BLE_GATTC_DISCOVER_PRIMARY_SERVICE_RSP @ref ble_gattc_rsp - * @return EVT: MSG_ID_BLE_GATTC_DISC_PRIM_SVC_EVT @ref ble_gattc_primary_svc_disc_evt_t - */ -int ble_gattc_discover_primary_service(svc_client_handle_t * p_svc_handle, - uint16_t conn_handle, - const struct bt_uuid * p_svc_uuid, - void *p_priv); - -/** - * Discover included services on a previously discovered primary service. - * - * @param p_svc_handle service handle - * @param conn_handle connection to use - * @param p_handle_range handle range previously returned by @ref ble_gattc_primary_svc_disc_evt_t - * @param p_priv pointer to private data - * - * @return @ref OS_ERR_TYPE - * @return MSG: MSG_ID_BLE_GATTC_DISCOVER_INCLUDED_SERVICES_RSP @ref ble_gattc_rsp - */ -int ble_gattc_discover_included_service(svc_client_handle_t * p_svc_handle, - uint16_t conn_handle, - const struct ble_gattc_handle_range * - p_handle_range, void *p_priv); - -/** - * Discover characteristics on a service. - * - * May be called several times if not all characteristics have been discovered. - * In this case a new handle range needs to be provided. - * - * @param p_svc_handle service handle - * @param conn_handle connection to use - * @param p_handle_range handle range - * @param p_priv pointer to private data - * - * @return @ref OS_ERR_TYPE - * @return MSG: MSG_ID_BLE_GATTC_DISCOVER_CHAR_RSP @ref ble_gattc_rsp - * @ref MSG_ID_BLE_GATTC_DISC_CHAR_EVT @ref ble_gattc_char_disc_evt_t - */ -int ble_gattc_discover_characteristic(svc_client_handle_t * p_svc_handle, - uint16_t conn_handle, - const struct ble_gattc_handle_range * p_handle_range, - void *p_priv); - -/** - * Discover characteristics on a service. - * - * May be called several times if not all characteristics have been discovered. - * In this case a new handle range needs to be provided. - * - * @param p_svc_handle service handle - * @param conn_handle connection to use - * @param p_handle_range handle range - * @param p_priv pointer to private data - * - * @return @ref OS_ERR_TYPE - * @return MSG: MSG_ID_BLE_GATTC_DISCOVER_DESCRIPTOR_RSP @ref ble_gattc_rsp - * @ref MSG_ID_BLE_GATTC_DISC_DESCR_EVT @ref ble_gattc_desc_disc_evt_t - */ -int ble_gattc_discover_descriptor(svc_client_handle_t * p_svc_handle, - uint16_t conn_handle, - const struct ble_gattc_handle_range * - p_handle_range, void *p_priv); - -/** - * Read characteristic on remote server. - * - * @param p_svc_handle service handle - * @param conn_handle connection to use - * @param type type of read to execute @ref BLE_GATTC_RD_CHAR_TYPES - * @param p_rd_char_param read type specific characteristic read parameter - * @param p_priv pointer to private data - * - * @return @ref OS_ERR_TYPE - * @return MSG: MSG_ID_BLE_GATTC_RD_CHARS_RSP @ref ble_gattc_rsp - * @return EVT: MSG_ID_BLE_GATTC_RD_EVT @ref ble_gattc_rd_char_evt_t - */ -int ble_gattc_read_characteristic(svc_client_handle_t * p_svc_handle, - uint16_t conn_handle, - uint8_t type, - const ble_gattc_rd_characteristic_t * p_rd_char_param, - void *p_priv); - -/** - * Write characteristic on server. - * - * @param p_svc_handle service handle - * @param conn_handle connection to use - * @param p_wr_char_param write characteristic on remote service - * @param p_priv pointer to private data - * - * @return @ref OS_ERR_TYPE, - * @return MSG: MSG_ID_BLE_GATTC_WR_OP_RSP @ref ble_gattc_rsp - */ -int ble_gattc_write_char_op(svc_client_handle_t * p_svc_handle, - uint16_t conn_handle, - const ble_gattc_wr_characteristic_t * - p_wr_char_param, - void *p_priv); - - -/** - * Write characteristic on server. - * - * @param p_svc_handle service handle - * @param conn_handle connection to use - * @param val_handle handle to confirm and received by Handle Value Indication (@ref MSG_ID_BLE_GATTC_HDL_NOTIF_EVT) - * @param p_priv pointer to private data - * - * @return @ref OS_ERR_TYPE, - * @return MSG: MSG_ID_BLE_GATTC_SEND_HANDLE_VALUE_RSP @ref ble_gattc_rsp - */ -int ble_gattc_send_confirm_handle_value(svc_client_handle_t * p_svc_handle, - uint16_t conn_handle, - uint16_t val_handle, - void *p_priv); - -/** @} */ - -#endif diff --git a/system/libarc32_arduino101/framework/include/services/ble/ble_service_gatts_api.h b/system/libarc32_arduino101/framework/include/services/ble/ble_service_gatts_api.h deleted file mode 100644 index 76bc3149..00000000 --- a/system/libarc32_arduino101/framework/include/services/ble/ble_service_gatts_api.h +++ /dev/null @@ -1,559 +0,0 @@ -/* - * Copyright (c) 2015, Intel Corporation. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its contributors - * may be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __BLE_SERVICE_GATTS_H__ -#define __BLE_SERVICE_GATTS_H__ - -#include "ble_service.h" -#include "ble_service_gap_api.h" -#include "ble_service_gatt.h" - -/** @defgroup ble_core_service_gatts BLE Core Service GATTS - * @ingroup ble_core_service - * - * BLE Core GATTS Service APIs to implement GATT Servers. - * - * This API should only be used by BLE service to implement additional BLE profiles/services. - * - * Those the GATT server APIs provide the following services: - * - Create an new (server) BLE service - * - Add characteristics to the service - * - Write local server characteristics - * - Receive data when updated by client - * - * @note If a service is based on a 128 bit UUID (vendor service), all the characteristic - * need to use the same 128 bit UUID base and only vary octets 12-13 of base UUID. - * - * @{ - */ - -/** - * BLE GATTS max attribute length. - * @note BLE controller dependent - */ -#define BLE_SVC_GATTS_FIX_ATTR_LEN_MAX 510 /**< Maximum length for fixed length Attribute Values. */ -#define BLE_SVC_GATTS_VAR_ATTR_LEN_MAX 512 /**< Maximum length for variable length Attribute Values. */ - -/* forward declaration for callback handlers */ -struct _ble_service_cb; -struct ble_gatts_add_svc_rsp; -struct ble_gatts_add_char_rsp; -struct ble_gatts_add_desc_rsp; -struct ble_gatts_notif_ind_rsp_msg; - -/** - * Generic GATTS response message. - */ -typedef struct { - struct cfw_message header; /**< Component framework message header (@ref cfw), MUST be first element of structure */ - ble_status_t status; - uint16_t conn_handle; /**< GAP connection handle */ -} ble_gatts_rsp_t; - -/** - * Add Service callback handler. - */ -typedef int (* ble_gatts_add_svc_cback_t)(struct ble_gatts_add_svc_rsp * rsp, - struct _ble_service_cb * p_cb); - -/** - * Add service response message. - */ -struct ble_gatts_add_svc_rsp { - struct cfw_message header; /**< Component framework message header (@ref cfw), MUST be first element of structure */ - ble_status_t status; /**< status of service creation */ - ble_gatts_add_svc_cback_t cback; /**< Callback function to execute on reception of this message */ - uint16_t svc_handle; /**< Handle of newly allocated service (only valid in case of success. */ -}; - -/** - * Include service response. - */ -typedef struct { - struct cfw_message header; /**< Component framework message header (@ref cfw), MUST be first element of structure */ - ble_status_t status; /**< status of service creation */ - uint16_t svc_handle; /**< updated handle of included service (only valid in case of success */ -} ble_gatts_incl_svc_rsp_t; - -/** - * ATT attribute permission - */ -struct ble_gatts_permissions { - uint8_t rd; /**< Read permissions, @ref BLE_GAP_SEC_MODES */ - uint8_t wr; /**< Write permissions @ref BLE_GAP_SEC_MODES */ -}; - -/** - * GATT characteristic. - */ -struct ble_gatts_characteristic { - struct bt_uuid * p_uuid; /**< Pointer to the characteristic UUID. */ - struct ble_gatts_permissions perms; /**< Characteristic value attribute permissions */ - struct ble_gatt_char_properties props; /**< Characteristic Properties. @ref ble_gatt_char_properties */ - uint16_t max_len; /**< Maximum characteristic value length in bytes, see @ref BLE_SVC_GATTS_FIX_ATTR_LEN_MAX or @ref BLE_SVC_GATTS_VAR_ATTR_LEN_MAX. */ - uint16_t init_len; /**< Initial characteristic value length in bytes. */ - uint8_t * p_value; /**< Pointer to the characteristic initialization value */ - // optional descriptors - struct ble_gatt_char_user_desc * p_user_desc; /**< Optional user description of the characteristic, NULL if not required */ - struct ble_gatt_pf_desc *p_char_pf_desc; /**< Pointer to a presentation format structure or NULL if the descriptor is not required. */ -}; - -/** - * GATT generic descriptor. - */ -struct ble_gatts_descriptor { - struct bt_uuid * p_uuid; /**< Pointer to the descriptor UUID. */ - uint8_t * p_value; /**< Value of the descriptor */ - uint16_t length; /**< Length of the descriptor value */ - struct ble_gatts_permissions perms; /**< Descriptor attribute permissions */ -}; - -struct ble_gatts_char_handles { - uint16_t value_handle; /**< Handle to the characteristic value. */ - uint16_t cccd_handle; /**< Handle to the Client Characteristic Configuration Descriptor, or BLE_GATT_HANDLE_INVALID if not present. */ - uint16_t sccd_handle; /**< Handle to the Server Characteristic Configuration Descriptor, or BLE_GATT_HANDLE_INVALID if not present. */ -}; - -/** - * Add Service callback handler. - */ -typedef int (* ble_gatts_add_char_cback_t)(struct ble_gatts_add_char_rsp * rsp, - struct _ble_service_cb * p_cb); - -/** - * Add characteristic response message. - */ -struct ble_gatts_add_char_rsp { - struct cfw_message header; /**< Component framework message header (@ref cfw), MUST be first element of structure */ - ble_status_t status; /**< Status of the operation. */ - ble_gatts_add_char_cback_t cback; /**< Callback function to call on reception of this message */ - struct ble_gatts_char_handles char_h; /**< Handles of the created characteristic */ -}; - -/** - * Add Service callback handler. - */ -typedef int (* ble_gatts_add_desc_cback_t)(struct ble_gatts_add_desc_rsp * rsp, - struct _ble_service_cb * p_cb); - -/** - * Add descriptor response message. - */ -struct ble_gatts_add_desc_rsp { - struct cfw_message header; /**< Component framework message header (@ref cfw), MUST be first element of structure */ - ble_status_t status; /**< Status of the operation. */ - ble_gatts_add_desc_cback_t cback; /**< Callback function to call on reception of this message */ - uint16_t handle; /**< Handle of the created descriptor */ -}; - -/** - * Set attribute response message. - */ -struct ble_gatts_set_attr_rsp_msg { - struct cfw_message header; /**< Component framework message header (@ref cfw), MUST be first element of structure */ - ble_status_t status; - uint16_t value_handle; -}; - -/** - * Notification/Indication callback. - */ -typedef int (* ble_gatts_notif_ind_cback_t)(struct ble_gatts_notif_ind_rsp_msg * rsp, - struct _ble_service_cb * p_cb); - -/** - * Notification/Indication response message. - */ -struct ble_gatts_notif_ind_rsp_msg { - struct cfw_message header; /**< Component framework message header (@ref cfw), MUST be first element of structure */ - ble_status_t status; - uint16_t conn_handle; - ble_gatts_notif_ind_cback_t cback; /**< Callback function to call on reception of this message */ - uint16_t handle; /**< Characteristic value handle */ -}; - -/** - * Shortened attribute type definitions. - * See BT Spec r Vol 3, PART G, chapter 3 - */ -enum BLE_SVC_GATTS_ATTR_TYPES { - BLE_SVC_GATTS_ATTR_TYPE_NONE = 0, - BLE_SVC_GATTS_ATTR_TYPE_PRIMARY_SVC_DECL, - /**< primary service attribute declaration (chpt 3.1) */ - BLE_SVC_GATTS_ATTR_TYPE_SECONDARY_SVC_DECL, - /**< secondary service attribute declaration (chpt 3.1) */ - BLE_SVC_GATTS_ATTR_TYPE_INCLUDE_DECL, /**< include attribute declaration (3.2) */ - BLE_SVC_GATTS_ATTR_TYPE_CHAR_DECL, /**< characteristic declaration (3.3.1) */ - BLE_SVC_GATTS_ATTR_TYPE_CHAR_VALUE_DECL,/**< Characteristic value declaration */ - BLE_SVC_GATTS_ATTR_TYPE_DESC_DECL, /**< descriptor declaration */ -}; - -/** - * GATT server write ops. - */ -enum BLE_GATTS_WR_OPS { - BLE_GATTS_OP_NONE = 0, - BLE_GATTS_OP_WR, /**< 3.4.5.1 Write Request (Attribute), expects write response */ - BLE_GATTS_OP_WR_CMD, /**< 3.4.5.3 Write Command (Attribute) NO response sent */ - BLE_GATTS_OP_WR_CMD_SIGNED, /**< 3.4.5.4 Write Command Signed (Attribute), NO response sent */ - BLE_GATTS_OP_WR_PREP_REQ, /**< 3.4.6.1 Write Prepare Request, expects a prepare write request response */ - BLE_GATTS_OP_WR_EXE_REQ_CANCEL, /**< 3.4.6.3 Cancel Executed Write Request, cancel and clear queue (flags = 0) */ - BLE_GATTS_OP_WR_EXE_REQ_IMM /**< 3.4.6.3 Immediately Execute Write Request */ -}; - -/** - * Write authorization context data structure. - */ -typedef struct { - uint16_t attr_handle; /**< handle of attribute to write */ - uint16_t offset; - uint16_t len; - uint8_t op; /**< @ref BLE_GATTS_WR_OPS */ - uint8_t data[]; -} ble_gatt_wr_evt_t; - -/** - * Read authorization context data structure. - */ -typedef struct { - uint16_t attr_handle; /**< handle of attribute to been read */ - uint16_t offset; -} ble_gatt_rd_evt_t; - -/** - * Connection attribute data is missing @ref MSG_ID_BLE_GATTS_CONN_ATTRIB_MISSING_EVT. - */ -typedef struct { - uint16_t miss_type; /**< missing connection attribute type */ -} ble_gatts_conn_attrib_missing_evt_t; - -/** - * Handle Value Confirmation, @ref MSG_ID_BLE_GATTS_INDICATION_CONF_EVT in response an handle value indication. - */ -typedef struct { - uint16_t handle; /**< attribute handle of indication value sent */ -} ble_gatts_handle_value_conf_evt_t; - -/** - * Read attribute value rsp message. - */ -typedef struct { - struct cfw_message header; /**< Component framework message header (@ref cfw), MUST be first element of structure */ - ble_status_t status; - uint16_t conn_handle; /**< GAP connection handle */ - uint16_t val_handle; /**< handle of attribute value */ - uint16_t len; /**< length of value returned */ - uint16_t offset; /**< offset in the value. the same as in the rd request! */ - uint8_t value[]; /**< value data of length \ref len */ -} ble_gatts_rd_attrib_val_rsp_t; - -/** - * Indication or notification. - */ -typedef struct { - uint16_t val_handle; /**< handle of attribute value */ - uint16_t len; /**< len of attribute data value to indicate */ - uint8_t *p_data; /**< data to indicate (maybe NULL if currently stored shall be used) */ - uint16_t offset; /**< optional offset into attribute value data */ -} ble_gatts_ind_params_t; - -/** - * Connection related attribute data parameters (stack specific). - */ -typedef struct { - struct cfw_message header; /**< Component framework message header (@ref cfw), MUST be first element of structure */ - ble_status_t status; /**< result for request, if not success, the data afterwards may not be valid */ - uint16_t conn_handle; /**< connection handle of the retrieved connection attribute data */ - uint16_t len; /**< length of the following connection attribute data */ - uint8_t conn_attr_data[]; -} ble_gatts_rd_conn_attr_rsp_t; - -/** - * GATTS timeout @ref MSG_ID_BLE_GATTS_TO_EVT. - */ -typedef struct { - uint16_t reason; /**< reason for timeout */ -} ble_gatts_timeout_evt_t; - -/** - * BLE GATTS Indication Data structure. - */ -struct ble_gatts_evt_msg { - struct cfw_message header; /**< Component framework message header (@ref cfw), MUST be first element of structure */ - ble_status_t status; /**< result for request, if not success, the data afterwards may not be valid */ - uint16_t conn_handle; - union { - ble_gatt_wr_evt_t wr; /**< write indication */ - ble_gatts_conn_attrib_missing_evt_t conn_attr; - /**< connection related attribute missing */ - ble_gatts_handle_value_conf_evt_t handle_val_conf; - /**< value confirmation (confirmation of an indication) */ - ble_gatts_timeout_evt_t timeout; /**< GATTS timeout occurred */ - }; -}; - -/** - * Create an new service, primary or include. - * - * @param p_svc_handle service handle - * @param p_uuid UUID of new service - * @param type primary versus included @ref BLE_GATT_SVC_TYPES - * @param cback Callback function to be called on reception of add service response - * @param p_priv pointer to private data - * - * @return @ref OS_ERR_TYPE - * @return MSG: MSG_ID_BLE_GATTS_ADD_SERVICE_RSP @ref ble_gatts_add_svc_rsp - */ -int ble_gatts_add_service(svc_client_handle_t * p_svc_handle, - const struct bt_uuid * p_uuid, - uint8_t type, - ble_gatts_add_svc_cback_t cback, - void *p_priv); - -/** - * Include a (secondary) service into a primary service. - * - * @param p_svc_handle service handle - * @param svc_handle service to which to add the included service - * @param svc_handle_to_include the previously created includable service - * @param p_priv pointer to private data - * - * @return @ref OS_ERR_TYPE - * @return MSG: MSG_ID_BLE_GATTS_ADD_INCL_SVC @ref ble_gatts_incl_svc_rsp_t - */ -int ble_gatts_add_included_svc(svc_client_handle_t * p_svc_handle, - uint16_t svc_handle, - uint16_t svc_handle_to_include, - void *p_priv); - -/** - * Add a characteristic to service. - * - * @note this may called with the same UUID. the returned handle will be different in this case to - * distinguish multiple instances of the same char - * - * @param p_svc_handle service handle - * @param svc_handle service to which to add the characteristic - * @param p_char meta data for characteristic - * @param cback Callback function called on reception of response message - * @param p_priv pointer to private data - * - * @return @ref OS_ERR_TYPE - * @return MSG: MSG_ID_BLE_GATTS_ADD_CHARACTERISTIC @ref ble_gatts_add_char_rsp - */ -int ble_gatts_add_characteristic(svc_client_handle_t * p_svc_handle, - uint16_t svc_handle, - const struct ble_gatts_characteristic * p_char, - ble_gatts_add_char_cback_t cback, - void *p_priv); - -/** - * Add a descriptor to the last added characteristic. - * - * @note The descriptor is automatically added to the latest - * added characteristic - * - * @param p_svc_handle service handle - * @param p_desc description of the descriptor - * @param cback Callback function called on reception of response message - * @param p_priv pointer to private data - * - * @return @ref OS_ERR_TYPE - * @return MSG: MSG_ID_BLE_GATTS_ADD_DESCRIPTOR @ref ble_gatts_add_desc_rsp - */ -int ble_gatts_add_descriptor(svc_client_handle_t * p_svc_handle, - const struct ble_gatts_descriptor * p_desc, - ble_gatts_add_desc_cback_t cback, - void * p_priv); - -/** - * Start BLE Service setup before. - * - * @param p_svc_handle service handle - * @param svc_handle service to start - * @param p_priv pointer to private data - * - * @return @ref OS_ERR_TYPE - * @return MSG: MSG_ID_BLE_GATTS_START_SERVICE @ref ble_rsp - */ -int ble_gatts_start_service(svc_client_handle_t * p_svc_handle, - uint16_t svc_handle, - void *p_priv); - -/** - * Stop and remove service. - * - * @note Not yet supported - * - * @param p_svc_handle service handle - * @param svc_handle handle of characteristic to which to add the descriptor - * @param p_priv pointer to private data - * - * @return @ref OS_ERR_TYPE - * @return MSG: MSG_ID_BLE_GATTS_REMOVE_SERVICE_RSP @ref ble_rsp - */ -int ble_gatts_remove_service(svc_client_handle_t * p_svc_handle, - uint16_t svc_handle, - void *p_priv); - -/** - * Send a service change indication. - * - * @note Not yet supported - * - * @param p_svc_handle service handle - * @param conn_handle handle of the connection affected by the service layout change - * @param start_handle start handle of changed attribute handle range - * @param end_handle end handle of changed attribute handle range - * @param p_priv pointer to private data - * - * @return @ref OS_ERR_TYPE - * @return MSG: MSG_ID_BLE_GATTS_INDICATE_SERVICE_CHANGE @ref ble_gatts_rsp_t - */ -int ble_gatts_send_svc_changed(svc_client_handle_t * p_svc_handle, - uint16_t conn_handle, - uint16_t start_handle, - uint16_t end_handle, - void *p_priv); - -/** - * Set an attribute value. - * - * @param p_svc_handle service handle - * @param value_handle handle of value to change - * @param len length of attribute value to write - * @param p_value attribute value data to write - * @param offset optional offset from which on to write the attribute value data - * @param p_priv pointer to private data - * - * @return @ref OS_ERR_TYPE - * @return MSG: MSG_ID_BLE_GATTS_WR_ATTRIBUTE_VALUE ble_gatts_wr_attr_rsp_msg - */ -int ble_gatts_set_attribute_value(svc_client_handle_t * p_svc_handle, - uint16_t value_handle, - uint16_t len, - const uint8_t * p_value, - uint16_t offset, - void *p_priv); - -/** - * Get an attribute value. - * - * @param p_svc_handle service handle - * @param value_handle handle of the attribute value to retrieve - * @param len length of the attribute value to get - * @param offset optional offset from which on to get the attribute value - * @param p_priv pointer to private data - * - * @return @ref OS_ERR_TYPE - * @return MSG: MSG_ID_BLE_GATTS_RD_ATTRIBUTE_VALUE @ref ble_gatts_rd_attrib_val_rsp_t - */ -int ble_gatts_get_attribute_value(svc_client_handle_t * p_svc_handle, - uint16_t value_handle, - uint16_t len, - uint16_t offset, - void *p_priv); - -/** - * Send notification. - * - * @param p_svc_handle service handle - * @param conn_handle handle of the connection affected by the service layout change - * @param p_ind_params length of attribute value to write - * @param cback callback function to be called on reception of reception of notif response - * @param p_priv pointer to private data - * - * @return @ref OS_ERR_TYPE - * @return MSG: MSG_ID_BLE_GATTS_SEND_NOTIF_RSP @ref ble_gatts_notif_ind_rsp_msg - */ -int ble_gatts_send_notif(svc_client_handle_t * p_svc_handle, - uint16_t conn_handle, - const ble_gatts_ind_params_t * p_params, - ble_gatts_notif_ind_cback_t cback, - void *p_priv); - -/** - * Send indication. - * - * @param p_svc_handle service handle - * @param conn_handle handle of the connection affected by the service layout change - * @param p_ind_params length of attribute value to write - * @param cback callback function to be called on reception of reception of ind response - * @param p_priv pointer to private data - * - * @return @ref OS_ERR_TYPE - * @return MSG: MSG_ID_BLE_GATTS_SEND_NOTIF_RSP @ref ble_gatts_notif_ind_rsp_msg - */ -int ble_gatts_send_ind(svc_client_handle_t * p_svc_handle, - uint16_t conn_handle, - const ble_gatts_ind_params_t * p_params, - ble_gatts_notif_ind_cback_t cback, - void *p_priv); - -/** - * Write stack specific data of a previously bonded connection. - * - * @note this data is typically stored in NVRAM in relation ship to the bonded device! - * (e.g. CCD) - * - * @param p_svc_handle service handle - * @param conn_handle handle of the connection - * @param p_data data blob specific to stack to write - * @param len length of above byte stream (little endian) - * @param p_priv pointer to private data - * - * @return @ref OS_ERR_TYPE - * @return MSG: MSG_ID_BLE_GATTS_WR_CONN_ATTRIBUTES @ref ble_gatts_rsp_t - */ -int ble_gatts_write_conn_attributes(svc_client_handle_t * p_svc_handle, - uint16_t conn_handle, - const uint8_t * p_data, - uint16_t len, - void *p_priv); - -/** - * Read stack specific data of the bonded connection. - * - * @note this data is typically stored in NVRAM in relation ship to the bonded device! - * - * @param p_svc_handle service handle - * @param conn_handle handle of the connection - * @param p_priv pointer to private data - * - * @return @ref OS_ERR_TYPE - * @return MSG: MSG_ID_BLE_GATTS_RD_CONN_ATTRIBUTES @ref ble_gatts_rd_conn_attr_rsp_t - */ -int ble_gatts_read_conn_attributes(svc_client_handle_t * p_svc_handle, - uint16_t conn_handle, - void *p_priv); - -/** @} */ - -#endif diff --git a/system/libarc32_arduino101/framework/include/services/services_ids.h b/system/libarc32_arduino101/framework/include/services/services_ids.h index ccf2260c..c153a468 100644 --- a/system/libarc32_arduino101/framework/include/services/services_ids.h +++ b/system/libarc32_arduino101/framework/include/services/services_ids.h @@ -57,6 +57,7 @@ enum { CFW_LAST_SERVICE_ID = 17 }; +#define MSG_ID_BLE_SERVICE_BASE (BLE_SERVICE_ID << 10) #define BLE_SERVICE_MSG_BASE (BLE_SERVICE_ID << 10) #define BLE_SERVICE_GAP_MSG_BASE (BLE_CORE_SERVICE_ID << 10) #define MSG_ID_GPIO_BASE (SOC_GPIO_SERVICE_ID << 10) diff --git a/system/libarc32_arduino101/framework/include/util/misc.h b/system/libarc32_arduino101/framework/include/util/misc.h new file mode 100644 index 00000000..ea2cdff4 --- /dev/null +++ b/system/libarc32_arduino101/framework/include/util/misc.h @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2015, Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __MISC_H__ +#define __MISC_H__ + +/* required for offsetof */ +#include + +//#include "util/compiler.h" + +/** Generate a build time error if a condition is met + * + * @param condition The condition to be tested + * + * @note This function should be used inside a code block + */ +#define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2 * !!(condition)])) + +/** Generate a build time error if a condition is met or return 0 + * + * @param condition The condition to be tested + * + * @return 0 + */ +#define BUILD_BUG_ON_ZERO(e) (sizeof(char[1 - 2 * !!(e)]) - 1) + +/** + * Similar to BUILD_BUG_ON_ZERO + */ +#define STATIC_ASSERT(EXPR) typedef char __unused static_assert_failed[(EXPR) ? \ + 1 : -1] + +/** Generate a build time error if the parameter is not an array otherwise return 0 + * + * @param A The array to be checked. + * + * @return 0 + */ +#define __must_be_array(A) \ + BUILD_BUG_ON_ZERO (HAVE_SAME_TYPE(A, &A[0])) + +/** + * Check if the integer provided is a power of two. + * + * @param A Number to be tested. + * + * @return true if value is power of two else false. + */ +#define IS_POWER_OF_TWO(A) ((A) != 0 && (((A)-1) & (A)) == 0) + +/** + * Given a pointer on a member, return the pointer on the containing struct + * + * @param ptr Pointer to the member + * @param type Containing struct + * @param member Member name + * + * @return Casted pointer to the struct + * + * @note Use if possible CONTAINER_OF() defined in Zephyr include + */ +#define container_of(ptr, type, member) ({ \ + (type *)((char *)(ptr) - \ + offsetof(type, member)); }) + +#define MAX(a, b) ((a) > (b) ? (a) : (b)) +#define MIN(a, b) ((a) < (b) ? (a) : (b)) + +/** + * Concatenate 4 ASCII characters into an integer + * + * @param key_1 first ASCII char + * @param key_2 second ASCII char + * @param key_3 third ASCII char + * @param key_4 fourth ASCII char + * + * @return the integer representation of the four-digit string + */ +#define GEN_KEY(key_1, key_2, key_3, key_4) \ + (key_1 << 24) | (key_2 << 16) | (key_3 << 8) | key_4 + +#endif /* __MISC_H__ */ diff --git a/system/libarc32_arduino101/framework/src/cfw/service_api.c b/system/libarc32_arduino101/framework/src/cfw/service_api.c index 936fa3f9..28b5bfe5 100644 --- a/system/libarc32_arduino101/framework/src/cfw/service_api.c +++ b/system/libarc32_arduino101/framework/src/cfw/service_api.c @@ -122,54 +122,6 @@ struct cfw_message * cfw_alloc_internal_msg(int msg_id, int size, void * priv) { return evt; } -void default_msg_handler(struct cfw_message * msg, void *data) { - pr_error(LOG_MODULE_CFW, "Bug: %s should not be called data: %p", __func__, data); - cfw_dump_message(msg); -} - -void client_handle_message(struct cfw_message * msg, void *param) { - _cfw_handle_t * h = (_cfw_handle_t*)param; - switch(CFW_MESSAGE_ID(msg)) { - case MSG_ID_CFW_OPEN_SERVICE: - { - cfw_open_conn_rsp_msg_t * cnf = (cfw_open_conn_rsp_msg_t *) msg; - /** Make client handle point to server handle */ - ((svc_client_handle_t*)cnf->client_handle)->server_handle = cnf->svc_server_handle; - /** Initialize service port. */ - ((svc_client_handle_t*)cnf->client_handle)->port = cnf->port; -#ifndef CONFIG_INFRA_IS_MASTER - /* Set local port and cpu id */ - if (get_cpu_id() != cnf->cpu_id) { - port_set_port_id(cnf->port); - port_set_cpu_id(cnf->port, cnf->cpu_id); - } -#endif - break; - } - case MSG_ID_CFW_CLOSE_SERVICE: - { - /* Free client-side conn */ - bfree(msg->conn); - break; - } - default: - //Nothing to do - break; - } - h->handle_msg(msg, h->data); -} - -cfw_handle_t cfw_init(void * queue, handle_msg_cb_t cb, void *cb_data) { - _cfw_handle_t * handle = (_cfw_handle_t*)balloc(sizeof(*handle), NULL); - handle->handle_msg = cb; - handle->data = cb_data; - - handle->client_port_id = port_alloc(queue); - - cfw_port_set_handler(handle->client_port_id, client_handle_message, handle); - - return (cfw_handle_t) handle; -} int _cfw_send_message(struct cfw_message * message) { diff --git a/system/libarc32_arduino101/framework/src/cfw_platform.c b/system/libarc32_arduino101/framework/src/cfw_platform.c index b2da0288..5daa0951 100644 --- a/system/libarc32_arduino101/framework/src/cfw_platform.c +++ b/system/libarc32_arduino101/framework/src/cfw_platform.c @@ -42,10 +42,11 @@ #include "cfw/cfw_messages.h" -#include "nordic_interface.h" +#include "nble_driver.h" /* FIXME: Service manager API */ extern void _cfw_init(void *); +extern void ble_cfw_service_init(int service_id, T_QUEUE queue); extern void *services; @@ -81,21 +82,6 @@ static void free_message_ipc(struct message *msg) { extern "C" { #endif - -void cfw_platform_nordic_init(void) -{ - /* Setup UART0 for BLE communication, HW flow control required */ - SET_PIN_MODE(18, QRK_PMUX_SEL_MODEA); /* UART0_RXD */ - SET_PIN_MODE(19, QRK_PMUX_SEL_MODEA); /* UART0_TXD */ - SET_PIN_MODE(40, QRK_PMUX_SEL_MODEB); /* UART0_CTS_B */ - SET_PIN_MODE(41, QRK_PMUX_SEL_MODEB); /* UART0_RTS_B */ - - /* Reset the nordic to force sync - Warning: not working everytime */ - nordic_interface_init(service_mgr_queue); - uart_ipc_init(0); - uart_ipc_set_channel(uart_ipc_channel_open(SYNC_CHANNEL, uart_ipc_message_cback)); -} - static void cfw_platform_mbx_int_enable(void) { /* Set up mailbox interrupt handler */ @@ -116,8 +102,6 @@ void cfw_platform_init(void) set_cpu_id(CPU_ID_ARC); set_cpu_message_sender(ipc_remote_cpu, send_message_ipc); set_cpu_free_handler(ipc_remote_cpu, free_message_ipc); - set_cpu_message_sender(CPU_ID_BLE, send_message_ipc_uart); - set_cpu_free_handler(CPU_ID_BLE, free_message_ipc_uart); service_mgr_queue = queue_create(IPC_QUEUE_DEPTH, NULL); @@ -131,6 +115,7 @@ void cfw_platform_init(void) shared_data->services, shared_data->service_mgr_port_id); #else _cfw_init(service_mgr_queue); + ble_cfw_service_init(BLE_SERVICE_ID, service_mgr_queue); /* Initialized shared structure. */ shared_data->ports = port_get_port_table(); diff --git a/system/libarc32_arduino101/framework/src/infra/log.c b/system/libarc32_arduino101/framework/src/infra/log.c index c0d0ab7a..7e21decf 100644 --- a/system/libarc32_arduino101/framework/src/infra/log.c +++ b/system/libarc32_arduino101/framework/src/infra/log.c @@ -62,10 +62,12 @@ void log_init() uint8_t i; for (i = 0; i < LOG_MODULE_NUM; i++) { - global_infos.modules_filter[i].status = 1; - global_infos.modules_filter[i].log_level = LOG_LEVEL_INFO; + global_infos.modules_filter[i].status = true; + global_infos.modules_filter[i].log_level = LOG_LEVEL_DEBUG; } - global_infos.log_level_limit = LOG_LEVEL_INFO; + global_infos.log_level_limit = LOG_LEVEL_DEBUG; + + global_infos.modules_filter[LOG_MODULE_MAIN].log_level = LOG_LEVEL_INFO; log_impl_init(); } diff --git a/system/libarc32_arduino101/framework/src/infra/log_impl_printk.c b/system/libarc32_arduino101/framework/src/infra/log_impl_printk.c index ed8f1e99..958b7521 100644 --- a/system/libarc32_arduino101/framework/src/infra/log_impl_printk.c +++ b/system/libarc32_arduino101/framework/src/infra/log_impl_printk.c @@ -32,13 +32,14 @@ #include "log_impl.h" #include "infra/log_backend.h" -extern int printk(const char * format, ...); +//extern int printk(const char * format, ...); +extern void printk(const char *fmt, va_list args); uint32_t log_write_msg(uint8_t level, uint8_t module, const char *format, va_list args) { // TODO - implement printk -// printk(format, args); + printk(format, args); return 0; } diff --git a/system/libarc32_arduino101/framework/src/nordic_interface.c b/system/libarc32_arduino101/framework/src/nordic_interface.c deleted file mode 100644 index daee0f12..00000000 --- a/system/libarc32_arduino101/framework/src/nordic_interface.c +++ /dev/null @@ -1,192 +0,0 @@ -/* - * Copyright (c) 2015, Intel Corporation. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its contributors - * may be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include -#include "os/os.h" -#include "cfw/cfw.h" -#include "cfw/cfw_debug.h" -#include "cfw/cfw_internal.h" -#include "cfw/cfw_messages.h" -#include "infra/ipc_uart.h" -#include "infra/ipc_requests.h" -#include "infra/log.h" -#include "infra/message.h" -#include "infra/time.h" -#include "drivers/soc_gpio.h" -#include "platform.h" - -#include "portable.h" - -/* Macro definition for reset pin */ -#define BLE_SW_CLK_PIN 27 -#define BLE_SWDIO_PIN 6 -#define RESET_PIN BLE_SWDIO_PIN -#define ATP_BLE_INT 5 - -static T_QUEUE service_mgr_queue; - -/* When we set val to 1 it will wake up the Nordic, setting it to 0 - * will set it back to sleep. */ -static int nordic_wake_assert(bool val) -{ - uint8_t ret = soc_gpio_write(SOC_GPIO_32_ID, ATP_BLE_INT, val); - if (ret != DRV_RC_OK) - pr_error(LOG_MODULE_IPC, "Error setting ATP_BLE_INT %d", val); - return ret; -} - -void nordic_wake_deassert(void* ignored) -{ - nordic_wake_assert(0); -} - -int send_message_ipc_uart(struct cfw_message * message) { - int ret = uart_ipc_send_message(uart_ipc_get_channel(), - CFW_MESSAGE_LEN(message), message); - message_free((struct message *)message); - return ret; -} - -void free_message_ipc_uart(void * ptr) { - bfree(ptr); -} - -/** - * IPC CFW message format is the following (little endian): - * ------------------------------------- - * | len: 2 bytes | chan 1 byte: sender cpu id: 1 byte | - * ------------------------------------- - * | REQUEST_ID | payload | - * ------------------------------------- - * - * For TYPE_MESSAGE request, the payload is the message copy. - * For TYPE_FREE is not valid (this ipc is not shared mem based) - */ -void uart_ipc_message_cback(uint8_t cpu_id, int channel, int len, void * p_data) -{ - struct cfw_message * msg; - unsigned int request = *(uint32_t*)p_data; - - switch (request) { - case IPC_MSG_TYPE_MESSAGE: - { - OS_ERR_TYPE error = E_OS_OK; - int size = len - sizeof(uint32_t); - msg = (struct cfw_message *)message_alloc(size, &error); - if (error != E_OS_OK) - pr_error(LOG_MODULE_IPC, "NO MEM: error: %d size: %d", error, size); - else { - memcpy(msg, (uint8_t *)p_data + sizeof(uint32_t), size); - handle_ipc_sync_request(cpu_id, request, 0, 0, msg); - } - break; - } - case IPC_REQUEST_ALLOC_PORT: - { - unsigned int ret; - unsigned int error; - uint16_t port_id = port_alloc(NULL); - port_set_cpu_id(port_id, cpu_id); - ret = port_id; - pr_info(LOG_MODULE_IPC, "%s return port_id %d", __func__, ret); - error = uart_ipc_send_sync_resp(channel, request, ret, 0, NULL); - if (error) - pr_error(LOG_MODULE_IPC, "%s returned error from ipc uart sync resp %d", __func__, error); - break; - } - default: - { - unsigned int error; - int32_t * p = ((int32_t *) p_data) + 1; - int32_t param0 = *p++; - int32_t param1 = *p++; - void * ptr = (void *) *p; - pr_info(LOG_MODULE_IPC, "%s request %xh, param1 %d, param2 %d", __func__, request, param0, param1); - handle_ipc_sync_request(cpu_id, request, param0, param1, ptr); - error = uart_ipc_send_sync_resp(channel, request, 0, 0, NULL); - if (error) - pr_error(LOG_MODULE_IPC, "%s returned error from ipc uart sync resp %d", __func__, error); - break; - } - } - bfree(p_data); - - /* Dequeue and process any new messages received */ - while(queue_process_message(service_mgr_queue) != 0); -} - -/* Nordic reset is achieved by asserting low the SWDIO pin. - * However, the Nordic chip can be in SWD debug mode, and NRF_POWER->RESET = 0 due to, - * other constraints: therefore, this reset might not work everytime, especially after - * flashing or debugging. - */ -static int nordic_reset(void) -{ - /* RESET_PIN depends on the board and the local configuration: check top of file */ - uint32_t delay_until; - gpio_cfg_data_t pin_cfg = { .gpio_type = GPIO_OUTPUT }; - - soc_gpio_set_config(SOC_GPIO_32_ID, RESET_PIN, &pin_cfg); - - /* Reset hold time is 0.2us (normal) or 100us (SWD debug) */ - soc_gpio_write(SOC_GPIO_32_ID, RESET_PIN, 0); - /* Wait for ~1ms */ - delay_until = get_uptime_32k() + 32768; - while (get_uptime_32k() < delay_until); - /* De-assert the reset */ - soc_gpio_write(SOC_GPIO_32_ID, RESET_PIN, 1); - - /* Set back GPIO to input to avoid interfering with external debugger */ - pin_cfg.gpio_type = GPIO_INPUT; - soc_gpio_set_config(SOC_GPIO_32_ID, RESET_PIN, &pin_cfg); - - return 0; -} - -int nordic_interface_init(T_QUEUE queue) -{ - uint8_t ret; - gpio_cfg_data_t config; - - service_mgr_queue = queue; - - config.gpio_type = GPIO_OUTPUT; - ret = soc_gpio_set_config(SOC_GPIO_32_ID, ATP_BLE_INT, &config); - if (ret != DRV_RC_OK) - return -1; - ret = nordic_wake_assert(1); - if (ret != DRV_RC_OK) - return -1; - ret = nordic_reset(); - if (ret != DRV_RC_OK) - return -1; - - return 0; -} diff --git a/system/libarc32_arduino101/framework/src/os/os.c b/system/libarc32_arduino101/framework/src/os/os.c index 63aa31f6..ed84eb8b 100644 --- a/system/libarc32_arduino101/framework/src/os/os.c +++ b/system/libarc32_arduino101/framework/src/os/os.c @@ -34,6 +34,7 @@ /************************* MEMORY *************************/ #ifdef TRACK_ALLOCS +#include "infra/log.h" int alloc_count = 0; #endif @@ -45,6 +46,7 @@ void * cfw_alloc(int size, OS_ERR_TYPE * err) { (*(int*) ptr) = size; #ifdef TRACK_ALLOCS alloc_count++; + pr_info(0, "alloc_count - %d", alloc_count); #endif interrupt_unlock(flags); return ptr; @@ -56,6 +58,7 @@ void cfw_free(void * ptr, OS_ERR_TYPE * err) { int flags = interrupt_lock(); #ifdef TRACK_ALLOCS alloc_count--; + pr_info(0, "alloc_countf - %d", alloc_count); #endif free(ptr); interrupt_unlock(flags); diff --git a/system/libarc32_arduino101/framework/src/os/panic.c b/system/libarc32_arduino101/framework/src/os/panic.c new file mode 100644 index 00000000..9fe88ef9 --- /dev/null +++ b/system/libarc32_arduino101/framework/src/os/panic.c @@ -0,0 +1,16 @@ + +#include "os/os.h" + +extern void _do_fault(); +void panic(int x) +{ + _do_fault(); +} + + +void __assert_fail() +{ + panic(-10); +} + + diff --git a/system/libarc32_arduino101/framework/src/services/ble/ble_protocol.h b/system/libarc32_arduino101/framework/src/services/ble/ble_protocol.h deleted file mode 100644 index 460e7458..00000000 --- a/system/libarc32_arduino101/framework/src/services/ble/ble_protocol.h +++ /dev/null @@ -1,233 +0,0 @@ -/* - * Copyright (c) 2015, Intel Corporation. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its contributors - * may be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __BLE_PROTOCOL_H__ -#define __BLE_PROTOCOL_H__ - -/** - * @defgroup ble_protocol BLE protocol definitions - * - * BT Spec definitions. - * @ingroup ble_service - * @{ - * - * Bluetooth SIG defined macros and enum extracted from Bluetooth Spec 4.2 - */ -#define BLE_MAX_DEVICE_NAME 20 /**< Max BLE device name length, spec size: 248 */ -#define BLE_MAX_ADV_SIZE 31 - -/** Advertising Data Type. */ -#define BLE_ADV_TYPE_FLAGS 0x01 /* Flags */ -#define BLE_ADV_TYPE_INC_16_UUID 0x02 /* Incomplete List of 16-bit Service Class UUIDs */ -#define BLE_ADV_TYPE_COMP_16_UUID 0x03 /* Complete List of 16-bit Service Class UUIDs */ -#define BLE_ADV_TYPE_INC_32_UUID 0x04 /* Incomplete List of 32-bit Service Class UUIDs */ -#define BLE_ADV_TYPE_COMP_32_UUID 0x05 /* Complete List of 32-bit Service Class UUIDs */ -#define BLE_ADV_TYPE_INC_128_UUID 0x06 /* Incomplete List of 128-bit Service Class UUIDs */ -#define BLE_ADV_TYPE_COMP_128_UUID 0x07 /* Complete List of 128-bit Service Class UUIDs */ -#define BLE_ADV_TYPE_SHORT_LOCAL_NAME 0x08 /* Shortened Local Name */ -#define BLE_ADV_TYPE_COMP_LOCAL_NAME 0x09 /* Complete Local Name */ -#define BLE_ADV_TYPE_TX_POWER 0x0A /* Tx Power Level */ -#define BLE_ADV_TYPE_CLASS 0x0D /* Class of Device */ -#define BLE_ADV_TYPE_PAIRING_C 0x0E /* Simple Pairing Hash C */ -#define BLE_ADV_TYPE_PAIRING_C_192 0x0E /* Simple Pairing Hash C-192 */ -#define BLE_ADV_TYPE_PAIRING_R_192 0x0F /* Simple Pairing Randomizer R-192 */ -#define BLE_ADV_TYPE_DEVICE_ID 0x10 /* Device ID */ -#define BLE_ADV_TYPE_TK_VALUE 0x10 /* Security Manager TK Value */ -#define BLE_ADV_TYPE_OOB_FLAGS 0x11 /* Security Manager Out of Band Flags */ -#define BLE_ADV_TYPE_CONN_INTERVAL_RANGE 0x12 /* Slave Connection Interval Range */ -#define BLE_ADV_TYPE_SERVICE_SOLICITATION_16_UUID 0x14 /* List of 16-bit Service Solicitation UUIDs */ -#define BLE_ADV_TYPE_SERVICE_SOLICITATION_32_UUID 0x1F /* List of 32-bit Service Solicitation UUIDs */ -#define BLE_ADV_TYPE_SERVICE_SOLICITATION_128_UUID 0x15 /* List of 128-bit Service Solicitation UUIDs */ -#define BLE_ADV_TYPE_SERVICE_DATA 0x16 /* Service Data */ -#define BLE_ADV_TYPE_SERVICE_DATA_16_UUID 0x16 /* Service Data - 16-bit UUID */ -#define BLE_ADV_TYPE_SERVICE_DATA_32_UUID 0x20 /* Service Data - 32-bit UUID */ -#define BLE_ADV_TYPE_SERVICE_DATA_128_UUID 0x21 /* Service Data - 128-bit UUID */ -#define BLE_ADV_TYPE_SEC_CONF_VALUE 0x22 /* LE Secure Connections Confirmation Value */ -#define BLE_ADV_TYPE_SEC_RANDOM_VALUE 0x23 /* LE Secure Connections Random Value */ -#define BLE_ADV_TYPE_PUB_TARGET_ADDR 0x17 /* Public Target Address */ -#define BLE_ADV_TYPE_APPEARANCE 0x19 /* Appearance */ -#define BLE_ADV_TYPE_ADV_INTERVAL 0x1A /* Advertising Interval */ -#define BLE_ADV_TYPE_DEVICE_ADDR 0x1B /* LE Bluetooth Device Address */ -#define BLE_ADV_TYPE_ROLE 0x1C /* LE Role */ -#define BLE_ADV_TYPE_PAIRING_C_256 0x1D /* Simple Pairing Hash C-256 */ -#define BLE_ADV_TYPE_PAIRING_R_256 0x1E /* Simple Pairing Randomizer R-256 */ -#define BLE_ADV_TYPE_3D 0x3D /* 3D Information Data */ -#define BLE_ADV_TYPE_MANUFACTURER 0xFF /* Manufacturer Specific Data */ - -/** BLE Service UUID Definitions. */ -#define BLE_SVC_UUID_IMMEDIATE_ALERT_SERVICE 0x1802 /**< Immediate Alert service UUID. */ -#define BLE_SVC_UUID_LINK_LOSS_SERVICE 0x1803 /**< Link Loss service UUID. */ -#define BLE_SVC_UUID_TX_POWER_SERVICE 0x1804 /**< TX Power service UUID. */ -#define BLE_SVC_UUID_CURRENT_TIME_SERVICE 0x1805 /**< Current Time service UUID. */ -#define BLE_SVC_UUID_REFERENCE_TIME_UPDATE_SERVICE 0x1806 /**< Reference Time Update service UUID. */ -#define BLE_SVC_UUID_NEXT_DST_CHANGE_SERVICE 0x1807 /**< Next Dst Change service UUID. */ -#define BLE_SVC_UUID_GLUCOSE_SERVICE 0x1808 /**< Glucose service UUID. */ -#define BLE_SVC_UUID_HEALTH_THERMOMETER_SERVICE 0x1809 /**< Health Thermometer service UUID. */ -#define BLE_SVC_UUID_DEVICE_INFORMATION_SERVICE 0x180A /**< Device Information service UUID. */ -#define BLE_SVC_UUID_HEART_RATE_SERVICE 0x180D /**< Heart Rate service UUID. */ -#define BLE_SVC_UUID_PHONE_ALERT_STATUS_SERVICE 0x180E /**< Phone Alert Status service UUID. */ -#define BLE_SVC_UUID_BATTERY_SERVICE 0x180F /**< Battery service UUID. */ -#define BLE_SVC_UUID_BLOOD_PRESSURE_SERVICE 0x1810 /**< Blood Pressure service UUID. */ -#define BLE_SVC_UUID_ALERT_NOTIFICATION_SERVICE 0x1811 /**< Alert Notification service UUID. */ -#define BLE_SVC_UUID_HUMAN_INTERFACE_DEVICE_SERVICE 0x1812 /**< Human Interface Device service UUID. */ -#define BLE_SVC_UUID_SCAN_PARAMETERS_SERVICE 0x1813 /**< Scan Parameters service UUID. */ -#define BLE_SVC_UUID_RUNNING_SPEED_AND_CADENCE 0x1814 /**< Running Speed and Cadence service UUID. */ -#define BLE_SVC_UUID_CYCLING_SPEED_AND_CADENCE 0x1816 /**< Cycling Speed and Cadence service UUID. */ - -#define BLE_SVC_GAP_ADV_FLAG_LE_LIMITED_DISC_MODE (0x01) /**< LE Limited Discoverable Mode. */ -#define BLE_SVC_GAP_ADV_FLAG_LE_GENERAL_DISC_MODE (0x02) /**< LE General Discoverable Mode. */ -#define BLE_SVC_GAP_ADV_FLAG_BR_EDR_NOT_SUPPORTED (0x04) /**< BR/EDR not supported. */ -#define BLE_SVC_GAP_ADV_FLAG_LE_BR_EDR_CONTROLLER (0x08) /**< Simultaneous LE and BR/EDR, Controller. */ -#define BLE_SVC_GAP_ADV_FLAG_LE_BR_EDR_HOST (0x10) /**< Simultaneous LE and BR/EDR, Host. */ -#define BLE_SVC_GAP_ADV_FLAGS_LE_ONLY_LIMITED_DISC_MODE (BLE_SVC_GAP_ADV_FLAG_LE_LIMITED_DISC_MODE | BLE_SVC_GAP_ADV_FLAG_BR_EDR_NOT_SUPPORTED) /**< LE Limited Discoverable Mode, BR/EDR not supported. */ -#define BLE_SVC_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE (BLE_SVC_GAP_ADV_FLAG_LE_GENERAL_DISC_MODE | BLE_SVC_GAP_ADV_FLAG_BR_EDR_NOT_SUPPORTED) /**< LE General Discoverable Mode, BR/EDR not supported. */ - - -/** - * Characteristics UUID definitions. - */ - -/* GAP */ -#define BLE_GAP_DEVICE_NAME 0x2A00 -#define BLE_GAP_APPEARANCE 0x2A01 -#define BLE_GAP_PER_PRIVACY_FLAG 0x2A02 -#define BLE_GAP_RECONN_ADDR 0x2A03 -#define BLE_GAP_PREF_CONN_PARAM 0x2A04 - -/* DIS */ -#define BLE_DIS_MANUFACTURER_NAME 0x2A29 -#define BLE_DIS_MODEL_NB 0x2A24 -#define BLE_DIS_SERIAL_NB 0x2A25 -#define BLE_DIS_FW_REV 0x2A26 -#define BLE_DIS_HW_REV 0x2A27 -#define BLE_DIS_SW_REV 0x2A28 -#define BLE_DIS_SYS_ID 0x2A23 -#define BLE_DIS_CERTIF_DATA_LIST 0x2A2A -#define BLE_DIS_PNP_ID 0x2A50 - -/* BATTERY */ -#define BLE_BAT_BAT_LEVEL 0x2A19 - -/* HR */ -#define BLE_HEART_RATE_MEASUREMENT 0x2A37 -#define BLE_HEART_RATE_SENSOR_LOCATION 0x2A38 -#define BLE_HEART_RATE_CONTROL_POINT 0x2A39 - -/* RSC */ -#define BLE_RSC_MEASUREMENT 0x2A53 -#define BLE_RSC_SENSOR_LOCATION 0x2A5D -#define BLE_RSC_SUPPORTED_FEATURE 0x2A54 -#define BLE_RSC_CONTROL_POINT 0x2A55 - -/*CSC */ -#define BLE_CSC_MEASUREMENT 0x2A5B -#define BLE_CSC_SENSOR_LOCATION BLE_RSC_SENSOR_LOCATION -#define BLE_CSC_SUPPORTED_FEATURE 0x2A5C -#define BLE_CSC_CONTROL_POINT 0x2A55 - -/* CP */ -#define BLE_CP_MEASUREMENT 0x2A63 -#define BLE_CP_SENSOR_LOCATION BLE_RSC_SENSOR_LOCATION -#define BLE_CP_SUPPORTED_FEATURE 0x2A65 -#define BLE_CP_POWER_VECTOR 0x2A64 -#define BLE_CP_CONTROL_POINT 0x2A66 - -/* HCI status (error) codes as per BT spec */ -#define HCI_REMOTE_USER_TERMINATED_CONNECTION 0x13 -#define HCI_REMOTE_DEV_TERMINATION_DUE_TO_LOW_RESOURCES 0x14 -#define HCI_REMOTE_DEV_TERMINATION_DUE_TO_POWER_OFF 0x15 -#define HCI_LOCAL_HOST_TERMINATED_CONNECTION 0x16 - -/** BLE GAP Appearance Characteristic definitions. - * - * See http://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.gap.appearance.xml - */ -#define BLE_GAP_APPEARANCE_TYPE_UNKNOWN 0 -#define BLE_GAP_APPEARANCE_TYPE_GENERIC_PHONE 64 -#define BLE_GAP_APPEARANCE_TYPE_GENERIC_COMPUTER 128 -#define BLE_GAP_APPEARANCE_TYPE_GENERIC_WATCH 192 -#define BLE_GAP_APPEARANCE_TYPE_WATCH_SPORTS_WATCH 193 -#define BLE_GAP_APPEARANCE_TYPE_GENERIC_CLOCK 256 -#define BLE_GAP_APPEARANCE_TYPE_GENERIC_DISPLAY 320 -#define BLE_GAP_APPEARANCE_TYPE_GENERIC_REMOTE_CONTROL 384 -#define BLE_GAP_APPEARANCE_TYPE_GENERIC_EYE_GLASSES 448 -#define BLE_GAP_APPEARANCE_TYPE_GENERIC_TAG 512 -#define BLE_GAP_APPEARANCE_TYPE_GENERIC_KEYRING 576 -#define BLE_GAP_APPEARANCE_TYPE_GENERIC_MEDIA_PLAYER 640 -#define BLE_GAP_APPEARANCE_TYPE_GENERIC_BARCODE_SCANNER 704 -#define BLE_GAP_APPEARANCE_TYPE_GENERIC_THERMOMETER 768 -#define BLE_GAP_APPEARANCE_TYPE_THERMOMETER_EAR 769 -#define BLE_GAP_APPEARANCE_TYPE_GENERIC_HEART_RATE_SENSOR 832 -#define BLE_GAP_APPEARANCE_TYPE_HEART_RATE_SENSOR_HEART_RATE_BELT 833 -#define BLE_GAP_APPEARANCE_TYPE_GENERIC_BLOOD_PRESSURE 896 -#define BLE_GAP_APPEARANCE_TYPE_BLOOD_PRESSURE_ARM 897 -#define BLE_GAP_APPEARANCE_TYPE_BLOOD_PRESSURE_WRIST 898 -#define BLE_GAP_APPEARANCE_TYPE_GENERIC_HID 960 -#define BLE_GAP_APPEARANCE_TYPE_HID_KEYBOARD 961 -#define BLE_GAP_APPEARANCE_TYPE_HID_MOUSE 962 -#define BLE_GAP_APPEARANCE_TYPE_HID_JOYSTICK 963 -#define BLE_GAP_APPEARANCE_TYPE_HID_GAMEPAD 964 -#define BLE_GAP_APPEARANCE_TYPE_HID_DIGITIZERSUBTYPE 965 -#define BLE_GAP_APPEARANCE_TYPE_HID_CARD_READER 966 -#define BLE_GAP_APPEARANCE_TYPE_HID_DIGITAL_PEN 967 -#define BLE_GAP_APPEARANCE_TYPE_HID_BARCODE 968 -#define BLE_GAP_APPEARANCE_TYPE_GENERIC_GLUCOSE_METER 1024 -#define BLE_GAP_APPEARANCE_TYPE_GENERIC_RUNNING_WALKING_SENSOR 1088 -#define BLE_GAP_APPEARANCE_TYPE_RUNNING_WALKING_SENSOR_IN_SHOE 1089 -#define BLE_GAP_APPEARANCE_TYPE_RUNNING_WALKING_SENSOR_ON_SHOE 1090 -#define BLE_GAP_APPEARANCE_TYPE_RUNNING_WALKING_SENSOR_ON_HIP 1091 -#define BLE_GAP_APPEARANCE_TYPE_GENERIC_CYCLING 1152 -#define BLE_GAP_APPEARANCE_TYPE_CYCLING_CYCLING_COMPUTER 1153 -#define BLE_GAP_APPEARANCE_TYPE_CYCLING_SPEED_SENSOR 1154 -#define BLE_GAP_APPEARANCE_TYPE_CYCLING_CADENCE_SENSOR 1155 -#define BLE_GAP_APPEARANCE_TYPE_CYCLING_POWER_SENSOR 1156 -#define BLE_GAP_APPEARANCE_TYPE_CYCLING_SPEED_CADENCE_SENSOR 1157 -#define BLE_GAP_APPEARANCE_TYPE_GENERIC_PULSE_OXIMETER 3136 -#define BLE_GAP_APPEARANCE_TYPE_PULSE_OXIMETER_FINGERTIP 3137 -#define BLE_GAP_APPEARANCE_TYPE_PULSE_OXIMETER_WRIST_WORN 3138 -#define BLE_GAP_APPEARANCE_TYPE_GENERIC_WEIGHT_SCALE 3200 -#define BLE_GAP_APPEARANCE_TYPE_GENERIC_OUTDOOR_SPORTS_ACT 5184 -#define BLE_GAP_APPEARANCE_TYPE_OUTDOOR_SPORTS_ACT_LOC_DISP 5185 -#define BLE_GAP_APPEARANCE_TYPE_OUTDOOR_SPORTS_ACT_LOC_AND_NAV_DISP 5186 -#define BLE_GAP_APPEARANCE_TYPE_OUTDOOR_SPORTS_ACT_LOC_POD 5187 -#define BLE_GAP_APPEARANCE_TYPE_OUTDOOR_SPORTS_ACT_LOC_AND_NAV_POD 5188 - -/** - * DTM commands, opcodes, indexes. - */ -#define DTM_HCI_CMD 0x01 -#define DTM_HCI_OPCODE2 0x20 - -#define DTM_HCI_STATUS_IDX 6 -#define DTM_HCI_LE_END_IDX (DTM_HCI_STATUS_IDX + 1) - -/** @} */ - -#endif diff --git a/system/libarc32_arduino101/framework/src/services/ble/ble_service_core_int.h b/system/libarc32_arduino101/framework/src/services/ble/ble_service_core_int.h deleted file mode 100644 index d2b9311d..00000000 --- a/system/libarc32_arduino101/framework/src/services/ble/ble_service_core_int.h +++ /dev/null @@ -1,207 +0,0 @@ -/* - * Copyright (c) 2015, Intel Corporation. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its contributors - * may be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __BLE_SERVICE_CORE_INT_H__ -#define __BLE_SERVICE_CORE_INT_H__ - -#include -#include "services/ble/ble_service_gap_api.h" -#include "services/ble/ble_service_gattc_api.h" - -/* Forward declarations */ -struct _ble_service_cb; -struct ble_enable_req_msg; - -/** - * BLE common structures. - */ - -struct ble_svc_string { - uint8_t *p_string; /**< String utf8 encoded */ - uint8_t len; /**< length of string */ -}; - -struct ble_svc_sec_mode { - uint8_t rd_perm; - uint8_t wr_perm; -}; - -struct ble_svc_cccd_sec_mode { - uint8_t cccd_wr_perm; - uint8_t rd_perm; /**< Read permissions. */ - uint8_t wr_perm; /**< Write permissions. */ -}; - -struct ble_svc_report_reference { - uint8_t report_id; /**< Non-zero value if these is more than one instance of the same Report Type */ - uint8_t report_type; /**< Type of Report characteristic */ -}; - -struct ble_gap_write_config_req_msg { - struct cfw_message header; /**< Component framework message header (@ref cfw), MUST be first element of structure */ - uint16_t appearance; - uint8_t bda_len; - uint8_t name_len; - int8_t tx_power; - struct ble_gap_connection_params peripheral_conn_params; - struct ble_gap_connection_params central_conn_params; - uint8_t data[]; -}; - -struct ble_gap_wr_adv_data_req_msg { - struct cfw_message header; /**< Component framework message header (@ref cfw), MUST be first element of structure */ - uint8_t adv_len; - uint8_t scan_rsp_len; - uint8_t data[]; - /* adv_data, - * scan_rsp_dat */ -}; - -struct ble_gap_start_advertise_req_msg { - struct cfw_message header; /**< Component framework message header (@ref cfw), MUST be first element of structure */ - uint16_t timeout; - uint16_t interval_min; /**< min interval 0xffff: use default 0x0800 */ - uint16_t interval_max; /**< max interval 0xffff: use default 0x0800 */ - uint8_t type; /**< advertisement types @ref GAP_ADV_TYPES */ - uint8_t filter_policy; /**< filter policy to apply with white list */ - uint8_t options; /**< options see @ref BLE_GAP_ADV_OPTIONS (to be ORed) */ - uint8_t bda_len; /**< non 0 if peer_bda is present */ - uint8_t peer_bda[]; /**< format ble_addr_t */ -}; - -struct ble_gap_conn_update_req_msg { - struct cfw_message header; /**< Component framework message header (@ref cfw), MUST be first element of structure */ - uint16_t conn_handle; - struct ble_gap_connection_params conn_params; -}; - -struct ble_gap_svc_local_name_req { - uint8_t sec_mode; /**< security mode for writing device name, @ref BLE_GAP_SEC_MODES (GAP_SEC_NO_PERMISSION: write forbidden) */ - uint8_t authorization; /**< 0: no authorization, 1: authorization required */ - uint8_t len; /**< device name length (0-248) */ - uint8_t name_array[]; /**< name to to write */ -}; - -struct ble_gap_service_write_req_msg { - struct cfw_message header; /**< Component framework message header (@ref cfw), MUST be first element of structure */ - uint16_t attr_type; /**< GAP Characteristics attribute type @ref BLE_GAP_SVC_ATTR_TYPE */ - union { - struct ble_gap_svc_local_name_req name; - uint16_t appearance; /**< Appearance UUID */ - struct ble_gap_connection_params conn_params; - /**< Preferred Peripheral Connection Parameters */ - uint8_t car; /**< Central Address Resolution support 0: no, 1: yes */ - }; -}; - -struct ble_gap_disconnect_req_msg { - struct cfw_message header; /**< Component framework message header (@ref cfw), MUST be first element of structure */ - uint16_t conn_handle; /**< Connection handle*/ - uint8_t reason; /**< Reason of the disconnect*/ -}; - -struct ble_gap_sm_config_req_msg { - struct cfw_message header; /**< Component framework message header (@ref cfw), MUST be first element of structure */ - struct ble_gap_sm_config_params params; -}; - -struct ble_gap_sm_pairing_req_msg { - struct cfw_message header; /**< Component framework message header (@ref cfw), MUST be first element of structure */ - struct ble_gap_sm_pairing_params params; - uint16_t conn_handle; -}; - -struct ble_dtm_test_req_msg { - struct cfw_message header; /**< Component framework message header (@ref cfw), MUST be first element of structure */ - struct ble_test_cmd params; -}; - -struct ble_gap_set_rssi_report_req_msg { - struct cfw_message header; /**< Component framework message header (@ref cfw), MUST be first element of structure */ - struct rssi_report_params params; /**< RSSI report config @ref rssi_report_cfg */ -}; - -struct ble_gattc_discover_primary_service_req_msg { - struct cfw_message header; - uint16_t conn_handle; /**< Connection handle */ - uint8_t data[]; /**< Variable length data of the request (UUID) */ -}; - -struct ble_gattc_discover_included_service_req_msg { - struct cfw_message header; - uint16_t conn_handle; - struct ble_gattc_handle_range handle_range; -}; - -struct ble_gattc_discover_characteristic_req_msg { - struct cfw_message header; - uint16_t conn_handle; - struct ble_gattc_handle_range handle_range; -}; - -struct ble_gattc_discover_descriptor_req_msg { - struct cfw_message header; - uint16_t conn_handle; - struct ble_gattc_handle_range handle_range; -}; - -struct ble_gattc_read_characteristic_req_msg { - struct cfw_message header; /**< Component framework message header (@ref cfw), MUST be first element of structure */ - uint16_t conn_handle; /**< Connection handle*/ - uint16_t char_handle; /**< handle of the attribute to be read */ - uint16_t offset; /**< offset into the attribute value to be read */ -}; - -struct _ble_gattc_wr_characteristic { - uint16_t char_handle; /**< handle of characteristic */ - uint16_t len; /**< if len is bigger then ATT MTU size, the controller fragment buffer itself */ - uint8_t wr_type; /**< type of write operation @ref BLE_GATT_WR_OP_TYPES */ - uint8_t value[]; /**< characteristic value to write */ -}; - -struct ble_gattc_write_char_op_req_msg { - struct cfw_message header; - uint16_t conn_handle; - struct _ble_gattc_wr_characteristic wr_char_param; -}; - -/** - * Generic BLE controller commands. - */ -struct ble_generic_cmd_req_msg { - struct cfw_message header; /**< Component framework message header (@ref cfw), MUST be first element of structure */ -}; - - -void ble_core_resume_enable(struct ble_enable_req_msg *req, struct _ble_service_cb * p_cb, uint8_t * p_name); - -void ble_core_delete_conn_params_timer(void); - -#endif diff --git a/system/libarc32_arduino101/framework/src/services/ble/ble_service_gap_api.c b/system/libarc32_arduino101/framework/src/services/ble/ble_service_gap_api.c deleted file mode 100644 index 6b772864..00000000 --- a/system/libarc32_arduino101/framework/src/services/ble/ble_service_gap_api.c +++ /dev/null @@ -1,384 +0,0 @@ -/* - * Copyright (c) 2015, Intel Corporation. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its contributors - * may be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include -#include "services/ble/ble_service_gap_api.h" -#include "ble_protocol.h" -#include "ble_service_core_int.h" -#include "infra/log.h" - -int ble_gap_set_enable_config(svc_client_handle_t * p_svc_handle, - const struct ble_wr_config * p_config, - void * p_priv) -{ - struct ble_gap_write_config_req_msg *msg; - int total_len = sizeof(*msg); - int str_len = 0; - - if (p_config->p_bda) - total_len += sizeof(ble_addr_t); - if (p_config->p_name) { - str_len = strlen((char *)p_config->p_name); - if (str_len > BLE_MAX_DEVICE_NAME) - return -2; - total_len += str_len; - } - msg = (struct ble_gap_write_config_req_msg *) - cfw_alloc_message_for_service(p_svc_handle, - MSG_ID_BLE_GAP_WR_CONF_REQ, - total_len, - p_priv); - msg->name_len = str_len; - msg->appearance = p_config->appearance; - msg->tx_power = p_config->tx_power; - msg->central_conn_params = p_config->central_conn_params; - msg->peripheral_conn_params = p_config->peripheral_conn_params; - if (p_config->p_bda) { - msg->bda_len = sizeof(ble_addr_t); - memcpy(msg->data, p_config->p_bda, msg->bda_len); - } else - msg->bda_len = 0; - if (p_config->p_name) - strcpy((char *)&msg->data[msg->bda_len], (char *)p_config->p_name); - - return cfw_send_message(msg); -} - -int ble_gap_read_bda(svc_client_handle_t * p_svc_handle, void * p_priv) -{ - struct cfw_message *msg = cfw_alloc_message_for_service(p_svc_handle, - MSG_ID_BLE_GAP_RD_BDA_REQ, - sizeof(*msg), - p_priv); - return cfw_send_message(msg); -} - -int ble_gap_wr_adv_data(svc_client_handle_t * p_svc_handle, - const struct ble_gap_adv_rsp_data * p_adv_data, - const struct ble_gap_adv_rsp_data * p_scan_data, - void * p_priv) -{ - int data_len = sizeof(struct ble_gap_wr_adv_data_req_msg); - struct ble_gap_wr_adv_data_req_msg *msg; - - if (NULL != p_adv_data) - data_len += p_adv_data->len; - if (NULL != p_scan_data) - data_len += p_scan_data->len; - - msg = (struct ble_gap_wr_adv_data_req_msg *)cfw_alloc_message_for_service( - p_svc_handle, MSG_ID_BLE_GAP_WR_ADV_DATA_REQ, - data_len, p_priv); - - if (NULL != p_adv_data) { - int i; - msg->adv_len = p_adv_data->len; - for (i = 0; i < msg->adv_len; i++) - msg->data[i] = p_adv_data->p_data[i]; - } else - msg->adv_len = 0; - - if (NULL != p_scan_data) { - int i; - msg->scan_rsp_len = p_scan_data->len; - for (i = 0; i < msg->adv_len; i++) - msg->data[msg->adv_len + i] = p_scan_data->p_data[i]; - } else - msg->scan_rsp_len = 0; - - return cfw_send_message(msg); -} - - -int ble_gap_wr_white_list(svc_client_handle_t * p_svc_handle, - const struct ble_gap_whitelist_info * p_white_list, - void * p_priv) -{ - struct cfw_message *msg = cfw_alloc_message_for_service(p_svc_handle, - MSG_ID_BLE_GAP_WR_WHITE_LIST_REQ, - sizeof(*msg), - p_priv); - return cfw_send_message(msg); -} - -int ble_gap_clr_white_list(svc_client_handle_t * p_svc_handle, - uint32_t wl_hdl, void *p_priv) -{ - struct cfw_message *msg = cfw_alloc_message_for_service(p_svc_handle, - MSG_ID_BLE_GAP_CLR_WHITE_LIST_REQ, - sizeof(*msg), - p_priv); - return cfw_send_message(msg); -} - -int ble_gap_start_advertise(svc_client_handle_t * p_svc_handle, - const ble_gap_adv_param_t * p_adv_param, - void *p_priv) -{ - struct ble_gap_start_advertise_req_msg *msg; - int data_len = sizeof(struct ble_gap_start_advertise_req_msg); - - if ((NULL != p_adv_param) && (NULL != p_adv_param->p_peer_bda)) { - data_len += sizeof(ble_addr_t); - } - msg = (struct ble_gap_start_advertise_req_msg *) - cfw_alloc_message_for_service(p_svc_handle, - MSG_ID_BLE_GAP_ENABLE_ADV_REQ, - data_len, - p_priv); - if (NULL != p_adv_param) { - uint8_t i; - msg->filter_policy = p_adv_param->filter_policy; - msg->interval_max = p_adv_param->interval_max; - msg->interval_min = p_adv_param->interval_min; - msg->options = p_adv_param->options; - msg->timeout = p_adv_param->timeout; - msg->type = p_adv_param->type; - if (NULL != (p_adv_param->p_peer_bda)) - { - msg->peer_bda[0] = p_adv_param->p_peer_bda->type; - for (i = 1; i <= BLE_ADDR_LEN; i++) - { - msg->peer_bda[i] = p_adv_param->p_peer_bda->addr[i-1]; - } - msg->bda_len = i; - } else - msg->bda_len = 0; - } - return cfw_send_message(msg); -} - -int ble_gap_stop_advertise(svc_client_handle_t * p_svc_handle, void *p_priv) -{ - struct cfw_message *msg = cfw_alloc_message_for_service(p_svc_handle, - MSG_ID_BLE_GAP_DISABLE_ADV_REQ, - sizeof(*msg), - p_priv); - return cfw_send_message(msg); -} - -int ble_gap_conn_update(svc_client_handle_t * p_svc_handle, - uint16_t conn_handle, - const struct ble_gap_connection_params * p_conn_param, - void *p_priv) -{ - CFW_ALLOC_FOR_SVC(struct ble_gap_conn_update_req_msg, msg, p_svc_handle, - MSG_ID_BLE_GAP_CONN_UPDATE_REQ, 0, p_priv); - - msg->conn_handle = conn_handle; - msg->conn_params = *p_conn_param; - - return cfw_send_message(msg); -} - -int ble_gap_disconnect(svc_client_handle_t * p_svc_handle, - uint16_t conn_hdl, uint8_t reason, - void *p_priv) -{ - struct ble_gap_disconnect_req_msg *msg; - - msg = (struct ble_gap_disconnect_req_msg*)cfw_alloc_message_for_service(p_svc_handle, - MSG_ID_BLE_GAP_DISCONNECT_REQ, - sizeof(*msg), - p_priv); - - msg->reason = reason; - msg->conn_handle = conn_hdl; - - return cfw_send_message(msg); -} - -int ble_gap_service_write(svc_client_handle_t * p_svc_handle, - const struct ble_gap_service_write_params * p_params, - void *p_priv) -{ - struct ble_gap_service_write_req_msg *msg; - int total_len = sizeof(*msg); - if ((p_params->attr_type == GAP_SVC_ATTR_NAME) && (p_params->name.len)) { - total_len += p_params->name.len; - } - msg = (struct ble_gap_service_write_req_msg *) - cfw_alloc_message_for_service(p_svc_handle, - MSG_ID_BLE_GAP_SERVICE_WRITE_REQ, - total_len, - p_priv); - msg->attr_type = p_params->attr_type; - - switch (p_params->attr_type) { - case GAP_SVC_ATTR_NAME: - msg->name.authorization = p_params->name.authorization; - msg->name.len = p_params->name.len; - msg->name.sec_mode = p_params->name.sec_mode; - if (msg->name.len) - strcpy((char *)&msg->name.name_array[0], (char *)p_params->name.p_name); - break; - case GAP_SVC_ATTR_APPEARANCE: - msg->appearance = p_params->appearance; - break; - case GAP_SVC_ATTR_PPCP: - msg->conn_params = p_params->conn_params; - break; - case GAP_SVC_ATTR_CAR: - msg->car = p_params->car; - break; - default: - pr_warning(LOG_MODULE_BLE, "ble_gap_srv_wr: Attr " - "not supported : 0x%x", p_params->attr_type); - } - - return cfw_send_message(msg); -} - -int ble_gap_service_read(svc_client_handle_t * p_svc_handle, - uint16_t type, void *p_priv) -{ - struct cfw_message *msg = cfw_alloc_message_for_service(p_svc_handle, - MSG_ID_BLE_GAP_SERVICE_READ_REQ, - sizeof(*msg), - p_priv); - return cfw_send_message(msg); -} - -int ble_gap_sm_config(const svc_client_handle_t * h, - const struct ble_gap_sm_config_params * p_params, - void *p_priv) -{ - CFW_ALLOC_FOR_SVC(struct ble_gap_sm_config_req_msg, msg, h, MSG_ID_BLE_GAP_SM_CONFIG_REQ, 0, p_priv); - - msg->params = *p_params; - - return cfw_send_message(msg); -} - -int ble_gap_sm_pairing_req(const svc_client_handle_t * h, - uint16_t conn_handle, - const struct ble_gap_sm_pairing_params * p_params, - void *p_priv) -{ - CFW_ALLOC_FOR_SVC(struct ble_gap_sm_pairing_req_msg, msg, h, MSG_ID_BLE_GAP_SM_PAIRING_REQ, 0, p_priv); - - msg->params = *p_params; - msg->conn_handle = conn_handle; - - return cfw_send_message(msg); -} - -int ble_gap_set_rssi_report(svc_client_handle_t * p_svc_handle, - const struct rssi_report_params *params, - void *p_priv) -{ - CFW_ALLOC_FOR_SVC(struct ble_gap_set_rssi_report_req_msg, msg, p_svc_handle, MSG_ID_BLE_GAP_SET_RSSI_REPORT_REQ, 0, p_priv); - msg->params = *params; - return cfw_send_message(msg); -} - -int ble_gap_start_scan(svc_client_handle_t * p_svc_handle, - const ble_gap_scan_param_t * p_scan_params, void * p_priv) -{ - struct cfw_message *msg = cfw_alloc_message_for_service(p_svc_handle, - MSG_ID_BLE_GAP_SCAN_START_REQ, - sizeof(*msg), - p_priv); - return cfw_send_message(msg); -} - -int ble_gap_stop_scan(svc_client_handle_t * p_svc_handle, void *p_priv) -{ - struct cfw_message *msg = cfw_alloc_message_for_service(p_svc_handle, - MSG_ID_BLE_GAP_SCAN_STOP_REQ, - sizeof(*msg), - p_priv); - return cfw_send_message(msg); -} - -int ble_gap_connect(svc_client_handle_t * p_svc_handle, const ble_addr_t * p_bd, - const ble_gap_scan_param_t * p_scan_params, - const struct ble_gap_connection_params * p_conn_params, - void *p_priv) -{ - struct cfw_message *msg = cfw_alloc_message_for_service(p_svc_handle, - MSG_ID_BLE_GAP_CONNECT_REQ, - sizeof(*msg), - p_priv); - return cfw_send_message(msg); -} - -int ble_gap_cancel_connect(svc_client_handle_t * p_svc_handle, - const ble_addr_t * p_bd, void *p_priv) -{ - struct cfw_message *msg = cfw_alloc_message_for_service(p_svc_handle, - MSG_ID_BLE_GAP_CONNECT_CANCEL_REQ, - sizeof(*msg), - p_priv); - return cfw_send_message(msg); -} - -int ble_gap_set_option(svc_client_handle_t * p_svc_handle, uint8_t op, - const ble_gap_option_t * p_opt, void *p_priv) -{ - struct cfw_message *msg = cfw_alloc_message_for_service(p_svc_handle, - MSG_ID_BLE_GAP_SET_OPTIONS_REQ, - sizeof(*msg), - p_priv); - return cfw_send_message(msg); -} - -int ble_gap_generic_cmd_req(svc_client_handle_t * p_svc_handle, - const struct ble_gap_gen_cmd_params *p_params, - void *p_priv) -{ - struct ble_generic_cmd_req_msg *msg = (struct ble_generic_cmd_req_msg *) - cfw_alloc_message_for_service(p_svc_handle, - MSG_ID_BLE_GAP_GENERIC_CMD_REQ, - sizeof(*msg), - p_priv); - - return cfw_send_message(msg); -} - -int ble_gap_get_version_req(svc_client_handle_t * p_svc_handle, void * p_priv) -{ - struct cfw_message *msg = (struct cfw_message *) - cfw_alloc_message_for_service(p_svc_handle, - MSG_ID_BLE_GAP_GET_VERSION_REQ, - sizeof(*msg), - p_priv); - return cfw_send_message(msg); -} - -int ble_gap_dtm_init_req(svc_client_handle_t * p_svc_handle, void * p_priv) -{ - struct cfw_message *msg = (struct cfw_message *) - cfw_alloc_message_for_service(p_svc_handle, - MSG_ID_BLE_GAP_DTM_INIT_REQ, - sizeof(*msg), - p_priv); - return cfw_send_message(msg); -} diff --git a/system/libarc32_arduino101/framework/src/services/ble/ble_service_gatt_int.h b/system/libarc32_arduino101/framework/src/services/ble/ble_service_gatt_int.h deleted file mode 100644 index 3f42b09f..00000000 --- a/system/libarc32_arduino101/framework/src/services/ble/ble_service_gatt_int.h +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright (c) 2015, Intel Corporation. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its contributors - * may be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __BLE_SERVICE_GATT_INT_H__ -#define __BLE_SERVICE_GATT_INT_H__ - -#include "services/ble/ble_service_gatt.h" -#include "services/ble/ble_service_gatts_api.h" - -/** - * BLE GATT related shared internal structures between master and BLE controller. - */ -struct ble_gatts_add_service_req_msg { - struct cfw_message header; /**< Component framework message header (@ref cfw), MUST be first element of structure */ - ble_gatts_add_svc_cback_t cback; /**< Callback function to be returnedn in response message */ - uint8_t type; /**< Primary or secondary \ref BLE_GATT_SVC_TYPES. */ - uint8_t data[]; /**< Variable length data of the request (UUID) */ -}; - -/** - * Component framework message to add a characteristic to a service - */ -struct ble_gatts_add_char_req_msg { - struct cfw_message header; /**< Component framework message header (@ref cfw), MUST be first element of structure */ - ble_gatts_add_char_cback_t cback; /**< Callback function, to be returned to sender! */ - uint16_t svc_handle; /**< Handle of the service to which the characteristic should be added */ - struct ble_gatts_permissions perms; - struct ble_gatt_char_properties props; - uint16_t max_len; /**< Maximum length of the characteristic value */ - uint16_t init_len; /**< Length of the initialization value */ - uint8_t ud_len; /**< Length of the characteristic User Description */ - uint8_t pf_len; - - uint8_t data[]; /**< Variable length data of the request (UUID, init value, user descriptor) */ -}; - -/** - * Component framework message to add a descriptor to a characteristic - */ -struct ble_gatts_add_desc_req_msg { - struct cfw_message header; /**< Component framework message header (@ref cfw), MUST be first element of structure */ - ble_gatts_add_desc_cback_t cback; /**< Callback function, to be returned to sender! */ - uint16_t length; - struct ble_gatts_permissions perms; /**< Read/Write permissions for descriptor */ - uint8_t data[]; /**< Variable length data of the request (descriptor value) */ -}; - -struct ble_gatts_start_service_msg { - struct cfw_message header; /**< Component framework message header (@ref cfw), MUST be first element of structure */ - uint16_t svc_handle; -}; - -struct ble_gatts_set_attribute_value_msg { - struct cfw_message header; /**< Component framework message header (@ref cfw), MUST be first element of structure */ - uint16_t value_handle; /* mandatory */ - uint16_t len; - uint16_t offset; /* by default 0 */ - uint8_t data[]; /* value to update */ -}; - -struct ble_gatts_notif_ind_params { - uint16_t conn_handle; - uint16_t val_handle; - uint16_t len; /* may be 0, in this case already stored data is sent */ - uint16_t offset; - uint8_t data[]; -}; - -struct ble_gatts_send_notif_ind_msg { - struct cfw_message header; /**< Component framework message header (@ref cfw), MUST be first element of structure */ - ble_gatts_notif_ind_cback_t cback; /**< Callback function to be returned in response message */ - struct ble_gatts_notif_ind_params params; /* parameters for notification/indication */ -}; - -#endif diff --git a/system/libarc32_arduino101/framework/src/services/ble/ble_service_gatts_api.c b/system/libarc32_arduino101/framework/src/services/ble/ble_service_gatts_api.c deleted file mode 100644 index 17345bde..00000000 --- a/system/libarc32_arduino101/framework/src/services/ble/ble_service_gatts_api.c +++ /dev/null @@ -1,287 +0,0 @@ -/* - * Copyright (c) 2015, Intel Corporation. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its contributors - * may be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include "services/ble/ble_service_gatt.h" -#include "services/ble/ble_service_gatts_api.h" -#include "ble_service_core_int.h" -#include "ble_service_gatt_int.h" -#include "ble_service_utils.h" -#include - -int ble_gatts_add_service(svc_client_handle_t * p_svc_handle, - const struct bt_uuid * p_uuid, - uint8_t type, - ble_gatts_add_svc_cback_t cback, - void *p_priv) -{ - struct ble_gatts_add_service_req_msg *msg = - (struct ble_gatts_add_service_req_msg *) - cfw_alloc_message_for_service(p_svc_handle, - MSG_ID_BLE_GATTS_ADD_SERVICE_REQ, - sizeof(*msg) + ble_sizeof_bt_uuid(p_uuid), - p_priv); - msg->cback = cback; - msg->type = type; - uint8_t *p = (uint8_t *)&msg->data; - ble_encode_bt_uuid(p_uuid, p); - return cfw_send_message(msg); -} - -int ble_gatts_add_included_svc(svc_client_handle_t * p_svc_handle, - uint16_t svc_handle, - uint16_t svc_handle_to_include, - void *p_priv) -{ - struct cfw_message *msg = cfw_alloc_message_for_service(p_svc_handle, - MSG_ID_BLE_GATTS_ADD_INCL_SVC_REQ, - sizeof(*msg), - p_priv); - return cfw_send_message(msg); -} - -int ble_gatts_add_characteristic(svc_client_handle_t * p_svc_handle, - uint16_t svc_handle, - const struct ble_gatts_characteristic * p_char, - ble_gatts_add_char_cback_t cback, - void *p_priv) -{ - struct ble_gatts_add_char_req_msg *msg; - int data_len = sizeof(struct ble_gatts_add_char_req_msg); - uint8_t * p; - - // Sanity check - if (!p_char || !p_char->p_uuid) - return E_OS_ERR; - - // compute the variable length part of the message - data_len += ble_sizeof_bt_uuid(p_char->p_uuid); - data_len += p_char->init_len; - if (p_char->p_user_desc) - data_len += p_char->p_user_desc->len; - if (p_char->p_char_pf_desc) - data_len += sizeof(struct ble_gatt_pf_desc); - - msg = (struct ble_gatts_add_char_req_msg *) - cfw_alloc_message_for_service(p_svc_handle, - MSG_ID_BLE_GATTS_ADD_CHARACTERISTIC_REQ, - data_len, p_priv); - msg->cback = cback; - p = msg->data; - p = ble_encode_bt_uuid(p_char->p_uuid, p); - msg->svc_handle = svc_handle; - msg->perms = p_char->perms; - msg->props = p_char->props; - msg->max_len = p_char->max_len; - msg->init_len = p_char->init_len; - memcpy(p, p_char->p_value, p_char->init_len); - p += p_char->init_len; - if (p_char->p_user_desc) { - msg->ud_len = p_char->p_user_desc->len; - memcpy(p, p_char->p_user_desc->buffer, p_char->p_user_desc->len); - p += p_char->p_user_desc->len; - } - if (p_char->p_char_pf_desc) { - msg->pf_len = sizeof(struct ble_gatt_pf_desc); - memcpy(p, p_char->p_char_pf_desc, msg->pf_len); - p += msg->pf_len; - } - return cfw_send_message(msg); -} - -int ble_gatts_add_descriptor(svc_client_handle_t * p_svc_handle, - const struct ble_gatts_descriptor * p_desc, - ble_gatts_add_desc_cback_t cback, - void * p_priv) -{ - struct ble_gatts_add_desc_req_msg *req; - uint8_t * p; - int data_len = sizeof(struct ble_gatts_add_desc_req_msg); - - /* Sanity check */ - if (!p_desc || !p_desc->length || !p_desc->p_value || !p_desc->p_uuid) - return E_OS_ERR; - - // compute the variable length part of the message - data_len += ble_sizeof_bt_uuid(p_desc->p_uuid); - data_len += p_desc->length; - - req = (struct ble_gatts_add_desc_req_msg *) - cfw_alloc_message_for_service(p_svc_handle, - MSG_ID_BLE_GATTS_ADD_DESCRIPTOR_REQ, - data_len, p_priv); - req->cback = cback; - p = req->data; - p = ble_encode_bt_uuid(p_desc->p_uuid, p); - req->length = p_desc->length; - req->perms = p_desc->perms; - memcpy(p, p_desc->p_value, p_desc->length); - - return cfw_send_message(req); -} - - -int ble_gatts_start_service(svc_client_handle_t * p_svc_handle, - uint16_t svc_handle, - void *p_priv) -{ - struct cfw_message *msg = cfw_alloc_message_for_service(p_svc_handle, - MSG_ID_BLE_GATTS_START_SERVICE_REQ, - sizeof(*msg), - p_priv); - return cfw_send_message(msg); -} - -int ble_gatts_remove_service(svc_client_handle_t * p_svc_handle, - uint16_t svc_handle, - void *p_priv) -{ - struct cfw_message *msg = cfw_alloc_message_for_service(p_svc_handle, - MSG_ID_BLE_GATTS_REMOVE_SERVICE_REQ, - sizeof(*msg), - p_priv); - return cfw_send_message(msg); -} - -int ble_gatts_send_svc_changed(svc_client_handle_t * p_svc_handle, - uint16_t conn_handle, - uint16_t start_handle, - uint16_t end_handle, - void *p_priv) -{ - struct cfw_message *msg = cfw_alloc_message_for_service(p_svc_handle, - MSG_ID_BLE_GATTS_INDICATE_SERVICE_CHANGE_REQ, - sizeof(*msg), - p_priv); - return cfw_send_message(msg); -} - -int ble_gatts_set_attribute_value(svc_client_handle_t * p_svc_handle, - uint16_t value_handle, - uint16_t len, - const uint8_t * p_value, - uint16_t offset, - void *p_priv) -{ - int i; - struct ble_gatts_set_attribute_value_msg *msg = - (struct ble_gatts_set_attribute_value_msg *) - cfw_alloc_message_for_service(p_svc_handle, - MSG_ID_BLE_GATTS_SET_ATTRIBUTE_VALUE_REQ, - sizeof(*msg)+len, - p_priv); - msg->value_handle = value_handle; - msg->len = len; - msg->offset = offset; - - for (i = 0; i < len; i++) - msg->data[i] = p_value[i]; - return cfw_send_message(msg); -} - -int ble_gatts_get_attribute_value(svc_client_handle_t * p_svc_handle, - uint16_t value_handle, - uint16_t len, - uint16_t offset, - void *p_priv) -{ - struct cfw_message *msg = cfw_alloc_message_for_service(p_svc_handle, - MSG_ID_BLE_GATTS_GET_ATTRIBUTE_VALUE_REQ, sizeof(*msg), - p_priv); - - return cfw_send_message(msg); -} - -int ble_gatts_send_notif(svc_client_handle_t * p_svc_handle, - uint16_t conn_handle, - const ble_gatts_ind_params_t * p_params, - ble_gatts_notif_ind_cback_t cback, - void *p_priv) -{ - struct ble_gatts_send_notif_ind_msg *msg = - (struct ble_gatts_send_notif_ind_msg *) - cfw_alloc_message_for_service(p_svc_handle, - MSG_ID_BLE_GATTS_SEND_NOTIF_REQ, - sizeof(*msg) + p_params->len, - p_priv); - - msg->cback = cback; - msg->params.conn_handle = conn_handle; - msg->params.val_handle = p_params->val_handle; - msg->params.len = p_params->len; - msg->params.offset = p_params->offset; - memcpy(msg->params.data, p_params->p_data, msg->params.len); - return cfw_send_message(msg); -} - -int ble_gatts_send_ind(svc_client_handle_t * p_svc_handle, - uint16_t conn_handle, - const ble_gatts_ind_params_t * p_params, - ble_gatts_notif_ind_cback_t cback, - void *p_priv) -{ - struct ble_gatts_send_notif_ind_msg *msg = - (struct ble_gatts_send_notif_ind_msg *) - cfw_alloc_message_for_service(p_svc_handle, - MSG_ID_BLE_GATTS_SEND_IND_REQ, - sizeof(*msg) + p_params->len, - p_priv); - - msg->cback = cback; - msg->params.conn_handle = conn_handle; - msg->params.val_handle = p_params->val_handle; - msg->params.len = p_params->len; - msg->params.offset = p_params->offset; - memcpy(msg->params.data, p_params->p_data, msg->params.len); - return cfw_send_message(msg); -} - -int ble_gatts_write_conn_attributes(svc_client_handle_t * p_svc_handle, - uint16_t conn_handle, - const uint8_t * p_data, - uint16_t len, - void *p_priv) -{ - struct cfw_message *msg = cfw_alloc_message_for_service(p_svc_handle, - MSG_ID_BLE_GATTS_WR_CONN_ATTRIBUTES_REQ, - sizeof(*msg), - p_priv); - return cfw_send_message(msg); -} - -int ble_gatts_read_conn_attributes(svc_client_handle_t * p_svc_handle, - uint16_t conn_handle, - void *p_priv) -{ - struct cfw_message *msg = cfw_alloc_message_for_service(p_svc_handle, - MSG_ID_BLE_GATTS_RD_CONN_ATTRIBUTES_REQ, - sizeof(*msg), - p_priv); - return cfw_send_message(msg); -} diff --git a/system/libarc32_arduino101/framework/src/services/ble/conn.c b/system/libarc32_arduino101/framework/src/services/ble/conn.c new file mode 100644 index 00000000..c0aa9014 --- /dev/null +++ b/system/libarc32_arduino101/framework/src/services/ble/conn.c @@ -0,0 +1,927 @@ +/* + * Copyright (c) 2016 Intel Corporation + * + * 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 +#include + +#include +#include +#include +#include + +#include "hci_core.h" +#include "conn_internal.h" +#include "gap_internal.h" +#include "l2cap_internal.h" +#include "smp.h" + +/* #define BT_GATT_DEBUG 1 */ + +extern void on_nble_curie_log(char *fmt, ...); +extern void __assert_fail(void); +#ifdef BT_GATT_DEBUG +#define BT_DBG(fmt, ...) on_nble_curie_log(fmt, ##__VA_ARGS__) +#define BT_ERR(fmt, ...) on_nble_curie_log(fmt, ##__VA_ARGS__) +#define BT_WARN(fmt, ...) on_nble_curie_log(fmt, ##__VA_ARGS__) +#define BT_INFO(fmt, ...) on_nble_curie_log(fmt, ##__VA_ARGS__) +#define BT_ASSERT(cond) ((cond) ? (void)0 : __assert_fail()) +#else +#define BT_DBG(fmt, ...) do {} while (0) +#define BT_ERR(fmt, ...) on_nble_curie_log(fmt, ##__VA_ARGS__) +#define BT_WARN(fmt, ...) on_nble_curie_log(fmt, ##__VA_ARGS__) +#define BT_INFO(fmt, ...) on_nble_curie_log(fmt, ##__VA_ARGS__) +#define BT_ASSERT(cond) ((cond) ? (void)0 : __assert_fail()) +#endif + +#if defined(CONFIG_BLUETOOTH_SMP) || defined(CONFIG_BLUETOOTH_BREDR) +const struct bt_conn_auth_cb *bt_auth; +#endif /* CONFIG_BLUETOOTH_SMP || CONFIG_BLUETOOTH_BREDR */ + +static struct bt_conn conns[CONFIG_BLUETOOTH_MAX_CONN]; +static struct bt_conn_cb *callback_list; + +static void notify_connected(struct bt_conn *conn) +{ + struct bt_conn_cb *cb; + + for (cb = callback_list; cb; cb = cb->_next) { + if (cb->connected) { + cb->connected(conn, conn->err); + } + } +} + +static void notify_disconnected(struct bt_conn *conn) +{ + struct bt_conn_cb *cb; + + for (cb = callback_list; cb; cb = cb->_next) { + if (cb->disconnected) { + cb->disconnected(conn, conn->err); + } + } +} + +void notify_le_param_updated(struct bt_conn *conn) +{ + struct bt_conn_cb *cb; + + for (cb = callback_list; cb; cb = cb->_next) { + if (cb->le_param_updated) { + cb->le_param_updated(conn, conn->le.interval, + conn->le.latency, + conn->le.timeout); + } + } +} + +#if defined(CONFIG_BLUETOOTH_SMP) + +void bt_conn_security_changed(struct bt_conn *conn) +{ + struct bt_conn_cb *cb; + + for (cb = callback_list; cb; cb = cb->_next) { + if (cb->security_changed) { + cb->security_changed(conn, conn->sec_level); + } + } +} + +static int start_security(struct bt_conn *conn) +{ + switch (conn->role) { +#if defined(CONFIG_BLUETOOTH_CENTRAL) + case BT_HCI_ROLE_MASTER: + { +#ifdef NOT_APPLICABLE_NBLE + if (!conn->keys) { + conn->keys = bt_keys_find(BT_KEYS_LTK_P256, + &conn->le.dst); + if (!conn->keys) { + conn->keys = bt_keys_find(BT_KEYS_LTK, + &conn->le.dst); + } + } + + if (!conn->keys || + !(conn->keys->keys & (BT_KEYS_LTK | BT_KEYS_LTK_P256))) { + return bt_smp_send_pairing_req(conn); + } + + if (conn->required_sec_level > BT_SECURITY_MEDIUM && + !atomic_test_bit(&conn->keys->flags, + BT_KEYS_AUTHENTICATED)) { + return bt_smp_send_pairing_req(conn); + } + + if (conn->required_sec_level > BT_SECURITY_HIGH && + !atomic_test_bit(&conn->keys->flags, + BT_KEYS_AUTHENTICATED) && + !(conn->keys->keys & BT_KEYS_LTK_P256)) { + return bt_smp_send_pairing_req(conn); + } + + /* LE SC LTK and legacy master LTK are stored in same place */ + return bt_conn_le_start_encryption(conn, conn->keys->ltk.rand, + conn->keys->ltk.ediv, + conn->keys->ltk.val, + conn->keys->enc_size); +#endif + return bt_smp_send_pairing_req(conn); + } +#endif /* CONFIG_BLUETOOTH_CENTRAL */ +#if defined(CONFIG_BLUETOOTH_PERIPHERAL) + case BT_HCI_ROLE_SLAVE: + return bt_smp_send_security_req(conn); +#endif /* CONFIG_BLUETOOTH_PERIPHERAL */ + default: + return -EINVAL; + } +} + +int bt_conn_security(struct bt_conn *conn, bt_security_t sec) +{ + int err; + + if (conn->state != BT_CONN_CONNECTED) { + return -ENOTCONN; + } + +#if defined(CONFIG_BLUETOOTH_SMP_SC_ONLY) + if (sec < BT_SECURITY_FIPS) { + return -EOPNOTSUPP; + } +#endif/* CONFIG_BLUETOOTH_SMP_SC_ONLY */ + + /* nothing to do */ + if (conn->sec_level >= sec || conn->required_sec_level >= sec) { + return 0; + } + + conn->required_sec_level = sec; + + err = start_security(conn); + + /* reset required security level in case of error */ + if (err) { + conn->required_sec_level = conn->sec_level; + } + return err; +} +#endif /* CONFIG_BLUETOOTH_SMP */ + +void bt_conn_cb_register(struct bt_conn_cb *cb) +{ + cb->_next = callback_list; + callback_list = cb; +} + +static struct bt_conn *conn_new(void) +{ + struct bt_conn *conn = NULL; + int i; + + for (i = 0; i < ARRAY_SIZE(conns); i++) { + if (!atomic_get(&conns[i].ref)) { + conn = &conns[i]; + break; + } + } + + if (!conn) { + return NULL; + } + + memset(conn, 0, sizeof(*conn)); + + atomic_set(&conn->ref, 1); + + return conn; +} + +struct bt_conn *bt_conn_add_le(const bt_addr_le_t *peer) +{ + struct bt_conn *conn = conn_new(); + + if (!conn) { + return NULL; + } + + bt_addr_le_copy(&conn->le.dst, peer); +#if defined(CONFIG_BLUETOOTH_SMP) + conn->sec_level = BT_SECURITY_LOW; + conn->required_sec_level = BT_SECURITY_LOW; +#endif /* CONFIG_BLUETOOTH_SMP */ + conn->type = BT_CONN_TYPE_LE; + conn->le.interval_min = BT_GAP_INIT_CONN_INT_MIN; + conn->le.interval_max = BT_GAP_INIT_CONN_INT_MAX; + + return conn; +} + +#if defined(CONFIG_BLUETOOTH_BREDR) +struct bt_conn *bt_conn_lookup_addr_br(const bt_addr_t *peer) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(conns); i++) { + if (!atomic_get(&conns[i].ref)) { + continue; + } + + if (conns[i].type != BT_CONN_TYPE_BR) { + continue; + } + + if (!bt_addr_cmp(peer, &conns[i].br.dst)) { + return bt_conn_ref(&conns[i]); + } + } + + return NULL; +} + +struct bt_conn *bt_conn_add_br(const bt_addr_t *peer) +{ + struct bt_conn *conn = conn_new(); + + if (!conn) { + return NULL; + } + + bt_addr_copy(&conn->br.dst, peer); + conn->type = BT_CONN_TYPE_BR; + + return conn; +} +#endif + +void bt_conn_set_state(struct bt_conn *conn, bt_conn_state_t state) +{ + bt_conn_state_t old_state; + + BT_DBG("conn state %d -> %d, err: %d", conn->state, state, conn->err); + + if (conn->state == state) { + BT_DBG("no transition"); + return; + } + + old_state = conn->state; + conn->state = state; + + /* Actions needed for exiting the old state */ + switch (old_state) { + case BT_CONN_DISCONNECTED: + /* Take a reference for the first state transition after + * bt_conn_add_le() and keep it until reaching DISCONNECTED + * again. + */ + bt_conn_ref(conn); + break; + case BT_CONN_CONNECT: +#if 0 + if (conn->timeout) { + fiber_delayed_start_cancel(conn->timeout); + conn->timeout = NULL; + + /* Drop the reference taken by timeout fiber */ + bt_conn_unref(conn); + } +#endif + break; + default: + break; + } + + /* Actions needed for entering the new state */ + switch (conn->state) { + case BT_CONN_CONNECTED: + bt_l2cap_connected(conn); + notify_connected(conn); + break; + case BT_CONN_DISCONNECTED: + /* Notify disconnection and queue a dummy buffer to wake + * up and stop the tx fiber for states where it was + * running. + */ + if (old_state == BT_CONN_CONNECTED || + old_state == BT_CONN_DISCONNECT) { + bt_l2cap_disconnected(conn); + notify_disconnected(conn); + } else if (old_state == BT_CONN_CONNECT) { + /* conn->err will be set in this case */ + notify_connected(conn); + } + + /* Release the reference we took for the very first + * state transition. + */ + bt_conn_unref(conn); + + break; + case BT_CONN_CONNECT_SCAN: + break; + case BT_CONN_CONNECT: + break; + case BT_CONN_DISCONNECT: + break; + default: + + break; + } +} + +struct bt_conn *bt_conn_lookup_handle(uint16_t handle) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(conns); i++) { + if (!atomic_get(&conns[i].ref)) { + continue; + } + /* We only care about connections with a valid handle */ + if (conns[i].state != BT_CONN_CONNECTED && + conns[i].state != BT_CONN_DISCONNECT) { + continue; + } + + if (conns[i].handle == handle) { + return bt_conn_ref(&conns[i]); + } + } + + return NULL; +} + +struct bt_conn *bt_conn_lookup_addr_le(const bt_addr_le_t *peer) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(conns); i++) { + if (!atomic_get(&conns[i].ref)) { + continue; + } + + if (conns[i].type != BT_CONN_TYPE_LE) { + continue; + } + + if (!bt_addr_le_cmp(peer, &conns[i].le.dst)) { + return bt_conn_ref(&conns[i]); + } + } + + return NULL; +} + +struct bt_conn *bt_conn_lookup_state_le(const bt_addr_le_t *peer, + const bt_conn_state_t state) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(conns); i++) { + if (!atomic_get(&conns[i].ref)) { + continue; + } + + if (conns[i].type != BT_CONN_TYPE_LE) { + continue; + } + + if (bt_addr_le_cmp(peer, BT_ADDR_LE_ANY) && + bt_addr_le_cmp(peer, &conns[i].le.dst)) { + continue; + } + + if (conns[i].state == state) { + return bt_conn_ref(&conns[i]); + } + } + + return NULL; +} + +struct bt_conn *bt_conn_ref(struct bt_conn *conn) +{ + atomic_inc(&conn->ref); + + return conn; +} + +void bt_conn_unref(struct bt_conn *conn) +{ + atomic_dec(&conn->ref); +} + +const bt_addr_le_t *bt_conn_get_dst(const struct bt_conn *conn) +{ + return &conn->le.dst; +} + +int bt_conn_get_info(const struct bt_conn *conn, struct bt_conn_info *info) +{ + info->type = conn->type; + info->role = conn->role; + + switch (conn->type) { + case BT_CONN_TYPE_LE: + if (conn->role == BT_HCI_ROLE_MASTER) { +#if 0 + info->le.src = &conn->le.init_addr; + info->le.dst = &conn->le.resp_addr; +#else + info->le.dst = &conn->le.dst; +#endif + } else { +#if 0 + info->le.src = &conn->le.resp_addr; + info->le.dst = &conn->le.init_addr; +#else + info->le.src = &conn->le.dst; +#endif + } + info->le.interval = conn->le.interval; + info->le.latency = conn->le.latency; + info->le.timeout = conn->le.timeout; + + return 0; +#if defined(CONFIG_BLUETOOTH_BREDR) + case BT_CONN_TYPE_BR: + info->br.dst = &conn->br.dst; + return 0; +#endif + } + + return -EINVAL; +} + +static int bt_hci_disconnect(struct bt_conn *conn, uint8_t reason) +{ + struct nble_gap_disconnect_req_params ble_gap_disconnect; + + ble_gap_disconnect.conn_handle = conn->handle; + ble_gap_disconnect.reason = reason; + nble_gap_disconnect_req(&ble_gap_disconnect); + + bt_conn_set_state(conn, BT_CONN_DISCONNECT); + return 0; +} + +static int bt_hci_connect_le_cancel(struct bt_conn *conn) +{ + nble_gap_cancel_connect_req(conn); + return 0; +} + +void on_nble_gap_cancel_connect_rsp(const struct nble_response *params) +{ + struct bt_conn *conn = params->user_data; + + conn->err = BT_HCI_ERR_INSUFFICIENT_RESOURCES; + bt_conn_set_state(conn, BT_CONN_DISCONNECTED); +} + +int bt_conn_disconnect(struct bt_conn *conn, uint8_t reason) +{ +#if defined(CONFIG_BLUETOOTH_CENTRAL) + /* Disconnection is initiated by us, so auto connection shall + * be disabled. Otherwise the passive scan would be enabled + * and we could send LE Create Connection as soon as the remote + * starts advertising. + */ + if (conn->type == BT_CONN_TYPE_LE) { + bt_le_set_auto_conn(&conn->le.dst, NULL); + } +#endif + + switch (conn->state) { + case BT_CONN_CONNECT_SCAN: + conn->err = BT_HCI_ERR_INSUFFICIENT_RESOURCES; + bt_conn_set_state(conn, BT_CONN_DISCONNECTED); + /* scan update not yet implemented */ + return 0; + case BT_CONN_CONNECT: + return bt_hci_connect_le_cancel(conn); + case BT_CONN_CONNECTED: + return bt_hci_disconnect(conn, reason); + case BT_CONN_DISCONNECT: + return 0; + case BT_CONN_DISCONNECTED: + default: + return -ENOTCONN; + } +} + +static bool valid_adv_params(const struct nble_gap_adv_params *params) +{ + if (params->type == BT_LE_ADV_DIRECT_IND) { + /* If high duty, ensure interval is 0 */ + if (params->interval_max != 0) + return false; + + if (params->timeout != 0) + return false; + } else if (params->type == BT_LE_ADV_DIRECT_IND_LOW_DUTY) { + if (params->interval_min < 0x20) + return false; + } else { + return false; + } + + if (params->interval_min > params->interval_max) + return false; + + if (params->interval_max > 0x4000) + return false; + + return true; +} + +struct bt_conn *bt_conn_create_slave_le(const bt_addr_le_t *peer, + const struct bt_le_adv_param *param) +{ + struct bt_conn *conn; + /* Timeout is handled by application timer */ + /* forced to none currently (no whitelist support) */ + struct nble_gap_adv_params params = { + .interval_max = param->interval_max, + .interval_min = param->interval_min, + .type = param->type, + .timeout = 0, + .filter_policy = 0 + }; + + bt_addr_le_copy(¶ms.peer_bda, peer); + + if (!valid_adv_params(¶ms)) { + return NULL; + } + + if (param->type == BT_LE_ADV_DIRECT_IND_LOW_DUTY) { + params.type = BT_LE_ADV_DIRECT_IND; + } + + if (atomic_test_bit(bt_dev.flags, BT_DEV_ADVERTISING)) { + return NULL; + } + + conn = bt_conn_add_le(¶ms.peer_bda); + + if (!conn) { + return NULL; + } + + bt_conn_set_state(conn, BT_CONN_CONNECT); + + nble_gap_set_adv_params_req(¶ms); + nble_gap_start_adv_req(); + + return conn; +} + +#if defined(CONFIG_BLUETOOTH_CENTRAL) +static int hci_le_create_conn(struct bt_conn *conn) +{ + struct nble_gap_connect_req_params conn_params; + + conn_params.bda = conn->le.dst; + conn_params.conn_params.interval_min = conn->le.interval_min; + conn_params.conn_params.interval_max = conn->le.interval_max; + conn_params.conn_params.slave_latency = conn->le.latency; + conn_params.conn_params.link_sup_to = conn->le.timeout; + + conn_params.scan_params.interval = sys_cpu_to_le16(BT_GAP_SCAN_FAST_INTERVAL); + conn_params.scan_params.window = conn_params.scan_params.interval; + conn_params.scan_params.selective = 0; + conn_params.scan_params.active = 1; + conn_params.scan_params.timeout = 0; + + nble_gap_connect_req(&conn_params, conn); + + return 0; +} + +void on_nble_gap_connect_rsp(const struct nble_response *params) +{ + struct bt_conn *conn = params->user_data; + + /* If the connection request was not issued successfully */ + if (params->status) { + conn->err = BT_HCI_ERR_UNACCEPT_CONN_PARAMS; + bt_conn_set_state(conn, BT_CONN_DISCONNECTED); + } +} + +struct bt_conn *bt_conn_create_le(const bt_addr_le_t *peer, + const struct bt_le_conn_param *param) +{ + struct bt_conn *conn; + + if (!bt_le_conn_params_valid(param->interval_min, param->interval_max, + param->latency, param->timeout)) { + return NULL; + } + + /* if (atomic_test_bit(bt_dev.flags, BT_DEV_EXPLICIT_SCAN)) */ + /* return NULL; */ + + conn = bt_conn_lookup_addr_le(peer); + if (conn) { + switch (conn->state) { + case BT_CONN_CONNECT_SCAN: + bt_conn_set_param_le(conn, param); + return conn; + case BT_CONN_CONNECT: + case BT_CONN_CONNECTED: + return conn; + default: + bt_conn_unref(conn); + return NULL; + } + } + + conn = bt_conn_add_le(peer); + if (!conn) { + return NULL; + } +#if 0 + bt_conn_set_state(conn, BT_CONN_CONNECT_SCAN); + + bt_le_scan_update(true); +#endif + + bt_addr_le_copy(&conn->le.dst, peer); + + bt_conn_set_param_le(conn, param); + + /* for the time being, the implementation bypassed the scan procedure */ + if (hci_le_create_conn(conn)) { + goto done; + } + + bt_conn_set_state(conn, BT_CONN_CONNECT); + +done: + return conn; +} +#else + +void on_nble_gap_connect_rsp(const struct nble_response *params) +{ +} + +#endif /* CONFIG_BLUETOOTH_CENTRAL */ + +int bt_conn_le_param_update(struct bt_conn *conn, const struct bt_le_conn_param *param) +{ + return bt_conn_update_param_le(conn, param); +} + +#if defined(CONFIG_BLUETOOTH_SMP) || defined(CONFIG_BLUETOOTH_BREDR) +uint8_t bt_conn_enc_key_size(struct bt_conn *conn) +{ + return 0; +} + +int bt_conn_auth_cb_register(const struct bt_conn_auth_cb *cb) +{ + if (!cb) { + bt_auth = NULL; + return 0; + } + + /* cancel callback should always be provided */ + if (!cb->cancel) { + return -EINVAL; + } + + if (bt_auth) { + return -EALREADY; + } + + bt_auth = cb; + return 0; +} + +#if defined(CONFIG_BLUETOOTH_BREDR) +static int pin_code_neg_reply(const bt_addr_t *bdaddr) +{ + struct bt_hci_cp_pin_code_neg_reply *cp; + struct net_buf *buf; + + BT_DBG(""); + + buf = bt_hci_cmd_create(BT_HCI_OP_PIN_CODE_NEG_REPLY, sizeof(*cp)); + if (!buf) { + return -ENOBUFS; + } + + cp = net_buf_add(buf, sizeof(*cp)); + bt_addr_copy(&cp->bdaddr, bdaddr); + + return bt_hci_cmd_send_sync(BT_HCI_OP_PIN_CODE_NEG_REPLY, buf, NULL); +} + +static int pin_code_reply(struct bt_conn *conn, const char *pin, uint8_t len) +{ + struct bt_hci_cp_pin_code_reply *cp; + struct net_buf *buf; + + BT_DBG(""); + + buf = bt_hci_cmd_create(BT_HCI_OP_PIN_CODE_REPLY, sizeof(*cp)); + if (!buf) { + return -ENOBUFS; + } + + cp = net_buf_add(buf, sizeof(*cp)); + + bt_addr_copy(&cp->bdaddr, &conn->br.dst); + cp->pin_len = len; + strncpy(cp->pin_code, pin, sizeof(cp->pin_code)); + + return bt_hci_cmd_send_sync(BT_HCI_OP_PIN_CODE_REPLY, buf, NULL); +} + +int bt_conn_auth_pincode_entry(struct bt_conn *conn, const char *pin) +{ + size_t len; + + if (!bt_auth) { + return -EINVAL; + } + + if (conn->type != BT_CONN_TYPE_BR) { + return -EINVAL; + } + + len = strlen(pin); + if (len > 16) { + return -EINVAL; + } + + if (conn->required_sec_level == BT_SECURITY_HIGH && len < 16) { + BT_WARN("PIN code for %s is not 16 bytes wide", + bt_addr_str(&conn->br.dst)); + return -EPERM; + } + + return pin_code_reply(conn, pin, len); +} + +void bt_conn_pin_code_req(struct bt_conn *conn) +{ + if (bt_auth && bt_auth->pincode_entry) { + bool secure = false; + + if (conn->required_sec_level == BT_SECURITY_HIGH) { + secure = true; + } + + bt_auth->pincode_entry(conn, secure); + } else { + pin_code_neg_reply(&conn->br.dst); + } + +} +#endif /* CONFIG_BLUETOOTH_BREDR */ + +int bt_conn_auth_passkey_entry(struct bt_conn *conn, unsigned int passkey) +{ + if (!bt_auth) { + return -EINVAL; + } +#if defined(CONFIG_BLUETOOTH_SMP) + if (conn->type == BT_CONN_TYPE_LE) { + return bt_smp_auth_passkey_entry(conn, passkey); + } +#endif /* CONFIG_BLUETOOTH_SMP */ + + return -EINVAL; +} + +int bt_conn_auth_passkey_confirm(struct bt_conn *conn, bool match) +{ + if (!bt_auth) { + return -EINVAL; + }; +#if defined(CONFIG_BLUETOOTH_SMP) + if (conn->type == BT_CONN_TYPE_LE) { + return bt_smp_auth_passkey_confirm(conn, match); + } +#endif /* CONFIG_BLUETOOTH_SMP */ + + return -EINVAL; +} + +int bt_conn_auth_cancel(struct bt_conn *conn) +{ + if (!bt_auth) { + return -EINVAL; + } +#if defined(CONFIG_BLUETOOTH_SMP) + if (conn->type == BT_CONN_TYPE_LE) { + return bt_smp_auth_cancel(conn); + } +#endif /* CONFIG_BLUETOOTH_SMP */ +#if defined(CONFIG_BLUETOOTH_BREDR) + if (conn->type == BT_CONN_TYPE_BR) { + return pin_code_neg_reply(&conn->br.dst); + } +#endif /* CONFIG_BLUETOOTH_BREDR */ + + return -EINVAL; +} + +int bt_conn_remove_info(const bt_addr_le_t *addr) +{ + struct bt_conn *conn; + + /* TODO: implement address specific removal */ + if (bt_addr_le_cmp(addr, BT_ADDR_LE_ANY)) + return -EINVAL; + + do { + conn = bt_conn_lookup_state_le(addr, BT_CONN_CONNECTED); + if (conn) { + bt_conn_unref(conn); + bt_conn_disconnect(conn, + BT_HCI_ERR_REMOTE_USER_TERM_CONN); + } + } while(conn); + + return bt_smp_remove_info(addr); +} +#endif /* CONFIG_BLUETOOTH_SMP || CONFIG_BLUETOOTH_BREDR */ + +int bt_conn_init(void) +{ + int err; +#if NOT_USED_FOR_NOW + + net_buf_pool_init(frag_pool); + net_buf_pool_init(dummy_pool); + + bt_att_init(); +#endif + + err = bt_smp_init(); + if (err) { + return err; + } + +#if NOT_USED_FOR_NOW + bt_l2cap_init(); + + background_scan_init(); +#endif + return 0; +} + +int bt_conn_le_conn_update(struct bt_conn *conn, + const struct bt_le_conn_param *param) +{ + struct nble_gap_connect_update_params ble_gap_connect_update; +#if 0 + struct hci_cp_le_conn_update *conn_update; + struct net_buf *buf; + + buf = bt_hci_cmd_create(BT_HCI_OP_LE_CONN_UPDATE, + sizeof(*conn_update)); + if (!buf) { + return -ENOBUFS; + } + + conn_update = net_buf_add(buf, sizeof(*conn_update)); + memset(conn_update, 0, sizeof(*conn_update)); + conn_update->handle = sys_cpu_to_le16(conn->handle); + conn_update->conn_interval_min = sys_cpu_to_le16(param->interval_min); + conn_update->conn_interval_max = sys_cpu_to_le16(param->interval_max); + conn_update->conn_latency = sys_cpu_to_le16(param->latency); + conn_update->supervision_timeout = sys_cpu_to_le16(param->timeout); +#endif + ble_gap_connect_update.conn_handle = conn->handle; + ble_gap_connect_update.params.interval_min = param->interval_min; + ble_gap_connect_update.params.interval_max = param->interval_max; + ble_gap_connect_update.params.slave_latency = param->latency; + ble_gap_connect_update.params.link_sup_to = param->timeout; + + nble_gap_conn_update_req(&ble_gap_connect_update); + + return 0; +} diff --git a/system/libarc32_arduino101/framework/src/services/ble/conn_internal.h b/system/libarc32_arduino101/framework/src/services/ble/conn_internal.h new file mode 100644 index 00000000..04c08839 --- /dev/null +++ b/system/libarc32_arduino101/framework/src/services/ble/conn_internal.h @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2016 Intel Corporation + * + * 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. + */ + +typedef enum { + BT_CONN_DISCONNECTED, + BT_CONN_CONNECT_SCAN, + BT_CONN_CONNECT, + BT_CONN_CONNECTED, + BT_CONN_DISCONNECT, +} bt_conn_state_t; + +/* bt_conn flags: the flags defined here represent connection parameters */ +enum { + BT_CONN_AUTO_CONNECT, +}; + +struct bt_conn_le { + bt_addr_le_t dst; + +#if 0 + bt_addr_le_t init_addr; + bt_addr_le_t resp_addr; +#endif + uint16_t interval; + uint16_t interval_min; + uint16_t interval_max; + + uint16_t latency; + uint16_t timeout; +#if 0 + uint8_t features[8]; +#endif +}; + +#if defined(CONFIG_BLUETOOTH_BREDR) +struct bt_conn_br { + bt_addr_t dst; +}; +#endif + +struct bt_conn { + uint16_t handle; + uint8_t type; + uint8_t role; + +#if defined(CONFIG_BLUETOOTH_SMP) + uint8_t encrypt; + bt_security_t sec_level; + bt_security_t required_sec_level; +#endif /* CONFIG_BLUETOOTH_SMP */ + + atomic_t ref; + + /* Connection error or reason for disconnect */ + uint8_t err; + + bt_conn_state_t state; + union { + struct bt_conn_le le; +#if defined(CONFIG_BLUETOOTH_BREDR) + struct bt_conn_br br; +#endif + }; +}; + +/* Add a new LE connection */ +struct bt_conn *bt_conn_add_le(const bt_addr_le_t *peer); + +#if defined(CONFIG_BLUETOOTH_BREDR) +/* Add a new BR/EDR connection */ +struct bt_conn *bt_conn_add_br(const bt_addr_t *peer); + +/* Look up an existing connection by BT address */ +struct bt_conn *bt_conn_lookup_addr_br(const bt_addr_t *peer); +#endif + +/* Look up an existing connection */ +struct bt_conn *bt_conn_lookup_handle(uint16_t handle); + +/* Look up a connection state. For BT_ADDR_LE_ANY, returns the first connection + * with the specific state + */ +struct bt_conn *bt_conn_lookup_state_le(const bt_addr_le_t *peer, + const bt_conn_state_t state); + +/* Set connection object in certain state and perform action related to state */ +void bt_conn_set_state(struct bt_conn *conn, bt_conn_state_t state); + +void bt_conn_set_param_le(struct bt_conn *conn, + const struct bt_le_conn_param *param); + +int bt_conn_update_param_le(struct bt_conn *conn, + const struct bt_le_conn_param *param); + +int bt_conn_le_conn_update(struct bt_conn *conn, + const struct bt_le_conn_param *param); + +void notify_le_param_updated(struct bt_conn *conn); + +#if defined(CONFIG_BLUETOOTH_SMP) +/* rand and ediv should be in BT order */ +int bt_conn_le_start_encryption(struct bt_conn *conn, uint64_t rand, + uint16_t ediv, const uint8_t *ltk, size_t len); + +/* Notify higher layers that RPA was resolved */ +void bt_conn_identity_resolved(struct bt_conn *conn); + +/* Notify higher layers that connection security changed */ +void bt_conn_security_changed(struct bt_conn *conn); +#endif /* CONFIG_BLUETOOTH_SMP */ +/* Initialize connection management */ +int bt_conn_init(void); diff --git a/system/libarc32_arduino101/framework/src/services/ble/dtm_tcmd.c b/system/libarc32_arduino101/framework/src/services/ble/dtm_tcmd.c new file mode 100644 index 00000000..4a0c5b0c --- /dev/null +++ b/system/libarc32_arduino101/framework/src/services/ble/dtm_tcmd.c @@ -0,0 +1,12 @@ + +#include +#include "uart.h" +#include "ipc_uart_ns16550.h" + +void on_nble_gap_dtm_init_rsp(void *user_data) +{ +#ifdef CONFIG_UART_NS16550 + uart_ipc_disable(); +#endif +} + diff --git a/system/libarc32_arduino101/framework/src/services/ble/gap.c b/system/libarc32_arduino101/framework/src/services/ble/gap.c new file mode 100644 index 00000000..4cf71d47 --- /dev/null +++ b/system/libarc32_arduino101/framework/src/services/ble/gap.c @@ -0,0 +1,912 @@ +/* + * Copyright (c) 2016 Intel Corporation + * + * 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 +#include +#include + +#include +#include +#include "gap_internal.h" +#include "conn_internal.h" + +#include "hci_core.h" + +#if defined(CONFIG_BLUETOOTH_SMP) +#include "smp.h" +#endif /* CONFIG_BLUETOOTH_SMP */ + +/* #define BT_GATT_DEBUG 1 */ + +extern void on_nble_curie_log(char *fmt, ...); +extern void __assert_fail(void); +#ifdef BT_GATT_DEBUG +#define BT_DBG(fmt, ...) on_nble_curie_log(fmt, ##__VA_ARGS__) +#define BT_ERR(fmt, ...) on_nble_curie_log(fmt, ##__VA_ARGS__) +#define BT_WARN(fmt, ...) on_nble_curie_log(fmt, ##__VA_ARGS__) +#define BT_INFO(fmt, ...) on_nble_curie_log(fmt, ##__VA_ARGS__) +#define BT_ASSERT(cond) ((cond) ? (void)0 : __assert_fail()) +#else +#define BT_DBG(fmt, ...) do {} while (0) +#define BT_ERR(fmt, ...) on_nble_curie_log(fmt, ##__VA_ARGS__) +#define BT_WARN(fmt, ...) on_nble_curie_log(fmt, ##__VA_ARGS__) +#define BT_INFO(fmt, ...) on_nble_curie_log(fmt, ##__VA_ARGS__) +#define BT_ASSERT(cond) ((cond) ? (void)0 : __assert_fail()) +#endif + +static bt_ready_cb_t bt_ready_cb; +static bt_le_scan_cb_t *scan_dev_found_cb; +static rssi_report_t rssi_report_cb; + +struct bt_dev bt_dev; + +static int set_advertise_enable(void) +{ +#if 0 + struct net_buf *buf; + int err; +#endif + if (atomic_test_bit(bt_dev.flags, BT_DEV_ADVERTISING)) { + return 0; + } +#if 0 + buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_ADV_ENABLE, 1); + if (!buf) { + return -ENOBUFS; + } + + net_buf_add_u8(buf, BT_HCI_LE_ADV_ENABLE); + err = bt_hci_cmd_send_sync(BT_HCI_OP_LE_SET_ADV_ENABLE, buf, NULL); + if (err) { + return err; + } +#endif + nble_gap_start_adv_req(); + + return 0; +} + +static int set_advertise_disable(void) +{ +#if 0 + struct net_buf *buf; + int err; +#endif + if (!atomic_test_bit(bt_dev.flags, BT_DEV_ADVERTISING)) { + return 0; + } +#if 0 + buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_ADV_ENABLE, 1); + if (!buf) { + return -ENOBUFS; + } + + net_buf_add_u8(buf, BT_HCI_LE_ADV_DISABLE); + err = bt_hci_cmd_send_sync(BT_HCI_OP_LE_SET_ADV_ENABLE, buf, NULL); + if (err) { + return err; + } +#endif + nble_gap_stop_adv_req(NULL); + + atomic_clear_bit(bt_dev.flags, BT_DEV_ADVERTISING); + return 0; +} + +void ble_gap_get_bonding_info(ble_bond_info_cb_t func, void *user_data, + bool include_bonded_addrs) +{ + struct nble_gap_sm_bond_info_param params; + + params.cb = func; + params.user_data = user_data; + params.include_bonded_addrs = include_bonded_addrs; + + nble_gap_sm_bond_info_req(¶ms); +} + +void on_nble_gap_start_advertise_rsp(const struct nble_response *params) +{ + if (params->status == 0) + atomic_set_bit(bt_dev.flags, BT_DEV_ADVERTISING); + else + BT_WARN("start advertise failed with %d", params->status); +} + +void on_nble_gap_disconnect_evt(const struct nble_gap_disconnect_evt *evt) +{ + struct bt_conn *conn; + +#if 0 + /* Nordic has no disconnection error */ + if (evt->status) { + return; + } +#endif + + conn = bt_conn_lookup_handle(evt->conn_handle); + if (!conn) { + BT_DBG("Unable to look up conn with handle %u", + evt->conn_handle); + return; + } +#if 0 + /* Check stacks usage (no-ops if not enabled) */ + stack_analyze("rx stack", rx_fiber_stack, sizeof(rx_fiber_stack)); + stack_analyze("cmd rx stack", rx_prio_fiber_stack, + sizeof(rx_prio_fiber_stack)); + stack_analyze("cmd tx stack", cmd_tx_fiber_stack, + sizeof(cmd_tx_fiber_stack)); + stack_analyze("conn tx stack", conn->stack, sizeof(conn->stack)); + +#endif + + conn->err = evt->hci_reason; + bt_conn_set_state(conn, BT_CONN_DISCONNECTED); + conn->handle = 0; + +#if 0 + /* Only LE supported */ + if (conn->type != BT_CONN_TYPE_LE) { + bt_conn_unref(conn); + return; + } + /* TODO enabled when autoconn is supported */ + if (atomic_test_bit(conn->flags, BT_CONN_AUTO_CONNECT)) { + bt_conn_set_state(conn, BT_CONN_CONNECT_SCAN); + bt_le_scan_update(false); + } +#endif + + bt_conn_unref(conn); + if (atomic_test_bit(bt_dev.flags, BT_DEV_KEEP_ADVERTISING)) { + set_advertise_enable(); + } +} + +void on_nble_gap_connect_evt(const struct nble_gap_connect_evt *evt) +{ + struct bt_conn *conn; + + /* Make lookup to check if there's a connection object in CONNECT state + * associated with passed peer LE address. + */ + conn = bt_conn_lookup_state_le(&evt->peer_bda, BT_CONN_CONNECT); + +#if 0 + /* Nordic has no connection error */ + if (evt->status) { + if (!conn) { + return; + } + + conn->err = BT_HCI_ERR_UNACCEPT_CONN_PARAMS; + bt_conn_set_state(conn, BT_CONN_DISCONNECTED); + + /* Drop the reference got by lookup call in CONNECT state. + * We are now in DISCONNECTED state since no successful LE + * link been made. + */ + bt_conn_unref(conn); + + return; + } +#endif + /* + * clear advertising even if we are not able to add connection object + * to keep host in sync with controller state + */ + if (evt->role_slave == BT_CONN_ROLE_SLAVE) { + atomic_clear_bit(bt_dev.flags, BT_DEV_ADVERTISING); + } + + if (!conn) { + conn = bt_conn_add_le(&evt->peer_bda); + } + + if (!conn) { + BT_DBG("Unable to add new conn for handle %u", + evt->conn_handle); + return; + } + + conn->handle = evt->conn_handle; + bt_addr_le_copy(&conn->le.dst, &evt->peer_bda); + conn->le.interval = evt->conn_values.interval; + conn->le.latency = evt->conn_values.latency; + conn->le.timeout = evt->conn_values.supervision_to; + conn->role = evt->role_slave; + +#if 0 + src.type = BT_ADDR_LE_PUBLIC; + memcpy(src.val, bt_dev.bdaddr.val, sizeof(bt_dev.bdaddr.val)); + + /* use connection address (instead of identity address) as initiator + * or responder address + */ + if (conn->role == BT_HCI_ROLE_MASTER) { + bt_addr_le_copy(&conn->le.init_addr, &src); + bt_addr_le_copy(&conn->le.resp_addr, &evt->peer_addr); + } else { + bt_addr_le_copy(&conn->le.init_addr, &evt->peer_addr); + bt_addr_le_copy(&conn->le.resp_addr, &src); + } +#endif + bt_conn_set_state(conn, BT_CONN_CONNECTED); + + /* Note: Connection update removed because Windows interop and BT spec recommendations */ + + bt_conn_unref(conn); +#if 0 + bt_le_scan_update(false); +#endif + +} + +void on_nble_gap_adv_report_evt(const struct nble_gap_adv_report_evt *evt, + const uint8_t *buf, uint8_t len) +{ +#if TODO_IMPLEMENT_CONNECTION + uint8_t num_reports = buf->data[0]; + struct bt_hci_ev_le_advertising_info *info; + + BT_DBG("Adv number of reports %u", num_reports); + + info = net_buf_pull(buf, sizeof(num_reports)); + + while (num_reports--) { + int8_t rssi = info->data[info->length]; + const bt_addr_le_t *addr; + + BT_DBG("%s event %u, len %u, rssi %d dBm", + bt_addr_le_str(&info->addr), + info->evt_type, info->length, rssi); + + addr = find_id_addr(&info->addr); +#endif + + BT_DBG("nble gap: event:%u, len %u", evt->adv_type, len); + + if (scan_dev_found_cb) { + scan_dev_found_cb(&evt->addr, evt->rssi, evt->adv_type, + buf, len); + } +#if TODO_IMPLEMENT_CONNECTION +#if defined(CONFIG_BLUETOOTH_CONN) + check_pending_conn(addr, &info->addr, info->evt_type); +#endif /* CONFIG_BLUETOOTH_CONN */ + /* Get next report iteration by moving pointer to right offset + * in buf according to spec 4.2, Vol 2, Part E, 7.7.65.2. + */ + info = net_buf_pull(buf, sizeof(*info) + info->length + + sizeof(rssi)); + } +#endif +} + +void on_nble_gap_conn_update_evt(const struct nble_gap_conn_update_evt *evt) +{ + struct bt_conn *conn; + uint16_t handle, interval; + + handle = evt->conn_handle; + interval = evt->conn_values.interval; + +/* BT_DBG("status %u, handle %u", evt->status, handle); */ + + conn = bt_conn_lookup_handle(handle); + if (!conn) { +/* BT_ERR("Unable to lookup conn for handle %u", handle); */ + return; + } + +/* if (!evt->status) { */ + conn->le.interval = interval; + conn->le.latency = evt->conn_values.latency; + conn->le.timeout = evt->conn_values.supervision_to; + notify_le_param_updated(conn); +/* } */ + + + bt_conn_unref(conn); +} + +void bt_conn_set_param_le(struct bt_conn *conn, + const struct bt_le_conn_param *param) +{ + conn->le.interval_min = param->interval_min; + conn->le.interval_max = param->interval_max; + conn->le.latency = param->latency; + conn->le.timeout = param->timeout; +} +int bt_conn_update_param_le(struct bt_conn *conn, + const struct bt_le_conn_param *param) +{ +#if 0 + BT_DBG("conn %p features 0x%x params (%d-%d %d %d)", conn, + conn->le.features[0], param->interval_min, param->interval_max, + param->latency, param->timeout); +#endif + /* Check if there's a need to update conn params */ + if (conn->le.interval >= param->interval_min && + conn->le.interval <= param->interval_max) { + return -EALREADY; + } +#if 0 + if ((conn->role == BT_HCI_ROLE_SLAVE) && + !(bt_dev.le.features[0] & BT_HCI_LE_CONN_PARAM_REQ_PROC)) { + return bt_l2cap_update_conn_param(conn, param); + } + + if ((conn->le.features[0] & BT_HCI_LE_CONN_PARAM_REQ_PROC) && + (bt_dev.le.features[0] & BT_HCI_LE_CONN_PARAM_REQ_PROC)) { +#endif + return bt_conn_le_conn_update(conn, param); +#if 0 + } + return -EBUSY; +#endif +} + +void on_nble_gap_scan_start_stop_rsp(const struct nble_response *rsp) +{ + if (rsp->status) + BT_INFO("scan start/stop failed: %d", rsp->status); + /* TODO: clear scanning bit atomic_clear_bit(bt_dev.flags, BT_DEV_SCANNING) */ +} + +static int bt_hci_stop_scanning(void) +{ +#ifdef NOT_USED_FOR_NOW + struct net_buf *buf, *rsp; + struct bt_hci_cp_le_set_scan_enable *scan_enable; + int err; + + if (!atomic_test_bit(bt_dev.flags, BT_DEV_SCANNING)) { + return -EALREADY; + } + + buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_SCAN_ENABLE, + sizeof(*scan_enable)); + if (!buf) { + return -ENOBUFS; + } + + scan_enable = net_buf_add(buf, sizeof(*scan_enable)); + memset(scan_enable, 0, sizeof(*scan_enable)); + scan_enable->filter_dup = BT_HCI_LE_SCAN_FILTER_DUP_DISABLE; + scan_enable->enable = BT_HCI_LE_SCAN_DISABLE; + + err = bt_hci_cmd_send_sync(BT_HCI_OP_LE_SET_SCAN_ENABLE, buf, &rsp); + if (err) { + return err; + } + + /* Update scan state in case of success (0) status */ + err = rsp->data[0]; + if (!err) { + atomic_clear_bit(bt_dev.flags, BT_DEV_SCANNING); + } + + net_buf_unref(rsp); + + return err; +#endif + + nble_gap_stop_scan_req(); + + return 0; +} + +#if defined(CONFIG_BLUETOOTH_CENTRAL) +int bt_le_set_auto_conn(bt_addr_le_t *addr, + const struct bt_le_conn_param *param) +{ + return -EINVAL; +} +#endif /* CONFIG_BLUETOOTH_CENTRAL */ + + +static int start_le_scan(uint8_t scan_type, uint16_t interval, uint16_t window, + uint8_t filter_dup) +{ + struct nble_gap_scan_params params = { + .interval = interval, + .window = window, + .scan_type = scan_type, + }; + +#ifdef NOT_USED_FOR_NOW + struct net_buf *buf, *rsp; + struct bt_hci_cp_le_set_scan_params *set_param; + struct bt_hci_cp_le_set_scan_enable *scan_enable; + int err; + + buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_SCAN_PARAMS, + sizeof(*set_param)); + if (!buf) { + return -ENOBUFS; + } + + + set_param = net_buf_add(buf, sizeof(*set_param)); + memset(set_param, 0, sizeof(*set_param)); + set_param->scan_type = scan_type; + + /* for the rest parameters apply default values according to + * spec 4.2, vol2, part E, 7.8.10 + */ + set_param->interval = sys_cpu_to_le16(interval); + set_param->window = sys_cpu_to_le16(window); + set_param->filter_policy = 0x00; + + if (scan_type == BT_HCI_LE_SCAN_ACTIVE) { + err = le_set_nrpa(); + if (err) { + net_buf_unref(buf); + return err; + } + + set_param->addr_type = BT_ADDR_LE_RANDOM; + } else { + set_param->addr_type = BT_ADDR_LE_PUBLIC; + } + + bt_hci_cmd_send(BT_HCI_OP_LE_SET_SCAN_PARAMS, buf); + buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_SCAN_ENABLE, + sizeof(*scan_enable)); + if (!buf) { + return -ENOBUFS; + } + + scan_enable = net_buf_add(buf, sizeof(*scan_enable)); + memset(scan_enable, 0, sizeof(*scan_enable)); + scan_enable->filter_dup = filter_dup; + scan_enable->enable = BT_HCI_LE_SCAN_ENABLE; + + err = bt_hci_cmd_send_sync(BT_HCI_OP_LE_SET_SCAN_ENABLE, buf, &rsp); + if (err) { + return err; + } + /* Update scan state in case of success (0) status */ + err = rsp->data[0]; + if (!err) { + atomic_set_bit(bt_dev.flags, BT_DEV_SCANNING); + } + + net_buf_unref(rsp); +#endif + + nble_gap_start_scan_req(¶ms); + + return 0; +} + +#if NOT_USED_FOR_NOW +/* Used to determine whether to start scan and which scan type should be used */ +int bt_le_scan_update(bool fast_scan) +{ +#if defined(CONFIG_BLUETOOTH_CENTRAL) + uint16_t interval, window; + struct bt_conn *conn; +#endif /* CONFIG_BLUETOOTH_CENTRAL */ + + if (atomic_test_bit(bt_dev.flags, BT_DEV_EXPLICIT_SCAN)) { + return 0; + } + + if (atomic_test_bit(bt_dev.flags, BT_DEV_SCANNING)) { + int err; + + err = bt_hci_stop_scanning(); + if (err) { + return err; + } + } + +#if defined(CONFIG_BLUETOOTH_CENTRAL) + conn = bt_conn_lookup_state_le(NULL, BT_CONN_CONNECT_SCAN); + if (!conn) { + return 0; + } + + bt_conn_unref(conn); + + if (fast_scan) { + interval = BT_GAP_SCAN_FAST_INTERVAL; + window = BT_GAP_SCAN_FAST_WINDOW; + } else { + interval = BT_GAP_SCAN_SLOW_INTERVAL_1; + window = BT_GAP_SCAN_SLOW_WINDOW_1; + } + + return start_le_scan(BT_HCI_LE_SCAN_PASSIVE, interval, window, 0x01); +#else + return 0; +#endif /* CONFIG_BLUETOOTH_CENTRAL */ +} +#endif + +static int bt_init(void) +{ +#if NOT_USED_FOR_NOW + struct bt_driver *drv = bt_dev.drv; +#endif + int err = 0; + +#if NOT_USED_FOR_NOW + err = drv->open(); + if (err) { + BT_ERR("HCI driver open failed (%d)", err); + return err; + } + + err = hci_init(); +#endif + + if (!err) { + err = bt_conn_init(); + } + + scan_dev_found_cb = NULL; + if (!err) { + atomic_set_bit(bt_dev.flags, BT_DEV_READY); +#if 0 + bt_le_scan_update(false); +#endif + } + + return err; +} + +void on_nble_up(void) +{ + BT_DBG("%s", __FUNCTION__); + if (bt_ready_cb) + bt_ready_cb(bt_init()); +} + +extern void on_nble_curie_init(void); + +int bt_enable(bt_ready_cb_t cb) +{ + bt_ready_cb = cb; + + on_nble_curie_init(); + + if (!cb) { + return bt_init(); + } + + return 0; +} + + +static bool valid_adv_param(const struct bt_le_adv_param *param) +{ + switch (param->type) { + case BT_LE_ADV_IND: + case BT_LE_ADV_SCAN_IND: + case BT_LE_ADV_NONCONN_IND: + break; + default: + return false; + } + +#if 0 + /* checks done in Nordic */ + switch (param->addr_type) { + case BT_LE_ADV_ADDR_IDENTITY: + case BT_LE_ADV_ADDR_NRPA: + break; + default: + return false; + } + + if (param->interval_min > param->interval_max || + param->interval_min < 0x0020 || param->interval_max > 0x4000) { + return false; + } +#endif + + return true; +} + +static int set_ad(struct bt_eir_data *p_ad_data, + const struct bt_data *ad, size_t ad_len) +{ + int i; + + for (i = 0; i < ad_len; i++) { + /* Check if ad fit in the remaining buffer */ + if (p_ad_data->len + ad[i].data_len + 2 > 31) { + return -EINVAL; + } + + p_ad_data->data[p_ad_data->len++] = ad[i].data_len + 1; + p_ad_data->data[p_ad_data->len++] = ad[i].type; + + memcpy(&p_ad_data->data[p_ad_data->len], ad[i].data, + ad[i].data_len); + p_ad_data->len += ad[i].data_len; + } + + return 0; +} + +int bt_le_adv_start(const struct bt_le_adv_param *param, + const struct bt_data *ad, size_t ad_len, + const struct bt_data *sd, size_t sd_len) +{ + int err; + struct nble_gap_adv_params set_param = {0}; + struct nble_gap_ad_data_params data; + + if (!valid_adv_param(param)) { + return -EINVAL; + } + + memset(&data, 0, sizeof(data)); + + if (atomic_test_bit(bt_dev.flags, BT_DEV_KEEP_ADVERTISING)) { + return -EALREADY; + } + + err = set_advertise_disable(); + if (err) { + return err; + } + err = set_ad(&data.ad, ad, ad_len); + if (err) { + return err; + } + + /* + * Don't bother with scan response if the advertising type isn't + * a scannable one. + */ + if (param->type == BT_LE_ADV_IND || param->type == BT_LE_ADV_SCAN_IND) { + err = set_ad(&data.sd, sd, sd_len); + if (err) { + return err; + } + } + nble_gap_set_adv_data_req(&data); + + /* Timeout is handled by application timer */ + set_param.timeout = 0; + /* forced to none currently (no whitelist support) */ + set_param.filter_policy = 0; + set_param.interval_max = param->interval_max; + set_param.interval_min = param->interval_min; + set_param.type = param->type; + nble_gap_set_adv_params_req(&set_param); + +#if 0 + if (param->addr_type == BT_LE_ADV_ADDR_NRPA) { + err = le_set_nrpa(); + if (err) { + net_buf_unref(buf); + return err; + } + + set_param->own_addr_type = BT_ADDR_LE_RANDOM; + } else { + set_param->own_addr_type = BT_ADDR_LE_PUBLIC; + } + + bt_hci_cmd_send(BT_HCI_OP_LE_SET_ADV_PARAMETERS, buf); +#endif + + err = set_advertise_enable(); + if (err) { + return err; + } + + atomic_set_bit(bt_dev.flags, BT_DEV_KEEP_ADVERTISING); + + return 0; +} + +void on_nble_gap_dir_adv_timeout_evt(const struct nble_gap_dir_adv_timeout_evt *p_evt) +{ + struct bt_conn *conn = bt_conn_lookup_state_le(BT_ADDR_LE_ANY, BT_CONN_CONNECT); + + if (conn) { + atomic_clear_bit(bt_dev.flags, BT_DEV_ADVERTISING); + conn->err = p_evt->error; + bt_conn_set_state(conn, BT_CONN_DISCONNECTED); + bt_conn_unref(conn); + } +} + +int bt_le_adv_stop(void) +{ + int err; + + if (!atomic_test_bit(bt_dev.flags, BT_DEV_KEEP_ADVERTISING)) { + return -EALREADY; + } + + err = set_advertise_disable(); + if (err) { + return err; + } + atomic_clear_bit(bt_dev.flags, BT_DEV_KEEP_ADVERTISING); + + return 0; +} + +static bool valid_le_scan_param(const struct bt_le_scan_param *param) +{ + if (param->type != BT_HCI_LE_SCAN_PASSIVE && + param->type != BT_HCI_LE_SCAN_ACTIVE) { + return false; + } + + if (/* param->filter_dup != BT_HCI_LE_SCAN_FILTER_DUP_DISABLE */ + /* && nble always filters duplicates */ + param->filter_dup != BT_HCI_LE_SCAN_FILTER_DUP_ENABLE) { + return false; + } + + if (param->interval < 0x0004 || param->interval > 0x4000) { + return false; + } + + if (param->window < 0x0004 || param->window > 0x4000) { + return false; + } + + if (param->window > param->interval) { + return false; + } + + return true; +} + +int bt_le_scan_start(const struct bt_le_scan_param *param, bt_le_scan_cb_t cb) +{ + + int err; + + /* Check that the parameters have valid values */ + if (!valid_le_scan_param(param)) { + return -EINVAL; + } +#if NOT_USED_FOR_NOW + /* Return if active scan is already enabled */ + if (atomic_test_and_set_bit(bt_dev.flags, BT_DEV_EXPLICIT_SCAN)) { + return -EALREADY; + } + + if (atomic_test_bit(bt_dev.flags, BT_DEV_SCANNING)) { + err = bt_hci_stop_scanning(); + if (err) { + atomic_clear_bit(bt_dev.flags, BT_DEV_EXPLICIT_SCAN); + return err; + } + } +#endif + + err = start_le_scan(param->type, param->interval, param->window, + param->filter_dup); + + + if (err) { +#if NOT_USED_FOR_NOW + atomic_clear_bit(bt_dev.flags, BT_DEV_EXPLICIT_SCAN); +#endif + return err; + } + + scan_dev_found_cb = cb; + + return 0; +} + +int bt_le_scan_stop(void) +{ +#if NOT_USED_FOR_NOW + /* Return if active scanning is already disabled */ + if (!atomic_test_and_clear_bit(bt_dev.flags, BT_DEV_EXPLICIT_SCAN)) { + return -EALREADY; + } +#endif + scan_dev_found_cb = NULL; + +#if NOT_USED_FOR_NOW + return bt_le_scan_update(false); +#else + return bt_hci_stop_scanning(); +#endif +} + +/* Temporary RSSI patch for UAS: RPC need definition if UAS not compiled */ +__attribute__((weak)) +void on_nble_uas_bucket_change(const struct nble_uas_bucket_change *p_params) +{ +} + +void ble_gap_set_rssi_report(struct nble_rssi_report_params *params, + struct bt_conn *conn, + rssi_report_resp_t resp_cb, rssi_report_t evt_cb) +{ + rssi_report_cb = evt_cb; + + params->conn_handle = conn->handle; + + nble_gap_set_rssi_report_req(params, resp_cb); +} + +void on_nble_gap_set_rssi_report_rsp(const struct nble_response *params) +{ + rssi_report_resp_t resp_cb = params->user_data; + + if (resp_cb) + resp_cb(params->status); +} + +void on_nble_gap_rssi_evt(const struct nble_gap_rssi_evt *event) +{ + if (rssi_report_cb) + rssi_report_cb(event->rssi_data); +} + +void ble_gap_set_tx_power(int8_t tx_power) +{ + struct nble_gap_tx_power_params params = { + .tx_power = tx_power, + }; + nble_gap_tx_power_req(¶ms); +} + +void on_nble_gap_tx_power_rsp(const struct nble_response *params) +{ +} + +void ble_gap_get_version(ble_get_version_cb_t func) +{ + struct nble_gap_get_version_param params; + + params.cb = func; + + nble_get_version_req(¶ms); +} + +void on_nble_get_version_rsp(const struct nble_version_response *par) +{ + struct nble_gap_get_version_param param = par->params; + ble_get_version_cb_t cb = param.cb; + + if (cb) { + cb(&par->ver); + } +} + +void bt_le_set_device_name(char *device_name, int len) +{ + struct nble_gap_service_write_params gap_service_params; + if (len > 20) + len = 20; + memset(&gap_service_params, 0, sizeof(gap_service_params)); + gap_service_params.attr_type = NBLE_GAP_SVC_ATTR_NAME; + gap_service_params.name.len = len; + gap_service_params.name.sec_mode = 0x11;// GAP_SEC_LEVEL_1 | GAP_SEC_MODE_1; + memcpy(gap_service_params.name.name_array, device_name, len); + nble_gap_service_write_req(&gap_service_params); +} + diff --git a/system/libarc32_arduino101/framework/src/services/ble/gatt.c b/system/libarc32_arduino101/framework/src/services/ble/gatt.c new file mode 100644 index 00000000..d3ef4c09 --- /dev/null +++ b/system/libarc32_arduino101/framework/src/services/ble/gatt.c @@ -0,0 +1,1561 @@ +/* + * Copyright (c) 2016 Intel Corporation + * + * 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 +#include +#include +#include + +#include + +#include +#include "gatt_internal.h" +#include "hci_core.h" +#include "conn_internal.h" + +/* #define BT_GATT_DEBUG 1 */ + +extern void on_nble_curie_log(char *fmt, ...); +extern void __assert_fail(void); +#ifdef BT_GATT_DEBUG +#define BT_DBG(fmt, ...) on_nble_curie_log(fmt, ##__VA_ARGS__) +#define BT_ERR(fmt, ...) on_nble_curie_log(fmt, ##__VA_ARGS__) +#define BT_WARN(fmt, ...) on_nble_curie_log(fmt, ##__VA_ARGS__) +#define BT_INFO(fmt, ...) on_nble_curie_log(fmt, ##__VA_ARGS__) +#define BT_ASSERT(cond) ((cond) ? (void)0 : __assert_fail()) +#else +#define BT_DBG(fmt, ...) do {} while (0) +#define BT_ERR(fmt, ...) on_nble_curie_log(fmt, ##__VA_ARGS__) +#define BT_WARN(fmt, ...) on_nble_curie_log(fmt, ##__VA_ARGS__) +#define BT_INFO(fmt, ...) on_nble_curie_log(fmt, ##__VA_ARGS__) +#define BT_ASSERT(cond) ((cond) ? (void)0 : __assert_fail()) +#endif + +#define N_BLE_BUF_SIZE 512 + +struct ble_gatt_service { + struct bt_gatt_attr *attrs; /* Pointer to the array of attributes */ + uint16_t attr_count; /* Number of attributes in the array */ +}; + +struct ble_gatts_flush_all { + struct bt_conn *conn; + int status; + uint8_t flag; +}; + +static struct ble_gatt_service db[CONFIG_BT_GATT_BLE_MAX_SERVICES]; + +static uint8_t db_cnt; + +#if defined(CONFIG_BLUETOOTH_GATT_CLIENT) +static struct bt_gatt_subscribe_params *subscriptions; +#endif + +/** + * Copy a UUID in a buffer using the smallest memory length + * @param buf Pointer to the memory where the UUID shall be copied + * @param uuid Pointer to the UUID to copy + * @return The length required to store the UUID in the memory + */ +static uint8_t bt_gatt_uuid_memcpy(uint8_t *buf, + const struct bt_uuid *uuid) +{ + uint8_t *ptr = buf; + + /* Store the type of the UUID */ + *ptr = uuid->type; + ptr++; + + /* Store the UUID data */ + if (uuid->type == BT_UUID_TYPE_16) { + uint16_t le16; + + le16 = sys_cpu_to_le16(BT_UUID_16(uuid)->val); + memcpy(ptr, &le16, sizeof(le16)); + ptr += sizeof(le16); + } else { + memcpy(ptr, BT_UUID_128(uuid)->val, + sizeof(BT_UUID_128(uuid)->val)); + ptr += sizeof(BT_UUID_128(uuid)->val); + } + return ptr - buf; +} + +/* These attributes need the value to be read */ +static struct bt_uuid *whitelist[] = { + BT_UUID_GATT_PRIMARY, + BT_UUID_GATT_SECONDARY, + BT_UUID_GATT_INCLUDE, + BT_UUID_GATT_CHRC, + BT_UUID_GATT_CEP, + BT_UUID_GATT_CUD, + BT_UUID_GATT_CPF, + BT_UUID_GAP_DEVICE_NAME, + BT_UUID_GAP_APPEARANCE, + BT_UUID_GAP_PPCP +}; + +static int attr_read(struct bt_gatt_attr *attr, uint8_t *data, size_t len) +{ + uint8_t i; + int data_size; + + if (!data || len < 0) { + return -ENOMEM; + } + + data_size = bt_gatt_uuid_memcpy(data, attr->uuid); + + for (i = 0; i < ARRAY_SIZE(whitelist); i++) { + if (!bt_uuid_cmp(attr->uuid, whitelist[i])) { + int read; + + read = attr->read(NULL, attr, data + data_size, len, + 0); + if (read < 0) { + return read; + } + + data_size += read; + break; + } + } + + return data_size; +} + +int bt_gatt_register(struct bt_gatt_attr *attrs, size_t count) +{ + size_t attr_table_size, i; + struct nble_gatt_register_req param; + /* TODO: Replace the following with net_buf */ + uint8_t attr_table[N_BLE_BUF_SIZE]; + + if (!attrs || !count) { + return -EINVAL; + } + BT_ASSERT(db_cnt < ARRAY_SIZE(db)); + + db[db_cnt].attrs = attrs; + db[db_cnt].attr_count = count; + db_cnt++; + param.attr_base = attrs; + param.attr_count = count; + + attr_table_size = 0; + + for (i = 0; i < count; i++) { + struct bt_gatt_attr *attr = &attrs[i]; + struct ble_gatt_attr *att; + int data_size; + + if (attr_table_size + sizeof(*att) > sizeof(attr_table)) { + return -ENOMEM; + } + + att = (void *)&attr_table[attr_table_size]; + att->perm = attr->perm; + + /* Read attribute data */ + data_size = attr_read(attr, att->data, + sizeof(attr_table) - + (attr_table_size + sizeof(*att))); + if (data_size < 0) { + return data_size; + } + att->data_size = data_size; + + BT_DBG("table size = %u attr data_size = %u", attr_table_size, + att->data_size); + + /* Compute the new element size and align it on upper 4 bytes + * boundary. + */ + attr_table_size += (sizeof(*att) + att->data_size + 3) & ~3; + } + + nble_gatt_register_req(¶m, attr_table, attr_table_size); + return 0; +} + +void on_nble_gatt_register_rsp(const struct nble_gatt_register_rsp *rsp, + const struct nble_gatt_attr_handles *handles, uint8_t len) +{ + + if (rsp->status != 0) { + BT_ERR("failure registering table: %d - %u - %p", rsp->status, + rsp->attr_count, rsp->attr_base); + } +#ifdef BT_GATT_DEBUG + BT_DBG("register rsp : s=%d - b=%p - c=%u", rsp->status, + rsp->attr_base, rsp->attr_count); + { + int i; + + for (i = 0; i < rsp->attr_count; i++) { + if (handles[i].handle != 0) { + BT_DBG("gatt: i %d, h %d, type %d, u16 0x%x", + i, handles[i].handle, + rsp->attr_base[i].uuid->type, + BT_UUID_16(rsp->attr_base[i].uuid)->val); + } + } + } +#endif +} + +ssize_t bt_gatt_attr_read(struct bt_conn *conn, const struct bt_gatt_attr *attr, + void *buf, uint16_t buf_len, uint16_t offset, + const void *value, uint16_t value_len) +{ + uint16_t len; + + if (offset > value_len) { + return BT_GATT_ERR(BT_ATT_ERR_INVALID_OFFSET); + } + + len = min(buf_len, value_len - offset); + + BT_DBG("handle 0x%04x offset %u length %u", attr->handle, offset, + len); + + memcpy(buf, value + offset, len); + + return len; +} + +ssize_t bt_gatt_attr_read_service(struct bt_conn *conn, + const struct bt_gatt_attr *attr, + void *buf, uint16_t len, uint16_t offset) +{ + struct bt_uuid *uuid = attr->user_data; + + if (uuid->type == BT_UUID_TYPE_16) { + uint16_t uuid16 = sys_cpu_to_le16(BT_UUID_16(uuid)->val); + + return bt_gatt_attr_read(conn, attr, buf, len, offset, + &uuid16, 2); + } + + return bt_gatt_attr_read(conn, attr, buf, len, offset, + BT_UUID_128(uuid)->val, 16); +} + +struct gatt_incl { + uint16_t start_handle; + uint16_t end_handle; + uint16_t uuid16; +} __packed; + +ssize_t bt_gatt_attr_read_included(struct bt_conn *conn, + const struct bt_gatt_attr *attr, + void *buf, uint16_t len, uint16_t offset) +{ + struct bt_gatt_include *incl = attr->user_data; + struct gatt_incl pdu; + uint8_t value_len; + + pdu.start_handle = sys_cpu_to_le16(incl->start_handle); + pdu.end_handle = sys_cpu_to_le16(incl->end_handle); + value_len = sizeof(pdu.start_handle) + sizeof(pdu.end_handle); + + /* + * Core 4.2, Vol 3, Part G, 3.2, + * The Service UUID shall only be present when the UUID is a 16-bit + * Bluetooth UUID. + */ + if (incl->uuid->type == BT_UUID_TYPE_16) { + pdu.uuid16 = sys_cpu_to_le16(BT_UUID_16(incl->uuid)->val); + value_len += sizeof(pdu.uuid16); + } + + return bt_gatt_attr_read(conn, attr, buf, len, offset, &pdu, value_len); +} + +struct gatt_chrc { + uint8_t properties; + uint16_t value_handle; + union { + uint16_t uuid16; + uint8_t uuid[16]; + }; +} __packed; + +ssize_t bt_gatt_attr_read_chrc(struct bt_conn *conn, + const struct bt_gatt_attr *attr, void *buf, + uint16_t len, uint16_t offset) +{ + struct bt_gatt_chrc *chrc = attr->user_data; + struct gatt_chrc pdu; + uint8_t value_len; + + pdu.properties = chrc->properties; + /* BLUETOOTH SPECIFICATION Version 4.2 [Vol 3, Part G] page 534: + * 3.3.2 Characteristic Value Declaration + * The Characteristic Value declaration contains the value of the + * characteristic. It is the first Attribute after the characteristic + * declaration. All characteristic definitions shall have a + * Characteristic Value declaration. + */ +#if 0 + next = bt_gatt_attr_next(attr); + if (!next) { + BT_WARN("No value for characteristic at 0x%04x", attr->handle); + pdu.value_handle = 0x0000; + } else { + pdu.value_handle = sys_cpu_to_le16(next->handle); + } +#else + pdu.value_handle = 0x0000; +#endif + value_len = sizeof(pdu.properties) + sizeof(pdu.value_handle); + + if (chrc->uuid->type == BT_UUID_TYPE_16) { + pdu.uuid16 = sys_cpu_to_le16(BT_UUID_16(chrc->uuid)->val); + value_len += 2; + } else { + memcpy(pdu.uuid, BT_UUID_128(chrc->uuid)->val, 16); + value_len += 16; + } + + return bt_gatt_attr_read(conn, attr, buf, len, offset, &pdu, value_len); +} + +void bt_gatt_foreach_attr(uint16_t start_handle, uint16_t end_handle, + bt_gatt_attr_func_t func, void *user_data) +{ + + const struct bt_gatt_attr *attr; + + BT_ASSERT(start_handle == 1 && end_handle == 0xFFFF); + + for (attr = db[0].attrs; attr; attr = bt_gatt_attr_next(attr)) { +#if 0 + /* Check if attribute handle is within range */ + if (attr->handle < start_handle || attr->handle > end_handle) { + continue; + } +#endif + + if (func(attr, user_data) == BT_GATT_ITER_STOP) { + break; + } + } +} + +struct bt_gatt_attr *bt_gatt_attr_next(const struct bt_gatt_attr *attr) +{ + struct ble_gatt_service *svc, *svc_last; + + svc_last = &db[db_cnt]; + + for (svc = db; svc < svc_last; svc++) { + if (attr >= svc->attrs && attr < &svc->attrs[svc->attr_count]) { + int index = attr - &svc->attrs[0]; + + if (index < (svc->attr_count - 1)) { + return (struct bt_gatt_attr *)&attr[1]; + } else if ((svc + 1) < svc_last) { + return (svc + 1)->attrs; + } else { + return NULL; + } + } + } + /* Normally, we should not reach here */ + return NULL; +} + +ssize_t bt_gatt_attr_read_ccc(struct bt_conn *conn, + const struct bt_gatt_attr *attr, void *buf, + uint16_t len, uint16_t offset) +{ + return BT_GATT_ERR(BT_ATT_ERR_NOT_SUPPORTED); + +#if 0 + struct _bt_gatt_ccc *ccc = attr->user_data; + uint16_t value; + size_t i; + + for (i = 0; i < ccc->cfg_len; i++) { + if (bt_addr_le_cmp(&ccc->cfg[i].peer, &conn->le.dst)) { + continue; + } + + value = sys_cpu_to_le16(ccc->cfg[i].value); + break; + } + + /* Default to disable if there is no cfg for the peer */ + if (i == ccc->cfg_len) { + value = 0x0000; + } + + return bt_gatt_attr_read(conn, attr, buf, len, offset, &value, + sizeof(value)); +#endif +} + +static void gatt_ccc_changed(struct _bt_gatt_ccc *ccc) +{ + int i; + uint16_t value = 0x0000; + + for (i = 0; i < ccc->cfg_len; i++) { + if (ccc->cfg[i].value > value) { + value = ccc->cfg[i].value; + } + } + + BT_DBG("ccc %p value 0x%04x", ccc, value); + + if (value != ccc->value) { + ccc->value = value; + if (ccc->cfg_changed) + ccc->cfg_changed(value); + } +} + +#if defined(CONFIG_BLUETOOTH_GATT_CLIENT) +static bool is_bonded(const bt_addr_le_t *addr) +{ +#if defined(CONFIG_BLUETOOTH_SMP) + struct bt_conn *conn = bt_conn_lookup_addr_le(addr); + + /* + * this is a temporary workaround. if encrypt is set, we know we are + * paired. nble does not yet report if device is bonded. + */ + if (conn) { + uint8_t encrypt = conn->encrypt; + + bt_conn_unref(conn); + + return encrypt; + } + return false; +#else + return false; +#endif /* defined(CONFIG_BLUETOOTH_SMP) */ +} +#endif + +ssize_t bt_gatt_attr_write_ccc(struct bt_conn *conn, + const struct bt_gatt_attr *attr, const void *buf, + uint16_t len, uint16_t offset) +{ + struct _bt_gatt_ccc *ccc = attr->user_data; + const uint16_t *data = buf; + size_t i; + + //BT_DBG("%s", __FUNCTION__); + + if (offset > sizeof(*data)) { + return BT_GATT_ERR(BT_ATT_ERR_INVALID_OFFSET); + } + + //BT_DBG("%s1", __FUNCTION__); + + if (offset + len > sizeof(*data)) { + return BT_GATT_ERR(BT_ATT_ERR_INVALID_ATTRIBUTE_LEN); + } + + //BT_DBG("%s2", __FUNCTION__); + + for (i = 0; i < ccc->cfg_len; i++) { + /* Check for existing configuration */ + if (!bt_addr_le_cmp(&ccc->cfg[i].peer, &conn->le.dst)) { + break; + } + } + + //BT_DBG("%s3", __FUNCTION__); + + if (i == ccc->cfg_len) { + for (i = 0; i < ccc->cfg_len; i++) { + /* Check for unused configuration */ + if (!ccc->cfg[i].valid) { + bt_addr_le_copy(&ccc->cfg[i].peer, &conn->le.dst); +#if NOT_USED_FOR_THE_TIME_BEING + /* Only set valid if bonded */ + ccc->cfg[i].valid = is_bonded(&conn->le.dst); +#endif + break; + } + } + + if ((i == ccc->cfg_len) && (ccc->cfg_len)) { + BT_WARN("No space to store CCC cfg"); + return -ENOMEM; + } + } + + //BT_DBG("%s len-%p", __FUNCTION__, ccc); + + ccc->cfg[i].value = sys_le16_to_cpu(*data); + //BT_DBG("%s 5len-%d", __FUNCTION__, len); + + //BT_DBG("handle 0x%04x value %u", attr->handle, *data); + + /* Update cfg if don't match */ + if (ccc->value != *data) { + gatt_ccc_changed(ccc); + } + + return len; +} + +ssize_t bt_gatt_attr_read_cep(struct bt_conn *conn, + const struct bt_gatt_attr *attr, void *buf, + uint16_t len, uint16_t offset) +{ + struct bt_gatt_cep *value = attr->user_data; + uint16_t props = sys_cpu_to_le16(value->properties); + + return bt_gatt_attr_read(conn, attr, buf, len, offset, &props, + sizeof(props)); +} + +ssize_t bt_gatt_attr_read_cud(struct bt_conn *conn, + const struct bt_gatt_attr *attr, void *buf, + uint16_t len, uint16_t offset) +{ + char *value = attr->user_data; + + return bt_gatt_attr_read(conn, attr, buf, len, offset, value, strlen(value)); +} + +ssize_t bt_gatt_attr_read_cpf(struct bt_conn *conn, + const struct bt_gatt_attr *attr, void *buf, + uint16_t len, uint16_t offset) +{ + struct bt_gatt_cpf *value = attr->user_data; + + return bt_gatt_attr_read(conn, attr, buf, len, offset, value, + sizeof(*value)); +} + +struct notify_data { + uint16_t state; + uint16_t type; + const struct bt_gatt_attr *attr; + const void *data; + uint16_t len; + bt_gatt_notify_sent_func_t notify_cb; + struct bt_gatt_indicate_params *params; +}; + +static int att_notify(struct bt_conn *conn, const struct bt_gatt_attr *attr, + const void *data, size_t len, + bt_gatt_notify_sent_func_t cb) +{ + struct nble_gatt_send_notif_params notif; + + notif.conn_handle = conn->handle; + notif.params.attr = attr; + notif.params.offset = 0; + notif.cback = cb; + + nble_gatt_send_notif_req(¬if, data, len); + + return 0; +} + +void on_nble_gatts_send_notif_rsp(const struct nble_gatt_notif_rsp *rsp) +{ + struct bt_conn *conn; + + conn = bt_conn_lookup_handle(rsp->conn_handle); + + if (conn) { + if (rsp->cback) { + rsp->cback(conn, rsp->attr, rsp->status); + } + bt_conn_unref(conn); + } +} + +void on_nble_gatts_send_ind_rsp(const struct nble_gatt_ind_rsp *rsp) +{ + struct bt_conn *conn; + + conn = bt_conn_lookup_handle(rsp->conn_handle); + + if (conn) { + if (rsp->cback) { + rsp->cback(conn, rsp->attr, rsp->status); + } + bt_conn_unref(conn); + } +} + +static int att_indicate(struct bt_conn *conn, + struct bt_gatt_indicate_params *params) +{ + struct nble_gatt_send_ind_params ind; + + ind.conn_handle = conn->handle; + ind.cback = params->func; + ind.params.attr = params->attr; + ind.params.offset = 0; + + nble_gatt_send_ind_req(&ind, params->data, params->len); + + return 0; +} + +static uint8_t notify_cb(const struct bt_gatt_attr *attr, void *user_data) +{ + struct notify_data *data = user_data; + struct _bt_gatt_ccc *ccc; + size_t i; + + /* Check if the attribute was reached */ + if (data->state == 0) { + if (attr == data->attr) + data->state = 1; + return BT_GATT_ITER_CONTINUE; + } + + if (bt_uuid_cmp(attr->uuid, BT_UUID_GATT_CCC)) { + /* Stop if we reach the next characteristic */ + if (!bt_uuid_cmp(attr->uuid, BT_UUID_GATT_CHRC)) { + return BT_GATT_ITER_STOP; + } + return BT_GATT_ITER_CONTINUE; + } + + /* Check attribute user_data must be of type struct _bt_gatt_ccc */ + if (attr->write != bt_gatt_attr_write_ccc) { + return BT_GATT_ITER_CONTINUE; + } + + ccc = attr->user_data; + + /* Notify all peers configured */ + for (i = 0; i < ccc->cfg_len; i++) { + struct bt_conn *conn; + int err; + + if (ccc->value != data->type) { + continue; + } + + conn = bt_conn_lookup_addr_le(&ccc->cfg[i].peer); + if (!conn || conn->state != BT_CONN_CONNECTED) {//Bug here + continue; + } + + if (data->type == BT_GATT_CCC_INDICATE) { + err = att_indicate(conn, data->params); + + } else { + err = att_notify(conn, data->attr, data->data, + data->len, data->notify_cb); + } + + bt_conn_unref(conn); + + if (err < 0) { + return BT_GATT_ITER_STOP; + } + } + + return BT_GATT_ITER_CONTINUE; +} + +int bt_gatt_notify(struct bt_conn *conn, const struct bt_gatt_attr *attr, + const void *data, uint16_t len, + bt_gatt_notify_sent_func_t cb) +{ + struct notify_data nfy; + + if (!attr) { + return -EINVAL; + } + + if (conn) { + return att_notify(conn, attr, data, len, cb); + } + + nfy.state = 0; + nfy.attr = attr; + nfy.type = BT_GATT_CCC_NOTIFY; + nfy.data = data; + nfy.len = len; + nfy.notify_cb = cb; + + bt_gatt_foreach_attr(1, 0xffff, notify_cb, &nfy); + + return 0; +} + +int bt_gatt_indicate(struct bt_conn *conn, + struct bt_gatt_indicate_params *params) +{ + struct notify_data nfy; + + if (!params || !params->attr) { + return -EINVAL; + } + + if (conn) { + return att_indicate(conn, params); + } + + nfy.state = 0; + nfy.type = BT_GATT_CCC_INDICATE; + nfy.params = params; + + bt_gatt_foreach_attr(1, 0xffff, notify_cb, &nfy); + + return 0; +} + +static uint8_t connected_cb(const struct bt_gatt_attr *attr, void *user_data) +{ + struct bt_conn *conn = user_data; + struct _bt_gatt_ccc *ccc; + size_t i; + + /* Check attribute user_data must be of type struct _bt_gatt_ccc */ + if (attr->write != bt_gatt_attr_write_ccc) { + return BT_GATT_ITER_CONTINUE; + } + + ccc = attr->user_data; + + /* If already enabled skip */ + if (ccc->value) { + return BT_GATT_ITER_CONTINUE; + } + + for (i = 0; i < ccc->cfg_len; i++) { + /* Ignore configuration for different peer */ + if (bt_addr_le_cmp(&conn->le.dst, &ccc->cfg[i].peer)) { + continue; + } + + if (ccc->cfg[i].value) { + gatt_ccc_changed(ccc); + return BT_GATT_ITER_CONTINUE; + } + } + + return BT_GATT_ITER_CONTINUE; +} + +static uint8_t disconnected_cb(const struct bt_gatt_attr *attr, void *user_data) +{ + struct bt_conn *conn = user_data; + struct _bt_gatt_ccc *ccc; + size_t i; + + /* Check attribute user_data must be of type struct _bt_gatt_ccc */ + if (attr->write != bt_gatt_attr_write_ccc) { + return BT_GATT_ITER_CONTINUE; + } + + ccc = attr->user_data; + + /* If already disabled skip */ + if (!ccc->value) { + return BT_GATT_ITER_CONTINUE; + } + + for (i = 0; i < ccc->cfg_len; i++) { + /* Ignore configurations with disabled value */ + if (!ccc->cfg[i].value) { + continue; + } + + if (bt_addr_le_cmp(&conn->le.dst, &ccc->cfg[i].peer)) { + struct bt_conn *tmp; + + /* Skip if there is another peer connected */ + tmp = bt_conn_lookup_addr_le(&ccc->cfg[i].peer); + if (tmp) { + if (tmp->state == BT_CONN_CONNECTED) { + bt_conn_unref(tmp); + return BT_GATT_ITER_CONTINUE; + } + + bt_conn_unref(tmp); + } + } + } + + /* Reset value while disconnected */ + memset(&ccc->value, 0, sizeof(ccc->value)); + + if (ccc->cfg_changed) { + ccc->cfg_changed(ccc->value); + } + + BT_DBG("ccc %p reseted", ccc); + + return BT_GATT_ITER_CONTINUE; +} + +void on_nble_gatts_write_evt(const struct nble_gatt_wr_evt *evt, + const uint8_t *buf, uint8_t buflen) +{ + const struct bt_gatt_attr *attr = evt->attr; + struct bt_conn *conn = bt_conn_lookup_handle(evt->conn_handle); + struct nble_gatts_wr_reply_params reply_data; + + //BT_DBG("write_evt %p", attr); + + /* Check for write support and flush support in case of prepare */ + if (!attr->write || + ((evt->flag & NBLE_GATT_WR_FLAG_PREP) && !attr->flush)) { + reply_data.status = BT_GATT_ERR(BT_ATT_ERR_WRITE_NOT_PERMITTED); + + goto reply; + } + //BT_DBG("%s", __FUNCTION__); + + reply_data.status = attr->write(conn, attr, buf, buflen, evt->offset); + if (reply_data.status < 0) { + + //BT_DBG("%s1-1", __FUNCTION__); + + goto reply; + } + + //BT_DBG("%s1", __FUNCTION__); + + /* Return an error if not all data has been written */ + if (reply_data.status != buflen) { + reply_data.status = BT_GATT_ERR(BT_ATT_ERR_UNLIKELY); + + goto reply; + } + + //BT_DBG("%s2", __FUNCTION__); + + if (attr->flush && !(evt->flag & NBLE_GATT_WR_FLAG_PREP)) + reply_data.status = attr->flush(conn, attr, BT_GATT_FLUSH_SYNC); + + //BT_DBG("%s3", __FUNCTION__); + +reply: + //BT_DBG("%s4", __FUNCTION__); + if (evt->flag & NBLE_GATT_WR_FLAG_REPLY) { + reply_data.conn_handle = evt->conn_handle; + + nble_gatts_wr_reply_req(&reply_data); + } + + if (conn) + bt_conn_unref(conn); +} + +static uint8_t flush_all(const struct bt_gatt_attr *attr, void *user_data) +{ + struct ble_gatts_flush_all *flush_data = user_data; + + if (attr->flush) { + int status = attr->flush(flush_data->conn, attr, flush_data->flag); + + if (status < 0 && flush_data->status == 0) + flush_data->status = status; + } + + return BT_GATT_ITER_CONTINUE; +} + +void on_nble_gatts_write_exec_evt(const struct nble_gatt_wr_exec_evt *evt) +{ + BT_DBG("write_exec_evt"); + + struct ble_gatts_flush_all flush_data = { + .conn = bt_conn_lookup_handle(evt->conn_handle), + .flag = evt->flag, + .status = 0, + }; + + bt_gatt_foreach_attr(0x0001, 0xFFFF, flush_all, &flush_data); + + struct nble_gatts_wr_reply_params reply_data = { + .conn_handle = evt->conn_handle, + .status = flush_data.status, + }; + nble_gatts_wr_reply_req(&reply_data); + + bt_conn_unref(flush_data.conn); +} + +void on_nble_gatts_read_evt(const struct nble_gatt_rd_evt *evt) +{ + struct nble_gatts_rd_reply_params reply_data; + const struct bt_gatt_attr *attr; + /* The length of the value sent back in the response is unknown because + * of NRF API limitation, so we use the max possible one: ATT_MTU-1 */ + uint8_t data[BLE_GATT_MTU_SIZE - 1] = { 0 }; + int len; + + attr = evt->attr; + + BT_DBG("read_evt %p", attr); + + memset(&reply_data, 0, sizeof(reply_data)); + + if (attr->read) { + struct bt_conn *conn = bt_conn_lookup_handle(evt->conn_handle); + + len = attr->read(conn, attr, data, sizeof(data), evt->offset); + + if (conn) + bt_conn_unref(conn); + + } else { + len = BT_GATT_ERR(BT_ATT_ERR_READ_NOT_PERMITTED); + } + + /* status >= 0 is considered as success by nble */ + reply_data.status = len; + + if (len < 0) { + len = 0; + } + + reply_data.conn_handle = evt->conn_handle; + + /* offset is needed by nble even in error case */ + reply_data.offset = evt->offset; + + nble_gatts_rd_reply_req(&reply_data, data, len); +} + +#if defined(CONFIG_BLUETOOTH_GATT_CLIENT) +void on_nble_gattc_value_evt(const struct ble_gattc_value_evt *evt, + uint8_t *data, uint8_t length) +{ + struct bt_gatt_subscribe_params *params; + struct bt_conn *conn; + + conn = bt_conn_lookup_handle(evt->conn_handle); + + //BT_DBG("FUNC %s", __FUNCTION__); + + if (conn) { + for (params = subscriptions; params; params = params->_next) { + if (evt->handle != params->value_handle) { + continue; + } + + if (params->notify(conn, params, data, length) == + BT_GATT_ITER_STOP) { + bt_gatt_unsubscribe(conn, params); + } + } + bt_conn_unref(conn); + } +} + +static void gatt_subscription_remove(struct bt_conn *conn, + struct bt_gatt_subscribe_params *prev, + struct bt_gatt_subscribe_params *params) +{ + /* Remove subscription from the list*/ + if (!prev) { + subscriptions = params->_next; + } else { + prev->_next = params->_next; + } + + params->notify(conn, params, NULL, 0); +} + +static void remove_subscribtions(struct bt_conn *conn) +{ + struct bt_gatt_subscribe_params *params, *prev; + + /* Lookup existing subscriptions */ + for (params = subscriptions, prev = NULL; params; + prev = params, params = params->_next) { + if (bt_addr_le_cmp(¶ms->_peer, &conn->le.dst)) { + continue; + } + + /* Remove subscription */ + gatt_subscription_remove(conn, prev, params); + } +} + +int bt_gatt_exchange_mtu(struct bt_conn *conn, bt_gatt_rsp_func_t func) +{ + return -EINVAL; +} + +void on_nble_gattc_discover_rsp(const struct nble_gattc_discover_rsp *rsp, + const uint8_t *data, uint8_t data_len) +{ + size_t i; + uint8_t attr_count; + uint16_t last_handle; + int status = BT_GATT_ITER_STOP; + struct bt_gatt_discover_params *params; + struct bt_gatt_service svc_value; + struct bt_gatt_include inc_value; + struct bt_conn *conn = bt_conn_lookup_handle(rsp->conn_handle); + + BT_ASSERT(conn); + + params = rsp->user_data; + + BT_DBG("disc_rsp: s=%d", rsp->status); + + if (rsp->status) + goto complete; + + if (rsp->type == BT_GATT_DISCOVER_PRIMARY) { + attr_count = (data_len / sizeof(struct nble_gattc_primary)); + } else if (rsp->type == BT_GATT_DISCOVER_INCLUDE) { + attr_count = (data_len / sizeof(struct nble_gattc_included)); + } else if (rsp->type == BT_GATT_DISCOVER_CHARACTERISTIC) { + attr_count = (data_len / sizeof(struct nble_gattc_characteristic)); + } else if (rsp->type == BT_GATT_DISCOVER_DESCRIPTOR) { + attr_count = (data_len / sizeof(struct nble_gattc_descriptor)); + } else + goto complete; + BT_DBG("disc_rsp: c=%d", attr_count); + last_handle = params->end_handle; + for (i = 0; i < attr_count; i++) { + struct bt_gatt_attr *attr = NULL; + + if (rsp->type == BT_GATT_DISCOVER_PRIMARY) { + const struct nble_gattc_primary *gattr = + (void *)&data[i * sizeof(*gattr)]; + if ((gattr->range.start_handle < params->start_handle) && + (gattr->range.end_handle > params->end_handle)) { + /* + * Only the attributes with attribute handles + * between and including the Starting + * Handle and the Ending Handle is returned + */ + goto complete; + } + svc_value.end_handle = gattr->range.end_handle; + svc_value.uuid = params->uuid; + attr = (&(struct bt_gatt_attr)BT_GATT_PRIMARY_SERVICE(&svc_value)); + attr->handle = gattr->handle; + last_handle = svc_value.end_handle; + } else if (rsp->type == BT_GATT_DISCOVER_INCLUDE) { + const struct nble_gattc_included *gattr = + (void *)&data[i * sizeof(*gattr)]; + + inc_value.start_handle = gattr->range.start_handle; + inc_value.end_handle = gattr->range.end_handle; + /* + * 4.5.1 If the service UUID is a 16-bit Bluetooth UUID + * it is also returned in the response. + */ + switch (gattr->uuid.uuid.type) { + case BT_UUID_TYPE_16: + inc_value.uuid = &gattr->uuid.uuid; + break; + case BT_UUID_TYPE_128: + /* Data is not available at this point */ + break; + } + attr = (&(struct bt_gatt_attr) + BT_GATT_INCLUDE_SERVICE(&inc_value)); + attr->handle = gattr->handle; + last_handle = gattr->handle; + } else if (rsp->type == BT_GATT_DISCOVER_CHARACTERISTIC) { + const struct nble_gattc_characteristic *gattr = + (void *)&data[i * sizeof(*gattr)]; + attr = (&(struct bt_gatt_attr) + BT_GATT_CHARACTERISTIC(&gattr->uuid.uuid, + gattr->prop)); + attr->handle = gattr->handle; + last_handle = gattr->handle; + /* Skip if UUID is set but doesn't match */ + if (params->uuid && bt_uuid_cmp(&gattr->uuid.uuid, params->uuid)) { + continue; + } + } else if (rsp->type == BT_GATT_DISCOVER_DESCRIPTOR) { + const struct nble_gattc_descriptor *gattr = + (void *)&data[i * sizeof(*gattr)]; + + attr = (&(struct bt_gatt_attr) + BT_GATT_DESCRIPTOR(&gattr->uuid.uuid, 0, NULL, NULL, NULL)); + attr->handle = gattr->handle; + last_handle = gattr->handle; + } else { + /* Error case */ + goto complete; + } + status = params->func(conn, attr, params); + if (status == BT_GATT_ITER_STOP) { + /* Not required to call complete */ + goto done; + } + } + if (last_handle < UINT16_MAX) { + last_handle++; + } + BT_DBG("disc_rsp: l=%d", last_handle); + params->start_handle = last_handle; + if (params->start_handle < params->end_handle) { + if (!bt_gatt_discover(conn, params)) + goto not_done; + } + +complete: + /* Indicate that there are no more attributes found */ + params->func(conn, NULL, params); + +done: + BT_DBG("disc_rsp: done"); + +not_done: + bt_conn_unref(conn); +} + +int bt_gatt_discover(struct bt_conn *conn, + struct bt_gatt_discover_params *params) +{ + struct nble_discover_params discover_params; + + if (!conn || !params || !params->func || !params->start_handle || + !params->end_handle || params->start_handle > params->end_handle) { + return -EINVAL; + } + + if (conn->state != BT_CONN_CONNECTED) { + return -EINVAL; + } + + BT_DBG("disc: %d", params->start_handle); + + memset(&discover_params, 0, sizeof(discover_params)); + + switch (params->type) { + case BT_GATT_DISCOVER_PRIMARY: + case BT_GATT_DISCOVER_CHARACTERISTIC: + if (params->uuid) { + /* Always copy a full 128 bit UUID */ + discover_params.uuid = *BT_UUID_128(params->uuid); + discover_params.flags = DISCOVER_FLAGS_UUID_PRESENT; + } + break; + + case BT_GATT_DISCOVER_INCLUDE: + case BT_GATT_DISCOVER_DESCRIPTOR: + break; + default: + return -EINVAL; + } + + discover_params.conn_handle = conn->handle; + discover_params.type = params->type; + discover_params.handle_range.start_handle = params->start_handle; + discover_params.handle_range.end_handle = params->end_handle; + + discover_params.user_data = params; + + nble_gattc_discover_req(&discover_params); + + return 0; +} + +void on_nble_gattc_read_multiple_rsp(const struct ble_gattc_read_rsp *rsp, + uint8_t *pdu, uint8_t length) +{ + struct bt_gatt_read_params *params; + struct bt_conn *conn = bt_conn_lookup_handle(rsp->conn_handle); + + BT_ASSERT(conn); + + params = rsp->user_data; + + BT_DBG("err 0x%02x", rsp->status); + + if (rsp->status) { + params->func(conn, rsp->status, params, NULL, 0); + bt_conn_unref(conn); + return; + } + + params->func(conn, 0, params, pdu, length); + + /* mark read as complete since read multiple is single response */ + params->func(conn, 0, params, NULL, 0); + + bt_conn_unref(conn); +} + +void on_nble_gattc_read_rsp(const struct ble_gattc_read_rsp *rsp, + uint8_t *pdu, uint8_t length) +{ + struct bt_gatt_read_params *params; + struct bt_conn *conn = bt_conn_lookup_handle(rsp->conn_handle); + + BT_ASSERT(conn); + + params = rsp->user_data; + + if (rsp->status) { + params->func(conn, rsp->status, params, NULL, 0); + bt_conn_unref(conn); + return; + } + + if (params->func(conn, 0, params, pdu, length) == BT_GATT_ITER_STOP) { + bt_conn_unref(conn); + return; + } + + /* + * Core Spec 4.2, Vol. 3, Part G, 4.8.1 + * If the Characteristic Value is greater than (ATT_MTU – 1) octets + * in length, the Read Long Characteristic Value procedure may be used + * if the rest of the Characteristic Value is required. + */ + if (length < BLE_GATT_MTU_SIZE - 1) { + params->func(conn, 0, params, NULL, 0); + bt_conn_unref(conn); + return; + } + + params->single.offset += length; + + /* Continue reading the attribute */ + if (bt_gatt_read(conn, params)) { + params->func(conn, BT_ATT_ERR_UNLIKELY, params, NULL, 0); + } + bt_conn_unref(conn); +} + +int bt_gatt_read(struct bt_conn *conn, struct bt_gatt_read_params *params) +{ + + struct ble_gattc_read_params single_req; + struct ble_gattc_read_multiple_params mutiple_req; + + if (!conn || conn->state != BT_CONN_CONNECTED || !params || + params->handle_count == 0 || !params->func) { + return -EINVAL; + } + + single_req.conn_handle = conn->handle; + + if (1 == params->handle_count) { + single_req.handle = params->single.handle; + single_req.offset = params->single.offset; + single_req.user_data = params; + + nble_gattc_read_req(&single_req); + } else { + mutiple_req.conn_handle = conn->handle; + mutiple_req.user_data = params; + + nble_gattc_read_multiple_req(&mutiple_req, params->handles, 2 * params->handle_count); + } + return 0; +} + +static void on_write_no_rsp_complete(struct bt_conn *conn, uint8_t err, + const void *data) +{ +} + +static void on_write_complete(struct bt_conn *conn, uint8_t err, + const struct bt_gatt_write_params *wr_params) +{ + bt_gatt_write_rsp_func_t func = wr_params->user_data[0]; + const void *data = wr_params->user_data[1]; + + BT_ASSERT(func); + func(conn, err, data); +} + +static int _bt_gatt_write(struct bt_conn *conn, uint16_t handle, bool with_resp, + uint16_t offset, const void *data, uint16_t length, + struct bt_gatt_write_params *wr_params) +{ + struct ble_gattc_write_params req; + + req.conn_handle = conn->handle; + req.handle = handle; + req.offset = offset; + req.with_resp = with_resp; + req.wr_params = *wr_params; + + nble_gattc_write_req(&req, data, length); + + return 0; +} + +void on_nble_gattc_write_rsp(const struct ble_gattc_write_rsp *rsp) +{ + + struct bt_conn *conn = bt_conn_lookup_handle(rsp->conn_handle); + + BT_ASSERT(conn); + + if (rsp->wr_params.func) { + rsp->wr_params.func(conn, rsp->status, &rsp->wr_params); + } + + bt_conn_unref(conn); +} + + +int bt_gatt_write_without_response(struct bt_conn *conn, uint16_t handle, + const void *data, uint16_t length, bool sign) +{ + return bt_gatt_write(conn, handle, 0, data, length, + on_write_no_rsp_complete); +} + +int bt_gatt_write(struct bt_conn *conn, uint16_t handle, uint16_t offset, + const void *data, uint16_t length, + bt_gatt_write_rsp_func_t func) +{ + struct bt_gatt_write_params wr_params; + + if (!conn || conn->state != BT_CONN_CONNECTED || !handle || !func) { + return -EINVAL; + } + + wr_params.func = on_write_complete; + wr_params.user_data[0] = func; + wr_params.user_data[1] = (void *)data; + + return _bt_gatt_write(conn, handle, + (func == on_write_no_rsp_complete) + ? false : true, + offset, data, length, &wr_params); +} + +static void gatt_subscription_add(struct bt_conn *conn, + struct bt_gatt_subscribe_params *params) +{ + bt_addr_le_copy(¶ms->_peer, &conn->le.dst); + + /* Prepend subscription */ + params->_next = subscriptions; + subscriptions = params; +} + +static void att_write_ccc_rsp(struct bt_conn *conn, uint8_t err, + const struct bt_gatt_write_params *wr_params) +{ + struct bt_gatt_subscribe_params *params = wr_params->user_data[0]; + + /* if write to CCC failed we remove subscription and notify app */ + if (err) { + struct bt_gatt_subscribe_params *cur, *prev; + + for (cur = subscriptions, prev = NULL; cur; + prev = cur, cur = cur->_next) { + + if (cur == params) { + gatt_subscription_remove(conn, prev, params); + break; + } + } + } +} + +static int gatt_write_ccc(struct bt_conn *conn, uint16_t handle, uint16_t value, + bt_att_func_t func, + struct bt_gatt_subscribe_params *params) +{ + struct bt_gatt_write_params wr_params; + + wr_params.func = func; + wr_params.user_data[0] = params; + + BT_DBG("handle 0x%04x value 0x%04x", handle, value); + + return _bt_gatt_write(conn, handle, true, 0, &value, sizeof(value), + &wr_params); +} + +int bt_gatt_subscribe(struct bt_conn *conn, + struct bt_gatt_subscribe_params *params) +{ + struct bt_gatt_subscribe_params *tmp; + bool has_subscription = false; + + if (!conn || conn->state != BT_CONN_CONNECTED) { + return -ENOTCONN; + } + + if (!params || !params->notify || + !params->value || !params->ccc_handle) { + return -EINVAL; + } + + /* Lookup existing subscriptions */ + for (tmp = subscriptions; tmp; tmp = tmp->_next) { + /* Fail if entry already exists */ + if (tmp == params) { + return -EALREADY; + } + + /* Check if another subscription exists */ + if (!bt_addr_le_cmp(&tmp->_peer, &conn->le.dst) && + tmp->value_handle == params->value_handle && + tmp->value >= params->value) { + has_subscription = true; + } + } + + /* Skip write if already subscribed */ + if (!has_subscription) { + int err; + + err = gatt_write_ccc(conn, params->ccc_handle, params->value, + att_write_ccc_rsp, params); + if (err) { + return err; + } + } + + /* + * Add subscription before write complete as some implementation were + * reported to send notification before reply to CCC write. + */ + gatt_subscription_add(conn, params); + + return 0; +} + +int bt_gatt_unsubscribe(struct bt_conn *conn, + struct bt_gatt_subscribe_params *params) +{ + struct bt_gatt_subscribe_params *tmp; + bool has_subscription = false, found = false; + + if (!conn || conn->state != BT_CONN_CONNECTED) { + return -ENOTCONN; + } + + if (!params) { + return -EINVAL; + } + + /* Check head */ + if (subscriptions == params) { + subscriptions = params->_next; + found = true; + } + + /* Lookup existing subscriptions */ + for (tmp = subscriptions; tmp; tmp = tmp->_next) { + /* Remove subscription */ + if (tmp->_next == params) { + tmp->_next = params->_next; + found = true; + } + + /* Check if there still remains any other subscription */ + if (!bt_addr_le_cmp(&tmp->_peer, &conn->le.dst) && + tmp->value_handle == params->value_handle) { + has_subscription = true; + } + } + + if (!found) { + return -EINVAL; + } + + if (has_subscription) { + return 0; + } + + params->value = 0; + + return gatt_write_ccc(conn, params->ccc_handle, params->value, NULL, + NULL); +} + +static void add_subscriptions(struct bt_conn *conn) +{ + struct bt_gatt_subscribe_params *params, *prev; + + /* Lookup existing subscriptions */ + for (params = subscriptions, prev = NULL; params; + prev = params, params = params->_next) { + if (bt_addr_le_cmp(¶ms->_peer, &conn->le.dst)) { + continue; + } + + /* Force write to CCC to workaround devices that don't track + * it properly. + */ + gatt_write_ccc(conn, params->ccc_handle, params->value, + att_write_ccc_rsp, params); + } +} +#else + +void on_nble_gattc_discover_rsp(const struct nble_gattc_discover_rsp *rsp, + const uint8_t *data, uint8_t data_len) +{ + +} +void on_nble_gattc_write_rsp(const struct ble_gattc_write_rsp *rsp) +{ +} + +void on_nble_gattc_value_evt(const struct ble_gattc_value_evt *evt, + uint8_t *buf, uint8_t buflen) +{ +} + +void on_nble_gattc_read_rsp(const struct ble_gattc_read_rsp *rsp, + uint8_t *data, uint8_t data_len) +{ +} + +void on_nble_gattc_read_multiple_rsp(const struct ble_gattc_read_rsp *rsp, + uint8_t *data, uint8_t data_len) +{ +} + +#endif + +void bt_gatt_connected(struct bt_conn *conn) +{ + BT_DBG("conn %p", conn); + bt_gatt_foreach_attr(0x0001, 0xffff, connected_cb, conn); +#if defined(CONFIG_BLUETOOTH_GATT_CLIENT) + add_subscriptions(conn); +#endif /* CONFIG_BLUETOOTH_GATT_CLIENT */ +} + +void bt_gatt_disconnected(struct bt_conn *conn) +{ + BT_DBG("conn %p", conn); + bt_gatt_foreach_attr(0x0001, 0xffff, disconnected_cb, conn); + +#if defined(CONFIG_BLUETOOTH_GATT_CLIENT) + /* If bonded don't remove subscriptions */ + if (is_bonded(&conn->le.dst)) { + return; + } + + remove_subscribtions(conn); +#endif /* CONFIG_BLUETOOTH_GATT_CLIENT */ +} diff --git a/system/libarc32_arduino101/framework/src/services/ble/hci_core.h b/system/libarc32_arduino101/framework/src/services/ble/hci_core.h new file mode 100644 index 00000000..dc7374b0 --- /dev/null +++ b/system/libarc32_arduino101/framework/src/services/ble/hci_core.h @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2016 Intel Corporation + * + * 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. + */ + +/* State tracking for the local Bluetooth controller */ +struct bt_dev { + atomic_t flags[1]; +}; +extern struct bt_dev bt_dev; + +#if defined(CONFIG_BLUETOOTH_SMP) || defined(CONFIG_BLUETOOTH_BREDR) +extern const struct bt_conn_auth_cb *bt_auth; +#endif /* CONFIG_BLUETOOTH_SMP || CONFIG_BLUETOOTH_BREDR */ + +static inline bool bt_addr_le_is_rpa(const bt_addr_le_t *addr) +{ + if (addr->type != BT_ADDR_LE_RANDOM) + return false; + + if ((addr->val[5] & 0xc0) == 0x40) + return true; + + return false; +} + +static inline bool bt_addr_le_is_identity(const bt_addr_le_t *addr) +{ + if (addr->type == BT_ADDR_LE_PUBLIC) + return true; + + /* Check for Random Static address type */ + if ((addr->val[5] & 0xc0) == 0xc0) + return true; + + return false; +} + +static inline bool bt_le_conn_params_valid(uint16_t min, uint16_t max, + uint16_t latency, uint16_t timeout) +{ + if (min > max || min < 6 || max > 3200) { + return false; + } + + /* Limits according to BT Core spec 4.2 [Vol 2, Part E, 7.8.12] */ + if (timeout < 10 || timeout > 3200) { + return false; + } + + /* Limits according to BT Core spec 4.2 [Vol 6, Part B, 4.5.1] */ + if (latency > 499 || ((latency + 1) * max) > (timeout * 4)) { + return false; + } + + return true; +} + + diff --git a/system/libarc32_arduino101/framework/src/services/ble/l2cap.c b/system/libarc32_arduino101/framework/src/services/ble/l2cap.c new file mode 100644 index 00000000..488cfd0e --- /dev/null +++ b/system/libarc32_arduino101/framework/src/services/ble/l2cap.c @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2016 Intel Corporation + * + * 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 +#include + +#include + +#include "conn_internal.h" +#include "gatt_internal.h" +#include "smp.h" + +/* #define BT_GATT_DEBUG 1 */ + +extern void on_nble_curie_log(char *fmt, ...); +extern void __assert_fail(void); +#ifdef BT_GATT_DEBUG +#define BT_DBG(fmt, ...) on_nble_curie_log(fmt, ##__VA_ARGS__) +#define BT_ERR(fmt, ...) on_nble_curie_log(fmt, ##__VA_ARGS__) +#define BT_WARN(fmt, ...) on_nble_curie_log(fmt, ##__VA_ARGS__) +#define BT_INFO(fmt, ...) on_nble_curie_log(fmt, ##__VA_ARGS__) +#define BT_ASSERT(cond) ((cond) ? (void)0 : __assert_fail()) +#else +#define BT_DBG(fmt, ...) do {} while (0) +#define BT_ERR(fmt, ...) on_nble_curie_log(fmt, ##__VA_ARGS__) +#define BT_WARN(fmt, ...) on_nble_curie_log(fmt, ##__VA_ARGS__) +#define BT_INFO(fmt, ...) on_nble_curie_log(fmt, ##__VA_ARGS__) +#define BT_ASSERT(cond) ((cond) ? (void)0 : __assert_fail()) +#endif + +void bt_l2cap_connected(struct bt_conn *conn) +{ + /* TODO Add support for fixed channels on BR/EDR transport */ + if (conn->type != BT_CONN_TYPE_LE) { + return; + } +#if defined(CONFIG_BLUETOOTH_SMP) + bt_smp_connected(conn); +#endif + bt_gatt_connected(conn); +} + +void bt_l2cap_disconnected(struct bt_conn *conn) +{ +#if defined(CONFIG_BLUETOOTH_SMP) + bt_smp_disconnected(conn); +#endif + bt_gatt_disconnected(conn); +} diff --git a/system/libarc32_arduino101/framework/src/services/ble/l2cap_internal.h b/system/libarc32_arduino101/framework/src/services/ble/l2cap_internal.h new file mode 100644 index 00000000..2f593fa5 --- /dev/null +++ b/system/libarc32_arduino101/framework/src/services/ble/l2cap_internal.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2016 Intel Corporation + * + * 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 L2CAP_INTERNAL_H_ +#define L2CAP_INTERNAL_H_ + +/* Notify L2CAP channels of a new connection */ +void bt_l2cap_connected(struct bt_conn *conn); + +/* Notify L2CAP channels of a disconnect event */ +void bt_l2cap_disconnected(struct bt_conn *conn); + + +#endif /* L2CAP_INTERNAL_H_ */ diff --git a/system/libarc32_arduino101/framework/src/services/ble/smp.h b/system/libarc32_arduino101/framework/src/services/ble/smp.h new file mode 100644 index 00000000..4f52c002 --- /dev/null +++ b/system/libarc32_arduino101/framework/src/services/ble/smp.h @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2016 Intel Corporation + * + * 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. + */ + +#define BT_SMP_ERR_PASSKEY_ENTRY_FAILED 0x01 +#define BT_SMP_ERR_OOB_NOT_AVAIL 0x02 +#define BT_SMP_ERR_AUTH_REQUIREMENTS 0x03 +#define BT_SMP_ERR_CONFIRM_FAILED 0x04 +#define BT_SMP_ERR_PAIRING_NOTSUPP 0x05 +#define BT_SMP_ERR_ENC_KEY_SIZE 0x06 +#define BT_SMP_ERR_CMD_NOTSUPP 0x07 +#define BT_SMP_ERR_UNSPECIFIED 0x08 +#define BT_SMP_ERR_REPEATED_ATTEMPTS 0x09 +#define BT_SMP_ERR_INVALID_PARAMS 0x0a +#define BT_SMP_ERR_DHKEY_CHECK_FAILED 0x0b +#define BT_SMP_ERR_NUMERIC_COMP_FAILED 0x0c +#define BT_SMP_ERR_BREDR_PAIRING_IN_PROGRESS 0x0d +#define BT_SMP_ERR_CROSS_TRANSP_NOT_ALLOWED 0x0e + +#define BT_SMP_IO_DISPLAY_ONLY 0x00 +#define BT_SMP_IO_DISPLAY_YESNO 0x01 +#define BT_SMP_IO_KEYBOARD_ONLY 0x02 +#define BT_SMP_IO_NO_INPUT_OUTPUT 0x03 +#define BT_SMP_IO_KEYBOARD_DISPLAY 0x04 + +#define BT_SMP_OOB_NOT_PRESENT 0x00 +#define BT_SMP_OOB_PRESENT 0x01 + +#define BT_SMP_MIN_ENC_KEY_SIZE 7 +#define BT_SMP_MAX_ENC_KEY_SIZE 16 + +#define BT_SMP_DIST_ENC_KEY 0x01 +#define BT_SMP_DIST_ID_KEY 0x02 +#define BT_SMP_DIST_SIGN 0x04 +#define BT_SMP_DIST_LINK_KEY 0x08 + +#define BT_SMP_DIST_MASK 0x0f + +#define BT_SMP_AUTH_NONE 0x00 +#define BT_SMP_AUTH_BONDING 0x01 +#define BT_SMP_AUTH_MITM 0x04 +#define BT_SMP_AUTH_SC 0x08 + +#if 0 +bool bt_smp_irk_matches(const uint8_t irk[16], const bt_addr_t *addr); +#endif +int bt_smp_send_pairing_req(struct bt_conn *conn); +int bt_smp_send_security_req(struct bt_conn *conn); +#if 0 +void bt_smp_update_keys(struct bt_conn *conn); +bool bt_smp_get_tk(struct bt_conn *conn, uint8_t *tk); + +void bt_smp_dhkey_ready(const uint8_t *dhkey); +void bt_smp_pkey_ready(void); +#endif + +int bt_smp_init(void); + +int bt_smp_auth_passkey_entry(struct bt_conn *conn, unsigned int passkey); +int bt_smp_auth_passkey_confirm(struct bt_conn *conn, bool match); +int bt_smp_auth_cancel(struct bt_conn *conn); + +int bt_smp_remove_info(const bt_addr_le_t *addr); + +#ifdef CONFIG_BLUETOOTH_SMP +void bt_smp_connected(struct bt_conn *conn); +void bt_smp_disconnected(struct bt_conn *conn); +#endif + +#if 0 +/** brief Verify signed message + * + * @param conn Bluetooth connection + * @param buf received packet buffer with message and signature + * + * @return 0 in success, error code otherwise + */ +int bt_smp_sign_verify(struct bt_conn *conn, struct net_buf *buf); + +/** brief Sign message + * + * @param conn Bluetooth connection + * @param buf message buffer + * + * @return 0 in success, error code otherwise + */ +int bt_smp_sign(struct bt_conn *conn, struct net_buf *buf); +#endif diff --git a/system/libarc32_arduino101/framework/src/services/ble/smp_null.c b/system/libarc32_arduino101/framework/src/services/ble/smp_null.c new file mode 100644 index 00000000..cdc3a4d5 --- /dev/null +++ b/system/libarc32_arduino101/framework/src/services/ble/smp_null.c @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2016 Intel Corporation + * + * 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 + +#include +#include +#include + +#include "smp.h" + +/* nble internal APIs */ +#include "gap_internal.h" + +/* #define BT_GATT_DEBUG 1 */ + +extern void on_nble_curie_log(char *fmt, ...); +extern void __assert_fail(void); +#ifdef BT_GATT_DEBUG +#define BT_DBG(fmt, ...) on_nble_curie_log(fmt, ##__VA_ARGS__) +#define BT_ERR(fmt, ...) on_nble_curie_log(fmt, ##__VA_ARGS__) +#define BT_WARN(fmt, ...) on_nble_curie_log(fmt, ##__VA_ARGS__) +#define BT_INFO(fmt, ...) on_nble_curie_log(fmt, ##__VA_ARGS__) +#define BT_ASSERT(cond) ((cond) ? (void)0 : __assert_fail()) +#else +#define BT_DBG(fmt, ...) do {} while (0) +#define BT_ERR(fmt, ...) on_nble_curie_log(fmt, ##__VA_ARGS__) +#define BT_WARN(fmt, ...) on_nble_curie_log(fmt, ##__VA_ARGS__) +#define BT_INFO(fmt, ...) on_nble_curie_log(fmt, ##__VA_ARGS__) +#define BT_ASSERT(cond) ((cond) ? (void)0 : __assert_fail()) +#endif + +/** + * Compile time IO capabilities and OOB support settings for nble. + * + * This compile options must match the application registered callbacks + * (bt_conn_auth_cb_register) + */ +#define NBLE_SMP_IO_CAPS BT_SMP_IO_NO_INPUT_OUTPUT +#define NBLE_SMP_AUTH_OPTIONS 0 +#define NBLE_SMP_OBB_PRESENT BT_SMP_OOB_NOT_PRESENT + +#if NOT_USED_FOR_NOW +int bt_smp_sign_verify(struct bt_conn *conn, struct net_buf *buf) +{ + return -ENOTSUP; +} + +int bt_smp_sign(struct bt_conn *conn, struct net_buf *buf) +{ + return -ENOTSUP; +} +#endif + +void on_nble_gap_sm_bond_info_rsp(const struct nble_gap_sm_bond_info_rsp *rsp, + const bt_addr_le_t *peer_addr, uint16_t len) +{ + /* stub */ +} + +void on_nble_gap_sm_passkey_req_evt(const struct nble_gap_sm_passkey_req_evt * p_evt) +{ + /* stub */ +} + +void on_nble_gap_sm_passkey_display_evt( + const struct nble_gap_sm_passkey_disp_evt *p_evt) +{ + /* stub */ +} + +void on_nble_gap_sm_status_evt(const struct nble_gap_sm_status_evt *evt) +{ + /* stub */ + BT_INFO("nble_gap_sm_status_evt: %d, gap_status: %d", + evt->evt_type, evt->status); +} + +int bt_smp_init(void) +{ + struct nble_gap_sm_config_params params = { + .options = NBLE_SMP_AUTH_OPTIONS, + .io_caps = NBLE_SMP_IO_CAPS, + .key_size = BT_SMP_MAX_ENC_KEY_SIZE, + .oob_present = NBLE_SMP_OBB_PRESENT, + }; + + nble_gap_sm_config_req(¶ms); + + return 0; +} + +void on_nble_gap_sm_config_rsp(struct nble_gap_sm_config_rsp *p_params) +{ + if (p_params->status) { + BT_ERR("sm_config failed: %d", p_params->status); + } +} + +void on_nble_gap_sm_common_rsp(const struct nble_gap_sm_response *rsp) +{ + if (rsp->status) { + BT_WARN("gap sm request failed: %d", rsp->status); + } +} diff --git a/system/libarc32_arduino101/framework/src/services/ble/uuid.c b/system/libarc32_arduino101/framework/src/services/ble/uuid.c new file mode 100644 index 00000000..dbacfd94 --- /dev/null +++ b/system/libarc32_arduino101/framework/src/services/ble/uuid.c @@ -0,0 +1,135 @@ +/* uuid.c - Bluetooth UUID handling */ + +/* + * Copyright (c) 2015 Intel Corporation + * + * 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 +//#include +#include +#include +#include +#include +#include + +#include + +#if defined(CONFIG_BLUETOOTH_DEBUG) +#include +#endif /* CONFIG_BLUETOOTH_DEBUG */ + +#define UUID_16_BASE_OFFSET 12 + +/* TODO: Decide whether to continue using BLE format or switch to RFC 4122 */ + +/* Base UUID : 0000[0000]-0000-1000-8000-00805F9B34FB -> + * { 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80, + * 0x00, 0x10, 0x00, 0x00, [0x00, 0x00], 0x00, 0x00 } + * 0x2800 : 0000[2800]-0000-1000-8000-00805F9B34FB -> + * { 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80, + * 0x00, 0x10, 0x00, 0x00, [0x00, 0x28], 0x00, 0x00 } + * little endian 0x2800 : [00 28] -> no swapping required + * big endian 0x2800 : [28 00] -> swapping required + */ +static const struct bt_uuid_128 uuid128_base = { + .uuid.type = BT_UUID_TYPE_128, + .val = { 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, +}; + +static inline void u16_to_uuid128(void *dst, uint16_t u16) +{ +#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + u16 = bswap_16(u16); +#endif + memcpy(dst, &u16, 2); +} + +static void uuid_to_uuid128(const struct bt_uuid *src, struct bt_uuid_128 *dst) +{ + switch (src->type) { + case BT_UUID_TYPE_16: + *dst = uuid128_base; + u16_to_uuid128(&dst->val[UUID_16_BASE_OFFSET], + BT_UUID_16(src)->val); + return; + case BT_UUID_TYPE_128: + memcpy(dst, src, sizeof(*dst)); + return; + } +} + +static int uuid128_cmp(const struct bt_uuid *u1, const struct bt_uuid *u2) +{ + struct bt_uuid_128 uuid1, uuid2; + + uuid_to_uuid128(u1, &uuid1); + uuid_to_uuid128(u2, &uuid2); + + return memcmp(uuid1.val, uuid2.val, 16); +} + +int bt_uuid_cmp(const struct bt_uuid *u1, const struct bt_uuid *u2) +{ + /* Convert to 128 bit if types don't match */ + if (u1->type != u2->type) + return uuid128_cmp(u1, u2); + + switch (u1->type) { + case BT_UUID_TYPE_16: + return (int)BT_UUID_16(u1)->val - (int)BT_UUID_16(u2)->val; + case BT_UUID_TYPE_128: + return memcmp(BT_UUID_128(u1)->val, BT_UUID_128(u2)->val, 16); + } + + return -EINVAL; +} + +#if defined(CONFIG_BLUETOOTH_DEBUG) +void bt_uuid_to_str(const struct bt_uuid *uuid, char *str, size_t len) +{ + uint32_t tmp1, tmp5; + uint16_t tmp0, tmp2, tmp3, tmp4; + + switch (uuid->type) { + case BT_UUID_TYPE_16: + snprintf(str, len, "%.4x", BT_UUID_16(uuid)->val); + break; + case BT_UUID_TYPE_128: + memcpy(&tmp0, &BT_UUID_128(uuid)->val[0], sizeof(tmp0)); + memcpy(&tmp1, &BT_UUID_128(uuid)->val[2], sizeof(tmp1)); + memcpy(&tmp2, &BT_UUID_128(uuid)->val[6], sizeof(tmp2)); + memcpy(&tmp3, &BT_UUID_128(uuid)->val[8], sizeof(tmp3)); + memcpy(&tmp4, &BT_UUID_128(uuid)->val[10], sizeof(tmp4)); + memcpy(&tmp5, &BT_UUID_128(uuid)->val[12], sizeof(tmp5)); + + snprintf(str, len, "%.8x-%.4x-%.4x-%.4x-%.8x%.4x", + tmp5, tmp4, tmp3, tmp2, tmp1, tmp0); + break; + default: + memset(str, 0, len); + return; + } +} + +const char *bt_uuid_str(const struct bt_uuid *uuid) +{ + static char str[37]; + + bt_uuid_to_str(uuid, str, sizeof(str)); + + return str; +} +#endif /* CONFIG_BLUETOOTH_DEBUG */ diff --git a/system/libarc32_arduino101/framework/include/services/ble/ble_service_msg.h b/system/libarc32_arduino101/framework/src/services/ble_service/ble_protocol.h similarity index 70% rename from system/libarc32_arduino101/framework/include/services/ble/ble_service_msg.h rename to system/libarc32_arduino101/framework/src/services/ble_service/ble_protocol.h index 6893731a..51109f9d 100644 --- a/system/libarc32_arduino101/framework/include/services/ble/ble_service_msg.h +++ b/system/libarc32_arduino101/framework/src/services/ble_service/ble_protocol.h @@ -28,23 +28,30 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#ifndef __BLE_SERVICE_MSG_H__ -#define __BLE_SERVICE_MSG_H__ +#ifndef __BLE_PROTOCOL_H__ +#define __BLE_PROTOCOL_H__ -#include "services/services_ids.h" - -/* - * CFW Message ID base definitions for BLE services. +/** + * @defgroup ble_protocol BLE protocol definitions + * + * BT Spec definitions. + * @ingroup ble_service + * @{ + * + * Bluetooth SIG defined macros and enum extracted from Bluetooth Spec 4.2 */ +#define BLE_MAX_DEVICE_NAME 20 /**< Max BLE device name length 20 + NULL, spec size: 248 */ +#define BLE_MAX_ADV_SIZE 31 + +#define BLE_GATT_MTU_SIZE 23 /**< Default MTU size */ + +/** Manufacturer IDs */ +#define INTEL_MANUFACTURER 0x0002 -/* BLE Service Message ID definitions. */ -#define MSG_ID_BLE_BASE BLE_SERVICE_MSG_BASE -#define MSG_ID_BLE_RSP (BLE_SERVICE_MSG_BASE + 0x40) -#define MSG_ID_BLE_EVT (BLE_SERVICE_MSG_BASE + 0x80) +/* HCI status (error) codes as per BT spec */ +#define HCI_REMOTE_DEV_TERMINATION_DUE_TO_POWER_OFF 0x15 +#define HCI_LOCAL_HOST_TERMINATED_CONNECTION 0x16 -/* BLE Core Service Message ID base (GAP/GATT) */ -#define MSG_ID_BLE_GAP_BASE BLE_SERVICE_GAP_MSG_BASE -#define MSG_ID_BLE_GAP_RSP (BLE_SERVICE_GAP_MSG_BASE + 0x40) -#define MSG_ID_BLE_GAP_EVT (BLE_SERVICE_GAP_MSG_BASE + 0x80) +/** @} */ #endif diff --git a/system/libarc32_arduino101/framework/src/services/ble_service/ble_service.c b/system/libarc32_arduino101/framework/src/services/ble_service/ble_service.c new file mode 100644 index 00000000..405c984a --- /dev/null +++ b/system/libarc32_arduino101/framework/src/services/ble_service/ble_service.c @@ -0,0 +1,297 @@ +/* + * Copyright (c) 2015, Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "ble_service.h" +#include "os/os.h" + +//#include "util/assert.h" +#include +//#include +#include "cfw/cfw_service.h" +#include "ble_protocol.h" +#include "ble_service_int.h" +#include "ble_service_internal.h" +#include "infra/log.h" + +#include +#include +#include +#include +#include "gap_internal.h" + +#include "nble_driver.h" + +#include "rpc.h" + +#include "util/misc.h" + +struct _ble_service_cb _ble_cb = { 0 }; +volatile uint8_t ble_inited = false; + + +static void ble_client_connected(conn_handle_t *instance); +static void ble_client_disconnected(conn_handle_t *instance); + +#if defined(CONFIG_BLUETOOTH_SMP) +static const struct bt_conn_auth_cb auth_callbacks; +#endif + +static service_t ble_service = { + .service_id = BLE_SERVICE_ID, + .client_connected = ble_client_connected, + .client_disconnected = ble_client_disconnected, +}; + +static void ble_is_not_enabled_rsp(struct cfw_message *msg, int status) +{ + struct ble_enable_rsp *resp = + (struct ble_enable_rsp *)cfw_alloc_rsp_msg(msg, + /* translate msg from req to rsp */ + (CFW_MESSAGE_ID(msg) ^ MSG_ID_BLE_SERVICE_BASE) + | MSG_ID_BLE_SERVICE_RSP, + sizeof(*resp)); + resp->status = status; + cfw_send_message(resp); +} + +#ifdef CONFIG_TCMD_BLE_DEBUG +static void handle_msg_id_ble_dbg(struct cfw_message *msg) +{ + struct nble_debug_params params; + struct ble_dbg_req_rsp *resp = (void *) + cfw_alloc_rsp_msg(msg, MSG_ID_BLE_DBG_RSP, sizeof(*resp)); + struct ble_dbg_req_rsp *req = (struct ble_dbg_req_rsp *) msg; + + params.u0 = req->u0; + params.u1 = req->u1; + + nble_gap_dbg_req(¶ms, resp); +} +#endif /* CONFIG_TCMD_BLE_DEBUG */ + +void on_nble_gap_dbg_rsp(const struct nble_debug_resp *params) +{ +#ifdef CONFIG_TCMD_BLE_DEBUG + struct ble_dbg_req_rsp *resp = params->user_data; + if (!resp) + return; + resp->u0 = params->u0; + resp->u1 = params->u1; + cfw_send_message(resp); +#endif /* CONFIG_TCMD_BLE_DEBUG */ +} + + +static void handle_msg_id_ble_rpc_callin(struct message *msg, void *priv) +{ + struct ble_rpc_callin *rpc = container_of(msg, struct ble_rpc_callin, msg); + /* handle incoming message */ + rpc_deserialize(rpc->p_data, rpc->len); + bfree(rpc->p_data); + message_free(msg); +} + +static void ble_set_bda_cb(int status, void *user_data) +{ + struct ble_enable_req *req = user_data; + + if (!req) + return; + + struct ble_enable_rsp *resp = (void *)cfw_alloc_rsp_msg(&req->header, + MSG_ID_BLE_ENABLE_RSP, sizeof(*resp)); + resp->status = status; + + if (status == 0) { + resp->enable = 1; + + nble_gap_read_bda_req(resp); + } else { + /* error case */ + resp->enable = 0; + cfw_send_message(resp); + } + bfree(req); +} + + +void on_nble_gap_read_bda_rsp(const struct nble_service_read_bda_response *params) +{ + struct cfw_message *rsp = params->user_data; + + if (rsp) { + struct ble_enable_rsp *r = container_of(rsp, struct ble_enable_rsp, header); + r->bd_addr = params->bd; + cfw_send_message(rsp); + } +} + +static void handle_ble_enable(struct ble_enable_req *req, + struct _ble_service_cb *p_cb) +{ + pr_info(LOG_MODULE_BLE, "ble_enable: state %d", p_cb->ble_state); + + p_cb->ble_state = BLE_ST_ENABLED; + + if (req->bda_present) { + struct nble_set_bda_params params; + + params.cb = ble_set_bda_cb; + params.user_data = req; + params.bda = req->bda; + + nble_set_bda_req(¶ms); + } else { + ble_set_bda_cb(0, req); + } +} + +void on_nble_set_bda_rsp(const struct nble_set_bda_rsp *params) +{ + if (params->cb) { + params->cb(params->status, params->user_data); + } +} + +static void handle_ble_disable(struct ble_enable_req *req, struct _ble_service_cb *p_cb) +{ + struct ble_enable_rsp *resp; + + pr_debug(LOG_MODULE_BLE, "ble_disable"); + p_cb->ble_state = BLE_ST_DISABLED; + + bt_le_adv_stop(); + + resp = (void *)cfw_alloc_rsp_msg(&req->header, + MSG_ID_BLE_ENABLE_RSP, + sizeof(*resp)); + cfw_send_message(resp); + +} + +static void ble_service_message_handler(struct cfw_message *msg, void *param) +{ + bool free_msg = true; + struct _ble_service_cb *p_cb = param; + uint16_t msg_id = CFW_MESSAGE_ID(msg); + + if (p_cb->ble_state < BLE_ST_ENABLED && + msg_id != MSG_ID_BLE_ENABLE_REQ) { + ble_is_not_enabled_rsp(msg, -ENODEV); + goto out; + } + + switch (msg_id) { + case MSG_ID_BLE_ENABLE_REQ: { + struct ble_enable_req *req = + container_of(msg, struct ble_enable_req, header); + if (p_cb->ble_state) { + if (req->enable) { + handle_ble_enable(req, p_cb); + free_msg = false; + } else + handle_ble_disable(req, p_cb); + } else { + pr_debug(LOG_MODULE_BLE, "ble_hdl_msg: core service not opened!"); + /* core service is not yet up */ + struct ble_enable_rsp *resp = (void *)cfw_alloc_rsp_msg(msg, + MSG_ID_BLE_ENABLE_RSP, sizeof(*resp)); + resp->status = -EINPROGRESS; + resp->enable = 0; + cfw_send_message(resp); + } + } + break; +#ifdef CONFIG_TCMD_BLE_DEBUG + case MSG_ID_BLE_DBG_REQ: + handle_msg_id_ble_dbg(msg); + break; +#endif + default: + pr_warning(LOG_MODULE_BLE, "unsupported %d", msg_id); + break; + } +out: + if (free_msg) + cfw_msg_free(msg); +} + +static void ble_client_connected(conn_handle_t *instance) +{ + if (_ble_cb.ble_state == BLE_ST_NOT_READY) + pr_warning(LOG_MODULE_BLE, "BLE_CORE service is not registered"); +} + +static void ble_client_disconnected(conn_handle_t *instance) +{ +} + +void ble_bt_rdy(int err) +{ + _ble_cb.ble_state = BLE_ST_DISABLED; + ble_inited = true; + + /* register BLE service */ + if (cfw_register_service(_ble_cb.queue, &ble_service, + ble_service_message_handler, &_ble_cb) == -1) { + panic(0xb1eb1e); + } +} + +void ble_cfw_service_init(int service_id, T_QUEUE queue) +{ + _ble_cb.queue = queue; + _ble_cb.ble_state = BLE_ST_NOT_READY; + +#ifdef CONFIG_IPC_UART_NS16550 + nble_driver_configure(queue, handle_msg_id_ble_rpc_callin); +#endif + + ble_inited = false; + + bt_enable(ble_bt_rdy); + do{} + while (ble_inited == false); +} + +void nble_log(const struct nble_log_s *param, char *buf, uint8_t buflen) +{ + pr_info(LOG_MODULE_BLE, buf, param->param0, param->param1, param->param2, param->param3); +} + +void on_nble_common_rsp(const struct nble_response *params) +{ + struct ble_rsp *resp = params->user_data; + + if (!resp) + return; + resp->status = params->status; + cfw_send_message(resp); +} diff --git a/system/libarc32_arduino101/framework/src/services/ble_service/ble_service_api.c b/system/libarc32_arduino101/framework/src/services/ble_service/ble_service_api.c new file mode 100644 index 00000000..e70b15c8 --- /dev/null +++ b/system/libarc32_arduino101/framework/src/services/ble_service/ble_service_api.c @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2015, Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "ble_service.h" + +#include +#include +//#include +//#include "util/assert.h" + +#include "ble_service_int.h" +#include "ble_service_internal.h" +#include "cfw/cfw_service.h" +#include "cfw/cfw_client.h" + +#include +#include + +#include "ble_protocol.h" +#include "ble_service_utils.h" + +int ble_service_enable(cfw_service_conn_t * p_service_conn, uint8_t enable, + const struct ble_enable_config * p_config, + void *p_priv) +{ + struct ble_enable_req * msg = + (void *) cfw_alloc_message_for_service(p_service_conn, + MSG_ID_BLE_ENABLE_REQ, + sizeof(*msg), p_priv); + msg->central_conn_params = p_config->central_conn_params; + msg->enable = enable; + + if (p_config->p_bda) { + msg->bda_present = 1; + msg->bda = *p_config->p_bda; + } + + return cfw_send_message(msg); +} diff --git a/system/libarc32_arduino101/framework/src/services/ble_service/ble_service_int.h b/system/libarc32_arduino101/framework/src/services/ble_service/ble_service_int.h new file mode 100644 index 00000000..857270c7 --- /dev/null +++ b/system/libarc32_arduino101/framework/src/services/ble_service/ble_service_int.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2015, Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef BLE_SERVICE_INT_H_ +#define BLE_SERVICE_INT_H_ + +#include + +/* For cfw_service_conn_t, cfw_client_t, T_QUEUE */ +#include "cfw/cfw.h" + +/* Forward declarations */ +struct ble_init_svc_req; +struct ble_init_svc_rsp; +struct bt_conn_cb; +struct bt_gatt_attr; + +enum BLE_STATE { + BLE_ST_NOT_READY = 0, + BLE_ST_DISABLED, + BLE_ST_ENABLED, + BLE_ST_DTM +}; + +struct _ble_service_cb { + T_QUEUE queue; /* Queue for the messages */ + uint8_t ble_state; +}; + +extern struct _ble_service_cb _ble_cb; + +/** Send advertisement timeout event to application */ +void ble_gap_advertisement_timeout(void); + +#ifdef CONFIG_BLE_CORE_TEST +void test_ble_service_init(void); +T_QUEUE get_service_queue(void); +#endif + +#endif /* BLE_SERVICE_INT_H_ */ diff --git a/system/libarc32_arduino101/framework/src/services/ble_service/ble_service_internal.h b/system/libarc32_arduino101/framework/src/services/ble_service/ble_service_internal.h new file mode 100644 index 00000000..013043a5 --- /dev/null +++ b/system/libarc32_arduino101/framework/src/services/ble_service/ble_service_internal.h @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2016, Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __BLE_SERVICE_INTERNAL_H__ +#define __BLE_SERVICE_INTERNAL_H__ + +// For MSG_ID_BLE_SERVICE_BASE +#include "services/services_ids.h" + +/* BLE High level Message IDs used for request, response, events. */ +enum BLE_MSG_ID_REQ { + MSG_ID_BLE_ENABLE_REQ = MSG_ID_BLE_SERVICE_BASE, /* Message ID for enable request */ + MSG_ID_BLE_SET_NAME_REQ, /* Message ID for set name request */ + MSG_ID_BLE_START_SCAN_REQ, /* Message ID for start scan request */ + MSG_ID_BLE_STOP_SCAN_REQ, /* Message ID for stop scan request */ + MSG_ID_BLE_INIT_SVC_REQ, /* Message ID for init service request */ + + /* BLE debug command */ + MSG_ID_BLE_DBG_REQ, /* Message ID for BLE debug command request */ + + MSG_ID_BLE_REQ_LAST, +}; + +/* Parameters of MSG_ID_BLE_ENABLE_REQ. */ +struct ble_enable_req { + struct cfw_message header; /* Component framework message header, MUST be first element of structure */ + struct bt_le_conn_param central_conn_params; + uint8_t enable; + uint8_t bda_present; + bt_addr_le_t bda; +}; + +struct ble_disconnect_req { + struct cfw_message header; /* Component framework message header, MUST be first element of structure */ + struct bt_conn *conn; /* Connection reference */ + uint8_t reason; /* Reason of the disconnect*/ +}; + +struct ble_connect_req { + struct cfw_message header; /* Component framework message header, MUST be first element of structure */ + struct bt_le_conn_param conn_params; + bt_addr_le_t bd_addr; +}; + +struct ble_init_svc_req { + struct cfw_message header; /* Component framework message header, MUST be first element of structure */ + int (*init_svc)(struct ble_init_svc_req *msg, struct _ble_service_cb *p_cb); + void (*init_svc_complete)(struct ble_init_svc_req *req); + uint8_t status; +}; + +#endif /* __BLE_SERVICE_INTERNAL_H__ */ diff --git a/system/libarc32_arduino101/framework/src/services/ble/ble_service_utils.c b/system/libarc32_arduino101/framework/src/services/ble_service/ble_service_utils.c similarity index 50% rename from system/libarc32_arduino101/framework/src/services/ble/ble_service_utils.c rename to system/libarc32_arduino101/framework/src/services/ble_service/ble_service_utils.c index d40c1b72..0275e79b 100644 --- a/system/libarc32_arduino101/framework/src/services/ble/ble_service_utils.c +++ b/system/libarc32_arduino101/framework/src/services/ble_service/ble_service_utils.c @@ -31,77 +31,48 @@ #include #include "os/os.h" #include "ble_protocol.h" -#include "services/ble/ble_service_gap_api.h" +#include "ble_service.h" +#include "ble_service_int.h" #include "ble_service_utils.h" -uint8_t ble_sizeof_bt_uuid(const struct bt_uuid * p_uuid) +void uint8_to_ascii(uint8_t in, uint8_t *p) { - return p_uuid->type + 1; + uint8_t hi = (in & 0xF0) >> 4; + uint8_t lo = in & 0x0F; + + if (hi < 0x0A) + *p = '0' + hi; + else + *p = 'A' + (hi - 0x0A); + + p++; + + if (lo < 10) + *p = '0' + lo; + else + *p = 'A' + (lo - 0x0A); } -uint8_t * ble_encode_bt_uuid(const struct bt_uuid * p_uuid, uint8_t * p_data) +void uint8buf_to_ascii(uint8_t * dst, const uint8_t * src, int len) { - // start with the type (length) - UINT8_TO_LESTREAM(p_data, p_uuid->type); - switch (p_uuid->type) { - case BT_UUID16: - UINT16_TO_LESTREAM(p_data, p_uuid->uuid16); - break; - case BT_UUID32: - UINT32_TO_LESTREAM(p_data, p_uuid->uuid32); - break; - case BT_UUID128: - memcpy(p_data, p_uuid->uuid128, MAX_UUID_SIZE); - p_data += MAX_UUID_SIZE; - break; + int i; + for (i = 0; i < len; ++i) { + uint8_to_ascii(src[i], dst); + dst += 2; } - return p_data; } -uint8_t ble_cpy_bt_uuid(uint8_t * p_uuid_dst, - const struct bt_uuid * p_uuid_src, - uint8_t type) +size_t adv_data_len(const struct bt_data *ad, size_t count) { - uint8_t *p = p_uuid_dst; - uint8_t res_type = (p_uuid_src->type >= type) ? type : 0; + int i; + size_t data_len = 0; - switch (res_type) { - case BT_UUID16: - switch (p_uuid_src->type) { - case BT_UUID16: - UINT16_TO_LESTREAM(p, p_uuid_src->uuid16); - break; - case BT_UUID32: - UINT16_TO_LESTREAM(p, p_uuid_src->uuid16); - break; - case BT_UUID128: { - uint16_t uuid16; - p = (uint8_t *)&p_uuid_src->uuid128[BLE_BASE_UUID_OCTET_OFFSET]; - LESTREAM_TO_UINT16(p, uuid16); - p = p_uuid_dst; - UINT16_TO_LESTREAM(p, p_uuid_src->uuid16); - break; - } - } - break; - case BT_UUID32: - switch (p_uuid_src->type) { - case BT_UUID32: - UINT32_TO_LESTREAM(p, p_uuid_src->uuid32); - break; - case BT_UUID128: { - uint32_t uuid32; - p = (uint8_t *)&p_uuid_src->uuid128[BLE_BASE_UUID_OCTET_OFFSET]; - LESTREAM_TO_UINT32(p, uuid32); - p = p_uuid_dst; - UINT32_TO_LESTREAM(p, uuid32); - break; - } - } - break; - case BT_UUID128: - memcpy(p_uuid_dst, p_uuid_src->uuid128, MAX_UUID_SIZE); - break; + if (ad == NULL) + return 0; + + for (i = 0; i < count ; i++) { + data_len += ad[i].data_len; } - return res_type; + + return data_len; } diff --git a/system/libarc32_arduino101/framework/src/services/ble/ble_service_utils.h b/system/libarc32_arduino101/framework/src/services/ble_service/ble_service_utils.h similarity index 66% rename from system/libarc32_arduino101/framework/src/services/ble/ble_service_utils.h rename to system/libarc32_arduino101/framework/src/services/ble_service/ble_service_utils.h index a51f8dcd..8d5d9378 100644 --- a/system/libarc32_arduino101/framework/src/services/ble/ble_service_utils.h +++ b/system/libarc32_arduino101/framework/src/services/ble_service/ble_service_utils.h @@ -28,20 +28,19 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#ifndef __BLE_SERVICE_UTILS_H__ -#define __BLE_SERVICE_UTILS_H__ +#ifndef BLE_SERVICE_UTILS_H_ +#define BLE_SERVICE_UTILS_H_ -#include "services/ble/ble_service_gap_api.h" -#include "services/ble/ble_service_gatt.h" -//#include "ble_service_int.h" +#include -#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) + __must_be_array(a) +// For HAVE_SAME_TYPE +#include "compiler.h" #define IS_BIG_ENDIAN (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) #define UINT8_TO_LESTREAM(p, i) \ do { *(p)++ = (uint8_t)(i); } \ - while (sizeof(char[1 - 2 * !(__builtin_types_compatible_p(__typeof__(p), uint8_t *))]) - 1) + while (sizeof(char[1 - 2 * !(HAVE_SAME_TYPE(p, uint8_t *))]) - 1) #define UINT16_TO_LESTREAM(p, i) UINT8_TO_LESTREAM(p, i); UINT8_TO_LESTREAM(p, (i)>>8) #define UINT32_TO_LESTREAM(p, i) UINT16_TO_LESTREAM(p, i); UINT16_TO_LESTREAM(p, (i)>>16) @@ -59,8 +58,8 @@ #define LESTREAM_TO_UINT8(p, i) \ do { i = *p; p++; } \ - while (sizeof(char[1 - 2 * !(__builtin_types_compatible_p(__typeof__(p), const uint8_t *) || \ - __builtin_types_compatible_p(__typeof__(p), uint8_t *))]) - 1) + while (sizeof(char[1 - 2 * !(HAVE_SAME_TYPE(p, const uint8_t *) || \ + HAVE_SAME_TYPE(p, uint8_t *))]) - 1) #define LESTREAM_TO_UINT16(p, i) \ do { uint16_t temp16; LESTREAM_TO_UINT8(p, i); LESTREAM_TO_UINT8(p, temp16); i |= (temp16 << 8); } \ while (0) @@ -90,53 +89,38 @@ #define BESTREAM_TO_INT32(p, i) \ do {uint32_t __i; BESTREAM_TO_UINT32(p, __i); i = (int32_t)__i; } while (0) -#define between(a, b, c) (((a) >= (b)) || ((a) <= (c))) - -#define strict_between(a, b, c) (((a) > (b)) || ((a) < (c))) - /** * BLE helper functions. */ -#define BLE_BASE_UUID_OCTET_OFFSET 12 -/** - * Compute the size required to encode a UUID in a buffer +/**@brief Represent an unsigned 8 bit value in ASCII hexadecimal + * + * @param[in] in The value to represent + * @param[inout] p Pointer to the buffer to fill * - * @param p_uuid Pointer to the UUID + * @note The representation requires 2 bytes */ -uint8_t ble_sizeof_bt_uuid(const struct bt_uuid * p_uuid); +void uint8_to_ascii(uint8_t in, uint8_t * p); -/** - * Encode a UUID in a buffer +/** Converts buffer from hex to ascii. * - * @param p_uuid Pointer to the UUID to encode - * @param p_data Pointer to the buffer to store the encoded UUID + * @param dst buffer converted + * @param src buffer which is converted + * @param len length of src (dst shall be large enough) * - * @return The pointer to the buffer after the encoded UUID + * @return None */ -uint8_t * ble_encode_bt_uuid(const struct bt_uuid * p_uuid, uint8_t * p_data); +void uint8buf_to_ascii(uint8_t * dst, const uint8_t * src, int len); -/** Copy BT/BLE address and eventually reduce size. - * - * Copies a uuid from src to dst. type may modify the resulting uuid type. only - * going from bigger to small type is supported. typically 128 bits to 16 bits - * If it is different from src type, a transformation is applied: - * IN: BT_UUID128: dd97c415-fed9-4766-b18f-ba690d24a06a (stored in little endian) - * OUT: BT_UUID16: c415 - * OUT: BT_UUID32: dd97c415 - * or - * IN: BT_UUID32: dd97c415 - * OUT: BT_UUID16: c415 - * - * @param p_uuid_src source uuid - * @param[out] p_uuid_dst: destination to copy uuid to (excluding type). little endian - * @param type output type +struct bt_data; +/** + * Get advertisement data length. * - * \return size/type of copied uuid: BT_UUID16, BT_UUID32, BT_UUID128 or 0 for failure! + * @param ad advertisement data + * @param count array length + * @return length of advertisement data * */ -uint8_t ble_cpy_bt_uuid(uint8_t * p_uuid_dst, - const struct bt_uuid * p_uuid_src, - uint8_t type); +size_t adv_data_len(const struct bt_data *ad, size_t count); -#endif +#endif /* BLE_SERVICE_UTILS_H_ */ diff --git a/system/libarc32_arduino101/framework/src/services/ble_service/gap_internal.h b/system/libarc32_arduino101/framework/src/services/ble_service/gap_internal.h new file mode 100644 index 00000000..333ad36e --- /dev/null +++ b/system/libarc32_arduino101/framework/src/services/ble_service/gap_internal.h @@ -0,0 +1,629 @@ +/* + * Copyright (c) 2016 Intel Corporation + * + * 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 GAP_INTERNAL_H_ +#define GAP_INTERNAL_H_ + +#include +/* For bt_addr_le_t */ +#include +/* For bt_security_t */ +#include + +/* Directed advertisement timeout error after 1.28s */ +#define ERR_DIRECTED_ADVERTISING_TIMEOUT 0x3C + +enum NBLE_GAP_SM_PASSKEY_TYPE { + NBLE_GAP_SM_REJECT = 0, + NBLE_GAP_SM_PK_PASSKEY, + NBLE_GAP_SM_PK_OOB, +}; + +enum NBLE_GAP_SM_EVT { + NBLE_GAP_SM_EVT_START_PAIRING, + NBLE_GAP_SM_EVT_BONDING_COMPLETE, + NBLE_GAP_SM_EVT_LINK_ENCRYPTED, + NBLE_GAP_SM_EVT_LINK_SECURITY_CHANGE, +}; + +enum NBLE_GAP_RSSI_OPS { + NBLE_GAP_RSSI_DISABLE_REPORT = 0, + NBLE_GAP_RSSI_ENABLE_REPORT +}; + +enum NBLE_TEST_OPCODES { + NBLE_TEST_INIT_DTM = 0x01, + NBLE_TEST_START_DTM_RX = 0x1d, + NBLE_TEST_START_DTM_TX = 0x1e, + NBLE_TEST_END_DTM = 0x1f, + /* vendor specific commands start at 0x80 */ + /* Set Tx power. To be called before start of tx test */ + NBLE_TEST_SET_TXPOWER = 0x80, + NBLE_TEST_START_TX_CARRIER, +}; + +/* DTM commands, opcodes, indexes. */ +#define H4_CMD 0x01 +#define HCI_OGF_LE_CMD 0x20 + +#define DTM_HCI_STATUS_IDX 6 +#define DTM_HCI_LE_END_IDX (DTM_HCI_STATUS_IDX + 1) + + +struct nble_response { + int status; + void *user_data; +}; + +struct nble_gap_device_name { + /* Security mode for writing device name, @ref BLE_GAP_SEC_MODES */ + uint8_t sec_mode; + /* 0: no authorization, 1: authorization required */ + uint8_t authorization; + /* Device name length (0-248) */ + uint8_t len; + uint8_t name_array[20]; +}; + +struct nble_gap_connection_values { + /* Connection interval (unit 1.25 ms) */ + uint16_t interval; + /* Connection latency (unit interval) */ + uint16_t latency; + /* Connection supervision timeout (unit 10ms)*/ + uint16_t supervision_to; +}; + + +enum NBLE_GAP_SVC_ATTR_TYPE { + /* Device Name, UUID 0x2a00 */ + NBLE_GAP_SVC_ATTR_NAME = 0, + /* Appearance, UUID 0x2a01 */ + NBLE_GAP_SVC_ATTR_APPEARANCE, + /* Peripheral Preferred Connection Parameters (PPCP), UUID 0x2a04 */ + NBLE_GAP_SVC_ATTR_PPCP = 4, + /* Central Address Resolution (CAR), UUID 0x2aa6, BT 4.2 */ + NBLE_GAP_SVC_ATTR_CAR = 0xa6, +}; + +struct nble_gap_connection_params { + /* minimal connection interval: range 0x0006 to 0x0c80 (unit 1.25ms) */ + uint16_t interval_min; + /* maximum connection interval: range 0x0006 to 0x0c80 must be bigger then min! */ + uint16_t interval_max; + /* maximum connection slave latency: 0x0000 to 0x01f3 */ + uint16_t slave_latency; + /* link supervision timeout: 0x000a to 0x0c80 (unit 10ms) */ + uint16_t link_sup_to; +}; + +struct nble_gap_scan_parameters { + /* If 1, perform active scanning (scan requests). */ + uint8_t active; + /* If 1, ignore unknown devices (non whitelisted). */ + uint8_t selective; + /* Scan interval between 0x0004 and 0x4000 in 0.625ms units (2.5ms to 10.24s). */ + uint16_t interval; + /* Scan window between 0x0004 and 0x4000 in 0.625ms units (2.5ms to 10.24s). */ + uint16_t window; + /* Scan timeout between 0x0001 and 0xFFFF in seconds, 0x0000 disables timeout. */ + uint16_t timeout; +}; + +struct nble_gap_service_write_params { + /* GAP Characteristics attribute type @ref BLE_GAP_SVC_ATTR_TYPE */ + uint16_t attr_type; + union { + struct nble_gap_device_name name; + /* Appearance UUID */ + uint16_t appearance; + /* Preferred Peripheral Connection Parameters */ + struct nble_gap_connection_params conn_params; + /* Central Address Resolution support 0: no, 1: yes */ + uint8_t car; + }; +}; + +struct nble_service_read_bda_response { + int status; + /* If @ref status ok */ + bt_addr_le_t bd; + void *user_data; +}; + +struct nble_service_write_response { + int status; + /* GAP Characteristics attribute type @ref BLE_GAP_SVC_ATTR_TYPE */ + uint16_t attr_type; + void *user_data; +}; + +struct nble_gap_service_read_params { + /* Type of GAP data characteristic to read @ref BLE_GAP_SVC_ATTR_TYPE */ + uint16_t attr_type; +}; + +struct nble_debug_params { + uint32_t u0; + uint32_t u1; +}; + +struct nble_debug_resp { + int status; + uint32_t u0; + uint32_t u1; + void *user_data; +}; + +typedef void (*nble_set_bda_cb_t)(int status, void *user_data); + +struct nble_set_bda_params { + bt_addr_le_t bda; + nble_set_bda_cb_t cb; + void *user_data; +}; + +struct nble_set_bda_rsp { + nble_set_bda_cb_t cb; + void *user_data; + int status; +}; + +struct bt_eir_data { + uint8_t len; + uint8_t data[31]; +}; + +struct nble_gap_adv_params { + uint16_t timeout; + /* min interval 0xffff: use default 0x0800 */ + uint16_t interval_min; + /* max interval 0xffff: use default 0x0800 */ + uint16_t interval_max; + /* advertisement types @ref GAP_ADV_TYPES */ + uint8_t type; + /* filter policy to apply with white list */ + uint8_t filter_policy; + /* bd address of peer device in case of directed advertisement */ + bt_addr_le_t peer_bda; +}; + +struct nble_gap_ad_data_params { + /* Advertisement data, maybe 0 (length) */ + struct bt_eir_data ad; + /* Scan response data, maybe 0 (length) */ + struct bt_eir_data sd; +}; + +struct nble_log_s { + uint8_t param0; + uint8_t param1; + uint8_t param2; + uint8_t param3; +}; + +/* bt_dev flags: the flags defined here represent BT controller state */ +enum { + BT_DEV_READY, + + BT_DEV_ADVERTISING, + BT_DEV_KEEP_ADVERTISING, + BT_DEV_SCANNING, + BT_DEV_EXPLICIT_SCAN, + +#if defined(CONFIG_BLUETOOTH_BREDR) + BT_DEV_ISCAN, + BT_DEV_PSCAN, +#endif /* CONFIG_BLUETOOTH_BREDR */ +}; + +void nble_log(const struct nble_log_s *param, char *buf, uint8_t buflen); + +void on_nble_up(void); + +void nble_gap_service_write_req(const struct nble_gap_service_write_params *params); + +void on_nble_gap_read_bda_rsp(const struct nble_service_read_bda_response *params); + +void nble_gap_dbg_req(const struct nble_debug_params *params, void *user_data); + +void on_nble_gap_dbg_rsp(const struct nble_debug_resp *params); + +void on_nble_set_bda_rsp(const struct nble_set_bda_rsp *params); + +void nble_set_bda_req(const struct nble_set_bda_params *params); + +void nble_gap_set_adv_data_req(struct nble_gap_ad_data_params *ad_data_params); + +void nble_gap_set_adv_params_req(struct nble_gap_adv_params *adv_params); + +void nble_gap_start_adv_req(void); + +void on_nble_gap_start_advertise_rsp(const struct nble_response *params); + +void nble_gap_stop_adv_req(void *user_data); + +void nble_gap_read_bda_req(void *priv); + +struct nble_gap_irk_info { + /* Identity Resolving Key (IRK) */ + uint8_t irk[16]; +}; + +void on_nble_common_rsp(const struct nble_response *params); + +struct nble_gap_connect_update_params { + uint16_t conn_handle; + struct nble_gap_connection_params params; +}; + +void nble_gap_conn_update_req(const struct nble_gap_connect_update_params *params); + +void on_nble_gap_conn_update_rsp(const struct nble_response *params); + +struct nble_gap_connect_req_params { + bt_addr_le_t bda; + struct nble_gap_connection_params conn_params; + struct nble_gap_scan_parameters scan_params; +}; + +struct nble_gap_disconnect_req_params { + uint16_t conn_handle; + uint8_t reason; +}; + +void nble_gap_disconnect_req(const struct nble_gap_disconnect_req_params *params); + +struct nble_gap_sm_config_params { + /* Security options (@ref BLE_GAP_SM_OPTIONS) */ + uint8_t options; + /* I/O Capabilities to allow passkey exchange (@ref BLE_GAP_IO_CAPABILITIES) */ + uint8_t io_caps; + /* Maximum encryption key size (7-16) */ + uint8_t key_size; + uint8_t oob_present; +}; + +void nble_gap_sm_config_req(const struct nble_gap_sm_config_params *params); + +struct nble_gap_sm_config_rsp { + void *user_data; + int status; + bool sm_bond_dev_avail; +}; + +void on_nble_gap_sm_config_rsp(struct nble_gap_sm_config_rsp *params); + + +struct nble_gap_sm_pairing_params { + /* authentication level see @ref BLE_GAP_SM_OPTIONS */ + uint8_t auth_level; +}; + +struct nble_gap_sm_security_params { + struct bt_conn *conn; + uint16_t conn_handle; + /* Local authentication/bonding parameters */ + struct nble_gap_sm_pairing_params params; +}; + +void nble_gap_sm_security_req(const struct nble_gap_sm_security_params * + params); + +struct nble_gap_sm_passkey { + uint8_t type; + union { + uint32_t passkey; + uint8_t oob[16]; + uint8_t reason; + }; +}; + +struct nble_gap_sm_key_reply_req_params { + struct bt_conn *conn; + uint16_t conn_handle; + struct nble_gap_sm_passkey params; +}; + +void nble_gap_sm_passkey_reply_req(const struct nble_gap_sm_key_reply_req_params + *params); + +struct nble_gap_sm_clear_bond_req_params { + bt_addr_le_t addr; +}; + +void nble_gap_sm_clear_bonds_req(const struct nble_gap_sm_clear_bond_req_params + *params); + +struct nble_gap_sm_response { + int status; + struct bt_conn *conn; +}; + +void on_nble_gap_sm_common_rsp(const struct nble_gap_sm_response *rsp); + +/** + * Callback for rssi event. + */ +typedef void (*rssi_report_t)(const int8_t *rssi_data); + +/** + * Callback for rssi report response. + */ +typedef void (*rssi_report_resp_t)(int status); + +struct nble_rssi_report_params { + uint16_t conn_handle; + /* RSSI operation @ref NBLE_GAP_RSSI_OPS */ + uint8_t op; + /* Channel for RSSI enabling */ + uint8_t channel; + /* minimum RSSI dBm change to report a new RSSI value */ + uint8_t delta_dBm; + /* number of delta_dBm changes before sending a new RSSI report */ + uint8_t min_count; +}; + +void ble_gap_set_rssi_report(struct nble_rssi_report_params *params, + struct bt_conn *conn, + rssi_report_resp_t resp_cb, rssi_report_t evt_cb); + +void nble_gap_set_rssi_report_req(const struct nble_rssi_report_params *params, + void *user_data); + +void on_nble_gap_set_rssi_report_rsp(const struct nble_response *params); + +struct nble_gap_scan_params { + uint16_t interval; + uint16_t window; + uint8_t scan_type; + uint8_t use_whitelist; +}; + +void nble_gap_start_scan_req(const struct nble_gap_scan_params *params); + +void nble_gap_stop_scan_req(void); + +void on_nble_gap_scan_start_stop_rsp(const struct nble_response *rsp); + +void nble_gap_connect_req(const struct nble_gap_connect_req_params *params, + void *user_data); + +void on_nble_gap_connect_rsp(const struct nble_response *params); + +void nble_gap_cancel_connect_req(void *priv); + +void on_nble_gap_cancel_connect_rsp(const struct nble_response *params); + +enum BLE_GAP_SET_OPTIONS { + BLE_GAP_SET_CH_MAP = 0, +}; + +struct nble_gap_channel_map { + /* connection on which to change channel map */ + uint16_t conn_handle; + /* 37 bits are used of the 40 bits (LSB) */ + uint8_t map[5]; +}; + + +struct nble_gap_set_option_params { + /* Option to set @ref BLE_GAP_SET_OPTIONS */ + uint8_t op; + union { + struct nble_gap_channel_map ch_map; + }; +}; + +/* + * Generic request op codes. + * This allows to access some non connection related commands like DTM. + */ +enum BLE_GAP_GEN_OPS { + /* Not used now. */ + DUMMY_VALUE = 0, +}; + +struct nble_gap_gen_cmd_params { + /* @ref BLE_GAP_GEN_OPS */ + uint8_t op_code; +}; + +/* Temporary patch: RSSI processing for UAS */ +struct nble_uas_rssi_calibrate { + float distance; +}; +void nble_uas_rssi_calibrate_req(const struct nble_uas_rssi_calibrate *p_struct); + +/* Temporary patch: RSSI processing for UAS */ +struct nble_uas_bucket_change { + uint8_t distance; +}; +void on_nble_uas_bucket_change(const struct nble_uas_bucket_change *p_params); + +struct nble_version { + uint8_t version; + uint8_t major; + uint8_t minor; + uint8_t patch; + char version_string[20]; + uint8_t hash[4]; +}; + +typedef void (*ble_get_version_cb_t)(const struct nble_version *ver); + +struct nble_gap_get_version_param { + ble_get_version_cb_t cb; +}; + +struct nble_version_response { + struct nble_gap_get_version_param params; + struct nble_version ver; +}; + +void nble_get_version_req(const struct nble_gap_get_version_param *params); + +void on_nble_get_version_rsp(const struct nble_version_response *params); + +void nble_gap_dtm_init_req(void *user_data); + +void on_nble_gap_dtm_init_rsp(void *user_data); + +struct nble_gap_tx_power_params { + int8_t tx_power; +}; + +void nble_gap_tx_power_req(const struct nble_gap_tx_power_params *params); + +void on_nble_gap_tx_power_rsp(const struct nble_response *params); + +struct nble_gap_connect_evt { + uint16_t conn_handle; + struct nble_gap_connection_values conn_values; + /* 0 if connected as master, otherwise as slave */ + uint8_t role_slave; + /* Address of peer device */ + bt_addr_le_t peer_bda; +}; + +void on_nble_gap_connect_evt(const struct nble_gap_connect_evt *evt); + +struct nble_gap_disconnect_evt { + uint16_t conn_handle; + uint8_t hci_reason; +}; + +void on_nble_gap_disconnect_evt(const struct nble_gap_disconnect_evt *evt); + +struct nble_gap_conn_update_evt { + uint16_t conn_handle; + struct nble_gap_connection_values conn_values; +}; + +void on_nble_gap_conn_update_evt(const struct nble_gap_conn_update_evt *evt); + +struct nble_gap_adv_report_evt { + bt_addr_le_t addr; + int8_t rssi; + uint8_t adv_type; +}; + +void on_nble_gap_adv_report_evt(const struct nble_gap_adv_report_evt *evt, + const uint8_t *buf, uint8_t len); + +struct nble_gap_dir_adv_timeout_evt { + uint16_t conn_handle; + uint16_t error; +}; + +void on_nble_gap_dir_adv_timeout_evt(const struct nble_gap_dir_adv_timeout_evt *p_evt); + +#define BLE_GAP_RSSI_EVT_SIZE 32 +struct nble_gap_rssi_evt { + uint16_t conn_handle; + int8_t rssi_data[BLE_GAP_RSSI_EVT_SIZE]; +}; + +void on_nble_gap_rssi_evt(const struct nble_gap_rssi_evt *evt); + +struct nble_gap_timout_evt { + uint16_t conn_handle; + /* reason for timeout @ref BLE_SVC_GAP_TIMEOUT_REASON */ + int reason; +}; + +struct nble_gap_sm_passkey_req_evt { + uint16_t conn_handle; + uint8_t key_type; +}; + +void on_nble_gap_sm_passkey_req_evt(const struct nble_gap_sm_passkey_req_evt *evt); + +struct nble_gap_sm_passkey_disp_evt { + uint16_t conn_handle; + uint32_t passkey; +}; + +void on_nble_gap_sm_passkey_display_evt(const struct nble_gap_sm_passkey_disp_evt *evt); + +struct nble_link_sec { + bt_security_t sec_level; + uint8_t enc_size; +}; + +struct nble_gap_sm_status_evt { + uint16_t conn_handle; + uint8_t evt_type; + int status; + struct nble_link_sec enc_link_sec; +}; + +void on_nble_gap_sm_status_evt(const struct nble_gap_sm_status_evt *evt); + +void on_nble_set_bda_rsp(const struct nble_set_bda_rsp *params); + +enum BLE_INFO_REQ_TYPES { + BLE_INFO_BONDING = 1, /* Get bonding database related information */ + BLE_INFO_LAST /* Keep last */ +}; + +struct ble_gap_bonded_dev_info +{ + uint8_t addr_count; /* Count of le_addr in array. */ + uint8_t irk_count; /* IRK count */ + bt_addr_le_t le_addr[]; /* Bonded device address */ +}; + +struct ble_get_info_rsp { + int status; /* Response status */ + uint8_t info_type; /* Requested information type */ + struct ble_gap_bonded_dev_info info_params; +}; + +struct nble_gap_sm_bond_info; +typedef void (*ble_bond_info_cb_t)(const struct nble_gap_sm_bond_info *info, + const bt_addr_le_t *addr, uint16_t len, + void *user_data); + +struct nble_gap_sm_bond_info_param { + ble_bond_info_cb_t cb; + void *user_data; + bool include_bonded_addrs; +}; + +void nble_gap_sm_bond_info_req(const struct nble_gap_sm_bond_info_param *params); + +struct nble_gap_sm_bond_info { + int err; + uint8_t addr_count; + uint8_t irk_count; +}; + +struct nble_gap_sm_bond_info_rsp { + ble_bond_info_cb_t cb; + void *user_data; + struct nble_gap_sm_bond_info info; +}; + +void on_nble_gap_sm_bond_info_rsp(const struct nble_gap_sm_bond_info_rsp *rsp, + const bt_addr_le_t *peer_addr, uint16_t len); + +void ble_gap_get_bonding_info(ble_bond_info_cb_t func, void *user_data, + bool include_bonded_addrs); + +void ble_gap_get_version(ble_get_version_cb_t func); + +#endif /* GAP_INTERNAL_H_ */ diff --git a/system/libarc32_arduino101/framework/src/services/ble_service/gatt_internal.h b/system/libarc32_arduino101/framework/src/services/ble_service/gatt_internal.h new file mode 100644 index 00000000..25ac4da8 --- /dev/null +++ b/system/libarc32_arduino101/framework/src/services/ble_service/gatt_internal.h @@ -0,0 +1,308 @@ +/* + * Copyright (c) 2016 Intel Corporation + * + * 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 GATT_INTERNAL_H_ +#define GATT_INTERNAL_H_ + +#include +#include + +/* Forward declarations */ +struct nble_response; + +#define BLE_GATT_MTU_SIZE 23 + +/* + * Internal APIs used between host and BLE controller + * Typically they are required if gatt.h APIs can not be mapped 1:1 onto controller API + */ + +enum NBLE_GATT_IND_TYPES { + NBLE_GATT_IND_TYPE_NONE = 0, + NBLE_GATT_IND_TYPE_NOTIFICATION, + NBLE_GATT_IND_TYPE_INDICATION, +}; + +struct nble_gatt_register_req { + /* Base address of the attribute table in the Quark mem space */ + struct bt_gatt_attr *attr_base; + /* Number of of attributes in this service */ + uint8_t attr_count; +}; + +struct nble_gatt_register_rsp { + int status; + struct bt_gatt_attr *attr_base; + /* Number of attributes successfully added */ + uint8_t attr_count; +}; + +enum nble_gatt_wr_flag { + NBLE_GATT_WR_FLAG_REPLY = 1, + NBLE_GATT_WR_FLAG_PREP = 2, +}; + +struct nble_gatt_wr_evt { + struct bt_gatt_attr *attr; + uint16_t conn_handle; + uint16_t offset; + uint8_t flag; /* Cf. enum nble_gatt_wr_flag */ +}; + +struct nble_gatt_wr_exec_evt { + uint16_t conn_handle; + uint8_t flag; +}; + +struct nble_gatt_rd_evt { + struct bt_gatt_attr *attr; + uint16_t conn_handle; + uint16_t offset; +}; + +struct nble_gatts_rd_reply_params { + uint16_t conn_handle; + uint16_t offset; + int32_t status; +}; + +struct nble_gatts_wr_reply_params { + uint16_t conn_handle; + int32_t status; +}; + +struct nble_gatt_notif_ind_params { + const struct bt_gatt_attr *attr; + uint16_t offset; +}; + +struct nble_gatt_send_notif_params { + /* Function to be invoked when buffer is freed */ + bt_gatt_notify_sent_func_t cback; + uint16_t conn_handle; + struct nble_gatt_notif_ind_params params; +}; + +struct nble_gatt_notif_rsp { + bt_gatt_notify_sent_func_t cback; + int status; + uint16_t conn_handle; + struct bt_gatt_attr *attr; +}; + +struct nble_gatt_send_ind_params { + /* Function to be invoked when buffer is freed */ + bt_gatt_indicate_func_t cback; + uint16_t conn_handle; + struct nble_gatt_notif_ind_params params; +}; + +struct nble_gatt_ind_rsp { + bt_gatt_indicate_func_t cback; + int status; + uint16_t conn_handle; + struct bt_gatt_attr *attr; +}; + +struct nble_gatt_handle_range { + uint16_t start_handle; + uint16_t end_handle; +}; + +struct nble_gattc_primary { + uint16_t handle; + struct nble_gatt_handle_range range; + struct bt_uuid_128 uuid; +}; + +struct nble_gattc_included { + uint16_t handle; + struct nble_gatt_handle_range range; + struct bt_uuid_128 uuid; +}; + +struct nble_gattc_characteristic { + uint16_t handle; + uint8_t prop; + uint16_t value_handle; + struct bt_uuid_128 uuid; +}; + +struct nble_gattc_descriptor { + uint16_t handle; + struct bt_uuid_128 uuid; +}; + +struct nble_gattc_discover_rsp { + int32_t status; + void *user_data; + uint16_t conn_handle; + uint8_t type; +}; + +struct nble_gatts_attribute_rsp { + int32_t status; + struct bt_gatt_attr *attr; + void *user_data; +}; + +void nble_gatts_rd_reply_req(const struct nble_gatts_rd_reply_params *, uint8_t *, uint16_t); + +void nble_gatts_wr_reply_req(const struct nble_gatts_wr_reply_params *p_params); + +void nble_gatt_register_req(const struct nble_gatt_register_req *p_param, + uint8_t *p_buf, + uint16_t len); + +struct nble_gatt_attr_handles { + uint16_t handle; +}; + +void on_nble_gatt_register_rsp(const struct nble_gatt_register_rsp *p_param, + const struct nble_gatt_attr_handles *p_attrs, uint8_t len); + +void on_nble_gatts_write_evt(const struct nble_gatt_wr_evt *p_evt, + const uint8_t *p_buf, uint8_t buflen); + +void on_nble_gatts_write_exec_evt(const struct nble_gatt_wr_exec_evt *evt); + +void on_nble_gatts_read_evt(const struct nble_gatt_rd_evt *p_evt); + +void nble_gatt_send_notif_req(const struct nble_gatt_send_notif_params *p_params, + const uint8_t *p_value, uint16_t length); + +void nble_gatt_send_ind_req(const struct nble_gatt_send_ind_params *p_params, + const uint8_t *p_value, uint8_t length); + +void on_nble_gatts_send_notif_rsp(const struct nble_gatt_notif_rsp *rsp); + +void on_nble_gatts_send_ind_rsp(const struct nble_gatt_ind_rsp *rsp); + +#define DISCOVER_FLAGS_UUID_PRESENT 1 + +struct nble_discover_params { + void *user_data; + struct bt_uuid_128 uuid; + struct nble_gatt_handle_range handle_range; + uint16_t conn_handle; + uint8_t type; + uint8_t flags; +}; + +void nble_gattc_discover_req(const struct nble_discover_params *req); + +void on_nble_gattc_discover_rsp(const struct nble_gattc_discover_rsp *rsp, + const uint8_t *data, uint8_t data_len); + +/* + * GATT Attribute stream structure. + * + * This structure is a "compressed" copy of @ref bt_gatt_attr. + * UUID pointer and user_data pointer are used as offset into buffer itself. + * The offset is from the beginning of the buffer. therefore a value of 0 + * means that UUID or user_data is not present. + */ +struct ble_gatt_attr { + /* Attribute permissions */ + uint16_t perm; + /* Attribute variable data size */ + uint16_t data_size; + /* Attribute variable data: always starts with the UUID and data follows */ + uint8_t data[]; +}; + +struct ble_gattc_read_params { + void *user_data; + uint16_t conn_handle; + uint16_t handle; + uint16_t offset; +}; + +struct ble_gattc_read_multiple_params { + void *user_data; + uint16_t conn_handle; +}; + +struct ble_gattc_read_rsp { + int status; + void *user_data; + uint16_t conn_handle; + uint16_t handle; + uint16_t offset; +}; + +/* forward declaration */ +struct bt_gatt_write_params; + +typedef void (*bt_att_func_t)(struct bt_conn *conn, uint8_t err, + const struct bt_gatt_write_params *wr_params); + +struct bt_gatt_write_params { + /* Function invoked upon write response */ + bt_att_func_t func; + /* User specific data */ + void *user_data[2]; +}; + +struct ble_gattc_write_params { + uint16_t conn_handle; + uint16_t handle; + uint16_t offset; + /* different than 0 if response required */ + uint8_t with_resp; + struct bt_gatt_write_params wr_params; +}; + +struct ble_gattc_write_rsp { + uint16_t conn_handle; + int status; + uint16_t handle; + uint16_t len; + struct bt_gatt_write_params wr_params; +}; + +void nble_gattc_read_req(const struct ble_gattc_read_params *params); + +void on_nble_gattc_read_rsp(const struct ble_gattc_read_rsp *rsp, + uint8_t *data, uint8_t data_len); + +void nble_gattc_read_multiple_req( + const struct ble_gattc_read_multiple_params *params, + const uint16_t *data, uint16_t data_len); + +void on_nble_gattc_read_multiple_rsp(const struct ble_gattc_read_rsp *rsp, + uint8_t *data, uint8_t data_len); + +void nble_gattc_write_req(const struct ble_gattc_write_params *params, + const uint8_t *buf, uint8_t buflen); + +void on_nble_gattc_write_rsp(const struct ble_gattc_write_rsp *rsp); + +void bt_gatt_connected(struct bt_conn *conn); +void bt_gatt_disconnected(struct bt_conn *conn); + + +struct ble_gattc_value_evt { + uint16_t conn_handle; + int status; + uint16_t handle; + uint8_t type; +}; + +void on_nble_gattc_value_evt(const struct ble_gattc_value_evt *evt, + uint8_t *buf, uint8_t buflen); + +#endif /* GATT_INTERNAL_H_ */ diff --git a/system/libarc32_arduino101/framework/src/services/ble_service/nble_driver.c b/system/libarc32_arduino101/framework/src/services/ble_service/nble_driver.c new file mode 100644 index 00000000..4a128f13 --- /dev/null +++ b/system/libarc32_arduino101/framework/src/services/ble_service/nble_driver.c @@ -0,0 +1,354 @@ +/* + * Copyright (c) 2015, Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +#include "nble_driver.h" + +#include "portable.h" + +/* ipc/rpc uart interface */ +#include "os/os.h" +#include "infra/ipc_requests.h" +#include "infra/port.h" +#include "infra/log.h" +#include "drivers/soc_gpio.h" +#include "drivers/ipc_uart_ns16550.h" + +#include "platform.h" + +#include "rpc.h" + +#include "util/misc.h" + +#include "infra/time.h" + +#include "infra/ipc_uart.h" + + + +/* + * Macro definition for reset pin + * Curie and other board - Everything should be working out of the box + */ +#define BLE_SW_CLK_PIN 27 +#define BLE_SWDIO_PIN 6 +#define RESET_PIN BLE_SWDIO_PIN +#define QRK_BLE_INT 5 + +static uint16_t rpc_port_id; +static list_head_t m_rpc_tx_q; + +extern void on_nble_curie_log(char *fmt, ...) +{ + va_list args; + + va_start(args, fmt); + log_vprintk(LOG_LEVEL_INFO, LOG_MODULE_BLE, fmt, args); + va_end(args); +} + +/* + * When we set val to 1 it will wake up the remote (BLE Core), setting it to 0 + * will allow remote to sleep. + */ +static int nble_wake_assert(bool val) +{ + val = true; + uint8_t ret = soc_gpio_write(SOC_GPIO_32, QRK_BLE_INT, val); + + //pr_debug(LOG_MODULE_BLE, "BLE wake up: %d", val); + if (ret != DRV_RC_OK) { + pr_debug(LOG_MODULE_BLE, "Error setting QRK_BLE_INT %d", ret); + } + return ret; +} + +/** + * Function registered to be invoked when the IPC starts or ends + * a transmission session. + * + * This sets the wake state of ble core to either keep it awake at start of a tx + * or to allow sleep at the end of a TX. + * + * @param wake_state false if remote may sleep (end of transmission). + * true, wake remote to start a transmission session. + * @param ignored not used + */ +static void nble_ipc_tx_wake_cb(bool wake_state, void *ignored) +{ + nble_wake_assert(wake_state); +} + +static int nble_interface_init(void) +{ + DRIVER_API_RC ret = DRV_RC_OK; + /* setup IPC UART reference */ + ipc_uart_ns16550_set_tx_cb(nble_ipc_tx_wake_cb, NULL); + + /* Configure GPIO as output and high by default */ + gpio_cfg_data_t config; + config.gpio_type = GPIO_OUTPUT; + ret = soc_gpio_set_config(SOC_GPIO_32, QRK_BLE_INT, &config); + if (ret != DRV_RC_OK) + return -1; + + list_init(&m_rpc_tx_q); + + ret = nble_wake_assert(1); + return ret; +} + +void uart_ipc_disable(void) +{ + ipc_uart_ns16550_disable(SYNC_CHANNEL); +} + +static void *m_rpc_channel; + +struct rpc_tx_elt { + list_t l; + uint16_t length; + uint8_t data[0]; +}; + +/** + * Try to send a element of the RPC waiting list + * + * @param l Pointer to the list element to try to send on the UART + * @return + */ +static int uart_rpc_try_tx(list_t *l) +{ + struct rpc_tx_elt *p_elt; + + /* Retrieve the RPC TX element from the list pointer */ + p_elt = container_of(l, struct rpc_tx_elt, l); + + /* Try to send the element payload */ + return ipc_uart_ns16550_send_pdu(m_rpc_channel, + p_elt->length, + p_elt->data); +} + +/** + * Try to send an RPC TX queue element during the free operation + * of the previous message. This is invoked under interrupt context + * and therefore does not require protection. It is also expected + * that the tx operation can not fail. + */ +static void uart_rpc_try_tx_on_free(void) +{ + list_t *l; + int ret; + + /* Get next element in tx q */ + l = list_get(&m_rpc_tx_q); + if (l) { + ret = uart_rpc_try_tx(l); + + /* It is not possible to fail when called on free event */ + assert(ret == IPC_UART_ERROR_OK); + } +} + +/** + * Try to send an RPC TX queue element after enqueuing an element to the + * RPC TX queue. At this point the state of the UART driver is not known + * and there could be a transmission in progress, so the procedure is to + * protect from interruption, pick (not get) the first element and only + * get it out of the queue if the tx operation was successful. + */ +static void uart_rpc_try_tx_on_add(void) +{ + list_t *l; + int ret; + + int flags = interrupt_lock(); + + /* Pick next element in tx q */ + l = m_rpc_tx_q.head; + if (l) { + ret = uart_rpc_try_tx(l); + + /* If it was sent correctly, remove it from the queue */ + if (ret == IPC_UART_ERROR_OK) { + l = list_get(&m_rpc_tx_q); + } + } + + interrupt_unlock(flags); +} + +/** + * Function handling the events from the UART IPC (irq). + * + * @param channel Channel on which the event applies + * @param request IPC_MSG_TYPE_MESSAGE when a new message was received, + * IPC_MSG_TYPE_FREE when the previous message was sent and can be freed. + * @param len Length of the data + * @param p_data Pointer to the data + * @return 0 + */ +static int uart_ipc_rpc_cback(int channel, int request, int len, void *p_data) +{ + switch (request) { + case IPC_MSG_TYPE_MESSAGE: { +#ifdef CONFIG_RPC_IN + /* if BLE service is available, handle it in BLE service context */ + struct ble_rpc_callin *rpc = (void *) message_alloc( + sizeof(*rpc), NULL); +if (NULL == rpc) +{ + panic(-1); +} + MESSAGE_ID(&rpc->msg) = 0; + MESSAGE_LEN(&rpc->msg) = sizeof(*rpc); + MESSAGE_SRC(&rpc->msg) = rpc_port_id; + MESSAGE_DST(&rpc->msg) = rpc_port_id; + MESSAGE_TYPE(&rpc->msg) = TYPE_INT; + rpc->p_data = p_data; + rpc->len = len; + if (port_send_message(&rpc->msg) != E_OS_OK) + panic(-1); +#endif + } + break; + case IPC_MSG_TYPE_FREE: + { + /* Free the message */ + struct rpc_tx_elt *p_elt; + + p_elt = container_of(p_data, struct rpc_tx_elt, data); + bfree(p_elt); + + //pr_debug(LOG_MODULE_IPC, "%s:%p", __FUNCTION__, p_elt); + + /* Try to send another message immediately */ + uart_rpc_try_tx_on_free(); + break; + } + default: + /* Free the message */ + bfree(p_data); + pr_error(LOG_MODULE_BLE, "Unsupported RPC request"); + break; + } + return 0; +} + +uint8_t *rpc_alloc_cb(uint16_t length) +{ + struct rpc_tx_elt *p_elt; + + //pr_info(0, "%s", __FUNCTION__); + + p_elt = balloc(length + offsetof(struct rpc_tx_elt, data), NULL); + //pr_debug(LOG_MODULE_IPC, "%s:%p", __FUNCTION__, p_elt); + assert(p_elt != NULL); + + /* Save the length of the buffer */ + p_elt->length = length; + + return p_elt->data; +} + +/* called under NON-interrupt context */ +void rpc_transmit_cb(uint8_t *p_buf, uint16_t length) +{ + struct rpc_tx_elt *p_elt; + + p_elt = container_of(p_buf, struct rpc_tx_elt, data); + + list_add(&m_rpc_tx_q, &p_elt->l); + + uart_rpc_try_tx_on_add(); +} + +/* nble reset is achieved by asserting low the SWDIO pin. + * However, the BLE Core chip can be in SWD debug mode, and NRF_POWER->RESET = 0 due to, + * other constraints: therefore, this reset might not work everytime, especially after + * flashing or debugging. + */ +void nble_driver_init(void) +{ + uint32_t delay_until; + + nble_interface_init(); + /* Setup UART0 for BLE communication, HW flow control required */ + SET_PIN_MODE(18, QRK_PMUX_SEL_MODEA); /* UART0_RXD */ + SET_PIN_MODE(19, QRK_PMUX_SEL_MODEA); /* UART0_TXD */ + SET_PIN_MODE(40, QRK_PMUX_SEL_MODEB); /* UART0_CTS_B */ + SET_PIN_MODE(41, QRK_PMUX_SEL_MODEB); /* UART0_RTS_B */ + + ipc_uart_init(0); + + //while (1) + //{} + /* RESET_PIN depends on the board and the local configuration: check top of file */ + gpio_cfg_data_t pin_cfg = { .gpio_type = GPIO_OUTPUT }; + + soc_gpio_set_config(SOC_GPIO_32, RESET_PIN, &pin_cfg); + //soc_gpio_set_config(SOC_GPIO_32_ID, BLE_SW_CLK_PIN, &pin_cfg); + /* Reset hold time is 0.2us (normal) or 100us (SWD debug) */ + soc_gpio_write(SOC_GPIO_32, RESET_PIN, 0); + /* Wait for ~1ms */ + delay_until = get_uptime_32k() + 32768; + + /* Open the UART channel for RPC while Nordic is in reset */ + m_rpc_channel = ipc_uart_channel_open(RPC_CHANNEL, uart_ipc_rpc_cback); + + while (get_uptime_32k() < delay_until); + + /* De-assert the reset */ + soc_gpio_write(SOC_GPIO_32, RESET_PIN, 1); + + + /* Set back GPIO to input to avoid interfering with external debugger */ + pin_cfg.gpio_type = GPIO_INPUT; + soc_gpio_set_config(SOC_GPIO_32, RESET_PIN, &pin_cfg); +} + + +void nble_driver_configure(T_QUEUE queue, void (*handler)(struct message*, void*)) +{ + rpc_port_id = port_alloc(queue); + assert(rpc_port_id != 0); + port_set_handler(rpc_port_id, handler, NULL); + pr_debug(LOG_MODULE_BLE, "%s: done port: %d", __func__, rpc_port_id); +} + + +void on_nble_curie_init(void) +{ + nble_driver_init(); +} + + diff --git a/system/libarc32_arduino101/framework/src/services/ble_service/nble_driver.h b/system/libarc32_arduino101/framework/src/services/ble_service/nble_driver.h new file mode 100644 index 00000000..7ea15b44 --- /dev/null +++ b/system/libarc32_arduino101/framework/src/services/ble_service/nble_driver.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2015, Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef NBLE_DRIVER_H_ +#define NBLE_DRIVER_H_ + +#include "os/os.h" +#include "infra/message.h" + +struct ble_rpc_callin { + struct message msg; /**< Message header, MUST be first element of structure */ + uint8_t *p_data; /**< RPC buffer, must be freed after deserializing */ + uint16_t len; /**< length of above buffer */ +}; + +/** + * This resets and initializes the uart/ipc mechanism of nble. + * + * This this will trigger the call to @ref on_nble_up indicating that rpc + * mechanism is up and running. + */ +void nble_driver_init(void); + +void nble_driver_configure(T_QUEUE queue, void (*handler)(struct message*, void*)); + +void uart_ipc_disable(void); + +#endif /* NBLE_DRIVER_H_ */ diff --git a/variants/arduino_101/libarc32drv_arduino101.a b/variants/arduino_101/libarc32drv_arduino101.a index 8b179a83..d7c4acca 100644 Binary files a/variants/arduino_101/libarc32drv_arduino101.a and b/variants/arduino_101/libarc32drv_arduino101.a differ diff --git a/variants/arduino_101/pins_arduino.h b/variants/arduino_101/pins_arduino.h index 631c35cc..e447277c 100644 --- a/variants/arduino_101/pins_arduino.h +++ b/variants/arduino_101/pins_arduino.h @@ -25,7 +25,7 @@ #ifndef Pins_Arduino_h #define Pins_Arduino_h -#define NUM_DIGITAL_PINS 22 +#define NUM_DIGITAL_PINS 29 #define NUM_ANALOG_INPUTS 6 #define NUM_PWM 4 #define NUM_UARTS 1 diff --git a/variants/arduino_101/variant.cpp b/variants/arduino_101/variant.cpp index 0fe85c2d..c20dc4c3 100644 --- a/variants/arduino_101/variant.cpp +++ b/variants/arduino_101/variant.cpp @@ -22,6 +22,11 @@ #include "cfw_platform.h" #include "platform.h" +// Add for debug corelib +#ifdef CONFIGURE_DEBUG_CORELIB_ENABLED +#include +#endif + /* * Arduino 101 @@ -82,9 +87,15 @@ PinDescription g_APinDescription[]= { 5, SS_GPIO_8B0, SS_GPIO, SS_GPIO_8B0_BASE_ADDR, 13, GPIO_MUX_MODE, INVALID, INVALID, 13, INPUT_MODE }, // Arduino IO17 { 6, SS_GPIO_8B0, SS_GPIO, SS_GPIO_8B0_BASE_ADDR, 14, GPIO_MUX_MODE, INVALID, INVALID, 14, INPUT_MODE }, // Arduino IO18 { 1, SS_GPIO_8B0, SS_GPIO, SS_GPIO_8B0_BASE_ADDR, 9, GPIO_MUX_MODE, INVALID, INVALID, 9, INPUT_MODE }, // Arduino IO19 - { 0, SS_GPIO_8B0, SS_GPIO, SS_GPIO_8B0_BASE_ADDR, 8, GPIO_MUX_MODE, INVALID, INVALID, INVALID, INPUT_MODE }, // Arduino IO20 - { 24, SOC_GPIO_32, SOC_GPIO, SOC_GPIO_BASE_ADDR, 58, GPIO_MUX_MODE, INVALID, INVALID, INVALID, INPUT_MODE }, // Arduino IO21 - + { 0, SS_GPIO_8B0, SS_GPIO, SS_GPIO_8B0_BASE_ADDR, 8, GPIO_MUX_MODE, INVALID, INVALID, INVALID, INPUT_MODE }, // Arduino IO20 + { 24, SOC_GPIO_32, SOC_GPIO, SOC_GPIO_BASE_ADDR, 58, GPIO_MUX_MODE, INVALID, INVALID, INVALID, INPUT_MODE }, // Arduino IO21 + { 12, SOC_GPIO_32, SOC_GPIO, SOC_GPIO_BASE_ADDR, 46, GPIO_MUX_MODE, INVALID, INVALID, INVALID, INPUT_MODE }, // Arduino IO22 + { 13, SOC_GPIO_32, SOC_GPIO, SOC_GPIO_BASE_ADDR, 47, GPIO_MUX_MODE, INVALID, INVALID, INVALID, INPUT_MODE }, // Arduino IO23 + { 14, SOC_GPIO_32, SOC_GPIO, SOC_GPIO_BASE_ADDR, 48, GPIO_MUX_MODE, INVALID, INVALID, INVALID, INPUT_MODE }, // Arduino IO24 + { 26, SOC_GPIO_32, SOC_GPIO, SOC_GPIO_BASE_ADDR, 60, GPIO_MUX_MODE, INVALID, INVALID, INVALID, INPUT_MODE }, // Arduino IO25 + { 1, SOC_GPIO_32, SOC_GPIO, SOC_GPIO_AON_BASE_ADDR, 1, GPIO_MUX_MODE, INVALID, INVALID, INVALID, INPUT_MODE }, // Arduino IO26 + { 2, SOC_GPIO_32, SOC_GPIO, SOC_GPIO_AON_BASE_ADDR, 2, GPIO_MUX_MODE, INVALID, INVALID, INVALID, INPUT_MODE }, // Arduino IO27 + { 3, SOC_GPIO_32, SOC_GPIO, SOC_GPIO_AON_BASE_ADDR, 3, GPIO_MUX_MODE, INVALID, INVALID, INVALID, INPUT_MODE }, // Arduino IO28 } ; #ifdef __cplusplus @@ -230,6 +241,11 @@ void initVariant( void ) variantAdcInit(); cfw_platform_init(); + + // Add for debug corelib + #ifdef CONFIGURE_DEBUG_CORELIB_ENABLED + log_init(); + #endif } #ifdef __cplusplus