From edd8df4c5020e51266b890f7fc66757d17ffe52d Mon Sep 17 00:00:00 2001 From: Noel Eck Date: Wed, 5 Oct 2016 13:36:56 -0700 Subject: [PATCH] encodings: Added check for non-8bit encodings in src tree. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit sanitizes source files for unicode encodings which cause failures in downstream flows (docgen, python2 module loading, etc...). * Removed explicit encodings from src files * Replaced 2 byte character encodings with ascii encodies: ± -> +/- ° -> deg “ -> " etc... * Added ctest to check src tree files for non-8bit encodings Signed-off-by: Noel Eck --- src/ads1x15/ads1015.hpp | 6 +- src/ads1x15/ads1115.hpp | 6 +- src/adxl345/adxl345.hpp | 2 +- src/bmp280/bme280.hpp | 2 +- src/bmp280/bmp280.cxx | 2 +- src/bmp280/bmp280.hpp | 4 +- src/bmx055/bmi055.hpp | 2 +- src/bmx055/bmm150.hpp | 2 +- src/bno055/bno055.hpp | 2 +- src/ds1808lc/CMakeLists.txt | 2 +- src/ds2413/ds2413.hpp | 2 +- src/grovescam/grovescam.hpp | 2 +- src/hlg150h/CMakeLists.txt | 2 +- src/lcd/ssd1308.hpp | 2 +- src/lcd/ssd1327.hpp | 2 +- src/lp8860/CMakeLists.txt | 2 +- src/lpd8806/CMakeLists.txt | 2 +- src/max44009/max44009.hpp | 2 +- src/mcp9808/mcp9808.hpp | 12 +- src/mpu9150/mpu60x0.hpp | 4 +- src/ms5611/CMakeLists.txt | 2 +- src/nrf8001/aci.h | 1344 ++++++++++++------------- src/nrf8001/aci_cmds.h | 866 ++++++++-------- src/nrf8001/aci_evts.h | 794 +++++++-------- src/nrf8001/aci_protocol_defines.h | 384 +++---- src/nrf8001/aci_queue.cpp | 402 ++++---- src/nrf8001/aci_queue.h | 152 +-- src/nrf8001/aci_setup.cpp | 354 +++---- src/nrf8001/aci_setup.h | 100 +- src/nrf8001/acilib.cpp | 1220 +++++++++++------------ src/nrf8001/acilib.h | 122 +-- src/nrf8001/acilib_defs.h | 74 +- src/nrf8001/acilib_if.h | 942 +++++++++--------- src/nrf8001/acilib_types.h | 66 +- src/nrf8001/boards.h | 72 +- src/nrf8001/dtm.h | 126 +-- src/nrf8001/hal_aci_tl.cpp | 918 ++++++++--------- src/nrf8001/hal_aci_tl.h | 378 +++---- src/nrf8001/hal_platform.h | 156 +-- src/nrf8001/lib_aci.cpp | 1484 ++++++++++++++-------------- src/nrf8001/lib_aci.h | 1138 ++++++++++----------- src/nrf8001/uart_over_ble.h | 158 +-- src/scam/scam.hpp | 2 +- src/tb7300/tb7300.hpp | 4 +- tests/CMakeLists.txt | 7 + tests/check_file_encoding.py | 54 + 46 files changed, 5721 insertions(+), 5660 deletions(-) create mode 100755 tests/check_file_encoding.py diff --git a/src/ads1x15/ads1015.hpp b/src/ads1x15/ads1015.hpp index c51a455a..476b3d5b 100644 --- a/src/ads1x15/ads1015.hpp +++ b/src/ads1x15/ads1015.hpp @@ -1,4 +1,4 @@ -/* +/* * Author: Marc Graham * Copyright (c) 2015 Intel Corporation. * @@ -71,12 +71,12 @@ namespace upm { * Data is transferred via an I2C-compatible serial interface; four I2C slave addresses can be selected. The ADS1013/4/5 * operate from a single power supply ranging from 2.0V to 5.5V. * The ADS1013/4/5 can perform conversions at rates up to 3300 samples per second (SPS). An onboard PGA is available - * on the ADS1014 and ADS1015 that offers input ranges from the supply to as low as ±256mV, allowing both large and small + * on the ADS1014 and ADS1015 that offers input ranges from the supply to as low as +/- 256mV, allowing both large and small * signals to be measured with high resolution. The ADS1015 also features an input multiplexer (MUX) that provides two * differential or four single-ended inputs. * The ADS1013/4/5 operate either in continuous conversion mode or a single-shot mode that automatically powers down * after a conversion and greatly reduces current consumption during idle periods. The ADS1013/4/5 are specified from - * –40°C to +125°C. + * -40 deg C to +125 deg C. * * Tested with Adafriut ADS1015 board: https://www.adafruit.com/products/1083 * diff --git a/src/ads1x15/ads1115.hpp b/src/ads1x15/ads1115.hpp index ffe44abc..44e9af50 100644 --- a/src/ads1x15/ads1115.hpp +++ b/src/ads1x15/ads1115.hpp @@ -1,4 +1,4 @@ -/* +/* * Author: Marc Graham * Copyright (c) 2015 Intel Corporation. * @@ -71,11 +71,11 @@ namespace upm { * an I2C-compatible serial interface; four I2C slave addresses can be selected. The ADS1113/4/5 operate from a single power * supply ranging from 2.0V to 5.5V. * The ADS1113/4/5 can perform conversions at rates up to 860 samples per second (SPS). An onboard PGA is available on - * the ADS1114 and ADS1115 that offers input ranges from the supply to as low as ±256mV, allowing both large and small + * the ADS1114 and ADS1115 that offers input ranges from the supply to as low as +/- 256mV, allowing both large and small * signals to be measured with high resolution. The ADS1115 also features an input multiplexer (MUX) that provides two * differential or four single-ended inputs. * The ADS1113/4/5 operate either in continuous conversion mode or a single-shot mode that automatically powers down after - * a conversion and greatly reduces current consumption during idle periods. The ADS1113/4/5 are specified from –40°C to +125°C. + * a conversion and greatly reduces current consumption during idle periods. The ADS1113/4/5 are specified from -40 deg C to +125 deg C. * * Tested with DIYMall ADS1115 board. Also available from Adafruit: https://www.adafruit.com/products/1085 * diff --git a/src/adxl345/adxl345.hpp b/src/adxl345/adxl345.hpp index 7d35f238..aa18c1bd 100644 --- a/src/adxl345/adxl345.hpp +++ b/src/adxl345/adxl345.hpp @@ -48,7 +48,7 @@ namespace upm { * * ADXL345 is a 3-axis digital accelerometer. * (http://www.seeedstudio.com/wiki/images/2/2c/ADXL345_datasheet.pdf) - * The sensor has configurable resolutions to measure ±2g, ±4g, ±8g, or ±16g. + * The sensor has configurable resolutions to measure +/- 2g, +/- 4g, +/- 8g, or +/- 16g. * Note: The Grove* version of the sensor is incompatible with and not detected * on the I2C bus by the Intel(R) Edison using an Arduino* breakout board at 5V * (3V works fine). diff --git a/src/bmp280/bme280.hpp b/src/bmp280/bme280.hpp index e6d84e54..da4a43c1 100644 --- a/src/bmp280/bme280.hpp +++ b/src/bmp280/bme280.hpp @@ -54,7 +54,7 @@ namespace upm { * The BME280 is as combined digital humidity, pressure and * temperature sensor based on proven sensing principles. The sensor * module is housed in an extremely compact metal-lid LGA package - * with a footprint of only 2.5 × 2.5 mm2 with a height of 0.93 + * with a footprint of only 2.5 * 2.5 mm2 with a height of 0.93 * mm. Its small dimensions and its low power consumption allow the * implementation in battery driven devices such as handsets, GPS * modules or watches. The BME280 is register and performance diff --git a/src/bmp280/bmp280.cxx b/src/bmp280/bmp280.cxx index 54bc3c8b..50027d28 100644 --- a/src/bmp280/bmp280.cxx +++ b/src/bmp280/bmp280.cxx @@ -538,7 +538,7 @@ void BMP280::csOff() // These functions come from the BMP280 datasheet, section 3.11.3 // Returns temperature in DegC, resolution is 0.01 DegC. Output value -// of “5123” equals 51.23 DegC. t_fine carries fine temperature as +// of "5123" equals 51.23 DegC. t_fine carries fine temperature as // global value int32_t BMP280::bmp280_compensate_T_int32(int32_t adc_T) { diff --git a/src/bmp280/bmp280.hpp b/src/bmp280/bmp280.hpp index e2c9eba3..a2ba0e51 100644 --- a/src/bmp280/bmp280.hpp +++ b/src/bmp280/bmp280.hpp @@ -58,8 +58,8 @@ namespace upm { * The BMP280 is an absolute barometric pressure sensor especially * designed for mobile applications. The sensor module is housed in * an extremely compact 8-pin metal-lid LGA package with a footprint - * of only 2.0 × 2.5 mm2 and 0.95 mm package height. Its small - * dimensions and its low power consumption of 2.7 μA @1Hz allow the + * of only 2.0 * 2.5 mm2 and 0.95 mm package height. Its small + * dimensions and its low power consumption of 2.7 uA @1Hz allow the * implementation in battery driven devices such as mobile phones, * GPS modules or watches. * diff --git a/src/bmx055/bmi055.hpp b/src/bmx055/bmi055.hpp index 0fb1e7bc..5075b829 100644 --- a/src/bmx055/bmi055.hpp +++ b/src/bmx055/bmi055.hpp @@ -45,7 +45,7 @@ namespace upm { * detection of movements and rotations in 6 degrees of freedom * (6DoF). It reflects the full functionality of a triaxial, low-g * acceleration sensor and at the same time it is capable to measure - * angular rates. Both – acceleration and angular rate – in three + * angular rates. Both - acceleration and angular rate - in three * perpendicular room dimensions, the x-, y- and z-axis. * * The BMI055 is essentially 2 separate devices in one: the BMA250E diff --git a/src/bmx055/bmm150.hpp b/src/bmx055/bmm150.hpp index db805e92..910e3ea7 100644 --- a/src/bmx055/bmm150.hpp +++ b/src/bmx055/bmm150.hpp @@ -48,7 +48,7 @@ namespace upm { * * The BMM150 is a standalone geomagnetic sensor for consumer market * applications. It allows measurements of the magnetic field in - * three perpendicular axes. Based on Bosch’s proprietary FlipCore + * three perpendicular axes. Based on Bosch's proprietary FlipCore * technology, performance and features of BMM150 are carefully * tuned and perfectly match the demanding requirements of all * 3-axis mobile applications such as electronic compass, navigation diff --git a/src/bno055/bno055.hpp b/src/bno055/bno055.hpp index 0faa4640..d974aa60 100644 --- a/src/bno055/bno055.hpp +++ b/src/bno055/bno055.hpp @@ -51,7 +51,7 @@ namespace upm { * * The BNO055 is a System in Package (SiP), integrating a triaxial * 14-bit accelerometer, a triaxial 16-bit gyroscope with a range of - * ±2000 degrees per second, a triaxial geomagnetic sensor and a + * +/- 2000 degrees per second, a triaxial geomagnetic sensor and a * 32-bit cortex M0+ microcontroller running Bosch Sensortec sensor * fusion software, in a single package. * diff --git a/src/ds1808lc/CMakeLists.txt b/src/ds1808lc/CMakeLists.txt index 6a46ccbc..6d3ab2c4 100644 --- a/src/ds1808lc/CMakeLists.txt +++ b/src/ds1808lc/CMakeLists.txt @@ -1,6 +1,6 @@ include_directories(..) set (libname "ds1808lc") -set (libdescription “DS1808 lighting controller”) +set (libdescription "DS1808 lighting controller") set (module_src ${libname}.cxx mraa-utils.cxx) set (module_hpp ${libname}.hpp) upm_module_init() diff --git a/src/ds2413/ds2413.hpp b/src/ds2413/ds2413.hpp index 1e9e238b..fb0da3af 100644 --- a/src/ds2413/ds2413.hpp +++ b/src/ds2413/ds2413.hpp @@ -54,7 +54,7 @@ namespace upm { * * @brief API for the DS2413 1-Wire Dual Channel Addressable Switch * - * The DS2413 is a dual-channel programmable I/O 1-Wire® chip. The + * The DS2413 is a dual-channel programmable I/O 1-Wire(r) chip. The * PIO outputs are configured as open-drain and provide up to 20mA * continuous sink capability and off-state operating voltage up * to 28V. Control and sensing of the PIO pins is performed with diff --git a/src/grovescam/grovescam.hpp b/src/grovescam/grovescam.hpp index 82fff7d8..a26cbeba 100644 --- a/src/grovescam/grovescam.hpp +++ b/src/grovescam/grovescam.hpp @@ -82,7 +82,7 @@ namespace upm { typedef enum { FORMAT_VGA = 7, // 640x480 - FORMAT_CIF = 5, // 352×288 + FORMAT_CIF = 5, // 352*288 FORMAT_OCIF = 3 // ??? (maybe they meant QCIF?) } PIC_FORMATS_T; diff --git a/src/hlg150h/CMakeLists.txt b/src/hlg150h/CMakeLists.txt index 6650f8b9..2b38a466 100644 --- a/src/hlg150h/CMakeLists.txt +++ b/src/hlg150h/CMakeLists.txt @@ -1,6 +1,6 @@ include_directories(..) set (libname "hlg150h") -set (libdescription “Lighting power supply”) +set (libdescription "Lighting power supply") set (module_src ${libname}.cxx mraa-utils.cxx) set (module_hpp ${libname}.hpp) upm_module_init() diff --git a/src/lcd/ssd1308.hpp b/src/lcd/ssd1308.hpp index 59c9da1b..13618da2 100644 --- a/src/lcd/ssd1308.hpp +++ b/src/lcd/ssd1308.hpp @@ -47,7 +47,7 @@ const uint8_t DISPLAY_CMD_SET_NORMAL_1308 = 0xA6; * @brief API for SSD1308 I2C-controlled OLED displays * * SSD1308 is a 128x64 dot-matrix OLED/PLED segment driver with a - * controller. This implementation was tested using the Grove LED 128×64 + * controller. This implementation was tested using the Grove LED 128*64 * Display module, which is an OLED monochrome display. * * @image html ssd1308.jpeg diff --git a/src/lcd/ssd1327.hpp b/src/lcd/ssd1327.hpp index 4e26f4d7..660b44ed 100644 --- a/src/lcd/ssd1327.hpp +++ b/src/lcd/ssd1327.hpp @@ -47,7 +47,7 @@ const uint8_t DISPLAY_CMD_SET_NORMAL = 0xA4; * @brief API for SSD1327 I2C-controlled OLED displays * * SSD1327 is a 96x96 dot-matrix OLED/PLED segment driver with a controller. - * This implementation was tested using the Grove LED 96×96 Display module, + * This implementation was tested using the Grove LED 96*96 Display module, * which is an OLED monochrome display. * * @image html ssd1327.jpeg diff --git a/src/lp8860/CMakeLists.txt b/src/lp8860/CMakeLists.txt index c4e99fb7..92370ecd 100644 --- a/src/lp8860/CMakeLists.txt +++ b/src/lp8860/CMakeLists.txt @@ -1,6 +1,6 @@ include_directories(..) set (libname "lp8860") -set (libdescription “LED lighting controller”) +set (libdescription "LED lighting controller") set (module_src ${libname}.cxx mraa-utils.cxx) set (module_hpp ${libname}.hpp) upm_module_init() diff --git a/src/lpd8806/CMakeLists.txt b/src/lpd8806/CMakeLists.txt index 0bbd74c7..1157dcdb 100644 --- a/src/lpd8806/CMakeLists.txt +++ b/src/lpd8806/CMakeLists.txt @@ -1,5 +1,5 @@ set (libname "lpd8806") -set (libdescription “Digital RGB LED strip”) +set (libdescription "Digital RGB LED strip") set (module_src ${libname}.cxx) set (module_hpp ${libname}.hpp) upm_module_init() diff --git a/src/max44009/max44009.hpp b/src/max44009/max44009.hpp index 87b98ffa..70bf50b6 100644 --- a/src/max44009/max44009.hpp +++ b/src/max44009/max44009.hpp @@ -91,7 +91,7 @@ namespace upm { * * The Maxim Integrated * [MAX44009](http://datasheets.maximintegrated.com/en/ds/MAX44009.pdf) - * is Industry’s Lowest-Power Ambient Light Sensor with ADC. + * is Industry's Lowest-Power Ambient Light Sensor with ADC. * * @library max44009 * @sensor max44009 diff --git a/src/mcp9808/mcp9808.hpp b/src/mcp9808/mcp9808.hpp index a3c99a25..dc8ec14d 100644 --- a/src/mcp9808/mcp9808.hpp +++ b/src/mcp9808/mcp9808.hpp @@ -59,8 +59,8 @@ namespace upm { * * @brief API for MCP9808 precision temprature sensor * - * The MCP9808 digital temperature sensor converts temperatures between -20°C and +100°C - * to a digital word with ±0.5°C (max.) accuracy. The MCP9808 comes with user-programmable + * The MCP9808 digital temperature sensor converts temperatures between -20 deg C and +100 deg C + * to a digital word with +/- 0.5 deg C (max.) accuracy. The MCP9808 comes with user-programmable * registers that provide flexibility for temperature sensing applications. The registers * allow user-selectable settings such as Shutdown or low-power modes and the specification * of temperature Event and Critical output boundaries. When the temperature changes beyond @@ -133,10 +133,10 @@ namespace upm { * @var MCP9808_CONFIG::ALERTMODE - Alert Output Mode bit * 0 = Comparator output (power-up default) * 1 = Interrupt output - * @var MCP9808_CONFIG::HYST_0 : 0°C - * @var MCP9808_CONFIG::HYST_1_5 : +1.5°C - * @var MCP9808_CONFIG::HYST_3_0 : +3.0°C - * @var MCP9808_CONFIG::HYST_6_0 : +6.0°C + * @var MCP9808_CONFIG::HYST_0 : 0 deg C + * @var MCP9808_CONFIG::HYST_1_5 : +1.5 deg C + * @var MCP9808_CONFIG::HYST_3_0 : +3.0 deg C + * @var MCP9808_CONFIG::HYST_6_0 : +6.0 deg C */ typedef enum { diff --git a/src/mpu9150/mpu60x0.hpp b/src/mpu9150/mpu60x0.hpp index d114ba35..11dcf17d 100644 --- a/src/mpu9150/mpu60x0.hpp +++ b/src/mpu9150/mpu60x0.hpp @@ -44,7 +44,7 @@ namespace upm { * * @brief API for the MPU60X0 3-axis Gyroscope and 3-axis Accelerometer * - * The MPU60X0 devices provide the world’s first integrated 6-axis + * The MPU60X0 devices provide the world's first integrated 6-axis * motion processor solution that eliminates the package-level * gyroscope and accelerometer cross-axis misalignment associated * with discrete solutions. The devices combine a 3-axis gyroscope @@ -401,7 +401,7 @@ namespace upm { * * MST_DLY is not enumerated in the register map. It configures * the reduced access rate of i2c slaves relative to the sample - * rate. When a slave’s access rate is decreased relative to the + * rate. When a slave's access rate is decreased relative to the * Sample Rate, the slave is accessed every * 1 / (1 + I2C_MST_DLY) samples */ diff --git a/src/ms5611/CMakeLists.txt b/src/ms5611/CMakeLists.txt index 1de88755..a24238ca 100644 --- a/src/ms5611/CMakeLists.txt +++ b/src/ms5611/CMakeLists.txt @@ -1,6 +1,6 @@ include_directories(..) set (libname "ms5611") -set (libdescription “Pressure and temperature sensor”) +set (libdescription "Pressure and temperature sensor") set (module_src ${libname}.cxx) set (module_hpp ${libname}.hpp) upm_module_init() diff --git a/src/nrf8001/aci.h b/src/nrf8001/aci.h index db67354b..33d48a61 100644 --- a/src/nrf8001/aci.h +++ b/src/nrf8001/aci.h @@ -1,672 +1,672 @@ -/* Copyright (c) 2014, Nordic Semiconductor ASA - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -/** - * @file - * @ingroup aci - */ - -/** - * @defgroup aci aci - * @{ - * @ingroup aci-lib - * - * @brief Definitions for the ACI (Application Control Interface) - * @remarks - * - * Flow control from application mcu to nRF8001 - * - * Data flow control: - * The flow control is credit based and the credit is initally given using the "device started" event. - * A credit of more than 1 is given to the application mcu. - * These credits are used only after the "ACI Connected Event" is sent to the application mcu. - * - * every send_data that is used decrements the credit available by 1. This is to be tracked by the application mcu. - * When the credit available reaches 0, the application mcu shall not send any more send_data. - * Credit is returned using the "credit event", this returned credit can then be used to send more send_data. - * This flow control is not necessary and not available for Broadcast. - * The entire credit available with the external mcu expires when a "disconnected" event arrives. - * - * Command flow control: - * When a command is sent over the ACI, the next command shall not be sent until after a response - * for the command sent has arrived. - * - */ - -#ifndef ACI_H__ -#define ACI_H__ - -/** - * Define an _aci_packed_ macro we can use in structure and enumerated type - * declarations so that the types are sized consistently across different - * platforms. In particular Arduino platforms using the GCC compiler and the - * Nordic processors using the Keil compiler. - * - * It's really the GNU compiler platforms that need a special keyword to get - * tight packing of values. On GNU platforms we can use the keyword: - * __attribute__((__packed__)) - * The thing is that while this keyword does the right thing with old and new - * versions of the gcc (C) compiler it only works right with g++ (C++) compiler - * versions that are version 4 or newer. - */ -#ifdef __GNUC__ -# if __GNUC__ >= 4 -# define _aci_packed_ __attribute__((__packed__)) -# else -# error "older g++ versions don't handle packed attribute in typedefs" -# endif -#else -# define _aci_packed_ -#endif - -#include -#include -#include -#include - -/* - * Define a macro that compares the size of the first parameter to the integer - * value of the second parameter. If they do not match, a compile time error - * for negative array size occurs (even gnu chokes on negative array size). - * - * This compare is done by creating a typedef for an array. No variables are - * created and no memory is consumed with this check. The created type is - * used for checking only and is not for use by any other code. The value - * of 10 in this macro is arbitrary, it just needs to be a value larger - * than one to result in a positive number for the array size. - */ -#define ACI_ASSERT_SIZE(x,y) typedef char x ## _assert_size_t[-1+10*(sizeof(x) == (y))] - -/** - * @def ACI_VERSION - * @brief Current ACI protocol version. 0 means a device that is not yet released. - * A numer greater than 0 refers to a specific ACI version documented and released. - * The ACI consists of the ACI commands, ACI events and error codes. - */ -#define ACI_VERSION (0x02) -/** - * @def BTLE_DEVICE_ADDRESS_SIZE - * @brief Size in bytes of a Bluetooth Address - */ -#define BTLE_DEVICE_ADDRESS_SIZE (6) -/** - * @def ACI_PACKET_MAX_LEN - * @brief Maximum length in bytes of a full ACI packet, including length prefix, opcode and payload - */ -#define ACI_PACKET_MAX_LEN (32) -/** - * @def ACI_ECHO_DATA_MAX_LEN - * @brief Maximum length in bytes of the echo data portion - */ -#define ACI_ECHO_DATA_MAX_LEN (ACI_PACKET_MAX_LEN - 3) -/** - * @def ACI_DEVICE_MAX_PIPES - * @brief Maximum number of ACI pipes - */ -#define ACI_DEVICE_MAX_PIPES (62) -/** - * @def ACI_PIPE_TX_DATA_MAX_LEN - * @brief Maximum length in bytes of a transmission data pipe packet - */ -#define ACI_PIPE_TX_DATA_MAX_LEN (20) -/** - * @def ACI_PIPE_RX_DATA_MAX_LEN - * @brief Maximum length in bytes of a reception data pipe packet - */ -#define ACI_PIPE_RX_DATA_MAX_LEN (22) -/** - * @def ACI_GAP_DEVNAME_MAX_LEN - * @brief Maximum length in bytes of the GAP device name - */ -#define ACI_GAP_DEVNAME_MAX_LEN (20) -/** - * @def ACI_AD_PACKET_MAX_LEN - * @brief Maximum length in bytes of an AD packet - */ -#define ACI_AD_PACKET_MAX_LEN (31) -/** - * @def ACI_AD_PACKET_MAX_USER_LEN - * @brief Maximum usable length in bytes of an AD packet - */ -#define ACI_AD_PACKET_MAX_USER_LEN (31 - 3) -/** - * @def ACI_PIPE_INVALID - * @brief Invalid pipe number - */ -#define ACI_PIPE_INVALID (0xFF) - -/** - * @enum aci_pipe_store_t - * @brief Storage type identifiers: local and remote - */ -typedef enum -{ - ACI_STORE_INVALID = 0x0, - ACI_STORE_LOCAL= 0x01, - ACI_STORE_REMOTE= 0x02 -} _aci_packed_ aci_pipe_store_t; - -/** - * @enum aci_pipe_type_t - * @brief Pipe types - */ -typedef enum -{ - ACI_TX_BROADCAST = 0x0001, - ACI_TX = 0x0002, - ACI_TX_ACK = 0x0004, - ACI_RX = 0x0008, - ACI_RX_ACK = 0x0010, - ACI_TX_REQ = 0x0020, - ACI_RX_REQ = 0x0040, - ACI_SET = 0x0080, - ACI_TX_SIGN = 0x0100, - ACI_RX_SIGN = 0x0200, - ACI_RX_ACK_AUTO = 0x0400 -} _aci_packed_ aci_pipe_type_t; - -ACI_ASSERT_SIZE(aci_pipe_type_t, 2); - -/** - * @enum aci_bd_addr_type_t - * @brief Bluetooth Address types - */ -typedef enum -{ - ACI_BD_ADDR_TYPE_INVALID = 0x00, - ACI_BD_ADDR_TYPE_PUBLIC = 0x01, - ACI_BD_ADDR_TYPE_RANDOM_STATIC = 0x02, - ACI_BD_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE = 0x03, - ACI_BD_ADDR_TYPE_RANDOM_PRIVATE_UNRESOLVABLE = 0x04 -} _aci_packed_ aci_bd_addr_type_t; - -/** - * @enum aci_device_output_power_t - * @brief Radio output power levels - */ -typedef enum -{ - ACI_DEVICE_OUTPUT_POWER_MINUS_18DBM = 0x00, /**< Output power set to -18dBm */ - ACI_DEVICE_OUTPUT_POWER_MINUS_12DBM = 0x01, /**< Output power set to -12dBm */ - ACI_DEVICE_OUTPUT_POWER_MINUS_6DBM = 0x02, /**< Output power set to -6dBm */ - ACI_DEVICE_OUTPUT_POWER_0DBM = 0x03 /**< Output power set to 0dBm - DEFAULT*/ -} _aci_packed_ aci_device_output_power_t; - -/** - * @enum aci_device_operation_mode_t - * @brief Device operation modes - */ -typedef enum -{ - ACI_DEVICE_INVALID =0x00, - ACI_DEVICE_TEST =0x01, - ACI_DEVICE_SETUP =0x02, - ACI_DEVICE_STANDBY =0x03, - ACI_DEVICE_SLEEP =0x04 -} _aci_packed_ aci_device_operation_mode_t; - -/** - * @enum aci_disconnect_reason_t - * @brief Reason enumeration for ACI_CMD_DISCONNECT - */ -typedef enum -{ - ACI_REASON_TERMINATE =0x01, /**< Use this to disconnect (does a terminate request), you need to wait for the "disconnected" event */ - ACI_REASON_BAD_TIMING =0x02 /*= 4 +# define _aci_packed_ __attribute__((__packed__)) +# else +# error "older g++ versions don't handle packed attribute in typedefs" +# endif +#else +# define _aci_packed_ +#endif + +#include +#include +#include +#include + +/* + * Define a macro that compares the size of the first parameter to the integer + * value of the second parameter. If they do not match, a compile time error + * for negative array size occurs (even gnu chokes on negative array size). + * + * This compare is done by creating a typedef for an array. No variables are + * created and no memory is consumed with this check. The created type is + * used for checking only and is not for use by any other code. The value + * of 10 in this macro is arbitrary, it just needs to be a value larger + * than one to result in a positive number for the array size. + */ +#define ACI_ASSERT_SIZE(x,y) typedef char x ## _assert_size_t[-1+10*(sizeof(x) == (y))] + +/** + * @def ACI_VERSION + * @brief Current ACI protocol version. 0 means a device that is not yet released. + * A numer greater than 0 refers to a specific ACI version documented and released. + * The ACI consists of the ACI commands, ACI events and error codes. + */ +#define ACI_VERSION (0x02) +/** + * @def BTLE_DEVICE_ADDRESS_SIZE + * @brief Size in bytes of a Bluetooth Address + */ +#define BTLE_DEVICE_ADDRESS_SIZE (6) +/** + * @def ACI_PACKET_MAX_LEN + * @brief Maximum length in bytes of a full ACI packet, including length prefix, opcode and payload + */ +#define ACI_PACKET_MAX_LEN (32) +/** + * @def ACI_ECHO_DATA_MAX_LEN + * @brief Maximum length in bytes of the echo data portion + */ +#define ACI_ECHO_DATA_MAX_LEN (ACI_PACKET_MAX_LEN - 3) +/** + * @def ACI_DEVICE_MAX_PIPES + * @brief Maximum number of ACI pipes + */ +#define ACI_DEVICE_MAX_PIPES (62) +/** + * @def ACI_PIPE_TX_DATA_MAX_LEN + * @brief Maximum length in bytes of a transmission data pipe packet + */ +#define ACI_PIPE_TX_DATA_MAX_LEN (20) +/** + * @def ACI_PIPE_RX_DATA_MAX_LEN + * @brief Maximum length in bytes of a reception data pipe packet + */ +#define ACI_PIPE_RX_DATA_MAX_LEN (22) +/** + * @def ACI_GAP_DEVNAME_MAX_LEN + * @brief Maximum length in bytes of the GAP device name + */ +#define ACI_GAP_DEVNAME_MAX_LEN (20) +/** + * @def ACI_AD_PACKET_MAX_LEN + * @brief Maximum length in bytes of an AD packet + */ +#define ACI_AD_PACKET_MAX_LEN (31) +/** + * @def ACI_AD_PACKET_MAX_USER_LEN + * @brief Maximum usable length in bytes of an AD packet + */ +#define ACI_AD_PACKET_MAX_USER_LEN (31 - 3) +/** + * @def ACI_PIPE_INVALID + * @brief Invalid pipe number + */ +#define ACI_PIPE_INVALID (0xFF) + +/** + * @enum aci_pipe_store_t + * @brief Storage type identifiers: local and remote + */ +typedef enum +{ + ACI_STORE_INVALID = 0x0, + ACI_STORE_LOCAL= 0x01, + ACI_STORE_REMOTE= 0x02 +} _aci_packed_ aci_pipe_store_t; + +/** + * @enum aci_pipe_type_t + * @brief Pipe types + */ +typedef enum +{ + ACI_TX_BROADCAST = 0x0001, + ACI_TX = 0x0002, + ACI_TX_ACK = 0x0004, + ACI_RX = 0x0008, + ACI_RX_ACK = 0x0010, + ACI_TX_REQ = 0x0020, + ACI_RX_REQ = 0x0040, + ACI_SET = 0x0080, + ACI_TX_SIGN = 0x0100, + ACI_RX_SIGN = 0x0200, + ACI_RX_ACK_AUTO = 0x0400 +} _aci_packed_ aci_pipe_type_t; + +ACI_ASSERT_SIZE(aci_pipe_type_t, 2); + +/** + * @enum aci_bd_addr_type_t + * @brief Bluetooth Address types + */ +typedef enum +{ + ACI_BD_ADDR_TYPE_INVALID = 0x00, + ACI_BD_ADDR_TYPE_PUBLIC = 0x01, + ACI_BD_ADDR_TYPE_RANDOM_STATIC = 0x02, + ACI_BD_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE = 0x03, + ACI_BD_ADDR_TYPE_RANDOM_PRIVATE_UNRESOLVABLE = 0x04 +} _aci_packed_ aci_bd_addr_type_t; + +/** + * @enum aci_device_output_power_t + * @brief Radio output power levels + */ +typedef enum +{ + ACI_DEVICE_OUTPUT_POWER_MINUS_18DBM = 0x00, /**< Output power set to -18dBm */ + ACI_DEVICE_OUTPUT_POWER_MINUS_12DBM = 0x01, /**< Output power set to -12dBm */ + ACI_DEVICE_OUTPUT_POWER_MINUS_6DBM = 0x02, /**< Output power set to -6dBm */ + ACI_DEVICE_OUTPUT_POWER_0DBM = 0x03 /**< Output power set to 0dBm - DEFAULT*/ +} _aci_packed_ aci_device_output_power_t; + +/** + * @enum aci_device_operation_mode_t + * @brief Device operation modes + */ +typedef enum +{ + ACI_DEVICE_INVALID =0x00, + ACI_DEVICE_TEST =0x01, + ACI_DEVICE_SETUP =0x02, + ACI_DEVICE_STANDBY =0x03, + ACI_DEVICE_SLEEP =0x04 +} _aci_packed_ aci_device_operation_mode_t; + +/** + * @enum aci_disconnect_reason_t + * @brief Reason enumeration for ACI_CMD_DISCONNECT + */ +typedef enum +{ + ACI_REASON_TERMINATE =0x01, /**< Use this to disconnect (does a terminate request), you need to wait for the "disconnected" event */ + ACI_REASON_BAD_TIMING =0x02 /* Opcode of the ACI command */ - union - { - aci_cmd_params_test_t test; - aci_cmd_params_echo_t echo; - aci_cmd_params_dtm_cmd_t dtm_cmd; - aci_cmd_params_setup_t setup; - aci_cmd_params_write_dynamic_data_t write_dynamic_data; - aci_cmd_params_set_local_data_t set_local_data; - aci_cmd_params_connect_t connect; - aci_cmd_params_bond_t bond; - aci_cmd_params_disconnect_t disconnect; - aci_cmd_params_set_tx_power_t set_tx_power; - aci_cmd_params_change_timing_t change_timing; - aci_cmd_params_open_remote_pipe_t open_remote_pipe; - aci_cmd_params_send_data_t send_data; - aci_cmd_params_send_data_ack_t send_data_ack; - aci_cmd_params_request_data_t request_data; - aci_cmd_params_send_data_nack_t send_data_nack; - aci_cmd_params_set_app_latency_t set_app_latency; - aci_cmd_params_set_key_t set_key; - aci_cmd_params_open_adv_pipe_t open_adv_pipe; - aci_cmd_params_broadcast_t broadcast; - aci_cmd_params_close_remote_pipe_t close_remote_pipe; - - } params; -} _aci_packed_ aci_cmd_t; - -#endif // ACI_CMDS_H__ - - +/* Copyright (c) 2014, Nordic Semiconductor ASA + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/** + * @file + * @ingroup aci + * @brief Definitions for the ACI (Application Control Interface) commands + * @remarks + * + */ + +#ifndef ACI_CMDS_H__ +#define ACI_CMDS_H__ + +#include "aci.h" + +/** + * @enum aci_cmd_opcode_t + * @brief ACI command opcodes + */ +typedef enum +{ + /** + * Enter test mode + */ + ACI_CMD_TEST = 0x01, + /** + * Echo (loopback) test command + */ + ACI_CMD_ECHO = 0x02, + /** + * Send a BTLE DTM command to the radio + */ + ACI_CMD_DTM_CMD = 0x03, + /** + * Put the device to sleep + */ + ACI_CMD_SLEEP = 0x04, + /** + * Wakeup the device from deep sleep + */ + ACI_CMD_WAKEUP = 0x05, + /** + * Replace the contents of the internal database with + * user provided data + */ + ACI_CMD_SETUP = 0x06, + /** + * Read the portions of memory required to be restored after a power cycle + */ + ACI_CMD_READ_DYNAMIC_DATA = 0x07, + /** + * Write back the data retrieved using ACI_CMD_READ_DYNAMIC_DATA + */ + ACI_CMD_WRITE_DYNAMIC_DATA = 0x08, + /** + * Retrieve the device's version information + */ + ACI_CMD_GET_DEVICE_VERSION = 0x09, + /** + * Request the Bluetooth address and its type + */ + ACI_CMD_GET_DEVICE_ADDRESS = 0x0A, + /** + * Request the battery level measured by nRF8001 + */ + ACI_CMD_GET_BATTERY_LEVEL = 0x0B, + /** + * Request the temperature value measured by nRF8001 + */ + ACI_CMD_GET_TEMPERATURE = 0x0C, + /** + * Write to the local Attribute Database + */ + ACI_CMD_SET_LOCAL_DATA = 0x0D, + /** + * Reset the baseband and radio and go back to idle + */ + ACI_CMD_RADIO_RESET = 0x0E, + /** + * Start advertising and wait for a master connection + */ + ACI_CMD_CONNECT = 0x0F, + /** + * Start advertising and wait for a master connection + */ + ACI_CMD_BOND = 0x10, + /** + * Start advertising and wait for a master connection + */ + ACI_CMD_DISCONNECT = 0x11, + /** + * Throttles the Radio transmit power + */ + ACI_CMD_SET_TX_POWER = 0x12, + /** + * Trigger a connection parameter update + */ + ACI_CMD_CHANGE_TIMING = 0x13, + /** + * Open a remote pipe for data reception + */ + ACI_CMD_OPEN_REMOTE_PIPE = 0x14, + /** + * Transmit data over an open pipe + */ + ACI_CMD_SEND_DATA = 0x15, + /** + * Send an acknowledgment of received data + */ + ACI_CMD_SEND_DATA_ACK = 0x16, + /** + * Request data over an open pipe + */ + ACI_CMD_REQUEST_DATA = 0x17, + /** + * NACK a data reception + */ + ACI_CMD_SEND_DATA_NACK = 0x18, + /** + * Set application latency + */ + ACI_CMD_SET_APP_LATENCY = 0x19, + /** + * Set a security key + */ + ACI_CMD_SET_KEY = 0x1A, + /** + * Open Advertising Pipes + */ + ACI_CMD_OPEN_ADV_PIPE = 0x1B, + /** + * Start non-connectable advertising + */ + ACI_CMD_BROADCAST = 0x1C, + /** + * Start a security request in bonding mode + */ + ACI_CMD_BOND_SECURITY_REQUEST = 0x1D, + /** + * Start Directed advertising towards a Bonded Peer + */ + ACI_CMD_CONNECT_DIRECT = 0x1E, + /** + * Close a previously opened remote pipe + */ + ACI_CMD_CLOSE_REMOTE_PIPE = 0x1F, + /** + * Invalid ACI command opcode + */ + ACI_CMD_INVALID = 0xFF + +} _aci_packed_ aci_cmd_opcode_t; + +ACI_ASSERT_SIZE(aci_cmd_opcode_t, 1); + +/** + * @struct aci_cmd_params_test_t + * @brief Structure for the ACI_CMD_TEST ACI command parameters + */ +typedef struct +{ + aci_test_mode_change_t test_mode_change; /**< enum aci_test_mode_change_t */ +} _aci_packed_ aci_cmd_params_test_t; + +ACI_ASSERT_SIZE(aci_cmd_params_test_t, 1); + +/** + * @struct aci_cmd_params_echo_t + * @brief Structure for the ACI_CMD_ECHO ACI command parameters + */ +typedef struct +{ + uint8_t echo_data[ACI_ECHO_DATA_MAX_LEN]; +} _aci_packed_ aci_cmd_params_echo_t; + +ACI_ASSERT_SIZE(aci_cmd_params_echo_t, ACI_ECHO_DATA_MAX_LEN); + +/** + * @struct aci_cmd_params_dtm_cmd_t + * @brief Structure for the ACI_CMD_DTM_CMD ACI command parameters + */ +typedef struct +{ + uint8_t cmd_msb; + uint8_t cmd_lsb; +} _aci_packed_ aci_cmd_params_dtm_cmd_t; + +/** + * @struct aci_cmd_params_setup_t + * @brief Structure for the ACI_CMD_SETUP ACI command parameters + */ +typedef struct +{ + uint8_t setup_data[1]; +} _aci_packed_ aci_cmd_params_setup_t; + +ACI_ASSERT_SIZE(aci_cmd_params_setup_t, 1); + +/** + * @struct aci_cmd_params_write_dynamic_data_t + * @brief Structure for the ACI_CMD_WRITE_DYNAMIC_DATA ACI command parameters + * @note Dynamic data chunk size in this command is defined to go up to ACI_PACKET_MAX_LEN - 3 + */ +typedef struct +{ + uint8_t seq_no; + uint8_t dynamic_data[1]; +} _aci_packed_ aci_cmd_params_write_dynamic_data_t; + +/** + * @define aci_cmd_params_set_local_data_t + * @brief Structure for the ACI_CMD_SET_LOCAL_DATA ACI command parameters + */ +typedef struct +{ + aci_tx_data_t tx_data; +} _aci_packed_ aci_cmd_params_set_local_data_t; + +/** + * @struct aci_cmd_params_connect_t + * @brief Structure for the ACI_CMD_CONNECT ACI command parameters + */ +typedef struct +{ + uint16_t timeout; /**< 0x0000 (no timeout) to 0x3FFF */ + uint16_t adv_interval; /**< 16 bits of advertising interval for general discovery */ +} _aci_packed_ aci_cmd_params_connect_t; + +ACI_ASSERT_SIZE(aci_cmd_params_connect_t, 4); + +/** + * @define aci_cmd_params_bond_t + * @brief Structure for the ACI_CMD_BOND ACI command parameters + */ +typedef struct +{ + uint16_t timeout; /**< 0x0000 (no timeout) to 0x3FFF */ + uint16_t adv_interval; /**< 16 bits of advertising interval for general discovery */ +} _aci_packed_ aci_cmd_params_bond_t; + +ACI_ASSERT_SIZE(aci_cmd_params_bond_t, 4); + +/** + * @struct aci_cmd_params_disconnect_t + * @brief Structure for the ACI_CMD_DISCONNECT ACI command parameters + */ +typedef struct +{ + aci_disconnect_reason_t reason; /**< enum aci_disconnect_reason_t */ +} _aci_packed_ aci_cmd_params_disconnect_t; + +ACI_ASSERT_SIZE(aci_cmd_params_disconnect_t, 1); + +/** + * @struct aci_cmd_params_set_tx_power_t + * @brief Structure for the ACI_CMD_SET_TX_POWER ACI command parameters + */ +typedef struct +{ + aci_device_output_power_t device_power; /**< enum aci_device_output_power_t */ +} _aci_packed_ aci_cmd_params_set_tx_power_t; + +ACI_ASSERT_SIZE(aci_cmd_params_set_tx_power_t, 1); +/** + * @struct aci_cmd_params_change_timing_t + * @brief Structure for the ACI_CMD_CHANGE_TIMING ACI command parameters + */ +typedef struct +{ + aci_ll_conn_params_t conn_params; +} _aci_packed_ aci_cmd_params_change_timing_t; + +ACI_ASSERT_SIZE(aci_cmd_params_change_timing_t, 8); + +/** + * @struct aci_cmd_params_open_remote_pipe_t + * @brief Structure for the ACI_CMD_OPEN_REMOTE_PIPE ACI command parameters + */ +typedef struct +{ + uint8_t pipe_number; +} _aci_packed_ aci_cmd_params_open_remote_pipe_t; + +/** + * @struct aci_cmd_params_send_data_t + * @brief Structure for the ACI_CMD_SEND_DATA ACI command parameters + */ +typedef struct +{ + aci_tx_data_t tx_data; +} _aci_packed_ aci_cmd_params_send_data_t; + +/** + * @define aci_cmd_params_send_data_ack_t + * @brief Structure for the ACI_CMD_SEND_DATA_ACK ACI command parameters + */ +typedef struct +{ + uint8_t pipe_number; +} _aci_packed_ aci_cmd_params_send_data_ack_t; + +/** + * @struct aci_cmd_params_send_data_t + * @brief Structure for the ACI_CMD_SEND_DATA ACI command parameters + */ +typedef struct +{ + uint8_t pipe_number; +} _aci_packed_ aci_cmd_params_request_data_t; + +/** + * @define aci_cmd_params_send_data_nack_t + * @brief Structure for the ACI_CMD_SEND_DATA_NACK ACI command parameters + */ +typedef struct +{ + uint8_t pipe_number; + uint8_t error_code; +} _aci_packed_ aci_cmd_params_send_data_nack_t; + +ACI_ASSERT_SIZE(aci_cmd_params_send_data_nack_t, 2); + +/** + * @define aci_cmd_params_set_app_latency_t + * @brief Structure for the ACI_CMD_SET_APP_LATENCY ACI command parameters + */ +typedef struct +{ + aci_app_latency_mode_t mode; + uint16_t latency; +} _aci_packed_ aci_cmd_params_set_app_latency_t; + +ACI_ASSERT_SIZE(aci_cmd_params_set_app_latency_t, 3); +/** + * @define aci_cmd_params_set_key_t + * @brief Structure for the ACI_CMD_SET_KEY ACI command parameters + */ +typedef struct +{ + aci_key_type_t key_type; + union + { + uint8_t passkey[6]; + uint8_t oob_key[16]; + } key; +} _aci_packed_ aci_cmd_params_set_key_t; + +ACI_ASSERT_SIZE(aci_cmd_params_set_key_t, 17); +/** + * @define aci_cmd_params_open_adv_pipe_t + * @brief Structure for the ACI_CMD_OPEN_ADV_PIPE ACI command parameters + */ +typedef struct +{ + uint8_t pipes[8]; +} _aci_packed_ aci_cmd_params_open_adv_pipe_t; + +/** + * @define aci_cmd_params_broadcast_t + * @brief Structure for the ACI_CMD_BROADCAST ACI command parameters + */ +typedef struct +{ + uint16_t timeout; /**< 0x0000 (no timeout) to 0x3FFF */ + uint16_t adv_interval; /**< 16 bits of advertising interval for general discovery */ +} _aci_packed_ aci_cmd_params_broadcast_t; + +/** + * @struct aci_cmd_params_close_remote_pipe_t + * @brief Structure for the ACI_CMD_CLOSE_REMOTE_PIPE ACI command parameters + */ +typedef struct +{ + uint8_t pipe_number; +} _aci_packed_ aci_cmd_params_close_remote_pipe_t; + +/** + * @struct aci_cmd_t + * @brief Encapsulates a generic ACI command + */ +typedef struct +{ + uint8_t len; /**< Length of the ACI command */ + aci_cmd_opcode_t cmd_opcode; /**< enum aci_cmd_opcode_t -> Opcode of the ACI command */ + union + { + aci_cmd_params_test_t test; + aci_cmd_params_echo_t echo; + aci_cmd_params_dtm_cmd_t dtm_cmd; + aci_cmd_params_setup_t setup; + aci_cmd_params_write_dynamic_data_t write_dynamic_data; + aci_cmd_params_set_local_data_t set_local_data; + aci_cmd_params_connect_t connect; + aci_cmd_params_bond_t bond; + aci_cmd_params_disconnect_t disconnect; + aci_cmd_params_set_tx_power_t set_tx_power; + aci_cmd_params_change_timing_t change_timing; + aci_cmd_params_open_remote_pipe_t open_remote_pipe; + aci_cmd_params_send_data_t send_data; + aci_cmd_params_send_data_ack_t send_data_ack; + aci_cmd_params_request_data_t request_data; + aci_cmd_params_send_data_nack_t send_data_nack; + aci_cmd_params_set_app_latency_t set_app_latency; + aci_cmd_params_set_key_t set_key; + aci_cmd_params_open_adv_pipe_t open_adv_pipe; + aci_cmd_params_broadcast_t broadcast; + aci_cmd_params_close_remote_pipe_t close_remote_pipe; + + } params; +} _aci_packed_ aci_cmd_t; + +#endif // ACI_CMDS_H__ + + diff --git a/src/nrf8001/aci_evts.h b/src/nrf8001/aci_evts.h index 0a577f59..48ead501 100644 --- a/src/nrf8001/aci_evts.h +++ b/src/nrf8001/aci_evts.h @@ -1,397 +1,397 @@ -/* Copyright (c) 2014, Nordic Semiconductor ASA - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -/** - * @file - * - * @ingroup aci - * - * @brief Definitions for the ACI (Application Control Interface) events - */ - -#ifndef ACI_EVTS_H__ -#define ACI_EVTS_H__ - -#include "aci.h" - -/** - * @enum aci_evt_opcode_t - * @brief ACI event opcodes - */ -typedef enum -{ - /** - * Invalid event code - */ - ACI_EVT_INVALID = 0x00, - /** - * Sent every time the device starts - */ - ACI_EVT_DEVICE_STARTED = 0x81, - /** - * Mirrors the ACI_CMD_ECHO - */ - ACI_EVT_ECHO = 0x82, - /** - * Asynchronous hardware error event - */ - ACI_EVT_HW_ERROR = 0x83, - /** - * Event opcode used as a event response for all commands - */ - ACI_EVT_CMD_RSP = 0x84, - /** - * Link connected - */ - ACI_EVT_CONNECTED = 0x85, - /** - * Link disconnected - */ - ACI_EVT_DISCONNECTED = 0x86, - /** - * Bond completion result - */ - ACI_EVT_BOND_STATUS = 0x87, - /** - * Pipe bitmap for available pipes - */ - ACI_EVT_PIPE_STATUS = 0x88, - /** - * Sent to the application when the radio enters a connected state - * or when the timing of the radio connection changes - */ - ACI_EVT_TIMING = 0x89, - /** - * Notification to the application that transmit credits are - * available - */ - ACI_EVT_DATA_CREDIT = 0x8A, - /** - * Data acknowledgement event - */ - ACI_EVT_DATA_ACK = 0x8B, - /** - * Data received notification event - */ - ACI_EVT_DATA_RECEIVED = 0x8C, - /** - * Error notification event - */ - ACI_EVT_PIPE_ERROR = 0x8D, - /** - * Display Passkey Event - */ - ACI_EVT_DISPLAY_PASSKEY = 0x8E, - /** - * Security Key request - */ - ACI_EVT_KEY_REQUEST = 0x8F - -} _aci_packed_ aci_evt_opcode_t; - -ACI_ASSERT_SIZE(aci_evt_opcode_t, 1); - -/** - * @struct aci_evt_params_device_started_t - * @brief Structure for the ACI_EVT_DEVICE_STARTED event return parameters - */ -typedef struct -{ - aci_device_operation_mode_t device_mode; /**< Mode in which the device is being started */ - aci_hw_error_t hw_error; /**< Hardware Error if available for the start */ - uint8_t credit_available; /**< Flow control credit available for this specific FW build */ -} _aci_packed_ aci_evt_params_device_started_t; - -ACI_ASSERT_SIZE(aci_evt_params_device_started_t, 3); - -/** - * @struct aci_evt_params_hw_error_t - * @brief Structure for the ACI_EVT_HW_ERROR event return parameters - */ -typedef struct -{ - uint16_t line_num; - uint8_t file_name[20]; -} _aci_packed_ aci_evt_params_hw_error_t; - -ACI_ASSERT_SIZE(aci_evt_params_hw_error_t, 22); - -/** - * @struct aci_evt_cmd_rsp_params_dtm_cmd_t - * @brief Structure for the ACI_EVT_CMD_RSP event with opcode=ACI_CMD_DTM_CMD event return parameters - */ -typedef struct -{ - uint8_t evt_msb; - uint8_t evt_lsb; -} _aci_packed_ aci_evt_cmd_rsp_params_dtm_cmd_t; - -/** - * @struct aci_evt_cmd_rsp_read_dynamic_data_t - * @brief Structure for the ACI_EVT_CMD_RSP event with opcode=ACI_CMD_READ_DYNAMIC_DATA event return parameters - * @note Dynamic data chunk size in this event is defined to go up to ACI_PACKET_MAX_LEN - 5 - */ -typedef struct -{ - uint8_t seq_no; - uint8_t dynamic_data[1]; -} _aci_packed_ aci_evt_cmd_rsp_read_dynamic_data_t; - -/** - * @struct aci_evt_cmd_rsp_params_get_device_version_t - * @brief Structure for the ACI_EVT_CMD_RSP event with opcode=ACI_CMD_GET_DEVICE_VERSION event return parameters - */ -typedef struct -{ - uint16_t configuration_id; - uint8_t aci_version; - uint8_t setup_format; - uint32_t setup_id; - uint8_t setup_status; -} _aci_packed_ aci_evt_cmd_rsp_params_get_device_version_t; - -ACI_ASSERT_SIZE(aci_evt_cmd_rsp_params_get_device_version_t, 9); - -/** - * @struct aci_evt_cmd_rsp_params_get_device_address_t - * @brief Structure for the ACI_EVT_CMD_RSP event with opcode=ACI_CMD_GET_DEVICE_ADDRESS event return parameters - */ -typedef struct -{ - uint8_t bd_addr_own[BTLE_DEVICE_ADDRESS_SIZE]; - aci_bd_addr_type_t bd_addr_type; -} _aci_packed_ aci_evt_cmd_rsp_params_get_device_address_t; - -ACI_ASSERT_SIZE(aci_evt_cmd_rsp_params_get_device_address_t, BTLE_DEVICE_ADDRESS_SIZE + 1); - -/** - * @struct aci_evt_cmd_rsp_params_get_battery_level_t - * @brief Structure for the ACI_EVT_CMD_RSP event with opcode=ACI_CMD_GET_BATTERY_LEVEL event return parameters - */ -typedef struct -{ - uint16_t battery_level; -} _aci_packed_ aci_evt_cmd_rsp_params_get_battery_level_t; - -/** - * @struct aci_evt_cmd_rsp_params_get_temperature_t - * @brief Structure for the ACI_EVT_CMD_RSP event with opcode=ACI_CMD_GET_TEMPERATURE event return parameters - */ -typedef struct -{ - int16_t temperature_value; -} _aci_packed_ aci_evt_cmd_rsp_params_get_temperature_t; - -/** - * @struct aci_evt_params_cmd_rsp_t - * @brief Structure for the ACI_EVT_CMD_RSP event return parameters - */ -typedef struct -{ - aci_cmd_opcode_t cmd_opcode; /**< Command opcode for which the event response is being sent */ - aci_status_code_t cmd_status; /**< Status of the command that was sent. Used in the context of the command. */ - union - { - aci_evt_cmd_rsp_params_dtm_cmd_t dtm_cmd; - aci_evt_cmd_rsp_read_dynamic_data_t read_dynamic_data; - aci_evt_cmd_rsp_params_get_device_version_t get_device_version; - aci_evt_cmd_rsp_params_get_device_address_t get_device_address; - aci_evt_cmd_rsp_params_get_battery_level_t get_battery_level; - aci_evt_cmd_rsp_params_get_temperature_t get_temperature; - uint8_t padding[29]; - } params; -} _aci_packed_ aci_evt_params_cmd_rsp_t; - -ACI_ASSERT_SIZE(aci_evt_params_cmd_rsp_t, 31); - -/** - * @struct aci_evt_params_connected_t - * @brief Structure for the ACI_EVT_CONNECTED event return parameters - */ -typedef struct -{ - aci_bd_addr_type_t dev_addr_type; - uint8_t dev_addr[BTLE_DEVICE_ADDRESS_SIZE]; - uint16_t conn_rf_interval; /**< rf_interval = conn_rf_interval * 1.25 ms Range:0x0006 to 0x0C80 */ - uint16_t conn_slave_rf_latency; /**< Number of RF events the slave can skip */ - uint16_t conn_rf_timeout; /**< Timeout as a multiple of 10ms i.e timeout = conn_rf_timeout * 10ms Range: 0x000A to 0x0C80 */ - aci_clock_accuracy_t master_clock_accuracy; /**< Clock accuracy of Bluetooth master: Enumerated list of values from 500 ppm to 20 ppm */ -} _aci_packed_ aci_evt_params_connected_t; - -ACI_ASSERT_SIZE(aci_evt_params_connected_t, 14); - -/** - * @struct aci_evt_params_disconnected_t - * @brief Structure for the ACI_EVT_DISCONNECTED event return parameters - */ -typedef struct -{ - aci_status_code_t aci_status; - uint8_t btle_status; -} _aci_packed_ aci_evt_params_disconnected_t; - -ACI_ASSERT_SIZE(aci_evt_params_disconnected_t, 2); - -/** - * @struct aci_evt_params_bond_status_t - * @brief Structure for the ACI_EVT_BOND_STATUS event return parameters - */ -typedef struct -{ - aci_bond_status_code_t status_code; - aci_bond_status_source_t status_source; - uint8_t secmode1_bitmap; - uint8_t secmode2_bitmap; - uint8_t keys_exchanged_slave; - uint8_t keys_exchanged_master; -} _aci_packed_ aci_evt_params_bond_status_t; - -ACI_ASSERT_SIZE(aci_evt_params_bond_status_t, 6); - -/** - * @struct aci_evt_params_pipe_status_t - * @brief Structure for the ACI_EVT_PIPE_STATUS event return parameters - */ -typedef struct -{ - uint8_t pipes_open_bitmap[8]; - uint8_t pipes_closed_bitmap[8]; -} _aci_packed_ aci_evt_params_pipe_status_t; - -ACI_ASSERT_SIZE(aci_evt_params_pipe_status_t, 16); - -/** - * @struct aci_evt_params_timing_t - * @brief Structure for the ACI_EVT_TIMING event return parameters - */ -typedef struct -{ - uint16_t conn_rf_interval; /**< rf_interval = conn_rf_interval * 1.25 ms Range:0x0006 to 0x0C80 */ - uint16_t conn_slave_rf_latency; /**< Number of RF events the slave can skip */ - uint16_t conn_rf_timeout; /**< Timeout as a multiple of 10ms i.e timeout = conn_rf_timeout * 10ms Range: 0x000A to 0x0C80 */ -} _aci_packed_ aci_evt_params_timing_t; - -ACI_ASSERT_SIZE(aci_evt_params_timing_t, 6); - -/** - * @struct aci_evt_params_data_credit_t - * @brief Structure for the ACI_EVT_DATA_CREDIT event return parameters - */ -typedef struct -{ - uint8_t credit; -} _aci_packed_ aci_evt_params_data_credit_t; - -/** - * @struct aci_evt_params_data_ack_t - * @brief Structure for the ACI_EVT_DATA_ACK event return parameters - */ -typedef struct -{ - uint8_t pipe_number; -} _aci_packed_ aci_evt_params_data_ack_t; - -/** - * @struct aci_evt_params_data_received_t - * @brief Structure for the ACI_EVT_DATA_RECEIVED event return parameters - */ -typedef struct -{ - aci_rx_data_t rx_data; -} _aci_packed_ aci_evt_params_data_received_t; - -typedef struct -{ - uint8_t content[1]; -} _aci_packed_ error_data_t; - -/** - * @struct aci_evt_params_pipe_error_t - * @brief Structure for the ACI_EVT_PIPE_ERROR event return parameters - */ -typedef struct -{ - uint8_t pipe_number; - uint8_t error_code; - union - { - error_data_t error_data; - } params; -} _aci_packed_ aci_evt_params_pipe_error_t; - -/** - * @struct aci_evt_params_display_passkey_t - * @brief Structure for the ACI_EVT_DISPLAY_PASSKEY event return parameters - */ -typedef struct -{ - uint8_t passkey[6]; -} _aci_packed_ aci_evt_params_display_passkey_t; - -/** - * @struct aci_evt_params_key_request_t - * @brief Structure for the ACI_EVT_KEY_REQUEST event return parameters - */ -typedef struct -{ - aci_key_type_t key_type; -} _aci_packed_ aci_evt_params_key_request_t; - -/** - * @struct aci_event_params_echo_t - * @brief Structure for the ACI_EVT_ECHO ACI event parameters - */ -typedef struct -{ - uint8_t echo_data[ACI_ECHO_DATA_MAX_LEN]; -} _aci_packed_ aci_evt_params_echo_t; - -/** - * @struct aci_evt_t - * @brief Encapsulates a generic ACI event - */ -typedef struct -{ - uint8_t len; - aci_evt_opcode_t evt_opcode; - union - { - aci_evt_params_device_started_t device_started; - aci_evt_params_echo_t echo; - aci_evt_params_hw_error_t hw_error; - aci_evt_params_cmd_rsp_t cmd_rsp; - aci_evt_params_connected_t connected; - aci_evt_params_disconnected_t disconnected; - aci_evt_params_bond_status_t bond_status; - aci_evt_params_pipe_status_t pipe_status; - aci_evt_params_timing_t timing; - aci_evt_params_data_credit_t data_credit; - aci_evt_params_data_ack_t data_ack; - aci_evt_params_data_received_t data_received; - aci_evt_params_pipe_error_t pipe_error; - aci_evt_params_display_passkey_t display_passkey; - aci_evt_params_key_request_t key_request; - } params; -} _aci_packed_ aci_evt_t; - -ACI_ASSERT_SIZE(aci_evt_t, 33); - -#endif // ACI_EVTS_H__ +/* Copyright (c) 2014, Nordic Semiconductor ASA + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/** + * @file + * + * @ingroup aci + * + * @brief Definitions for the ACI (Application Control Interface) events + */ + +#ifndef ACI_EVTS_H__ +#define ACI_EVTS_H__ + +#include "aci.h" + +/** + * @enum aci_evt_opcode_t + * @brief ACI event opcodes + */ +typedef enum +{ + /** + * Invalid event code + */ + ACI_EVT_INVALID = 0x00, + /** + * Sent every time the device starts + */ + ACI_EVT_DEVICE_STARTED = 0x81, + /** + * Mirrors the ACI_CMD_ECHO + */ + ACI_EVT_ECHO = 0x82, + /** + * Asynchronous hardware error event + */ + ACI_EVT_HW_ERROR = 0x83, + /** + * Event opcode used as a event response for all commands + */ + ACI_EVT_CMD_RSP = 0x84, + /** + * Link connected + */ + ACI_EVT_CONNECTED = 0x85, + /** + * Link disconnected + */ + ACI_EVT_DISCONNECTED = 0x86, + /** + * Bond completion result + */ + ACI_EVT_BOND_STATUS = 0x87, + /** + * Pipe bitmap for available pipes + */ + ACI_EVT_PIPE_STATUS = 0x88, + /** + * Sent to the application when the radio enters a connected state + * or when the timing of the radio connection changes + */ + ACI_EVT_TIMING = 0x89, + /** + * Notification to the application that transmit credits are + * available + */ + ACI_EVT_DATA_CREDIT = 0x8A, + /** + * Data acknowledgement event + */ + ACI_EVT_DATA_ACK = 0x8B, + /** + * Data received notification event + */ + ACI_EVT_DATA_RECEIVED = 0x8C, + /** + * Error notification event + */ + ACI_EVT_PIPE_ERROR = 0x8D, + /** + * Display Passkey Event + */ + ACI_EVT_DISPLAY_PASSKEY = 0x8E, + /** + * Security Key request + */ + ACI_EVT_KEY_REQUEST = 0x8F + +} _aci_packed_ aci_evt_opcode_t; + +ACI_ASSERT_SIZE(aci_evt_opcode_t, 1); + +/** + * @struct aci_evt_params_device_started_t + * @brief Structure for the ACI_EVT_DEVICE_STARTED event return parameters + */ +typedef struct +{ + aci_device_operation_mode_t device_mode; /**< Mode in which the device is being started */ + aci_hw_error_t hw_error; /**< Hardware Error if available for the start */ + uint8_t credit_available; /**< Flow control credit available for this specific FW build */ +} _aci_packed_ aci_evt_params_device_started_t; + +ACI_ASSERT_SIZE(aci_evt_params_device_started_t, 3); + +/** + * @struct aci_evt_params_hw_error_t + * @brief Structure for the ACI_EVT_HW_ERROR event return parameters + */ +typedef struct +{ + uint16_t line_num; + uint8_t file_name[20]; +} _aci_packed_ aci_evt_params_hw_error_t; + +ACI_ASSERT_SIZE(aci_evt_params_hw_error_t, 22); + +/** + * @struct aci_evt_cmd_rsp_params_dtm_cmd_t + * @brief Structure for the ACI_EVT_CMD_RSP event with opcode=ACI_CMD_DTM_CMD event return parameters + */ +typedef struct +{ + uint8_t evt_msb; + uint8_t evt_lsb; +} _aci_packed_ aci_evt_cmd_rsp_params_dtm_cmd_t; + +/** + * @struct aci_evt_cmd_rsp_read_dynamic_data_t + * @brief Structure for the ACI_EVT_CMD_RSP event with opcode=ACI_CMD_READ_DYNAMIC_DATA event return parameters + * @note Dynamic data chunk size in this event is defined to go up to ACI_PACKET_MAX_LEN - 5 + */ +typedef struct +{ + uint8_t seq_no; + uint8_t dynamic_data[1]; +} _aci_packed_ aci_evt_cmd_rsp_read_dynamic_data_t; + +/** + * @struct aci_evt_cmd_rsp_params_get_device_version_t + * @brief Structure for the ACI_EVT_CMD_RSP event with opcode=ACI_CMD_GET_DEVICE_VERSION event return parameters + */ +typedef struct +{ + uint16_t configuration_id; + uint8_t aci_version; + uint8_t setup_format; + uint32_t setup_id; + uint8_t setup_status; +} _aci_packed_ aci_evt_cmd_rsp_params_get_device_version_t; + +ACI_ASSERT_SIZE(aci_evt_cmd_rsp_params_get_device_version_t, 9); + +/** + * @struct aci_evt_cmd_rsp_params_get_device_address_t + * @brief Structure for the ACI_EVT_CMD_RSP event with opcode=ACI_CMD_GET_DEVICE_ADDRESS event return parameters + */ +typedef struct +{ + uint8_t bd_addr_own[BTLE_DEVICE_ADDRESS_SIZE]; + aci_bd_addr_type_t bd_addr_type; +} _aci_packed_ aci_evt_cmd_rsp_params_get_device_address_t; + +ACI_ASSERT_SIZE(aci_evt_cmd_rsp_params_get_device_address_t, BTLE_DEVICE_ADDRESS_SIZE + 1); + +/** + * @struct aci_evt_cmd_rsp_params_get_battery_level_t + * @brief Structure for the ACI_EVT_CMD_RSP event with opcode=ACI_CMD_GET_BATTERY_LEVEL event return parameters + */ +typedef struct +{ + uint16_t battery_level; +} _aci_packed_ aci_evt_cmd_rsp_params_get_battery_level_t; + +/** + * @struct aci_evt_cmd_rsp_params_get_temperature_t + * @brief Structure for the ACI_EVT_CMD_RSP event with opcode=ACI_CMD_GET_TEMPERATURE event return parameters + */ +typedef struct +{ + int16_t temperature_value; +} _aci_packed_ aci_evt_cmd_rsp_params_get_temperature_t; + +/** + * @struct aci_evt_params_cmd_rsp_t + * @brief Structure for the ACI_EVT_CMD_RSP event return parameters + */ +typedef struct +{ + aci_cmd_opcode_t cmd_opcode; /**< Command opcode for which the event response is being sent */ + aci_status_code_t cmd_status; /**< Status of the command that was sent. Used in the context of the command. */ + union + { + aci_evt_cmd_rsp_params_dtm_cmd_t dtm_cmd; + aci_evt_cmd_rsp_read_dynamic_data_t read_dynamic_data; + aci_evt_cmd_rsp_params_get_device_version_t get_device_version; + aci_evt_cmd_rsp_params_get_device_address_t get_device_address; + aci_evt_cmd_rsp_params_get_battery_level_t get_battery_level; + aci_evt_cmd_rsp_params_get_temperature_t get_temperature; + uint8_t padding[29]; + } params; +} _aci_packed_ aci_evt_params_cmd_rsp_t; + +ACI_ASSERT_SIZE(aci_evt_params_cmd_rsp_t, 31); + +/** + * @struct aci_evt_params_connected_t + * @brief Structure for the ACI_EVT_CONNECTED event return parameters + */ +typedef struct +{ + aci_bd_addr_type_t dev_addr_type; + uint8_t dev_addr[BTLE_DEVICE_ADDRESS_SIZE]; + uint16_t conn_rf_interval; /**< rf_interval = conn_rf_interval * 1.25 ms Range:0x0006 to 0x0C80 */ + uint16_t conn_slave_rf_latency; /**< Number of RF events the slave can skip */ + uint16_t conn_rf_timeout; /**< Timeout as a multiple of 10ms i.e timeout = conn_rf_timeout * 10ms Range: 0x000A to 0x0C80 */ + aci_clock_accuracy_t master_clock_accuracy; /**< Clock accuracy of Bluetooth master: Enumerated list of values from 500 ppm to 20 ppm */ +} _aci_packed_ aci_evt_params_connected_t; + +ACI_ASSERT_SIZE(aci_evt_params_connected_t, 14); + +/** + * @struct aci_evt_params_disconnected_t + * @brief Structure for the ACI_EVT_DISCONNECTED event return parameters + */ +typedef struct +{ + aci_status_code_t aci_status; + uint8_t btle_status; +} _aci_packed_ aci_evt_params_disconnected_t; + +ACI_ASSERT_SIZE(aci_evt_params_disconnected_t, 2); + +/** + * @struct aci_evt_params_bond_status_t + * @brief Structure for the ACI_EVT_BOND_STATUS event return parameters + */ +typedef struct +{ + aci_bond_status_code_t status_code; + aci_bond_status_source_t status_source; + uint8_t secmode1_bitmap; + uint8_t secmode2_bitmap; + uint8_t keys_exchanged_slave; + uint8_t keys_exchanged_master; +} _aci_packed_ aci_evt_params_bond_status_t; + +ACI_ASSERT_SIZE(aci_evt_params_bond_status_t, 6); + +/** + * @struct aci_evt_params_pipe_status_t + * @brief Structure for the ACI_EVT_PIPE_STATUS event return parameters + */ +typedef struct +{ + uint8_t pipes_open_bitmap[8]; + uint8_t pipes_closed_bitmap[8]; +} _aci_packed_ aci_evt_params_pipe_status_t; + +ACI_ASSERT_SIZE(aci_evt_params_pipe_status_t, 16); + +/** + * @struct aci_evt_params_timing_t + * @brief Structure for the ACI_EVT_TIMING event return parameters + */ +typedef struct +{ + uint16_t conn_rf_interval; /**< rf_interval = conn_rf_interval * 1.25 ms Range:0x0006 to 0x0C80 */ + uint16_t conn_slave_rf_latency; /**< Number of RF events the slave can skip */ + uint16_t conn_rf_timeout; /**< Timeout as a multiple of 10ms i.e timeout = conn_rf_timeout * 10ms Range: 0x000A to 0x0C80 */ +} _aci_packed_ aci_evt_params_timing_t; + +ACI_ASSERT_SIZE(aci_evt_params_timing_t, 6); + +/** + * @struct aci_evt_params_data_credit_t + * @brief Structure for the ACI_EVT_DATA_CREDIT event return parameters + */ +typedef struct +{ + uint8_t credit; +} _aci_packed_ aci_evt_params_data_credit_t; + +/** + * @struct aci_evt_params_data_ack_t + * @brief Structure for the ACI_EVT_DATA_ACK event return parameters + */ +typedef struct +{ + uint8_t pipe_number; +} _aci_packed_ aci_evt_params_data_ack_t; + +/** + * @struct aci_evt_params_data_received_t + * @brief Structure for the ACI_EVT_DATA_RECEIVED event return parameters + */ +typedef struct +{ + aci_rx_data_t rx_data; +} _aci_packed_ aci_evt_params_data_received_t; + +typedef struct +{ + uint8_t content[1]; +} _aci_packed_ error_data_t; + +/** + * @struct aci_evt_params_pipe_error_t + * @brief Structure for the ACI_EVT_PIPE_ERROR event return parameters + */ +typedef struct +{ + uint8_t pipe_number; + uint8_t error_code; + union + { + error_data_t error_data; + } params; +} _aci_packed_ aci_evt_params_pipe_error_t; + +/** + * @struct aci_evt_params_display_passkey_t + * @brief Structure for the ACI_EVT_DISPLAY_PASSKEY event return parameters + */ +typedef struct +{ + uint8_t passkey[6]; +} _aci_packed_ aci_evt_params_display_passkey_t; + +/** + * @struct aci_evt_params_key_request_t + * @brief Structure for the ACI_EVT_KEY_REQUEST event return parameters + */ +typedef struct +{ + aci_key_type_t key_type; +} _aci_packed_ aci_evt_params_key_request_t; + +/** + * @struct aci_event_params_echo_t + * @brief Structure for the ACI_EVT_ECHO ACI event parameters + */ +typedef struct +{ + uint8_t echo_data[ACI_ECHO_DATA_MAX_LEN]; +} _aci_packed_ aci_evt_params_echo_t; + +/** + * @struct aci_evt_t + * @brief Encapsulates a generic ACI event + */ +typedef struct +{ + uint8_t len; + aci_evt_opcode_t evt_opcode; + union + { + aci_evt_params_device_started_t device_started; + aci_evt_params_echo_t echo; + aci_evt_params_hw_error_t hw_error; + aci_evt_params_cmd_rsp_t cmd_rsp; + aci_evt_params_connected_t connected; + aci_evt_params_disconnected_t disconnected; + aci_evt_params_bond_status_t bond_status; + aci_evt_params_pipe_status_t pipe_status; + aci_evt_params_timing_t timing; + aci_evt_params_data_credit_t data_credit; + aci_evt_params_data_ack_t data_ack; + aci_evt_params_data_received_t data_received; + aci_evt_params_pipe_error_t pipe_error; + aci_evt_params_display_passkey_t display_passkey; + aci_evt_params_key_request_t key_request; + } params; +} _aci_packed_ aci_evt_t; + +ACI_ASSERT_SIZE(aci_evt_t, 33); + +#endif // ACI_EVTS_H__ diff --git a/src/nrf8001/aci_protocol_defines.h b/src/nrf8001/aci_protocol_defines.h index 65b2aad8..3d70ca4a 100644 --- a/src/nrf8001/aci_protocol_defines.h +++ b/src/nrf8001/aci_protocol_defines.h @@ -1,192 +1,192 @@ -/* Copyright (c) 2014, Nordic Semiconductor ASA - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -/** - * @file - * - * @ingroup aci - * - * @brief This file contents defines for the position of all the fields of ACI - * command or event messages - */ - -#ifndef ACI_OFFSET_H__ -#define ACI_OFFSET_H__ - - - #define OFFSET_ACI_LL_CONN_PARAMS_T_MIN_CONN_INTERVAL_LSB 0 - #define OFFSET_ACI_LL_CONN_PARAMS_T_MIN_CONN_INTERVAL_MSB 1 - #define OFFSET_ACI_LL_CONN_PARAMS_T_MAX_CONN_INTERVAL_LSB 2 - #define OFFSET_ACI_LL_CONN_PARAMS_T_MAX_CONN_INTERVAL_MSB 3 - #define OFFSET_ACI_LL_CONN_PARAMS_T_SLAVE_LATENCY_LSB 4 - #define OFFSET_ACI_LL_CONN_PARAMS_T_SLAVE_LATENCY_MSB 5 - #define OFFSET_ACI_LL_CONN_PARAMS_T_TIMEOUT_MULT_LSB 6 - #define OFFSET_ACI_LL_CONN_PARAMS_T_TIMEOUT_MULT_MSB 7 - #define OFFSET_ACI_TX_DATA_T_PIPE_NUMBER 0 - #define OFFSET_ACI_TX_DATA_T_ACI_DATA 1 - #define OFFSET_ACI_RX_DATA_T_PIPE_NUMBER 0 - #define OFFSET_ACI_RX_DATA_T_ACI_DATA 1 - #define OFFSET_ACI_CMD_PARAMS_TEST_T_TEST_MODE_CHANGE 0 - #define OFFSET_ACI_CMD_PARAMS_ECHO_T_ECHO_DATA 0 - #define OFFSET_ACI_CMD_PARAMS_DTM_CMD_T_CMD_MSB 0 - #define OFFSET_ACI_CMD_PARAMS_DTM_CMD_T_CMD_LSB 1 - #define OFFSET_ACI_CMD_PARAMS_SETUP_T_SETUP_DATA 0 - #define OFFSET_ACI_CMD_PARAMS_WRITE_DYNAMIC_DATA_T_SEQ_NO 0 - #define OFFSET_ACI_CMD_PARAMS_WRITE_DYNAMIC_DATA_T_DYNAMIC_DATA 1 - #define OFFSET_ACI_CMD_PARAMS_SET_LOCAL_DATA_T_TX_DATA 0 - #define OFFSET_ACI_CMD_PARAMS_CONNECT_T_TIMEOUT_LSB 0 - #define OFFSET_ACI_CMD_PARAMS_CONNECT_T_TIMEOUT_MSB 1 - #define OFFSET_ACI_CMD_PARAMS_CONNECT_T_ADV_INTERVAL_LSB 2 - #define OFFSET_ACI_CMD_PARAMS_CONNECT_T_ADV_INTERVAL_MSB 3 - #define OFFSET_ACI_CMD_PARAMS_BOND_T_TIMEOUT_LSB 0 - #define OFFSET_ACI_CMD_PARAMS_BOND_T_TIMEOUT_MSB 1 - #define OFFSET_ACI_CMD_PARAMS_BOND_T_ADV_INTERVAL_LSB 2 - #define OFFSET_ACI_CMD_PARAMS_BOND_T_ADV_INTERVAL_MSB 3 - #define OFFSET_ACI_CMD_PARAMS_DISCONNECT_T_REASON 0 - #define OFFSET_ACI_CMD_PARAMS_SET_TX_POWER_T_DEVICE_POWER 0 - #define OFFSET_ACI_CMD_PARAMS_CHANGE_TIMING_T_CONN_PARAMS 0 - #define OFFSET_ACI_CMD_PARAMS_OPEN_REMOTE_PIPE_T_PIPE_NUMBER 0 - #define OFFSET_ACI_CMD_PARAMS_SEND_DATA_T_TX_DATA 0 - #define OFFSET_ACI_CMD_PARAMS_SEND_DATA_ACK_T_PIPE_NUMBER 0 - #define OFFSET_ACI_CMD_PARAMS_REQUEST_DATA_T_PIPE_NUMBER 0 - #define OFFSET_ACI_CMD_PARAMS_SEND_DATA_NACK_T_PIPE_NUMBER 0 - #define OFFSET_ACI_CMD_PARAMS_SEND_DATA_NACK_T_ERROR_CODE 1 - #define OFFSET_ACI_CMD_PARAMS_SET_APP_LATENCY_T_MODE 0 - #define OFFSET_ACI_CMD_PARAMS_SET_APP_LATENCY_T_LATENCY_LSB 1 - #define OFFSET_ACI_CMD_PARAMS_SET_APP_LATENCY_T_LATENCY_MSB 2 - #define OFFSET_ACI_CMD_PARAMS_SET_KEY_T_KEY_TYPE 0 - #define OFFSET_ACI_CMD_PARAMS_SET_KEY_T_PASSKEY 1 - #define OFFSET_ACI_CMD_PARAMS_SET_KEY_T_OOB_KEY 1 - #define OFFSET_ACI_CMD_PARAMS_OPEN_ADV_PIPE_T_PIPES 0 - #define OFFSET_ACI_CMD_PARAMS_BROADCAST_T_TIMEOUT_LSB 0 - #define OFFSET_ACI_CMD_PARAMS_BROADCAST_T_TIMEOUT_MSB 1 - #define OFFSET_ACI_CMD_PARAMS_BROADCAST_T_ADV_INTERVAL_LSB 2 - #define OFFSET_ACI_CMD_PARAMS_BROADCAST_T_ADV_INTERVAL_MSB 3 - #define OFFSET_ACI_CMD_PARAMS_CLOSE_REMOTE_PIPE_T_PIPE_NUMBER 0 - #define OFFSET_ACI_CMD_T_LEN 0 - #define OFFSET_ACI_CMD_T_CMD_OPCODE 1 - #define OFFSET_ACI_CMD_T_TEST 2 - #define OFFSET_ACI_CMD_T_ECHO 2 - #define OFFSET_ACI_CMD_T_DTM_CMD 2 - #define OFFSET_ACI_CMD_T_SETUP 2 - #define OFFSET_ACI_CMD_T_WRITE_DYNAMIC_DATA 2 - #define OFFSET_ACI_CMD_T_SET_LOCAL_DATA 2 - #define OFFSET_ACI_CMD_T_CONNECT 2 - #define OFFSET_ACI_CMD_T_BOND 2 - #define OFFSET_ACI_CMD_T_DISCONNECT 2 - #define OFFSET_ACI_CMD_T_SET_TX_POWER 2 - #define OFFSET_ACI_CMD_T_CHANGE_TIMING 2 - #define OFFSET_ACI_CMD_T_OPEN_REMOTE_PIPE 2 - #define OFFSET_ACI_CMD_T_SEND_DATA 2 - #define OFFSET_ACI_CMD_T_SEND_DATA_ACK 2 - #define OFFSET_ACI_CMD_T_REQUEST_DATA 2 - #define OFFSET_ACI_CMD_T_SEND_DATA_NACK 2 - #define OFFSET_ACI_CMD_T_SET_APP_LATENCY 2 - #define OFFSET_ACI_CMD_T_SET_KEY 2 - #define OFFSET_ACI_CMD_T_OPEN_ADV_PIPE 2 - #define OFFSET_ACI_CMD_T_BROADCAST 2 - #define OFFSET_ACI_CMD_T_CLOSE_REMOTE_PIPE 2 - #define OFFSET_ACI_EVT_PARAMS_DEVICE_STARTED_T_DEVICE_MODE 0 - #define OFFSET_ACI_EVT_PARAMS_DEVICE_STARTED_T_HW_ERROR 1 - #define OFFSET_ACI_EVT_PARAMS_DEVICE_STARTED_T_CREDIT_AVAILABLE 2 - #define OFFSET_ACI_EVT_PARAMS_HW_ERROR_T_LINE_NUM_LSB 0 - #define OFFSET_ACI_EVT_PARAMS_HW_ERROR_T_LINE_NUM_MSB 1 - #define OFFSET_ACI_EVT_PARAMS_HW_ERROR_T_FILE_NAME 2 - #define OFFSET_ACI_EVT_CMD_RSP_PARAMS_DTM_CMD_T_EVT_MSB 0 - #define OFFSET_ACI_EVT_CMD_RSP_PARAMS_DTM_CMD_T_EVT_LSB 1 - #define OFFSET_ACI_EVT_CMD_RSP_READ_DYNAMIC_DATA_T_SEQ_NO 0 - #define OFFSET_ACI_EVT_CMD_RSP_READ_DYNAMIC_DATA_T_DYNAMIC_DATA 1 - #define OFFSET_ACI_EVT_CMD_RSP_PARAMS_GET_DEVICE_VERSION_T_CONFIGURATION_ID_LSB 0 - #define OFFSET_ACI_EVT_CMD_RSP_PARAMS_GET_DEVICE_VERSION_T_CONFIGURATION_ID_MSB 1 - #define OFFSET_ACI_EVT_CMD_RSP_PARAMS_GET_DEVICE_VERSION_T_ACI_VERSION 2 - #define OFFSET_ACI_EVT_CMD_RSP_PARAMS_GET_DEVICE_VERSION_T_SETUP_FORMAT 3 - #define OFFSET_ACI_EVT_CMD_RSP_PARAMS_GET_DEVICE_VERSION_T_SETUP_ID_LSB0 4 - #define OFFSET_ACI_EVT_CMD_RSP_PARAMS_GET_DEVICE_VERSION_T_SETUP_ID_LSB1 5 - #define OFFSET_ACI_EVT_CMD_RSP_PARAMS_GET_DEVICE_VERSION_T_SETUP_ID_MSB0 6 - #define OFFSET_ACI_EVT_CMD_RSP_PARAMS_GET_DEVICE_VERSION_T_SETUP_ID_MSB1 7 - #define OFFSET_ACI_EVT_CMD_RSP_PARAMS_GET_DEVICE_VERSION_T_SETUP_STATUS 8 - #define OFFSET_ACI_EVT_CMD_RSP_PARAMS_GET_DEVICE_ADDRESS_T_BD_ADDR_OWN 0 - #define OFFSET_ACI_EVT_CMD_RSP_PARAMS_GET_DEVICE_ADDRESS_T_BD_ADDR_TYPE 6 - #define OFFSET_ACI_EVT_CMD_RSP_PARAMS_GET_BATTERY_LEVEL_T_BATTERY_LEVEL_LSB 0 - #define OFFSET_ACI_EVT_CMD_RSP_PARAMS_GET_BATTERY_LEVEL_T_BATTERY_LEVEL_MSB 1 - #define OFFSET_ACI_EVT_CMD_RSP_PARAMS_GET_TEMPERATURE_T_TEMPERATURE_VALUE_LSB 0 - #define OFFSET_ACI_EVT_CMD_RSP_PARAMS_GET_TEMPERATURE_T_TEMPERATURE_VALUE_MSB 1 - #define OFFSET_ACI_EVT_PARAMS_CMD_RSP_T_CMD_OPCODE 0 - #define OFFSET_ACI_EVT_PARAMS_CMD_RSP_T_CMD_STATUS 1 - #define OFFSET_ACI_EVT_PARAMS_CMD_RSP_T_DTM_CMD 2 - #define OFFSET_ACI_EVT_PARAMS_CMD_RSP_T_READ_DYNAMIC_DATA 2 - #define OFFSET_ACI_EVT_PARAMS_CMD_RSP_T_GET_DEVICE_VERSION 2 - #define OFFSET_ACI_EVT_PARAMS_CMD_RSP_T_GET_DEVICE_ADDRESS 2 - #define OFFSET_ACI_EVT_PARAMS_CMD_RSP_T_GET_BATTERY_LEVEL 2 - #define OFFSET_ACI_EVT_PARAMS_CMD_RSP_T_GET_TEMPERATURE 2 - #define OFFSET_ACI_EVT_PARAMS_CONNECTED_T_DEV_ADDR_TYPE 0 - #define OFFSET_ACI_EVT_PARAMS_CONNECTED_T_DEV_ADDR 1 - #define OFFSET_ACI_EVT_PARAMS_CONNECTED_T_CONN_RF_INTERVAL_LSB 7 - #define OFFSET_ACI_EVT_PARAMS_CONNECTED_T_CONN_RF_INTERVAL_MSB 8 - #define OFFSET_ACI_EVT_PARAMS_CONNECTED_T_CONN_SLAVE_RF_LATENCY_LSB 9 - #define OFFSET_ACI_EVT_PARAMS_CONNECTED_T_CONN_SLAVE_RF_LATENCY_MSB 10 - #define OFFSET_ACI_EVT_PARAMS_CONNECTED_T_CONN_RF_TIMEOUT_LSB 11 - #define OFFSET_ACI_EVT_PARAMS_CONNECTED_T_CONN_RF_TIMEOUT_MSB 12 - #define OFFSET_ACI_EVT_PARAMS_CONNECTED_T_MASTER_CLOCK_ACCURACY 13 - #define OFFSET_ACI_EVT_PARAMS_DISCONNECTED_T_ACI_STATUS 0 - #define OFFSET_ACI_EVT_PARAMS_DISCONNECTED_T_BTLE_STATUS 1 - #define OFFSET_ACI_EVT_PARAMS_BOND_STATUS_T_STATUS_CODE 0 - #define OFFSET_ACI_EVT_PARAMS_BOND_STATUS_T_STATUS_SOURCE 1 - #define OFFSET_ACI_EVT_PARAMS_BOND_STATUS_T_SECMODE1_BITMAP 2 - #define OFFSET_ACI_EVT_PARAMS_BOND_STATUS_T_SECMODE2_BITMAP 3 - #define OFFSET_ACI_EVT_PARAMS_BOND_STATUS_T_KEYS_EXCHANGED_SLAVE 4 - #define OFFSET_ACI_EVT_PARAMS_BOND_STATUS_T_KEYS_EXCHANGED_MASTER 5 - #define OFFSET_ACI_EVT_PARAMS_PIPE_STATUS_T_PIPES_OPEN_BITMAP 0 - #define OFFSET_ACI_EVT_PARAMS_PIPE_STATUS_T_PIPES_CLOSED_BITMAP 8 - #define OFFSET_ACI_EVT_PARAMS_TIMING_T_CONN_RF_INTERVAL_LSB 0 - #define OFFSET_ACI_EVT_PARAMS_TIMING_T_CONN_RF_INTERVAL_MSB 1 - #define OFFSET_ACI_EVT_PARAMS_TIMING_T_CONN_SLAVE_RF_LATENCY_LSB 2 - #define OFFSET_ACI_EVT_PARAMS_TIMING_T_CONN_SLAVE_RF_LATENCY_MSB 3 - #define OFFSET_ACI_EVT_PARAMS_TIMING_T_CONN_RF_TIMEOUT_LSB 4 - #define OFFSET_ACI_EVT_PARAMS_TIMING_T_CONN_RF_TIMEOUT_MSB 5 - #define OFFSET_ACI_EVT_PARAMS_DATA_CREDIT_T_CREDIT 0 - #define OFFSET_ACI_EVT_PARAMS_DATA_ACK_T_PIPE_NUMBER 0 - #define OFFSET_ACI_EVT_PARAMS_DATA_RECEIVED_T_RX_DATA 0 - #define OFFSET_ERROR_DATA_T_CONTENT 0 - #define OFFSET_ACI_EVT_PARAMS_PIPE_ERROR_T_PIPE_NUMBER 0 - #define OFFSET_ACI_EVT_PARAMS_PIPE_ERROR_T_ERROR_CODE 1 - #define OFFSET_ACI_EVT_PARAMS_PIPE_ERROR_T_ERROR_DATA 2 - #define OFFSET_ACI_EVT_PARAMS_DISPLAY_PASSKEY_T_PASSKEY 0 - #define OFFSET_ACI_EVT_PARAMS_KEY_REQUEST_T_KEY_TYPE 0 - #define OFFSET_ACI_EVT_T_LEN 0 - #define OFFSET_ACI_EVT_T_EVT_OPCODE 1 - #define OFFSET_ACI_EVT_T_DEVICE_STARTED 2 - #define OFFSET_ACI_EVT_T_HW_ERROR 2 - #define OFFSET_ACI_EVT_T_CMD_RSP 2 - #define OFFSET_ACI_EVT_T_CONNECTED 2 - #define OFFSET_ACI_EVT_T_DISCONNECTED 2 - #define OFFSET_ACI_EVT_T_BOND_STATUS 2 - #define OFFSET_ACI_EVT_T_PIPE_STATUS 2 - #define OFFSET_ACI_EVT_T_TIMING 2 - #define OFFSET_ACI_EVT_T_DATA_CREDIT 2 - #define OFFSET_ACI_EVT_T_DATA_ACK 2 - #define OFFSET_ACI_EVT_T_DATA_RECEIVED 2 - #define OFFSET_ACI_EVT_T_PIPE_ERROR 2 - #define OFFSET_ACI_EVT_T_DISPLAY_PASSKEY 2 - #define OFFSET_ACI_EVT_T_KEY_REQUEST 2 - -#endif //ACI_OFFSET_H__ - +/* Copyright (c) 2014, Nordic Semiconductor ASA + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/** + * @file + * + * @ingroup aci + * + * @brief This file contents defines for the position of all the fields of ACI + * command or event messages + */ + +#ifndef ACI_OFFSET_H__ +#define ACI_OFFSET_H__ + + + #define OFFSET_ACI_LL_CONN_PARAMS_T_MIN_CONN_INTERVAL_LSB 0 + #define OFFSET_ACI_LL_CONN_PARAMS_T_MIN_CONN_INTERVAL_MSB 1 + #define OFFSET_ACI_LL_CONN_PARAMS_T_MAX_CONN_INTERVAL_LSB 2 + #define OFFSET_ACI_LL_CONN_PARAMS_T_MAX_CONN_INTERVAL_MSB 3 + #define OFFSET_ACI_LL_CONN_PARAMS_T_SLAVE_LATENCY_LSB 4 + #define OFFSET_ACI_LL_CONN_PARAMS_T_SLAVE_LATENCY_MSB 5 + #define OFFSET_ACI_LL_CONN_PARAMS_T_TIMEOUT_MULT_LSB 6 + #define OFFSET_ACI_LL_CONN_PARAMS_T_TIMEOUT_MULT_MSB 7 + #define OFFSET_ACI_TX_DATA_T_PIPE_NUMBER 0 + #define OFFSET_ACI_TX_DATA_T_ACI_DATA 1 + #define OFFSET_ACI_RX_DATA_T_PIPE_NUMBER 0 + #define OFFSET_ACI_RX_DATA_T_ACI_DATA 1 + #define OFFSET_ACI_CMD_PARAMS_TEST_T_TEST_MODE_CHANGE 0 + #define OFFSET_ACI_CMD_PARAMS_ECHO_T_ECHO_DATA 0 + #define OFFSET_ACI_CMD_PARAMS_DTM_CMD_T_CMD_MSB 0 + #define OFFSET_ACI_CMD_PARAMS_DTM_CMD_T_CMD_LSB 1 + #define OFFSET_ACI_CMD_PARAMS_SETUP_T_SETUP_DATA 0 + #define OFFSET_ACI_CMD_PARAMS_WRITE_DYNAMIC_DATA_T_SEQ_NO 0 + #define OFFSET_ACI_CMD_PARAMS_WRITE_DYNAMIC_DATA_T_DYNAMIC_DATA 1 + #define OFFSET_ACI_CMD_PARAMS_SET_LOCAL_DATA_T_TX_DATA 0 + #define OFFSET_ACI_CMD_PARAMS_CONNECT_T_TIMEOUT_LSB 0 + #define OFFSET_ACI_CMD_PARAMS_CONNECT_T_TIMEOUT_MSB 1 + #define OFFSET_ACI_CMD_PARAMS_CONNECT_T_ADV_INTERVAL_LSB 2 + #define OFFSET_ACI_CMD_PARAMS_CONNECT_T_ADV_INTERVAL_MSB 3 + #define OFFSET_ACI_CMD_PARAMS_BOND_T_TIMEOUT_LSB 0 + #define OFFSET_ACI_CMD_PARAMS_BOND_T_TIMEOUT_MSB 1 + #define OFFSET_ACI_CMD_PARAMS_BOND_T_ADV_INTERVAL_LSB 2 + #define OFFSET_ACI_CMD_PARAMS_BOND_T_ADV_INTERVAL_MSB 3 + #define OFFSET_ACI_CMD_PARAMS_DISCONNECT_T_REASON 0 + #define OFFSET_ACI_CMD_PARAMS_SET_TX_POWER_T_DEVICE_POWER 0 + #define OFFSET_ACI_CMD_PARAMS_CHANGE_TIMING_T_CONN_PARAMS 0 + #define OFFSET_ACI_CMD_PARAMS_OPEN_REMOTE_PIPE_T_PIPE_NUMBER 0 + #define OFFSET_ACI_CMD_PARAMS_SEND_DATA_T_TX_DATA 0 + #define OFFSET_ACI_CMD_PARAMS_SEND_DATA_ACK_T_PIPE_NUMBER 0 + #define OFFSET_ACI_CMD_PARAMS_REQUEST_DATA_T_PIPE_NUMBER 0 + #define OFFSET_ACI_CMD_PARAMS_SEND_DATA_NACK_T_PIPE_NUMBER 0 + #define OFFSET_ACI_CMD_PARAMS_SEND_DATA_NACK_T_ERROR_CODE 1 + #define OFFSET_ACI_CMD_PARAMS_SET_APP_LATENCY_T_MODE 0 + #define OFFSET_ACI_CMD_PARAMS_SET_APP_LATENCY_T_LATENCY_LSB 1 + #define OFFSET_ACI_CMD_PARAMS_SET_APP_LATENCY_T_LATENCY_MSB 2 + #define OFFSET_ACI_CMD_PARAMS_SET_KEY_T_KEY_TYPE 0 + #define OFFSET_ACI_CMD_PARAMS_SET_KEY_T_PASSKEY 1 + #define OFFSET_ACI_CMD_PARAMS_SET_KEY_T_OOB_KEY 1 + #define OFFSET_ACI_CMD_PARAMS_OPEN_ADV_PIPE_T_PIPES 0 + #define OFFSET_ACI_CMD_PARAMS_BROADCAST_T_TIMEOUT_LSB 0 + #define OFFSET_ACI_CMD_PARAMS_BROADCAST_T_TIMEOUT_MSB 1 + #define OFFSET_ACI_CMD_PARAMS_BROADCAST_T_ADV_INTERVAL_LSB 2 + #define OFFSET_ACI_CMD_PARAMS_BROADCAST_T_ADV_INTERVAL_MSB 3 + #define OFFSET_ACI_CMD_PARAMS_CLOSE_REMOTE_PIPE_T_PIPE_NUMBER 0 + #define OFFSET_ACI_CMD_T_LEN 0 + #define OFFSET_ACI_CMD_T_CMD_OPCODE 1 + #define OFFSET_ACI_CMD_T_TEST 2 + #define OFFSET_ACI_CMD_T_ECHO 2 + #define OFFSET_ACI_CMD_T_DTM_CMD 2 + #define OFFSET_ACI_CMD_T_SETUP 2 + #define OFFSET_ACI_CMD_T_WRITE_DYNAMIC_DATA 2 + #define OFFSET_ACI_CMD_T_SET_LOCAL_DATA 2 + #define OFFSET_ACI_CMD_T_CONNECT 2 + #define OFFSET_ACI_CMD_T_BOND 2 + #define OFFSET_ACI_CMD_T_DISCONNECT 2 + #define OFFSET_ACI_CMD_T_SET_TX_POWER 2 + #define OFFSET_ACI_CMD_T_CHANGE_TIMING 2 + #define OFFSET_ACI_CMD_T_OPEN_REMOTE_PIPE 2 + #define OFFSET_ACI_CMD_T_SEND_DATA 2 + #define OFFSET_ACI_CMD_T_SEND_DATA_ACK 2 + #define OFFSET_ACI_CMD_T_REQUEST_DATA 2 + #define OFFSET_ACI_CMD_T_SEND_DATA_NACK 2 + #define OFFSET_ACI_CMD_T_SET_APP_LATENCY 2 + #define OFFSET_ACI_CMD_T_SET_KEY 2 + #define OFFSET_ACI_CMD_T_OPEN_ADV_PIPE 2 + #define OFFSET_ACI_CMD_T_BROADCAST 2 + #define OFFSET_ACI_CMD_T_CLOSE_REMOTE_PIPE 2 + #define OFFSET_ACI_EVT_PARAMS_DEVICE_STARTED_T_DEVICE_MODE 0 + #define OFFSET_ACI_EVT_PARAMS_DEVICE_STARTED_T_HW_ERROR 1 + #define OFFSET_ACI_EVT_PARAMS_DEVICE_STARTED_T_CREDIT_AVAILABLE 2 + #define OFFSET_ACI_EVT_PARAMS_HW_ERROR_T_LINE_NUM_LSB 0 + #define OFFSET_ACI_EVT_PARAMS_HW_ERROR_T_LINE_NUM_MSB 1 + #define OFFSET_ACI_EVT_PARAMS_HW_ERROR_T_FILE_NAME 2 + #define OFFSET_ACI_EVT_CMD_RSP_PARAMS_DTM_CMD_T_EVT_MSB 0 + #define OFFSET_ACI_EVT_CMD_RSP_PARAMS_DTM_CMD_T_EVT_LSB 1 + #define OFFSET_ACI_EVT_CMD_RSP_READ_DYNAMIC_DATA_T_SEQ_NO 0 + #define OFFSET_ACI_EVT_CMD_RSP_READ_DYNAMIC_DATA_T_DYNAMIC_DATA 1 + #define OFFSET_ACI_EVT_CMD_RSP_PARAMS_GET_DEVICE_VERSION_T_CONFIGURATION_ID_LSB 0 + #define OFFSET_ACI_EVT_CMD_RSP_PARAMS_GET_DEVICE_VERSION_T_CONFIGURATION_ID_MSB 1 + #define OFFSET_ACI_EVT_CMD_RSP_PARAMS_GET_DEVICE_VERSION_T_ACI_VERSION 2 + #define OFFSET_ACI_EVT_CMD_RSP_PARAMS_GET_DEVICE_VERSION_T_SETUP_FORMAT 3 + #define OFFSET_ACI_EVT_CMD_RSP_PARAMS_GET_DEVICE_VERSION_T_SETUP_ID_LSB0 4 + #define OFFSET_ACI_EVT_CMD_RSP_PARAMS_GET_DEVICE_VERSION_T_SETUP_ID_LSB1 5 + #define OFFSET_ACI_EVT_CMD_RSP_PARAMS_GET_DEVICE_VERSION_T_SETUP_ID_MSB0 6 + #define OFFSET_ACI_EVT_CMD_RSP_PARAMS_GET_DEVICE_VERSION_T_SETUP_ID_MSB1 7 + #define OFFSET_ACI_EVT_CMD_RSP_PARAMS_GET_DEVICE_VERSION_T_SETUP_STATUS 8 + #define OFFSET_ACI_EVT_CMD_RSP_PARAMS_GET_DEVICE_ADDRESS_T_BD_ADDR_OWN 0 + #define OFFSET_ACI_EVT_CMD_RSP_PARAMS_GET_DEVICE_ADDRESS_T_BD_ADDR_TYPE 6 + #define OFFSET_ACI_EVT_CMD_RSP_PARAMS_GET_BATTERY_LEVEL_T_BATTERY_LEVEL_LSB 0 + #define OFFSET_ACI_EVT_CMD_RSP_PARAMS_GET_BATTERY_LEVEL_T_BATTERY_LEVEL_MSB 1 + #define OFFSET_ACI_EVT_CMD_RSP_PARAMS_GET_TEMPERATURE_T_TEMPERATURE_VALUE_LSB 0 + #define OFFSET_ACI_EVT_CMD_RSP_PARAMS_GET_TEMPERATURE_T_TEMPERATURE_VALUE_MSB 1 + #define OFFSET_ACI_EVT_PARAMS_CMD_RSP_T_CMD_OPCODE 0 + #define OFFSET_ACI_EVT_PARAMS_CMD_RSP_T_CMD_STATUS 1 + #define OFFSET_ACI_EVT_PARAMS_CMD_RSP_T_DTM_CMD 2 + #define OFFSET_ACI_EVT_PARAMS_CMD_RSP_T_READ_DYNAMIC_DATA 2 + #define OFFSET_ACI_EVT_PARAMS_CMD_RSP_T_GET_DEVICE_VERSION 2 + #define OFFSET_ACI_EVT_PARAMS_CMD_RSP_T_GET_DEVICE_ADDRESS 2 + #define OFFSET_ACI_EVT_PARAMS_CMD_RSP_T_GET_BATTERY_LEVEL 2 + #define OFFSET_ACI_EVT_PARAMS_CMD_RSP_T_GET_TEMPERATURE 2 + #define OFFSET_ACI_EVT_PARAMS_CONNECTED_T_DEV_ADDR_TYPE 0 + #define OFFSET_ACI_EVT_PARAMS_CONNECTED_T_DEV_ADDR 1 + #define OFFSET_ACI_EVT_PARAMS_CONNECTED_T_CONN_RF_INTERVAL_LSB 7 + #define OFFSET_ACI_EVT_PARAMS_CONNECTED_T_CONN_RF_INTERVAL_MSB 8 + #define OFFSET_ACI_EVT_PARAMS_CONNECTED_T_CONN_SLAVE_RF_LATENCY_LSB 9 + #define OFFSET_ACI_EVT_PARAMS_CONNECTED_T_CONN_SLAVE_RF_LATENCY_MSB 10 + #define OFFSET_ACI_EVT_PARAMS_CONNECTED_T_CONN_RF_TIMEOUT_LSB 11 + #define OFFSET_ACI_EVT_PARAMS_CONNECTED_T_CONN_RF_TIMEOUT_MSB 12 + #define OFFSET_ACI_EVT_PARAMS_CONNECTED_T_MASTER_CLOCK_ACCURACY 13 + #define OFFSET_ACI_EVT_PARAMS_DISCONNECTED_T_ACI_STATUS 0 + #define OFFSET_ACI_EVT_PARAMS_DISCONNECTED_T_BTLE_STATUS 1 + #define OFFSET_ACI_EVT_PARAMS_BOND_STATUS_T_STATUS_CODE 0 + #define OFFSET_ACI_EVT_PARAMS_BOND_STATUS_T_STATUS_SOURCE 1 + #define OFFSET_ACI_EVT_PARAMS_BOND_STATUS_T_SECMODE1_BITMAP 2 + #define OFFSET_ACI_EVT_PARAMS_BOND_STATUS_T_SECMODE2_BITMAP 3 + #define OFFSET_ACI_EVT_PARAMS_BOND_STATUS_T_KEYS_EXCHANGED_SLAVE 4 + #define OFFSET_ACI_EVT_PARAMS_BOND_STATUS_T_KEYS_EXCHANGED_MASTER 5 + #define OFFSET_ACI_EVT_PARAMS_PIPE_STATUS_T_PIPES_OPEN_BITMAP 0 + #define OFFSET_ACI_EVT_PARAMS_PIPE_STATUS_T_PIPES_CLOSED_BITMAP 8 + #define OFFSET_ACI_EVT_PARAMS_TIMING_T_CONN_RF_INTERVAL_LSB 0 + #define OFFSET_ACI_EVT_PARAMS_TIMING_T_CONN_RF_INTERVAL_MSB 1 + #define OFFSET_ACI_EVT_PARAMS_TIMING_T_CONN_SLAVE_RF_LATENCY_LSB 2 + #define OFFSET_ACI_EVT_PARAMS_TIMING_T_CONN_SLAVE_RF_LATENCY_MSB 3 + #define OFFSET_ACI_EVT_PARAMS_TIMING_T_CONN_RF_TIMEOUT_LSB 4 + #define OFFSET_ACI_EVT_PARAMS_TIMING_T_CONN_RF_TIMEOUT_MSB 5 + #define OFFSET_ACI_EVT_PARAMS_DATA_CREDIT_T_CREDIT 0 + #define OFFSET_ACI_EVT_PARAMS_DATA_ACK_T_PIPE_NUMBER 0 + #define OFFSET_ACI_EVT_PARAMS_DATA_RECEIVED_T_RX_DATA 0 + #define OFFSET_ERROR_DATA_T_CONTENT 0 + #define OFFSET_ACI_EVT_PARAMS_PIPE_ERROR_T_PIPE_NUMBER 0 + #define OFFSET_ACI_EVT_PARAMS_PIPE_ERROR_T_ERROR_CODE 1 + #define OFFSET_ACI_EVT_PARAMS_PIPE_ERROR_T_ERROR_DATA 2 + #define OFFSET_ACI_EVT_PARAMS_DISPLAY_PASSKEY_T_PASSKEY 0 + #define OFFSET_ACI_EVT_PARAMS_KEY_REQUEST_T_KEY_TYPE 0 + #define OFFSET_ACI_EVT_T_LEN 0 + #define OFFSET_ACI_EVT_T_EVT_OPCODE 1 + #define OFFSET_ACI_EVT_T_DEVICE_STARTED 2 + #define OFFSET_ACI_EVT_T_HW_ERROR 2 + #define OFFSET_ACI_EVT_T_CMD_RSP 2 + #define OFFSET_ACI_EVT_T_CONNECTED 2 + #define OFFSET_ACI_EVT_T_DISCONNECTED 2 + #define OFFSET_ACI_EVT_T_BOND_STATUS 2 + #define OFFSET_ACI_EVT_T_PIPE_STATUS 2 + #define OFFSET_ACI_EVT_T_TIMING 2 + #define OFFSET_ACI_EVT_T_DATA_CREDIT 2 + #define OFFSET_ACI_EVT_T_DATA_ACK 2 + #define OFFSET_ACI_EVT_T_DATA_RECEIVED 2 + #define OFFSET_ACI_EVT_T_PIPE_ERROR 2 + #define OFFSET_ACI_EVT_T_DISPLAY_PASSKEY 2 + #define OFFSET_ACI_EVT_T_KEY_REQUEST 2 + +#endif //ACI_OFFSET_H__ + diff --git a/src/nrf8001/aci_queue.cpp b/src/nrf8001/aci_queue.cpp index 63ac0f8b..86b85498 100644 --- a/src/nrf8001/aci_queue.cpp +++ b/src/nrf8001/aci_queue.cpp @@ -1,201 +1,201 @@ -/* Copyright (c) 2014, Nordic Semiconductor ASA - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - - /** @file -@brief Implementation of a circular queue for ACI data -*/ - -#include "hal_aci_tl.h" -#include "aci_queue.h" - -void aci_queue_init(aci_queue_t *aci_q) -{ - uint8_t loop; - - // ble_assert(NULL != aci_q); - - aci_q->head = 0; - aci_q->tail = 0; - for(loop=0; loopaci_data[loop].buffer[0] = 0x00; - aci_q->aci_data[loop].buffer[1] = 0x00; - } -} - -bool aci_queue_dequeue(aci_queue_t *aci_q, hal_aci_data_t *p_data) -{ - // ble_assert(NULL != aci_q); - // ble_assert(NULL != p_data); - - if (aci_queue_is_empty(aci_q)) - { - return false; - } - - memcpy((uint8_t *)p_data, (uint8_t *)&(aci_q->aci_data[aci_q->head]), sizeof(hal_aci_data_t)); - aci_q->head = (aci_q->head + 1) % ACI_QUEUE_SIZE; - - return true; -} - -bool aci_queue_dequeue_from_isr(aci_queue_t *aci_q, hal_aci_data_t *p_data) -{ - // ble_assert(NULL != aci_q); - // ble_assert(NULL != p_data); - - if (aci_queue_is_empty_from_isr(aci_q)) - { - return false; - } - - memcpy((uint8_t *)p_data, (uint8_t *)&(aci_q->aci_data[aci_q->head]), sizeof(hal_aci_data_t)); - aci_q->head = (aci_q->head + 1) % ACI_QUEUE_SIZE; - - return true; -} - -bool aci_queue_enqueue(aci_queue_t *aci_q, hal_aci_data_t *p_data) -{ - const uint8_t length = p_data->buffer[0]; - - // ble_assert(NULL != aci_q); - // ble_assert(NULL != p_data); - - if (aci_queue_is_full(aci_q)) - { - return false; - } - - aci_q->aci_data[aci_q->tail].status_byte = 0; - memcpy((uint8_t *)&(aci_q->aci_data[aci_q->tail].buffer[0]), (uint8_t *)&p_data->buffer[0], length + 1); - aci_q->tail = (aci_q->tail + 1) % ACI_QUEUE_SIZE; - - return true; -} - -bool aci_queue_enqueue_from_isr(aci_queue_t *aci_q, hal_aci_data_t *p_data) -{ - const uint8_t length = p_data->buffer[0]; - - // ble_assert(NULL != aci_q); - // ble_assert(NULL != p_data); - - if (aci_queue_is_full_from_isr(aci_q)) - { - return false; - } - - aci_q->aci_data[aci_q->tail].status_byte = 0; - memcpy((uint8_t *)&(aci_q->aci_data[aci_q->tail].buffer[0]), (uint8_t *)&p_data->buffer[0], length + 1); - aci_q->tail = (aci_q->tail + 1) % ACI_QUEUE_SIZE; - - return true; -} - -bool aci_queue_is_empty(aci_queue_t *aci_q) -{ - bool state = false; - - // ble_assert(NULL != aci_q); - - //Critical section - // noInterrupts(); - if (aci_q->head == aci_q->tail) - { - state = true; - } - // interrupts(); - - return state; -} - -bool aci_queue_is_empty_from_isr(aci_queue_t *aci_q) -{ - // ble_assert(NULL != aci_q); - - return aci_q->head == aci_q->tail; -} - -bool aci_queue_is_full(aci_queue_t *aci_q) -{ - uint8_t next; - bool state; - - // ble_assert(NULL != aci_q); - - //This should be done in a critical section - // noInterrupts(); - next = (aci_q->tail + 1) % ACI_QUEUE_SIZE; - - if (next == aci_q->head) - { - state = true; - } - else - { - state = false; - } - - // interrupts(); - //end - - return state; -} - -bool aci_queue_is_full_from_isr(aci_queue_t *aci_q) -{ - const uint8_t next = (aci_q->tail + 1) % ACI_QUEUE_SIZE; - - // ble_assert(NULL != aci_q); - - return next == aci_q->head; -} - -bool aci_queue_peek(aci_queue_t *aci_q, hal_aci_data_t *p_data) -{ - // ble_assert(NULL != aci_q); - // ble_assert(NULL != p_data); - - if (aci_queue_is_empty(aci_q)) - { - return false; - } - - memcpy((uint8_t *)p_data, (uint8_t *)&(aci_q->aci_data[aci_q->head]), sizeof(hal_aci_data_t)); - - return true; -} - -bool aci_queue_peek_from_isr(aci_queue_t *aci_q, hal_aci_data_t *p_data) -{ - // ble_assert(NULL != aci_q); - // ble_assert(NULL != p_data); - - if (aci_queue_is_empty_from_isr(aci_q)) - { - return false; - } - - memcpy((uint8_t *)p_data, (uint8_t *)&(aci_q->aci_data[aci_q->head]), sizeof(hal_aci_data_t)); - - return true; -} +/* Copyright (c) 2014, Nordic Semiconductor ASA + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + /** @file +@brief Implementation of a circular queue for ACI data +*/ + +#include "hal_aci_tl.h" +#include "aci_queue.h" + +void aci_queue_init(aci_queue_t *aci_q) +{ + uint8_t loop; + + // ble_assert(NULL != aci_q); + + aci_q->head = 0; + aci_q->tail = 0; + for(loop=0; loopaci_data[loop].buffer[0] = 0x00; + aci_q->aci_data[loop].buffer[1] = 0x00; + } +} + +bool aci_queue_dequeue(aci_queue_t *aci_q, hal_aci_data_t *p_data) +{ + // ble_assert(NULL != aci_q); + // ble_assert(NULL != p_data); + + if (aci_queue_is_empty(aci_q)) + { + return false; + } + + memcpy((uint8_t *)p_data, (uint8_t *)&(aci_q->aci_data[aci_q->head]), sizeof(hal_aci_data_t)); + aci_q->head = (aci_q->head + 1) % ACI_QUEUE_SIZE; + + return true; +} + +bool aci_queue_dequeue_from_isr(aci_queue_t *aci_q, hal_aci_data_t *p_data) +{ + // ble_assert(NULL != aci_q); + // ble_assert(NULL != p_data); + + if (aci_queue_is_empty_from_isr(aci_q)) + { + return false; + } + + memcpy((uint8_t *)p_data, (uint8_t *)&(aci_q->aci_data[aci_q->head]), sizeof(hal_aci_data_t)); + aci_q->head = (aci_q->head + 1) % ACI_QUEUE_SIZE; + + return true; +} + +bool aci_queue_enqueue(aci_queue_t *aci_q, hal_aci_data_t *p_data) +{ + const uint8_t length = p_data->buffer[0]; + + // ble_assert(NULL != aci_q); + // ble_assert(NULL != p_data); + + if (aci_queue_is_full(aci_q)) + { + return false; + } + + aci_q->aci_data[aci_q->tail].status_byte = 0; + memcpy((uint8_t *)&(aci_q->aci_data[aci_q->tail].buffer[0]), (uint8_t *)&p_data->buffer[0], length + 1); + aci_q->tail = (aci_q->tail + 1) % ACI_QUEUE_SIZE; + + return true; +} + +bool aci_queue_enqueue_from_isr(aci_queue_t *aci_q, hal_aci_data_t *p_data) +{ + const uint8_t length = p_data->buffer[0]; + + // ble_assert(NULL != aci_q); + // ble_assert(NULL != p_data); + + if (aci_queue_is_full_from_isr(aci_q)) + { + return false; + } + + aci_q->aci_data[aci_q->tail].status_byte = 0; + memcpy((uint8_t *)&(aci_q->aci_data[aci_q->tail].buffer[0]), (uint8_t *)&p_data->buffer[0], length + 1); + aci_q->tail = (aci_q->tail + 1) % ACI_QUEUE_SIZE; + + return true; +} + +bool aci_queue_is_empty(aci_queue_t *aci_q) +{ + bool state = false; + + // ble_assert(NULL != aci_q); + + //Critical section + // noInterrupts(); + if (aci_q->head == aci_q->tail) + { + state = true; + } + // interrupts(); + + return state; +} + +bool aci_queue_is_empty_from_isr(aci_queue_t *aci_q) +{ + // ble_assert(NULL != aci_q); + + return aci_q->head == aci_q->tail; +} + +bool aci_queue_is_full(aci_queue_t *aci_q) +{ + uint8_t next; + bool state; + + // ble_assert(NULL != aci_q); + + //This should be done in a critical section + // noInterrupts(); + next = (aci_q->tail + 1) % ACI_QUEUE_SIZE; + + if (next == aci_q->head) + { + state = true; + } + else + { + state = false; + } + + // interrupts(); + //end + + return state; +} + +bool aci_queue_is_full_from_isr(aci_queue_t *aci_q) +{ + const uint8_t next = (aci_q->tail + 1) % ACI_QUEUE_SIZE; + + // ble_assert(NULL != aci_q); + + return next == aci_q->head; +} + +bool aci_queue_peek(aci_queue_t *aci_q, hal_aci_data_t *p_data) +{ + // ble_assert(NULL != aci_q); + // ble_assert(NULL != p_data); + + if (aci_queue_is_empty(aci_q)) + { + return false; + } + + memcpy((uint8_t *)p_data, (uint8_t *)&(aci_q->aci_data[aci_q->head]), sizeof(hal_aci_data_t)); + + return true; +} + +bool aci_queue_peek_from_isr(aci_queue_t *aci_q, hal_aci_data_t *p_data) +{ + // ble_assert(NULL != aci_q); + // ble_assert(NULL != p_data); + + if (aci_queue_is_empty_from_isr(aci_q)) + { + return false; + } + + memcpy((uint8_t *)p_data, (uint8_t *)&(aci_q->aci_data[aci_q->head]), sizeof(hal_aci_data_t)); + + return true; +} diff --git a/src/nrf8001/aci_queue.h b/src/nrf8001/aci_queue.h index 4d95e2aa..564b8dc1 100644 --- a/src/nrf8001/aci_queue.h +++ b/src/nrf8001/aci_queue.h @@ -1,76 +1,76 @@ -/* Copyright (c) 2014, Nordic Semiconductor ASA - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -/** - * @file - * @brief Interface for buffer. - * @ingroup aci - */ - -/** -@{ -*/ - -#ifndef ACI_QUEUE_H__ -#define ACI_QUEUE_H__ - -#include "aci.h" -#include "hal_aci_tl.h" - -/*********************************************************************** */ -/* The ACI_QUEUE_SIZE determines the memory usage of the system. */ -/* Successfully tested to a ACI_QUEUE_SIZE of 4 (interrupt) and 4 (polling) */ -/*********************************************************************** */ -#define ACI_QUEUE_SIZE 4 - -/** Data type for queue of data packets to send/receive from radio. - * - * A FIFO queue is maintained for packets. New packets are added (enqueued) - * at the tail and taken (dequeued) from the head. The head variable is the - * index of the next packet to dequeue while the tail variable is the index of - * where the next packet should be queued. - */ - -typedef struct { - hal_aci_data_t aci_data[ACI_QUEUE_SIZE]; - uint8_t head; - uint8_t tail; -} aci_queue_t; - -void aci_queue_init(aci_queue_t *aci_q); - -bool aci_queue_dequeue(aci_queue_t *aci_q, hal_aci_data_t *p_data); -bool aci_queue_dequeue_from_isr(aci_queue_t *aci_q, hal_aci_data_t *p_data); - -bool aci_queue_enqueue(aci_queue_t *aci_q, hal_aci_data_t *p_data); -bool aci_queue_enqueue_from_isr(aci_queue_t *aci_q, hal_aci_data_t *p_data); - -bool aci_queue_is_empty(aci_queue_t *aci_q); -bool aci_queue_is_empty_from_isr(aci_queue_t *aci_q); - -bool aci_queue_is_full(aci_queue_t *aci_q); -bool aci_queue_is_full_from_isr(aci_queue_t *aci_q); - -bool aci_queue_peek(aci_queue_t *aci_q, hal_aci_data_t *p_data); -bool aci_queue_peek_from_isr(aci_queue_t *aci_q, hal_aci_data_t *p_data); - -#endif /* ACI_QUEUE_H__ */ -/** @} */ +/* Copyright (c) 2014, Nordic Semiconductor ASA + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/** + * @file + * @brief Interface for buffer. + * @ingroup aci + */ + +/** +@{ +*/ + +#ifndef ACI_QUEUE_H__ +#define ACI_QUEUE_H__ + +#include "aci.h" +#include "hal_aci_tl.h" + +/*********************************************************************** */ +/* The ACI_QUEUE_SIZE determines the memory usage of the system. */ +/* Successfully tested to a ACI_QUEUE_SIZE of 4 (interrupt) and 4 (polling) */ +/*********************************************************************** */ +#define ACI_QUEUE_SIZE 4 + +/** Data type for queue of data packets to send/receive from radio. + * + * A FIFO queue is maintained for packets. New packets are added (enqueued) + * at the tail and taken (dequeued) from the head. The head variable is the + * index of the next packet to dequeue while the tail variable is the index of + * where the next packet should be queued. + */ + +typedef struct { + hal_aci_data_t aci_data[ACI_QUEUE_SIZE]; + uint8_t head; + uint8_t tail; +} aci_queue_t; + +void aci_queue_init(aci_queue_t *aci_q); + +bool aci_queue_dequeue(aci_queue_t *aci_q, hal_aci_data_t *p_data); +bool aci_queue_dequeue_from_isr(aci_queue_t *aci_q, hal_aci_data_t *p_data); + +bool aci_queue_enqueue(aci_queue_t *aci_q, hal_aci_data_t *p_data); +bool aci_queue_enqueue_from_isr(aci_queue_t *aci_q, hal_aci_data_t *p_data); + +bool aci_queue_is_empty(aci_queue_t *aci_q); +bool aci_queue_is_empty_from_isr(aci_queue_t *aci_q); + +bool aci_queue_is_full(aci_queue_t *aci_q); +bool aci_queue_is_full_from_isr(aci_queue_t *aci_q); + +bool aci_queue_peek(aci_queue_t *aci_q, hal_aci_data_t *p_data); +bool aci_queue_peek_from_isr(aci_queue_t *aci_q, hal_aci_data_t *p_data); + +#endif /* ACI_QUEUE_H__ */ +/** @} */ diff --git a/src/nrf8001/aci_setup.cpp b/src/nrf8001/aci_setup.cpp index dca6d4ed..810c70f0 100644 --- a/src/nrf8001/aci_setup.cpp +++ b/src/nrf8001/aci_setup.cpp @@ -1,177 +1,177 @@ -/* Copyright (c) 2014, Nordic Semiconductor ASA - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - - -#include "aci.h" -#include "hal_aci_tl.h" -#include -#include "aci_setup.h" - - -// aci_struct that will contain -// total initial credits -// current credit -// current state of the aci (setup/standby/active/sleep) -// open remote pipe pending -// close remote pipe pending -// Current pipe available bitmap -// Current pipe closed bitmap -// Current connection interval, slave latency and link supervision timeout -// Current State of the the GATT client (Service Discovery status) - - -// hal_aci_data_t msg_to_send; -extern hal_aci_data_t msg_to_send; - - -/************************************************************************** */ -/* Utility function to fill the the ACI command queue */ -/* aci_stat Pointer to the ACI state */ -/* num_cmd_offset(in/out) Offset in the Setup message array to start from */ -/* offset is updated to the new index after the queue is filled */ -/* or the last message us placed in the queue */ -/* Returns true if at least one message was transferred */ -/***************************************************************************/ -bool aci_setup_fill(aci_state_t *aci_stat, uint8_t *num_cmd_offset) -{ - bool ret_val = false; - - while (*num_cmd_offset < aci_stat->aci_setup_info.num_setup_msgs) - { - //Board dependent defines - /*#if defined (__AVR__) - //For Arduino copy the setup ACI message from Flash to RAM. - memcpy_P(&msg_to_send, &(aci_stat->aci_setup_info.setup_msgs[*num_cmd_offset]), - pgm_read_byte_near(&(aci_stat->aci_setup_info.setup_msgs[*num_cmd_offset].buffer[0]))+2); - #elif defined(__PIC32MX__) - //In ChipKit we store the setup messages in RAM - //Add 2 bytes to the length byte for status byte, length for the total number of bytes - memcpy(&msg_to_send, &(aci_stat->aci_setup_info.setup_msgs[*num_cmd_offset]), - (aci_stat->aci_setup_info.setup_msgs[*num_cmd_offset].buffer[0]+2)); - #endif*/ - - memcpy(&msg_to_send, &(aci_stat->aci_setup_info.setup_msgs[*num_cmd_offset]), - (aci_stat->aci_setup_info.setup_msgs[*num_cmd_offset].buffer[0]+2)); - - //Put the Setup ACI message in the command queue - if (!hal_aci_tl_send(&msg_to_send)) - { - //ACI Command Queue is full - // *num_cmd_offset is now pointing to the index of the Setup command that did not get sent - return ret_val; - } - - ret_val = true; - - (*num_cmd_offset)++; - } - - return ret_val; -} - -uint8_t do_aci_setup(aci_state_t *aci_stat) -{ - uint8_t setup_offset = 0; - uint32_t i = 0x0000; - aci_evt_t * aci_evt = NULL; - aci_status_code_t cmd_status = ACI_STATUS_ERROR_CRC_MISMATCH; - - /* - We are using the same buffer since we are copying the contents of the buffer - when queuing and immediately processing the buffer when receiving - */ - hal_aci_evt_t *aci_data = (hal_aci_evt_t *)&msg_to_send; - - /* Messages in the outgoing queue must be handled before the Setup routine can run. - * If it is non-empty we return. The user should then process the messages before calling - * do_aci_setup() again. - */ - if (!lib_aci_command_queue_empty()) - { - return SETUP_FAIL_COMMAND_QUEUE_NOT_EMPTY; - } - - /* If there are events pending from the device that are not relevant to setup, we return false - * so that the user can handle them. At this point we don't care what the event is, - * as any event is an error. - */ - if (lib_aci_event_peek(aci_data)) - { - return SETUP_FAIL_EVENT_QUEUE_NOT_EMPTY; - } - - /* Fill the ACI command queue with as many Setup messages as it will hold. */ - aci_setup_fill(aci_stat, &setup_offset); - - while (cmd_status != ACI_STATUS_TRANSACTION_COMPLETE) - { - /* This counter is used to ensure that this function does not loop forever. When the device - * returns a valid response, we reset the counter. - */ - if (i++ > 0xFFFFE) - { - return SETUP_FAIL_TIMEOUT; - } - - if (lib_aci_event_peek(aci_data)) - { - aci_evt = &(aci_data->evt); - - if (ACI_EVT_CMD_RSP != aci_evt->evt_opcode) - { - //Receiving something other than a Command Response Event is an error. - return SETUP_FAIL_NOT_COMMAND_RESPONSE; - } - - cmd_status = (aci_status_code_t) aci_evt->params.cmd_rsp.cmd_status; - switch (cmd_status) - { - case ACI_STATUS_TRANSACTION_CONTINUE: - //As the device is responding, reset guard counter - i = 0; - - /* As the device has processed the Setup messages we put in the command queue earlier, - * we can proceed to fill the queue with new messages - */ - aci_setup_fill(aci_stat, &setup_offset); - break; - - case ACI_STATUS_TRANSACTION_COMPLETE: - //Break out of the while loop when this status code appears - break; - - default: - //An event with any other status code should be handled by the application - return SETUP_FAIL_NOT_SETUP_EVENT; - } - - /* If we haven't returned at this point, the event was either ACI_STATUS_TRANSACTION_CONTINUE - * or ACI_STATUS_TRANSACTION_COMPLETE. We don't need the event itself, so we simply - * remove it from the queue. - */ - lib_aci_event_get (aci_stat, aci_data); - } - } - - return SETUP_SUCCESS; -} - - +/* Copyright (c) 2014, Nordic Semiconductor ASA + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + +#include "aci.h" +#include "hal_aci_tl.h" +#include +#include "aci_setup.h" + + +// aci_struct that will contain +// total initial credits +// current credit +// current state of the aci (setup/standby/active/sleep) +// open remote pipe pending +// close remote pipe pending +// Current pipe available bitmap +// Current pipe closed bitmap +// Current connection interval, slave latency and link supervision timeout +// Current State of the the GATT client (Service Discovery status) + + +// hal_aci_data_t msg_to_send; +extern hal_aci_data_t msg_to_send; + + +/************************************************************************** */ +/* Utility function to fill the the ACI command queue */ +/* aci_stat Pointer to the ACI state */ +/* num_cmd_offset(in/out) Offset in the Setup message array to start from */ +/* offset is updated to the new index after the queue is filled */ +/* or the last message us placed in the queue */ +/* Returns true if at least one message was transferred */ +/***************************************************************************/ +bool aci_setup_fill(aci_state_t *aci_stat, uint8_t *num_cmd_offset) +{ + bool ret_val = false; + + while (*num_cmd_offset < aci_stat->aci_setup_info.num_setup_msgs) + { + //Board dependent defines + /*#if defined (__AVR__) + //For Arduino copy the setup ACI message from Flash to RAM. + memcpy_P(&msg_to_send, &(aci_stat->aci_setup_info.setup_msgs[*num_cmd_offset]), + pgm_read_byte_near(&(aci_stat->aci_setup_info.setup_msgs[*num_cmd_offset].buffer[0]))+2); + #elif defined(__PIC32MX__) + //In ChipKit we store the setup messages in RAM + //Add 2 bytes to the length byte for status byte, length for the total number of bytes + memcpy(&msg_to_send, &(aci_stat->aci_setup_info.setup_msgs[*num_cmd_offset]), + (aci_stat->aci_setup_info.setup_msgs[*num_cmd_offset].buffer[0]+2)); + #endif*/ + + memcpy(&msg_to_send, &(aci_stat->aci_setup_info.setup_msgs[*num_cmd_offset]), + (aci_stat->aci_setup_info.setup_msgs[*num_cmd_offset].buffer[0]+2)); + + //Put the Setup ACI message in the command queue + if (!hal_aci_tl_send(&msg_to_send)) + { + //ACI Command Queue is full + // *num_cmd_offset is now pointing to the index of the Setup command that did not get sent + return ret_val; + } + + ret_val = true; + + (*num_cmd_offset)++; + } + + return ret_val; +} + +uint8_t do_aci_setup(aci_state_t *aci_stat) +{ + uint8_t setup_offset = 0; + uint32_t i = 0x0000; + aci_evt_t * aci_evt = NULL; + aci_status_code_t cmd_status = ACI_STATUS_ERROR_CRC_MISMATCH; + + /* + We are using the same buffer since we are copying the contents of the buffer + when queuing and immediately processing the buffer when receiving + */ + hal_aci_evt_t *aci_data = (hal_aci_evt_t *)&msg_to_send; + + /* Messages in the outgoing queue must be handled before the Setup routine can run. + * If it is non-empty we return. The user should then process the messages before calling + * do_aci_setup() again. + */ + if (!lib_aci_command_queue_empty()) + { + return SETUP_FAIL_COMMAND_QUEUE_NOT_EMPTY; + } + + /* If there are events pending from the device that are not relevant to setup, we return false + * so that the user can handle them. At this point we don't care what the event is, + * as any event is an error. + */ + if (lib_aci_event_peek(aci_data)) + { + return SETUP_FAIL_EVENT_QUEUE_NOT_EMPTY; + } + + /* Fill the ACI command queue with as many Setup messages as it will hold. */ + aci_setup_fill(aci_stat, &setup_offset); + + while (cmd_status != ACI_STATUS_TRANSACTION_COMPLETE) + { + /* This counter is used to ensure that this function does not loop forever. When the device + * returns a valid response, we reset the counter. + */ + if (i++ > 0xFFFFE) + { + return SETUP_FAIL_TIMEOUT; + } + + if (lib_aci_event_peek(aci_data)) + { + aci_evt = &(aci_data->evt); + + if (ACI_EVT_CMD_RSP != aci_evt->evt_opcode) + { + //Receiving something other than a Command Response Event is an error. + return SETUP_FAIL_NOT_COMMAND_RESPONSE; + } + + cmd_status = (aci_status_code_t) aci_evt->params.cmd_rsp.cmd_status; + switch (cmd_status) + { + case ACI_STATUS_TRANSACTION_CONTINUE: + //As the device is responding, reset guard counter + i = 0; + + /* As the device has processed the Setup messages we put in the command queue earlier, + * we can proceed to fill the queue with new messages + */ + aci_setup_fill(aci_stat, &setup_offset); + break; + + case ACI_STATUS_TRANSACTION_COMPLETE: + //Break out of the while loop when this status code appears + break; + + default: + //An event with any other status code should be handled by the application + return SETUP_FAIL_NOT_SETUP_EVENT; + } + + /* If we haven't returned at this point, the event was either ACI_STATUS_TRANSACTION_CONTINUE + * or ACI_STATUS_TRANSACTION_COMPLETE. We don't need the event itself, so we simply + * remove it from the queue. + */ + lib_aci_event_get (aci_stat, aci_data); + } + } + + return SETUP_SUCCESS; +} + + diff --git a/src/nrf8001/aci_setup.h b/src/nrf8001/aci_setup.h index 7f9a4206..d50438ff 100644 --- a/src/nrf8001/aci_setup.h +++ b/src/nrf8001/aci_setup.h @@ -1,50 +1,50 @@ -/* Copyright (c) 2014, Nordic Semiconductor ASA - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -/** - * @file - * @brief ACI setup functions - * @ingroup aci - */ - -#ifndef H_ACI_SETUP -#define H_ACI_SETUP - -#define SETUP_SUCCESS 0 -#define SETUP_FAIL_COMMAND_QUEUE_NOT_EMPTY 1 -#define SETUP_FAIL_EVENT_QUEUE_NOT_EMPTY 2 -#define SETUP_FAIL_TIMEOUT 3 -#define SETUP_FAIL_NOT_SETUP_EVENT 4 -#define SETUP_FAIL_NOT_COMMAND_RESPONSE 5 - -bool aci_setup_fill(aci_state_t *aci_stat, uint8_t *num_cmd_offset); -/** @brief Setup the nRF8001 device - * @details - * Performs ACI Setup by transmitting the setup messages generated by nRFgo Studio to the - * nRF8001, and should be called when the nRF8001 starts or resets. - * Once all messages are sent, the nRF8001 will send a Device Started Event. - * The function requires that the Command queue is empty when it is invoked, and will fail - * otherwise. - * @returns An integer indicating the reason the function terminated - */ -uint8_t do_aci_setup(aci_state_t *aci_stat); - -#endif +/* Copyright (c) 2014, Nordic Semiconductor ASA + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/** + * @file + * @brief ACI setup functions + * @ingroup aci + */ + +#ifndef H_ACI_SETUP +#define H_ACI_SETUP + +#define SETUP_SUCCESS 0 +#define SETUP_FAIL_COMMAND_QUEUE_NOT_EMPTY 1 +#define SETUP_FAIL_EVENT_QUEUE_NOT_EMPTY 2 +#define SETUP_FAIL_TIMEOUT 3 +#define SETUP_FAIL_NOT_SETUP_EVENT 4 +#define SETUP_FAIL_NOT_COMMAND_RESPONSE 5 + +bool aci_setup_fill(aci_state_t *aci_stat, uint8_t *num_cmd_offset); +/** @brief Setup the nRF8001 device + * @details + * Performs ACI Setup by transmitting the setup messages generated by nRFgo Studio to the + * nRF8001, and should be called when the nRF8001 starts or resets. + * Once all messages are sent, the nRF8001 will send a Device Started Event. + * The function requires that the Command queue is empty when it is invoked, and will fail + * otherwise. + * @returns An integer indicating the reason the function terminated + */ +uint8_t do_aci_setup(aci_state_t *aci_stat); + +#endif diff --git a/src/nrf8001/acilib.cpp b/src/nrf8001/acilib.cpp index 4e7f41f2..5dbb547f 100644 --- a/src/nrf8001/acilib.cpp +++ b/src/nrf8001/acilib.cpp @@ -1,610 +1,610 @@ -/* Copyright (c) 2014, Nordic Semiconductor ASA - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -/** - * @file - * - * @ingroup group_acilib - * - * @brief Implementation of the acilib module. - */ - - -#include "hal_platform.h" -#include "aci.h" -#include "aci_cmds.h" -#include "aci_evts.h" -#include "acilib.h" -#include "aci_protocol_defines.h" -#include "acilib_defs.h" -#include "acilib_if.h" -#include "acilib_types.h" - - -void acil_encode_cmd_set_test_mode(uint8_t *buffer, aci_cmd_params_test_t *p_aci_cmd_params_test) -{ - *(buffer + OFFSET_ACI_CMD_T_LEN) = 2; - *(buffer + OFFSET_ACI_CMD_T_CMD_OPCODE) = ACI_CMD_TEST; - *(buffer + OFFSET_ACI_CMD_T_TEST + OFFSET_ACI_CMD_PARAMS_TEST_T_TEST_MODE_CHANGE) = p_aci_cmd_params_test->test_mode_change; -} - -void acil_encode_cmd_sleep(uint8_t *buffer) -{ - *(buffer + OFFSET_ACI_CMD_T_LEN) = 1; - *(buffer + OFFSET_ACI_CMD_T_CMD_OPCODE) = ACI_CMD_SLEEP; -} - -void acil_encode_cmd_get_device_version(uint8_t *buffer) -{ - *(buffer + OFFSET_ACI_CMD_T_LEN) = 1; - *(buffer + OFFSET_ACI_CMD_T_CMD_OPCODE) = ACI_CMD_GET_DEVICE_VERSION; -} - -void acil_encode_cmd_set_local_data(uint8_t *buffer, aci_cmd_params_set_local_data_t *p_aci_cmd_params_set_local_data, uint8_t data_size) -{ - *(buffer + OFFSET_ACI_CMD_T_LEN) = MSG_SET_LOCAL_DATA_BASE_LEN + data_size; - *(buffer + OFFSET_ACI_CMD_T_CMD_OPCODE) = ACI_CMD_SET_LOCAL_DATA; - *(buffer + OFFSET_ACI_CMD_T_SET_LOCAL_DATA + OFFSET_ACI_CMD_PARAMS_SEND_DATA_T_TX_DATA + OFFSET_ACI_TX_DATA_T_PIPE_NUMBER) = p_aci_cmd_params_set_local_data->tx_data.pipe_number; - memcpy(buffer + OFFSET_ACI_CMD_T_SET_LOCAL_DATA + OFFSET_ACI_CMD_PARAMS_SEND_DATA_T_TX_DATA + OFFSET_ACI_TX_DATA_T_ACI_DATA, &(p_aci_cmd_params_set_local_data->tx_data.aci_data[0]), data_size); -} - -void acil_encode_cmd_connect(uint8_t *buffer, aci_cmd_params_connect_t *p_aci_cmd_params_connect) -{ - *(buffer + OFFSET_ACI_CMD_T_LEN) = MSG_CONNECT_LEN; - *(buffer + OFFSET_ACI_CMD_T_CMD_OPCODE) = ACI_CMD_CONNECT; - *(buffer + OFFSET_ACI_CMD_T_CONNECT + OFFSET_ACI_CMD_PARAMS_CONNECT_T_TIMEOUT_MSB) = (uint8_t)(p_aci_cmd_params_connect->timeout >> 8); - *(buffer + OFFSET_ACI_CMD_T_CONNECT + OFFSET_ACI_CMD_PARAMS_CONNECT_T_TIMEOUT_LSB) = (uint8_t)(p_aci_cmd_params_connect->timeout); - *(buffer + OFFSET_ACI_CMD_T_CONNECT + OFFSET_ACI_CMD_PARAMS_CONNECT_T_ADV_INTERVAL_MSB) = (uint8_t)(p_aci_cmd_params_connect->adv_interval >> 8); - *(buffer + OFFSET_ACI_CMD_T_CONNECT + OFFSET_ACI_CMD_PARAMS_CONNECT_T_ADV_INTERVAL_LSB) = (uint8_t)(p_aci_cmd_params_connect->adv_interval); -} - -void acil_encode_cmd_bond(uint8_t *buffer, aci_cmd_params_bond_t *p_aci_cmd_params_bond) -{ - *(buffer + OFFSET_ACI_CMD_T_LEN) = MSG_BOND_LEN; - *(buffer + OFFSET_ACI_CMD_T_CMD_OPCODE) = ACI_CMD_BOND; - *(buffer + OFFSET_ACI_CMD_T_BOND + OFFSET_ACI_CMD_PARAMS_BOND_T_TIMEOUT_MSB) = (uint8_t)(p_aci_cmd_params_bond->timeout >> 8); - *(buffer + OFFSET_ACI_CMD_T_BOND + OFFSET_ACI_CMD_PARAMS_BOND_T_TIMEOUT_LSB) = (uint8_t)(p_aci_cmd_params_bond->timeout); - *(buffer + OFFSET_ACI_CMD_T_BOND + OFFSET_ACI_CMD_PARAMS_BOND_T_ADV_INTERVAL_MSB) = (uint8_t)(p_aci_cmd_params_bond->adv_interval >> 8); - *(buffer + OFFSET_ACI_CMD_T_BOND + OFFSET_ACI_CMD_PARAMS_BOND_T_ADV_INTERVAL_LSB) = (uint8_t)(p_aci_cmd_params_bond->adv_interval); -} - -void acil_encode_cmd_disconnect(uint8_t *buffer, aci_cmd_params_disconnect_t *p_aci_cmd_params_disconnect) -{ - *(buffer + OFFSET_ACI_CMD_T_LEN) = MSG_DISCONNECT_LEN; - *(buffer + OFFSET_ACI_CMD_T_CMD_OPCODE) = ACI_CMD_DISCONNECT; - *(buffer + OFFSET_ACI_CMD_T_DISCONNECT + OFFSET_ACI_CMD_PARAMS_DISCONNECT_T_REASON) = (uint8_t)(p_aci_cmd_params_disconnect->reason); -} - -void acil_encode_baseband_reset(uint8_t *buffer) -{ - *(buffer + OFFSET_ACI_CMD_T_LEN) = MSG_BASEBAND_RESET_LEN; - *(buffer + OFFSET_ACI_CMD_T_CMD_OPCODE) = ACI_CMD_RADIO_RESET; -} - -void acil_encode_direct_connect(uint8_t *buffer) -{ - *(buffer + OFFSET_ACI_CMD_T_LEN) = MSG_DIRECT_CONNECT_LEN; - *(buffer + OFFSET_ACI_CMD_T_CMD_OPCODE) = ACI_CMD_CONNECT_DIRECT; -} - -void acil_encode_cmd_wakeup(uint8_t *buffer) -{ - *(buffer + OFFSET_ACI_CMD_T_LEN) = MSG_WAKEUP_LEN; - *(buffer + OFFSET_ACI_CMD_T_CMD_OPCODE) = ACI_CMD_WAKEUP; -} - -void acil_encode_cmd_set_radio_tx_power(uint8_t *buffer, aci_cmd_params_set_tx_power_t *p_aci_cmd_params_set_tx_power) -{ - *(buffer + OFFSET_ACI_CMD_T_LEN) = MSG_SET_RADIO_TX_POWER_LEN; - *(buffer + OFFSET_ACI_CMD_T_CMD_OPCODE) = ACI_CMD_SET_TX_POWER; - *(buffer + OFFSET_ACI_CMD_T_SET_TX_POWER + OFFSET_ACI_CMD_PARAMS_SET_TX_POWER_T_DEVICE_POWER) = (uint8_t)p_aci_cmd_params_set_tx_power->device_power; -} - -void acil_encode_cmd_get_address(uint8_t *buffer) -{ - *(buffer + OFFSET_ACI_CMD_T_LEN) = MSG_GET_DEVICE_ADDR_LEN; - *(buffer + OFFSET_ACI_CMD_T_CMD_OPCODE) = ACI_CMD_GET_DEVICE_ADDRESS; -} - -void acil_encode_cmd_send_data(uint8_t *buffer, aci_cmd_params_send_data_t *p_aci_cmd_params_send_data_t, uint8_t data_size) -{ - *(buffer + OFFSET_ACI_CMD_T_LEN) = MSG_SEND_DATA_BASE_LEN + data_size; - *(buffer + OFFSET_ACI_CMD_T_CMD_OPCODE) = ACI_CMD_SEND_DATA; - *(buffer + OFFSET_ACI_CMD_T_SEND_DATA + OFFSET_ACI_CMD_PARAMS_SEND_DATA_T_TX_DATA + OFFSET_ACI_TX_DATA_T_PIPE_NUMBER) = p_aci_cmd_params_send_data_t->tx_data.pipe_number; - memcpy((buffer + OFFSET_ACI_CMD_T_SEND_DATA + OFFSET_ACI_CMD_PARAMS_SEND_DATA_T_TX_DATA + OFFSET_ACI_TX_DATA_T_ACI_DATA), &(p_aci_cmd_params_send_data_t->tx_data.aci_data[0]), data_size); -} - -void acil_encode_cmd_request_data(uint8_t *buffer, aci_cmd_params_request_data_t *p_aci_cmd_params_request_data) -{ - *(buffer + OFFSET_ACI_CMD_T_LEN) = MSG_DATA_REQUEST_LEN; - *(buffer + OFFSET_ACI_CMD_T_CMD_OPCODE) = ACI_CMD_REQUEST_DATA; - *(buffer + OFFSET_ACI_CMD_T_REQUEST_DATA + OFFSET_ACI_CMD_PARAMS_REQUEST_DATA_T_PIPE_NUMBER) = p_aci_cmd_params_request_data->pipe_number; -} - -void acil_encode_cmd_open_remote_pipe(uint8_t *buffer, aci_cmd_params_open_remote_pipe_t *p_aci_cmd_params_open_remote_pipe) -{ - *(buffer + OFFSET_ACI_CMD_T_LEN) = MSG_OPEN_REMOTE_PIPE_LEN; - *(buffer + OFFSET_ACI_CMD_T_CMD_OPCODE) = ACI_CMD_OPEN_REMOTE_PIPE; - *(buffer + OFFSET_ACI_CMD_T_OPEN_REMOTE_PIPE + OFFSET_ACI_CMD_PARAMS_OPEN_REMOTE_PIPE_T_PIPE_NUMBER) = p_aci_cmd_params_open_remote_pipe->pipe_number; -} - -void acil_encode_cmd_close_remote_pipe(uint8_t *buffer, aci_cmd_params_close_remote_pipe_t *p_aci_cmd_params_close_remote_pipe) -{ - *(buffer + OFFSET_ACI_CMD_T_LEN) = MSG_CLOSE_REMOTE_PIPE_LEN; - *(buffer + OFFSET_ACI_CMD_T_CMD_OPCODE) = ACI_CMD_CLOSE_REMOTE_PIPE; - *(buffer + OFFSET_ACI_CMD_T_CLOSE_REMOTE_PIPE + OFFSET_ACI_CMD_PARAMS_CLOSE_REMOTE_PIPE_T_PIPE_NUMBER) = p_aci_cmd_params_close_remote_pipe->pipe_number; -} - -void acil_encode_cmd_echo_msg(uint8_t *buffer, aci_cmd_params_echo_t *p_cmd_params_echo, uint8_t msg_size) -{ - *(buffer + OFFSET_ACI_CMD_T_LEN) = MSG_ECHO_MSG_CMD_BASE_LEN + msg_size; - *(buffer + OFFSET_ACI_CMD_T_CMD_OPCODE) = ACI_CMD_ECHO; - memcpy((buffer + OFFSET_ACI_CMD_T_ECHO + OFFSET_ACI_CMD_PARAMS_ECHO_T_ECHO_DATA), &(p_cmd_params_echo->echo_data[0]), msg_size); -} - -void acil_encode_cmd_battery_level(uint8_t *buffer) -{ - *(buffer + OFFSET_ACI_CMD_T_LEN) = 1; - *(buffer + OFFSET_ACI_CMD_T_CMD_OPCODE) = ACI_CMD_GET_BATTERY_LEVEL; -} - -void acil_encode_cmd_temparature(uint8_t *buffer) -{ - *(buffer + OFFSET_ACI_CMD_T_LEN) = 1; - *(buffer + OFFSET_ACI_CMD_T_CMD_OPCODE) = ACI_CMD_GET_TEMPERATURE; -} - -void acil_encode_cmd_read_dynamic_data(uint8_t *buffer) -{ - *(buffer + OFFSET_ACI_CMD_T_LEN) = 1; - *(buffer + OFFSET_ACI_CMD_T_CMD_OPCODE) = ACI_CMD_READ_DYNAMIC_DATA; -} - -void acil_encode_cmd_write_dynamic_data(uint8_t *buffer, uint8_t seq_no, uint8_t* dynamic_data, uint8_t dynamic_data_size) -{ - *(buffer + OFFSET_ACI_CMD_T_LEN) = MSG_WRITE_DYNAMIC_DATA_BASE_LEN + dynamic_data_size; - *(buffer + OFFSET_ACI_CMD_T_CMD_OPCODE) = ACI_CMD_WRITE_DYNAMIC_DATA; - *(buffer + OFFSET_ACI_CMD_T_WRITE_DYNAMIC_DATA + OFFSET_ACI_CMD_PARAMS_WRITE_DYNAMIC_DATA_T_SEQ_NO) = seq_no; - memcpy((buffer + OFFSET_ACI_CMD_T_WRITE_DYNAMIC_DATA + OFFSET_ACI_CMD_PARAMS_WRITE_DYNAMIC_DATA_T_DYNAMIC_DATA), dynamic_data, dynamic_data_size); -} - -void acil_encode_cmd_change_timing_req(uint8_t *buffer, aci_cmd_params_change_timing_t *p_aci_cmd_params_change_timing) -{ - *(buffer + OFFSET_ACI_CMD_T_LEN) = MSG_CHANGE_TIMING_LEN; - *(buffer + OFFSET_ACI_CMD_T_CMD_OPCODE) = ACI_CMD_CHANGE_TIMING; - *(buffer + OFFSET_ACI_CMD_T_CHANGE_TIMING + OFFSET_ACI_CMD_PARAMS_CHANGE_TIMING_T_CONN_PARAMS + OFFSET_ACI_LL_CONN_PARAMS_T_MIN_CONN_INTERVAL_MSB) = (uint8_t)(p_aci_cmd_params_change_timing->conn_params.min_conn_interval >> 8); - *(buffer + OFFSET_ACI_CMD_T_CHANGE_TIMING + OFFSET_ACI_CMD_PARAMS_CHANGE_TIMING_T_CONN_PARAMS + OFFSET_ACI_LL_CONN_PARAMS_T_MIN_CONN_INTERVAL_LSB) = (uint8_t)(p_aci_cmd_params_change_timing->conn_params.min_conn_interval); - *(buffer + OFFSET_ACI_CMD_T_CHANGE_TIMING + OFFSET_ACI_CMD_PARAMS_CHANGE_TIMING_T_CONN_PARAMS + OFFSET_ACI_LL_CONN_PARAMS_T_MAX_CONN_INTERVAL_MSB) = (uint8_t)(p_aci_cmd_params_change_timing->conn_params.max_conn_interval >> 8); - *(buffer + OFFSET_ACI_CMD_T_CHANGE_TIMING + OFFSET_ACI_CMD_PARAMS_CHANGE_TIMING_T_CONN_PARAMS + OFFSET_ACI_LL_CONN_PARAMS_T_MAX_CONN_INTERVAL_LSB) = (uint8_t)(p_aci_cmd_params_change_timing->conn_params.max_conn_interval); - *(buffer + OFFSET_ACI_CMD_T_CHANGE_TIMING + OFFSET_ACI_CMD_PARAMS_CHANGE_TIMING_T_CONN_PARAMS + OFFSET_ACI_LL_CONN_PARAMS_T_SLAVE_LATENCY_MSB ) = (uint8_t)(p_aci_cmd_params_change_timing->conn_params.slave_latency >> 8); - *(buffer + OFFSET_ACI_CMD_T_CHANGE_TIMING + OFFSET_ACI_CMD_PARAMS_CHANGE_TIMING_T_CONN_PARAMS + OFFSET_ACI_LL_CONN_PARAMS_T_SLAVE_LATENCY_LSB ) = (uint8_t)(p_aci_cmd_params_change_timing->conn_params.slave_latency); - *(buffer + OFFSET_ACI_CMD_T_CHANGE_TIMING + OFFSET_ACI_CMD_PARAMS_CHANGE_TIMING_T_CONN_PARAMS + OFFSET_ACI_LL_CONN_PARAMS_T_TIMEOUT_MULT_MSB ) = (uint8_t)(p_aci_cmd_params_change_timing->conn_params.timeout_mult >> 8); - *(buffer + OFFSET_ACI_CMD_T_CHANGE_TIMING + OFFSET_ACI_CMD_PARAMS_CHANGE_TIMING_T_CONN_PARAMS + OFFSET_ACI_LL_CONN_PARAMS_T_TIMEOUT_MULT_LSB ) = (uint8_t)(p_aci_cmd_params_change_timing->conn_params.timeout_mult); -} - -void acil_encode_cmd_set_app_latency(uint8_t *buffer, aci_cmd_params_set_app_latency_t *p_aci_cmd_params_set_app_latency) -{ - *(buffer + OFFSET_ACI_CMD_T_LEN) = MSG_SET_APP_LATENCY_LEN; - *(buffer + OFFSET_ACI_CMD_T_CMD_OPCODE) = ACI_CMD_SET_APP_LATENCY; - *(buffer + OFFSET_ACI_CMD_T_SET_APP_LATENCY + OFFSET_ACI_CMD_PARAMS_SET_APP_LATENCY_T_MODE) = (uint8_t)( p_aci_cmd_params_set_app_latency->mode); - *(buffer + OFFSET_ACI_CMD_T_SET_APP_LATENCY + OFFSET_ACI_CMD_PARAMS_SET_APP_LATENCY_T_LATENCY_MSB) = (uint8_t)( p_aci_cmd_params_set_app_latency->latency>>8); - *(buffer + OFFSET_ACI_CMD_T_SET_APP_LATENCY + OFFSET_ACI_CMD_PARAMS_SET_APP_LATENCY_T_LATENCY_LSB) = (uint8_t)( p_aci_cmd_params_set_app_latency->latency); -} - -void acil_encode_cmd_change_timing_req_GAP_PPCP(uint8_t *buffer) -{ - *(buffer + OFFSET_ACI_CMD_T_LEN) = MSG_CHANGE_TIMING_LEN_GAP_PPCP; - *(buffer + OFFSET_ACI_CMD_T_CMD_OPCODE) = ACI_CMD_CHANGE_TIMING; -} - - -void acil_encode_cmd_setup(uint8_t *buffer, aci_cmd_params_setup_t *p_aci_cmd_params_setup, uint8_t setup_data_size) -{ - *(buffer + OFFSET_ACI_CMD_T_LEN) = setup_data_size + MSG_SETUP_CMD_BASE_LEN; - *(buffer + OFFSET_ACI_CMD_T_CMD_OPCODE) = ACI_CMD_SETUP; - memcpy((buffer + OFFSET_ACI_CMD_T_SETUP), &(p_aci_cmd_params_setup->setup_data[0]), setup_data_size); -} - -void acil_encode_cmd_dtm_cmd(uint8_t *buffer, aci_cmd_params_dtm_cmd_t *p_aci_cmd_params_dtm_cmd) -{ - *(buffer + OFFSET_ACI_CMD_T_LEN) = MSG_DTM_CMD; - *(buffer + OFFSET_ACI_CMD_T_CMD_OPCODE) = ACI_CMD_DTM_CMD; - *(buffer + OFFSET_ACI_CMD_T_DTM_CMD) = p_aci_cmd_params_dtm_cmd->cmd_msb; - *(buffer + OFFSET_ACI_CMD_T_DTM_CMD + 1) = p_aci_cmd_params_dtm_cmd->cmd_lsb; -} - -void acil_encode_cmd_send_data_ack(uint8_t *buffer, const uint8_t pipe_number ) -{ - *(buffer + OFFSET_ACI_CMD_T_LEN) = MSG_ACK_LEN; - *(buffer + OFFSET_ACI_CMD_T_CMD_OPCODE) = ACI_CMD_SEND_DATA_ACK; - *(buffer + OFFSET_ACI_CMD_T_SEND_DATA_ACK + OFFSET_ACI_CMD_PARAMS_SEND_DATA_ACK_T_PIPE_NUMBER) = pipe_number; -} - -void acil_encode_cmd_send_data_nack(uint8_t *buffer, const uint8_t pipe_number, const uint8_t err_code ) -{ - *(buffer + OFFSET_ACI_CMD_T_LEN) = MSG_NACK_LEN; - *(buffer + OFFSET_ACI_CMD_T_CMD_OPCODE) = ACI_CMD_SEND_DATA_NACK; - *(buffer + OFFSET_ACI_CMD_T_SEND_DATA_NACK + OFFSET_ACI_CMD_PARAMS_SEND_DATA_NACK_T_PIPE_NUMBER) = pipe_number; - *(buffer + OFFSET_ACI_CMD_T_SEND_DATA_NACK + OFFSET_ACI_CMD_PARAMS_SEND_DATA_NACK_T_ERROR_CODE) = err_code; -} - -void acil_encode_cmd_bond_security_request(uint8_t *buffer) -{ - *(buffer + OFFSET_ACI_CMD_T_LEN) = 1; - *(buffer + OFFSET_ACI_CMD_T_CMD_OPCODE) = ACI_CMD_BOND_SECURITY_REQUEST; -} - -void acil_encode_cmd_broadcast(uint8_t *buffer, aci_cmd_params_broadcast_t * p_aci_cmd_params_broadcast) -{ - *(buffer + OFFSET_ACI_CMD_T_LEN) = MSG_BROADCAST_LEN; - *(buffer + OFFSET_ACI_CMD_T_CMD_OPCODE) = ACI_CMD_BROADCAST; - *(buffer + OFFSET_ACI_CMD_T_BROADCAST + OFFSET_ACI_CMD_PARAMS_BROADCAST_T_TIMEOUT_LSB) = (p_aci_cmd_params_broadcast->timeout & 0xff); - *(buffer + OFFSET_ACI_CMD_T_BROADCAST + OFFSET_ACI_CMD_PARAMS_BROADCAST_T_TIMEOUT_MSB) = (uint8_t)(p_aci_cmd_params_broadcast->timeout >> 8); - *(buffer + OFFSET_ACI_CMD_T_BROADCAST + OFFSET_ACI_CMD_PARAMS_BROADCAST_T_ADV_INTERVAL_LSB) = (p_aci_cmd_params_broadcast->adv_interval & 0xff); - *(buffer + OFFSET_ACI_CMD_T_BROADCAST + OFFSET_ACI_CMD_PARAMS_BROADCAST_T_ADV_INTERVAL_MSB) = (uint8_t)(p_aci_cmd_params_broadcast->adv_interval >> 8); -} - -void acil_encode_cmd_open_adv_pipes(uint8_t *buffer, aci_cmd_params_open_adv_pipe_t * p_aci_cmd_params_open_adv_pipe) -{ - *(buffer + OFFSET_ACI_CMD_T_LEN) = MSG_OPEN_ADV_PIPES_LEN; - *(buffer + OFFSET_ACI_CMD_T_CMD_OPCODE) = ACI_CMD_OPEN_ADV_PIPE; - memcpy(buffer + OFFSET_ACI_CMD_T_OPEN_ADV_PIPE + OFFSET_ACI_CMD_PARAMS_OPEN_ADV_PIPE_T_PIPES, p_aci_cmd_params_open_adv_pipe->pipes, 8); -} - - -void acil_encode_cmd_set_key(uint8_t *buffer, aci_cmd_params_set_key_t *p_aci_cmd_params_set_key) -{ - /* - The length of the key is computed based on the type of key transaction. - - Key Reject - - Key type is passkey - */ - uint8_t len; - - switch (p_aci_cmd_params_set_key->key_type) - { - case ACI_KEY_TYPE_INVALID: - len = MSG_SET_KEY_REJECT_LEN; - break; - case ACI_KEY_TYPE_PASSKEY: - len = MSG_SET_KEY_PASSKEY_LEN; - break; - default: - len=0; - break; - } - *(buffer + OFFSET_ACI_CMD_T_LEN) = len; - *(buffer + OFFSET_ACI_CMD_T_CMD_OPCODE) = ACI_CMD_SET_KEY; - *(buffer + OFFSET_ACI_CMD_T_SET_KEY + OFFSET_ACI_CMD_PARAMS_SET_KEY_T_KEY_TYPE) = p_aci_cmd_params_set_key->key_type; - memcpy((buffer + OFFSET_ACI_CMD_T_SET_KEY + OFFSET_ACI_CMD_PARAMS_SET_KEY_T_PASSKEY), (uint8_t * )&(p_aci_cmd_params_set_key->key), len-2);//Reducing 2 for the opcode byte and type -} - -bool acil_encode_cmd(uint8_t *buffer, aci_cmd_t *p_aci_cmd) -{ - bool ret_val = false; - - switch(p_aci_cmd->cmd_opcode) - { - case ACI_CMD_TEST: - acil_encode_cmd_set_test_mode(buffer, &(p_aci_cmd->params.test)); - break; - case ACI_CMD_SLEEP: - acil_encode_cmd_sleep(buffer); - break; - case ACI_CMD_GET_DEVICE_VERSION: - acil_encode_cmd_get_device_version(buffer); - break; - case ACI_CMD_WAKEUP: - acil_encode_cmd_wakeup(buffer); - break; - case ACI_CMD_ECHO: - acil_encode_cmd_echo_msg(buffer, &(p_aci_cmd->params.echo), (p_aci_cmd->len - MSG_ECHO_MSG_CMD_BASE_LEN)); - break; - case ACI_CMD_GET_BATTERY_LEVEL: - acil_encode_cmd_battery_level(buffer); - break; - case ACI_CMD_GET_TEMPERATURE: - acil_encode_cmd_temparature(buffer); - break; - case ACI_CMD_GET_DEVICE_ADDRESS: - acil_encode_cmd_get_address(buffer); - break; - case ACI_CMD_SET_TX_POWER: - acil_encode_cmd_set_radio_tx_power(buffer, &(p_aci_cmd->params.set_tx_power)); - break; - case ACI_CMD_CONNECT: - acil_encode_cmd_connect(buffer, &(p_aci_cmd->params.connect)); - break; - case ACI_CMD_BOND: - acil_encode_cmd_bond(buffer, &(p_aci_cmd->params.bond)); - break; - case ACI_CMD_DISCONNECT: - acil_encode_cmd_disconnect(buffer, &(p_aci_cmd->params.disconnect)); - break; - case ACI_CMD_RADIO_RESET: - acil_encode_baseband_reset(buffer); - break; - case ACI_CMD_CHANGE_TIMING: - acil_encode_cmd_change_timing_req(buffer, &(p_aci_cmd->params.change_timing)); - break; - case ACI_CMD_SETUP: - acil_encode_cmd_setup(buffer, &(p_aci_cmd->params.setup), (p_aci_cmd->len - MSG_SETUP_CMD_BASE_LEN)); - break; - case ACI_CMD_DTM_CMD: - acil_encode_cmd_dtm_cmd(buffer, &(p_aci_cmd->params.dtm_cmd)); - break; - case ACI_CMD_READ_DYNAMIC_DATA: - acil_encode_cmd_read_dynamic_data(buffer); - break; - case ACI_CMD_WRITE_DYNAMIC_DATA: - acil_encode_cmd_write_dynamic_data(buffer, p_aci_cmd->params.write_dynamic_data.seq_no, &(p_aci_cmd->params.write_dynamic_data.dynamic_data[0]), (p_aci_cmd->len - MSG_WRITE_DYNAMIC_DATA_BASE_LEN)); - break; - case ACI_CMD_OPEN_REMOTE_PIPE: - acil_encode_cmd_open_remote_pipe(buffer, &(p_aci_cmd->params.open_remote_pipe)); - break; - case ACI_CMD_SEND_DATA: - acil_encode_cmd_send_data(buffer, &(p_aci_cmd->params.send_data), (p_aci_cmd->len - MSG_SEND_DATA_BASE_LEN)); - break; - case ACI_CMD_SEND_DATA_ACK: - acil_encode_cmd_send_data_ack(buffer, p_aci_cmd->params.send_data_ack.pipe_number ); - break; - case ACI_CMD_REQUEST_DATA: - acil_encode_cmd_request_data(buffer, &(p_aci_cmd->params.request_data)); - break; - case ACI_CMD_SET_LOCAL_DATA: - acil_encode_cmd_set_local_data(buffer, (aci_cmd_params_set_local_data_t *)(&(p_aci_cmd->params.send_data)), (p_aci_cmd->len - MSG_SET_LOCAL_DATA_BASE_LEN)); - break; - case ACI_CMD_BOND_SECURITY_REQUEST: - acil_encode_cmd_bond_security_request(buffer); - break; - default: - break; - } - return ret_val; -} - -void acil_decode_evt_command_response(uint8_t *buffer_in, aci_evt_params_cmd_rsp_t *p_evt_params_cmd_rsp) -{ - aci_evt_cmd_rsp_params_get_device_version_t *p_device_version; - aci_evt_cmd_rsp_params_get_device_address_t *p_device_address; - aci_evt_cmd_rsp_params_get_temperature_t *p_temperature; - aci_evt_cmd_rsp_params_get_battery_level_t *p_batt_lvl; - aci_evt_cmd_rsp_read_dynamic_data_t *p_read_dyn_data; - aci_evt_cmd_rsp_params_dtm_cmd_t *p_dtm_evt; - - p_evt_params_cmd_rsp->cmd_opcode = (aci_cmd_opcode_t)*(buffer_in + OFFSET_ACI_EVT_T_CMD_RSP + OFFSET_ACI_EVT_PARAMS_CMD_RSP_T_CMD_OPCODE); - p_evt_params_cmd_rsp->cmd_status = (aci_status_code_t)*(buffer_in + OFFSET_ACI_EVT_T_CMD_RSP + OFFSET_ACI_EVT_PARAMS_CMD_RSP_T_CMD_STATUS); - - switch (p_evt_params_cmd_rsp->cmd_opcode) - { - case ACI_CMD_GET_DEVICE_VERSION: - p_device_version = &(p_evt_params_cmd_rsp->params.get_device_version); - p_device_version->configuration_id = (uint16_t)*(buffer_in + OFFSET_ACI_EVT_T_CMD_RSP + OFFSET_ACI_EVT_PARAMS_CMD_RSP_T_GET_DEVICE_VERSION + OFFSET_ACI_EVT_CMD_RSP_PARAMS_GET_DEVICE_VERSION_T_CONFIGURATION_ID_LSB); - p_device_version->configuration_id |= (uint16_t)*(buffer_in + OFFSET_ACI_EVT_T_CMD_RSP + OFFSET_ACI_EVT_PARAMS_CMD_RSP_T_GET_DEVICE_VERSION + OFFSET_ACI_EVT_CMD_RSP_PARAMS_GET_DEVICE_VERSION_T_CONFIGURATION_ID_MSB) << 8; - p_device_version->aci_version = *(buffer_in + OFFSET_ACI_EVT_T_CMD_RSP + OFFSET_ACI_EVT_PARAMS_CMD_RSP_T_GET_DEVICE_VERSION + OFFSET_ACI_EVT_CMD_RSP_PARAMS_GET_DEVICE_VERSION_T_ACI_VERSION); - p_device_version->setup_format = *(buffer_in + OFFSET_ACI_EVT_T_CMD_RSP + OFFSET_ACI_EVT_PARAMS_CMD_RSP_T_GET_DEVICE_VERSION + OFFSET_ACI_EVT_CMD_RSP_PARAMS_GET_DEVICE_VERSION_T_SETUP_FORMAT); - p_device_version->setup_id = (uint32_t)*(buffer_in + OFFSET_ACI_EVT_T_CMD_RSP + OFFSET_ACI_EVT_PARAMS_CMD_RSP_T_GET_DEVICE_VERSION + OFFSET_ACI_EVT_CMD_RSP_PARAMS_GET_DEVICE_VERSION_T_SETUP_ID_LSB0); - p_device_version->setup_id |= (uint32_t)*(buffer_in + OFFSET_ACI_EVT_T_CMD_RSP + OFFSET_ACI_EVT_PARAMS_CMD_RSP_T_GET_DEVICE_VERSION + OFFSET_ACI_EVT_CMD_RSP_PARAMS_GET_DEVICE_VERSION_T_SETUP_ID_LSB1) << 8; - p_device_version->setup_id |= (uint32_t)*(buffer_in + OFFSET_ACI_EVT_T_CMD_RSP + OFFSET_ACI_EVT_PARAMS_CMD_RSP_T_GET_DEVICE_VERSION + OFFSET_ACI_EVT_CMD_RSP_PARAMS_GET_DEVICE_VERSION_T_SETUP_ID_MSB0) << 16; - p_device_version->setup_id |= (uint32_t)*(buffer_in + OFFSET_ACI_EVT_T_CMD_RSP + OFFSET_ACI_EVT_PARAMS_CMD_RSP_T_GET_DEVICE_VERSION + OFFSET_ACI_EVT_CMD_RSP_PARAMS_GET_DEVICE_VERSION_T_SETUP_ID_MSB1) << 24; - p_device_version->setup_status = *(buffer_in + OFFSET_ACI_EVT_T_CMD_RSP + OFFSET_ACI_EVT_PARAMS_CMD_RSP_T_GET_DEVICE_VERSION + OFFSET_ACI_EVT_CMD_RSP_PARAMS_GET_DEVICE_VERSION_T_SETUP_STATUS); - break; - - case ACI_CMD_GET_DEVICE_ADDRESS: - p_device_address = &(p_evt_params_cmd_rsp->params.get_device_address); - memcpy((uint8_t *)(p_device_address->bd_addr_own), (buffer_in + OFFSET_ACI_EVT_T_CMD_RSP+OFFSET_ACI_EVT_PARAMS_CMD_RSP_T_GET_DEVICE_ADDRESS+OFFSET_ACI_EVT_CMD_RSP_PARAMS_GET_DEVICE_ADDRESS_T_BD_ADDR_OWN), BTLE_DEVICE_ADDRESS_SIZE); - p_device_address->bd_addr_type = (aci_bd_addr_type_t) *(buffer_in + OFFSET_ACI_EVT_T_CMD_RSP+OFFSET_ACI_EVT_PARAMS_CMD_RSP_T_GET_DEVICE_ADDRESS+OFFSET_ACI_EVT_CMD_RSP_PARAMS_GET_DEVICE_ADDRESS_T_BD_ADDR_TYPE); - break; - - case ACI_CMD_GET_TEMPERATURE: - p_temperature = &(p_evt_params_cmd_rsp->params.get_temperature); - p_temperature->temperature_value = (int16_t)*(buffer_in + OFFSET_ACI_EVT_T_CMD_RSP + OFFSET_ACI_EVT_PARAMS_CMD_RSP_T_GET_TEMPERATURE + OFFSET_ACI_EVT_CMD_RSP_PARAMS_GET_TEMPERATURE_T_TEMPERATURE_VALUE_LSB); - p_temperature->temperature_value |= (int16_t)*(buffer_in + OFFSET_ACI_EVT_T_CMD_RSP + OFFSET_ACI_EVT_PARAMS_CMD_RSP_T_GET_TEMPERATURE + OFFSET_ACI_EVT_CMD_RSP_PARAMS_GET_TEMPERATURE_T_TEMPERATURE_VALUE_MSB) << 8; - break; - - case ACI_CMD_GET_BATTERY_LEVEL: - p_batt_lvl = &(p_evt_params_cmd_rsp->params.get_battery_level); - p_batt_lvl->battery_level = (int16_t)*(buffer_in + OFFSET_ACI_EVT_T_CMD_RSP + OFFSET_ACI_EVT_PARAMS_CMD_RSP_T_GET_BATTERY_LEVEL + OFFSET_ACI_EVT_CMD_RSP_PARAMS_GET_BATTERY_LEVEL_T_BATTERY_LEVEL_LSB); - p_batt_lvl->battery_level |= (int16_t)*(buffer_in + OFFSET_ACI_EVT_T_CMD_RSP + OFFSET_ACI_EVT_PARAMS_CMD_RSP_T_GET_BATTERY_LEVEL + OFFSET_ACI_EVT_CMD_RSP_PARAMS_GET_BATTERY_LEVEL_T_BATTERY_LEVEL_MSB) << 8; - break; - - case ACI_CMD_READ_DYNAMIC_DATA: - p_read_dyn_data = &(p_evt_params_cmd_rsp->params.read_dynamic_data); - p_read_dyn_data->seq_no = (uint8_t)*(buffer_in + OFFSET_ACI_EVT_T_CMD_RSP + OFFSET_ACI_EVT_PARAMS_CMD_RSP_T_READ_DYNAMIC_DATA + OFFSET_ACI_EVT_CMD_RSP_READ_DYNAMIC_DATA_T_SEQ_NO); - memcpy((uint8_t *)(p_read_dyn_data->dynamic_data), (buffer_in + OFFSET_ACI_EVT_T_CMD_RSP + OFFSET_ACI_EVT_PARAMS_CMD_RSP_T_READ_DYNAMIC_DATA + OFFSET_ACI_CMD_PARAMS_WRITE_DYNAMIC_DATA_T_DYNAMIC_DATA), ACIL_DECODE_EVT_GET_LENGTH(buffer_in) - 3); // 3 bytes subtracted account for EventCode, CommandOpCode and Status bytes. - // Now that the p_read_dyn_data->dynamic_data will be pointing to memory location with enough space to accommodate upto 27 bytes of dynamic data received. This is because of the padding element in aci_evt_params_cmd_rsp_t - break; - - case ACI_CMD_DTM_CMD: - p_dtm_evt = &(p_evt_params_cmd_rsp->params.dtm_cmd); - p_dtm_evt->evt_msb = (uint8_t)*(buffer_in + OFFSET_ACI_EVT_T_CMD_RSP + OFFSET_ACI_EVT_PARAMS_CMD_RSP_T_DTM_CMD + OFFSET_ACI_EVT_CMD_RSP_PARAMS_DTM_CMD_T_EVT_MSB); - p_dtm_evt->evt_lsb = (uint8_t)*(buffer_in + OFFSET_ACI_EVT_T_CMD_RSP + OFFSET_ACI_EVT_PARAMS_CMD_RSP_T_DTM_CMD + OFFSET_ACI_EVT_CMD_RSP_PARAMS_DTM_CMD_T_EVT_LSB); - break; - } -} - -void acil_decode_evt_device_started(uint8_t *buffer_in, aci_evt_params_device_started_t *p_evt_params_device_started) -{ - p_evt_params_device_started->device_mode = (aci_device_operation_mode_t) *(buffer_in + OFFSET_ACI_EVT_T_DEVICE_STARTED+OFFSET_ACI_EVT_PARAMS_DEVICE_STARTED_T_DEVICE_MODE); - p_evt_params_device_started->hw_error = (aci_hw_error_t) *(buffer_in + OFFSET_ACI_EVT_T_DEVICE_STARTED+OFFSET_ACI_EVT_PARAMS_DEVICE_STARTED_T_HW_ERROR); - p_evt_params_device_started->credit_available = *(buffer_in + OFFSET_ACI_EVT_T_DEVICE_STARTED+OFFSET_ACI_EVT_PARAMS_DEVICE_STARTED_T_CREDIT_AVAILABLE); -} - -void acil_decode_evt_pipe_status(uint8_t *buffer_in, aci_evt_params_pipe_status_t *p_aci_evt_params_pipe_status) -{ - memcpy((uint8_t *)p_aci_evt_params_pipe_status->pipes_open_bitmap, (buffer_in + OFFSET_ACI_EVT_T_PIPE_STATUS + OFFSET_ACI_EVT_PARAMS_PIPE_STATUS_T_PIPES_OPEN_BITMAP), 8); - memcpy((uint8_t *)p_aci_evt_params_pipe_status->pipes_closed_bitmap, (buffer_in + OFFSET_ACI_EVT_T_PIPE_STATUS + OFFSET_ACI_EVT_PARAMS_PIPE_STATUS_T_PIPES_CLOSED_BITMAP), 8); -} - -void acil_decode_evt_disconnected(uint8_t *buffer_in, aci_evt_params_disconnected_t *p_aci_evt_params_disconnected) -{ - p_aci_evt_params_disconnected->aci_status = (aci_status_code_t)*(buffer_in + OFFSET_ACI_EVT_T_DISCONNECTED + OFFSET_ACI_EVT_PARAMS_DISCONNECTED_T_ACI_STATUS); - p_aci_evt_params_disconnected->btle_status = *(buffer_in + OFFSET_ACI_EVT_T_DISCONNECTED + OFFSET_ACI_EVT_PARAMS_DISCONNECTED_T_BTLE_STATUS); -} - -void acil_decode_evt_bond_status(uint8_t *buffer_in, aci_evt_params_bond_status_t *p_aci_evt_params_bond_status) -{ - p_aci_evt_params_bond_status->status_code = (aci_bond_status_code_t)*(buffer_in + OFFSET_ACI_EVT_T_BOND_STATUS + OFFSET_ACI_EVT_PARAMS_BOND_STATUS_T_STATUS_CODE); - p_aci_evt_params_bond_status->status_source = (aci_bond_status_source_t)*(buffer_in + OFFSET_ACI_EVT_T_BOND_STATUS + OFFSET_ACI_EVT_PARAMS_BOND_STATUS_T_STATUS_SOURCE); - p_aci_evt_params_bond_status->secmode1_bitmap = *(buffer_in + OFFSET_ACI_EVT_T_BOND_STATUS + OFFSET_ACI_EVT_PARAMS_BOND_STATUS_T_SECMODE1_BITMAP); - p_aci_evt_params_bond_status->secmode2_bitmap = *(buffer_in + OFFSET_ACI_EVT_T_BOND_STATUS + OFFSET_ACI_EVT_PARAMS_BOND_STATUS_T_SECMODE2_BITMAP); - p_aci_evt_params_bond_status->keys_exchanged_slave = *(buffer_in + OFFSET_ACI_EVT_T_BOND_STATUS + OFFSET_ACI_EVT_PARAMS_BOND_STATUS_T_KEYS_EXCHANGED_SLAVE); - p_aci_evt_params_bond_status->keys_exchanged_master = *(buffer_in + OFFSET_ACI_EVT_T_BOND_STATUS + OFFSET_ACI_EVT_PARAMS_BOND_STATUS_T_KEYS_EXCHANGED_MASTER); -} - -uint8_t acil_decode_evt_data_received(uint8_t *buffer_in, aci_evt_params_data_received_t *p_evt_params_data_received) -{ - uint8_t size = *( buffer_in + OFFSET_ACI_EVT_T_LEN) - (OFFSET_ACI_EVT_T_DATA_RECEIVED + OFFSET_ACI_RX_DATA_T_ACI_DATA) + 1 ; - p_evt_params_data_received->rx_data.pipe_number = *(buffer_in + OFFSET_ACI_EVT_T_DATA_RECEIVED + OFFSET_ACI_RX_DATA_T_PIPE_NUMBER); - memcpy((uint8_t *)p_evt_params_data_received->rx_data.aci_data, (buffer_in + OFFSET_ACI_EVT_T_DATA_RECEIVED + OFFSET_ACI_RX_DATA_T_ACI_DATA), size); - return size; -} - -void acil_decode_evt_data_ack(uint8_t *buffer_in, aci_evt_params_data_ack_t *p_evt_params_data_ack) -{ - p_evt_params_data_ack->pipe_number = *(buffer_in + OFFSET_ACI_EVT_T_DATA_ACK + OFFSET_ACI_EVT_PARAMS_DATA_ACK_T_PIPE_NUMBER); -} - -uint8_t acil_decode_evt_hw_error(uint8_t *buffer_in, aci_evt_params_hw_error_t *p_aci_evt_params_hw_error) -{ - uint8_t size = *(buffer_in + OFFSET_ACI_EVT_T_LEN) - (OFFSET_ACI_EVT_T_HW_ERROR + OFFSET_ACI_EVT_PARAMS_HW_ERROR_T_FILE_NAME) + 1; - p_aci_evt_params_hw_error->line_num = (uint16_t)(*(buffer_in + OFFSET_ACI_EVT_T_HW_ERROR + OFFSET_ACI_EVT_PARAMS_HW_ERROR_T_LINE_NUM_MSB)) << 8; - p_aci_evt_params_hw_error->line_num |= (uint16_t)*(buffer_in + OFFSET_ACI_EVT_T_HW_ERROR + OFFSET_ACI_EVT_PARAMS_HW_ERROR_T_LINE_NUM_LSB); - memcpy((uint8_t *)p_aci_evt_params_hw_error->file_name, (buffer_in + OFFSET_ACI_EVT_T_HW_ERROR + OFFSET_ACI_EVT_PARAMS_HW_ERROR_T_FILE_NAME), size); - return size; -} - -void acil_decode_evt_credit(uint8_t *buffer_in, aci_evt_params_data_credit_t *p_evt_params_data_credit) -{ - p_evt_params_data_credit->credit = *(buffer_in + OFFSET_ACI_EVT_T_DATA_CREDIT + OFFSET_ACI_EVT_PARAMS_DATA_CREDIT_T_CREDIT); -} - -void acil_decode_evt_connected(uint8_t *buffer_in, aci_evt_params_connected_t *p_aci_evt_params_connected) -{ - p_aci_evt_params_connected->dev_addr_type = (aci_bd_addr_type_t)*(buffer_in + OFFSET_ACI_EVT_T_CONNECTED + OFFSET_ACI_EVT_PARAMS_CONNECTED_T_DEV_ADDR_TYPE); - memcpy(&(p_aci_evt_params_connected->dev_addr[0]), (buffer_in + OFFSET_ACI_EVT_T_CONNECTED + OFFSET_ACI_EVT_PARAMS_CONNECTED_T_DEV_ADDR), BTLE_DEVICE_ADDRESS_SIZE); - p_aci_evt_params_connected->conn_rf_interval = (uint16_t)*(buffer_in + OFFSET_ACI_EVT_T_CONNECTED + OFFSET_ACI_EVT_PARAMS_CONNECTED_T_CONN_RF_INTERVAL_MSB) << 8; - p_aci_evt_params_connected->conn_rf_interval |= (uint16_t)*(buffer_in + OFFSET_ACI_EVT_T_CONNECTED + OFFSET_ACI_EVT_PARAMS_CONNECTED_T_CONN_RF_INTERVAL_LSB); - p_aci_evt_params_connected->conn_slave_rf_latency = (uint16_t)*(buffer_in + OFFSET_ACI_EVT_T_CONNECTED + OFFSET_ACI_EVT_PARAMS_CONNECTED_T_CONN_SLAVE_RF_LATENCY_MSB) << 8; - p_aci_evt_params_connected->conn_slave_rf_latency |= (uint16_t)*(buffer_in + OFFSET_ACI_EVT_T_CONNECTED + OFFSET_ACI_EVT_PARAMS_CONNECTED_T_CONN_SLAVE_RF_LATENCY_LSB); - p_aci_evt_params_connected->conn_rf_timeout = (uint16_t)*(buffer_in + OFFSET_ACI_EVT_T_CONNECTED + OFFSET_ACI_EVT_PARAMS_CONNECTED_T_CONN_RF_TIMEOUT_MSB) << 8; - p_aci_evt_params_connected->conn_rf_timeout |= (uint16_t)*(buffer_in + OFFSET_ACI_EVT_T_CONNECTED + OFFSET_ACI_EVT_PARAMS_CONNECTED_T_CONN_RF_TIMEOUT_LSB); - p_aci_evt_params_connected->master_clock_accuracy = (aci_clock_accuracy_t)*(buffer_in + OFFSET_ACI_EVT_T_CONNECTED + OFFSET_ACI_EVT_PARAMS_CONNECTED_T_MASTER_CLOCK_ACCURACY); - -} - -void acil_decode_evt_timing(uint8_t *buffer_in, aci_evt_params_timing_t *p_evt_params_timing) -{ - p_evt_params_timing->conn_rf_interval = *(buffer_in + OFFSET_ACI_EVT_T_TIMING + OFFSET_ACI_EVT_PARAMS_TIMING_T_CONN_RF_INTERVAL_MSB) << 8; - p_evt_params_timing->conn_rf_interval |= (uint16_t)*(buffer_in + OFFSET_ACI_EVT_T_TIMING + OFFSET_ACI_EVT_PARAMS_TIMING_T_CONN_RF_INTERVAL_LSB); - p_evt_params_timing->conn_slave_rf_latency = (uint16_t)*(buffer_in + OFFSET_ACI_EVT_T_TIMING + OFFSET_ACI_EVT_PARAMS_TIMING_T_CONN_SLAVE_RF_LATENCY_MSB) << 8; - p_evt_params_timing->conn_slave_rf_latency |= (uint16_t)*(buffer_in + OFFSET_ACI_EVT_T_TIMING + OFFSET_ACI_EVT_PARAMS_TIMING_T_CONN_SLAVE_RF_LATENCY_LSB); - p_evt_params_timing->conn_rf_timeout = (uint16_t)*(buffer_in + OFFSET_ACI_EVT_T_TIMING + OFFSET_ACI_EVT_PARAMS_TIMING_T_CONN_RF_TIMEOUT_MSB) << 8; - p_evt_params_timing->conn_rf_timeout |= *(buffer_in + OFFSET_ACI_EVT_T_TIMING + OFFSET_ACI_EVT_PARAMS_TIMING_T_CONN_RF_TIMEOUT_LSB); -} - -void acil_decode_evt_pipe_error(uint8_t *buffer_in, aci_evt_params_pipe_error_t *p_evt_params_pipe_error) -{ - //volatile uint8_t size = *(buffer_in + OFFSET_ACI_EVT_T_LEN) - (OFFSET_ACI_EVT_T_PIPE_ERROR + OFFSET_ACI_EVT_PARAMS_PIPE_ERROR_T_ERROR_DATA) + 1; - p_evt_params_pipe_error->pipe_number = *(buffer_in + OFFSET_ACI_EVT_T_PIPE_ERROR + OFFSET_ACI_EVT_PARAMS_PIPE_ERROR_T_PIPE_NUMBER); - p_evt_params_pipe_error->error_code = *(buffer_in + OFFSET_ACI_EVT_T_PIPE_ERROR + OFFSET_ACI_EVT_PARAMS_PIPE_ERROR_T_ERROR_CODE); - p_evt_params_pipe_error->params.error_data.content[0] = *(buffer_in + OFFSET_ACI_EVT_T_PIPE_ERROR + OFFSET_ACI_EVT_PARAMS_PIPE_ERROR_T_ERROR_DATA + OFFSET_ERROR_DATA_T_CONTENT); -} - -void acil_decode_evt_key_request(uint8_t *buffer_in, aci_evt_params_key_request_t *p_evt_params_key_request) -{ - p_evt_params_key_request->key_type = (aci_key_type_t)*(buffer_in + OFFSET_ACI_EVT_T_KEY_REQUEST + OFFSET_ACI_EVT_PARAMS_KEY_REQUEST_T_KEY_TYPE); -} - -uint8_t acil_decode_evt_echo(uint8_t *buffer_in, aci_evt_params_echo_t *aci_evt_params_echo) -{ - uint8_t size = *(buffer_in + OFFSET_ACI_EVT_T_LEN) - 1; - memcpy(&aci_evt_params_echo->echo_data[0], (buffer_in + OFFSET_ACI_EVT_T_EVT_OPCODE + 1), size); - return size; -} - -void acil_decode_evt_display_passkey(uint8_t *buffer_in, aci_evt_params_display_passkey_t *p_aci_evt_params_display_passkey) -{ - p_aci_evt_params_display_passkey->passkey[0] = *(buffer_in + OFFSET_ACI_EVT_T_DISPLAY_PASSKEY + OFFSET_ACI_EVT_PARAMS_DISPLAY_PASSKEY_T_PASSKEY + 0); - p_aci_evt_params_display_passkey->passkey[1] = *(buffer_in + OFFSET_ACI_EVT_T_DISPLAY_PASSKEY + OFFSET_ACI_EVT_PARAMS_DISPLAY_PASSKEY_T_PASSKEY + 1); - p_aci_evt_params_display_passkey->passkey[2] = *(buffer_in + OFFSET_ACI_EVT_T_DISPLAY_PASSKEY + OFFSET_ACI_EVT_PARAMS_DISPLAY_PASSKEY_T_PASSKEY + 2); - p_aci_evt_params_display_passkey->passkey[3] = *(buffer_in + OFFSET_ACI_EVT_T_DISPLAY_PASSKEY + OFFSET_ACI_EVT_PARAMS_DISPLAY_PASSKEY_T_PASSKEY + 3); - p_aci_evt_params_display_passkey->passkey[4] = *(buffer_in + OFFSET_ACI_EVT_T_DISPLAY_PASSKEY + OFFSET_ACI_EVT_PARAMS_DISPLAY_PASSKEY_T_PASSKEY + 4); - p_aci_evt_params_display_passkey->passkey[5] = *(buffer_in + OFFSET_ACI_EVT_T_DISPLAY_PASSKEY + OFFSET_ACI_EVT_PARAMS_DISPLAY_PASSKEY_T_PASSKEY + 5); -} - -bool acil_decode_evt(uint8_t *buffer_in, aci_evt_t *p_aci_evt) -{ - bool ret_val = true; - - p_aci_evt->len = ACIL_DECODE_EVT_GET_LENGTH(buffer_in); - p_aci_evt->evt_opcode = (aci_evt_opcode_t)ACIL_DECODE_EVT_GET_OPCODE(buffer_in); - - switch(p_aci_evt->evt_opcode) - { - case ACI_EVT_DEVICE_STARTED: - acil_decode_evt_device_started(buffer_in, &(p_aci_evt->params.device_started)); - break; - case ACI_EVT_HW_ERROR: - acil_decode_evt_hw_error(buffer_in, &(p_aci_evt->params.hw_error)); - break; - case ACI_EVT_CMD_RSP: - acil_decode_evt_command_response(buffer_in, &(p_aci_evt->params.cmd_rsp)); - break; - case ACI_EVT_DATA_CREDIT: - acil_decode_evt_credit(buffer_in, &(p_aci_evt->params.data_credit)); - break; - case ACI_EVT_CONNECTED: - acil_decode_evt_connected(buffer_in, &(p_aci_evt->params.connected)); - break; - case ACI_EVT_PIPE_STATUS: - acil_decode_evt_pipe_status(buffer_in, &(p_aci_evt->params.pipe_status)); - break; - case ACI_EVT_DISCONNECTED: - acil_decode_evt_disconnected(buffer_in, &(p_aci_evt->params.disconnected)); - break; - case ACI_EVT_BOND_STATUS: - acil_decode_evt_bond_status(buffer_in, &(p_aci_evt->params.bond_status)); - break; - case ACI_EVT_TIMING: - acil_decode_evt_timing(buffer_in, &(p_aci_evt->params.timing)); - break; - case ACI_EVT_DATA_ACK: - acil_decode_evt_data_ack(buffer_in, &(p_aci_evt->params.data_ack)); - break; - case ACI_EVT_DATA_RECEIVED: - acil_decode_evt_data_received(buffer_in, &(p_aci_evt->params.data_received)); - break; - case ACI_EVT_PIPE_ERROR: - acil_decode_evt_pipe_error(buffer_in, &(p_aci_evt->params.pipe_error)); - break; - case ACI_EVT_KEY_REQUEST: - acil_decode_evt_key_request(buffer_in, &(p_aci_evt->params.key_request)); - break; - case ACI_EVT_DISPLAY_PASSKEY: - acil_decode_evt_display_passkey(buffer_in, &(p_aci_evt->params.display_passkey)); - break; - default: - ret_val = false; - break; - } - return ret_val; -} +/* Copyright (c) 2014, Nordic Semiconductor ASA + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/** + * @file + * + * @ingroup group_acilib + * + * @brief Implementation of the acilib module. + */ + + +#include "hal_platform.h" +#include "aci.h" +#include "aci_cmds.h" +#include "aci_evts.h" +#include "acilib.h" +#include "aci_protocol_defines.h" +#include "acilib_defs.h" +#include "acilib_if.h" +#include "acilib_types.h" + + +void acil_encode_cmd_set_test_mode(uint8_t *buffer, aci_cmd_params_test_t *p_aci_cmd_params_test) +{ + *(buffer + OFFSET_ACI_CMD_T_LEN) = 2; + *(buffer + OFFSET_ACI_CMD_T_CMD_OPCODE) = ACI_CMD_TEST; + *(buffer + OFFSET_ACI_CMD_T_TEST + OFFSET_ACI_CMD_PARAMS_TEST_T_TEST_MODE_CHANGE) = p_aci_cmd_params_test->test_mode_change; +} + +void acil_encode_cmd_sleep(uint8_t *buffer) +{ + *(buffer + OFFSET_ACI_CMD_T_LEN) = 1; + *(buffer + OFFSET_ACI_CMD_T_CMD_OPCODE) = ACI_CMD_SLEEP; +} + +void acil_encode_cmd_get_device_version(uint8_t *buffer) +{ + *(buffer + OFFSET_ACI_CMD_T_LEN) = 1; + *(buffer + OFFSET_ACI_CMD_T_CMD_OPCODE) = ACI_CMD_GET_DEVICE_VERSION; +} + +void acil_encode_cmd_set_local_data(uint8_t *buffer, aci_cmd_params_set_local_data_t *p_aci_cmd_params_set_local_data, uint8_t data_size) +{ + *(buffer + OFFSET_ACI_CMD_T_LEN) = MSG_SET_LOCAL_DATA_BASE_LEN + data_size; + *(buffer + OFFSET_ACI_CMD_T_CMD_OPCODE) = ACI_CMD_SET_LOCAL_DATA; + *(buffer + OFFSET_ACI_CMD_T_SET_LOCAL_DATA + OFFSET_ACI_CMD_PARAMS_SEND_DATA_T_TX_DATA + OFFSET_ACI_TX_DATA_T_PIPE_NUMBER) = p_aci_cmd_params_set_local_data->tx_data.pipe_number; + memcpy(buffer + OFFSET_ACI_CMD_T_SET_LOCAL_DATA + OFFSET_ACI_CMD_PARAMS_SEND_DATA_T_TX_DATA + OFFSET_ACI_TX_DATA_T_ACI_DATA, &(p_aci_cmd_params_set_local_data->tx_data.aci_data[0]), data_size); +} + +void acil_encode_cmd_connect(uint8_t *buffer, aci_cmd_params_connect_t *p_aci_cmd_params_connect) +{ + *(buffer + OFFSET_ACI_CMD_T_LEN) = MSG_CONNECT_LEN; + *(buffer + OFFSET_ACI_CMD_T_CMD_OPCODE) = ACI_CMD_CONNECT; + *(buffer + OFFSET_ACI_CMD_T_CONNECT + OFFSET_ACI_CMD_PARAMS_CONNECT_T_TIMEOUT_MSB) = (uint8_t)(p_aci_cmd_params_connect->timeout >> 8); + *(buffer + OFFSET_ACI_CMD_T_CONNECT + OFFSET_ACI_CMD_PARAMS_CONNECT_T_TIMEOUT_LSB) = (uint8_t)(p_aci_cmd_params_connect->timeout); + *(buffer + OFFSET_ACI_CMD_T_CONNECT + OFFSET_ACI_CMD_PARAMS_CONNECT_T_ADV_INTERVAL_MSB) = (uint8_t)(p_aci_cmd_params_connect->adv_interval >> 8); + *(buffer + OFFSET_ACI_CMD_T_CONNECT + OFFSET_ACI_CMD_PARAMS_CONNECT_T_ADV_INTERVAL_LSB) = (uint8_t)(p_aci_cmd_params_connect->adv_interval); +} + +void acil_encode_cmd_bond(uint8_t *buffer, aci_cmd_params_bond_t *p_aci_cmd_params_bond) +{ + *(buffer + OFFSET_ACI_CMD_T_LEN) = MSG_BOND_LEN; + *(buffer + OFFSET_ACI_CMD_T_CMD_OPCODE) = ACI_CMD_BOND; + *(buffer + OFFSET_ACI_CMD_T_BOND + OFFSET_ACI_CMD_PARAMS_BOND_T_TIMEOUT_MSB) = (uint8_t)(p_aci_cmd_params_bond->timeout >> 8); + *(buffer + OFFSET_ACI_CMD_T_BOND + OFFSET_ACI_CMD_PARAMS_BOND_T_TIMEOUT_LSB) = (uint8_t)(p_aci_cmd_params_bond->timeout); + *(buffer + OFFSET_ACI_CMD_T_BOND + OFFSET_ACI_CMD_PARAMS_BOND_T_ADV_INTERVAL_MSB) = (uint8_t)(p_aci_cmd_params_bond->adv_interval >> 8); + *(buffer + OFFSET_ACI_CMD_T_BOND + OFFSET_ACI_CMD_PARAMS_BOND_T_ADV_INTERVAL_LSB) = (uint8_t)(p_aci_cmd_params_bond->adv_interval); +} + +void acil_encode_cmd_disconnect(uint8_t *buffer, aci_cmd_params_disconnect_t *p_aci_cmd_params_disconnect) +{ + *(buffer + OFFSET_ACI_CMD_T_LEN) = MSG_DISCONNECT_LEN; + *(buffer + OFFSET_ACI_CMD_T_CMD_OPCODE) = ACI_CMD_DISCONNECT; + *(buffer + OFFSET_ACI_CMD_T_DISCONNECT + OFFSET_ACI_CMD_PARAMS_DISCONNECT_T_REASON) = (uint8_t)(p_aci_cmd_params_disconnect->reason); +} + +void acil_encode_baseband_reset(uint8_t *buffer) +{ + *(buffer + OFFSET_ACI_CMD_T_LEN) = MSG_BASEBAND_RESET_LEN; + *(buffer + OFFSET_ACI_CMD_T_CMD_OPCODE) = ACI_CMD_RADIO_RESET; +} + +void acil_encode_direct_connect(uint8_t *buffer) +{ + *(buffer + OFFSET_ACI_CMD_T_LEN) = MSG_DIRECT_CONNECT_LEN; + *(buffer + OFFSET_ACI_CMD_T_CMD_OPCODE) = ACI_CMD_CONNECT_DIRECT; +} + +void acil_encode_cmd_wakeup(uint8_t *buffer) +{ + *(buffer + OFFSET_ACI_CMD_T_LEN) = MSG_WAKEUP_LEN; + *(buffer + OFFSET_ACI_CMD_T_CMD_OPCODE) = ACI_CMD_WAKEUP; +} + +void acil_encode_cmd_set_radio_tx_power(uint8_t *buffer, aci_cmd_params_set_tx_power_t *p_aci_cmd_params_set_tx_power) +{ + *(buffer + OFFSET_ACI_CMD_T_LEN) = MSG_SET_RADIO_TX_POWER_LEN; + *(buffer + OFFSET_ACI_CMD_T_CMD_OPCODE) = ACI_CMD_SET_TX_POWER; + *(buffer + OFFSET_ACI_CMD_T_SET_TX_POWER + OFFSET_ACI_CMD_PARAMS_SET_TX_POWER_T_DEVICE_POWER) = (uint8_t)p_aci_cmd_params_set_tx_power->device_power; +} + +void acil_encode_cmd_get_address(uint8_t *buffer) +{ + *(buffer + OFFSET_ACI_CMD_T_LEN) = MSG_GET_DEVICE_ADDR_LEN; + *(buffer + OFFSET_ACI_CMD_T_CMD_OPCODE) = ACI_CMD_GET_DEVICE_ADDRESS; +} + +void acil_encode_cmd_send_data(uint8_t *buffer, aci_cmd_params_send_data_t *p_aci_cmd_params_send_data_t, uint8_t data_size) +{ + *(buffer + OFFSET_ACI_CMD_T_LEN) = MSG_SEND_DATA_BASE_LEN + data_size; + *(buffer + OFFSET_ACI_CMD_T_CMD_OPCODE) = ACI_CMD_SEND_DATA; + *(buffer + OFFSET_ACI_CMD_T_SEND_DATA + OFFSET_ACI_CMD_PARAMS_SEND_DATA_T_TX_DATA + OFFSET_ACI_TX_DATA_T_PIPE_NUMBER) = p_aci_cmd_params_send_data_t->tx_data.pipe_number; + memcpy((buffer + OFFSET_ACI_CMD_T_SEND_DATA + OFFSET_ACI_CMD_PARAMS_SEND_DATA_T_TX_DATA + OFFSET_ACI_TX_DATA_T_ACI_DATA), &(p_aci_cmd_params_send_data_t->tx_data.aci_data[0]), data_size); +} + +void acil_encode_cmd_request_data(uint8_t *buffer, aci_cmd_params_request_data_t *p_aci_cmd_params_request_data) +{ + *(buffer + OFFSET_ACI_CMD_T_LEN) = MSG_DATA_REQUEST_LEN; + *(buffer + OFFSET_ACI_CMD_T_CMD_OPCODE) = ACI_CMD_REQUEST_DATA; + *(buffer + OFFSET_ACI_CMD_T_REQUEST_DATA + OFFSET_ACI_CMD_PARAMS_REQUEST_DATA_T_PIPE_NUMBER) = p_aci_cmd_params_request_data->pipe_number; +} + +void acil_encode_cmd_open_remote_pipe(uint8_t *buffer, aci_cmd_params_open_remote_pipe_t *p_aci_cmd_params_open_remote_pipe) +{ + *(buffer + OFFSET_ACI_CMD_T_LEN) = MSG_OPEN_REMOTE_PIPE_LEN; + *(buffer + OFFSET_ACI_CMD_T_CMD_OPCODE) = ACI_CMD_OPEN_REMOTE_PIPE; + *(buffer + OFFSET_ACI_CMD_T_OPEN_REMOTE_PIPE + OFFSET_ACI_CMD_PARAMS_OPEN_REMOTE_PIPE_T_PIPE_NUMBER) = p_aci_cmd_params_open_remote_pipe->pipe_number; +} + +void acil_encode_cmd_close_remote_pipe(uint8_t *buffer, aci_cmd_params_close_remote_pipe_t *p_aci_cmd_params_close_remote_pipe) +{ + *(buffer + OFFSET_ACI_CMD_T_LEN) = MSG_CLOSE_REMOTE_PIPE_LEN; + *(buffer + OFFSET_ACI_CMD_T_CMD_OPCODE) = ACI_CMD_CLOSE_REMOTE_PIPE; + *(buffer + OFFSET_ACI_CMD_T_CLOSE_REMOTE_PIPE + OFFSET_ACI_CMD_PARAMS_CLOSE_REMOTE_PIPE_T_PIPE_NUMBER) = p_aci_cmd_params_close_remote_pipe->pipe_number; +} + +void acil_encode_cmd_echo_msg(uint8_t *buffer, aci_cmd_params_echo_t *p_cmd_params_echo, uint8_t msg_size) +{ + *(buffer + OFFSET_ACI_CMD_T_LEN) = MSG_ECHO_MSG_CMD_BASE_LEN + msg_size; + *(buffer + OFFSET_ACI_CMD_T_CMD_OPCODE) = ACI_CMD_ECHO; + memcpy((buffer + OFFSET_ACI_CMD_T_ECHO + OFFSET_ACI_CMD_PARAMS_ECHO_T_ECHO_DATA), &(p_cmd_params_echo->echo_data[0]), msg_size); +} + +void acil_encode_cmd_battery_level(uint8_t *buffer) +{ + *(buffer + OFFSET_ACI_CMD_T_LEN) = 1; + *(buffer + OFFSET_ACI_CMD_T_CMD_OPCODE) = ACI_CMD_GET_BATTERY_LEVEL; +} + +void acil_encode_cmd_temparature(uint8_t *buffer) +{ + *(buffer + OFFSET_ACI_CMD_T_LEN) = 1; + *(buffer + OFFSET_ACI_CMD_T_CMD_OPCODE) = ACI_CMD_GET_TEMPERATURE; +} + +void acil_encode_cmd_read_dynamic_data(uint8_t *buffer) +{ + *(buffer + OFFSET_ACI_CMD_T_LEN) = 1; + *(buffer + OFFSET_ACI_CMD_T_CMD_OPCODE) = ACI_CMD_READ_DYNAMIC_DATA; +} + +void acil_encode_cmd_write_dynamic_data(uint8_t *buffer, uint8_t seq_no, uint8_t* dynamic_data, uint8_t dynamic_data_size) +{ + *(buffer + OFFSET_ACI_CMD_T_LEN) = MSG_WRITE_DYNAMIC_DATA_BASE_LEN + dynamic_data_size; + *(buffer + OFFSET_ACI_CMD_T_CMD_OPCODE) = ACI_CMD_WRITE_DYNAMIC_DATA; + *(buffer + OFFSET_ACI_CMD_T_WRITE_DYNAMIC_DATA + OFFSET_ACI_CMD_PARAMS_WRITE_DYNAMIC_DATA_T_SEQ_NO) = seq_no; + memcpy((buffer + OFFSET_ACI_CMD_T_WRITE_DYNAMIC_DATA + OFFSET_ACI_CMD_PARAMS_WRITE_DYNAMIC_DATA_T_DYNAMIC_DATA), dynamic_data, dynamic_data_size); +} + +void acil_encode_cmd_change_timing_req(uint8_t *buffer, aci_cmd_params_change_timing_t *p_aci_cmd_params_change_timing) +{ + *(buffer + OFFSET_ACI_CMD_T_LEN) = MSG_CHANGE_TIMING_LEN; + *(buffer + OFFSET_ACI_CMD_T_CMD_OPCODE) = ACI_CMD_CHANGE_TIMING; + *(buffer + OFFSET_ACI_CMD_T_CHANGE_TIMING + OFFSET_ACI_CMD_PARAMS_CHANGE_TIMING_T_CONN_PARAMS + OFFSET_ACI_LL_CONN_PARAMS_T_MIN_CONN_INTERVAL_MSB) = (uint8_t)(p_aci_cmd_params_change_timing->conn_params.min_conn_interval >> 8); + *(buffer + OFFSET_ACI_CMD_T_CHANGE_TIMING + OFFSET_ACI_CMD_PARAMS_CHANGE_TIMING_T_CONN_PARAMS + OFFSET_ACI_LL_CONN_PARAMS_T_MIN_CONN_INTERVAL_LSB) = (uint8_t)(p_aci_cmd_params_change_timing->conn_params.min_conn_interval); + *(buffer + OFFSET_ACI_CMD_T_CHANGE_TIMING + OFFSET_ACI_CMD_PARAMS_CHANGE_TIMING_T_CONN_PARAMS + OFFSET_ACI_LL_CONN_PARAMS_T_MAX_CONN_INTERVAL_MSB) = (uint8_t)(p_aci_cmd_params_change_timing->conn_params.max_conn_interval >> 8); + *(buffer + OFFSET_ACI_CMD_T_CHANGE_TIMING + OFFSET_ACI_CMD_PARAMS_CHANGE_TIMING_T_CONN_PARAMS + OFFSET_ACI_LL_CONN_PARAMS_T_MAX_CONN_INTERVAL_LSB) = (uint8_t)(p_aci_cmd_params_change_timing->conn_params.max_conn_interval); + *(buffer + OFFSET_ACI_CMD_T_CHANGE_TIMING + OFFSET_ACI_CMD_PARAMS_CHANGE_TIMING_T_CONN_PARAMS + OFFSET_ACI_LL_CONN_PARAMS_T_SLAVE_LATENCY_MSB ) = (uint8_t)(p_aci_cmd_params_change_timing->conn_params.slave_latency >> 8); + *(buffer + OFFSET_ACI_CMD_T_CHANGE_TIMING + OFFSET_ACI_CMD_PARAMS_CHANGE_TIMING_T_CONN_PARAMS + OFFSET_ACI_LL_CONN_PARAMS_T_SLAVE_LATENCY_LSB ) = (uint8_t)(p_aci_cmd_params_change_timing->conn_params.slave_latency); + *(buffer + OFFSET_ACI_CMD_T_CHANGE_TIMING + OFFSET_ACI_CMD_PARAMS_CHANGE_TIMING_T_CONN_PARAMS + OFFSET_ACI_LL_CONN_PARAMS_T_TIMEOUT_MULT_MSB ) = (uint8_t)(p_aci_cmd_params_change_timing->conn_params.timeout_mult >> 8); + *(buffer + OFFSET_ACI_CMD_T_CHANGE_TIMING + OFFSET_ACI_CMD_PARAMS_CHANGE_TIMING_T_CONN_PARAMS + OFFSET_ACI_LL_CONN_PARAMS_T_TIMEOUT_MULT_LSB ) = (uint8_t)(p_aci_cmd_params_change_timing->conn_params.timeout_mult); +} + +void acil_encode_cmd_set_app_latency(uint8_t *buffer, aci_cmd_params_set_app_latency_t *p_aci_cmd_params_set_app_latency) +{ + *(buffer + OFFSET_ACI_CMD_T_LEN) = MSG_SET_APP_LATENCY_LEN; + *(buffer + OFFSET_ACI_CMD_T_CMD_OPCODE) = ACI_CMD_SET_APP_LATENCY; + *(buffer + OFFSET_ACI_CMD_T_SET_APP_LATENCY + OFFSET_ACI_CMD_PARAMS_SET_APP_LATENCY_T_MODE) = (uint8_t)( p_aci_cmd_params_set_app_latency->mode); + *(buffer + OFFSET_ACI_CMD_T_SET_APP_LATENCY + OFFSET_ACI_CMD_PARAMS_SET_APP_LATENCY_T_LATENCY_MSB) = (uint8_t)( p_aci_cmd_params_set_app_latency->latency>>8); + *(buffer + OFFSET_ACI_CMD_T_SET_APP_LATENCY + OFFSET_ACI_CMD_PARAMS_SET_APP_LATENCY_T_LATENCY_LSB) = (uint8_t)( p_aci_cmd_params_set_app_latency->latency); +} + +void acil_encode_cmd_change_timing_req_GAP_PPCP(uint8_t *buffer) +{ + *(buffer + OFFSET_ACI_CMD_T_LEN) = MSG_CHANGE_TIMING_LEN_GAP_PPCP; + *(buffer + OFFSET_ACI_CMD_T_CMD_OPCODE) = ACI_CMD_CHANGE_TIMING; +} + + +void acil_encode_cmd_setup(uint8_t *buffer, aci_cmd_params_setup_t *p_aci_cmd_params_setup, uint8_t setup_data_size) +{ + *(buffer + OFFSET_ACI_CMD_T_LEN) = setup_data_size + MSG_SETUP_CMD_BASE_LEN; + *(buffer + OFFSET_ACI_CMD_T_CMD_OPCODE) = ACI_CMD_SETUP; + memcpy((buffer + OFFSET_ACI_CMD_T_SETUP), &(p_aci_cmd_params_setup->setup_data[0]), setup_data_size); +} + +void acil_encode_cmd_dtm_cmd(uint8_t *buffer, aci_cmd_params_dtm_cmd_t *p_aci_cmd_params_dtm_cmd) +{ + *(buffer + OFFSET_ACI_CMD_T_LEN) = MSG_DTM_CMD; + *(buffer + OFFSET_ACI_CMD_T_CMD_OPCODE) = ACI_CMD_DTM_CMD; + *(buffer + OFFSET_ACI_CMD_T_DTM_CMD) = p_aci_cmd_params_dtm_cmd->cmd_msb; + *(buffer + OFFSET_ACI_CMD_T_DTM_CMD + 1) = p_aci_cmd_params_dtm_cmd->cmd_lsb; +} + +void acil_encode_cmd_send_data_ack(uint8_t *buffer, const uint8_t pipe_number ) +{ + *(buffer + OFFSET_ACI_CMD_T_LEN) = MSG_ACK_LEN; + *(buffer + OFFSET_ACI_CMD_T_CMD_OPCODE) = ACI_CMD_SEND_DATA_ACK; + *(buffer + OFFSET_ACI_CMD_T_SEND_DATA_ACK + OFFSET_ACI_CMD_PARAMS_SEND_DATA_ACK_T_PIPE_NUMBER) = pipe_number; +} + +void acil_encode_cmd_send_data_nack(uint8_t *buffer, const uint8_t pipe_number, const uint8_t err_code ) +{ + *(buffer + OFFSET_ACI_CMD_T_LEN) = MSG_NACK_LEN; + *(buffer + OFFSET_ACI_CMD_T_CMD_OPCODE) = ACI_CMD_SEND_DATA_NACK; + *(buffer + OFFSET_ACI_CMD_T_SEND_DATA_NACK + OFFSET_ACI_CMD_PARAMS_SEND_DATA_NACK_T_PIPE_NUMBER) = pipe_number; + *(buffer + OFFSET_ACI_CMD_T_SEND_DATA_NACK + OFFSET_ACI_CMD_PARAMS_SEND_DATA_NACK_T_ERROR_CODE) = err_code; +} + +void acil_encode_cmd_bond_security_request(uint8_t *buffer) +{ + *(buffer + OFFSET_ACI_CMD_T_LEN) = 1; + *(buffer + OFFSET_ACI_CMD_T_CMD_OPCODE) = ACI_CMD_BOND_SECURITY_REQUEST; +} + +void acil_encode_cmd_broadcast(uint8_t *buffer, aci_cmd_params_broadcast_t * p_aci_cmd_params_broadcast) +{ + *(buffer + OFFSET_ACI_CMD_T_LEN) = MSG_BROADCAST_LEN; + *(buffer + OFFSET_ACI_CMD_T_CMD_OPCODE) = ACI_CMD_BROADCAST; + *(buffer + OFFSET_ACI_CMD_T_BROADCAST + OFFSET_ACI_CMD_PARAMS_BROADCAST_T_TIMEOUT_LSB) = (p_aci_cmd_params_broadcast->timeout & 0xff); + *(buffer + OFFSET_ACI_CMD_T_BROADCAST + OFFSET_ACI_CMD_PARAMS_BROADCAST_T_TIMEOUT_MSB) = (uint8_t)(p_aci_cmd_params_broadcast->timeout >> 8); + *(buffer + OFFSET_ACI_CMD_T_BROADCAST + OFFSET_ACI_CMD_PARAMS_BROADCAST_T_ADV_INTERVAL_LSB) = (p_aci_cmd_params_broadcast->adv_interval & 0xff); + *(buffer + OFFSET_ACI_CMD_T_BROADCAST + OFFSET_ACI_CMD_PARAMS_BROADCAST_T_ADV_INTERVAL_MSB) = (uint8_t)(p_aci_cmd_params_broadcast->adv_interval >> 8); +} + +void acil_encode_cmd_open_adv_pipes(uint8_t *buffer, aci_cmd_params_open_adv_pipe_t * p_aci_cmd_params_open_adv_pipe) +{ + *(buffer + OFFSET_ACI_CMD_T_LEN) = MSG_OPEN_ADV_PIPES_LEN; + *(buffer + OFFSET_ACI_CMD_T_CMD_OPCODE) = ACI_CMD_OPEN_ADV_PIPE; + memcpy(buffer + OFFSET_ACI_CMD_T_OPEN_ADV_PIPE + OFFSET_ACI_CMD_PARAMS_OPEN_ADV_PIPE_T_PIPES, p_aci_cmd_params_open_adv_pipe->pipes, 8); +} + + +void acil_encode_cmd_set_key(uint8_t *buffer, aci_cmd_params_set_key_t *p_aci_cmd_params_set_key) +{ + /* + The length of the key is computed based on the type of key transaction. + - Key Reject + - Key type is passkey + */ + uint8_t len; + + switch (p_aci_cmd_params_set_key->key_type) + { + case ACI_KEY_TYPE_INVALID: + len = MSG_SET_KEY_REJECT_LEN; + break; + case ACI_KEY_TYPE_PASSKEY: + len = MSG_SET_KEY_PASSKEY_LEN; + break; + default: + len=0; + break; + } + *(buffer + OFFSET_ACI_CMD_T_LEN) = len; + *(buffer + OFFSET_ACI_CMD_T_CMD_OPCODE) = ACI_CMD_SET_KEY; + *(buffer + OFFSET_ACI_CMD_T_SET_KEY + OFFSET_ACI_CMD_PARAMS_SET_KEY_T_KEY_TYPE) = p_aci_cmd_params_set_key->key_type; + memcpy((buffer + OFFSET_ACI_CMD_T_SET_KEY + OFFSET_ACI_CMD_PARAMS_SET_KEY_T_PASSKEY), (uint8_t * )&(p_aci_cmd_params_set_key->key), len-2);//Reducing 2 for the opcode byte and type +} + +bool acil_encode_cmd(uint8_t *buffer, aci_cmd_t *p_aci_cmd) +{ + bool ret_val = false; + + switch(p_aci_cmd->cmd_opcode) + { + case ACI_CMD_TEST: + acil_encode_cmd_set_test_mode(buffer, &(p_aci_cmd->params.test)); + break; + case ACI_CMD_SLEEP: + acil_encode_cmd_sleep(buffer); + break; + case ACI_CMD_GET_DEVICE_VERSION: + acil_encode_cmd_get_device_version(buffer); + break; + case ACI_CMD_WAKEUP: + acil_encode_cmd_wakeup(buffer); + break; + case ACI_CMD_ECHO: + acil_encode_cmd_echo_msg(buffer, &(p_aci_cmd->params.echo), (p_aci_cmd->len - MSG_ECHO_MSG_CMD_BASE_LEN)); + break; + case ACI_CMD_GET_BATTERY_LEVEL: + acil_encode_cmd_battery_level(buffer); + break; + case ACI_CMD_GET_TEMPERATURE: + acil_encode_cmd_temparature(buffer); + break; + case ACI_CMD_GET_DEVICE_ADDRESS: + acil_encode_cmd_get_address(buffer); + break; + case ACI_CMD_SET_TX_POWER: + acil_encode_cmd_set_radio_tx_power(buffer, &(p_aci_cmd->params.set_tx_power)); + break; + case ACI_CMD_CONNECT: + acil_encode_cmd_connect(buffer, &(p_aci_cmd->params.connect)); + break; + case ACI_CMD_BOND: + acil_encode_cmd_bond(buffer, &(p_aci_cmd->params.bond)); + break; + case ACI_CMD_DISCONNECT: + acil_encode_cmd_disconnect(buffer, &(p_aci_cmd->params.disconnect)); + break; + case ACI_CMD_RADIO_RESET: + acil_encode_baseband_reset(buffer); + break; + case ACI_CMD_CHANGE_TIMING: + acil_encode_cmd_change_timing_req(buffer, &(p_aci_cmd->params.change_timing)); + break; + case ACI_CMD_SETUP: + acil_encode_cmd_setup(buffer, &(p_aci_cmd->params.setup), (p_aci_cmd->len - MSG_SETUP_CMD_BASE_LEN)); + break; + case ACI_CMD_DTM_CMD: + acil_encode_cmd_dtm_cmd(buffer, &(p_aci_cmd->params.dtm_cmd)); + break; + case ACI_CMD_READ_DYNAMIC_DATA: + acil_encode_cmd_read_dynamic_data(buffer); + break; + case ACI_CMD_WRITE_DYNAMIC_DATA: + acil_encode_cmd_write_dynamic_data(buffer, p_aci_cmd->params.write_dynamic_data.seq_no, &(p_aci_cmd->params.write_dynamic_data.dynamic_data[0]), (p_aci_cmd->len - MSG_WRITE_DYNAMIC_DATA_BASE_LEN)); + break; + case ACI_CMD_OPEN_REMOTE_PIPE: + acil_encode_cmd_open_remote_pipe(buffer, &(p_aci_cmd->params.open_remote_pipe)); + break; + case ACI_CMD_SEND_DATA: + acil_encode_cmd_send_data(buffer, &(p_aci_cmd->params.send_data), (p_aci_cmd->len - MSG_SEND_DATA_BASE_LEN)); + break; + case ACI_CMD_SEND_DATA_ACK: + acil_encode_cmd_send_data_ack(buffer, p_aci_cmd->params.send_data_ack.pipe_number ); + break; + case ACI_CMD_REQUEST_DATA: + acil_encode_cmd_request_data(buffer, &(p_aci_cmd->params.request_data)); + break; + case ACI_CMD_SET_LOCAL_DATA: + acil_encode_cmd_set_local_data(buffer, (aci_cmd_params_set_local_data_t *)(&(p_aci_cmd->params.send_data)), (p_aci_cmd->len - MSG_SET_LOCAL_DATA_BASE_LEN)); + break; + case ACI_CMD_BOND_SECURITY_REQUEST: + acil_encode_cmd_bond_security_request(buffer); + break; + default: + break; + } + return ret_val; +} + +void acil_decode_evt_command_response(uint8_t *buffer_in, aci_evt_params_cmd_rsp_t *p_evt_params_cmd_rsp) +{ + aci_evt_cmd_rsp_params_get_device_version_t *p_device_version; + aci_evt_cmd_rsp_params_get_device_address_t *p_device_address; + aci_evt_cmd_rsp_params_get_temperature_t *p_temperature; + aci_evt_cmd_rsp_params_get_battery_level_t *p_batt_lvl; + aci_evt_cmd_rsp_read_dynamic_data_t *p_read_dyn_data; + aci_evt_cmd_rsp_params_dtm_cmd_t *p_dtm_evt; + + p_evt_params_cmd_rsp->cmd_opcode = (aci_cmd_opcode_t)*(buffer_in + OFFSET_ACI_EVT_T_CMD_RSP + OFFSET_ACI_EVT_PARAMS_CMD_RSP_T_CMD_OPCODE); + p_evt_params_cmd_rsp->cmd_status = (aci_status_code_t)*(buffer_in + OFFSET_ACI_EVT_T_CMD_RSP + OFFSET_ACI_EVT_PARAMS_CMD_RSP_T_CMD_STATUS); + + switch (p_evt_params_cmd_rsp->cmd_opcode) + { + case ACI_CMD_GET_DEVICE_VERSION: + p_device_version = &(p_evt_params_cmd_rsp->params.get_device_version); + p_device_version->configuration_id = (uint16_t)*(buffer_in + OFFSET_ACI_EVT_T_CMD_RSP + OFFSET_ACI_EVT_PARAMS_CMD_RSP_T_GET_DEVICE_VERSION + OFFSET_ACI_EVT_CMD_RSP_PARAMS_GET_DEVICE_VERSION_T_CONFIGURATION_ID_LSB); + p_device_version->configuration_id |= (uint16_t)*(buffer_in + OFFSET_ACI_EVT_T_CMD_RSP + OFFSET_ACI_EVT_PARAMS_CMD_RSP_T_GET_DEVICE_VERSION + OFFSET_ACI_EVT_CMD_RSP_PARAMS_GET_DEVICE_VERSION_T_CONFIGURATION_ID_MSB) << 8; + p_device_version->aci_version = *(buffer_in + OFFSET_ACI_EVT_T_CMD_RSP + OFFSET_ACI_EVT_PARAMS_CMD_RSP_T_GET_DEVICE_VERSION + OFFSET_ACI_EVT_CMD_RSP_PARAMS_GET_DEVICE_VERSION_T_ACI_VERSION); + p_device_version->setup_format = *(buffer_in + OFFSET_ACI_EVT_T_CMD_RSP + OFFSET_ACI_EVT_PARAMS_CMD_RSP_T_GET_DEVICE_VERSION + OFFSET_ACI_EVT_CMD_RSP_PARAMS_GET_DEVICE_VERSION_T_SETUP_FORMAT); + p_device_version->setup_id = (uint32_t)*(buffer_in + OFFSET_ACI_EVT_T_CMD_RSP + OFFSET_ACI_EVT_PARAMS_CMD_RSP_T_GET_DEVICE_VERSION + OFFSET_ACI_EVT_CMD_RSP_PARAMS_GET_DEVICE_VERSION_T_SETUP_ID_LSB0); + p_device_version->setup_id |= (uint32_t)*(buffer_in + OFFSET_ACI_EVT_T_CMD_RSP + OFFSET_ACI_EVT_PARAMS_CMD_RSP_T_GET_DEVICE_VERSION + OFFSET_ACI_EVT_CMD_RSP_PARAMS_GET_DEVICE_VERSION_T_SETUP_ID_LSB1) << 8; + p_device_version->setup_id |= (uint32_t)*(buffer_in + OFFSET_ACI_EVT_T_CMD_RSP + OFFSET_ACI_EVT_PARAMS_CMD_RSP_T_GET_DEVICE_VERSION + OFFSET_ACI_EVT_CMD_RSP_PARAMS_GET_DEVICE_VERSION_T_SETUP_ID_MSB0) << 16; + p_device_version->setup_id |= (uint32_t)*(buffer_in + OFFSET_ACI_EVT_T_CMD_RSP + OFFSET_ACI_EVT_PARAMS_CMD_RSP_T_GET_DEVICE_VERSION + OFFSET_ACI_EVT_CMD_RSP_PARAMS_GET_DEVICE_VERSION_T_SETUP_ID_MSB1) << 24; + p_device_version->setup_status = *(buffer_in + OFFSET_ACI_EVT_T_CMD_RSP + OFFSET_ACI_EVT_PARAMS_CMD_RSP_T_GET_DEVICE_VERSION + OFFSET_ACI_EVT_CMD_RSP_PARAMS_GET_DEVICE_VERSION_T_SETUP_STATUS); + break; + + case ACI_CMD_GET_DEVICE_ADDRESS: + p_device_address = &(p_evt_params_cmd_rsp->params.get_device_address); + memcpy((uint8_t *)(p_device_address->bd_addr_own), (buffer_in + OFFSET_ACI_EVT_T_CMD_RSP+OFFSET_ACI_EVT_PARAMS_CMD_RSP_T_GET_DEVICE_ADDRESS+OFFSET_ACI_EVT_CMD_RSP_PARAMS_GET_DEVICE_ADDRESS_T_BD_ADDR_OWN), BTLE_DEVICE_ADDRESS_SIZE); + p_device_address->bd_addr_type = (aci_bd_addr_type_t) *(buffer_in + OFFSET_ACI_EVT_T_CMD_RSP+OFFSET_ACI_EVT_PARAMS_CMD_RSP_T_GET_DEVICE_ADDRESS+OFFSET_ACI_EVT_CMD_RSP_PARAMS_GET_DEVICE_ADDRESS_T_BD_ADDR_TYPE); + break; + + case ACI_CMD_GET_TEMPERATURE: + p_temperature = &(p_evt_params_cmd_rsp->params.get_temperature); + p_temperature->temperature_value = (int16_t)*(buffer_in + OFFSET_ACI_EVT_T_CMD_RSP + OFFSET_ACI_EVT_PARAMS_CMD_RSP_T_GET_TEMPERATURE + OFFSET_ACI_EVT_CMD_RSP_PARAMS_GET_TEMPERATURE_T_TEMPERATURE_VALUE_LSB); + p_temperature->temperature_value |= (int16_t)*(buffer_in + OFFSET_ACI_EVT_T_CMD_RSP + OFFSET_ACI_EVT_PARAMS_CMD_RSP_T_GET_TEMPERATURE + OFFSET_ACI_EVT_CMD_RSP_PARAMS_GET_TEMPERATURE_T_TEMPERATURE_VALUE_MSB) << 8; + break; + + case ACI_CMD_GET_BATTERY_LEVEL: + p_batt_lvl = &(p_evt_params_cmd_rsp->params.get_battery_level); + p_batt_lvl->battery_level = (int16_t)*(buffer_in + OFFSET_ACI_EVT_T_CMD_RSP + OFFSET_ACI_EVT_PARAMS_CMD_RSP_T_GET_BATTERY_LEVEL + OFFSET_ACI_EVT_CMD_RSP_PARAMS_GET_BATTERY_LEVEL_T_BATTERY_LEVEL_LSB); + p_batt_lvl->battery_level |= (int16_t)*(buffer_in + OFFSET_ACI_EVT_T_CMD_RSP + OFFSET_ACI_EVT_PARAMS_CMD_RSP_T_GET_BATTERY_LEVEL + OFFSET_ACI_EVT_CMD_RSP_PARAMS_GET_BATTERY_LEVEL_T_BATTERY_LEVEL_MSB) << 8; + break; + + case ACI_CMD_READ_DYNAMIC_DATA: + p_read_dyn_data = &(p_evt_params_cmd_rsp->params.read_dynamic_data); + p_read_dyn_data->seq_no = (uint8_t)*(buffer_in + OFFSET_ACI_EVT_T_CMD_RSP + OFFSET_ACI_EVT_PARAMS_CMD_RSP_T_READ_DYNAMIC_DATA + OFFSET_ACI_EVT_CMD_RSP_READ_DYNAMIC_DATA_T_SEQ_NO); + memcpy((uint8_t *)(p_read_dyn_data->dynamic_data), (buffer_in + OFFSET_ACI_EVT_T_CMD_RSP + OFFSET_ACI_EVT_PARAMS_CMD_RSP_T_READ_DYNAMIC_DATA + OFFSET_ACI_CMD_PARAMS_WRITE_DYNAMIC_DATA_T_DYNAMIC_DATA), ACIL_DECODE_EVT_GET_LENGTH(buffer_in) - 3); // 3 bytes subtracted account for EventCode, CommandOpCode and Status bytes. + // Now that the p_read_dyn_data->dynamic_data will be pointing to memory location with enough space to accommodate upto 27 bytes of dynamic data received. This is because of the padding element in aci_evt_params_cmd_rsp_t + break; + + case ACI_CMD_DTM_CMD: + p_dtm_evt = &(p_evt_params_cmd_rsp->params.dtm_cmd); + p_dtm_evt->evt_msb = (uint8_t)*(buffer_in + OFFSET_ACI_EVT_T_CMD_RSP + OFFSET_ACI_EVT_PARAMS_CMD_RSP_T_DTM_CMD + OFFSET_ACI_EVT_CMD_RSP_PARAMS_DTM_CMD_T_EVT_MSB); + p_dtm_evt->evt_lsb = (uint8_t)*(buffer_in + OFFSET_ACI_EVT_T_CMD_RSP + OFFSET_ACI_EVT_PARAMS_CMD_RSP_T_DTM_CMD + OFFSET_ACI_EVT_CMD_RSP_PARAMS_DTM_CMD_T_EVT_LSB); + break; + } +} + +void acil_decode_evt_device_started(uint8_t *buffer_in, aci_evt_params_device_started_t *p_evt_params_device_started) +{ + p_evt_params_device_started->device_mode = (aci_device_operation_mode_t) *(buffer_in + OFFSET_ACI_EVT_T_DEVICE_STARTED+OFFSET_ACI_EVT_PARAMS_DEVICE_STARTED_T_DEVICE_MODE); + p_evt_params_device_started->hw_error = (aci_hw_error_t) *(buffer_in + OFFSET_ACI_EVT_T_DEVICE_STARTED+OFFSET_ACI_EVT_PARAMS_DEVICE_STARTED_T_HW_ERROR); + p_evt_params_device_started->credit_available = *(buffer_in + OFFSET_ACI_EVT_T_DEVICE_STARTED+OFFSET_ACI_EVT_PARAMS_DEVICE_STARTED_T_CREDIT_AVAILABLE); +} + +void acil_decode_evt_pipe_status(uint8_t *buffer_in, aci_evt_params_pipe_status_t *p_aci_evt_params_pipe_status) +{ + memcpy((uint8_t *)p_aci_evt_params_pipe_status->pipes_open_bitmap, (buffer_in + OFFSET_ACI_EVT_T_PIPE_STATUS + OFFSET_ACI_EVT_PARAMS_PIPE_STATUS_T_PIPES_OPEN_BITMAP), 8); + memcpy((uint8_t *)p_aci_evt_params_pipe_status->pipes_closed_bitmap, (buffer_in + OFFSET_ACI_EVT_T_PIPE_STATUS + OFFSET_ACI_EVT_PARAMS_PIPE_STATUS_T_PIPES_CLOSED_BITMAP), 8); +} + +void acil_decode_evt_disconnected(uint8_t *buffer_in, aci_evt_params_disconnected_t *p_aci_evt_params_disconnected) +{ + p_aci_evt_params_disconnected->aci_status = (aci_status_code_t)*(buffer_in + OFFSET_ACI_EVT_T_DISCONNECTED + OFFSET_ACI_EVT_PARAMS_DISCONNECTED_T_ACI_STATUS); + p_aci_evt_params_disconnected->btle_status = *(buffer_in + OFFSET_ACI_EVT_T_DISCONNECTED + OFFSET_ACI_EVT_PARAMS_DISCONNECTED_T_BTLE_STATUS); +} + +void acil_decode_evt_bond_status(uint8_t *buffer_in, aci_evt_params_bond_status_t *p_aci_evt_params_bond_status) +{ + p_aci_evt_params_bond_status->status_code = (aci_bond_status_code_t)*(buffer_in + OFFSET_ACI_EVT_T_BOND_STATUS + OFFSET_ACI_EVT_PARAMS_BOND_STATUS_T_STATUS_CODE); + p_aci_evt_params_bond_status->status_source = (aci_bond_status_source_t)*(buffer_in + OFFSET_ACI_EVT_T_BOND_STATUS + OFFSET_ACI_EVT_PARAMS_BOND_STATUS_T_STATUS_SOURCE); + p_aci_evt_params_bond_status->secmode1_bitmap = *(buffer_in + OFFSET_ACI_EVT_T_BOND_STATUS + OFFSET_ACI_EVT_PARAMS_BOND_STATUS_T_SECMODE1_BITMAP); + p_aci_evt_params_bond_status->secmode2_bitmap = *(buffer_in + OFFSET_ACI_EVT_T_BOND_STATUS + OFFSET_ACI_EVT_PARAMS_BOND_STATUS_T_SECMODE2_BITMAP); + p_aci_evt_params_bond_status->keys_exchanged_slave = *(buffer_in + OFFSET_ACI_EVT_T_BOND_STATUS + OFFSET_ACI_EVT_PARAMS_BOND_STATUS_T_KEYS_EXCHANGED_SLAVE); + p_aci_evt_params_bond_status->keys_exchanged_master = *(buffer_in + OFFSET_ACI_EVT_T_BOND_STATUS + OFFSET_ACI_EVT_PARAMS_BOND_STATUS_T_KEYS_EXCHANGED_MASTER); +} + +uint8_t acil_decode_evt_data_received(uint8_t *buffer_in, aci_evt_params_data_received_t *p_evt_params_data_received) +{ + uint8_t size = *( buffer_in + OFFSET_ACI_EVT_T_LEN) - (OFFSET_ACI_EVT_T_DATA_RECEIVED + OFFSET_ACI_RX_DATA_T_ACI_DATA) + 1 ; + p_evt_params_data_received->rx_data.pipe_number = *(buffer_in + OFFSET_ACI_EVT_T_DATA_RECEIVED + OFFSET_ACI_RX_DATA_T_PIPE_NUMBER); + memcpy((uint8_t *)p_evt_params_data_received->rx_data.aci_data, (buffer_in + OFFSET_ACI_EVT_T_DATA_RECEIVED + OFFSET_ACI_RX_DATA_T_ACI_DATA), size); + return size; +} + +void acil_decode_evt_data_ack(uint8_t *buffer_in, aci_evt_params_data_ack_t *p_evt_params_data_ack) +{ + p_evt_params_data_ack->pipe_number = *(buffer_in + OFFSET_ACI_EVT_T_DATA_ACK + OFFSET_ACI_EVT_PARAMS_DATA_ACK_T_PIPE_NUMBER); +} + +uint8_t acil_decode_evt_hw_error(uint8_t *buffer_in, aci_evt_params_hw_error_t *p_aci_evt_params_hw_error) +{ + uint8_t size = *(buffer_in + OFFSET_ACI_EVT_T_LEN) - (OFFSET_ACI_EVT_T_HW_ERROR + OFFSET_ACI_EVT_PARAMS_HW_ERROR_T_FILE_NAME) + 1; + p_aci_evt_params_hw_error->line_num = (uint16_t)(*(buffer_in + OFFSET_ACI_EVT_T_HW_ERROR + OFFSET_ACI_EVT_PARAMS_HW_ERROR_T_LINE_NUM_MSB)) << 8; + p_aci_evt_params_hw_error->line_num |= (uint16_t)*(buffer_in + OFFSET_ACI_EVT_T_HW_ERROR + OFFSET_ACI_EVT_PARAMS_HW_ERROR_T_LINE_NUM_LSB); + memcpy((uint8_t *)p_aci_evt_params_hw_error->file_name, (buffer_in + OFFSET_ACI_EVT_T_HW_ERROR + OFFSET_ACI_EVT_PARAMS_HW_ERROR_T_FILE_NAME), size); + return size; +} + +void acil_decode_evt_credit(uint8_t *buffer_in, aci_evt_params_data_credit_t *p_evt_params_data_credit) +{ + p_evt_params_data_credit->credit = *(buffer_in + OFFSET_ACI_EVT_T_DATA_CREDIT + OFFSET_ACI_EVT_PARAMS_DATA_CREDIT_T_CREDIT); +} + +void acil_decode_evt_connected(uint8_t *buffer_in, aci_evt_params_connected_t *p_aci_evt_params_connected) +{ + p_aci_evt_params_connected->dev_addr_type = (aci_bd_addr_type_t)*(buffer_in + OFFSET_ACI_EVT_T_CONNECTED + OFFSET_ACI_EVT_PARAMS_CONNECTED_T_DEV_ADDR_TYPE); + memcpy(&(p_aci_evt_params_connected->dev_addr[0]), (buffer_in + OFFSET_ACI_EVT_T_CONNECTED + OFFSET_ACI_EVT_PARAMS_CONNECTED_T_DEV_ADDR), BTLE_DEVICE_ADDRESS_SIZE); + p_aci_evt_params_connected->conn_rf_interval = (uint16_t)*(buffer_in + OFFSET_ACI_EVT_T_CONNECTED + OFFSET_ACI_EVT_PARAMS_CONNECTED_T_CONN_RF_INTERVAL_MSB) << 8; + p_aci_evt_params_connected->conn_rf_interval |= (uint16_t)*(buffer_in + OFFSET_ACI_EVT_T_CONNECTED + OFFSET_ACI_EVT_PARAMS_CONNECTED_T_CONN_RF_INTERVAL_LSB); + p_aci_evt_params_connected->conn_slave_rf_latency = (uint16_t)*(buffer_in + OFFSET_ACI_EVT_T_CONNECTED + OFFSET_ACI_EVT_PARAMS_CONNECTED_T_CONN_SLAVE_RF_LATENCY_MSB) << 8; + p_aci_evt_params_connected->conn_slave_rf_latency |= (uint16_t)*(buffer_in + OFFSET_ACI_EVT_T_CONNECTED + OFFSET_ACI_EVT_PARAMS_CONNECTED_T_CONN_SLAVE_RF_LATENCY_LSB); + p_aci_evt_params_connected->conn_rf_timeout = (uint16_t)*(buffer_in + OFFSET_ACI_EVT_T_CONNECTED + OFFSET_ACI_EVT_PARAMS_CONNECTED_T_CONN_RF_TIMEOUT_MSB) << 8; + p_aci_evt_params_connected->conn_rf_timeout |= (uint16_t)*(buffer_in + OFFSET_ACI_EVT_T_CONNECTED + OFFSET_ACI_EVT_PARAMS_CONNECTED_T_CONN_RF_TIMEOUT_LSB); + p_aci_evt_params_connected->master_clock_accuracy = (aci_clock_accuracy_t)*(buffer_in + OFFSET_ACI_EVT_T_CONNECTED + OFFSET_ACI_EVT_PARAMS_CONNECTED_T_MASTER_CLOCK_ACCURACY); + +} + +void acil_decode_evt_timing(uint8_t *buffer_in, aci_evt_params_timing_t *p_evt_params_timing) +{ + p_evt_params_timing->conn_rf_interval = *(buffer_in + OFFSET_ACI_EVT_T_TIMING + OFFSET_ACI_EVT_PARAMS_TIMING_T_CONN_RF_INTERVAL_MSB) << 8; + p_evt_params_timing->conn_rf_interval |= (uint16_t)*(buffer_in + OFFSET_ACI_EVT_T_TIMING + OFFSET_ACI_EVT_PARAMS_TIMING_T_CONN_RF_INTERVAL_LSB); + p_evt_params_timing->conn_slave_rf_latency = (uint16_t)*(buffer_in + OFFSET_ACI_EVT_T_TIMING + OFFSET_ACI_EVT_PARAMS_TIMING_T_CONN_SLAVE_RF_LATENCY_MSB) << 8; + p_evt_params_timing->conn_slave_rf_latency |= (uint16_t)*(buffer_in + OFFSET_ACI_EVT_T_TIMING + OFFSET_ACI_EVT_PARAMS_TIMING_T_CONN_SLAVE_RF_LATENCY_LSB); + p_evt_params_timing->conn_rf_timeout = (uint16_t)*(buffer_in + OFFSET_ACI_EVT_T_TIMING + OFFSET_ACI_EVT_PARAMS_TIMING_T_CONN_RF_TIMEOUT_MSB) << 8; + p_evt_params_timing->conn_rf_timeout |= *(buffer_in + OFFSET_ACI_EVT_T_TIMING + OFFSET_ACI_EVT_PARAMS_TIMING_T_CONN_RF_TIMEOUT_LSB); +} + +void acil_decode_evt_pipe_error(uint8_t *buffer_in, aci_evt_params_pipe_error_t *p_evt_params_pipe_error) +{ + //volatile uint8_t size = *(buffer_in + OFFSET_ACI_EVT_T_LEN) - (OFFSET_ACI_EVT_T_PIPE_ERROR + OFFSET_ACI_EVT_PARAMS_PIPE_ERROR_T_ERROR_DATA) + 1; + p_evt_params_pipe_error->pipe_number = *(buffer_in + OFFSET_ACI_EVT_T_PIPE_ERROR + OFFSET_ACI_EVT_PARAMS_PIPE_ERROR_T_PIPE_NUMBER); + p_evt_params_pipe_error->error_code = *(buffer_in + OFFSET_ACI_EVT_T_PIPE_ERROR + OFFSET_ACI_EVT_PARAMS_PIPE_ERROR_T_ERROR_CODE); + p_evt_params_pipe_error->params.error_data.content[0] = *(buffer_in + OFFSET_ACI_EVT_T_PIPE_ERROR + OFFSET_ACI_EVT_PARAMS_PIPE_ERROR_T_ERROR_DATA + OFFSET_ERROR_DATA_T_CONTENT); +} + +void acil_decode_evt_key_request(uint8_t *buffer_in, aci_evt_params_key_request_t *p_evt_params_key_request) +{ + p_evt_params_key_request->key_type = (aci_key_type_t)*(buffer_in + OFFSET_ACI_EVT_T_KEY_REQUEST + OFFSET_ACI_EVT_PARAMS_KEY_REQUEST_T_KEY_TYPE); +} + +uint8_t acil_decode_evt_echo(uint8_t *buffer_in, aci_evt_params_echo_t *aci_evt_params_echo) +{ + uint8_t size = *(buffer_in + OFFSET_ACI_EVT_T_LEN) - 1; + memcpy(&aci_evt_params_echo->echo_data[0], (buffer_in + OFFSET_ACI_EVT_T_EVT_OPCODE + 1), size); + return size; +} + +void acil_decode_evt_display_passkey(uint8_t *buffer_in, aci_evt_params_display_passkey_t *p_aci_evt_params_display_passkey) +{ + p_aci_evt_params_display_passkey->passkey[0] = *(buffer_in + OFFSET_ACI_EVT_T_DISPLAY_PASSKEY + OFFSET_ACI_EVT_PARAMS_DISPLAY_PASSKEY_T_PASSKEY + 0); + p_aci_evt_params_display_passkey->passkey[1] = *(buffer_in + OFFSET_ACI_EVT_T_DISPLAY_PASSKEY + OFFSET_ACI_EVT_PARAMS_DISPLAY_PASSKEY_T_PASSKEY + 1); + p_aci_evt_params_display_passkey->passkey[2] = *(buffer_in + OFFSET_ACI_EVT_T_DISPLAY_PASSKEY + OFFSET_ACI_EVT_PARAMS_DISPLAY_PASSKEY_T_PASSKEY + 2); + p_aci_evt_params_display_passkey->passkey[3] = *(buffer_in + OFFSET_ACI_EVT_T_DISPLAY_PASSKEY + OFFSET_ACI_EVT_PARAMS_DISPLAY_PASSKEY_T_PASSKEY + 3); + p_aci_evt_params_display_passkey->passkey[4] = *(buffer_in + OFFSET_ACI_EVT_T_DISPLAY_PASSKEY + OFFSET_ACI_EVT_PARAMS_DISPLAY_PASSKEY_T_PASSKEY + 4); + p_aci_evt_params_display_passkey->passkey[5] = *(buffer_in + OFFSET_ACI_EVT_T_DISPLAY_PASSKEY + OFFSET_ACI_EVT_PARAMS_DISPLAY_PASSKEY_T_PASSKEY + 5); +} + +bool acil_decode_evt(uint8_t *buffer_in, aci_evt_t *p_aci_evt) +{ + bool ret_val = true; + + p_aci_evt->len = ACIL_DECODE_EVT_GET_LENGTH(buffer_in); + p_aci_evt->evt_opcode = (aci_evt_opcode_t)ACIL_DECODE_EVT_GET_OPCODE(buffer_in); + + switch(p_aci_evt->evt_opcode) + { + case ACI_EVT_DEVICE_STARTED: + acil_decode_evt_device_started(buffer_in, &(p_aci_evt->params.device_started)); + break; + case ACI_EVT_HW_ERROR: + acil_decode_evt_hw_error(buffer_in, &(p_aci_evt->params.hw_error)); + break; + case ACI_EVT_CMD_RSP: + acil_decode_evt_command_response(buffer_in, &(p_aci_evt->params.cmd_rsp)); + break; + case ACI_EVT_DATA_CREDIT: + acil_decode_evt_credit(buffer_in, &(p_aci_evt->params.data_credit)); + break; + case ACI_EVT_CONNECTED: + acil_decode_evt_connected(buffer_in, &(p_aci_evt->params.connected)); + break; + case ACI_EVT_PIPE_STATUS: + acil_decode_evt_pipe_status(buffer_in, &(p_aci_evt->params.pipe_status)); + break; + case ACI_EVT_DISCONNECTED: + acil_decode_evt_disconnected(buffer_in, &(p_aci_evt->params.disconnected)); + break; + case ACI_EVT_BOND_STATUS: + acil_decode_evt_bond_status(buffer_in, &(p_aci_evt->params.bond_status)); + break; + case ACI_EVT_TIMING: + acil_decode_evt_timing(buffer_in, &(p_aci_evt->params.timing)); + break; + case ACI_EVT_DATA_ACK: + acil_decode_evt_data_ack(buffer_in, &(p_aci_evt->params.data_ack)); + break; + case ACI_EVT_DATA_RECEIVED: + acil_decode_evt_data_received(buffer_in, &(p_aci_evt->params.data_received)); + break; + case ACI_EVT_PIPE_ERROR: + acil_decode_evt_pipe_error(buffer_in, &(p_aci_evt->params.pipe_error)); + break; + case ACI_EVT_KEY_REQUEST: + acil_decode_evt_key_request(buffer_in, &(p_aci_evt->params.key_request)); + break; + case ACI_EVT_DISPLAY_PASSKEY: + acil_decode_evt_display_passkey(buffer_in, &(p_aci_evt->params.display_passkey)); + break; + default: + ret_val = false; + break; + } + return ret_val; +} diff --git a/src/nrf8001/acilib.h b/src/nrf8001/acilib.h index d7d20c00..924fba94 100644 --- a/src/nrf8001/acilib.h +++ b/src/nrf8001/acilib.h @@ -1,61 +1,61 @@ -/* Copyright (c) 2014, Nordic Semiconductor ASA - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -/** - * @file - * - * @ingroup aci-lib - * - * @brief Internal prototype for acilib module. - */ - -#ifndef _acilib_H_ -#define _acilib_H_ - -#define MSG_SET_LOCAL_DATA_BASE_LEN 2 -#define MSG_CONNECT_LEN 5 -#define MSG_BOND_LEN 5 -#define MSG_DISCONNECT_LEN 2 -#define MSG_BASEBAND_RESET_LEN 1 -#define MSG_WAKEUP_LEN 1 -#define MSG_SET_RADIO_TX_POWER_LEN 2 -#define MSG_GET_DEVICE_ADDR_LEN 1 -#define MSG_SEND_DATA_BASE_LEN 2 -#define MSG_DATA_REQUEST_LEN 2 -#define MSG_OPEN_REMOTE_PIPE_LEN 2 -#define MSG_CLOSE_REMOTE_PIPE_LEN 2 -#define MSG_DTM_CMD 3 -#define MSG_WRITE_DYNAMIC_DATA_BASE_LEN 2 -#define MSG_SETUP_CMD_BASE_LEN 1 -#define MSG_ECHO_MSG_CMD_BASE_LEN 1 -#define MSG_CHANGE_TIMING_LEN 9 -#define MSG_SET_APP_LATENCY_LEN 4 -#define MSG_CHANGE_TIMING_LEN_GAP_PPCP 1 -#define MSG_DIRECT_CONNECT_LEN 1 -#define MSG_SET_KEY_REJECT_LEN 2 -#define MSG_SET_KEY_PASSKEY_LEN 8 -#define MSG_SET_KEY_OOB_LEN 18 -#define MSG_ACK_LEN 2 -#define MSG_NACK_LEN 3 -#define MSG_BROADCAST_LEN 5 -#define MSG_OPEN_ADV_PIPES_LEN 9 - -#endif /* _acilib_H_ */ +/* Copyright (c) 2014, Nordic Semiconductor ASA + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/** + * @file + * + * @ingroup aci-lib + * + * @brief Internal prototype for acilib module. + */ + +#ifndef _acilib_H_ +#define _acilib_H_ + +#define MSG_SET_LOCAL_DATA_BASE_LEN 2 +#define MSG_CONNECT_LEN 5 +#define MSG_BOND_LEN 5 +#define MSG_DISCONNECT_LEN 2 +#define MSG_BASEBAND_RESET_LEN 1 +#define MSG_WAKEUP_LEN 1 +#define MSG_SET_RADIO_TX_POWER_LEN 2 +#define MSG_GET_DEVICE_ADDR_LEN 1 +#define MSG_SEND_DATA_BASE_LEN 2 +#define MSG_DATA_REQUEST_LEN 2 +#define MSG_OPEN_REMOTE_PIPE_LEN 2 +#define MSG_CLOSE_REMOTE_PIPE_LEN 2 +#define MSG_DTM_CMD 3 +#define MSG_WRITE_DYNAMIC_DATA_BASE_LEN 2 +#define MSG_SETUP_CMD_BASE_LEN 1 +#define MSG_ECHO_MSG_CMD_BASE_LEN 1 +#define MSG_CHANGE_TIMING_LEN 9 +#define MSG_SET_APP_LATENCY_LEN 4 +#define MSG_CHANGE_TIMING_LEN_GAP_PPCP 1 +#define MSG_DIRECT_CONNECT_LEN 1 +#define MSG_SET_KEY_REJECT_LEN 2 +#define MSG_SET_KEY_PASSKEY_LEN 8 +#define MSG_SET_KEY_OOB_LEN 18 +#define MSG_ACK_LEN 2 +#define MSG_NACK_LEN 3 +#define MSG_BROADCAST_LEN 5 +#define MSG_OPEN_ADV_PIPES_LEN 9 + +#endif /* _acilib_H_ */ diff --git a/src/nrf8001/acilib_defs.h b/src/nrf8001/acilib_defs.h index c1934152..503114a7 100644 --- a/src/nrf8001/acilib_defs.h +++ b/src/nrf8001/acilib_defs.h @@ -1,37 +1,37 @@ -/* Copyright (c) 2014, Nordic Semiconductor ASA - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -/** - * @file - * - * @ingroup aci-lib - * - * @brief Definitions for the acilib interfaces - */ - -#ifndef _acilib_DEFS_H_ -#define _acilib_DEFS_H_ - -#define ACIL_DECODE_EVT_GET_LENGTH(buffer_in) (*(buffer_in + OFFSET_ACI_EVT_T_LEN)) - -#define ACIL_DECODE_EVT_GET_OPCODE(buffer_in) (*(buffer_in + OFFSET_ACI_EVT_T_EVT_OPCODE)) - -#endif /* _acilib_DEFS_H_ */ +/* Copyright (c) 2014, Nordic Semiconductor ASA + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/** + * @file + * + * @ingroup aci-lib + * + * @brief Definitions for the acilib interfaces + */ + +#ifndef _acilib_DEFS_H_ +#define _acilib_DEFS_H_ + +#define ACIL_DECODE_EVT_GET_LENGTH(buffer_in) (*(buffer_in + OFFSET_ACI_EVT_T_LEN)) + +#define ACIL_DECODE_EVT_GET_OPCODE(buffer_in) (*(buffer_in + OFFSET_ACI_EVT_T_EVT_OPCODE)) + +#endif /* _acilib_DEFS_H_ */ diff --git a/src/nrf8001/acilib_if.h b/src/nrf8001/acilib_if.h index 483e893b..37879aae 100644 --- a/src/nrf8001/acilib_if.h +++ b/src/nrf8001/acilib_if.h @@ -1,471 +1,471 @@ -/* Copyright (c) 2014, Nordic Semiconductor ASA - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -/** - * @file - * - * @ingroup aci-lib - * - * @brief Prototypes for the acilib interfaces. - */ - -#ifndef _acilib_IF_H_ -#define _acilib_IF_H_ - -/** @brief Encode the ACI message for set test mode command - * - * @param[in,out] buffer Pointer to ACI message buffer - * @param[in] test_mode Pointer to the test mode in ::aci_cmd_params_test_t - * - * @return None - */ -void acil_encode_cmd_set_test_mode(uint8_t *buffer, aci_cmd_params_test_t *p_aci_cmd_params_test); - -/** @brief Encode the ACI message for sleep command - * - * @param[in,out] buffer Pointer to ACI message buffer - * - * @return None - */ -void acil_encode_cmd_sleep(uint8_t *buffer); - -/** @brief Encode the ACI message for get device version - * - * @param[in,out] buffer Pointer to ACI message buffer - * - * @return None - */ -void acil_encode_cmd_get_device_version(uint8_t *buffer); - -/** @brief Encode the ACI message for set local data - * - * @param[in,out] buffer Pointer to ACI message buffer - * @param[in] p_aci_cmd_params_set_local_data Pointer to the local data parameters in ::aci_cmd_params_set_local_data_t - * @param[in] data_size Size of data message - * - * @return None - */ -void acil_encode_cmd_set_local_data(uint8_t *buffer, aci_cmd_params_set_local_data_t *p_aci_cmd_params_set_local_data, uint8_t data_size); - -/** @brief Encode the ACI message to connect - * - * @param[in,out] buffer Pointer to ACI message buffer - * @param[in] p_aci_cmd_params_connect Pointer to the run parameters in ::aci_cmd_params_connect_t - * - * @return None - */ -void acil_encode_cmd_connect(uint8_t *buffer, aci_cmd_params_connect_t *p_aci_cmd_params_connect); - -/** @brief Encode the ACI message to bond - * - * @param[in,out] buffer Pointer to ACI message buffer - * @param[in] p_aci_cmd_params_bond Pointer to the run parameters in ::aci_cmd_params_bond_t - * - * @return None - */ -void acil_encode_cmd_bond(uint8_t *buffer, aci_cmd_params_bond_t *p_aci_cmd_params_bond); - -/** @brief Encode the ACI message to disconnect - * - * @param[in,out] buffer Pointer to ACI message buffer - * @param[in] p_aci_cmd_params_disconnect Pointer to the run parameters in ::aci_cmd_params_disconnect_t - * - * @return None - */ -void acil_encode_cmd_disconnect(uint8_t *buffer, aci_cmd_params_disconnect_t *p_aci_cmd_params_disconnect); - -/** @brief Encode the ACI message to baseband reset - * - * @param[in,out] buffer Pointer to ACI message buffer - * - * @return None - */ - void acil_encode_baseband_reset(uint8_t *buffer); - - /** @brief Encode the ACI message for Directed Advertising - * - * @param[in,out] buffer Pointer to ACI message buffer - * - * @return None - */ - void acil_encode_direct_connect(uint8_t *buffer); - -/** @brief Encode the ACI message to wakeup - * - * @param[in,out] buffer Pointer to ACI message buffer - * - * @return None - */ -void acil_encode_cmd_wakeup(uint8_t *buffer); - -/** @brief Encode the ACI message for set radio Tx power - * - * @param[in,out] buffer Pointer to ACI message buffer - * @param[in] p_aci_cmd_params_set_tx_power Pointer to the set Tx power parameters in ::aci_cmd_params_set_tx_power_t - * - * @return None - */ -void acil_encode_cmd_set_radio_tx_power(uint8_t *buffer, aci_cmd_params_set_tx_power_t *p_aci_cmd_params_set_tx_power); - -/** @brief Encode the ACI message for get device address - * - * @param[in,out] buffer Pointer to ACI message buffer - * - * @return None - */ -void acil_encode_cmd_get_address(uint8_t *buffer); - -/** @brief Encode the ACI message for send data - * - * @param[in,out] buffer Pointer to ACI message buffer - * @param[in] p_aci_cmd_params_send_data_t Pointer to the data parameters in ::aci_cmd_params_send_data_t - * @param[in] data_size Size of data message - * - * @return None - */ -void acil_encode_cmd_send_data(uint8_t *buffer, aci_cmd_params_send_data_t *p_aci_cmd_params_send_data_t, uint8_t data_size); - -/** @brief Encode the ACI message for request data - * - * @param[in,out] buffer Pointer to ACI message buffer - * @param[in] p_aci_cmd_params_request_data Pointer to the request data parameters in ::aci_cmd_params_request_data_t - * - * @return None - */ -void acil_encode_cmd_request_data(uint8_t *buffer, aci_cmd_params_request_data_t *p_aci_cmd_params_request_data); - -/** @brief Encode the ACI message for open remote pipe - * - * @param[in,out] buffer Pointer to ACI message buffer - * @param[in] p_aci_cmd_params_open_remote_pipe Pointer to the dynamic data parameters in ::aci_cmd_params_open_remote_pipe_t - * - * @return None - */ -void acil_encode_cmd_open_remote_pipe(uint8_t *buffer, aci_cmd_params_open_remote_pipe_t *p_aci_cmd_params_open_remote_pipe); - -/** @brief Encode the ACI message for close remote pipe - * - * @param[in,out] buffer Pointer to ACI message buffer - * @param[in] p_aci_cmd_params_close_remote_pipe Pointer to the dynamic data parameters in ::aci_cmd_params_close_remote_pipe_t - * - * @return None - */ -void acil_encode_cmd_close_remote_pipe(uint8_t *buffer, aci_cmd_params_close_remote_pipe_t *p_aci_cmd_params_close_remote_pipe); - -/** @brief Encode the ACI message for echo message - * - * @param[in,out] buffer Pointer to ACI message buffer - * @param[in] p_cmd_params_echo Pointer to the dynamic data parameters in ::aci_cmd_params_echo_t - * @param[in] msg_size Size of the message - * - * @return None - */ -void acil_encode_cmd_echo_msg(uint8_t *buffer, aci_cmd_params_echo_t *p_cmd_params_echo, uint8_t msg_size); - -/** @brief Encode the ACI message to battery level - * - * @param[in,out] buffer Pointer to ACI message buffer - * - * @return None - */ -void acil_encode_cmd_battery_level(uint8_t *buffer); - -/** @brief Encode the ACI message to temparature - * - * @param[in,out] buffer Pointer to ACI message buffer - * - * @return None - */ -void acil_encode_cmd_temparature(uint8_t *buffer); - -/** @brief Encode the ACI message to read dynamic data - * - * @param[in,out] buffer Pointer to ACI message buffer - * - * @return None - */ -void acil_encode_cmd_read_dynamic_data(uint8_t *buffer); - -/** @brief Encode the ACI message to change timing request - * - * @param[in,out] buffer Pointer to ACI message buffer - * @param[in] p_aci_cmd_params_change_timing Pointer to the change timing parameters in ::aci_cmd_params_change_timing_t - * - * @return None - */ -void acil_encode_cmd_change_timing_req(uint8_t *buffer, aci_cmd_params_change_timing_t *p_aci_cmd_params_change_timing); - -/** @brief Encode the ACI message to change timing request using the timing parameters from GAP PPCP - * - * @param[in,out] buffer Pointer to ACI message buffer - * @param[in] p_aci_cmd_params_change_timing Pointer to the change timing parameters in ::aci_cmd_params_change_timing_t - * - * @return None - */ -void acil_encode_cmd_change_timing_req_GAP_PPCP(uint8_t *buffer); - - -/** @brief Encode the ACI message for write dynamic data - * - * @param[in,out] buffer Pointer to ACI message buffer - * @param[in] seq_no Sequence number of the dynamic data (as received in the response to @c Read Dynamic Data) - * @param[in] dynamic_data Pointer to the dynamic data - * @param[in] dynamic_data_size Size of dynamic data - * - * @return None - */ -void acil_encode_cmd_write_dynamic_data(uint8_t *buffer, uint8_t seq_no, uint8_t* dynamic_data, uint8_t dynamic_data_size); - -/** @brief Encode the ACI message to send data acknowledgement - * - * @param[in,out] buffer Pointer to ACI message buffer - * @param[in] pipe_number Pipe number for which the ack is to be sent - * - * @return None - */ -void acil_encode_cmd_send_data_ack(uint8_t *buffer, const uint8_t pipe_number); - -/** @brief Encode the ACI message to send negative acknowledgement - * - * @param[in,out] buffer Pointer to ACI message buffer - * @param[in] pipe_number Pipe number for which the nack is to be sent - * @param[in] error_code Error code that has to be sent in the NACK - * - * @return None - */ -void acil_encode_cmd_send_data_nack(uint8_t *buffer, const uint8_t pipe_number,const uint8_t error_code); - -/** @brief Encode the ACI message to set the application latency - * - * @param[in,out] buffer Pointer to ACI message buffer - * @param[in] p_aci_cmd_params_set_app_latency Pointer to the set_application_latency command parameters in ::aci_cmd_params_dtm_cmd_t - * - * @return None - */ -void acil_encode_cmd_set_app_latency(uint8_t *buffer, aci_cmd_params_set_app_latency_t *p_aci_cmd_params_set_app_latency); - -/** @brief Encode the ACI message for setup - * - * @param[in,out] buffer Pointer to ACI message buffer - * @param[in] p_cmd_params_set_run_behaviour Pointer to the setup data in ::aci_cmd_params_setup_t - * @param[in] setup_data_size Size of setup message - * - * @return None - */ -void acil_encode_cmd_setup(uint8_t *buffer, aci_cmd_params_setup_t *p_aci_cmd_params_setup, uint8_t setup_data_size); - -/** @brief Encode the ACI message for DTM command - * - * @param[in,out] buffer Pointer to ACI message buffer - * @param[in] p_cmd_params_set_run_behaviour Pointer to the DTM command parameters in ::aci_cmd_params_dtm_cmd_t - * - * @return None - */ -void acil_encode_cmd_dtm_cmd(uint8_t *buffer, aci_cmd_params_dtm_cmd_t *p_aci_cmd_params_dtm_cmd); - -/** @brief Encode the ACI message for Set Key Request command - * - * @param[in,out] buffer Pointer to ACI message buffer - * - * @return None - */ -void acil_encode_cmd_set_key(uint8_t *buffer, aci_cmd_params_set_key_t *p_aci_cmd_params_set_key); - -/** @brief Encode the ACI message for Bond Security Request command - * - * @param[in,out] buffer Pointer to ACI message buffer - * - * @return None - */ -void acil_encode_cmd_bond_security_request(uint8_t *buffer); - -/** @brief Encode the ACI message - * - * @param[in,out] buffer Pointer to ACI message buffer - * @param[in] p_aci_cmd Pointer to ACI command data in ::aci_cmd_t - * @param[in] bool - * - * @return bool true, if succesful, else returns false - */ -bool acil_encode_cmd(uint8_t *buffer, aci_cmd_t *p_aci_cmd); - -/** @brief Encode the ACI message for Broadcast command - * - * @param[in,out] buffer Pointer to ACI message buffer - * @param[in] p_aci_cmd Pointer to ACI command data in ::aci_cmd_params_broadcast_t - * - * @return None - */ -void acil_encode_cmd_broadcast(uint8_t *buffer, aci_cmd_params_broadcast_t * p_aci_cmd_params_broadcast); - -/** @brief Encode the ACI message for Open Adv Pipes - * - * @param[in,out] buffer Pointer to ACI message buffer - * @param[in] p_aci_cmd Pointer to ACI command data in ::aci_cmd_params_open_adv_pipe_t - * - * @return None - */ -void acil_encode_cmd_open_adv_pipes(uint8_t *buffer, aci_cmd_params_open_adv_pipe_t * p_aci_cmd_params_set_adv_svc_data); - -/** @brief Decode the ACI event command response - * - * @param[in] buffer_in Pointer to message received - * @param[in,out] buffer Pointer to the decoded message in ::aci_evt_params_cmd_rsp_t - * - * @return None - */ -void acil_decode_evt_command_response(uint8_t *buffer_in, aci_evt_params_cmd_rsp_t *p_evt_params_cmd_rsp); - -/** @brief Decode the ACI event device started - * - * @param[in] buffer_in Pointer to message received - * @param[in,out] p_aci_evt Pointer to the decoded message in ::aci_evt_params_device_started_t - * - * @return None - */ -void acil_decode_evt_device_started(uint8_t *buffer_in, aci_evt_params_device_started_t *p_evt_params_device_started); - -/** @brief Decode the ACI event pipe status - * - * @param[in] buffer_in Pointer to message received - * @param[in,out] p_aci_evt_params_pipe_status Pointer to the decoded message in ::aci_evt_params_pipe_status_t - * - * @return None - */ -void acil_decode_evt_pipe_status(uint8_t *buffer_in, aci_evt_params_pipe_status_t *p_aci_evt_params_pipe_status); - -/** @brief Decode the ACI event for disconnected - * - * @param[in] buffer_in Pointer to message received - * @param[in,out] p_aci_evt_params_disconnected Pointer to the decoded message in ::aci_evt_params_disconnected_t - * - * @return None - */ -void acil_decode_evt_disconnected(uint8_t *buffer_in, aci_evt_params_disconnected_t *p_aci_evt_params_disconnected); - -/** @brief Decode the ACI event for bond status - * - * @param[in] buffer_in Pointer to message received - * @param[in,out] p_aci_evt_params_bond_status Pointer to the decoded message in ::aci_evt_params_bond_status_t - * - * @return None - */ -void acil_decode_evt_bond_status(uint8_t *buffer_in, aci_evt_params_bond_status_t *p_aci_evt_params_bond_status); - -/** @brief Decode the ACI event for data received - * - * @param[in] buffer_in Pointer to message received - * @param[in,out] p_evt_params_data_received Pointer to the decoded message in ::aci_evt_params_data_received_t - * - * @return size Received data size - */ -uint8_t acil_decode_evt_data_received(uint8_t *buffer_in, aci_evt_params_data_received_t *p_evt_params_data_received); - -/** @brief Decode the ACI event data acknowledgement - * - * @param[in] buffer_in Pointer to message received - * @param[in,out] p_evt_params_data_ack Pointer to the decoded message in ::aci_evt_params_data_ack_t - * - * @return None - */ -void acil_decode_evt_data_ack(uint8_t *buffer_in, aci_evt_params_data_ack_t *p_evt_params_data_ack); - -/** @brief Decode the ACI event for hardware error - * - * @param[in] buffer_in Pointer to message received - * @param[in,out] p_aci_evt_params_hw_error Pointer to the decoded message in ::aci_evt_params_hw_error_t - * - * @return size Size of debug information - */ -uint8_t acil_decode_evt_hw_error(uint8_t *buffer_in, aci_evt_params_hw_error_t *p_aci_evt_params_hw_error); - -/** @brief Decode the ACI event data credit - * - * @param[in] buffer_in Pointer to message received - * @param[in,out] p_evt_params_data_credit Pointer to the decoded message in ::aci_evt_params_data_credit_t - * - * @return None - */ -void acil_decode_evt_credit(uint8_t *buffer_in, aci_evt_params_data_credit_t *p_evt_params_data_credit); - -/** @brief Decode the ACI event for connected - * - * @param[in] buffer_in Pointer to message received - * @param[in,out] p_aci_evt_params_connected Pointer to the decoded message in ::aci_evt_params_connected_t - * - * @return None - */ -void acil_decode_evt_connected(uint8_t *buffer_in, aci_evt_params_connected_t *p_aci_evt_params_connected); - -/** @brief Decode the ACI event for timing - * - * @param[in] buffer_in Pointer to message received - * @param[in,out] p_evt_params_timing Pointer to the decoded message in ::aci_evt_params_timing_t - * - * @return None - */ -void acil_decode_evt_timing(uint8_t *buffer_in, aci_evt_params_timing_t *p_evt_params_timing); - -/** @brief Decode the ACI event for pipe error - * - * @param[in] buffer_in Pointer to message received - * @param[in,out] p_evt_params_pipe_error Pointer to the decoded message in ::aci_evt_params_pipe_error_t - * - */ -void acil_decode_evt_pipe_error(uint8_t *buffer_in, aci_evt_params_pipe_error_t *p_evt_params_pipe_error); - -/** @brief Decode the ACI event for key request - * - * @param[in] buffer_in Pointer to message received - * @param[in,out] p_evt_params_key_type Pointer to the decoded message in ::aci_evt_params_key_type_t - * - * @return None - */ -void acil_decode_evt_key_request(uint8_t *buffer_in, aci_evt_params_key_request_t *p_evt_params_key_request); - -/** @brief Decode the ACI event for echo - * - * @param[in] buffer_in Pointer to message received - * @param[in,out] buffer_out Pointer to the echo message (max size of buffer ::ACI_ECHO_DATA_MAX_LEN) - * - * @return size Received echo message size - */ -uint8_t acil_decode_evt_echo(uint8_t *buffer_in, aci_evt_params_echo_t *buffer_out); - -/** @brief Decode the ACI event - * - * @param[in] buffer_in Pointer to message received - * @param[in,out] p_aci_evt Pointer to the decoded message in ::aci_evt_t - * - * @return bool true, if succesful, else returns false - */ -bool acil_decode_evt(uint8_t *buffer_in, aci_evt_t *p_aci_evt); - -/** @brief Decode the Display Key Event - * - * @param[in] buffer_in Pointer to message received - * @param[in,out] p_aci_evt Pointer to the decoded message in ::aci_evt_params_display_passkey_t - * - * @return None - */ -void acil_decode_evt_display_passkey(uint8_t *buffer_in, aci_evt_params_display_passkey_t *p_aci_evt_params_display_passkey); - -#endif /* _acilib_IF_H_ */ +/* Copyright (c) 2014, Nordic Semiconductor ASA + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/** + * @file + * + * @ingroup aci-lib + * + * @brief Prototypes for the acilib interfaces. + */ + +#ifndef _acilib_IF_H_ +#define _acilib_IF_H_ + +/** @brief Encode the ACI message for set test mode command + * + * @param[in,out] buffer Pointer to ACI message buffer + * @param[in] test_mode Pointer to the test mode in ::aci_cmd_params_test_t + * + * @return None + */ +void acil_encode_cmd_set_test_mode(uint8_t *buffer, aci_cmd_params_test_t *p_aci_cmd_params_test); + +/** @brief Encode the ACI message for sleep command + * + * @param[in,out] buffer Pointer to ACI message buffer + * + * @return None + */ +void acil_encode_cmd_sleep(uint8_t *buffer); + +/** @brief Encode the ACI message for get device version + * + * @param[in,out] buffer Pointer to ACI message buffer + * + * @return None + */ +void acil_encode_cmd_get_device_version(uint8_t *buffer); + +/** @brief Encode the ACI message for set local data + * + * @param[in,out] buffer Pointer to ACI message buffer + * @param[in] p_aci_cmd_params_set_local_data Pointer to the local data parameters in ::aci_cmd_params_set_local_data_t + * @param[in] data_size Size of data message + * + * @return None + */ +void acil_encode_cmd_set_local_data(uint8_t *buffer, aci_cmd_params_set_local_data_t *p_aci_cmd_params_set_local_data, uint8_t data_size); + +/** @brief Encode the ACI message to connect + * + * @param[in,out] buffer Pointer to ACI message buffer + * @param[in] p_aci_cmd_params_connect Pointer to the run parameters in ::aci_cmd_params_connect_t + * + * @return None + */ +void acil_encode_cmd_connect(uint8_t *buffer, aci_cmd_params_connect_t *p_aci_cmd_params_connect); + +/** @brief Encode the ACI message to bond + * + * @param[in,out] buffer Pointer to ACI message buffer + * @param[in] p_aci_cmd_params_bond Pointer to the run parameters in ::aci_cmd_params_bond_t + * + * @return None + */ +void acil_encode_cmd_bond(uint8_t *buffer, aci_cmd_params_bond_t *p_aci_cmd_params_bond); + +/** @brief Encode the ACI message to disconnect + * + * @param[in,out] buffer Pointer to ACI message buffer + * @param[in] p_aci_cmd_params_disconnect Pointer to the run parameters in ::aci_cmd_params_disconnect_t + * + * @return None + */ +void acil_encode_cmd_disconnect(uint8_t *buffer, aci_cmd_params_disconnect_t *p_aci_cmd_params_disconnect); + +/** @brief Encode the ACI message to baseband reset + * + * @param[in,out] buffer Pointer to ACI message buffer + * + * @return None + */ + void acil_encode_baseband_reset(uint8_t *buffer); + + /** @brief Encode the ACI message for Directed Advertising + * + * @param[in,out] buffer Pointer to ACI message buffer + * + * @return None + */ + void acil_encode_direct_connect(uint8_t *buffer); + +/** @brief Encode the ACI message to wakeup + * + * @param[in,out] buffer Pointer to ACI message buffer + * + * @return None + */ +void acil_encode_cmd_wakeup(uint8_t *buffer); + +/** @brief Encode the ACI message for set radio Tx power + * + * @param[in,out] buffer Pointer to ACI message buffer + * @param[in] p_aci_cmd_params_set_tx_power Pointer to the set Tx power parameters in ::aci_cmd_params_set_tx_power_t + * + * @return None + */ +void acil_encode_cmd_set_radio_tx_power(uint8_t *buffer, aci_cmd_params_set_tx_power_t *p_aci_cmd_params_set_tx_power); + +/** @brief Encode the ACI message for get device address + * + * @param[in,out] buffer Pointer to ACI message buffer + * + * @return None + */ +void acil_encode_cmd_get_address(uint8_t *buffer); + +/** @brief Encode the ACI message for send data + * + * @param[in,out] buffer Pointer to ACI message buffer + * @param[in] p_aci_cmd_params_send_data_t Pointer to the data parameters in ::aci_cmd_params_send_data_t + * @param[in] data_size Size of data message + * + * @return None + */ +void acil_encode_cmd_send_data(uint8_t *buffer, aci_cmd_params_send_data_t *p_aci_cmd_params_send_data_t, uint8_t data_size); + +/** @brief Encode the ACI message for request data + * + * @param[in,out] buffer Pointer to ACI message buffer + * @param[in] p_aci_cmd_params_request_data Pointer to the request data parameters in ::aci_cmd_params_request_data_t + * + * @return None + */ +void acil_encode_cmd_request_data(uint8_t *buffer, aci_cmd_params_request_data_t *p_aci_cmd_params_request_data); + +/** @brief Encode the ACI message for open remote pipe + * + * @param[in,out] buffer Pointer to ACI message buffer + * @param[in] p_aci_cmd_params_open_remote_pipe Pointer to the dynamic data parameters in ::aci_cmd_params_open_remote_pipe_t + * + * @return None + */ +void acil_encode_cmd_open_remote_pipe(uint8_t *buffer, aci_cmd_params_open_remote_pipe_t *p_aci_cmd_params_open_remote_pipe); + +/** @brief Encode the ACI message for close remote pipe + * + * @param[in,out] buffer Pointer to ACI message buffer + * @param[in] p_aci_cmd_params_close_remote_pipe Pointer to the dynamic data parameters in ::aci_cmd_params_close_remote_pipe_t + * + * @return None + */ +void acil_encode_cmd_close_remote_pipe(uint8_t *buffer, aci_cmd_params_close_remote_pipe_t *p_aci_cmd_params_close_remote_pipe); + +/** @brief Encode the ACI message for echo message + * + * @param[in,out] buffer Pointer to ACI message buffer + * @param[in] p_cmd_params_echo Pointer to the dynamic data parameters in ::aci_cmd_params_echo_t + * @param[in] msg_size Size of the message + * + * @return None + */ +void acil_encode_cmd_echo_msg(uint8_t *buffer, aci_cmd_params_echo_t *p_cmd_params_echo, uint8_t msg_size); + +/** @brief Encode the ACI message to battery level + * + * @param[in,out] buffer Pointer to ACI message buffer + * + * @return None + */ +void acil_encode_cmd_battery_level(uint8_t *buffer); + +/** @brief Encode the ACI message to temparature + * + * @param[in,out] buffer Pointer to ACI message buffer + * + * @return None + */ +void acil_encode_cmd_temparature(uint8_t *buffer); + +/** @brief Encode the ACI message to read dynamic data + * + * @param[in,out] buffer Pointer to ACI message buffer + * + * @return None + */ +void acil_encode_cmd_read_dynamic_data(uint8_t *buffer); + +/** @brief Encode the ACI message to change timing request + * + * @param[in,out] buffer Pointer to ACI message buffer + * @param[in] p_aci_cmd_params_change_timing Pointer to the change timing parameters in ::aci_cmd_params_change_timing_t + * + * @return None + */ +void acil_encode_cmd_change_timing_req(uint8_t *buffer, aci_cmd_params_change_timing_t *p_aci_cmd_params_change_timing); + +/** @brief Encode the ACI message to change timing request using the timing parameters from GAP PPCP + * + * @param[in,out] buffer Pointer to ACI message buffer + * @param[in] p_aci_cmd_params_change_timing Pointer to the change timing parameters in ::aci_cmd_params_change_timing_t + * + * @return None + */ +void acil_encode_cmd_change_timing_req_GAP_PPCP(uint8_t *buffer); + + +/** @brief Encode the ACI message for write dynamic data + * + * @param[in,out] buffer Pointer to ACI message buffer + * @param[in] seq_no Sequence number of the dynamic data (as received in the response to @c Read Dynamic Data) + * @param[in] dynamic_data Pointer to the dynamic data + * @param[in] dynamic_data_size Size of dynamic data + * + * @return None + */ +void acil_encode_cmd_write_dynamic_data(uint8_t *buffer, uint8_t seq_no, uint8_t* dynamic_data, uint8_t dynamic_data_size); + +/** @brief Encode the ACI message to send data acknowledgement + * + * @param[in,out] buffer Pointer to ACI message buffer + * @param[in] pipe_number Pipe number for which the ack is to be sent + * + * @return None + */ +void acil_encode_cmd_send_data_ack(uint8_t *buffer, const uint8_t pipe_number); + +/** @brief Encode the ACI message to send negative acknowledgement + * + * @param[in,out] buffer Pointer to ACI message buffer + * @param[in] pipe_number Pipe number for which the nack is to be sent + * @param[in] error_code Error code that has to be sent in the NACK + * + * @return None + */ +void acil_encode_cmd_send_data_nack(uint8_t *buffer, const uint8_t pipe_number,const uint8_t error_code); + +/** @brief Encode the ACI message to set the application latency + * + * @param[in,out] buffer Pointer to ACI message buffer + * @param[in] p_aci_cmd_params_set_app_latency Pointer to the set_application_latency command parameters in ::aci_cmd_params_dtm_cmd_t + * + * @return None + */ +void acil_encode_cmd_set_app_latency(uint8_t *buffer, aci_cmd_params_set_app_latency_t *p_aci_cmd_params_set_app_latency); + +/** @brief Encode the ACI message for setup + * + * @param[in,out] buffer Pointer to ACI message buffer + * @param[in] p_cmd_params_set_run_behaviour Pointer to the setup data in ::aci_cmd_params_setup_t + * @param[in] setup_data_size Size of setup message + * + * @return None + */ +void acil_encode_cmd_setup(uint8_t *buffer, aci_cmd_params_setup_t *p_aci_cmd_params_setup, uint8_t setup_data_size); + +/** @brief Encode the ACI message for DTM command + * + * @param[in,out] buffer Pointer to ACI message buffer + * @param[in] p_cmd_params_set_run_behaviour Pointer to the DTM command parameters in ::aci_cmd_params_dtm_cmd_t + * + * @return None + */ +void acil_encode_cmd_dtm_cmd(uint8_t *buffer, aci_cmd_params_dtm_cmd_t *p_aci_cmd_params_dtm_cmd); + +/** @brief Encode the ACI message for Set Key Request command + * + * @param[in,out] buffer Pointer to ACI message buffer + * + * @return None + */ +void acil_encode_cmd_set_key(uint8_t *buffer, aci_cmd_params_set_key_t *p_aci_cmd_params_set_key); + +/** @brief Encode the ACI message for Bond Security Request command + * + * @param[in,out] buffer Pointer to ACI message buffer + * + * @return None + */ +void acil_encode_cmd_bond_security_request(uint8_t *buffer); + +/** @brief Encode the ACI message + * + * @param[in,out] buffer Pointer to ACI message buffer + * @param[in] p_aci_cmd Pointer to ACI command data in ::aci_cmd_t + * @param[in] bool + * + * @return bool true, if succesful, else returns false + */ +bool acil_encode_cmd(uint8_t *buffer, aci_cmd_t *p_aci_cmd); + +/** @brief Encode the ACI message for Broadcast command + * + * @param[in,out] buffer Pointer to ACI message buffer + * @param[in] p_aci_cmd Pointer to ACI command data in ::aci_cmd_params_broadcast_t + * + * @return None + */ +void acil_encode_cmd_broadcast(uint8_t *buffer, aci_cmd_params_broadcast_t * p_aci_cmd_params_broadcast); + +/** @brief Encode the ACI message for Open Adv Pipes + * + * @param[in,out] buffer Pointer to ACI message buffer + * @param[in] p_aci_cmd Pointer to ACI command data in ::aci_cmd_params_open_adv_pipe_t + * + * @return None + */ +void acil_encode_cmd_open_adv_pipes(uint8_t *buffer, aci_cmd_params_open_adv_pipe_t * p_aci_cmd_params_set_adv_svc_data); + +/** @brief Decode the ACI event command response + * + * @param[in] buffer_in Pointer to message received + * @param[in,out] buffer Pointer to the decoded message in ::aci_evt_params_cmd_rsp_t + * + * @return None + */ +void acil_decode_evt_command_response(uint8_t *buffer_in, aci_evt_params_cmd_rsp_t *p_evt_params_cmd_rsp); + +/** @brief Decode the ACI event device started + * + * @param[in] buffer_in Pointer to message received + * @param[in,out] p_aci_evt Pointer to the decoded message in ::aci_evt_params_device_started_t + * + * @return None + */ +void acil_decode_evt_device_started(uint8_t *buffer_in, aci_evt_params_device_started_t *p_evt_params_device_started); + +/** @brief Decode the ACI event pipe status + * + * @param[in] buffer_in Pointer to message received + * @param[in,out] p_aci_evt_params_pipe_status Pointer to the decoded message in ::aci_evt_params_pipe_status_t + * + * @return None + */ +void acil_decode_evt_pipe_status(uint8_t *buffer_in, aci_evt_params_pipe_status_t *p_aci_evt_params_pipe_status); + +/** @brief Decode the ACI event for disconnected + * + * @param[in] buffer_in Pointer to message received + * @param[in,out] p_aci_evt_params_disconnected Pointer to the decoded message in ::aci_evt_params_disconnected_t + * + * @return None + */ +void acil_decode_evt_disconnected(uint8_t *buffer_in, aci_evt_params_disconnected_t *p_aci_evt_params_disconnected); + +/** @brief Decode the ACI event for bond status + * + * @param[in] buffer_in Pointer to message received + * @param[in,out] p_aci_evt_params_bond_status Pointer to the decoded message in ::aci_evt_params_bond_status_t + * + * @return None + */ +void acil_decode_evt_bond_status(uint8_t *buffer_in, aci_evt_params_bond_status_t *p_aci_evt_params_bond_status); + +/** @brief Decode the ACI event for data received + * + * @param[in] buffer_in Pointer to message received + * @param[in,out] p_evt_params_data_received Pointer to the decoded message in ::aci_evt_params_data_received_t + * + * @return size Received data size + */ +uint8_t acil_decode_evt_data_received(uint8_t *buffer_in, aci_evt_params_data_received_t *p_evt_params_data_received); + +/** @brief Decode the ACI event data acknowledgement + * + * @param[in] buffer_in Pointer to message received + * @param[in,out] p_evt_params_data_ack Pointer to the decoded message in ::aci_evt_params_data_ack_t + * + * @return None + */ +void acil_decode_evt_data_ack(uint8_t *buffer_in, aci_evt_params_data_ack_t *p_evt_params_data_ack); + +/** @brief Decode the ACI event for hardware error + * + * @param[in] buffer_in Pointer to message received + * @param[in,out] p_aci_evt_params_hw_error Pointer to the decoded message in ::aci_evt_params_hw_error_t + * + * @return size Size of debug information + */ +uint8_t acil_decode_evt_hw_error(uint8_t *buffer_in, aci_evt_params_hw_error_t *p_aci_evt_params_hw_error); + +/** @brief Decode the ACI event data credit + * + * @param[in] buffer_in Pointer to message received + * @param[in,out] p_evt_params_data_credit Pointer to the decoded message in ::aci_evt_params_data_credit_t + * + * @return None + */ +void acil_decode_evt_credit(uint8_t *buffer_in, aci_evt_params_data_credit_t *p_evt_params_data_credit); + +/** @brief Decode the ACI event for connected + * + * @param[in] buffer_in Pointer to message received + * @param[in,out] p_aci_evt_params_connected Pointer to the decoded message in ::aci_evt_params_connected_t + * + * @return None + */ +void acil_decode_evt_connected(uint8_t *buffer_in, aci_evt_params_connected_t *p_aci_evt_params_connected); + +/** @brief Decode the ACI event for timing + * + * @param[in] buffer_in Pointer to message received + * @param[in,out] p_evt_params_timing Pointer to the decoded message in ::aci_evt_params_timing_t + * + * @return None + */ +void acil_decode_evt_timing(uint8_t *buffer_in, aci_evt_params_timing_t *p_evt_params_timing); + +/** @brief Decode the ACI event for pipe error + * + * @param[in] buffer_in Pointer to message received + * @param[in,out] p_evt_params_pipe_error Pointer to the decoded message in ::aci_evt_params_pipe_error_t + * + */ +void acil_decode_evt_pipe_error(uint8_t *buffer_in, aci_evt_params_pipe_error_t *p_evt_params_pipe_error); + +/** @brief Decode the ACI event for key request + * + * @param[in] buffer_in Pointer to message received + * @param[in,out] p_evt_params_key_type Pointer to the decoded message in ::aci_evt_params_key_type_t + * + * @return None + */ +void acil_decode_evt_key_request(uint8_t *buffer_in, aci_evt_params_key_request_t *p_evt_params_key_request); + +/** @brief Decode the ACI event for echo + * + * @param[in] buffer_in Pointer to message received + * @param[in,out] buffer_out Pointer to the echo message (max size of buffer ::ACI_ECHO_DATA_MAX_LEN) + * + * @return size Received echo message size + */ +uint8_t acil_decode_evt_echo(uint8_t *buffer_in, aci_evt_params_echo_t *buffer_out); + +/** @brief Decode the ACI event + * + * @param[in] buffer_in Pointer to message received + * @param[in,out] p_aci_evt Pointer to the decoded message in ::aci_evt_t + * + * @return bool true, if succesful, else returns false + */ +bool acil_decode_evt(uint8_t *buffer_in, aci_evt_t *p_aci_evt); + +/** @brief Decode the Display Key Event + * + * @param[in] buffer_in Pointer to message received + * @param[in,out] p_aci_evt Pointer to the decoded message in ::aci_evt_params_display_passkey_t + * + * @return None + */ +void acil_decode_evt_display_passkey(uint8_t *buffer_in, aci_evt_params_display_passkey_t *p_aci_evt_params_display_passkey); + +#endif /* _acilib_IF_H_ */ diff --git a/src/nrf8001/acilib_types.h b/src/nrf8001/acilib_types.h index 438ea3c8..5c427397 100644 --- a/src/nrf8001/acilib_types.h +++ b/src/nrf8001/acilib_types.h @@ -1,33 +1,33 @@ -/* Copyright (c) 2014, Nordic Semiconductor ASA - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -/** - * @file - * - * @ingroup aci-lib - * - * @brief Type used in the acilib interfaces - */ - -#ifndef _acilib_TYPES_H_ -#define _acilib_TYPES_H_ - -#endif /* _acilib_TYPES_H_ */ +/* Copyright (c) 2014, Nordic Semiconductor ASA + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/** + * @file + * + * @ingroup aci-lib + * + * @brief Type used in the acilib interfaces + */ + +#ifndef _acilib_TYPES_H_ +#define _acilib_TYPES_H_ + +#endif /* _acilib_TYPES_H_ */ diff --git a/src/nrf8001/boards.h b/src/nrf8001/boards.h index c84db0a4..64bb4cb6 100644 --- a/src/nrf8001/boards.h +++ b/src/nrf8001/boards.h @@ -1,36 +1,36 @@ -/* Copyright (c) 2014, Nordic Semiconductor ASA - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -/** - * @file - * @brief Defines for the different Bluetooth low energy boards - * @ingroup nrf8001 - */ - -#ifndef _BLE_BOARDS_H_ -#define _BLE_BOARDS_H_ - -#define BOARD_DEFAULT 0 /**< Use this if you do not know the board you are using or you are creating a new one */ -#define REDBEARLAB_SHIELD_V1_1 1 /**< Redbearlab Bluetooth low energy shield v1.1 */ -#define REDBEARLAB_SHIELD_V2012_07 1 /**< Identical to Redbearlab v1.1 shield */ -#define REDBEARLAB_SHIELD_V2 0 /**< Redbearlab Bluetooth low energy shield v2.x - No special handling required for pin reset same as default */ - -#endif +/* Copyright (c) 2014, Nordic Semiconductor ASA + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/** + * @file + * @brief Defines for the different Bluetooth low energy boards + * @ingroup nrf8001 + */ + +#ifndef _BLE_BOARDS_H_ +#define _BLE_BOARDS_H_ + +#define BOARD_DEFAULT 0 /**< Use this if you do not know the board you are using or you are creating a new one */ +#define REDBEARLAB_SHIELD_V1_1 1 /**< Redbearlab Bluetooth low energy shield v1.1 */ +#define REDBEARLAB_SHIELD_V2012_07 1 /**< Identical to Redbearlab v1.1 shield */ +#define REDBEARLAB_SHIELD_V2 0 /**< Redbearlab Bluetooth low energy shield v2.x - No special handling required for pin reset same as default */ + +#endif diff --git a/src/nrf8001/dtm.h b/src/nrf8001/dtm.h index 9ae01c5f..b6ddf56a 100644 --- a/src/nrf8001/dtm.h +++ b/src/nrf8001/dtm.h @@ -1,63 +1,63 @@ -/* Copyright (c) 2014, Nordic Semiconductor ASA - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -/** - * @file - * - * @ingroup aci-lib - * - * @brief Internal prototype for acilib module. - */ - -#ifndef DTM_H__ -#define DTM_H__ - -/** @brief DTM command codes (upper two bits in the DTM command), use a bitwise OR with the frequency N = 0x00 - 0x27: N = (F-2402)/2 Frequency Range 2402 MHz -to 2480 MHz*/ -#define DTM_LE_CMD_RESET 0x00 /**< DTM reset command code */ -#define DTM_LE_CMD_RECEIVER_TEST 0x40 /**< DTM receiver test command code */ -#define DTM_LE_CMD_TRANSMITTER_TEST 0x80 /**< DTM transmitter test command code */ -#define DTM_LE_CMD_TEST_END 0xC0 /**< DTM test end command code */ - - -/** @brief Defined packet types for DTM */ -#define DTM_LE_PKT_PRBS9 0x00 /**< Bit pattern PRBS9. */ -#define DTM_LE_PKT_0X0F 0x01 /**< Bit pattern 11110000 (LSB is the leftmost bit). */ -#define DTM_LE_PKT_0X55 0x02 /**< Bit pattern 10101010 (LSB is the leftmost bit). */ -#define DTM_LE_PKT_VENDOR 0x03 /**< Vendor specific. Nordic: continous carrier test */ - -/** @brief Defined bit fields for DTM responses. */ -#define LE_PACKET_REPORTING_EVENT_MSB_BIT 0x80 /**< Bit field for most significant bit */ -#define LE_TEST_STATUS_EVENT_LSB_BIT 0x01 /**< Bit field for least significant bit */ - -/** @brief DTM response types. */ -#define LE_TEST_STATUS_EVENT 0x00 /**< DTM event response */ -#define LE_TEST_PACKET_REPORT_EVENT 0x80 /**< DTM packet report reponse */ - -/** @brief DTM return values. */ -#define LE_TEST_STATUS_SUCCESS 0x00 /**< DTM success return value */ -#define LE_TEST_STATUS_FAILURE 0x01 /**< DTM failure return value */ - - - -#endif //DTM_H__ - -/** @} */ +/* Copyright (c) 2014, Nordic Semiconductor ASA + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/** + * @file + * + * @ingroup aci-lib + * + * @brief Internal prototype for acilib module. + */ + +#ifndef DTM_H__ +#define DTM_H__ + +/** @brief DTM command codes (upper two bits in the DTM command), use a bitwise OR with the frequency N = 0x00 - 0x27: N = (F-2402)/2 Frequency Range 2402 MHz +to 2480 MHz*/ +#define DTM_LE_CMD_RESET 0x00 /**< DTM reset command code */ +#define DTM_LE_CMD_RECEIVER_TEST 0x40 /**< DTM receiver test command code */ +#define DTM_LE_CMD_TRANSMITTER_TEST 0x80 /**< DTM transmitter test command code */ +#define DTM_LE_CMD_TEST_END 0xC0 /**< DTM test end command code */ + + +/** @brief Defined packet types for DTM */ +#define DTM_LE_PKT_PRBS9 0x00 /**< Bit pattern PRBS9. */ +#define DTM_LE_PKT_0X0F 0x01 /**< Bit pattern 11110000 (LSB is the leftmost bit). */ +#define DTM_LE_PKT_0X55 0x02 /**< Bit pattern 10101010 (LSB is the leftmost bit). */ +#define DTM_LE_PKT_VENDOR 0x03 /**< Vendor specific. Nordic: continous carrier test */ + +/** @brief Defined bit fields for DTM responses. */ +#define LE_PACKET_REPORTING_EVENT_MSB_BIT 0x80 /**< Bit field for most significant bit */ +#define LE_TEST_STATUS_EVENT_LSB_BIT 0x01 /**< Bit field for least significant bit */ + +/** @brief DTM response types. */ +#define LE_TEST_STATUS_EVENT 0x00 /**< DTM event response */ +#define LE_TEST_PACKET_REPORT_EVENT 0x80 /**< DTM packet report reponse */ + +/** @brief DTM return values. */ +#define LE_TEST_STATUS_SUCCESS 0x00 /**< DTM success return value */ +#define LE_TEST_STATUS_FAILURE 0x01 /**< DTM failure return value */ + + + +#endif //DTM_H__ + +/** @} */ diff --git a/src/nrf8001/hal_aci_tl.cpp b/src/nrf8001/hal_aci_tl.cpp index 2610baea..84d0865f 100644 --- a/src/nrf8001/hal_aci_tl.cpp +++ b/src/nrf8001/hal_aci_tl.cpp @@ -1,459 +1,459 @@ -/* Copyright (c) 2014, Nordic Semiconductor ASA - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -/** @file -@brief Implementation of the ACI transport layer module -*/ - -#include -#include -#include - -#include "hal_platform.h" -#include "hal_aci_tl.h" -#include "aci_queue.h" - -#define HIGH 1 -#define LOW 0 - -#define REVERSE_BITS(byte) (((reverse_lookup[(byte & 0x0F)]) << 4) + reverse_lookup[((byte & 0xF0) >> 4)]) -static const uint8_t reverse_lookup[] = { 0, 8, 4, 12, 2, 10, 6, 14,1, 9, 5, 13,3, 11, 7, 15 }; - -static void m_aci_data_print(hal_aci_data_t *p_data); -static void m_aci_event_check(void); -static void m_aci_isr(void); -static void m_aci_pins_set(aci_pins_t *a_pins_ptr); -static inline void m_aci_reqn_disable (void); -static inline void m_aci_reqn_enable (void); -static void m_aci_q_flush(void); -static bool m_aci_spi_transfer(hal_aci_data_t * data_to_send, hal_aci_data_t * received_data); - -static uint8_t spi_readwrite(uint8_t aci_byte); - -static bool aci_debug_print = false; - -aci_queue_t aci_tx_q; -aci_queue_t aci_rx_q; - -static aci_pins_t *a_pins_local_ptr; - -void m_aci_data_print(hal_aci_data_t *p_data) -{ - const uint8_t length = p_data->buffer[0]; - uint8_t i; - printf("%d\n", length); - printf(" :\n"); - for (i=0; i<=length; i++) - { - printf("%x", p_data->buffer[i]); - printf(", "); - } - printf("\n"); -} - -/* - Interrupt service routine called when the RDYN line goes low. Runs the SPI transfer. -*/ -static void m_aci_isr(void) -{ - hal_aci_data_t data_to_send; - hal_aci_data_t received_data; - - // Receive from queue - if (!aci_queue_dequeue_from_isr(&aci_tx_q, &data_to_send)) - { - /* queue was empty, nothing to send */ - data_to_send.status_byte = 0; - data_to_send.buffer[0] = 0; - } - - // Receive and/or transmit data - m_aci_spi_transfer(&data_to_send, &received_data); - - if (!aci_queue_is_full_from_isr(&aci_rx_q) && !aci_queue_is_empty_from_isr(&aci_tx_q)) - { - m_aci_reqn_enable(); - } - - // Check if we received data - if (received_data.buffer[0] > 0) - { - if (!aci_queue_enqueue_from_isr(&aci_rx_q, &received_data)) - { - /* Receive Buffer full. - Should never happen. - Spin in a while loop. - */ - while(1); - } - - // Disable ready line interrupt until we have room to store incoming messages - if (aci_queue_is_full_from_isr(&aci_rx_q)) - { - // detachInterrupt(a_pins_local_ptr->interrupt_number); - } - } - - return; -} - -/* - Checks the RDYN line and runs the SPI transfer if required. -*/ -static void m_aci_event_check(void) -{ - hal_aci_data_t data_to_send; - hal_aci_data_t received_data; - - // No room to store incoming messages - if (aci_queue_is_full(&aci_rx_q)) - { - return; - } - - // If the ready line is disabled and we have pending messages outgoing we enable the request line - if (HIGH == mraa_gpio_read (a_pins_local_ptr->m_rdy_ctx)) - // if (HIGH == digitalRead(a_pins_local_ptr->rdyn_pin)) - { - if (!aci_queue_is_empty(&aci_tx_q)) - { - m_aci_reqn_enable(); - } - - return; - } - - // Receive from queue - if (!aci_queue_dequeue(&aci_tx_q, &data_to_send)) - { - /* queue was empty, nothing to send */ - data_to_send.status_byte = 0; - data_to_send.buffer[0] = 0; - } - - // Receive and/or transmit data - m_aci_spi_transfer(&data_to_send, &received_data); - - /* If there are messages to transmit, and we can store the reply, we request a new transfer */ - if (!aci_queue_is_full(&aci_rx_q) && !aci_queue_is_empty(&aci_tx_q)) - { - m_aci_reqn_enable(); - } - - // Check if we received data - if (received_data.buffer[0] > 0) - { - if (!aci_queue_enqueue(&aci_rx_q, &received_data)) - { - /* Receive Buffer full. - Should never happen. - Spin in a while loop. - */ - while(1); - } - } - - return; -} - -/** @brief Point the low level library at the ACI pins specified - * @details - * The ACI pins are specified in the application and a pointer is made available for - * the low level library to use - */ -static void m_aci_pins_set(aci_pins_t *a_pins_ptr) -{ - a_pins_local_ptr = a_pins_ptr; -} - -static inline void m_aci_reqn_disable (void) -{ - mraa_gpio_write (a_pins_local_ptr->m_req_ctx, HIGH); -} - -static inline void m_aci_reqn_enable (void) -{ - mraa_gpio_write (a_pins_local_ptr->m_req_ctx, LOW); -} - -static void m_aci_q_flush(void) -{ - // noInterrupts(); - /* re-initialize aci cmd queue and aci event queue to flush them*/ - aci_queue_init(&aci_tx_q); - aci_queue_init(&aci_rx_q); - // interrupts(); -} - -static bool m_aci_spi_transfer(hal_aci_data_t * data_to_send, hal_aci_data_t * received_data) -{ - uint8_t byte_cnt; - uint8_t byte_sent_cnt; - uint8_t max_bytes; - - m_aci_reqn_enable(); - - // Send length, receive header - byte_sent_cnt = 0; - received_data->status_byte = spi_readwrite(data_to_send->buffer[byte_sent_cnt++]); - // Send first byte, receive length from slave - received_data->buffer[0] = spi_readwrite(data_to_send->buffer[byte_sent_cnt++]); - if (0 == data_to_send->buffer[0]) - { - max_bytes = received_data->buffer[0]; - } - else - { - // Set the maximum to the biggest size. One command byte is already sent - max_bytes = (received_data->buffer[0] > (data_to_send->buffer[0] - 1)) - ? received_data->buffer[0] - : (data_to_send->buffer[0] - 1); - } - - if (max_bytes > HAL_ACI_MAX_LENGTH) - { - max_bytes = HAL_ACI_MAX_LENGTH; - } - - // Transmit/receive the rest of the packet - for (byte_cnt = 0; byte_cnt < max_bytes; byte_cnt++) - { - received_data->buffer[byte_cnt+1] = spi_readwrite(data_to_send->buffer[byte_sent_cnt++]); - } - - // RDYN should follow the REQN line in approx 100ns - m_aci_reqn_disable(); - - return (max_bytes > 0); -} - -void hal_aci_tl_debug_print(bool enable) -{ - aci_debug_print = enable; -} - -void hal_aci_tl_pin_reset(void) -{ - if (UNUSED != a_pins_local_ptr->reset_pin) - { - // pinMode(a_pins_local_ptr->reset_pin, OUTPUT); - - if ((REDBEARLAB_SHIELD_V1_1 == a_pins_local_ptr->board_name) || - (REDBEARLAB_SHIELD_V2012_07 == a_pins_local_ptr->board_name)) - { - //The reset for the Redbearlab v1.1 and v2012.07 boards are inverted and has a Power On Reset - //circuit that takes about 100ms to trigger the reset - mraa_gpio_write (a_pins_local_ptr->m_rst_ctx, HIGH); - usleep (100000); - mraa_gpio_write (a_pins_local_ptr->m_rst_ctx, LOW); - } - else - { - mraa_gpio_write (a_pins_local_ptr->m_rst_ctx, HIGH); - mraa_gpio_write (a_pins_local_ptr->m_rst_ctx, LOW); - mraa_gpio_write (a_pins_local_ptr->m_rst_ctx, HIGH); - } - } -} - -bool hal_aci_tl_event_peek(hal_aci_data_t *p_aci_data) -{ - if (!a_pins_local_ptr->interface_is_interrupt) - { - m_aci_event_check(); - } - - if (aci_queue_peek(&aci_rx_q, p_aci_data)) - { - return true; - } - - return false; -} - -bool hal_aci_tl_event_get(hal_aci_data_t *p_aci_data) -{ - bool was_full; - - if (!a_pins_local_ptr->interface_is_interrupt && !aci_queue_is_full(&aci_rx_q)) - { - m_aci_event_check(); - } - - was_full = aci_queue_is_full(&aci_rx_q); - - if (aci_queue_dequeue(&aci_rx_q, p_aci_data)) - { - if (aci_debug_print) - { - printf(" E"); - m_aci_data_print(p_aci_data); - } - - if (was_full && a_pins_local_ptr->interface_is_interrupt) - { - /* Enable RDY line interrupt again */ - // attachInterrupt(a_pins_local_ptr->interrupt_number, m_aci_isr, LOW); - } - - /* Attempt to pull REQN LOW since we've made room for new messages */ - if (!aci_queue_is_full(&aci_rx_q) && !aci_queue_is_empty(&aci_tx_q)) - { - m_aci_reqn_enable(); - } - - return true; - } - - return false; -} - -void hal_aci_tl_init(aci_pins_t *a_pins, bool debug) -{ - mraa_result_t error = MRAA_SUCCESS; - aci_debug_print = debug; - - /* Needs to be called as the first thing for proper intialization*/ - m_aci_pins_set(a_pins); - - /* - * Init SPI - */ - a_pins->m_spi = mraa_spi_init (0); - if (a_pins->m_spi == NULL) { - throw std::invalid_argument(std::string(__FUNCTION__) + - ": mraa_spi_init() failed"); - } - - mraa_spi_frequency (a_pins->m_spi, 2000000); - mraa_spi_mode (a_pins->m_spi, MRAA_SPI_MODE0); - - /* Initialize the ACI Command queue. This must be called after the delay above. */ - aci_queue_init(&aci_tx_q); - aci_queue_init(&aci_rx_q); - - // Configure the IO lines - a_pins->m_rdy_ctx = mraa_gpio_init (a_pins->rdyn_pin); - if (a_pins->m_rdy_ctx == NULL) { - throw std::invalid_argument(std::string(__FUNCTION__) + - ": mraa_gpio_init(rdyn) failed, invalid pin?"); - } - - a_pins->m_req_ctx = mraa_gpio_init (a_pins->reqn_pin); - if (a_pins->m_req_ctx == NULL) { - throw std::invalid_argument(std::string(__FUNCTION__) + - ": mraa_gpio_init(reqn) failed, invalid pin?"); - } - - a_pins->m_rst_ctx = mraa_gpio_init (a_pins->reset_pin); - if (a_pins->m_rst_ctx == NULL) { - throw std::invalid_argument(std::string(__FUNCTION__) + - ": mraa_gpio_init(reset) failed, invalid pin?"); - } - - error = mraa_gpio_dir (a_pins->m_rdy_ctx, MRAA_GPIO_IN); - if (error != MRAA_SUCCESS) { - printf ("[ERROR] GPIO failed to initialize \n"); - } - - error = mraa_gpio_dir (a_pins->m_req_ctx, MRAA_GPIO_OUT); - if (error != MRAA_SUCCESS) { - printf ("[ERROR] GPIO failed to initialize \n"); - } - - error = mraa_gpio_dir (a_pins->m_rst_ctx, MRAA_GPIO_OUT); - if (error != MRAA_SUCCESS) { - printf ("[ERROR] GPIO failed to initialize \n"); - } - - if (UNUSED != a_pins->active_pin) { - } - - /* Pin reset the nRF8001, required when the nRF8001 setup is being changed */ - hal_aci_tl_pin_reset(); - - /* Set the nRF8001 to a known state as required by the datasheet*/ - mraa_gpio_write (a_pins->m_req_ctx, LOW); - - usleep(30000); //Wait for the nRF8001 to get hold of its lines - the lines float for a few ms after the reset - - /* Attach the interrupt to the RDYN line as requested by the caller */ - if (a_pins->interface_is_interrupt) { - // We use the LOW level of the RDYN line as the atmega328 can wakeup from sleep only on LOW - // attachInterrupt(a_pins->interrupt_number, m_aci_isr, LOW); - } -} - -bool hal_aci_tl_send(hal_aci_data_t *p_aci_cmd) -{ - const uint8_t length = p_aci_cmd->buffer[0]; - bool ret_val = false; - - if (length > HAL_ACI_MAX_LENGTH) - { - return false; - } - - ret_val = aci_queue_enqueue(&aci_tx_q, p_aci_cmd); - if (ret_val) - { - if(!aci_queue_is_full(&aci_rx_q)) - { - // Lower the REQN only when successfully enqueued - m_aci_reqn_enable(); - } - } - - return ret_val; -} - -static uint8_t spi_readwrite(const uint8_t aci_byte) -{ - uint8_t reversed, ret; - reversed = mraa_spi_write (a_pins_local_ptr->m_spi, REVERSE_BITS (aci_byte)); - ret = REVERSE_BITS (reversed); - return ret; -} - -bool hal_aci_tl_rx_q_empty (void) -{ - return aci_queue_is_empty(&aci_rx_q); -} - -bool hal_aci_tl_rx_q_full (void) -{ - return aci_queue_is_full(&aci_rx_q); -} - -bool hal_aci_tl_tx_q_empty (void) -{ - return aci_queue_is_empty(&aci_tx_q); -} - -bool hal_aci_tl_tx_q_full (void) -{ - return aci_queue_is_full(&aci_tx_q); -} - -void hal_aci_tl_q_flush (void) -{ - m_aci_q_flush(); -} +/* Copyright (c) 2014, Nordic Semiconductor ASA + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/** @file +@brief Implementation of the ACI transport layer module +*/ + +#include +#include +#include + +#include "hal_platform.h" +#include "hal_aci_tl.h" +#include "aci_queue.h" + +#define HIGH 1 +#define LOW 0 + +#define REVERSE_BITS(byte) (((reverse_lookup[(byte & 0x0F)]) << 4) + reverse_lookup[((byte & 0xF0) >> 4)]) +static const uint8_t reverse_lookup[] = { 0, 8, 4, 12, 2, 10, 6, 14,1, 9, 5, 13,3, 11, 7, 15 }; + +static void m_aci_data_print(hal_aci_data_t *p_data); +static void m_aci_event_check(void); +static void m_aci_isr(void); +static void m_aci_pins_set(aci_pins_t *a_pins_ptr); +static inline void m_aci_reqn_disable (void); +static inline void m_aci_reqn_enable (void); +static void m_aci_q_flush(void); +static bool m_aci_spi_transfer(hal_aci_data_t * data_to_send, hal_aci_data_t * received_data); + +static uint8_t spi_readwrite(uint8_t aci_byte); + +static bool aci_debug_print = false; + +aci_queue_t aci_tx_q; +aci_queue_t aci_rx_q; + +static aci_pins_t *a_pins_local_ptr; + +void m_aci_data_print(hal_aci_data_t *p_data) +{ + const uint8_t length = p_data->buffer[0]; + uint8_t i; + printf("%d\n", length); + printf(" :\n"); + for (i=0; i<=length; i++) + { + printf("%x", p_data->buffer[i]); + printf(", "); + } + printf("\n"); +} + +/* + Interrupt service routine called when the RDYN line goes low. Runs the SPI transfer. +*/ +static void m_aci_isr(void) +{ + hal_aci_data_t data_to_send; + hal_aci_data_t received_data; + + // Receive from queue + if (!aci_queue_dequeue_from_isr(&aci_tx_q, &data_to_send)) + { + /* queue was empty, nothing to send */ + data_to_send.status_byte = 0; + data_to_send.buffer[0] = 0; + } + + // Receive and/or transmit data + m_aci_spi_transfer(&data_to_send, &received_data); + + if (!aci_queue_is_full_from_isr(&aci_rx_q) && !aci_queue_is_empty_from_isr(&aci_tx_q)) + { + m_aci_reqn_enable(); + } + + // Check if we received data + if (received_data.buffer[0] > 0) + { + if (!aci_queue_enqueue_from_isr(&aci_rx_q, &received_data)) + { + /* Receive Buffer full. + Should never happen. + Spin in a while loop. + */ + while(1); + } + + // Disable ready line interrupt until we have room to store incoming messages + if (aci_queue_is_full_from_isr(&aci_rx_q)) + { + // detachInterrupt(a_pins_local_ptr->interrupt_number); + } + } + + return; +} + +/* + Checks the RDYN line and runs the SPI transfer if required. +*/ +static void m_aci_event_check(void) +{ + hal_aci_data_t data_to_send; + hal_aci_data_t received_data; + + // No room to store incoming messages + if (aci_queue_is_full(&aci_rx_q)) + { + return; + } + + // If the ready line is disabled and we have pending messages outgoing we enable the request line + if (HIGH == mraa_gpio_read (a_pins_local_ptr->m_rdy_ctx)) + // if (HIGH == digitalRead(a_pins_local_ptr->rdyn_pin)) + { + if (!aci_queue_is_empty(&aci_tx_q)) + { + m_aci_reqn_enable(); + } + + return; + } + + // Receive from queue + if (!aci_queue_dequeue(&aci_tx_q, &data_to_send)) + { + /* queue was empty, nothing to send */ + data_to_send.status_byte = 0; + data_to_send.buffer[0] = 0; + } + + // Receive and/or transmit data + m_aci_spi_transfer(&data_to_send, &received_data); + + /* If there are messages to transmit, and we can store the reply, we request a new transfer */ + if (!aci_queue_is_full(&aci_rx_q) && !aci_queue_is_empty(&aci_tx_q)) + { + m_aci_reqn_enable(); + } + + // Check if we received data + if (received_data.buffer[0] > 0) + { + if (!aci_queue_enqueue(&aci_rx_q, &received_data)) + { + /* Receive Buffer full. + Should never happen. + Spin in a while loop. + */ + while(1); + } + } + + return; +} + +/** @brief Point the low level library at the ACI pins specified + * @details + * The ACI pins are specified in the application and a pointer is made available for + * the low level library to use + */ +static void m_aci_pins_set(aci_pins_t *a_pins_ptr) +{ + a_pins_local_ptr = a_pins_ptr; +} + +static inline void m_aci_reqn_disable (void) +{ + mraa_gpio_write (a_pins_local_ptr->m_req_ctx, HIGH); +} + +static inline void m_aci_reqn_enable (void) +{ + mraa_gpio_write (a_pins_local_ptr->m_req_ctx, LOW); +} + +static void m_aci_q_flush(void) +{ + // noInterrupts(); + /* re-initialize aci cmd queue and aci event queue to flush them*/ + aci_queue_init(&aci_tx_q); + aci_queue_init(&aci_rx_q); + // interrupts(); +} + +static bool m_aci_spi_transfer(hal_aci_data_t * data_to_send, hal_aci_data_t * received_data) +{ + uint8_t byte_cnt; + uint8_t byte_sent_cnt; + uint8_t max_bytes; + + m_aci_reqn_enable(); + + // Send length, receive header + byte_sent_cnt = 0; + received_data->status_byte = spi_readwrite(data_to_send->buffer[byte_sent_cnt++]); + // Send first byte, receive length from slave + received_data->buffer[0] = spi_readwrite(data_to_send->buffer[byte_sent_cnt++]); + if (0 == data_to_send->buffer[0]) + { + max_bytes = received_data->buffer[0]; + } + else + { + // Set the maximum to the biggest size. One command byte is already sent + max_bytes = (received_data->buffer[0] > (data_to_send->buffer[0] - 1)) + ? received_data->buffer[0] + : (data_to_send->buffer[0] - 1); + } + + if (max_bytes > HAL_ACI_MAX_LENGTH) + { + max_bytes = HAL_ACI_MAX_LENGTH; + } + + // Transmit/receive the rest of the packet + for (byte_cnt = 0; byte_cnt < max_bytes; byte_cnt++) + { + received_data->buffer[byte_cnt+1] = spi_readwrite(data_to_send->buffer[byte_sent_cnt++]); + } + + // RDYN should follow the REQN line in approx 100ns + m_aci_reqn_disable(); + + return (max_bytes > 0); +} + +void hal_aci_tl_debug_print(bool enable) +{ + aci_debug_print = enable; +} + +void hal_aci_tl_pin_reset(void) +{ + if (UNUSED != a_pins_local_ptr->reset_pin) + { + // pinMode(a_pins_local_ptr->reset_pin, OUTPUT); + + if ((REDBEARLAB_SHIELD_V1_1 == a_pins_local_ptr->board_name) || + (REDBEARLAB_SHIELD_V2012_07 == a_pins_local_ptr->board_name)) + { + //The reset for the Redbearlab v1.1 and v2012.07 boards are inverted and has a Power On Reset + //circuit that takes about 100ms to trigger the reset + mraa_gpio_write (a_pins_local_ptr->m_rst_ctx, HIGH); + usleep (100000); + mraa_gpio_write (a_pins_local_ptr->m_rst_ctx, LOW); + } + else + { + mraa_gpio_write (a_pins_local_ptr->m_rst_ctx, HIGH); + mraa_gpio_write (a_pins_local_ptr->m_rst_ctx, LOW); + mraa_gpio_write (a_pins_local_ptr->m_rst_ctx, HIGH); + } + } +} + +bool hal_aci_tl_event_peek(hal_aci_data_t *p_aci_data) +{ + if (!a_pins_local_ptr->interface_is_interrupt) + { + m_aci_event_check(); + } + + if (aci_queue_peek(&aci_rx_q, p_aci_data)) + { + return true; + } + + return false; +} + +bool hal_aci_tl_event_get(hal_aci_data_t *p_aci_data) +{ + bool was_full; + + if (!a_pins_local_ptr->interface_is_interrupt && !aci_queue_is_full(&aci_rx_q)) + { + m_aci_event_check(); + } + + was_full = aci_queue_is_full(&aci_rx_q); + + if (aci_queue_dequeue(&aci_rx_q, p_aci_data)) + { + if (aci_debug_print) + { + printf(" E"); + m_aci_data_print(p_aci_data); + } + + if (was_full && a_pins_local_ptr->interface_is_interrupt) + { + /* Enable RDY line interrupt again */ + // attachInterrupt(a_pins_local_ptr->interrupt_number, m_aci_isr, LOW); + } + + /* Attempt to pull REQN LOW since we've made room for new messages */ + if (!aci_queue_is_full(&aci_rx_q) && !aci_queue_is_empty(&aci_tx_q)) + { + m_aci_reqn_enable(); + } + + return true; + } + + return false; +} + +void hal_aci_tl_init(aci_pins_t *a_pins, bool debug) +{ + mraa_result_t error = MRAA_SUCCESS; + aci_debug_print = debug; + + /* Needs to be called as the first thing for proper intialization*/ + m_aci_pins_set(a_pins); + + /* + * Init SPI + */ + a_pins->m_spi = mraa_spi_init (0); + if (a_pins->m_spi == NULL) { + throw std::invalid_argument(std::string(__FUNCTION__) + + ": mraa_spi_init() failed"); + } + + mraa_spi_frequency (a_pins->m_spi, 2000000); + mraa_spi_mode (a_pins->m_spi, MRAA_SPI_MODE0); + + /* Initialize the ACI Command queue. This must be called after the delay above. */ + aci_queue_init(&aci_tx_q); + aci_queue_init(&aci_rx_q); + + // Configure the IO lines + a_pins->m_rdy_ctx = mraa_gpio_init (a_pins->rdyn_pin); + if (a_pins->m_rdy_ctx == NULL) { + throw std::invalid_argument(std::string(__FUNCTION__) + + ": mraa_gpio_init(rdyn) failed, invalid pin?"); + } + + a_pins->m_req_ctx = mraa_gpio_init (a_pins->reqn_pin); + if (a_pins->m_req_ctx == NULL) { + throw std::invalid_argument(std::string(__FUNCTION__) + + ": mraa_gpio_init(reqn) failed, invalid pin?"); + } + + a_pins->m_rst_ctx = mraa_gpio_init (a_pins->reset_pin); + if (a_pins->m_rst_ctx == NULL) { + throw std::invalid_argument(std::string(__FUNCTION__) + + ": mraa_gpio_init(reset) failed, invalid pin?"); + } + + error = mraa_gpio_dir (a_pins->m_rdy_ctx, MRAA_GPIO_IN); + if (error != MRAA_SUCCESS) { + printf ("[ERROR] GPIO failed to initialize \n"); + } + + error = mraa_gpio_dir (a_pins->m_req_ctx, MRAA_GPIO_OUT); + if (error != MRAA_SUCCESS) { + printf ("[ERROR] GPIO failed to initialize \n"); + } + + error = mraa_gpio_dir (a_pins->m_rst_ctx, MRAA_GPIO_OUT); + if (error != MRAA_SUCCESS) { + printf ("[ERROR] GPIO failed to initialize \n"); + } + + if (UNUSED != a_pins->active_pin) { + } + + /* Pin reset the nRF8001, required when the nRF8001 setup is being changed */ + hal_aci_tl_pin_reset(); + + /* Set the nRF8001 to a known state as required by the datasheet*/ + mraa_gpio_write (a_pins->m_req_ctx, LOW); + + usleep(30000); //Wait for the nRF8001 to get hold of its lines - the lines float for a few ms after the reset + + /* Attach the interrupt to the RDYN line as requested by the caller */ + if (a_pins->interface_is_interrupt) { + // We use the LOW level of the RDYN line as the atmega328 can wakeup from sleep only on LOW + // attachInterrupt(a_pins->interrupt_number, m_aci_isr, LOW); + } +} + +bool hal_aci_tl_send(hal_aci_data_t *p_aci_cmd) +{ + const uint8_t length = p_aci_cmd->buffer[0]; + bool ret_val = false; + + if (length > HAL_ACI_MAX_LENGTH) + { + return false; + } + + ret_val = aci_queue_enqueue(&aci_tx_q, p_aci_cmd); + if (ret_val) + { + if(!aci_queue_is_full(&aci_rx_q)) + { + // Lower the REQN only when successfully enqueued + m_aci_reqn_enable(); + } + } + + return ret_val; +} + +static uint8_t spi_readwrite(const uint8_t aci_byte) +{ + uint8_t reversed, ret; + reversed = mraa_spi_write (a_pins_local_ptr->m_spi, REVERSE_BITS (aci_byte)); + ret = REVERSE_BITS (reversed); + return ret; +} + +bool hal_aci_tl_rx_q_empty (void) +{ + return aci_queue_is_empty(&aci_rx_q); +} + +bool hal_aci_tl_rx_q_full (void) +{ + return aci_queue_is_full(&aci_rx_q); +} + +bool hal_aci_tl_tx_q_empty (void) +{ + return aci_queue_is_empty(&aci_tx_q); +} + +bool hal_aci_tl_tx_q_full (void) +{ + return aci_queue_is_full(&aci_tx_q); +} + +void hal_aci_tl_q_flush (void) +{ + m_aci_q_flush(); +} diff --git a/src/nrf8001/hal_aci_tl.h b/src/nrf8001/hal_aci_tl.h index 6511faed..e2299c3d 100644 --- a/src/nrf8001/hal_aci_tl.h +++ b/src/nrf8001/hal_aci_tl.h @@ -1,189 +1,189 @@ -/* Copyright (c) 2014, Nordic Semiconductor ASA - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -/** - * @file - * @brief Interface for hal_aci_tl. - * @ingroup nrf8001 - */ - -/** -@{ - -@brief Module for the ACI Transport Layer interface -@details This module is responsible for sending and receiving messages over the ACI interface of the nRF8001 chip. - The hal_aci_tl_send_cmd() can be called directly to send ACI commands. - - -The RDYN line is hooked to an interrupt on the MCU when the level is low. -The SPI master clocks in the interrupt context. -The ACI Command is taken from the head of the command queue is sent over the SPI -and the received ACI event is placed in the tail of the event queue. - -*/ - -#ifndef HAL_ACI_TL_H__ -#define HAL_ACI_TL_H__ - -#include "hal_platform.h" -#include "aci.h" -#include "boards.h" - -#include -#include -#include - -#ifndef HAL_ACI_MAX_LENGTH -#define HAL_ACI_MAX_LENGTH 31 -#endif - -/************************************************************************/ -/* Unused nRF8001 pin */ -/************************************************************************/ -#define UNUSED 255 - -/** Data type for ACI commands and events */ -typedef struct { - uint8_t status_byte; - uint8_t buffer[HAL_ACI_MAX_LENGTH+1]; -} _aci_packed_ hal_aci_data_t; - -ACI_ASSERT_SIZE(hal_aci_data_t, HAL_ACI_MAX_LENGTH + 2); - -/** Datatype for ACI pins and interface (polling/interrupt)*/ -typedef struct aci_pins_t -{ - mraa_spi_context m_spi; - mraa_gpio_context m_rdy_ctx; - mraa_gpio_context m_req_ctx; - mraa_gpio_context m_rst_ctx; - - uint8_t board_name; //Optional : Use BOARD_DEFAULT if you do not know. See boards.h - uint8_t reqn_pin; //Required - uint8_t rdyn_pin; //Required - uint8_t mosi_pin; //Required - uint8_t miso_pin; //Required - uint8_t sck_pin; //Required - - uint8_t spi_clock_divider; //Required : Clock divider on the SPI clock : nRF8001 supports a maximum clock of 3MHz - - uint8_t reset_pin; //Recommended but optional - Set it to UNUSED when not connected - uint8_t active_pin; //Optional - Set it to UNUSED when not connected - uint8_t optional_chip_sel_pin; //Optional - Used only when the reqn line is required to be separate from the SPI chip select. Eg. Arduino DUE - - bool interface_is_interrupt; //Required - true = Uses interrupt on RDYN pin. false - Uses polling on RDYN pin - - uint8_t interrupt_number; //Required when using interrupts, otherwise ignored -} aci_pins_t; - -/** @brief ACI Transport Layer initialization. - * @details - * This function initializes the transport layer, including configuring the SPI, creating - * message queues for Commands and Events and setting up interrupt if required. - * @param a_pins Pins on the MCU used to connect to the nRF8001 - * @param bool True if debug printing should be enabled on the Serial. - */ -void hal_aci_tl_init(aci_pins_t *a_pins, bool debug); - -/** @brief Sends an ACI command to the radio. - * @details - * This function sends an ACI command to the radio. This queue up the message to send and - * lower the request line. When the device lowers the ready line, @ref m_aci_spi_transfer() - * will send the data. - * @param aci_buffer Pointer to the message to send. - * @return True if the data was successfully queued for sending, - * false if there is no more space to store messages to send. - */ -bool hal_aci_tl_send(hal_aci_data_t *aci_buffer); - -/** @brief Process pending transactions. - * @details - * The library code takes care of calling this function to check if the nRF8001 RDYN line indicates a - * pending transaction. It will send a pending message if there is one and return any receive message - * that was pending. - * @return Points to data buffer for received data. Length byte in buffer is 0 if no data received. - */ -hal_aci_data_t * hal_aci_tl_poll_get(void); - -/** @brief Get an ACI event from the event queue - * @details - * Call this function from the main context to get an event from the ACI event queue - * This is called by lib_aci_event_get - */ -bool hal_aci_tl_event_get(hal_aci_data_t *p_aci_data); - -/** @brief Peek an ACI event from the event queue - * @details - * Call this function from the main context to peek an event from the ACI event queue. - * This is called by lib_aci_event_peek - */ -bool hal_aci_tl_event_peek(hal_aci_data_t *p_aci_data); - -/** @brief Enable debug printing of all ACI commands sent and ACI events received - * @details - * when the enable parameter is true. The debug printing is enabled on the Serial. - * When the enable parameter is false. The debug printing is disabled on the Serial. - * By default the debug printing is disabled. - */ -void hal_aci_tl_debug_print(bool enable); - - -/** @brief Pin reset the nRF8001 - * @details - * The reset line of the nF8001 needs to kept low for 200 ns. - * Redbearlab shield v1.1 and v2012.07 are exceptions as they - * have a Power ON Reset circuit that works differently. - * The function handles the exceptions based on the board_name in aci_pins_t - */ -void hal_aci_tl_pin_reset(void); - -/** @brief Return full status of transmit queue - * @details - * - */ - bool hal_aci_tl_rx_q_full(void); - - /** @brief Return empty status of receive queue - * @details - * - */ - bool hal_aci_tl_rx_q_empty(void); - -/** @brief Return full status of receive queue - * @details - * - */ - bool hal_aci_tl_tx_q_full(void); - - /** @brief Return empty status of transmit queue - * @details - * - */ - bool hal_aci_tl_tx_q_empty(void); - -/** @brief Flush the ACI command Queue and the ACI Event Queue - * @details - * Call this function in the main thread - */ -void hal_aci_tl_q_flush(void); - -#endif // HAL_ACI_TL_H__ -/** @} */ +/* Copyright (c) 2014, Nordic Semiconductor ASA + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/** + * @file + * @brief Interface for hal_aci_tl. + * @ingroup nrf8001 + */ + +/** +@{ + +@brief Module for the ACI Transport Layer interface +@details This module is responsible for sending and receiving messages over the ACI interface of the nRF8001 chip. + The hal_aci_tl_send_cmd() can be called directly to send ACI commands. + + +The RDYN line is hooked to an interrupt on the MCU when the level is low. +The SPI master clocks in the interrupt context. +The ACI Command is taken from the head of the command queue is sent over the SPI +and the received ACI event is placed in the tail of the event queue. + +*/ + +#ifndef HAL_ACI_TL_H__ +#define HAL_ACI_TL_H__ + +#include "hal_platform.h" +#include "aci.h" +#include "boards.h" + +#include +#include +#include + +#ifndef HAL_ACI_MAX_LENGTH +#define HAL_ACI_MAX_LENGTH 31 +#endif + +/************************************************************************/ +/* Unused nRF8001 pin */ +/************************************************************************/ +#define UNUSED 255 + +/** Data type for ACI commands and events */ +typedef struct { + uint8_t status_byte; + uint8_t buffer[HAL_ACI_MAX_LENGTH+1]; +} _aci_packed_ hal_aci_data_t; + +ACI_ASSERT_SIZE(hal_aci_data_t, HAL_ACI_MAX_LENGTH + 2); + +/** Datatype for ACI pins and interface (polling/interrupt)*/ +typedef struct aci_pins_t +{ + mraa_spi_context m_spi; + mraa_gpio_context m_rdy_ctx; + mraa_gpio_context m_req_ctx; + mraa_gpio_context m_rst_ctx; + + uint8_t board_name; //Optional : Use BOARD_DEFAULT if you do not know. See boards.h + uint8_t reqn_pin; //Required + uint8_t rdyn_pin; //Required + uint8_t mosi_pin; //Required + uint8_t miso_pin; //Required + uint8_t sck_pin; //Required + + uint8_t spi_clock_divider; //Required : Clock divider on the SPI clock : nRF8001 supports a maximum clock of 3MHz + + uint8_t reset_pin; //Recommended but optional - Set it to UNUSED when not connected + uint8_t active_pin; //Optional - Set it to UNUSED when not connected + uint8_t optional_chip_sel_pin; //Optional - Used only when the reqn line is required to be separate from the SPI chip select. Eg. Arduino DUE + + bool interface_is_interrupt; //Required - true = Uses interrupt on RDYN pin. false - Uses polling on RDYN pin + + uint8_t interrupt_number; //Required when using interrupts, otherwise ignored +} aci_pins_t; + +/** @brief ACI Transport Layer initialization. + * @details + * This function initializes the transport layer, including configuring the SPI, creating + * message queues for Commands and Events and setting up interrupt if required. + * @param a_pins Pins on the MCU used to connect to the nRF8001 + * @param bool True if debug printing should be enabled on the Serial. + */ +void hal_aci_tl_init(aci_pins_t *a_pins, bool debug); + +/** @brief Sends an ACI command to the radio. + * @details + * This function sends an ACI command to the radio. This queue up the message to send and + * lower the request line. When the device lowers the ready line, @ref m_aci_spi_transfer() + * will send the data. + * @param aci_buffer Pointer to the message to send. + * @return True if the data was successfully queued for sending, + * false if there is no more space to store messages to send. + */ +bool hal_aci_tl_send(hal_aci_data_t *aci_buffer); + +/** @brief Process pending transactions. + * @details + * The library code takes care of calling this function to check if the nRF8001 RDYN line indicates a + * pending transaction. It will send a pending message if there is one and return any receive message + * that was pending. + * @return Points to data buffer for received data. Length byte in buffer is 0 if no data received. + */ +hal_aci_data_t * hal_aci_tl_poll_get(void); + +/** @brief Get an ACI event from the event queue + * @details + * Call this function from the main context to get an event from the ACI event queue + * This is called by lib_aci_event_get + */ +bool hal_aci_tl_event_get(hal_aci_data_t *p_aci_data); + +/** @brief Peek an ACI event from the event queue + * @details + * Call this function from the main context to peek an event from the ACI event queue. + * This is called by lib_aci_event_peek + */ +bool hal_aci_tl_event_peek(hal_aci_data_t *p_aci_data); + +/** @brief Enable debug printing of all ACI commands sent and ACI events received + * @details + * when the enable parameter is true. The debug printing is enabled on the Serial. + * When the enable parameter is false. The debug printing is disabled on the Serial. + * By default the debug printing is disabled. + */ +void hal_aci_tl_debug_print(bool enable); + + +/** @brief Pin reset the nRF8001 + * @details + * The reset line of the nF8001 needs to kept low for 200 ns. + * Redbearlab shield v1.1 and v2012.07 are exceptions as they + * have a Power ON Reset circuit that works differently. + * The function handles the exceptions based on the board_name in aci_pins_t + */ +void hal_aci_tl_pin_reset(void); + +/** @brief Return full status of transmit queue + * @details + * + */ + bool hal_aci_tl_rx_q_full(void); + + /** @brief Return empty status of receive queue + * @details + * + */ + bool hal_aci_tl_rx_q_empty(void); + +/** @brief Return full status of receive queue + * @details + * + */ + bool hal_aci_tl_tx_q_full(void); + + /** @brief Return empty status of transmit queue + * @details + * + */ + bool hal_aci_tl_tx_q_empty(void); + +/** @brief Flush the ACI command Queue and the ACI Event Queue + * @details + * Call this function in the main thread + */ +void hal_aci_tl_q_flush(void); + +#endif // HAL_ACI_TL_H__ +/** @} */ diff --git a/src/nrf8001/hal_platform.h b/src/nrf8001/hal_platform.h index 73ac4026..9ef7fbe2 100644 --- a/src/nrf8001/hal_platform.h +++ b/src/nrf8001/hal_platform.h @@ -1,78 +1,78 @@ -/* Copyright (c) 2014, Nordic Semiconductor ASA - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -/** - * @file - * @brief HAL specific macros - * @ingroup nrf8001 - */ - -#ifndef PLATFORM_H__ -#define PLATFORM_H__ - -//Board dependent defines -#if defined (__AVR__) - //For Arduino this AVR specific library has to be used for reading from Flash memory - #include - #include "Arduino.h" - #ifdef PROGMEM - #undef PROGMEM - #define PROGMEM __attribute__(( section(".progmem.data") )) - #endif -#elif defined(__PIC32MX__) - //For Chipkit add the following libraries. - #include - #include - #include - #include - #include - - //For making the Serial.Print compatible between Arduino and Chipkit - #define F(X) (X) - - //For ChipKit neither PROGMEM or PSTR are needed for PIC32 - #define PROGMEM - #define PSTR(s) (s) - - #define pgm_read_byte(x) (*((char *)x)) - #define pgm_read_byte_near(x) (*((char *)x)) - #define pgm_read_byte_far(x) (*((char *)x)) - #define pgm_read_word(x) (*((short *)x)) - #define pgm_read_word_near(x) (*((short *)x)) - #define pgm_read_workd_far(x) (*((short *)x)) - - #define prog_void const void - #define prog_char const char - #define prog_uchar const unsigned char - #define prog_int8_t const int8_t - #define prog_uint8_t const uint8_t - #define prog_int16_t const int16_t - #define prog_uint16_t const uint16_t - #define prog_int32_t const int32_t - #define prog_uint32_t const uint32_t - #define prog_int64_t const int64_t - #define prog_uint64_t const uint64_t - - //Redefine the function for reading from flash in ChipKit - #define memcpy_P memcpy -#endif - -#endif /* PLATFORM_H__ */ +/* Copyright (c) 2014, Nordic Semiconductor ASA + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/** + * @file + * @brief HAL specific macros + * @ingroup nrf8001 + */ + +#ifndef PLATFORM_H__ +#define PLATFORM_H__ + +//Board dependent defines +#if defined (__AVR__) + //For Arduino this AVR specific library has to be used for reading from Flash memory + #include + #include "Arduino.h" + #ifdef PROGMEM + #undef PROGMEM + #define PROGMEM __attribute__(( section(".progmem.data") )) + #endif +#elif defined(__PIC32MX__) + //For Chipkit add the following libraries. + #include + #include + #include + #include + #include + + //For making the Serial.Print compatible between Arduino and Chipkit + #define F(X) (X) + + //For ChipKit neither PROGMEM or PSTR are needed for PIC32 + #define PROGMEM + #define PSTR(s) (s) + + #define pgm_read_byte(x) (*((char *)x)) + #define pgm_read_byte_near(x) (*((char *)x)) + #define pgm_read_byte_far(x) (*((char *)x)) + #define pgm_read_word(x) (*((short *)x)) + #define pgm_read_word_near(x) (*((short *)x)) + #define pgm_read_workd_far(x) (*((short *)x)) + + #define prog_void const void + #define prog_char const char + #define prog_uchar const unsigned char + #define prog_int8_t const int8_t + #define prog_uint8_t const uint8_t + #define prog_int16_t const int16_t + #define prog_uint16_t const uint16_t + #define prog_int32_t const int32_t + #define prog_uint32_t const uint32_t + #define prog_int64_t const int64_t + #define prog_uint64_t const uint64_t + + //Redefine the function for reading from flash in ChipKit + #define memcpy_P memcpy +#endif + +#endif /* PLATFORM_H__ */ diff --git a/src/nrf8001/lib_aci.cpp b/src/nrf8001/lib_aci.cpp index c1948769..5655f617 100644 --- a/src/nrf8001/lib_aci.cpp +++ b/src/nrf8001/lib_aci.cpp @@ -1,742 +1,742 @@ -/* Copyright (c) 2014, Nordic Semiconductor ASA - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -/** @file - @brief Implementation of the ACI library. - */ - -#include "hal_platform.h" -#include "aci.h" -#include "aci_cmds.h" -#include "aci_evts.h" -#include "aci_protocol_defines.h" -#include "acilib_defs.h" -#include "acilib_if.h" -#include "hal_aci_tl.h" -#include "aci_queue.h" -#include "lib_aci.h" - - -#define LIB_ACI_DEFAULT_CREDIT_NUMBER 1 - -/* -Global additionally used used in aci_setup -*/ -hal_aci_data_t msg_to_send; - - -static services_pipe_type_mapping_t * p_services_pipe_type_map; -static hal_aci_data_t * p_setup_msgs; - - - - -static bool is_request_operation_pending; -static bool is_indicate_operation_pending; -static bool is_open_remote_pipe_pending; -static bool is_close_remote_pipe_pending; - -static uint8_t request_operation_pipe = 0; -static uint8_t indicate_operation_pipe = 0; - - -// The following structure (aci_cmd_params_open_adv_pipe) will be used to store the complete command -// including the pipes to be opened. -static aci_cmd_params_open_adv_pipe_t aci_cmd_params_open_adv_pipe; - - - -extern aci_queue_t aci_rx_q; -extern aci_queue_t aci_tx_q; - -bool lib_aci_is_pipe_available(aci_state_t *aci_stat, uint8_t pipe) -{ - uint8_t byte_idx; - - byte_idx = pipe / 8; - if (aci_stat->pipes_open_bitmap[byte_idx] & (0x01 << (pipe % 8))) - { - return(true); - } - return(false); -} - - -bool lib_aci_is_pipe_closed(aci_state_t *aci_stat, uint8_t pipe) -{ - uint8_t byte_idx; - - byte_idx = pipe / 8; - if (aci_stat->pipes_closed_bitmap[byte_idx] & (0x01 << (pipe % 8))) - { - return(true); - } - return(false); -} - - -bool lib_aci_is_discovery_finished(aci_state_t *aci_stat) -{ - return(aci_stat->pipes_open_bitmap[0]&0x01); -} - -void lib_aci_board_init(aci_state_t *aci_stat) -{ - hal_aci_evt_t *aci_data = NULL; - aci_data = (hal_aci_evt_t *)&msg_to_send; - - if (REDBEARLAB_SHIELD_V1_1 == aci_stat->aci_pins.board_name) - { - /* - The Bluetooth low energy Arduino shield v1.1 requires about 100ms to reset. - This is not required for the nRF2740, nRF2741 modules - */ - usleep(100000); - - /* - Send the soft reset command to the nRF8001 to get the nRF8001 to a known state. - */ - lib_aci_radio_reset(); - - while (1) - { - /*Wait for the command response of the radio reset command. - as the nRF8001 will be in either SETUP or STANDBY after the ACI Reset Radio is processed - */ - - - if (true == lib_aci_event_get(aci_stat, aci_data)) - { - aci_evt_t * aci_evt; - aci_evt = &(aci_data->evt); - - if (ACI_EVT_CMD_RSP == aci_evt->evt_opcode) - { - if (ACI_STATUS_ERROR_DEVICE_STATE_INVALID == aci_evt->params.cmd_rsp.cmd_status) //in SETUP - { - //Inject a Device Started Event Setup to the ACI Event Queue - msg_to_send.buffer[0] = 4; //Length - msg_to_send.buffer[1] = 0x81; //Device Started Event - msg_to_send.buffer[2] = 0x02; //Setup - msg_to_send.buffer[3] = 0; //Hardware Error -> None - msg_to_send.buffer[4] = 2; //Data Credit Available - aci_queue_enqueue(&aci_rx_q, &msg_to_send); - } - else if (ACI_STATUS_SUCCESS == aci_evt->params.cmd_rsp.cmd_status) //We are now in STANDBY - { - //Inject a Device Started Event Standby to the ACI Event Queue - msg_to_send.buffer[0] = 4; //Length - msg_to_send.buffer[1] = 0x81; //Device Started Event - msg_to_send.buffer[2] = 0x03; //Standby - msg_to_send.buffer[3] = 0; //Hardware Error -> None - msg_to_send.buffer[4] = 2; //Data Credit Available - aci_queue_enqueue(&aci_rx_q, &msg_to_send); - } - else if (ACI_STATUS_ERROR_CMD_UNKNOWN == aci_evt->params.cmd_rsp.cmd_status) //We are now in TEST - { - //Inject a Device Started Event Test to the ACI Event Queue - msg_to_send.buffer[0] = 4; //Length - msg_to_send.buffer[1] = 0x81; //Device Started Event - msg_to_send.buffer[2] = 0x01; //Test - msg_to_send.buffer[3] = 0; //Hardware Error -> None - msg_to_send.buffer[4] = 0; //Data Credit Available - aci_queue_enqueue(&aci_rx_q, &msg_to_send); - } - - printf ("BREAK\n"); - //Break out of the while loop - break; - } - else - { - //Serial.println(F("Discard any other ACI Events")); - } - - } - } - } -} - - -void lib_aci_init(aci_state_t *aci_stat, bool debug) -{ - uint8_t i; - - for (i = 0; i < PIPES_ARRAY_SIZE; i++) { - aci_stat->pipes_open_bitmap[i] = 0; - aci_stat->pipes_closed_bitmap[i] = 0; - aci_cmd_params_open_adv_pipe.pipes[i] = 0; - } - - is_request_operation_pending = false; - is_indicate_operation_pending = false; - is_open_remote_pipe_pending = false; - is_close_remote_pipe_pending = false; - - request_operation_pipe = 0; - indicate_operation_pipe = 0; - - p_services_pipe_type_map = aci_stat->aci_setup_info.services_pipe_type_mapping; - p_setup_msgs = aci_stat->aci_setup_info.setup_msgs; - - hal_aci_tl_init (&aci_stat->aci_pins, debug); - lib_aci_board_init (aci_stat); -} - - -uint8_t lib_aci_get_nb_available_credits(aci_state_t *aci_stat) -{ - return aci_stat->data_credit_available; -} - -uint16_t lib_aci_get_cx_interval_ms(aci_state_t *aci_stat) -{ - uint32_t cx_rf_interval_ms_32bits; - uint16_t cx_rf_interval_ms; - - cx_rf_interval_ms_32bits = aci_stat->connection_interval; - cx_rf_interval_ms_32bits *= 125; // the connection interval is given in multiples of 0.125 milliseconds - cx_rf_interval_ms = cx_rf_interval_ms_32bits / 100; - - return cx_rf_interval_ms; -} - - -uint16_t lib_aci_get_cx_interval(aci_state_t *aci_stat) -{ - return aci_stat->connection_interval; -} - - -uint16_t lib_aci_get_slave_latency(aci_state_t *aci_stat) -{ - return aci_stat->slave_latency; -} - - -bool lib_aci_set_app_latency(uint16_t latency, aci_app_latency_mode_t latency_mode) -{ - aci_cmd_params_set_app_latency_t aci_set_app_latency; - - aci_set_app_latency.mode = latency_mode; - aci_set_app_latency.latency = latency; - acil_encode_cmd_set_app_latency(&(msg_to_send.buffer[0]), &aci_set_app_latency); - - return hal_aci_tl_send(&msg_to_send); -} - - -bool lib_aci_test(aci_test_mode_change_t enter_exit_test_mode) -{ - aci_cmd_params_test_t aci_cmd_params_test; - aci_cmd_params_test.test_mode_change = enter_exit_test_mode; - acil_encode_cmd_set_test_mode(&(msg_to_send.buffer[0]), &aci_cmd_params_test); - return hal_aci_tl_send(&msg_to_send); -} - - -bool lib_aci_sleep() -{ - acil_encode_cmd_sleep(&(msg_to_send.buffer[0])); - return hal_aci_tl_send(&msg_to_send); -} - - -bool lib_aci_radio_reset() -{ - acil_encode_baseband_reset(&(msg_to_send.buffer[0])); - return hal_aci_tl_send(&msg_to_send); -} - - -bool lib_aci_direct_connect() -{ - acil_encode_direct_connect(&(msg_to_send.buffer[0])); - return hal_aci_tl_send(&msg_to_send); -} - - -bool lib_aci_device_version() -{ - acil_encode_cmd_get_device_version(&(msg_to_send.buffer[0])); - return hal_aci_tl_send(&msg_to_send); -} - - -bool lib_aci_set_local_data(aci_state_t *aci_stat, uint8_t pipe, uint8_t *p_value, uint8_t size) -{ - aci_cmd_params_set_local_data_t aci_cmd_params_set_local_data; - - if ((p_services_pipe_type_map[pipe-1].location != ACI_STORE_LOCAL) - || - (size > ACI_PIPE_TX_DATA_MAX_LEN)) - { - return false; - } - - aci_cmd_params_set_local_data.tx_data.pipe_number = pipe; - memcpy(&(aci_cmd_params_set_local_data.tx_data.aci_data[0]), p_value, size); - acil_encode_cmd_set_local_data(&(msg_to_send.buffer[0]), &aci_cmd_params_set_local_data, size); - return hal_aci_tl_send(&msg_to_send); -} - -bool lib_aci_connect(uint16_t run_timeout, uint16_t adv_interval) -{ - aci_cmd_params_connect_t aci_cmd_params_connect; - aci_cmd_params_connect.timeout = run_timeout; - aci_cmd_params_connect.adv_interval = adv_interval; - acil_encode_cmd_connect(&(msg_to_send.buffer[0]), &aci_cmd_params_connect); - return hal_aci_tl_send(&msg_to_send); -} - - -bool lib_aci_disconnect(aci_state_t *aci_stat, aci_disconnect_reason_t reason) -{ - bool ret_val; - uint8_t i; - aci_cmd_params_disconnect_t aci_cmd_params_disconnect; - aci_cmd_params_disconnect.reason = reason; - acil_encode_cmd_disconnect(&(msg_to_send.buffer[0]), &aci_cmd_params_disconnect); - ret_val = hal_aci_tl_send(&msg_to_send); - // If we have actually sent the disconnect - if (ret_val) - { - // Update pipes immediately so that while the disconnect is happening, - // the application can't attempt sending another message - // If the application sends another message before we updated this - // a ACI Pipe Error Event will be received from nRF8001 - for (i=0; i < PIPES_ARRAY_SIZE; i++) - { - aci_stat->pipes_open_bitmap[i] = 0; - aci_stat->pipes_closed_bitmap[i] = 0; - } - } - return ret_val; -} - - -bool lib_aci_bond(uint16_t run_timeout, uint16_t adv_interval) -{ - aci_cmd_params_bond_t aci_cmd_params_bond; - aci_cmd_params_bond.timeout = run_timeout; - aci_cmd_params_bond.adv_interval = adv_interval; - acil_encode_cmd_bond(&(msg_to_send.buffer[0]), &aci_cmd_params_bond); - return hal_aci_tl_send(&msg_to_send); -} - - -bool lib_aci_wakeup() -{ - acil_encode_cmd_wakeup(&(msg_to_send.buffer[0])); - return hal_aci_tl_send(&msg_to_send); -} - - -bool lib_aci_set_tx_power(aci_device_output_power_t tx_power) -{ - aci_cmd_params_set_tx_power_t aci_cmd_params_set_tx_power; - aci_cmd_params_set_tx_power.device_power = tx_power; - acil_encode_cmd_set_radio_tx_power(&(msg_to_send.buffer[0]), &aci_cmd_params_set_tx_power); - return hal_aci_tl_send(&msg_to_send); -} - - -bool lib_aci_get_address() -{ - acil_encode_cmd_get_address(&(msg_to_send.buffer[0])); - return hal_aci_tl_send(&msg_to_send); -} - - -bool lib_aci_get_temperature() -{ - acil_encode_cmd_temparature(&(msg_to_send.buffer[0])); - return hal_aci_tl_send(&msg_to_send); -} - - -bool lib_aci_get_battery_level() -{ - acil_encode_cmd_battery_level(&(msg_to_send.buffer[0])); - return hal_aci_tl_send(&msg_to_send); -} - - -bool lib_aci_send_data(uint8_t pipe, uint8_t *p_value, uint8_t size) -{ - bool ret_val = false; - aci_cmd_params_send_data_t aci_cmd_params_send_data; - - - if(!((p_services_pipe_type_map[pipe-1].pipe_type == ACI_TX) || - (p_services_pipe_type_map[pipe-1].pipe_type == ACI_TX_ACK))) - { - return false; - } - - if (size > ACI_PIPE_TX_DATA_MAX_LEN) - { - return false; - } - { - aci_cmd_params_send_data.tx_data.pipe_number = pipe; - memcpy(&(aci_cmd_params_send_data.tx_data.aci_data[0]), p_value, size); - acil_encode_cmd_send_data(&(msg_to_send.buffer[0]), &aci_cmd_params_send_data, size); - - ret_val = hal_aci_tl_send(&msg_to_send); - } - return ret_val; -} - - -bool lib_aci_request_data(aci_state_t *aci_stat, uint8_t pipe) -{ - bool ret_val = false; - aci_cmd_params_request_data_t aci_cmd_params_request_data; - - if(!((p_services_pipe_type_map[pipe-1].location == ACI_STORE_REMOTE)&&(p_services_pipe_type_map[pipe-1].pipe_type == ACI_RX_REQ))) - { - return false; - } - - - { - - { - - - - aci_cmd_params_request_data.pipe_number = pipe; - acil_encode_cmd_request_data(&(msg_to_send.buffer[0]), &aci_cmd_params_request_data); - - ret_val = hal_aci_tl_send(&msg_to_send); - } - } - return ret_val; -} - - -bool lib_aci_change_timing(uint16_t minimun_cx_interval, uint16_t maximum_cx_interval, uint16_t slave_latency, uint16_t timeout) -{ - aci_cmd_params_change_timing_t aci_cmd_params_change_timing; - aci_cmd_params_change_timing.conn_params.min_conn_interval = minimun_cx_interval; - aci_cmd_params_change_timing.conn_params.max_conn_interval = maximum_cx_interval; - aci_cmd_params_change_timing.conn_params.slave_latency = slave_latency; - aci_cmd_params_change_timing.conn_params.timeout_mult = timeout; - acil_encode_cmd_change_timing_req(&(msg_to_send.buffer[0]), &aci_cmd_params_change_timing); - return hal_aci_tl_send(&msg_to_send); -} - - -bool lib_aci_change_timing_GAP_PPCP() -{ - acil_encode_cmd_change_timing_req_GAP_PPCP(&(msg_to_send.buffer[0])); - return hal_aci_tl_send(&msg_to_send); -} - - -bool lib_aci_open_remote_pipe(aci_state_t *aci_stat, uint8_t pipe) -{ - bool ret_val = false; - aci_cmd_params_open_remote_pipe_t aci_cmd_params_open_remote_pipe; - - if(!((p_services_pipe_type_map[pipe-1].location == ACI_STORE_REMOTE)&& - ((p_services_pipe_type_map[pipe-1].pipe_type == ACI_RX)|| - (p_services_pipe_type_map[pipe-1].pipe_type == ACI_RX_ACK_AUTO)|| - (p_services_pipe_type_map[pipe-1].pipe_type == ACI_RX_ACK)))) - { - return false; - } - - - { - - is_request_operation_pending = true; - is_open_remote_pipe_pending = true; - request_operation_pipe = pipe; - aci_cmd_params_open_remote_pipe.pipe_number = pipe; - acil_encode_cmd_open_remote_pipe(&(msg_to_send.buffer[0]), &aci_cmd_params_open_remote_pipe); - ret_val = hal_aci_tl_send(&msg_to_send); - } - return ret_val; -} - - -bool lib_aci_close_remote_pipe(aci_state_t *aci_stat, uint8_t pipe) -{ - bool ret_val = false; - aci_cmd_params_close_remote_pipe_t aci_cmd_params_close_remote_pipe; - - if(!((p_services_pipe_type_map[pipe-1].location == ACI_STORE_REMOTE)&& - ((p_services_pipe_type_map[pipe-1].pipe_type == ACI_RX)|| - (p_services_pipe_type_map[pipe-1].pipe_type == ACI_RX_ACK_AUTO)|| - (p_services_pipe_type_map[pipe-1].pipe_type == ACI_RX_ACK)))) - { - return false; - } - - - { - - is_request_operation_pending = true; - is_close_remote_pipe_pending = true; - request_operation_pipe = pipe; - aci_cmd_params_close_remote_pipe.pipe_number = pipe; - acil_encode_cmd_close_remote_pipe(&(msg_to_send.buffer[0]), &aci_cmd_params_close_remote_pipe); - ret_val = hal_aci_tl_send(&msg_to_send); - } - return ret_val; -} - - -bool lib_aci_set_key(aci_key_type_t key_rsp_type, uint8_t *key, uint8_t len) -{ - aci_cmd_params_set_key_t aci_cmd_params_set_key; - aci_cmd_params_set_key.key_type = key_rsp_type; - memcpy((uint8_t*)&(aci_cmd_params_set_key.key), key, len); - acil_encode_cmd_set_key(&(msg_to_send.buffer[0]), &aci_cmd_params_set_key); - return hal_aci_tl_send(&msg_to_send); -} - - -bool lib_aci_echo_msg(uint8_t msg_size, uint8_t *p_msg_data) -{ - aci_cmd_params_echo_t aci_cmd_params_echo; - if(msg_size > (ACI_ECHO_DATA_MAX_LEN)) - { - return false; - } - - if (msg_size > (ACI_ECHO_DATA_MAX_LEN)) - { - msg_size = ACI_ECHO_DATA_MAX_LEN; - } - - memcpy(&(aci_cmd_params_echo.echo_data[0]), p_msg_data, msg_size); - acil_encode_cmd_echo_msg(&(msg_to_send.buffer[0]), &aci_cmd_params_echo, msg_size); - - return hal_aci_tl_send(&msg_to_send); -} - - -bool lib_aci_bond_request() -{ - acil_encode_cmd_bond_security_request(&(msg_to_send.buffer[0])); - return hal_aci_tl_send(&msg_to_send); -} - -bool lib_aci_event_peek(hal_aci_evt_t *p_aci_evt_data) -{ - return hal_aci_tl_event_peek((hal_aci_data_t *)p_aci_evt_data); -} - -bool lib_aci_event_get(aci_state_t *aci_stat, hal_aci_evt_t *p_aci_evt_data) -{ - bool status = false; - - status = hal_aci_tl_event_get((hal_aci_data_t *)p_aci_evt_data); - - /** - Update the state of the ACI with the - ACI Events -> Pipe Status, Disconnected, Connected, Bond Status, Pipe Error - */ - if (true == status) - { - aci_evt_t * aci_evt; - - aci_evt = &p_aci_evt_data->evt; - - switch(aci_evt->evt_opcode) - { - case ACI_EVT_PIPE_STATUS: - { - uint8_t i=0; - - for (i=0; i < PIPES_ARRAY_SIZE; i++) - { - aci_stat->pipes_open_bitmap[i] = aci_evt->params.pipe_status.pipes_open_bitmap[i]; - aci_stat->pipes_closed_bitmap[i] = aci_evt->params.pipe_status.pipes_closed_bitmap[i]; - } - } - break; - - case ACI_EVT_DISCONNECTED: - { - uint8_t i=0; - - for (i=0; i < PIPES_ARRAY_SIZE; i++) - { - aci_stat->pipes_open_bitmap[i] = 0; - aci_stat->pipes_closed_bitmap[i] = 0; - } - aci_stat->confirmation_pending = false; - aci_stat->data_credit_available = aci_stat->data_credit_total; - - } - break; - - case ACI_EVT_TIMING: - aci_stat->connection_interval = aci_evt->params.timing.conn_rf_interval; - aci_stat->slave_latency = aci_evt->params.timing.conn_slave_rf_latency; - aci_stat->supervision_timeout = aci_evt->params.timing.conn_rf_timeout; - break; - - default: - /* Need default case to avoid compiler warnings about missing enum - * values on some platforms. - */ - break; - - - - } - } - return status; -} - - -bool lib_aci_send_ack(aci_state_t *aci_stat, const uint8_t pipe) -{ - bool ret_val = false; - { - acil_encode_cmd_send_data_ack(&(msg_to_send.buffer[0]), pipe); - - ret_val = hal_aci_tl_send(&msg_to_send); - } - return ret_val; -} - - -bool lib_aci_send_nack(aci_state_t *aci_stat, const uint8_t pipe, const uint8_t error_code) -{ - bool ret_val = false; - - { - - acil_encode_cmd_send_data_nack(&(msg_to_send.buffer[0]), pipe, error_code); - ret_val = hal_aci_tl_send(&msg_to_send); - } - return ret_val; -} - - -bool lib_aci_broadcast(const uint16_t timeout, const uint16_t adv_interval) -{ - aci_cmd_params_broadcast_t aci_cmd_params_broadcast; - if (timeout > 16383) - { - return false; - } - - // The adv_interval should be between 160 and 16384 (which translates to the advertisement - // interval values 100 ms and 10.24 s. - if ((160 > adv_interval) || (adv_interval > 16384)) - { - return false; - } - - aci_cmd_params_broadcast.timeout = timeout; - aci_cmd_params_broadcast.adv_interval = adv_interval; - acil_encode_cmd_broadcast(&(msg_to_send.buffer[0]), &aci_cmd_params_broadcast); - return hal_aci_tl_send(&msg_to_send); -} - - -bool lib_aci_open_adv_pipes(const uint8_t * const adv_service_data_pipes) -{ - uint8_t i; - - for (i = 0; i < PIPES_ARRAY_SIZE; i++) - { - aci_cmd_params_open_adv_pipe.pipes[i] = adv_service_data_pipes[i]; - } - - acil_encode_cmd_open_adv_pipes(&(msg_to_send.buffer[0]), &aci_cmd_params_open_adv_pipe); - return hal_aci_tl_send(&msg_to_send); -} - -bool lib_aci_open_adv_pipe(const uint8_t pipe) -{ - uint8_t byte_idx = pipe / 8; - - aci_cmd_params_open_adv_pipe.pipes[byte_idx] |= (0x01 << (pipe % 8)); - acil_encode_cmd_open_adv_pipes(&(msg_to_send.buffer[0]), &aci_cmd_params_open_adv_pipe); - return hal_aci_tl_send(&msg_to_send); -} - - -bool lib_aci_read_dynamic_data() -{ - acil_encode_cmd_read_dynamic_data(&(msg_to_send.buffer[0])); - return hal_aci_tl_send(&msg_to_send); -} - - -bool lib_aci_write_dynamic_data(uint8_t sequence_number, uint8_t* dynamic_data, uint8_t length) -{ - acil_encode_cmd_write_dynamic_data(&(msg_to_send.buffer[0]), sequence_number, dynamic_data, length); - return hal_aci_tl_send(&msg_to_send); -} - -bool lib_aci_dtm_command(uint8_t dtm_command_msbyte, uint8_t dtm_command_lsbyte) -{ - aci_cmd_params_dtm_cmd_t aci_cmd_params_dtm_cmd; - aci_cmd_params_dtm_cmd.cmd_msb = dtm_command_msbyte; - aci_cmd_params_dtm_cmd.cmd_lsb = dtm_command_lsbyte; - acil_encode_cmd_dtm_cmd(&(msg_to_send.buffer[0]), &aci_cmd_params_dtm_cmd); - return hal_aci_tl_send(&msg_to_send); -} - -void lib_aci_flush(void) -{ - hal_aci_tl_q_flush(); -} - -void lib_aci_debug_print(bool enable) -{ - hal_aci_tl_debug_print(enable); - -} - -void lib_aci_pin_reset(void) -{ - hal_aci_tl_pin_reset(); -} - -bool lib_aci_event_queue_empty(void) -{ - return hal_aci_tl_rx_q_empty(); -} - -bool lib_aci_event_queue_full(void) -{ - return hal_aci_tl_rx_q_full(); -} - -bool lib_aci_command_queue_empty(void) -{ - return hal_aci_tl_tx_q_empty(); -} - -bool lib_aci_command_queue_full(void) -{ - return hal_aci_tl_tx_q_full(); -} +/* Copyright (c) 2014, Nordic Semiconductor ASA + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/** @file + @brief Implementation of the ACI library. + */ + +#include "hal_platform.h" +#include "aci.h" +#include "aci_cmds.h" +#include "aci_evts.h" +#include "aci_protocol_defines.h" +#include "acilib_defs.h" +#include "acilib_if.h" +#include "hal_aci_tl.h" +#include "aci_queue.h" +#include "lib_aci.h" + + +#define LIB_ACI_DEFAULT_CREDIT_NUMBER 1 + +/* +Global additionally used used in aci_setup +*/ +hal_aci_data_t msg_to_send; + + +static services_pipe_type_mapping_t * p_services_pipe_type_map; +static hal_aci_data_t * p_setup_msgs; + + + + +static bool is_request_operation_pending; +static bool is_indicate_operation_pending; +static bool is_open_remote_pipe_pending; +static bool is_close_remote_pipe_pending; + +static uint8_t request_operation_pipe = 0; +static uint8_t indicate_operation_pipe = 0; + + +// The following structure (aci_cmd_params_open_adv_pipe) will be used to store the complete command +// including the pipes to be opened. +static aci_cmd_params_open_adv_pipe_t aci_cmd_params_open_adv_pipe; + + + +extern aci_queue_t aci_rx_q; +extern aci_queue_t aci_tx_q; + +bool lib_aci_is_pipe_available(aci_state_t *aci_stat, uint8_t pipe) +{ + uint8_t byte_idx; + + byte_idx = pipe / 8; + if (aci_stat->pipes_open_bitmap[byte_idx] & (0x01 << (pipe % 8))) + { + return(true); + } + return(false); +} + + +bool lib_aci_is_pipe_closed(aci_state_t *aci_stat, uint8_t pipe) +{ + uint8_t byte_idx; + + byte_idx = pipe / 8; + if (aci_stat->pipes_closed_bitmap[byte_idx] & (0x01 << (pipe % 8))) + { + return(true); + } + return(false); +} + + +bool lib_aci_is_discovery_finished(aci_state_t *aci_stat) +{ + return(aci_stat->pipes_open_bitmap[0]&0x01); +} + +void lib_aci_board_init(aci_state_t *aci_stat) +{ + hal_aci_evt_t *aci_data = NULL; + aci_data = (hal_aci_evt_t *)&msg_to_send; + + if (REDBEARLAB_SHIELD_V1_1 == aci_stat->aci_pins.board_name) + { + /* + The Bluetooth low energy Arduino shield v1.1 requires about 100ms to reset. + This is not required for the nRF2740, nRF2741 modules + */ + usleep(100000); + + /* + Send the soft reset command to the nRF8001 to get the nRF8001 to a known state. + */ + lib_aci_radio_reset(); + + while (1) + { + /*Wait for the command response of the radio reset command. + as the nRF8001 will be in either SETUP or STANDBY after the ACI Reset Radio is processed + */ + + + if (true == lib_aci_event_get(aci_stat, aci_data)) + { + aci_evt_t * aci_evt; + aci_evt = &(aci_data->evt); + + if (ACI_EVT_CMD_RSP == aci_evt->evt_opcode) + { + if (ACI_STATUS_ERROR_DEVICE_STATE_INVALID == aci_evt->params.cmd_rsp.cmd_status) //in SETUP + { + //Inject a Device Started Event Setup to the ACI Event Queue + msg_to_send.buffer[0] = 4; //Length + msg_to_send.buffer[1] = 0x81; //Device Started Event + msg_to_send.buffer[2] = 0x02; //Setup + msg_to_send.buffer[3] = 0; //Hardware Error -> None + msg_to_send.buffer[4] = 2; //Data Credit Available + aci_queue_enqueue(&aci_rx_q, &msg_to_send); + } + else if (ACI_STATUS_SUCCESS == aci_evt->params.cmd_rsp.cmd_status) //We are now in STANDBY + { + //Inject a Device Started Event Standby to the ACI Event Queue + msg_to_send.buffer[0] = 4; //Length + msg_to_send.buffer[1] = 0x81; //Device Started Event + msg_to_send.buffer[2] = 0x03; //Standby + msg_to_send.buffer[3] = 0; //Hardware Error -> None + msg_to_send.buffer[4] = 2; //Data Credit Available + aci_queue_enqueue(&aci_rx_q, &msg_to_send); + } + else if (ACI_STATUS_ERROR_CMD_UNKNOWN == aci_evt->params.cmd_rsp.cmd_status) //We are now in TEST + { + //Inject a Device Started Event Test to the ACI Event Queue + msg_to_send.buffer[0] = 4; //Length + msg_to_send.buffer[1] = 0x81; //Device Started Event + msg_to_send.buffer[2] = 0x01; //Test + msg_to_send.buffer[3] = 0; //Hardware Error -> None + msg_to_send.buffer[4] = 0; //Data Credit Available + aci_queue_enqueue(&aci_rx_q, &msg_to_send); + } + + printf ("BREAK\n"); + //Break out of the while loop + break; + } + else + { + //Serial.println(F("Discard any other ACI Events")); + } + + } + } + } +} + + +void lib_aci_init(aci_state_t *aci_stat, bool debug) +{ + uint8_t i; + + for (i = 0; i < PIPES_ARRAY_SIZE; i++) { + aci_stat->pipes_open_bitmap[i] = 0; + aci_stat->pipes_closed_bitmap[i] = 0; + aci_cmd_params_open_adv_pipe.pipes[i] = 0; + } + + is_request_operation_pending = false; + is_indicate_operation_pending = false; + is_open_remote_pipe_pending = false; + is_close_remote_pipe_pending = false; + + request_operation_pipe = 0; + indicate_operation_pipe = 0; + + p_services_pipe_type_map = aci_stat->aci_setup_info.services_pipe_type_mapping; + p_setup_msgs = aci_stat->aci_setup_info.setup_msgs; + + hal_aci_tl_init (&aci_stat->aci_pins, debug); + lib_aci_board_init (aci_stat); +} + + +uint8_t lib_aci_get_nb_available_credits(aci_state_t *aci_stat) +{ + return aci_stat->data_credit_available; +} + +uint16_t lib_aci_get_cx_interval_ms(aci_state_t *aci_stat) +{ + uint32_t cx_rf_interval_ms_32bits; + uint16_t cx_rf_interval_ms; + + cx_rf_interval_ms_32bits = aci_stat->connection_interval; + cx_rf_interval_ms_32bits *= 125; // the connection interval is given in multiples of 0.125 milliseconds + cx_rf_interval_ms = cx_rf_interval_ms_32bits / 100; + + return cx_rf_interval_ms; +} + + +uint16_t lib_aci_get_cx_interval(aci_state_t *aci_stat) +{ + return aci_stat->connection_interval; +} + + +uint16_t lib_aci_get_slave_latency(aci_state_t *aci_stat) +{ + return aci_stat->slave_latency; +} + + +bool lib_aci_set_app_latency(uint16_t latency, aci_app_latency_mode_t latency_mode) +{ + aci_cmd_params_set_app_latency_t aci_set_app_latency; + + aci_set_app_latency.mode = latency_mode; + aci_set_app_latency.latency = latency; + acil_encode_cmd_set_app_latency(&(msg_to_send.buffer[0]), &aci_set_app_latency); + + return hal_aci_tl_send(&msg_to_send); +} + + +bool lib_aci_test(aci_test_mode_change_t enter_exit_test_mode) +{ + aci_cmd_params_test_t aci_cmd_params_test; + aci_cmd_params_test.test_mode_change = enter_exit_test_mode; + acil_encode_cmd_set_test_mode(&(msg_to_send.buffer[0]), &aci_cmd_params_test); + return hal_aci_tl_send(&msg_to_send); +} + + +bool lib_aci_sleep() +{ + acil_encode_cmd_sleep(&(msg_to_send.buffer[0])); + return hal_aci_tl_send(&msg_to_send); +} + + +bool lib_aci_radio_reset() +{ + acil_encode_baseband_reset(&(msg_to_send.buffer[0])); + return hal_aci_tl_send(&msg_to_send); +} + + +bool lib_aci_direct_connect() +{ + acil_encode_direct_connect(&(msg_to_send.buffer[0])); + return hal_aci_tl_send(&msg_to_send); +} + + +bool lib_aci_device_version() +{ + acil_encode_cmd_get_device_version(&(msg_to_send.buffer[0])); + return hal_aci_tl_send(&msg_to_send); +} + + +bool lib_aci_set_local_data(aci_state_t *aci_stat, uint8_t pipe, uint8_t *p_value, uint8_t size) +{ + aci_cmd_params_set_local_data_t aci_cmd_params_set_local_data; + + if ((p_services_pipe_type_map[pipe-1].location != ACI_STORE_LOCAL) + || + (size > ACI_PIPE_TX_DATA_MAX_LEN)) + { + return false; + } + + aci_cmd_params_set_local_data.tx_data.pipe_number = pipe; + memcpy(&(aci_cmd_params_set_local_data.tx_data.aci_data[0]), p_value, size); + acil_encode_cmd_set_local_data(&(msg_to_send.buffer[0]), &aci_cmd_params_set_local_data, size); + return hal_aci_tl_send(&msg_to_send); +} + +bool lib_aci_connect(uint16_t run_timeout, uint16_t adv_interval) +{ + aci_cmd_params_connect_t aci_cmd_params_connect; + aci_cmd_params_connect.timeout = run_timeout; + aci_cmd_params_connect.adv_interval = adv_interval; + acil_encode_cmd_connect(&(msg_to_send.buffer[0]), &aci_cmd_params_connect); + return hal_aci_tl_send(&msg_to_send); +} + + +bool lib_aci_disconnect(aci_state_t *aci_stat, aci_disconnect_reason_t reason) +{ + bool ret_val; + uint8_t i; + aci_cmd_params_disconnect_t aci_cmd_params_disconnect; + aci_cmd_params_disconnect.reason = reason; + acil_encode_cmd_disconnect(&(msg_to_send.buffer[0]), &aci_cmd_params_disconnect); + ret_val = hal_aci_tl_send(&msg_to_send); + // If we have actually sent the disconnect + if (ret_val) + { + // Update pipes immediately so that while the disconnect is happening, + // the application can't attempt sending another message + // If the application sends another message before we updated this + // a ACI Pipe Error Event will be received from nRF8001 + for (i=0; i < PIPES_ARRAY_SIZE; i++) + { + aci_stat->pipes_open_bitmap[i] = 0; + aci_stat->pipes_closed_bitmap[i] = 0; + } + } + return ret_val; +} + + +bool lib_aci_bond(uint16_t run_timeout, uint16_t adv_interval) +{ + aci_cmd_params_bond_t aci_cmd_params_bond; + aci_cmd_params_bond.timeout = run_timeout; + aci_cmd_params_bond.adv_interval = adv_interval; + acil_encode_cmd_bond(&(msg_to_send.buffer[0]), &aci_cmd_params_bond); + return hal_aci_tl_send(&msg_to_send); +} + + +bool lib_aci_wakeup() +{ + acil_encode_cmd_wakeup(&(msg_to_send.buffer[0])); + return hal_aci_tl_send(&msg_to_send); +} + + +bool lib_aci_set_tx_power(aci_device_output_power_t tx_power) +{ + aci_cmd_params_set_tx_power_t aci_cmd_params_set_tx_power; + aci_cmd_params_set_tx_power.device_power = tx_power; + acil_encode_cmd_set_radio_tx_power(&(msg_to_send.buffer[0]), &aci_cmd_params_set_tx_power); + return hal_aci_tl_send(&msg_to_send); +} + + +bool lib_aci_get_address() +{ + acil_encode_cmd_get_address(&(msg_to_send.buffer[0])); + return hal_aci_tl_send(&msg_to_send); +} + + +bool lib_aci_get_temperature() +{ + acil_encode_cmd_temparature(&(msg_to_send.buffer[0])); + return hal_aci_tl_send(&msg_to_send); +} + + +bool lib_aci_get_battery_level() +{ + acil_encode_cmd_battery_level(&(msg_to_send.buffer[0])); + return hal_aci_tl_send(&msg_to_send); +} + + +bool lib_aci_send_data(uint8_t pipe, uint8_t *p_value, uint8_t size) +{ + bool ret_val = false; + aci_cmd_params_send_data_t aci_cmd_params_send_data; + + + if(!((p_services_pipe_type_map[pipe-1].pipe_type == ACI_TX) || + (p_services_pipe_type_map[pipe-1].pipe_type == ACI_TX_ACK))) + { + return false; + } + + if (size > ACI_PIPE_TX_DATA_MAX_LEN) + { + return false; + } + { + aci_cmd_params_send_data.tx_data.pipe_number = pipe; + memcpy(&(aci_cmd_params_send_data.tx_data.aci_data[0]), p_value, size); + acil_encode_cmd_send_data(&(msg_to_send.buffer[0]), &aci_cmd_params_send_data, size); + + ret_val = hal_aci_tl_send(&msg_to_send); + } + return ret_val; +} + + +bool lib_aci_request_data(aci_state_t *aci_stat, uint8_t pipe) +{ + bool ret_val = false; + aci_cmd_params_request_data_t aci_cmd_params_request_data; + + if(!((p_services_pipe_type_map[pipe-1].location == ACI_STORE_REMOTE)&&(p_services_pipe_type_map[pipe-1].pipe_type == ACI_RX_REQ))) + { + return false; + } + + + { + + { + + + + aci_cmd_params_request_data.pipe_number = pipe; + acil_encode_cmd_request_data(&(msg_to_send.buffer[0]), &aci_cmd_params_request_data); + + ret_val = hal_aci_tl_send(&msg_to_send); + } + } + return ret_val; +} + + +bool lib_aci_change_timing(uint16_t minimun_cx_interval, uint16_t maximum_cx_interval, uint16_t slave_latency, uint16_t timeout) +{ + aci_cmd_params_change_timing_t aci_cmd_params_change_timing; + aci_cmd_params_change_timing.conn_params.min_conn_interval = minimun_cx_interval; + aci_cmd_params_change_timing.conn_params.max_conn_interval = maximum_cx_interval; + aci_cmd_params_change_timing.conn_params.slave_latency = slave_latency; + aci_cmd_params_change_timing.conn_params.timeout_mult = timeout; + acil_encode_cmd_change_timing_req(&(msg_to_send.buffer[0]), &aci_cmd_params_change_timing); + return hal_aci_tl_send(&msg_to_send); +} + + +bool lib_aci_change_timing_GAP_PPCP() +{ + acil_encode_cmd_change_timing_req_GAP_PPCP(&(msg_to_send.buffer[0])); + return hal_aci_tl_send(&msg_to_send); +} + + +bool lib_aci_open_remote_pipe(aci_state_t *aci_stat, uint8_t pipe) +{ + bool ret_val = false; + aci_cmd_params_open_remote_pipe_t aci_cmd_params_open_remote_pipe; + + if(!((p_services_pipe_type_map[pipe-1].location == ACI_STORE_REMOTE)&& + ((p_services_pipe_type_map[pipe-1].pipe_type == ACI_RX)|| + (p_services_pipe_type_map[pipe-1].pipe_type == ACI_RX_ACK_AUTO)|| + (p_services_pipe_type_map[pipe-1].pipe_type == ACI_RX_ACK)))) + { + return false; + } + + + { + + is_request_operation_pending = true; + is_open_remote_pipe_pending = true; + request_operation_pipe = pipe; + aci_cmd_params_open_remote_pipe.pipe_number = pipe; + acil_encode_cmd_open_remote_pipe(&(msg_to_send.buffer[0]), &aci_cmd_params_open_remote_pipe); + ret_val = hal_aci_tl_send(&msg_to_send); + } + return ret_val; +} + + +bool lib_aci_close_remote_pipe(aci_state_t *aci_stat, uint8_t pipe) +{ + bool ret_val = false; + aci_cmd_params_close_remote_pipe_t aci_cmd_params_close_remote_pipe; + + if(!((p_services_pipe_type_map[pipe-1].location == ACI_STORE_REMOTE)&& + ((p_services_pipe_type_map[pipe-1].pipe_type == ACI_RX)|| + (p_services_pipe_type_map[pipe-1].pipe_type == ACI_RX_ACK_AUTO)|| + (p_services_pipe_type_map[pipe-1].pipe_type == ACI_RX_ACK)))) + { + return false; + } + + + { + + is_request_operation_pending = true; + is_close_remote_pipe_pending = true; + request_operation_pipe = pipe; + aci_cmd_params_close_remote_pipe.pipe_number = pipe; + acil_encode_cmd_close_remote_pipe(&(msg_to_send.buffer[0]), &aci_cmd_params_close_remote_pipe); + ret_val = hal_aci_tl_send(&msg_to_send); + } + return ret_val; +} + + +bool lib_aci_set_key(aci_key_type_t key_rsp_type, uint8_t *key, uint8_t len) +{ + aci_cmd_params_set_key_t aci_cmd_params_set_key; + aci_cmd_params_set_key.key_type = key_rsp_type; + memcpy((uint8_t*)&(aci_cmd_params_set_key.key), key, len); + acil_encode_cmd_set_key(&(msg_to_send.buffer[0]), &aci_cmd_params_set_key); + return hal_aci_tl_send(&msg_to_send); +} + + +bool lib_aci_echo_msg(uint8_t msg_size, uint8_t *p_msg_data) +{ + aci_cmd_params_echo_t aci_cmd_params_echo; + if(msg_size > (ACI_ECHO_DATA_MAX_LEN)) + { + return false; + } + + if (msg_size > (ACI_ECHO_DATA_MAX_LEN)) + { + msg_size = ACI_ECHO_DATA_MAX_LEN; + } + + memcpy(&(aci_cmd_params_echo.echo_data[0]), p_msg_data, msg_size); + acil_encode_cmd_echo_msg(&(msg_to_send.buffer[0]), &aci_cmd_params_echo, msg_size); + + return hal_aci_tl_send(&msg_to_send); +} + + +bool lib_aci_bond_request() +{ + acil_encode_cmd_bond_security_request(&(msg_to_send.buffer[0])); + return hal_aci_tl_send(&msg_to_send); +} + +bool lib_aci_event_peek(hal_aci_evt_t *p_aci_evt_data) +{ + return hal_aci_tl_event_peek((hal_aci_data_t *)p_aci_evt_data); +} + +bool lib_aci_event_get(aci_state_t *aci_stat, hal_aci_evt_t *p_aci_evt_data) +{ + bool status = false; + + status = hal_aci_tl_event_get((hal_aci_data_t *)p_aci_evt_data); + + /** + Update the state of the ACI with the + ACI Events -> Pipe Status, Disconnected, Connected, Bond Status, Pipe Error + */ + if (true == status) + { + aci_evt_t * aci_evt; + + aci_evt = &p_aci_evt_data->evt; + + switch(aci_evt->evt_opcode) + { + case ACI_EVT_PIPE_STATUS: + { + uint8_t i=0; + + for (i=0; i < PIPES_ARRAY_SIZE; i++) + { + aci_stat->pipes_open_bitmap[i] = aci_evt->params.pipe_status.pipes_open_bitmap[i]; + aci_stat->pipes_closed_bitmap[i] = aci_evt->params.pipe_status.pipes_closed_bitmap[i]; + } + } + break; + + case ACI_EVT_DISCONNECTED: + { + uint8_t i=0; + + for (i=0; i < PIPES_ARRAY_SIZE; i++) + { + aci_stat->pipes_open_bitmap[i] = 0; + aci_stat->pipes_closed_bitmap[i] = 0; + } + aci_stat->confirmation_pending = false; + aci_stat->data_credit_available = aci_stat->data_credit_total; + + } + break; + + case ACI_EVT_TIMING: + aci_stat->connection_interval = aci_evt->params.timing.conn_rf_interval; + aci_stat->slave_latency = aci_evt->params.timing.conn_slave_rf_latency; + aci_stat->supervision_timeout = aci_evt->params.timing.conn_rf_timeout; + break; + + default: + /* Need default case to avoid compiler warnings about missing enum + * values on some platforms. + */ + break; + + + + } + } + return status; +} + + +bool lib_aci_send_ack(aci_state_t *aci_stat, const uint8_t pipe) +{ + bool ret_val = false; + { + acil_encode_cmd_send_data_ack(&(msg_to_send.buffer[0]), pipe); + + ret_val = hal_aci_tl_send(&msg_to_send); + } + return ret_val; +} + + +bool lib_aci_send_nack(aci_state_t *aci_stat, const uint8_t pipe, const uint8_t error_code) +{ + bool ret_val = false; + + { + + acil_encode_cmd_send_data_nack(&(msg_to_send.buffer[0]), pipe, error_code); + ret_val = hal_aci_tl_send(&msg_to_send); + } + return ret_val; +} + + +bool lib_aci_broadcast(const uint16_t timeout, const uint16_t adv_interval) +{ + aci_cmd_params_broadcast_t aci_cmd_params_broadcast; + if (timeout > 16383) + { + return false; + } + + // The adv_interval should be between 160 and 16384 (which translates to the advertisement + // interval values 100 ms and 10.24 s. + if ((160 > adv_interval) || (adv_interval > 16384)) + { + return false; + } + + aci_cmd_params_broadcast.timeout = timeout; + aci_cmd_params_broadcast.adv_interval = adv_interval; + acil_encode_cmd_broadcast(&(msg_to_send.buffer[0]), &aci_cmd_params_broadcast); + return hal_aci_tl_send(&msg_to_send); +} + + +bool lib_aci_open_adv_pipes(const uint8_t * const adv_service_data_pipes) +{ + uint8_t i; + + for (i = 0; i < PIPES_ARRAY_SIZE; i++) + { + aci_cmd_params_open_adv_pipe.pipes[i] = adv_service_data_pipes[i]; + } + + acil_encode_cmd_open_adv_pipes(&(msg_to_send.buffer[0]), &aci_cmd_params_open_adv_pipe); + return hal_aci_tl_send(&msg_to_send); +} + +bool lib_aci_open_adv_pipe(const uint8_t pipe) +{ + uint8_t byte_idx = pipe / 8; + + aci_cmd_params_open_adv_pipe.pipes[byte_idx] |= (0x01 << (pipe % 8)); + acil_encode_cmd_open_adv_pipes(&(msg_to_send.buffer[0]), &aci_cmd_params_open_adv_pipe); + return hal_aci_tl_send(&msg_to_send); +} + + +bool lib_aci_read_dynamic_data() +{ + acil_encode_cmd_read_dynamic_data(&(msg_to_send.buffer[0])); + return hal_aci_tl_send(&msg_to_send); +} + + +bool lib_aci_write_dynamic_data(uint8_t sequence_number, uint8_t* dynamic_data, uint8_t length) +{ + acil_encode_cmd_write_dynamic_data(&(msg_to_send.buffer[0]), sequence_number, dynamic_data, length); + return hal_aci_tl_send(&msg_to_send); +} + +bool lib_aci_dtm_command(uint8_t dtm_command_msbyte, uint8_t dtm_command_lsbyte) +{ + aci_cmd_params_dtm_cmd_t aci_cmd_params_dtm_cmd; + aci_cmd_params_dtm_cmd.cmd_msb = dtm_command_msbyte; + aci_cmd_params_dtm_cmd.cmd_lsb = dtm_command_lsbyte; + acil_encode_cmd_dtm_cmd(&(msg_to_send.buffer[0]), &aci_cmd_params_dtm_cmd); + return hal_aci_tl_send(&msg_to_send); +} + +void lib_aci_flush(void) +{ + hal_aci_tl_q_flush(); +} + +void lib_aci_debug_print(bool enable) +{ + hal_aci_tl_debug_print(enable); + +} + +void lib_aci_pin_reset(void) +{ + hal_aci_tl_pin_reset(); +} + +bool lib_aci_event_queue_empty(void) +{ + return hal_aci_tl_rx_q_empty(); +} + +bool lib_aci_event_queue_full(void) +{ + return hal_aci_tl_rx_q_full(); +} + +bool lib_aci_command_queue_empty(void) +{ + return hal_aci_tl_tx_q_empty(); +} + +bool lib_aci_command_queue_full(void) +{ + return hal_aci_tl_tx_q_full(); +} diff --git a/src/nrf8001/lib_aci.h b/src/nrf8001/lib_aci.h index fc85ef4c..557536bc 100644 --- a/src/nrf8001/lib_aci.h +++ b/src/nrf8001/lib_aci.h @@ -1,569 +1,569 @@ -/* Copyright (c) 2014, Nordic Semiconductor ASA - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -/** - * @file - * @defgroup aci-lib aci-library - * @brief ACI library - * - * Library for the logical part of the Application Controller Interface (ACI) - * - * @ingroup nrf8001 - */ - -#ifndef LIB_ACI_H__ -#define LIB_ACI_H__ - -/** -* @{ -*/ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "hal_platform.h" -#include "hal_aci_tl.h" -#include "aci_queue.h" -#include "aci.h" -#include "aci_cmds.h" -#include "aci_evts.h" - -#define EVT_CMD_RESPONSE_MIN_LENGTH 3 - -#define PIPES_ARRAY_SIZE ((ACI_DEVICE_MAX_PIPES + 7)/8) - -/* Same size as a hal_aci_data_t */ -typedef struct { - uint8_t debug_byte; - aci_evt_t evt; -} _aci_packed_ hal_aci_evt_t; - -ACI_ASSERT_SIZE(hal_aci_evt_t, 34); - -typedef struct -{ - uint8_t location; /**< enum aci_pipe_store_t */ - aci_pipe_type_t pipe_type; -} services_pipe_type_mapping_t; - -typedef struct aci_setup_info_t -{ - services_pipe_type_mapping_t *services_pipe_type_mapping; - uint8_t number_of_pipes; - hal_aci_data_t *setup_msgs; - uint8_t num_setup_msgs; -} aci_setup_info_t; - - - -// aci_struct that will contain -// total initial credits -// current credit -// current state of the aci (setup/standby/active/sleep) -// open remote pipe pending -// close remote pipe pending -// Current pipe available bitmap -// Current pipe closed bitmap -// Current connection interval, slave latency and link supervision timeout -// Current State of the the GATT client (Service Discovery status) -// Relationship of bond to peer address -typedef struct aci_state_t -{ - aci_pins_t aci_pins; /* Pins on the MCU used to connect to the nRF8001 */ - aci_setup_info_t aci_setup_info; /* Data structures that are created from nRFgo Studio */ - uint8_t bonded; /* ( aci_bond_status_code_t ) Is the nRF8001 bonded to a peer device */ - uint8_t data_credit_total; /* Total data credit available for the specific version of the nRF8001, total equals available when a link is established */ - aci_device_operation_mode_t device_state; /* Operating mode of the nRF8001 */ - - /* */ - - /* Start : Variables that are valid only when in a connection */ - uint8_t data_credit_available; /* Available data credits at a specific point of time, ACI_EVT_DATA_CREDIT updates the available credits */ - - uint16_t connection_interval; /* Multiply by 1.25 to get the connection interval in milliseconds*/ - uint16_t slave_latency; /* Number of consecutive connection intervals that the nRF8001 is not required to transmit. Use this to save power */ - uint16_t supervision_timeout; /* Multiply by 10 to get the supervision timeout in milliseconds */ - - uint8_t pipes_open_bitmap[PIPES_ARRAY_SIZE]; /* Bitmap -> pipes are open and can be used for sending data over the air */ - uint8_t pipes_closed_bitmap[PIPES_ARRAY_SIZE]; /* Bitmap -> pipes are closed and cannot be used for sending data over the air */ - bool confirmation_pending; /* Attribute protocol Handle Value confirmation is pending for a Handle Value Indication - (ACK is pending for a TX_ACK pipe) on local GATT Server*/ - /* End : Variables that are valid only when in a connection */ - -} aci_state_t; - - - -#define DISCONNECT_REASON_CX_TIMEOUT 0x08 -#define DISCONNECT_REASON_CX_CLOSED_BY_PEER_DEVICE 0x13 -#define DISCONNECT_REASON_POWER_LOSS 0x14 -#define DISCONNECT_REASON_CX_CLOSED_BY_LOCAL_DEVICE 0x16 -#define DISCONNECT_REASON_ADVERTISER_TIMEOUT 0x50 - - -/** @name Functions for library management */ -//@{ - -/** @brief Function to enable printing of all ACI commands sent and ACI events received - * @details This function shall be used to enable or disable the debug printing. - Debug printing is disabled by default. - */ -void lib_aci_debug_print(bool enable); - -/** @brief Function to pin reset the nRF8001 - * @details Pin resets the nRF8001 also handles differences between development boards - */ -void lib_aci_pin_reset(void); - -/** @brief Initialization function. - * @details This function shall be used to initialize/reset ACI Library and also Resets the - * nRF8001 by togging the reset pin of the nRF8001. This function will reset - * all the variables locally used by ACI library to their respective default values. - * @param bool True if the data was successfully queued for sending, - * false if there is no more space to store messages to send. - */ -void lib_aci_init(aci_state_t *aci_stat, bool debug); - - -/** @brief Gets the number of currently available ACI credits. - * @return Number of ACI credits. - */ -uint8_t lib_aci_get_nb_available_credits(aci_state_t *aci_stat); - -/** @brief Gets the connection interval in milliseconds. - * @return Connection interval in milliseconds. - */ -uint16_t lib_aci_get_cx_interval_ms(aci_state_t *aci_stat); - -/** @brief Gets the connection interval in multiple of 1.25 ms. - * @return Connection interval in multiple of 1.25 ms. - */ -uint16_t lib_aci_get_cx_interval(aci_state_t *aci_stat); - -/** @brief Gets the current slave latency. - * @return Current slave latency. - */ -uint16_t lib_aci_get_slave_latency(aci_state_t *aci_stat); - -/** @brief Checks if a given pipe is available. - * @param pipe Pipe to check. - * @return True if the pipe is available, otherwise false. - */ -bool lib_aci_is_pipe_available(aci_state_t *aci_stat, uint8_t pipe); - -/** @brief Checks if a given pipe is closed. - * @param pipe Pipe to check. - * @return True if the pipe is closed, otherwise false. - */ -bool lib_aci_is_pipe_closed(aci_state_t *aci_stat, uint8_t pipe); - -/** @brief Checks if the discovery operation is finished. - * @return True if the discovery is finished. - */ -bool lib_aci_is_discovery_finished(aci_state_t *aci_stat); - - - -//@} - -/** @name ACI Commands available in all modes */ -//@{ - -/** @brief Sets the radio in sleep mode. - * @details The function sends a @c sleep command to the radio. - * If the radio is advertising or connected, it sends back an error, then use lib_aci_radio_reset - * if advertising or disconnect if in a connection. - * @return True if the transaction is successfully initiated. - */ -bool lib_aci_sleep(void); - -/** @brief Resets the radio. - * @details The function sends a @c BasebandReset command to the radio. - * @return True if the transaction is successfully initiated. - */ -bool lib_aci_radio_reset(void); - -/** @brief Radio starts directed advertising to bonded device. - * @details The function sends a @c DirectedConnect command to the radio. - * @return True if the transaction is successfully initiated. - */ -bool lib_aci_direct_connect(void); - -/** @brief Gets the radio's version. - * @details This function sends a @c GetDeviceVersion command. - * @return True if the transaction is successfully initiated. - */ -bool lib_aci_device_version(void); - -/** @brief Gets the device address. - * @details This function sends a @c GetDeviceAddress command. - * @return True if the transaction is successfully initiated. - */ -bool lib_aci_get_address(void); - -/** @brief Gets the temperature. - * @details This function sends a @c GetTemperature command. lib_aci - * calls the @ref lib_aci_transaction_finished_hook() function when the temperature is received. - * @return True if the transaction is successfully initiated. - */ -bool lib_aci_get_temperature(void); - -/** @brief Gets the battery level. - * @details This function sends a @c GetBatteryLevel command. - * @return True if the transaction is successfully initiated. - */ -bool lib_aci_get_battery_level(void); - -//@} - -/** @name ACI commands available in Sleep mode */ -//@{ - -/** @brief Wakes up the radio. - * @details This function sends a @c Wakeup command to wake up the radio from - * sleep mode. When woken up the radio sends a @c DeviceStartedEvent and - * a @c CommandResponseEvent. - * @return True if the transaction is successfully initiated. - */ -bool lib_aci_wakeup(void); - -//@} - -/** @name ACI commands available in Active mode */ -//@{ - -/** @brief Sets the radio in test mode. - * @details This function sends a @c Test command to the radio. There are two - * Test modes available: - * - UART: DTM commands are received over UART. - * - ACI: DTM commands are received over ACI. - * The same command is used to exit the test mode When receiving - * a @c DeviceStartedEvent the radio has entered the new mode. - * @param enter_exit_test_mode Enter a Test mode, or exit Test mode. - * @return True if the transaction is successfully initiated. - */ -bool lib_aci_test(aci_test_mode_change_t enter_exit_test_mode); - -/** @brief Sets the radio's TX power. - * @details This function sends a @c SetTxPower command. - * @param tx_power TX power to be used by the radio. - * @return True if the transaction is successfully initiated. - */ -bool lib_aci_set_tx_power(aci_device_output_power_t tx_power); - -/** @brief Tries to connect to a peer device. - * @details This function sends a @c Connect command to the radio. - * @param run_timeout Maximum advertising time in seconds (0 means infinite). - * @param adv_interval Advertising interval (in multiple of 0.625 ms). - * @return True if the transaction is successfully initiated. - */ -bool lib_aci_connect(uint16_t run_timeout, uint16_t adv_interval); - -/** @brief Tries to bond with a peer device. - * @details This function sends a @c Bond command to the radio. - * @param run_timeout Maximum advertising time in seconds (0 means infinite). - * @param adv_interval Advertising interval (in multiple of 0.625 ms). - * @return True if the transaction is successfully initiated. - */ -bool lib_aci_bond(uint16_t run_timeout, uint16_t adv_interval); - -/** @brief Disconnects from peer device. - * @details This function sends a @c Disconnect command to the radio. - * @param reason Reason for disconnecting. - * @return True if the transaction is successfully initiated. - */ -bool lib_aci_disconnect(aci_state_t *aci_stat, aci_disconnect_reason_t reason); - -/**@brief Sets Local Data. - * @details - * This command updates the value of the characteristic value or the characteristic descriptor stored locally on the device. - * Can be called for all types of pipes as long as the data is stored locally. - * @param ACI state structure - * @param pipe Pipe number on which the data should be set. - * @param value Pointer to the data to set. - * @param size Size of the data to set. - * @return True if the transaction is successfully initiated. -*/ -bool lib_aci_set_local_data(aci_state_t *aci_stat, uint8_t pipe, uint8_t *value, uint8_t size); - -/** @brief Sends Broadcast message to the radio. - * @details The Broadcast message starts advertisement procedure - * using the given interval with the intention of broadcasting data to a peer device. - * @param timeout Time, in seconds, to advertise before exiting to standby mode (0 means infinite). - * Valid values: 0 to 16383. - * @param adv_interval Advertising interval (in multiple of 0.625 ms). - * Valid values: 160 to 16384 (which corresponds to an interval from 100 ms to 10.24 s). - * @return True if the broadcast message is sent successfully to the radio. -*/ -bool lib_aci_broadcast(const uint16_t timeout, const uint16_t adv_interval); - -/** @name Open Advertising Pipes. */ - -/** @brief Sends a command to the radio to set the input pipe to be placed in Advertisement Service Data. - * @details This function sends a command to the radio that places the pipe in - * advertisement service data. To start advertising service data, call this function before - * Connecting, Broadcasting or Bonding to peer. The data that should be sent in the advertisement packets - * must be set using the @c lib_aci_set_local_data function. This function can be called during - * advertising to enable/disable broadcast pipes. - * @param pipe The pipe that has to be placed in advertising service data. - * @return True if the Open Adv Pipe message is sent successfully to the radio. -*/ -bool lib_aci_open_adv_pipe(const uint8_t pipe); - - -/** @name Open Advertising Pipes */ - -/** @brief Sends a command to the radio to set the pipes to be placed in Advertisement Service Data. - * @details This function will send a command to the radio that will set the pipes to be placed in - * advertisement Service Data. To start advertising service data, this function should be called before - * Connecting, Broadcasting or Bonding to peer. This function can be called during - * advertising to enable/disable broadcast pipes. Use this as an alternative to @ref lib_aci_open_adv_pipe - * to avoid multiple function calls for placing multiple pipes in the adv data. - * @param adv_service_data_pipes Pipe bitmap, where '1' indicates that the corresponding - * Valid Values: 0000000000000000 to FEFFFFFFFFFFFF7F (See the ACI Pipe Status Evt bitmap in the nRF8001 datasheet - * TX_BROADCAST pipe data is to be placed in Advertising Service Data fields - * @return true if the Open Adv Pipe message was sent successfully to the radio. -*/ -bool lib_aci_open_adv_pipes(const uint8_t * const adv_service_data_pipes); - - -//@} - -/** @name ACI commands available in Connected mode */ -//@{ - - -/** @brief Sets a given application latency. - * @details This function sends a @c setApplicationLatency command. - * @return True if the transaction is successfully initiated. - */ -bool lib_aci_set_app_latency(uint16_t latency, aci_app_latency_mode_t latency_mode); - -/** @brief Opens a remote pipe. - * @details This function sends an @c OpenRemotePipe command. - * @param pipe Number of the pipe to open. - * @return True if the transaction is successfully initiated. - */ -bool lib_aci_open_remote_pipe(aci_state_t *aci_stat, uint8_t pipe); - -/** @brief Closes a remote pipe. - * @details This function sends an @c CloseRemotePipe command. - * @param pipe Pipe number to close. - * @return True if the transaction is successfully initiated. - */ -bool lib_aci_close_remote_pipe(aci_state_t *aci_stat, uint8_t pipe); - -/** @brief Sends data on a given pipe. - * @details This function sends a @c SendData command with application data to - * the radio. This function memorizes credit use, and checks that - * enough credits are available. - * @param pipe Pipe number on which the data should be sent. - * @param value Pointer to the data to send. - * @param size Size of the data to send. - * @return True if the transaction is successfully initiated. - */ -bool lib_aci_send_data(uint8_t pipe, uint8_t *value, uint8_t size); - -/** @brief Requests data from a given pipe. - * @details This function sends a @c RequestData command to the radio. This - * function memorizes credit uses, and check that enough credits are available. - * After this command, the radio sends back either a @c DataReceivedEvent - * or a @c PipeErrorEvent. - * @param pipe Pipe number on which the data is requested. - * @return True if the transaction is successfully initiated. - */ -bool lib_aci_request_data(aci_state_t *aci_stat, uint8_t pipe); - -/** @brief Sends a L2CAP change connection parameters request. - * @details This function sends a @c ChangeTiming command to the radio. This command triggers a "L2CAP change connection parameters" request - * to the master. If the master rejects or accepts but doesn't change the connection parameters within - * 30 seconds, a timing event with the unchanged connection parameters is sent by the radio. - * If the request is accepted and the master changes connection parameters, a timing event with - * the new connection parameters is sent by the radio. - * If the master doesn't reply to the request within 60 seconds, the radio disconnects. - * @param minimun_cx_interval Minimum connection interval requested, in multiple of 1.25 ms. - * @param maximum_cx_interval Maximum connection interval requested, in multiple of 1.25 ms. - * @param slave_latency requested slave latency. - * @param timeout requested slave timeout, in multiple of 10 ms. - * @return True if the transaction is successfully initiated. - */ -bool lib_aci_change_timing(uint16_t minimun_cx_interval, uint16_t maximum_cx_interval, uint16_t slave_latency, uint16_t timeout); - -/** @brief Sends a L2CAP change connection parameters request with the connection predefined preffered connection parameters. - * @details This function sends a @c ChangeTiming command to the radio. This command triggers a "L2CAP change connection parameters" request - * to the master. If the master rejects or accepts but doesn't change the connection parameters within - * 30 seconds, a timing event with the unchanged connection parameters is sent by the radio. - * If the request is accepted and the master changes connection parameters, a timing event with - * the new connection parameters is sent by the radio. - * If the master doesn't reply to the request within 60 seconds, the radio disconnects. - * The timing parameters used are the Timing parameters in the GAP settings in the nRFgo Studio. - * The Timing parameters as stored as the GAP Preferred Peripheral Connection Parameters. - * @return True if the transaction is successfully initiated. - */ -bool lib_aci_change_timing_GAP_PPCP(void); - -/** @brief Sends acknowledgement message to peer. - * @details This function sends @c SendDataAck command to radio. The radio is expected - * to send either Handle Value Confirmation or Write response depending - * on whether the data is stored remotely or locally. - * @param pipe Pipe number for which the acknowledgement is to be sent. - * @return True if the ack was sent successfully. False otherwise. -*/ -bool lib_aci_send_ack(aci_state_t *aci_stat, const uint8_t pipe); - -/** @brief Sends negative acknowledgement message to peer. - * @details This function sends @c SendDataNack command to radio. The radio is expected - * to send Error Response to the peer. - * @param pipe Pipe number for which the nack is to be sent. - * @param error_code Error code to be sent in the NACk. - * @return True if the nack was sent successfully. False otherwise. -*/ -bool lib_aci_send_nack(aci_state_t *aci_stat, const uint8_t pipe, const uint8_t error_code); - -/** @brief Sends ReadDynamicData command to the host. - * @details This function sends @c ReadDynamicData command to host. The host is expected - * to send @c CommandResponse back with the dynamic data. The application is expected to - * call this function in a loop until all the dynamic data is read out from the host. - * As long as there is dynamic data to be read from the host, the command response - * for this message has its status field set to ACI_STATUS_TRANSACTION_CONTINUE (0x01). - * The application may chose to store this read out data in a non-volatile memory location - * and later chose to write it back using the function lib_aci_write_dynamic_data. - * @return True if the command was sent successfully through the ACI. False otherwise. -*/ -bool lib_aci_read_dynamic_data(void); - -/** @brief Sends WriteDynamicData command to the host. - * @details This function sends @c WriteDynamicData command to host. The host is expected - * to send @c CommandResponse with the status of this operation. As long as the status field - * in the @c CommandResponse is ACI_STATUS_TRANSACTION_CONTINUE (0x01), the hosts expects - * more dynamic data to be written. This function should ideally be called in a cycle, - * until all the stored dynamic data is sent to the host. This function should be - * called with the dynamic data obtained from the response to a @c ReadDynamicData - * (see @c lib_aci_read_dynamic_data) command. - * @param sequence_number Sequence number of the dynamic data to be sent. - * @param dynamic_data Pointer to the dynamic data. - * @param length Length of the dynamic data. - * @return True if the command was sent successfully through the ACI. False otherwise. -*/ -bool lib_aci_write_dynamic_data(uint8_t sequence_number, uint8_t* dynamic_data, uint8_t length); -//@} - -/** @name ACI commands available while connected in Bond mode */ -//@{ - -/** @brief Sends a SMP Security Request. - * @details This function send a @c BondRequest command to the radio. - * This command triggers a SMP Security Request to the master. If the - * master rejects with a pairing failed or if the bond timer expires the connection is closed. - * @return True if the transaction is successfully initiated. - */ -bool lib_aci_bond_request(void); - -/** @brief Set the key requested by the 8001. - * @details This function sends an @c SetKey command to the radio. - * @param key_rsp_type Type of key. - * @param key Pointer to the key to set. - * @param len Length of the key. - * @return True if the transaction is successfully initiated. -*/ -bool lib_aci_set_key(aci_key_type_t key_rsp_type, uint8_t *key, uint8_t len); - -//@} - - - -/** @name ACI commands available in Test mode */ -//@{ - -/** @brief Sends an echo message - * @details This function sends an @c Echo command to the radio. lib_aci - * places the Echp ACI command in the ACI command queue - * @param message_size Length of the data to send. - * @param message_data Pointer to the data to send. - * @return True if the transaction is successfully initiated. -*/ -bool lib_aci_echo_msg(uint8_t message_size, uint8_t *message_data); - -/** @brief Sends an DTM command - * @details This function sends an @c DTM command to the radio. - * @param dtm_command_msbyte Most significant byte of the DTM command. - * @param dtm_command_lsbyte Least significant byte of the DTM command. - * @return True if the transaction is successfully initiated. -*/ -bool lib_aci_dtm_command(uint8_t dtm_command_msbyte, uint8_t dtm_command_lsbyte); - -/** @brief Gets an ACI event from the ACI Event Queue - * @details This function gets an ACI event from the ACI event queue. - * The queue is updated by the SPI driver for the ACI running in the interrupt context - * @param aci_stat pointer to the state of the ACI. - * @param p_aci_data pointer to the ACI Event. The ACI Event received will be copied into this pointer. - * @return True if an ACI Event was copied to the pointer. -*/ -bool lib_aci_event_get(aci_state_t *aci_stat, hal_aci_evt_t * aci_evt); - -/** @brief Peeks an ACI event from the ACI Event Queue - * @details This function peeks at the top event in the ACI event queue. - * In polling mode, this function will query the nRF8001 for pending events, but unlike - * lib_aci_event_get() it will not dequeue the event from the local queue, but will instead - * only peek at it. - * @return True if an ACI Event was copied to the pointer. -*/ -bool lib_aci_event_peek(hal_aci_evt_t *p_aci_evt_data); - -/** @brief Flushes the events in the ACI command queues and ACI Event queue - * -*/ -void lib_aci_flush(void); - -/** @brief Return full status of the Event queue - * @details - * - */ - bool lib_aci_event_queue_full(void); - - /** @brief Return empty status of the Event queue - * @details - * - */ - bool lib_aci_event_queue_empty(void); - -/** @brief Return full status of Command queue - * @details - * - */ - bool lib_aci_command_queue_full(void); - - /** @brief Return empty status of Command queue - * @details - * - */ - bool lib_aci_command_queue_empty(void); - -//@} - -/** @} */ - -#ifdef __cplusplus -} -#endif - -#endif /* LIB_ACI_H__ */ +/* Copyright (c) 2014, Nordic Semiconductor ASA + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/** + * @file + * @defgroup aci-lib aci-library + * @brief ACI library + * + * Library for the logical part of the Application Controller Interface (ACI) + * + * @ingroup nrf8001 + */ + +#ifndef LIB_ACI_H__ +#define LIB_ACI_H__ + +/** +* @{ +*/ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "hal_platform.h" +#include "hal_aci_tl.h" +#include "aci_queue.h" +#include "aci.h" +#include "aci_cmds.h" +#include "aci_evts.h" + +#define EVT_CMD_RESPONSE_MIN_LENGTH 3 + +#define PIPES_ARRAY_SIZE ((ACI_DEVICE_MAX_PIPES + 7)/8) + +/* Same size as a hal_aci_data_t */ +typedef struct { + uint8_t debug_byte; + aci_evt_t evt; +} _aci_packed_ hal_aci_evt_t; + +ACI_ASSERT_SIZE(hal_aci_evt_t, 34); + +typedef struct +{ + uint8_t location; /**< enum aci_pipe_store_t */ + aci_pipe_type_t pipe_type; +} services_pipe_type_mapping_t; + +typedef struct aci_setup_info_t +{ + services_pipe_type_mapping_t *services_pipe_type_mapping; + uint8_t number_of_pipes; + hal_aci_data_t *setup_msgs; + uint8_t num_setup_msgs; +} aci_setup_info_t; + + + +// aci_struct that will contain +// total initial credits +// current credit +// current state of the aci (setup/standby/active/sleep) +// open remote pipe pending +// close remote pipe pending +// Current pipe available bitmap +// Current pipe closed bitmap +// Current connection interval, slave latency and link supervision timeout +// Current State of the the GATT client (Service Discovery status) +// Relationship of bond to peer address +typedef struct aci_state_t +{ + aci_pins_t aci_pins; /* Pins on the MCU used to connect to the nRF8001 */ + aci_setup_info_t aci_setup_info; /* Data structures that are created from nRFgo Studio */ + uint8_t bonded; /* ( aci_bond_status_code_t ) Is the nRF8001 bonded to a peer device */ + uint8_t data_credit_total; /* Total data credit available for the specific version of the nRF8001, total equals available when a link is established */ + aci_device_operation_mode_t device_state; /* Operating mode of the nRF8001 */ + + /* */ + + /* Start : Variables that are valid only when in a connection */ + uint8_t data_credit_available; /* Available data credits at a specific point of time, ACI_EVT_DATA_CREDIT updates the available credits */ + + uint16_t connection_interval; /* Multiply by 1.25 to get the connection interval in milliseconds*/ + uint16_t slave_latency; /* Number of consecutive connection intervals that the nRF8001 is not required to transmit. Use this to save power */ + uint16_t supervision_timeout; /* Multiply by 10 to get the supervision timeout in milliseconds */ + + uint8_t pipes_open_bitmap[PIPES_ARRAY_SIZE]; /* Bitmap -> pipes are open and can be used for sending data over the air */ + uint8_t pipes_closed_bitmap[PIPES_ARRAY_SIZE]; /* Bitmap -> pipes are closed and cannot be used for sending data over the air */ + bool confirmation_pending; /* Attribute protocol Handle Value confirmation is pending for a Handle Value Indication + (ACK is pending for a TX_ACK pipe) on local GATT Server*/ + /* End : Variables that are valid only when in a connection */ + +} aci_state_t; + + + +#define DISCONNECT_REASON_CX_TIMEOUT 0x08 +#define DISCONNECT_REASON_CX_CLOSED_BY_PEER_DEVICE 0x13 +#define DISCONNECT_REASON_POWER_LOSS 0x14 +#define DISCONNECT_REASON_CX_CLOSED_BY_LOCAL_DEVICE 0x16 +#define DISCONNECT_REASON_ADVERTISER_TIMEOUT 0x50 + + +/** @name Functions for library management */ +//@{ + +/** @brief Function to enable printing of all ACI commands sent and ACI events received + * @details This function shall be used to enable or disable the debug printing. + Debug printing is disabled by default. + */ +void lib_aci_debug_print(bool enable); + +/** @brief Function to pin reset the nRF8001 + * @details Pin resets the nRF8001 also handles differences between development boards + */ +void lib_aci_pin_reset(void); + +/** @brief Initialization function. + * @details This function shall be used to initialize/reset ACI Library and also Resets the + * nRF8001 by togging the reset pin of the nRF8001. This function will reset + * all the variables locally used by ACI library to their respective default values. + * @param bool True if the data was successfully queued for sending, + * false if there is no more space to store messages to send. + */ +void lib_aci_init(aci_state_t *aci_stat, bool debug); + + +/** @brief Gets the number of currently available ACI credits. + * @return Number of ACI credits. + */ +uint8_t lib_aci_get_nb_available_credits(aci_state_t *aci_stat); + +/** @brief Gets the connection interval in milliseconds. + * @return Connection interval in milliseconds. + */ +uint16_t lib_aci_get_cx_interval_ms(aci_state_t *aci_stat); + +/** @brief Gets the connection interval in multiple of 1.25 ms. + * @return Connection interval in multiple of 1.25 ms. + */ +uint16_t lib_aci_get_cx_interval(aci_state_t *aci_stat); + +/** @brief Gets the current slave latency. + * @return Current slave latency. + */ +uint16_t lib_aci_get_slave_latency(aci_state_t *aci_stat); + +/** @brief Checks if a given pipe is available. + * @param pipe Pipe to check. + * @return True if the pipe is available, otherwise false. + */ +bool lib_aci_is_pipe_available(aci_state_t *aci_stat, uint8_t pipe); + +/** @brief Checks if a given pipe is closed. + * @param pipe Pipe to check. + * @return True if the pipe is closed, otherwise false. + */ +bool lib_aci_is_pipe_closed(aci_state_t *aci_stat, uint8_t pipe); + +/** @brief Checks if the discovery operation is finished. + * @return True if the discovery is finished. + */ +bool lib_aci_is_discovery_finished(aci_state_t *aci_stat); + + + +//@} + +/** @name ACI Commands available in all modes */ +//@{ + +/** @brief Sets the radio in sleep mode. + * @details The function sends a @c sleep command to the radio. + * If the radio is advertising or connected, it sends back an error, then use lib_aci_radio_reset + * if advertising or disconnect if in a connection. + * @return True if the transaction is successfully initiated. + */ +bool lib_aci_sleep(void); + +/** @brief Resets the radio. + * @details The function sends a @c BasebandReset command to the radio. + * @return True if the transaction is successfully initiated. + */ +bool lib_aci_radio_reset(void); + +/** @brief Radio starts directed advertising to bonded device. + * @details The function sends a @c DirectedConnect command to the radio. + * @return True if the transaction is successfully initiated. + */ +bool lib_aci_direct_connect(void); + +/** @brief Gets the radio's version. + * @details This function sends a @c GetDeviceVersion command. + * @return True if the transaction is successfully initiated. + */ +bool lib_aci_device_version(void); + +/** @brief Gets the device address. + * @details This function sends a @c GetDeviceAddress command. + * @return True if the transaction is successfully initiated. + */ +bool lib_aci_get_address(void); + +/** @brief Gets the temperature. + * @details This function sends a @c GetTemperature command. lib_aci + * calls the @ref lib_aci_transaction_finished_hook() function when the temperature is received. + * @return True if the transaction is successfully initiated. + */ +bool lib_aci_get_temperature(void); + +/** @brief Gets the battery level. + * @details This function sends a @c GetBatteryLevel command. + * @return True if the transaction is successfully initiated. + */ +bool lib_aci_get_battery_level(void); + +//@} + +/** @name ACI commands available in Sleep mode */ +//@{ + +/** @brief Wakes up the radio. + * @details This function sends a @c Wakeup command to wake up the radio from + * sleep mode. When woken up the radio sends a @c DeviceStartedEvent and + * a @c CommandResponseEvent. + * @return True if the transaction is successfully initiated. + */ +bool lib_aci_wakeup(void); + +//@} + +/** @name ACI commands available in Active mode */ +//@{ + +/** @brief Sets the radio in test mode. + * @details This function sends a @c Test command to the radio. There are two + * Test modes available: + * - UART: DTM commands are received over UART. + * - ACI: DTM commands are received over ACI. + * The same command is used to exit the test mode When receiving + * a @c DeviceStartedEvent the radio has entered the new mode. + * @param enter_exit_test_mode Enter a Test mode, or exit Test mode. + * @return True if the transaction is successfully initiated. + */ +bool lib_aci_test(aci_test_mode_change_t enter_exit_test_mode); + +/** @brief Sets the radio's TX power. + * @details This function sends a @c SetTxPower command. + * @param tx_power TX power to be used by the radio. + * @return True if the transaction is successfully initiated. + */ +bool lib_aci_set_tx_power(aci_device_output_power_t tx_power); + +/** @brief Tries to connect to a peer device. + * @details This function sends a @c Connect command to the radio. + * @param run_timeout Maximum advertising time in seconds (0 means infinite). + * @param adv_interval Advertising interval (in multiple of 0.625 ms). + * @return True if the transaction is successfully initiated. + */ +bool lib_aci_connect(uint16_t run_timeout, uint16_t adv_interval); + +/** @brief Tries to bond with a peer device. + * @details This function sends a @c Bond command to the radio. + * @param run_timeout Maximum advertising time in seconds (0 means infinite). + * @param adv_interval Advertising interval (in multiple of 0.625 ms). + * @return True if the transaction is successfully initiated. + */ +bool lib_aci_bond(uint16_t run_timeout, uint16_t adv_interval); + +/** @brief Disconnects from peer device. + * @details This function sends a @c Disconnect command to the radio. + * @param reason Reason for disconnecting. + * @return True if the transaction is successfully initiated. + */ +bool lib_aci_disconnect(aci_state_t *aci_stat, aci_disconnect_reason_t reason); + +/**@brief Sets Local Data. + * @details + * This command updates the value of the characteristic value or the characteristic descriptor stored locally on the device. + * Can be called for all types of pipes as long as the data is stored locally. + * @param ACI state structure + * @param pipe Pipe number on which the data should be set. + * @param value Pointer to the data to set. + * @param size Size of the data to set. + * @return True if the transaction is successfully initiated. +*/ +bool lib_aci_set_local_data(aci_state_t *aci_stat, uint8_t pipe, uint8_t *value, uint8_t size); + +/** @brief Sends Broadcast message to the radio. + * @details The Broadcast message starts advertisement procedure + * using the given interval with the intention of broadcasting data to a peer device. + * @param timeout Time, in seconds, to advertise before exiting to standby mode (0 means infinite). + * Valid values: 0 to 16383. + * @param adv_interval Advertising interval (in multiple of 0.625 ms). + * Valid values: 160 to 16384 (which corresponds to an interval from 100 ms to 10.24 s). + * @return True if the broadcast message is sent successfully to the radio. +*/ +bool lib_aci_broadcast(const uint16_t timeout, const uint16_t adv_interval); + +/** @name Open Advertising Pipes. */ + +/** @brief Sends a command to the radio to set the input pipe to be placed in Advertisement Service Data. + * @details This function sends a command to the radio that places the pipe in + * advertisement service data. To start advertising service data, call this function before + * Connecting, Broadcasting or Bonding to peer. The data that should be sent in the advertisement packets + * must be set using the @c lib_aci_set_local_data function. This function can be called during + * advertising to enable/disable broadcast pipes. + * @param pipe The pipe that has to be placed in advertising service data. + * @return True if the Open Adv Pipe message is sent successfully to the radio. +*/ +bool lib_aci_open_adv_pipe(const uint8_t pipe); + + +/** @name Open Advertising Pipes */ + +/** @brief Sends a command to the radio to set the pipes to be placed in Advertisement Service Data. + * @details This function will send a command to the radio that will set the pipes to be placed in + * advertisement Service Data. To start advertising service data, this function should be called before + * Connecting, Broadcasting or Bonding to peer. This function can be called during + * advertising to enable/disable broadcast pipes. Use this as an alternative to @ref lib_aci_open_adv_pipe + * to avoid multiple function calls for placing multiple pipes in the adv data. + * @param adv_service_data_pipes Pipe bitmap, where '1' indicates that the corresponding + * Valid Values: 0000000000000000 to FEFFFFFFFFFFFF7F (See the ACI Pipe Status Evt bitmap in the nRF8001 datasheet + * TX_BROADCAST pipe data is to be placed in Advertising Service Data fields + * @return true if the Open Adv Pipe message was sent successfully to the radio. +*/ +bool lib_aci_open_adv_pipes(const uint8_t * const adv_service_data_pipes); + + +//@} + +/** @name ACI commands available in Connected mode */ +//@{ + + +/** @brief Sets a given application latency. + * @details This function sends a @c setApplicationLatency command. + * @return True if the transaction is successfully initiated. + */ +bool lib_aci_set_app_latency(uint16_t latency, aci_app_latency_mode_t latency_mode); + +/** @brief Opens a remote pipe. + * @details This function sends an @c OpenRemotePipe command. + * @param pipe Number of the pipe to open. + * @return True if the transaction is successfully initiated. + */ +bool lib_aci_open_remote_pipe(aci_state_t *aci_stat, uint8_t pipe); + +/** @brief Closes a remote pipe. + * @details This function sends an @c CloseRemotePipe command. + * @param pipe Pipe number to close. + * @return True if the transaction is successfully initiated. + */ +bool lib_aci_close_remote_pipe(aci_state_t *aci_stat, uint8_t pipe); + +/** @brief Sends data on a given pipe. + * @details This function sends a @c SendData command with application data to + * the radio. This function memorizes credit use, and checks that + * enough credits are available. + * @param pipe Pipe number on which the data should be sent. + * @param value Pointer to the data to send. + * @param size Size of the data to send. + * @return True if the transaction is successfully initiated. + */ +bool lib_aci_send_data(uint8_t pipe, uint8_t *value, uint8_t size); + +/** @brief Requests data from a given pipe. + * @details This function sends a @c RequestData command to the radio. This + * function memorizes credit uses, and check that enough credits are available. + * After this command, the radio sends back either a @c DataReceivedEvent + * or a @c PipeErrorEvent. + * @param pipe Pipe number on which the data is requested. + * @return True if the transaction is successfully initiated. + */ +bool lib_aci_request_data(aci_state_t *aci_stat, uint8_t pipe); + +/** @brief Sends a L2CAP change connection parameters request. + * @details This function sends a @c ChangeTiming command to the radio. This command triggers a "L2CAP change connection parameters" request + * to the master. If the master rejects or accepts but doesn't change the connection parameters within + * 30 seconds, a timing event with the unchanged connection parameters is sent by the radio. + * If the request is accepted and the master changes connection parameters, a timing event with + * the new connection parameters is sent by the radio. + * If the master doesn't reply to the request within 60 seconds, the radio disconnects. + * @param minimun_cx_interval Minimum connection interval requested, in multiple of 1.25 ms. + * @param maximum_cx_interval Maximum connection interval requested, in multiple of 1.25 ms. + * @param slave_latency requested slave latency. + * @param timeout requested slave timeout, in multiple of 10 ms. + * @return True if the transaction is successfully initiated. + */ +bool lib_aci_change_timing(uint16_t minimun_cx_interval, uint16_t maximum_cx_interval, uint16_t slave_latency, uint16_t timeout); + +/** @brief Sends a L2CAP change connection parameters request with the connection predefined preffered connection parameters. + * @details This function sends a @c ChangeTiming command to the radio. This command triggers a "L2CAP change connection parameters" request + * to the master. If the master rejects or accepts but doesn't change the connection parameters within + * 30 seconds, a timing event with the unchanged connection parameters is sent by the radio. + * If the request is accepted and the master changes connection parameters, a timing event with + * the new connection parameters is sent by the radio. + * If the master doesn't reply to the request within 60 seconds, the radio disconnects. + * The timing parameters used are the Timing parameters in the GAP settings in the nRFgo Studio. + * The Timing parameters as stored as the GAP Preferred Peripheral Connection Parameters. + * @return True if the transaction is successfully initiated. + */ +bool lib_aci_change_timing_GAP_PPCP(void); + +/** @brief Sends acknowledgement message to peer. + * @details This function sends @c SendDataAck command to radio. The radio is expected + * to send either Handle Value Confirmation or Write response depending + * on whether the data is stored remotely or locally. + * @param pipe Pipe number for which the acknowledgement is to be sent. + * @return True if the ack was sent successfully. False otherwise. +*/ +bool lib_aci_send_ack(aci_state_t *aci_stat, const uint8_t pipe); + +/** @brief Sends negative acknowledgement message to peer. + * @details This function sends @c SendDataNack command to radio. The radio is expected + * to send Error Response to the peer. + * @param pipe Pipe number for which the nack is to be sent. + * @param error_code Error code to be sent in the NACk. + * @return True if the nack was sent successfully. False otherwise. +*/ +bool lib_aci_send_nack(aci_state_t *aci_stat, const uint8_t pipe, const uint8_t error_code); + +/** @brief Sends ReadDynamicData command to the host. + * @details This function sends @c ReadDynamicData command to host. The host is expected + * to send @c CommandResponse back with the dynamic data. The application is expected to + * call this function in a loop until all the dynamic data is read out from the host. + * As long as there is dynamic data to be read from the host, the command response + * for this message has its status field set to ACI_STATUS_TRANSACTION_CONTINUE (0x01). + * The application may chose to store this read out data in a non-volatile memory location + * and later chose to write it back using the function lib_aci_write_dynamic_data. + * @return True if the command was sent successfully through the ACI. False otherwise. +*/ +bool lib_aci_read_dynamic_data(void); + +/** @brief Sends WriteDynamicData command to the host. + * @details This function sends @c WriteDynamicData command to host. The host is expected + * to send @c CommandResponse with the status of this operation. As long as the status field + * in the @c CommandResponse is ACI_STATUS_TRANSACTION_CONTINUE (0x01), the hosts expects + * more dynamic data to be written. This function should ideally be called in a cycle, + * until all the stored dynamic data is sent to the host. This function should be + * called with the dynamic data obtained from the response to a @c ReadDynamicData + * (see @c lib_aci_read_dynamic_data) command. + * @param sequence_number Sequence number of the dynamic data to be sent. + * @param dynamic_data Pointer to the dynamic data. + * @param length Length of the dynamic data. + * @return True if the command was sent successfully through the ACI. False otherwise. +*/ +bool lib_aci_write_dynamic_data(uint8_t sequence_number, uint8_t* dynamic_data, uint8_t length); +//@} + +/** @name ACI commands available while connected in Bond mode */ +//@{ + +/** @brief Sends a SMP Security Request. + * @details This function send a @c BondRequest command to the radio. + * This command triggers a SMP Security Request to the master. If the + * master rejects with a pairing failed or if the bond timer expires the connection is closed. + * @return True if the transaction is successfully initiated. + */ +bool lib_aci_bond_request(void); + +/** @brief Set the key requested by the 8001. + * @details This function sends an @c SetKey command to the radio. + * @param key_rsp_type Type of key. + * @param key Pointer to the key to set. + * @param len Length of the key. + * @return True if the transaction is successfully initiated. +*/ +bool lib_aci_set_key(aci_key_type_t key_rsp_type, uint8_t *key, uint8_t len); + +//@} + + + +/** @name ACI commands available in Test mode */ +//@{ + +/** @brief Sends an echo message + * @details This function sends an @c Echo command to the radio. lib_aci + * places the Echp ACI command in the ACI command queue + * @param message_size Length of the data to send. + * @param message_data Pointer to the data to send. + * @return True if the transaction is successfully initiated. +*/ +bool lib_aci_echo_msg(uint8_t message_size, uint8_t *message_data); + +/** @brief Sends an DTM command + * @details This function sends an @c DTM command to the radio. + * @param dtm_command_msbyte Most significant byte of the DTM command. + * @param dtm_command_lsbyte Least significant byte of the DTM command. + * @return True if the transaction is successfully initiated. +*/ +bool lib_aci_dtm_command(uint8_t dtm_command_msbyte, uint8_t dtm_command_lsbyte); + +/** @brief Gets an ACI event from the ACI Event Queue + * @details This function gets an ACI event from the ACI event queue. + * The queue is updated by the SPI driver for the ACI running in the interrupt context + * @param aci_stat pointer to the state of the ACI. + * @param p_aci_data pointer to the ACI Event. The ACI Event received will be copied into this pointer. + * @return True if an ACI Event was copied to the pointer. +*/ +bool lib_aci_event_get(aci_state_t *aci_stat, hal_aci_evt_t * aci_evt); + +/** @brief Peeks an ACI event from the ACI Event Queue + * @details This function peeks at the top event in the ACI event queue. + * In polling mode, this function will query the nRF8001 for pending events, but unlike + * lib_aci_event_get() it will not dequeue the event from the local queue, but will instead + * only peek at it. + * @return True if an ACI Event was copied to the pointer. +*/ +bool lib_aci_event_peek(hal_aci_evt_t *p_aci_evt_data); + +/** @brief Flushes the events in the ACI command queues and ACI Event queue + * +*/ +void lib_aci_flush(void); + +/** @brief Return full status of the Event queue + * @details + * + */ + bool lib_aci_event_queue_full(void); + + /** @brief Return empty status of the Event queue + * @details + * + */ + bool lib_aci_event_queue_empty(void); + +/** @brief Return full status of Command queue + * @details + * + */ + bool lib_aci_command_queue_full(void); + + /** @brief Return empty status of Command queue + * @details + * + */ + bool lib_aci_command_queue_empty(void); + +//@} + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* LIB_ACI_H__ */ diff --git a/src/nrf8001/uart_over_ble.h b/src/nrf8001/uart_over_ble.h index 9a72821f..fe2709a8 100644 --- a/src/nrf8001/uart_over_ble.h +++ b/src/nrf8001/uart_over_ble.h @@ -1,79 +1,79 @@ -/* Copyright (c) 2013, Nordic Semiconductor ASA - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 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. - * - * Neither the name of Nordic Semiconductor ASA 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. - */ - -/** - * @file - * @brief BLE specific macros - * @ingroup nrf8001 - */ - -#ifndef UART_OVER_BLE_H__ -#define UART_OVER_BLE_H__ - -/** - * @def UART_OVER_BLE_DISCONNECT - * @brief - * Command to queue a ACI Disconnect to the nRF8001 - */ -#define UART_OVER_BLE_DISCONNECT (0x01) - - -/** - * @def UART_OVER_BLE_LINK_TIMING_REQ - * @brief - * Command to queue a ACI Change Timing to the nRF8001 - */ -#define UART_OVER_BLE_LINK_TIMING_REQ (0x02) - -/** - * @def UART_OVER_BLE_TRANSMIT_STOP - * @brief - * Command to stop sending UART over BLE packets - */ -#define UART_OVER_BLE_TRANSMIT_STOP (0x03) - - -/** - * @def UART_OVER_BLE_TRANSMIT_OK - * @brief - * Command to allow sending UART over BLE packets - */ -#define UART_OVER_BLE_TRANSMIT_OK (0x04) - -/** - * @struct uart_over_ble_t - * @brief State of the UART RTS over Bluetooth Low Energy(BLE) - */ -typedef struct -{ - uint8_t uart_rts_local; /**< State of the local UART RTS */ - uint8_t uart_rts_remote; /**< State of the remote UART RTS */ -} uart_over_ble_t; - -#endif // UART_OVER_BLE_H__ +/* Copyright (c) 2013, Nordic Semiconductor ASA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 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. + * + * Neither the name of Nordic Semiconductor ASA 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. + */ + +/** + * @file + * @brief BLE specific macros + * @ingroup nrf8001 + */ + +#ifndef UART_OVER_BLE_H__ +#define UART_OVER_BLE_H__ + +/** + * @def UART_OVER_BLE_DISCONNECT + * @brief + * Command to queue a ACI Disconnect to the nRF8001 + */ +#define UART_OVER_BLE_DISCONNECT (0x01) + + +/** + * @def UART_OVER_BLE_LINK_TIMING_REQ + * @brief + * Command to queue a ACI Change Timing to the nRF8001 + */ +#define UART_OVER_BLE_LINK_TIMING_REQ (0x02) + +/** + * @def UART_OVER_BLE_TRANSMIT_STOP + * @brief + * Command to stop sending UART over BLE packets + */ +#define UART_OVER_BLE_TRANSMIT_STOP (0x03) + + +/** + * @def UART_OVER_BLE_TRANSMIT_OK + * @brief + * Command to allow sending UART over BLE packets + */ +#define UART_OVER_BLE_TRANSMIT_OK (0x04) + +/** + * @struct uart_over_ble_t + * @brief State of the UART RTS over Bluetooth Low Energy(BLE) + */ +typedef struct +{ + uint8_t uart_rts_local; /**< State of the local UART RTS */ + uint8_t uart_rts_remote; /**< State of the remote UART RTS */ +} uart_over_ble_t; + +#endif // UART_OVER_BLE_H__ diff --git a/src/scam/scam.hpp b/src/scam/scam.hpp index cd80c9ca..91fcae17 100644 --- a/src/scam/scam.hpp +++ b/src/scam/scam.hpp @@ -83,7 +83,7 @@ namespace upm { typedef enum { FORMAT_VGA = 7, // 640x480 - FORMAT_CIF = 5, // 352×288 + FORMAT_CIF = 5, // 352*288 FORMAT_OCIF = 3 // ??? (maybe they meant QCIF?) } PIC_FORMATS_T; diff --git a/src/tb7300/tb7300.hpp b/src/tb7300/tb7300.hpp index 78d16e54..d9cedf0e 100644 --- a/src/tb7300/tb7300.hpp +++ b/src/tb7300/tb7300.hpp @@ -57,9 +57,9 @@ namespace upm { * The TB7200 Series PI thermostats are designed for zoning * applications, and the TB7300 Series PI thermostats are designed * for fan coil control. Both Series are communicating thermostats - * with models available in BACnet® MS/TP protocol and can be easily + * with models available in BACnet(r) MS/TP protocol and can be easily * integrated into a WEBs-AX building automation system based on the - * NiagaraAX® platform. + * NiagaraAX(r) platform. * * TB7200 and TB7300 Series thermostats are compatible with the * Honeywell Occupancy Sensor Cover. Thermostats equipped with an diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 136349be..758dd7f1 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -2,6 +2,13 @@ add_test (NAME check_consistency COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/check_consistency.py WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) +# Check file encodings in src tree +if (PYTHON2INTERP_FOUND) + add_test (NAME check_file_encoding COMMAND ${PYTHON_EXECUTABLE} + ${CMAKE_CURRENT_SOURCE_DIR}/check_file_encoding.py + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/src) +endif (PYTHON2INTERP_FOUND) + if (BUILDSWIGJAVA) add_test (NAME check_autoloadlibrary COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/check_autoloadlibrary.py diff --git a/tests/check_file_encoding.py b/tests/check_file_encoding.py new file mode 100755 index 00000000..b36f48db --- /dev/null +++ b/tests/check_file_encoding.py @@ -0,0 +1,54 @@ +#!/usr/bin/python + +import unittest +import os +import chardet + +target_exts = ['.h', '.hpp', '.hxx', '.txt'] +valid_encodings = ['ascii', 'utf-8'] + +class EncodingTests(unittest.TestCase): + '''Non-ascii/utf-8 encodings can cause failures on downstream tools + such as documentation-generation and python2 module loading. This + class helps find those files which could cause an encoding problem''' + + def test_headers_ascii(self): + '''Assert/print list of: + file:linenumber offending line + for all lines of matching files which are not in valid_encodings''' + # Keep a map of files with alternate encodes to report + invalid_files = {} + + # Recusively search cwd for files with target_exts + for root, dirs, files in os.walk(os.curdir): + # Work on full paths + for file in files: + file = os.path.join(root, file) + + # Skip any files not ending with target_exts + if not any(file.lower().endswith(x) for x in target_exts): + continue + + # Check each with chardet + with open(file, 'r') as f: + for ndx, line in enumerate(f): + result = chardet.detect(line) + if not result['encoding'] in valid_encodings: + if not invalid_files.has_key(file): + invalid_files[file] = [] + invalid_files[file].append([ndx,line]) + + # Sort the failures by filename + skeys = list(invalid_files.keys()) + skeys.sort() + invalid_lines = '' + for fn in skeys: + for line in invalid_files[fn]: + invalid_lines += '%s:%d %s' % (fn, line[0], line[1]) + + self.assertEqual( len(invalid_files), 0, + "\nThe following modules have alternate encodings:\n" + \ + invalid_lines) + +if __name__ == '__main__': + unittest.main()