diff --git a/CHANGELOG.md b/CHANGELOG.md index ded922bad..f39aea56c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,11 @@ All notable changes to this project will be documented in this file. - Extent compile time SetOptions support (#11204) - ESP32 Extent BLE (#11212) +- ESP32 support for WS2812 hardware driver via RMT or I2S + +- ESP32 support for secondary I2C controller + + ### Changed - ESP32 core library from v1.0.5-rc6 to v1.0.5 - TasmotaSerial library from v3.2.0 to v3.3.0 diff --git a/README.md b/README.md index 232c92565..8105a2f53 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,7 @@ See [CHANGELOG.md](CHANGELOG.md) for detailed change information. Unless your Tasmota powered device exhibits a problem or you need to make use of a feature that is not available in the Tasmota version currently installed on your device, leave your device alone - it works so don't make unnecessary changes! If the release version (i.e., the master branch) exhibits unexpected behaviour for your device and configuration, you should upgrade to the latest development version instead to see if your problem is resolved as some bugs in previous releases or development builds may already have been resolved. -The Tasmota development codebase is checked every 1-2 hours for changes. If new commits have been merged and they compile successfuly, new binary files for every variant will be posted at http://ota.tasmota.com/tasmota/ (this web address can be used for OTA updates too). It is important to note that these binaries are based on the current development codebase. These commits are tested as much as is possible and are typically quite stable. However, it is infeasible to test on the hundreds of different types of devices with all the available configuration options permitted. +Every commit made to the development branch, which is compiling successfuly, will post new binary files at http://ota.tasmota.com/tasmota/ (this web address can be used for OTA updates too). It is important to note that these binaries are based on the current development codebase. These commits are tested as much as is possible and are typically quite stable. However, it is infeasible to test on the hundreds of different types of devices with all the available configuration options permitted. Note that there is a chance, as with any upgrade, that the device may not function as expected. You must always account for the possibility that you may need to flash the device via the serial programming interface if the OTA upgrade fails. Even with the master release, you should always attempt to test the device or a similar prototype before upgrading a device which is in production or is hard to reach. And, as always, make a backup of the device configuration before beginning any firmware update. @@ -125,6 +125,7 @@ People helping to keep the show on the road: - Flexiti for his initial timer implementation - reloxx13 for his [TasmoAdmin](https://github.com/reloxx13/TasmoAdmin) management tool - Joachim Banzhaf for his TSL2561 library and driver +- Andre Thomas for providing many drivers - Gijs Noorlander for his MHZ19, SenseAir and updated PubSubClient drivers - Erik Montnemery for his HomeAssistant Discovery concept and many code tuning tips - Federico Leoni for continued HomeAssistant Discovery support @@ -136,7 +137,6 @@ People helping to keep the show on the road: - Gennaro Tortone for implementing and maintaining Eastron drivers - Raymond Mouthaan for managing Wemos Wiki information - Norbert Richter for his [decode-config.py](https://github.com/tasmota/decode-config) tool -- Andre Thomas for providing [thehackbox](http://thehackbox.org/tasmota/) OTA support and daily development builds - Joel Stein, digiblur and Shantur Rathore for their Tuya research and driver - Frogmore42 for providing many issue answers - Jason2866 for platformio support and providing many issue answers diff --git a/lib/libesp32/ESP32-to-ESP8266-compat/src/esp8266toEsp32.h b/lib/libesp32/ESP32-to-ESP8266-compat/src/esp8266toEsp32.h index 6a45d6632..25f6f539b 100644 --- a/lib/libesp32/ESP32-to-ESP8266-compat/src/esp8266toEsp32.h +++ b/lib/libesp32/ESP32-to-ESP8266-compat/src/esp8266toEsp32.h @@ -114,10 +114,6 @@ typedef int SerConfu8; typedef int SerialConfig; //#define analogWrite(a, b) -// -// WS2812 -// -#define NeoEsp8266BitBang800KbpsMethod NeoEsp32BitBang800KbpsMethod // // UDP // diff --git a/lib/libesp32_div/ESP32-HomeKit/.gitattributes b/lib/libesp32_div/ESP32-HomeKit/.gitattributes new file mode 100644 index 000000000..dfe077042 --- /dev/null +++ b/lib/libesp32_div/ESP32-HomeKit/.gitattributes @@ -0,0 +1,2 @@ +# Auto detect text files and perform LF normalization +* text=auto diff --git a/lib/libesp32_div/ESP32-HomeKit/.gitignore b/lib/libesp32_div/ESP32-HomeKit/.gitignore new file mode 100644 index 000000000..259148fa1 --- /dev/null +++ b/lib/libesp32_div/ESP32-HomeKit/.gitignore @@ -0,0 +1,32 @@ +# Prerequisites +*.d + +# Compiled Object files +*.slo +*.lo +*.o +*.obj + +# Precompiled Headers +*.gch +*.pch + +# Compiled Dynamic libraries +*.so +*.dylib +*.dll + +# Fortran module files +*.mod +*.smod + +# Compiled Static libraries +*.lai +*.la +*.a +*.lib + +# Executables +*.exe +*.out +*.app diff --git a/lib/libesp32_div/ESP32-HomeKit/LICENSE b/lib/libesp32_div/ESP32-HomeKit/LICENSE new file mode 100644 index 000000000..46f369f28 --- /dev/null +++ b/lib/libesp32_div/ESP32-HomeKit/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020 Mixiaoxiao (Wang Bin) + +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. diff --git a/lib/libesp32_div/ESP32-HomeKit/README.md b/lib/libesp32_div/ESP32-HomeKit/README.md new file mode 100644 index 000000000..923bd4a11 --- /dev/null +++ b/lib/libesp32_div/ESP32-HomeKit/README.md @@ -0,0 +1,31 @@ +# Arduino-HomeKit-ESP +Arduino library version of espressif's official [esp-homekit-sdk](https://github.com/espressif/esp-homekit-sdk). + +Currently, only for ESP32 with hardware acceleration. ESP32-S2, ESP32-C3 and future IDF based chips are all on the way. + +Tested on my ESP32 board, works fine. + +The performance is awesome!!! + +The serial log is [here](https://raw.github.com/Mixiaoxiao/Arduino-HomeKit-ESP/master/extras/SerialLog.txt) + +## Setup code + +``111-11-111`` + +## Manual Installation + +Refer to the official guide: [Manual installation](https://www.arduino.cc/en/guide/libraries#toc5) +Note: this library will not publish the release version for Arduino IDE. + + +#### Manual Installation for Windows + +1. Click on _"Clone or Download"_ button, then click _"[Download ZIP](https://github.com/Mixiaoxiao/Arduino-HomeKit-ESP/archive/master.zip)"_ on the page. +1. Extract the contents of the downloaded zip file. +1. Rename the extracted folder to _"Arduino-HomeKit-ESP"_. +1. Move this folder to your libraries directory. (under windows: `C:\Users\\Documents\Arduino\libraries\`) +1. Restart your Arduino IDE. +1. Check out the examples. + + diff --git a/lib/libesp32_div/ESP32-HomeKit/SerialLog.txt b/lib/libesp32_div/ESP32-HomeKit/SerialLog.txt new file mode 100644 index 000000000..04a3862c7 --- /dev/null +++ b/lib/libesp32_div/ESP32-HomeKit/SerialLog.txt @@ -0,0 +1,43 @@ +Boot OK +WiFi connecting... +............... +WiFi connected, IP: 192.168.6.134 +[ 1657] Keystore initialised +[ 1662] Accessory is not Paired with any controller +[ 1664] Database initialised. Accessory Device ID: 90:60:09:AB:F0:1D +[ 1664] HAP Initialization succeeded. Version : 4.0 +[ 1670] MFi auth not supported. Falling back to HAP_MFI_AUTH_NONE +[ 1675] Setup ID: ES32 +[ 1681] HAP Main Loop Started +[ 1684] mDNS initialised +[ 1684] Registering HomeKit web handlers +[ 1687] Announcing _hap._tcp mDNS service +[ 10032] ######## Starting Pair Setup ######## +[ 10032] Pair Setup M1 Received +[ 12073] Pair Setup M2 Successful +[ 12501] Pair Setup M3 Received +[ 14540] Using pair-setup without MFi. +[ 14540] Pair Setup M4 Successful +[ 14929] Pair Setup M5 Received +[ 15023] Pair Setup Successful for CF87DA6B-7078-44BB-AC04-27B6F2B26D37 +[ 15027] Updated state number to 11 +[ 15028] Cleaning Pair Setup Context +[ 15032] Re-announcing _hap._tcp mDNS service +[ 16205] ######## Starting Pair Verify ######## +[ 16205] Pair Verify M1 Received +[ 16327] Pair Verify M2 Successful +[ 16385] Pair Verify M3 Received +[ 16444] HomeKit Session active +[ 16445] Pair Verify Successful for CF87DA6B-7078-44BB-AC04-27B6F2B26D37 +[ 16781] Events Enabled for aid=1 iid=12 +[ 16781] Events Enabled for aid=1 iid=13 +[ 17080] Events Enabled for aid=1 iid=12 +[ 17080] Events Enabled for aid=1 iid=13 +[ 22311] ######## Starting Pair Verify ######## +[ 22311] Pair Verify M1 Received +[ 22435] Pair Verify M2 Successful +[ 22470] Pair Verify M3 Received +[ 22528] HomeKit Session active +[ 22528] Pair Verify Successful for CF87DA6B-7078-44BB-AC04-27B6F2B26D37 +[ 25069] Value Changed +[ 26605] Value Changed \ No newline at end of file diff --git a/lib/libesp32_div/ESP32-HomeKit/examples/HomeKit_IDF/HomeKit_IDF.ino b/lib/libesp32_div/ESP32-HomeKit/examples/HomeKit_IDF/HomeKit_IDF.ino new file mode 100644 index 000000000..d0b7b6743 --- /dev/null +++ b/lib/libesp32_div/ESP32-HomeKit/examples/HomeKit_IDF/HomeKit_IDF.ino @@ -0,0 +1,20 @@ +#include "Arduino.h" +#include "wifi_info.h" +#include "hap.h" + +extern "C" void homekit_main(); + +void setup() { + Serial.begin(115200); + Serial.println("Boot OK"); + wifi_connect(); + // Useful apis: (see hap.h) + // hap_reset_to_factory(); + // hap_reset_homekit_data(); + // hap_reset_pairings(); + homekit_main(); + vTaskDelete(NULL); +} + +void loop() { +} diff --git a/lib/libesp32_div/ESP32-HomeKit/examples/HomeKit_IDF/homekit_main.c b/lib/libesp32_div/ESP32-HomeKit/examples/HomeKit_IDF/homekit_main.c new file mode 100644 index 000000000..b9a14ce2c --- /dev/null +++ b/lib/libesp32_div/ESP32-HomeKit/examples/HomeKit_IDF/homekit_main.c @@ -0,0 +1,244 @@ +/* + * ESPRESSIF MIT License + * + * Copyright (c) 2018 + * + * Permission is hereby granted for use on ESPRESSIF SYSTEMS products only, in which case, + * it is 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. + * + */ +/* HomeKit Smart Outlet Example +*/ +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +//#include +//#include + +static const char *TAG = "HAP outlet"; + +#define SMART_OUTLET_TASK_PRIORITY 1 +#define SMART_OUTLET_TASK_STACKSIZE 4 * 1024 +#define SMART_OUTLET_TASK_NAME "hap_outlet" + +//#define OUTLET_IN_USE_GPIO GPIO_NUM_0 +#define OUTLET_IN_USE_GPIO -1 + +#define ESP_INTR_FLAG_DEFAULT 0 + +static xQueueHandle s_esp_evt_queue = NULL; +/** + * @brief the recover outlet in use gpio interrupt function + */ +static void IRAM_ATTR outlet_in_use_isr(void* arg) +{ + uint32_t gpio_num = (uint32_t) arg; + xQueueSendFromISR(s_esp_evt_queue, &gpio_num, NULL); +} + +/** + * Enable a GPIO Pin for Outlet in Use Detection + */ +static void outlet_in_use_key_init(uint32_t key_gpio_pin) +{ + gpio_config_t io_conf; + /* Interrupt for both the edges */ + io_conf.intr_type = GPIO_INTR_ANYEDGE; + /* Bit mask of the pins */ + io_conf.pin_bit_mask = 1 << key_gpio_pin; + /* Set as input mode */ + io_conf.mode = GPIO_MODE_INPUT; + /* Enable internal pull-up */ + io_conf.pull_up_en = 1; + /* Disable internal pull-down */ + io_conf.pull_down_en = 0; + /* Set the GPIO configuration */ + gpio_config(&io_conf); + + /* Install gpio isr service */ + gpio_install_isr_service(ESP_INTR_FLAG_DEFAULT); + /* Hook isr handler for specified gpio pin */ + gpio_isr_handler_add(key_gpio_pin, outlet_in_use_isr, (void*)key_gpio_pin); +} + +/** + * Initialize the Smart Outlet Hardware.Here, we just enebale the Outlet-In-Use detection. + */ +void smart_outlet_hardware_init(gpio_num_t gpio_num) +{ + s_esp_evt_queue = xQueueCreate(2, sizeof(uint32_t)); + if (s_esp_evt_queue != NULL) { + outlet_in_use_key_init(gpio_num); + } +} + +/* Mandatory identify routine for the accessory. + * In a real accessory, something like LED blink should be implemented + * got visual identification + */ +static int outlet_identify(hap_acc_t *ha) +{ + ESP_LOGI(TAG, "Accessory identified"); + return HAP_SUCCESS; +} + +/* A dummy callback for handling a write on the "On" characteristic of Outlet. + * In an actual accessory, this should control the hardware + */ +static int outlet_write(hap_write_data_t write_data[], int count, + void *serv_priv, void *write_priv) +{ + int i, ret = HAP_SUCCESS; + hap_write_data_t *write; + for (i = 0; i < count; i++) { + write = &write_data[i]; + if (!strcmp(hap_char_get_type_uuid(write->hc), HAP_CHAR_UUID_ON)) { + //ESP_LOGI(TAG, "Received Write. Outlet %s", write->val.b ? "On" : "Off"); + ESP_LOG_LEVEL(ESP_LOG_INFO, TAG, "Received Write. Outlet %s", write->val.b ? "On" : "Off"); + /* TODO: Control Actual Hardware */ + hap_char_update_val(write->hc, &(write->val)); + *(write->status) = HAP_STATUS_SUCCESS; + } else { + *(write->status) = HAP_STATUS_RES_ABSENT; + } + } + return ret; +} + +/*The main thread for handling the Smart Outlet Accessory */ +static void smart_outlet_thread_entry(void *p) +{ + hap_acc_t *accessory; + hap_serv_t *service; + + /* Initialize the HAP core */ + hap_init(HAP_TRANSPORT_WIFI); + + /* Initialise the mandatory parameters for Accessory which will be added as + * the mandatory services internally + */ + hap_acc_cfg_t cfg = { + .name = "Esp-Smart-Outlet", + .manufacturer = "Espressif", + .model = "EspSmartOutlet01", + .serial_num = "001122334455", + .fw_rev = "0.9.0", + .hw_rev = NULL, + .pv = "1.1.0", + .identify_routine = outlet_identify, + .cid = HAP_CID_OUTLET, + }; + /* Create accessory object */ + accessory = hap_acc_create(&cfg); + + /* Add a dummy Product Data */ + uint8_t product_data[] = {'E','S','P','3','2','H','A','P'}; + hap_acc_add_product_data(accessory, product_data, sizeof(product_data)); + + /* Create the Outlet Service. Include the "name" since this is a user visible service */ + service = hap_serv_outlet_create(false, false); + hap_serv_add_char(service, hap_char_name_create("My Smart Outlet")); + + /* Get pointer to the outlet in use characteristic which we need to monitor for state changes */ + hap_char_t *outlet_in_use = hap_serv_get_char_by_uuid(service, HAP_CHAR_UUID_OUTLET_IN_USE); + + /* Set the write callback for the service */ + hap_serv_set_write_cb(service, outlet_write); + + /* Add the Outlet Service to the Accessory Object */ + hap_acc_add_serv(accessory, service); + + /* Add the Accessory to the HomeKit Database */ + hap_add_accessory(accessory); + + /* Initialize the appliance specific hardware. This enables out-in-use detection */ + smart_outlet_hardware_init(OUTLET_IN_USE_GPIO); + + /* For production accessories, the setup code shouldn't be programmed on to + * the device. Instead, the setup info, derived from the setup code must + * be used. Use the factory_nvs_gen utility to generate this data and then + * flash it into the factory NVS partition. + * + * By default, the setup ID and setup info will be read from the factory_nvs + * Flash partition and so, is not required to set here explicitly. + * + * However, for testing purpose, this can be overridden by using hap_set_setup_code() + * and hap_set_setup_id() APIs, as has been done here. + */ + hap_set_setup_code("111-11-111"); + hap_set_setup_id("ES32"); +#ifdef CONFIG_EXAMPLE_USE_HARDCODED_SETUP_CODE + /* Unique Setup code of the format xxx-xx-xxx. Default: 111-22-333 */ + hap_set_setup_code(CONFIG_EXAMPLE_SETUP_CODE); + /* Unique four character Setup Id. Default: ES32 */ + hap_set_setup_id(CONFIG_EXAMPLE_SETUP_ID); +#ifdef CONFIG_APP_WIFI_USE_WAC_PROVISIONING + app_hap_setup_payload(CONFIG_EXAMPLE_SETUP_CODE, CONFIG_EXAMPLE_SETUP_ID, true, cfg.cid); +#else + app_hap_setup_payload(CONFIG_EXAMPLE_SETUP_CODE, CONFIG_EXAMPLE_SETUP_ID, false, cfg.cid); +#endif +#endif + + /* Enable Hardware MFi authentication (applicable only for MFi variant of SDK) */ + hap_enable_mfi_auth(HAP_MFI_AUTH_HW); + + /* Initialize Wi-Fi */ + //app_wifi_init(); + + /* After all the initializations are done, start the HAP core */ + hap_start(); + /* Start Wi-Fi */ + //app_wifi_start(portMAX_DELAY); + + uint32_t io_num = OUTLET_IN_USE_GPIO; + hap_val_t appliance_value = { + .b = true, + }; + /* Listen for Outlet-In-Use state change events. Other read/write functionality will be handled + * by the HAP Core. + * When the Outlet in Use GPIO goes low, it means Outlet is not in use. + * When the Outlet in Use GPIO goes high, it means Outlet is in use. + * Applications can define own logic as per their hardware. + */ + while (1) { + if (xQueueReceive(s_esp_evt_queue, &io_num, portMAX_DELAY) == pdFALSE) { + ESP_LOGI(TAG, "Outlet-In-Use trigger FAIL"); + } else { + appliance_value.b = gpio_get_level(io_num); + /* If any state change is detected, update the Outlet In Use characteristic value */ + hap_char_update_val(outlet_in_use, &appliance_value); + ESP_LOGI(TAG, "Outlet-In-Use triggered [%d]", appliance_value.b); + } + } +} + +void homekit_main() +{ + /* Create the application thread */ + xTaskCreate(smart_outlet_thread_entry, SMART_OUTLET_TASK_NAME, SMART_OUTLET_TASK_STACKSIZE, + NULL, SMART_OUTLET_TASK_PRIORITY, NULL); +} diff --git a/lib/libesp32_div/ESP32-HomeKit/examples/HomeKit_IDF/wifi_info.h b/lib/libesp32_div/ESP32-HomeKit/examples/HomeKit_IDF/wifi_info.h new file mode 100644 index 000000000..39e2c5320 --- /dev/null +++ b/lib/libesp32_div/ESP32-HomeKit/examples/HomeKit_IDF/wifi_info.h @@ -0,0 +1,34 @@ +/* + * wifi_info.h + * + * Created on: 2020-05-15 + * Author: Mixiaoxiao (Wang Bin) + */ + +#ifndef WIFI_INFO_H_ +#define WIFI_INFO_H_ + +#if defined(ESP8266) +#include +#elif defined(ESP32) +#include +#endif + +const char *ssid = "your-ssid"; +const char *password = "your-password"; + +void wifi_connect() { + WiFi.persistent(false); + WiFi.mode(WIFI_STA); + WiFi.setAutoReconnect(true); + WiFi.begin(ssid, password); + Serial.println("WiFi connecting..."); + while (!WiFi.isConnected()) { + delay(100); + Serial.print("."); + } + Serial.print("\n"); + Serial.printf("WiFi connected, IP: %s\n", WiFi.localIP().toString().c_str()); +} + +#endif /* WIFI_INFO_H_ */ diff --git a/lib/libesp32_div/ESP32-HomeKit/src/_esp_hap_config.h b/lib/libesp32_div/ESP32-HomeKit/src/_esp_hap_config.h new file mode 100644 index 000000000..e848049b8 --- /dev/null +++ b/lib/libesp32_div/ESP32-HomeKit/src/_esp_hap_config.h @@ -0,0 +1,20 @@ +/* + * _esp_hap_config.h + * + * Created on: 2020-11-23 + * Author: Mixiaoxiao + */ + +#ifndef ESP_HAP_CONFIG_H_ +#define ESP_HAP_CONFIG_H_ + +#define HAP_SDK_VER "4.0" +#define MFI_VER HAP_SDK_VER + +#define CONFIG_HAP_HTTP_STACK_SIZE 12288 +#define CONFIG_HAP_HTTP_SERVER_PORT 5556 // 80 for normal webserver +#define CONFIG_HAP_HTTP_CONTROL_PORT 32859 +#define CONFIG_HAP_HTTP_MAX_OPEN_SOCKETS 6 +#define CONFIG_HAP_HTTP_MAX_URI_HANDLERS 16 + +#endif /* ESP_HAP_CONFIG_H_ */ diff --git a/lib/libesp32_div/ESP32-HomeKit/src/base36.h b/lib/libesp32_div/ESP32-HomeKit/src/base36.h new file mode 100644 index 000000000..332e38794 --- /dev/null +++ b/lib/libesp32_div/ESP32-HomeKit/src/base36.h @@ -0,0 +1,60 @@ +/* + * Base36 PostgreSQL input/output function for bigint + * + * Author: Dimitri Fontaine + * + * Taken from https://github.com/dimitri/base36/blob/master/base36.c + */ + +#include +#include + +#define BASE36_LENGTH 13 + +typedef long long int base36; + +static int base36_digits[36] = + {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', + 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', + 'U', 'V', 'W', 'X', 'Y', 'Z' + }; + +static base36 base36_powers[BASE36_LENGTH] = + { +1ULL, + 36ULL, + 1296ULL, + 46656ULL, + 1679616ULL, + 60466176ULL, + 2176782336ULL, + 78364164096ULL, + 2821109907456ULL, + 101559956668416ULL, + 3656158440062976ULL, + 131621703842267136ULL, + 4738381338321616896ULL + }; + +static inline +char *base36_to_str(base36 c) +{ + int i, d, p = 0; + base36 m = c; + bool discard = true; + char *str = calloc((BASE36_LENGTH + 1), sizeof(char)); + + for(i=BASE36_LENGTH-1; i>=0; i--) + { + d = m / base36_powers[i]; + m = m - base36_powers[i] * d; + + discard = discard && (d == 0 && i >0); + + if( !discard ) + str[p++] = base36_digits[d]; + } + + return str; +} diff --git a/lib/libesp32_div/ESP32-HomeKit/src/byte_convert.c b/lib/libesp32_div/ESP32-HomeKit/src/byte_convert.c new file mode 100644 index 000000000..57decd165 --- /dev/null +++ b/lib/libesp32_div/ESP32-HomeKit/src/byte_convert.c @@ -0,0 +1,173 @@ +// Copyright 2020 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#include +#include + +/* Functions to convert Little Endian byte stream to + * uint16, uint32 and uint64 + */ +uint16_t get_u16_le(const void *val_ptr) +{ + const uint8_t *p = (const uint8_t *)val_ptr; + uint16_t val; + + val = (uint16_t)p[0]; + val |= (uint16_t)p[1] << 8; + + return val; +} + +uint32_t get_u32_le(const void *val_ptr) +{ + const uint8_t *p = (const uint8_t *)val_ptr; + uint32_t val; + + val = (uint32_t)p[0]; + val |= (uint32_t)p[1] << 8; + val |= (uint32_t)p[2] << 16; + val |= (uint32_t)p[3] << 24; + + return val; +} + +uint64_t get_u64_le(const void *val_ptr) +{ + const uint8_t *p = (const uint8_t *)val_ptr; + uint64_t val; + + val = (uint64_t)p[0]; + val |= (uint64_t)p[1] << 8; + val |= (uint64_t)p[2] << 16; + val |= (uint64_t)p[3] << 24; + val |= (uint64_t)p[4] << 32; + val |= (uint64_t)p[5] << 40; + val |= (uint64_t)p[6] << 48; + val |= (uint64_t)p[7] << 56; + + return val; +} + +/* Functions to convert Big Endian byte stream to + * uint16, uint32 and uint64 + */ +uint16_t get_u16_be(const void *val_ptr) +{ + const uint8_t *p = (const uint8_t *)val_ptr; + uint16_t val; + + val = (uint16_t)p[0] << 8; + val |= (uint16_t)p[1]; + + return val; +} + +uint32_t get_u32_be(const void *val_ptr) +{ + const uint8_t *p = (const uint8_t *)val_ptr; + uint32_t val; + + val = (uint32_t)p[0] << 24; + val |= (uint32_t)p[1] << 16; + val |= (uint32_t)p[2] << 8; + val |= (uint32_t)p[3]; + + return val; +} + +uint64_t get_u64_be(const void *val_ptr) +{ + const uint8_t *p = (const uint8_t *)val_ptr; + uint64_t val; + + val = (uint64_t)p[0] << 56; + val |= (uint64_t)p[1] << 48; + val |= (uint64_t)p[2] << 40; + val |= (uint64_t)p[3] << 32; + val |= (uint64_t)p[4] << 24; + val |= (uint64_t)p[5] << 16; + val |= (uint64_t)p[6] << 8; + val |= (uint64_t)p[7]; + + return val; +} + +/* Functions to convert uint16, uint32 and uint64 + * to Little Endian + */ +void put_u16_le(void *val_ptr, const uint16_t val) +{ + uint8_t *p = (uint8_t *)val_ptr; + + p[0] = (uint8_t)val & 0xff; + p[1] = (uint8_t)(val >> 8) & 0xff; +} + +void put_u32_le(void *val_ptr, const uint32_t val) +{ + uint8_t *p = (uint8_t *)val_ptr; + + p[0] = (uint8_t)val & 0xff; + p[1] = (uint8_t)(val >> 8) & 0xff; + p[2] = (uint8_t)(val >> 16) & 0xff; + p[3] = (uint8_t)(val >> 24) & 0xff; +} + +void put_u64_le(void *val_ptr, const uint64_t val) +{ + uint8_t *p = (uint8_t *)val_ptr; + + p[0] = (uint8_t)val & 0xff; + p[1] = (uint8_t)(val >> 8) & 0xff; + p[2] = (uint8_t)(val >> 16) & 0xff; + p[3] = (uint8_t)(val >> 24) & 0xff; + p[4] = (uint8_t)(val >> 32) & 0xff; + p[5] = (uint8_t)(val >> 40) & 0xff; + p[6] = (uint8_t)(val >> 48) & 0xff; + p[7] = (uint8_t)(val >> 56) & 0xff; +} + +/* Functions to convert uint16, uint32 and uint64 + * to Big Endian + */ +void put_u16_be(void *val_ptr, const uint16_t val) +{ + uint8_t *p = (uint8_t *)val_ptr; + + p[0] = (uint8_t)(val >> 8) & 0xff; + p[1] = (uint8_t)val & 0xff; +} + +void put_u32_be(void *val_ptr, const uint32_t val) +{ + uint8_t *p = (uint8_t *)val_ptr; + + p[0] = (uint8_t)((val >> 24) & 0xff); + p[1] = (uint8_t)((val >> 16) & 0xff); + p[2] = (uint8_t)((val >> 8) & 0xff); + p[3] = (uint8_t)(val & 0xff); +} + +void put_u64_be(void *val_ptr, const uint64_t val) +{ + uint8_t *p = (uint8_t *)val_ptr; + + p[0] = (uint8_t)(val >> 56) & 0xff; + p[1] = (uint8_t)(val >> 48) & 0xff; + p[2] = (uint8_t)(val >> 40) & 0xff; + p[3] = (uint8_t)(val >> 32) & 0xff; + p[4] = (uint8_t)(val >> 24) & 0xff; + p[5] = (uint8_t)(val >> 16) & 0xff; + p[6] = (uint8_t)(val >> 8) & 0xff; + p[7] = (uint8_t)val & 0xff; +} diff --git a/lib/libesp32_div/ESP32-HomeKit/src/byte_convert.h b/lib/libesp32_div/ESP32-HomeKit/src/byte_convert.h new file mode 100644 index 000000000..0c91ed8d2 --- /dev/null +++ b/lib/libesp32_div/ESP32-HomeKit/src/byte_convert.h @@ -0,0 +1,139 @@ +// Copyright 2020 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +/** + * \file byte_convert.h + * \brief Conversion between integers and byte streams + * + * This module offers APIs to convert 16bit, 32bit and 64 bit unsigned integers + * into Little/Big Endian byte streams + */ +#ifndef _BYTE_CONVERT_H +#define _BYTE_CONVERT_H + +#include + +/** Little Endian to uint16 Conversion + * Get a uint16 integer from a little Endian byte stream + * + * \param[in] val_ptr Pointer to the 2 byte stream + * + * \return The converted uint16 integer + */ +uint16_t get_u16_le(const void *val_ptr); + +/** Little Endian to uint32 Conversion + * Get a uint32 integer from a little Endian byte stream + * + * \param[in] val_ptr Pointer to the 4 byte stream + * + * \return The converted uint32 integer + */ +uint32_t get_u32_le(const void *val_ptr); + +/** Little Endian to uint64 Conversion + * Get a uint64 integer from a little Endian byte stream + * + * \param[in] val_ptr Pointer to the 8 byte stream + * + * \return The converted uint32 integer + */ +uint64_t get_u64_le(const void *val_ptr); + +/** Big Endian to uint16 Conversion + * Get a uint16 integer from a Big Endian byte stream + * + * \param[in] val_ptr Pointer to the 2 byte stream + * + * \return The converted uint16 integer + */ +uint16_t get_u16_be(const void *val_ptr); + +/** Big Endian to uint32 Conversion + * Get a uint32 integer from a Big Endian byte stream + * + * \param[in] val_ptr Pointer to the 4 byte stream + * + * \return The converted uint32 integer + */ +uint32_t get_u32_be(const void *val_ptr); + +/** Big Endian to uint64 Conversion + * Get a uint64 integer from a Big Endian byte stream + * + * \param[in] val_ptr Pointer to the 8 byte stream + * + * \return The converted uint16 integer + */ +uint64_t get_u64_be(const void *val_ptr); + +/** Uint16 to Little Endian Conversion + * + * Put a uint16 integer into a Little Endian byte stream + * + * \param[out] Pointer to a 2 byte stream that will be filled with the value + * + * \param[in] The uint16 integer + */ +void put_u16_le(void *val_ptr, const uint16_t val); + +/** Uint32 to Little Endian Conversion + * + * Put a uint32 integer into a Little Endian byte stream + * + * \param[out] Pointer to a 4 byte stream that will be filled with the value + * + * \param[in] The uint32 integer + */ +void put_u32_le(void *val_ptr, const uint32_t val); + +/** Uint64 to Little Endian Conversion + * + * Put a uint64 integer into a Little Endian byte stream + * + * \param[out] Pointer to a 8 byte stream that will be filled with the value + * + * \param[in] The uint64 integer + */ +void put_u64_le(void *val_ptr, const uint64_t val); + +/** Uint16 to Big Endian Conversion + * + * Put a uint16 integer into a Big Endian byte stream + * + * \param[out] Pointer to a 2 byte stream that will be filled with the value + * + * \param[in] The uint16 integer + */ +void put_u16_be(void *val_ptr, const uint16_t val); + +/** Uint32 to Big Endian Conversion + * + * Put a uint32 integer into a Big Endian byte stream + * + * \param[out] Pointer to a 4 byte stream that will be filled with the value + * + * \param[in] The uint32 integer + */ +void put_u32_be(void *val_ptr, const uint32_t val); + +/** Uint64 to Big Endian Conversion + * + * Put a uint64 integer into a Big Endian byte stream + * + * \param[out] Pointer to a 8 byte stream that will be filled with the value + * + * \param[in] The uint64 integer + */ +void put_u64_be(void *val_ptr, const uint64_t val); +#endif /* _BYTE_CONVERT_H */ diff --git a/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_acc.c b/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_acc.c new file mode 100644 index 000000000..b42314afc --- /dev/null +++ b/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_acc.c @@ -0,0 +1,491 @@ +/* + * ESPRESSIF MIT License + * + * Copyright (c) 2020 + * + * Permission is hereby granted for use on ESPRESSIF SYSTEMS products only, in which case, + * it is 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 +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +/* Primary Accessory Pointer */ +static __hap_acc_t *primary_acc; + +/*****************************************************************************************************/ + +hap_acc_t *hap_get_first_acc() +{ + return (hap_acc_t *)primary_acc; +} + +hap_acc_t *hap_acc_get_next(hap_acc_t *ha) +{ + if (!ha) + return NULL; + + __hap_acc_t *_ha = (__hap_acc_t *)ha; + return (hap_acc_t *)_ha->next; +} +/* Service write callback to handle "Identify" */ +static int hap_acc_info_write(hap_write_data_t write_data[], int count, + void *serv_priv, void *write_priv) +{ + int i; + __hap_char_t *_hc; + for (i = 0; i < count; i++) { + _hc = (__hap_char_t *)write_data[i].hc; + if (!strcmp(_hc->type_uuid, HAP_CHAR_UUID_IDENTIFY)) { + __hap_acc_t *_ha = (__hap_acc_t *)serv_priv; + if (_ha) { + _ha->identify_routine((hap_acc_t *)_ha); + *(write_data->status) = HAP_STATUS_SUCCESS; + continue; + } + } + *(write_data->status) = HAP_STATUS_VAL_INVALID; + } + return HAP_SUCCESS; +} + +/** + * @brief HAP create an accessory + */ +hap_acc_t *hap_acc_create(hap_acc_cfg_t *acc_cfg) +{ + static bool first = true; + int ret = 0; + __hap_acc_t *_ha = hap_platform_memory_calloc(1, sizeof(__hap_acc_t)); + if (!_ha) { + return NULL; + } + + _ha->identify_routine = acc_cfg->identify_routine; + _ha->next_iid = 1; + + /* Add the Accessory Information Service internally */ + hap_serv_t *hs = hap_serv_create("3E"); + if (!hs) { + goto acc_create_fail; + } + ret = hap_serv_add_char(hs, hap_char_bool_create(HAP_CHAR_UUID_IDENTIFY, HAP_CHAR_PERM_PW, false)); + ret |= hap_serv_add_char(hs, hap_char_string_create(HAP_CHAR_UUID_MANUFACTURER, HAP_CHAR_PERM_PR, acc_cfg->manufacturer)); + ret |= hap_serv_add_char(hs, hap_char_string_create(HAP_CHAR_UUID_MODEL, HAP_CHAR_PERM_PR, acc_cfg->model)); + ret |= hap_serv_add_char(hs, hap_char_string_create(HAP_CHAR_UUID_NAME, HAP_CHAR_PERM_PR, acc_cfg->name)); + ret |= hap_serv_add_char(hs, hap_char_string_create(HAP_CHAR_UUID_SERIAL_NUMBER, HAP_CHAR_PERM_PR, acc_cfg->serial_num)); + ret |= hap_serv_add_char(hs, hap_char_string_create(HAP_CHAR_UUID_FIRMWARE_REVISION, HAP_CHAR_PERM_PR, acc_cfg->fw_rev)); + if (acc_cfg->hw_rev) { + ret |= hap_serv_add_char(hs, hap_char_string_create(HAP_CHAR_UUID_HARDWARE_REVISION, HAP_CHAR_PERM_PR, acc_cfg->hw_rev)); + } + + if (ret) { + goto acc_create_fail; + } + + hap_serv_set_write_cb(hs, hap_acc_info_write); + hap_serv_set_priv(hs,(void *)_ha); + hap_acc_add_serv((hap_acc_t *)_ha, hs); + + if (first) { + /* Add the Procol Information Service Internally */ + hs = hap_serv_create("A2"); + if (!hs) { + goto acc_create_fail; + } + ret = hap_serv_add_char(hs, hap_char_string_create("37", HAP_CHAR_PERM_PR, "1.1.0")); + + if (ret) { + goto acc_create_fail; + } + hap_acc_add_serv((hap_acc_t *)_ha, hs); + hap_priv.cid = acc_cfg->cid; + first = false; + } + + return (hap_acc_t *)_ha; + +acc_create_fail: + hap_acc_delete((hap_acc_t *)_ha); + return NULL; +} + +int hap_acc_add_accessory_flags(hap_acc_t *ha, uint32_t flags) +{ + if (!ha) { + return HAP_FAIL; + } + hap_serv_t *hs = hap_acc_get_serv_by_uuid(ha, HAP_SERV_UUID_ACCESSORY_INFORMATION); + if (!hs) { + return HAP_FAIL; + } + return hap_serv_add_char(hs, hap_char_accessory_flags_create(flags)); + +} + +int hap_acc_update_accessory_flags(hap_acc_t *ha, uint32_t flags) +{ + if (!ha) { + return HAP_FAIL; + } + hap_serv_t *hs = hap_acc_get_serv_by_uuid(ha, HAP_SERV_UUID_ACCESSORY_INFORMATION); + if (!hs) { + return HAP_FAIL; + } + hap_char_t *hc = hap_serv_get_char_by_uuid(hs, HAP_CHAR_UUID_ACCESSORY_FLAGS); + if (!hc) { + return HAP_FAIL; + } + hap_val_t val = { + .u = flags, + }; + return hap_char_update_val(hc, &val); +} + +int hap_acc_add_product_data(hap_acc_t *ha, uint8_t *product_data, size_t data_size) +{ + if (!ha) { + return HAP_FAIL; + } + hap_serv_t *hs = hap_acc_get_serv_by_uuid(ha, HAP_SERV_UUID_ACCESSORY_INFORMATION); + if (!hs) { + return HAP_FAIL; + } + if (data_size != 8) { + ESP_MFI_DEBUG(ESP_MFI_DEBUG_ERR, "Product data size is not 8"); + } + uint8_t *buf = calloc(1, data_size); + if (!buf) { + return HAP_FAIL; + } + memcpy(buf, product_data, data_size); + hap_data_val_t data_val = { + .buf = buf, + .buflen = data_size + }; + return hap_serv_add_char(hs, hap_char_product_data_create(&data_val)); +} + +const hap_val_t *hap_get_product_data() +{ + hap_char_t *acc_info = hap_acc_get_serv_by_uuid(hap_get_first_acc(), HAP_SERV_UUID_ACCESSORY_INFORMATION); + if (acc_info) { + hap_char_t *product_data = hap_serv_get_char_by_uuid(acc_info, HAP_CHAR_UUID_PRODUCT_DATA); + if (product_data) { + return hap_char_get_val(product_data); + } + } + return NULL; +} +/** + * @brief check if accessory's AID matches the target AID + */ +bool hap_check_aid(__hap_acc_t *accessory, int32_t aid) +{ + return accessory->aid == aid ? true : false; +} + +hap_serv_t *hap_acc_get_first_serv(hap_acc_t *ha) +{ + return ((__hap_acc_t *)ha)->servs; +} +/** + * @brief get target service by it's type description string + */ +hap_serv_t *hap_acc_get_serv_by_iid(hap_acc_t *ha, int32_t iid) +{ + if (!ha) + return NULL; + + hap_serv_t *hs; + for (hs = hap_acc_get_first_serv(ha); hs; hs = hap_serv_get_next(hs)) { + if (((__hap_serv_t *)hs)->iid == iid) + return hs; + } + return NULL; +} + +hap_serv_t *hap_acc_get_serv_by_uuid(hap_acc_t *ha, const char *uuid) +{ + if (!ha) + return NULL; + + hap_serv_t *hs; + for (hs = hap_acc_get_first_serv(ha); hs; hs = hap_serv_get_next(hs)) { + if (!strcmp(((__hap_serv_t *)hs)->type_uuid, uuid)) + return hs; + } + return NULL; +} + +/** + * @brief get target characteristics by it's IID + */ +hap_char_t *hap_acc_get_char_by_iid(hap_acc_t *ha, int32_t iid) +{ + if (!ha) + return NULL; + hap_serv_t *hs; + hap_char_t *hc; + for (hs = hap_acc_get_first_serv(ha); hs; hs = hap_serv_get_next(hs)) { + hc = hap_serv_get_char_by_iid(hs, iid); + if (hc) + return hc; + } + return NULL; +} + +int hap_acc_get_info(hap_acc_cfg_t *acc_cfg) +{ + ESP_MFI_ASSERT(acc_cfg); + hap_acc_t *ha = hap_get_first_acc(); + + ESP_MFI_ASSERT(ha); + + hap_serv_t *hs = hap_acc_get_serv_by_uuid(ha, HAP_SERV_UUID_ACCESSORY_INFORMATION); + + hap_char_t *hc = hap_serv_get_char_by_uuid(hs, HAP_CHAR_UUID_NAME); + acc_cfg->name = ((__hap_char_t *)hc)->val.s; + + hc = hap_serv_get_char_by_uuid(hs, HAP_CHAR_UUID_MODEL); + acc_cfg->model = ((__hap_char_t *)hc)->val.s; + + hc = hap_serv_get_char_by_uuid(hs, HAP_CHAR_UUID_MANUFACTURER); + acc_cfg->manufacturer = ((__hap_char_t *)hc)->val.s; + + hc = hap_serv_get_char_by_uuid(hs, HAP_CHAR_UUID_SERIAL_NUMBER); + acc_cfg->serial_num = ((__hap_char_t *)hc)->val.s; + + hc = hap_serv_get_char_by_uuid(hs, HAP_CHAR_UUID_FIRMWARE_REVISION); + acc_cfg->fw_rev = ((__hap_char_t *)hc)->val.s; + + hc = hap_serv_get_char_by_uuid(hs, HAP_CHAR_UUID_HARDWARE_REVISION); + if (hc) { + acc_cfg->hw_rev = ((__hap_char_t *)hc)->val.s; + } else { + acc_cfg->hw_rev = NULL; + } + + hs = hap_acc_get_serv_by_uuid(ha, HAP_SERV_UUID_PROTOCOL_INFORMATION); + + hc = hap_serv_get_char_by_uuid(hs, HAP_CHAR_UUID_VERSION); + acc_cfg->pv = ((__hap_char_t *)hc)->val.s; + + return 0; +} + +/** + * @brief add a characteristics to a service + */ +int hap_acc_add_serv(hap_acc_t *ha, hap_serv_t *hs) +{ + ESP_MFI_ASSERT(ha); + ESP_MFI_ASSERT(hs); + __hap_acc_t *_ha = (__hap_acc_t *)ha; + __hap_serv_t *_hs = (__hap_serv_t *)hs; + + if (_hs->parent) { + ESP_MFI_DEBUG(ESP_MFI_DEBUG_ERR, "Service already added"); + return HAP_FAIL; + } + + /* If the accessory has no services, add this as the first */ + if (!_ha->servs) { + _ha->servs = hs; + } else { + /* Else loop through the services to get to the last one, + * and add this at the end + */ + __hap_serv_t *temp = (__hap_serv_t *)_ha->servs; + while (temp->next_serv) + temp = (__hap_serv_t *)temp->next_serv; + temp->next_serv = hs; + } + _hs->iid = _ha->next_iid++; + __hap_char_t *_hc = (__hap_char_t *)_hs->chars; + while(_hc) { + _hc->iid = _ha->next_iid++; + _hc = (__hap_char_t *)_hc->next_char; + } + _hs->parent = ha; + return 0; +} + +static void hap_add_acc_to_list(__hap_acc_t *primary, __hap_acc_t *new) +{ + __hap_acc_t *cur = primary; + while (cur->next) { + cur = cur->next; + } + cur->next = new; +} + +static void hap_remove_acc_from_list(__hap_acc_t *primary, __hap_acc_t *old) +{ + __hap_acc_t *cur = primary; + while (cur->next != old) { + cur = cur->next; + } + cur->next = cur->next->next; +} + +#define HAP_BRIDGE_KEYSTORE "hap_bridge" + +int hap_get_unique_aid(const char *id) +{ + if (!id) { + return -1; + } + int aid = 0; + size_t aid_size = sizeof(aid); + if (hap_keystore_get(HAP_KEYSTORE_NAMESPACE_HAPMAIN, id, (uint8_t *)&aid, &aid_size) != HAP_SUCCESS) { + aid = hap_get_next_aid(); + ESP_MFI_DEBUG(ESP_MFI_DEBUG_INFO, "Assigning aid = %d for Bridged accessory %s", aid, id); + hap_keystore_set(HAP_KEYSTORE_NAMESPACE_HAPMAIN, id, (uint8_t *)&aid, sizeof(aid)); + } else { + ESP_MFI_DEBUG(ESP_MFI_DEBUG_INFO, "Using aid = %d for Bridged accessory %s", aid, id); + } + return aid; +} + +/** + * @brief HAP add accessory to HAP kernel + */ +void hap_add_accessory(hap_acc_t *ha) +{ + if (!ha) { + return; + } + if (primary_acc) { + ESP_MFI_DEBUG(ESP_MFI_DEBUG_ERR, "Primary Accessory already added. Use hap_add_bridged_accessory() instead"); + return; + } + __hap_acc_t *_ha = (__hap_acc_t *)ha; + _ha->aid = 1; + primary_acc = _ha; + if (hap_priv.cfg.unique_param >= UNIQUE_NAME) { + char name[74]; + uint8_t eth_mac[6]; + esp_wifi_get_mac(WIFI_IF_STA, eth_mac); + hap_serv_t *hs = hap_acc_get_serv_by_uuid(ha, HAP_SERV_UUID_ACCESSORY_INFORMATION); + hap_char_t *hc = hap_serv_get_char_by_uuid(hs, HAP_CHAR_UUID_NAME); + snprintf(name, sizeof(name), "%s-%02X%02X%02X", ((__hap_char_t *)hc)->val.s, + eth_mac[3], eth_mac[4], eth_mac[5]); + hap_platform_memory_free(((__hap_char_t *)hc)->val.s); + ((__hap_char_t *)hc)->val.s = strdup(name); + } + hap_acc_get_info(&hap_priv.primary_acc); +} + +void hap_add_bridged_accessory(hap_acc_t *ha, int aid) +{ + if (!ha) { + return; + } + __hap_acc_t *_ha = (__hap_acc_t *)ha; + if (aid) { + _ha->aid = aid; + } else { + _ha->aid = hap_get_next_aid(); + } + + hap_add_acc_to_list(primary_acc, _ha); + if (!hap_priv.cfg.disable_config_num_update) { + hap_update_config_number(); + } +} + +void hap_remove_bridged_accessory(hap_acc_t *ha) +{ + if ((__hap_acc_t *)ha == primary_acc) { + ESP_MFI_DEBUG(ESP_MFI_DEBUG_ERR, "Cannot remove primary accessory"); + } else { + if (ha) { + hap_remove_acc_from_list(primary_acc, (__hap_acc_t *)ha); + if (!hap_priv.cfg.disable_config_num_update) { + hap_update_config_number(); + } + } + + } +} +/** + * @brief HAP delete target accessory + */ +void hap_acc_delete(hap_acc_t *ha) +{ + /* Returning success even if pointer is NULL, because it means + * that the accessory is absent and as good as deleted + */ + if (!ha) + return; + __hap_acc_t *_ha = (__hap_acc_t *)ha; + __hap_serv_t *_hs = (__hap_serv_t *)_ha->servs; + while (_hs) { + _ha->servs = _hs->next_serv; + hap_serv_delete((hap_serv_t *)_hs); + _hs = (__hap_serv_t *)_ha->servs; + } + hap_platform_memory_free(_ha); +} + +/** + * @brief HAP get target accessory AID + */ +uint32_t hap_acc_get_aid(hap_acc_t *ha) +{ + ESP_MFI_ASSERT(ha); + __hap_acc_t *_ha = (__hap_acc_t *)ha; + + return _ha->aid; +} + +/** + * @brief delete all accessories + */ +void hap_delete_all_accessories(void) +{ + __hap_acc_t *next, *ha = primary_acc; + while (ha) { + next = ha->next; + hap_acc_delete((hap_acc_t *)ha); + ha = next; + } +} +/** + * @brief get target accessory by AID + */ +hap_acc_t *hap_acc_get_by_aid(int32_t aid) +{ + hap_acc_t *ha; + for (ha = hap_get_first_acc(); ha; ha = hap_acc_get_next(ha)) { + if (((__hap_acc_t *)ha)->aid == aid) { + return ha; + } + } + return NULL; +} diff --git a/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_acc.h b/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_acc.h new file mode 100644 index 000000000..2783f9c3c --- /dev/null +++ b/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_acc.h @@ -0,0 +1,51 @@ +/* + * ESPRESSIF MIT License + * + * Copyright (c) 2020 + * + * Permission is hereby granted for use on ESPRESSIF SYSTEMS products only, in which case, + * it is 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. + * + */ + +#ifndef _HAP_ACC_H_ +#define _HAP_ACC_H_ + +#include +#include + +#ifdef __cplusplus +extern "C"{ +#endif + +typedef struct esp_mfi_accessory { + struct esp_mfi_accessory *next; + uint32_t aid; /* accessory AID */ + hap_serv_t *servs; /* service list */ + bool power_off; + uint32_t next_iid; + hap_identify_routine_t identify_routine; +} __hap_acc_t; +hap_char_t *hap_acc_get_char_by_iid(hap_acc_t *ha, int32_t iid); +hap_acc_t *hap_acc_get_by_aid(int32_t aid); +int hap_acc_get_info(hap_acc_cfg_t *acc_cfg); +const hap_val_t *hap_get_product_data(); +#ifdef __cplusplus +} +#endif + +#endif /* _HAP_ACC_H_ */ diff --git a/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_bct.c b/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_bct.c new file mode 100644 index 000000000..ff9083a59 --- /dev/null +++ b/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_bct.c @@ -0,0 +1,71 @@ +/* + * ESPRESSIF MIT License + * + * Copyright (c) 2020 + * + * Permission is hereby granted for use on ESPRESSIF SYSTEMS products only, in which case, + * it is 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 +#include +#include +#include +#include +#include +#include +#include + +static char *new_name; + +void hap_bct_change_name(const char *name) +{ + if (new_name) { + hap_platform_memory_free(new_name); + } + new_name = strdup(name); + hap_send_event(HAP_INTERNAL_EVENT_BCT_CHANGE_NAME); +} + +void hap_bct_hot_plug() +{ + hap_send_event(HAP_INTERNAL_EVENT_BCT_HOT_PLUG); +} + +void hap_handle_bct_change_name() +{ + if (!new_name) { + ESP_MFI_DEBUG(ESP_MFI_DEBUG_ERR, "No BCT name specified"); + return; + } else { + ESP_MFI_DEBUG(ESP_MFI_DEBUG_INFO, "Changing BCT Name to %s", new_name); + } + if (hap_mdns_serv_name_change(&hap_priv.hap_mdns_handle, new_name) != HAP_SUCCESS) { + ESP_MFI_DEBUG(ESP_MFI_DEBUG_ERR, "Failed to change BCT name"); + } + hap_platform_memory_free(new_name); + new_name = NULL; +} + +void hap_handle_hot_plug() +{ + esp_wifi_stop(); + vTaskDelay((10 * 1000) / portTICK_PERIOD_MS); /* Wait for 10 seconds */ + esp_wifi_start(); + esp_wifi_connect(); +} diff --git a/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_bct_priv.h b/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_bct_priv.h new file mode 100644 index 000000000..70df56ce9 --- /dev/null +++ b/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_bct_priv.h @@ -0,0 +1,28 @@ +/* + * ESPRESSIF MIT License + * + * Copyright (c) 2020 + * + * Permission is hereby granted for use on ESPRESSIF SYSTEMS products only, in which case, + * it is 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. + * + */ +#ifndef _HAP_BCT_PRIV_H_ +#define _HAP_BCT_PRIV_H_ +void hap_handle_bct_change_name(); +void hap_handle_hot_plug(); +#endif /* _HAP_BCT_PRIV_H_ */ diff --git a/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_char.c b/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_char.c new file mode 100644 index 000000000..9b712e32e --- /dev/null +++ b/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_char.c @@ -0,0 +1,601 @@ +/* + * ESPRESSIF MIT License + * + * Copyright (c) 2020 + * + * Permission is hereby granted for use on ESPRESSIF SYSTEMS products only, in which case, + * it is 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 +#include +#include +#include "esp_mfi_debug.h" + +#include +#include +#include +#include +#include + +static QueueHandle_t hap_event_queue; + +/** + * @brief get characteristics's value + */ +hap_val_t *esp_mfi_characteristics_get_value(__hap_char_t *_hc) +{ + return &_hc->val; +} + +/** + * @brief check if characteristics has the specific permission + */ +bool hap_char_has_permission(__hap_char_t *_hc, uint16_t permission) +{ + return _hc->permission & permission ? true : false; +} + +/** + * @brief compute the mod of a and b: a % b + */ +static double esp_mfi_fmod(double a, double b) +{ + if (a < 1e-06 || b < 1e-06) + return 0; + + while (!((long long)a) || !((long long)b)) { + a *= 10.0; + b *= 10.0; + } + + return fmod(a, b); +} + +int hap_event_queue_init() +{ + hap_event_queue = xQueueCreate( hap_priv.cfg.max_event_notif_chars, + sizeof(hap_char_t *) ); + if (hap_event_queue) { + return HAP_SUCCESS; + } else { + return HAP_FAIL; + } +} + +hap_char_t * hap_get_pending_notif_char() +{ + hap_char_t *hc; + if (xQueueReceive(hap_event_queue, &hc, 0) != pdTRUE) { + return NULL; + } + return hc; +} + +static int hap_queue_event(hap_char_t *hc) +{ + int ret; + if (!hap_event_queue) { + return HAP_FAIL; + } + if (xPortInIsrContext() == pdTRUE) { + ret = xQueueSendFromISR(hap_event_queue, &hc, NULL); + } else { + ret = xQueueSend(hap_event_queue, &hc, 0); + } + if (ret == pdTRUE) { + hap_send_event(HAP_INTERNAL_EVENT_TRIGGER_NOTIF); + return HAP_SUCCESS; + } + return HAP_FAIL; +} + + +/** + * @brief check if characteristics value is at the range + */ +int hap_char_check_val_constraints(__hap_char_t *_hc, hap_val_t *val) +{ + if (!_hc->constraint_flags) + return HAP_SUCCESS; + + if (_hc->format == HAP_CHAR_FORMAT_INT) { + int value = val->i; + int remainder; + + if (value > _hc->max.i + || value < _hc->min.i) + return HAP_FAIL; + + if (!_hc->step.i) + return HAP_SUCCESS; + + remainder = (value - _hc->min.i) % _hc->step.i; + if (remainder) + return HAP_FAIL; + } else if (_hc->format == HAP_CHAR_FORMAT_FLOAT) { + float value = val->f; + + if (value > _hc->max.f + || value < _hc->min.f) + return HAP_FAIL; +# if 0 + /* Check for step value for floats has a high chance of failure, + * because of precision issues. Hence, better to skip it. + */ + double remainder; + if (_hc->step.f == 0.0) + return HAP_SUCCESS; + + remainder = esp_mfi_fmod(value - _hc->min.f, _hc->step.f); + if (remainder != 0.0) + return HAP_FAIL; +#endif + } else if (_hc->format == HAP_CHAR_FORMAT_UINT8 + || _hc->format == HAP_CHAR_FORMAT_UINT16 + || _hc->format == HAP_CHAR_FORMAT_UINT32) { + uint32_t value = val->u; + uint32_t remainder; + + + if (value > _hc->max.u + || value < _hc->min.u) + return HAP_FAIL; + + if (!_hc->step.u) + return HAP_SUCCESS; + + remainder = (value - _hc->min.u) % _hc->step.u; + if (remainder) + return HAP_FAIL; + } else if (_hc->format == HAP_CHAR_FORMAT_UINT64) { + /* TODO: Add support. Currently, there is no particular 64-bit characteristic */ + } + + return HAP_SUCCESS; +} + +/** + * @brief user update characteristics value, preparing for notification + */ +int hap_char_update_val(hap_char_t *hc, hap_val_t *val) +{ + if (!hc || !val) { + return HAP_FAIL; + } + __hap_char_t *_hc = (__hap_char_t *)hc; + _hc->update_called = true; + if (hap_char_check_val_constraints(_hc, val) != HAP_SUCCESS) + return HAP_FAIL; + /* Boolean to track if the value has changed. + * This will be later used to decide if an event notification + * is required or not. If the new and old values are same, + * there is no need of a notification + */ + bool value_changed = false; + + switch (_hc->format) { + case HAP_CHAR_FORMAT_BOOL: + if (_hc->val.b != val->b) { + _hc->val.b = val->b; + value_changed = true; + } + break; + case HAP_CHAR_FORMAT_INT: + case HAP_CHAR_FORMAT_UINT8: + case HAP_CHAR_FORMAT_UINT16: + case HAP_CHAR_FORMAT_UINT32: + if (_hc->val.i != val->i) { + _hc->val.i = val->i; + value_changed = true; + } + break; + case HAP_CHAR_FORMAT_FLOAT: + if (_hc->val.f != val->f) { + _hc->val.f = val->f; + value_changed = true; + } + break; + case HAP_CHAR_FORMAT_STRING: + /* Not checking all combinations to find if value has changed, + * since generally we do not expect dynamic string values + * + * Eg. + * Both (old and new) values being NULL + * Old value NULL, New non-NULL + * Old value non-NULL, new NULL + */ + if (_hc->val.s && val->s && !strcmp(_hc->val.s, val->s)) + value_changed = false; + else + value_changed = true; + + if (_hc->val.s) { + hap_platform_memory_free(_hc->val.s); + _hc->val.s = NULL; + } + + if (val->s) { + _hc->val.s = strdup(val->s); + if (!_hc->val.s) + return HAP_FAIL; + } + break; + case HAP_CHAR_FORMAT_DATA: + case HAP_CHAR_FORMAT_TLV8: { + _hc->val.d.buf = val->d.buf; + _hc->val.d.buflen = val->d.buflen; + value_changed = true; + } + break; + default: + break; + } + if (value_changed || (_hc->permission & HAP_CHAR_PERM_SPECIAL_READ)) { + ESP_MFI_DEBUG_INTR(ESP_MFI_DEBUG_INFO, "Value Changed"); + hap_queue_event(hc); + } else { + /* If there is no value change, reset the owner flag here itself, as no notification + * is being sent anyways. In the absence of this, if there is a GET /characteristics + * followed by some value change from hardware, the owner_ctrl stays assigned to a + * stale value, and so the controller misses a notification. + */ + _hc->owner_ctrl = 0; + } + return HAP_SUCCESS; +} + +const hap_val_t *hap_char_get_val(hap_char_t *hc) +{ + if (!hc) + return NULL; + return &((__hap_char_t *)hc)->val; +} + +/** + * @brief Get the minimum value of characteristic + */ +const hap_val_t *hap_char_get_min_val(hap_char_t *hc) +{ + if (hc) { + if(((__hap_char_t *)hc)->constraint_flags & HAP_CHAR_MIN_FLAG) { + return &((__hap_char_t *)hc)->min; + } + } + return NULL; +} + +/** + * @brief Get the maximum value of characteristic + */ +const hap_val_t *hap_char_get_max_val(hap_char_t *hc) +{ + if (hc) { + if(((__hap_char_t *)hc)->constraint_flags & HAP_CHAR_MAX_FLAG || ((__hap_char_t *)hc)->constraint_flags & HAP_CHAR_MAXLEN_FLAG) { + return &((__hap_char_t *)hc)->max; + } + } + return NULL; +} + +/** + * @brief Get the step value of characteristic + */ +const hap_val_t *hap_char_get_step_val(hap_char_t *hc) +{ + if (hc) { + if (((__hap_char_t *)hc)->constraint_flags & HAP_CHAR_STEP_FLAG) { + return &((__hap_char_t *)hc)->step; + } + } + return NULL; +} + +/** + * @brief HAP create a characteristics + */ +static hap_char_t *hap_char_create(char *type_uuid, uint32_t permission, hap_char_format_t format, hap_val_t val) +{ + __hap_char_t *new_ch; + + ESP_MFI_ASSERT(type_uuid); + + if (HAP_CHAR_FORMAT_STRING == format && val.s) { + if (strlen(val.s) > HAP_CHAR_STRING_MAX_LEN) + return NULL; + } + + new_ch = hap_platform_memory_calloc(1, sizeof(__hap_char_t)); + if (!new_ch) { + return NULL; + } + + new_ch->val = val; + new_ch->type_uuid = type_uuid; + new_ch->format = format; + new_ch->permission = permission; + + return (hap_char_t *) new_ch; +} + +hap_char_t *hap_char_bool_create(char *type_uuid, uint16_t perms, bool b) +{ + hap_val_t val = {.b = b}; + return hap_char_create(type_uuid, perms, HAP_CHAR_FORMAT_BOOL, val); +} +hap_char_t *hap_char_uint8_create(char *type_uuid, uint16_t perms, uint8_t u8) +{ + hap_val_t val = {.u = u8}; + return hap_char_create(type_uuid, perms, HAP_CHAR_FORMAT_UINT8, val); +} +hap_char_t *hap_char_uint16_create(char *type_uuid, uint16_t perms, uint16_t u16) +{ + hap_val_t val = {.u = u16}; + return hap_char_create(type_uuid, perms, HAP_CHAR_FORMAT_UINT16, val); +} +hap_char_t *hap_char_uint32_create(char *type_uuid, uint16_t perms, uint32_t u32) +{ + hap_val_t val = {.u = u32}; + return hap_char_create(type_uuid, perms, HAP_CHAR_FORMAT_UINT32, val); +} +hap_char_t *hap_char_uint64_create(char *type_uuid, uint16_t perms, uint64_t u64) +{ + hap_val_t val = {.i64 = u64}; + return hap_char_create(type_uuid, perms, HAP_CHAR_FORMAT_UINT64, val); +} +hap_char_t *hap_char_int_create(char *type_uuid, uint16_t perms, int i32) +{ + hap_val_t val = {.i = i32}; + return hap_char_create(type_uuid, perms, HAP_CHAR_FORMAT_INT, val); +} +hap_char_t *hap_char_float_create(char *type_uuid, uint16_t perms, float f) +{ + hap_val_t val = {.f = f}; + return hap_char_create(type_uuid, perms, HAP_CHAR_FORMAT_FLOAT, val); +} +hap_char_t *hap_char_string_create(char *type_uuid, uint16_t perms, char *s) +{ + hap_val_t val; + if (s) + val.s = strdup(s); + else + val.s = NULL; + return hap_char_create(type_uuid, perms, HAP_CHAR_FORMAT_STRING, val); +} + +hap_char_t *hap_char_data_create(char *type_uuid, uint16_t perms, hap_data_val_t *d) +{ + hap_val_t val = {0}; + if (d) { + val.d = *d; + } + return hap_char_create(type_uuid, perms, HAP_CHAR_FORMAT_DATA, val); +} + +hap_char_t *hap_char_tlv8_create(char *type_uuid, uint16_t perms, hap_tlv8_val_t *t) +{ + hap_val_t val = {0}; + if (t) { + val.t = *t; + } + return hap_char_create(type_uuid, perms, HAP_CHAR_FORMAT_TLV8, val); +} + +/** + * @brief HAP get target characteristics IID + */ +uint32_t hap_char_get_iid(hap_char_t *hc) +{ + ESP_MFI_ASSERT(hc); + __hap_char_t *tmp = (__hap_char_t *)hc; + + return tmp->iid; +} + +/** + * @brief HAP get target characteristics type UUID + */ +const char * hap_char_get_type_uuid(hap_char_t *hc) +{ + ESP_MFI_ASSERT(hc); + __hap_char_t *tmp = (__hap_char_t *)hc; + + return tmp->type_uuid; +} + +uint16_t hap_char_get_perm(hap_char_t *hc) +{ + if (!hc) + return 0; + + __hap_char_t *tmp = (__hap_char_t *)hc; + return tmp->permission; +} + +hap_char_format_t hap_char_get_format(hap_char_t *hc) +{ + if (!hc) + return 0; + + __hap_char_t *tmp = (__hap_char_t *)hc; + return tmp->format; +} + +/** + * @brief HAP delete target characteristics + */ +void hap_char_delete(hap_char_t *hc) +{ + ESP_MFI_ASSERT(hc); + __hap_char_t *_hc = (__hap_char_t *)hc; + if (_hc->format == HAP_CHAR_FORMAT_STRING) { + if (_hc->val.s) { + hap_platform_memory_free(_hc->val.s); + } + } + if (_hc->valid_vals) { + hap_platform_memory_free(_hc->valid_vals); + } + if (_hc->valid_vals_range) { + hap_platform_memory_free(_hc->valid_vals_range); + } + hap_platform_memory_free(_hc); +} + +/** + * @brief HAP configure the characteristics's value description + */ +void hap_char_int_set_constraints(hap_char_t *hc, int min, int max, int step) +{ + ESP_MFI_ASSERT(hc); + __hap_char_t *tmp = (__hap_char_t *)hc; + tmp->min.i = min; + tmp->max.i = max; + tmp->step.i = step; + if (step) { + tmp->constraint_flags |= (HAP_CHAR_MIN_FLAG | HAP_CHAR_MAX_FLAG | HAP_CHAR_STEP_FLAG); + } else { + tmp->constraint_flags |= (HAP_CHAR_MIN_FLAG | HAP_CHAR_MAX_FLAG); + } +} +void hap_char_float_set_constraints(hap_char_t *hc, float min, float max, float step) +{ + ESP_MFI_ASSERT(hc); + __hap_char_t *tmp = (__hap_char_t *)hc; + tmp->min.f = min; + tmp->max.f = max; + tmp->step.f = step; + if (step) { + tmp->constraint_flags |= (HAP_CHAR_MIN_FLAG | HAP_CHAR_MAX_FLAG | HAP_CHAR_STEP_FLAG); + } else { + tmp->constraint_flags |= (HAP_CHAR_MIN_FLAG | HAP_CHAR_MAX_FLAG); + } +} + +void hap_char_string_set_maxlen(hap_char_t *hc, int maxlen) +{ + ESP_MFI_ASSERT(hc); + __hap_char_t *tmp = (__hap_char_t *)hc; + if (maxlen > HAP_CHAR_STRING_MAX_LEN) { + maxlen = HAP_CHAR_STRING_MAX_LEN; + ESP_MFI_DEBUG(ESP_MFI_DEBUG_WARN, "Characteristic string length larger than maximum value(%d), falling back to the maximum value.", HAP_CHAR_STRING_MAX_LEN); + } + tmp->max.i = maxlen; + tmp->constraint_flags |= HAP_CHAR_MAXLEN_FLAG; +} + +void hap_char_add_description(hap_char_t *hc, const char *description) +{ + ESP_MFI_ASSERT(hc); + __hap_char_t *tmp = (__hap_char_t *)hc; + tmp->description = (char *)description; +} +void hap_char_add_unit(hap_char_t *hc, const char *unit) +{ + ESP_MFI_ASSERT(hc); + __hap_char_t *tmp = (__hap_char_t *)hc; + tmp->unit = (char *)unit; +} +hap_char_t *hap_char_get_next(hap_char_t *hc) +{ + return ((__hap_char_t *)hc)->next_char; +} + +hap_serv_t *hap_char_get_parent(hap_char_t *hc) +{ + return ((__hap_char_t *)hc)->parent; + +} + +#define set_bit(val, index) ((val) |= (1 << index)) +#define reset_bit(val, index) ((val) &= ~(1 << index)) +void hap_char_manage_notification(hap_char_t *hc, int index, bool ev) +{ + __hap_char_t *_hc = (__hap_char_t *)hc; + if (ev) + set_bit(_hc->ev_ctrls, index); + else + reset_bit(_hc->ev_ctrls, index); +} + +bool hap_char_is_ctrl_subscribed(hap_char_t *hc, int index) +{ + __hap_char_t *_hc = (__hap_char_t *)hc; + return (_hc->ev_ctrls & (1 << index)) ? true : false; +} + +void hap_char_set_owner_ctrl(hap_char_t *hc, int index) +{ + __hap_char_t *_hc = (__hap_char_t *)hc; + _hc->owner_ctrl = 0; + set_bit(_hc->owner_ctrl, index); +} + +bool hap_char_is_ctrl_owner(hap_char_t *hc, int index) +{ + __hap_char_t *_hc = (__hap_char_t *)hc; + return (_hc->owner_ctrl & (1 << index)) ? true : false; +} + +void hap_char_set_iid(hap_char_t *hc, int32_t iid) +{ + if (hc) { + ((__hap_char_t *)hc)->iid = iid; + } +} + +void hap_disable_all_char_notif(int index) +{ + /* Just loop through all characteristic objects and reset the + * bit indicating event notifications. This is the simplest way + */ + hap_acc_t *ha; + hap_serv_t *hs; + hap_char_t *hc; + for (ha = hap_get_first_acc(); ha; ha = hap_acc_get_next(ha)) { + for (hs = hap_acc_get_first_serv(ha); hs; hs = hap_serv_get_next(hs)) { + for (hc = hap_serv_get_first_char(hs); hc; hc = hap_char_get_next(hc)) { + reset_bit(((__hap_char_t *)hc)->ev_ctrls, index); + } + } + } +} + +void hap_char_add_valid_vals(hap_char_t *hc, const uint8_t *valid_vals, size_t valid_val_cnt) +{ + if (!hc) + return; + __hap_char_t *_hc = (__hap_char_t *)hc; + _hc->valid_vals = hap_platform_memory_malloc(valid_val_cnt); + if (_hc->valid_vals) { + memcpy(_hc->valid_vals, valid_vals, valid_val_cnt); + _hc->valid_vals_cnt = valid_val_cnt; + } +} + +void hap_char_add_valid_vals_range(hap_char_t *hc, uint8_t start_val, uint8_t end_val) +{ + if (!hc) + return; + __hap_char_t *_hc = (__hap_char_t *)hc; + _hc->valid_vals_range = hap_platform_memory_malloc(sizeof(uint8_t)); + if (_hc->valid_vals_range) { + _hc->valid_vals_range[0] = start_val; + _hc->valid_vals_range[1] = end_val; + } +} diff --git a/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_char.h b/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_char.h new file mode 100644 index 000000000..d24fcf8b6 --- /dev/null +++ b/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_char.h @@ -0,0 +1,98 @@ +/* + * ESPRESSIF MIT License + * + * Copyright (c) 2020 + * + * Permission is hereby granted for use on ESPRESSIF SYSTEMS products only, in which case, + * it is 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. + * + */ + +#ifndef _HAP_CHAR_H_ +#define _HAP_CHAR_H_ + +#include +#include +#include + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif +#define HAP_CHAR_MIN_FLAG (1 << 0) +#define HAP_CHAR_MAX_FLAG (1 << 1) +#define HAP_CHAR_STEP_FLAG (1 << 2) +#define HAP_CHAR_MAXLEN_FLAG (1 << 3) +#define HAP_CHAR_MAXDATALEN_FLAG (1 << 4) + +/** + * @brief characteristics object information + */ +typedef struct { + uint32_t iid; /* Characteristic instance ID */ + const char *type_uuid; /* Apple's characteristic UUID */ + uint16_t permission; /* Characteristic permission */ + hap_char_format_t format; /* data type of the value */ + hap_val_t val; + bool ev; /* check if characteristics supports event */ + char *description; /* characteristics's description */ + char *unit; + + /* Characteristics's father subsystem */ + hap_serv_t *parent; + + uint8_t constraint_flags; + + hap_val_t max; /* maximum value, maxlen, max data len*/ + hap_val_t min; /* minimum value */ + hap_val_t step; /* step value */ + + hap_char_t *next_char; + /* Bitmap to indicate which controllers have enabled notifications + */ + uint16_t ev_ctrls; + + /* Bitmap indicating the last controller that modified the value. + * No notification should be sent to the owner + */ + uint16_t owner_ctrl; + + /* Pointer to a valid values range. It will be a 2 byte array, if set from application */ + uint8_t *valid_vals_range; + /* Since a list of valid values can have any length, using a pointer here, + * which will be allocated if valid values are set for a characteristic + */ + uint8_t *valid_vals; + size_t valid_vals_cnt; + bool update_called; +} __hap_char_t; + +void hap_char_manage_notification(hap_char_t *hc, int index, bool ev); +bool hap_char_is_ctrl_subscribed(hap_char_t *hc, int index); +void hap_char_set_owner_ctrl(hap_char_t *hc, int index); +bool hap_char_is_ctrl_owner(hap_char_t *hc, int index); +void hap_disable_all_char_notif(int index); +int hap_char_check_val_constraints(__hap_char_t *_hc, hap_val_t *val); +int hap_event_queue_init(); +hap_char_t * hap_get_pending_notif_char(); +#ifdef __cplusplus +} +#endif + +#endif /* _HAP_CHAR_H_ */ diff --git a/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_controllers.c b/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_controllers.c new file mode 100644 index 000000000..4b2b16eb2 --- /dev/null +++ b/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_controllers.c @@ -0,0 +1,149 @@ +/* + * ESPRESSIF MIT License + * + * Copyright (c) 2020 + * + * Permission is hereby granted for use on ESPRESSIF SYSTEMS products only, in which case, + * it is 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 +#include +#include + +#include +#include +#include +#include + +#define HAP_KEYSTORE_NAMESPACE_CTRL "hap_ctrl" + +int hap_controllers_init() +{ + memset(hap_priv.controllers, 0, sizeof(hap_priv.controllers)); + char index_str[4]; + uint8_t i; + size_t info_size; + bool acc_paired = false; + for (i = 0; i < HAP_MAX_CONTROLLERS; i++) { + snprintf(index_str, sizeof(index_str), "%d", i); + info_size = sizeof(hap_ctrl_info_t); + if (hap_keystore_get(HAP_KEYSTORE_NAMESPACE_CTRL, index_str, + (uint8_t *)&hap_priv.controllers[i].info, &info_size) == HAP_SUCCESS) { + if (info_size == sizeof(hap_ctrl_info_t)) { + hap_priv.controllers[i].index = i; + hap_priv.controllers[i].valid = true; + acc_paired = true; + } + } + } + if (acc_paired) { + ESP_MFI_DEBUG(ESP_MFI_DEBUG_INFO, "Accessory is Paired with atleast one controller"); + } else { + ESP_MFI_DEBUG(ESP_MFI_DEBUG_INFO, "Accessory is not Paired with any controller"); + } + return HAP_SUCCESS; +} + +hap_ctrl_data_t *hap_controller_get_empty_loc() +{ + int i; + for (i = 0; i < HAP_MAX_CONTROLLERS; i++) { + if (!hap_priv.controllers[i].valid) { + hap_priv.controllers[i].index = i; + return &hap_priv.controllers[i]; + } + } + return NULL; +} + +int hap_get_paired_controller_count() +{ + int i, cnt = 0; + for (i = 0; i < HAP_MAX_CONTROLLERS; i++) { + if (hap_priv.controllers[i].valid) { + cnt++; + } + } + return cnt; +} + +bool is_accessory_paired() +{ + int i; + for (i = 0; i < HAP_MAX_CONTROLLERS; i++) { + if (hap_priv.controllers[i].valid) + return true; + } + return false; +} + +bool is_admin_paired() +{ + int i; + for (i = 0; i < HAP_MAX_CONTROLLERS; i++) { + if (hap_priv.controllers[i].valid && hap_priv.controllers[i].info.perms) + return true; + } + return false; +} + +int hap_controller_save(hap_ctrl_data_t *ctrl_data) +{ + ctrl_data->valid = true; + char index_str[4]; + snprintf(index_str, sizeof(index_str), "%d", ctrl_data->index); + int ret = hap_keystore_set(HAP_KEYSTORE_NAMESPACE_CTRL, index_str, + (const uint8_t *)&ctrl_data->info, (size_t)sizeof(hap_ctrl_info_t)); + + if (ret != HAP_SUCCESS) { + ESP_MFI_DEBUG(ESP_MFI_DEBUG_ERR, "Failed to store controller %d", ctrl_data->index); + return HAP_FAIL; + } + hap_report_event(HAP_EVENT_CTRL_PAIRED, ctrl_data->info.id, sizeof(ctrl_data->info.id)); + return HAP_SUCCESS; +} + +void hap_controller_remove(hap_ctrl_data_t *ctrl_data) +{ + if (!ctrl_data) + return; + char index_str[4]; + snprintf(index_str, sizeof(index_str), "%d", ctrl_data->index); + char id[HAP_CTRL_ID_LEN]; + strncpy(id, ctrl_data->info.id, sizeof(id)); + hap_keystore_delete(HAP_KEYSTORE_NAMESPACE_CTRL, index_str); + memset(ctrl_data, 0, sizeof(hap_ctrl_data_t)); + hap_report_event(HAP_EVENT_CTRL_UNPAIRED, id, sizeof(id)); +} + +hap_ctrl_data_t *hap_get_controller(char *ctrl_id) +{ + int i; + for (i = 0; i < HAP_MAX_CONTROLLERS; i++) { + if (hap_priv.controllers[i].valid + && (!strcmp(hap_priv.controllers[i].info.id, ctrl_id))) + return &hap_priv.controllers[i]; + } + return NULL; +} + +void hap_erase_controller_info() +{ + hap_keystore_delete_namespace(HAP_KEYSTORE_NAMESPACE_CTRL); +} diff --git a/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_controllers.h b/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_controllers.h new file mode 100644 index 000000000..1a341ddeb --- /dev/null +++ b/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_controllers.h @@ -0,0 +1,61 @@ +/* + * ESPRESSIF MIT License + * + * Copyright (c) 2020 + * + * Permission is hereby granted for use on ESPRESSIF SYSTEMS products only, in which case, + * it is 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. + * + */ +#ifndef _HAP_CONTROLLERS_H_ +#define _HAP_CONTROLLERS_H_ + +#include +#include + +#define HAP_MAX_CONTROLLERS 16 +#define HAP_CTRL_ID_LEN 64 +#define ED_KEY_LEN 32 + + +typedef struct { + char id[HAP_CTRL_ID_LEN]; + uint8_t ltpk[ED_KEY_LEN]; + uint8_t perms; +} __attribute__((packed)) hap_ctrl_info_t; + +typedef struct { + hap_ctrl_info_t info; + /* If "valid" is false, it means that the entry is invalid, + * irrespective of the values of other members, and can be + * used to store new controller info + */ + bool valid; + /* Index is used just for better managing the keystore data */ + uint8_t index; +} hap_ctrl_data_t; + +int hap_controllers_init(); +bool is_accessory_paired(); +bool is_admin_paired(); +hap_ctrl_data_t *hap_controller_get_empty_loc(); +int hap_controller_save(hap_ctrl_data_t *ctrl_data); +void hap_controller_remove(hap_ctrl_data_t *ctrl_data); +hap_ctrl_data_t *hap_get_controller(char *ctrl_id); +void hap_erase_controller_info(); + +#endif /* _HAP_CONTROLLERS_H_ */ diff --git a/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_database.c b/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_database.c new file mode 100644 index 000000000..dec7e80f8 --- /dev/null +++ b/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_database.c @@ -0,0 +1,334 @@ +/* + * ESPRESSIF MIT License + * + * Copyright (c) 2020 + * + * Permission is hereby granted for use on ESPRESSIF SYSTEMS products only, in which case, + * it is 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 +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +#include + +#define HAP_KEY_ACC_ID "acc_id" +#define HAP_KEY_LTSKA "ltska" +#define HAP_KEY_LTPKA "ltpka" +#define HAP_KEY_CONFIG_NUM "config_num" +#define HAP_KEY_FW_REV "fw_rev" +#define HAP_KEY_CUR_AID "cur_aid" +#define HAP_KEY_STATE_NUM "state_num" + +#define HAP_KEY_SETUP_ID "setup_id" +#define HAP_KEY_SETUP_SALT "setup_salt" +#define HAP_KEY_SETUP_VERIFIER "setup_verifier" + +#define HAP_LOOP_STACK (4 * 1024) +#define HAP_MAIN_THREAD_PRIORITY 7 +#define HAP_MAX_NOTIF_CHARS 8 +#define HAP_SOCK_RECV_TIMEOUT 10 +#define HAP_SOCK_SEND_TIMEOUT 10 + +hap_priv_t hap_priv = { + .cfg = { + .task_stack_size = HAP_LOOP_STACK, + .task_priority = HAP_MAIN_THREAD_PRIORITY, + .max_event_notif_chars = HAP_MAX_NOTIF_CHARS, + .unique_param = UNIQUE_SSID, + .recv_timeout = HAP_SOCK_RECV_TIMEOUT, + .send_timeout = HAP_SOCK_SEND_TIMEOUT, + .sw_token_max_len = HAP_SW_TOKEN_MAX_LEN, + } +}; + +static void hap_save_config_number() +{ + + hap_keystore_set(HAP_KEYSTORE_NAMESPACE_HAPMAIN, HAP_KEY_CONFIG_NUM, + (uint8_t *)&hap_priv.config_num, sizeof(hap_priv.config_num)); +} + +static void hap_get_config_number() +{ + size_t config_num_len = sizeof(hap_priv.config_num); + if (hap_keystore_get(HAP_KEYSTORE_NAMESPACE_HAPMAIN, HAP_KEY_CONFIG_NUM, + (uint8_t *)&hap_priv.config_num, &config_num_len) != HAP_SUCCESS) { + hap_priv.config_num = 1; + hap_save_config_number(); + } + if (hap_priv.config_num > 65535) { + hap_priv.config_num = 1; + hap_save_config_number(); + } +} + +void hap_increment_and_save_config_num() +{ + hap_priv.config_num++; + if (hap_priv.config_num > 65535) { + hap_priv.config_num = 1; + } + hap_save_config_number(); +} + + +static void hap_save_state_number() +{ + hap_keystore_set(HAP_KEYSTORE_NAMESPACE_HAPMAIN, HAP_KEY_STATE_NUM, + (uint8_t *)&hap_priv.state_num, sizeof(hap_priv.state_num)); +} + +void hap_increment_and_save_state_num() +{ + if (is_accessory_paired()) { + hap_priv.state_num++; + /* If value becomes 0 after incrementing, it means that it has wrapped around. + * So, reset to 1 + */ + if (hap_priv.state_num == 0) { + hap_priv.state_num = 1; + } + ESP_MFI_DEBUG(ESP_MFI_DEBUG_INFO, "Updated state number to %d", hap_priv.state_num); + hap_save_state_number(); + } +} + +static void hap_init_state_number() +{ + size_t state_num_len = sizeof(hap_priv.state_num); + if (hap_keystore_get(HAP_KEYSTORE_NAMESPACE_HAPMAIN, HAP_KEY_STATE_NUM, + (uint8_t *)&hap_priv.state_num, &state_num_len) != HAP_SUCCESS) { + /* If state number is not found, initialise with 1 and store. + */ + hap_priv.state_num = 1; + hap_save_state_number(); + } else { + hap_increment_and_save_state_num(); + } +} + +static void hap_save_cur_aid() +{ + hap_keystore_set(HAP_KEYSTORE_NAMESPACE_HAPMAIN, HAP_KEY_CUR_AID, + (uint8_t *)&hap_priv.cur_aid, sizeof(hap_priv.cur_aid)); +} + +static void hap_get_cur_aid() +{ + size_t aid_len = sizeof(hap_priv.cur_aid); + if (hap_keystore_get(HAP_KEYSTORE_NAMESPACE_HAPMAIN, HAP_KEY_CUR_AID, + (uint8_t *)&hap_priv.cur_aid, &aid_len) != HAP_SUCCESS) { + /* AID = 1 is reserved for Primary Accessory. So, we set the initial + * value to 1, so that the bridged accessories get assigned aid from + * 2 onwards + */ + hap_priv.cur_aid = 1; + hap_save_cur_aid(); + } +} + +static int hap_get_setup_id() +{ + /* Read setup id from NVS, only if it is not already set from the accessory code */ + if (!strlen(hap_priv.setup_id)) { + size_t setup_id_len = sizeof(hap_priv.setup_id); + if (hap_factory_keystore_get(HAP_FACTORY_NAMESPACE_HAP_SETUP, HAP_KEY_SETUP_ID, + (uint8_t *)hap_priv.setup_id, &setup_id_len) != HAP_SUCCESS) { + return HAP_FAIL; + } + } + return HAP_SUCCESS; +} + +static int hap_get_setup_info() +{ + /* If the setup code has been set directly, no need to check for setup info */ + if (hap_priv.setup_code) { + return HAP_SUCCESS; + } + /* If the setup info has been set externally, directly from the accessory code, + * no need to check in the NVS + */ + if (!hap_priv.setup_info) { + ESP_MFI_DEBUG(ESP_MFI_DEBUG_INFO, "Getting setup info from factory NVS"); + hap_priv.setup_info = hap_platform_memory_calloc(1, sizeof(hap_setup_info_t)); + if (!hap_priv.setup_info) + return HAP_FAIL; + size_t salt_len = sizeof(hap_priv.setup_info->salt); + size_t verifier_len = sizeof(hap_priv.setup_info->verifier); + int ret = hap_factory_keystore_get(HAP_FACTORY_NAMESPACE_HAP_SETUP, HAP_KEY_SETUP_SALT, + hap_priv.setup_info->salt, &salt_len); + ret |= hap_factory_keystore_get(HAP_FACTORY_NAMESPACE_HAP_SETUP, HAP_KEY_SETUP_VERIFIER, + hap_priv.setup_info->verifier, &verifier_len); + if (ret != HAP_SUCCESS) { + hap_platform_memory_free(hap_priv.setup_info); + hap_priv.setup_info = NULL; + return HAP_FAIL; + } + } + return HAP_SUCCESS; +} + +static void hap_check_fw_version() +{ + char fw_rev[64] = {0}; + size_t fw_rev_len = sizeof(fw_rev); + /* Check if the firmware revision is stored in NVS */ + if (hap_keystore_get(HAP_KEYSTORE_NAMESPACE_HAPMAIN, HAP_KEY_FW_REV, + (uint8_t *)fw_rev, &fw_rev_len) == HAP_SUCCESS) { + /* If the firmware revision is found, compare with the current revision. + * If it is the same, no need to do anything. So, just return + */ + if (strncmp(fw_rev, hap_priv.primary_acc.fw_rev, sizeof(fw_rev)) == 0) { + return; + } else { + /* If there is a version mismatch, it means that the firmware was upgraded. + * Update config number in that case + */ + ESP_MFI_DEBUG(ESP_MFI_DEBUG_INFO, "FW Update detected. Incrementing config number"); + hap_increment_and_save_config_num(); + } + } + /* Save the new firmare revision to NVS */ + hap_keystore_set(HAP_KEYSTORE_NAMESPACE_HAPMAIN, HAP_KEY_FW_REV, + (uint8_t *)hap_priv.primary_acc.fw_rev, + strlen(hap_priv.primary_acc.fw_rev)); +} + +int hap_acc_setup_init() +{ + if (hap_get_setup_id() != HAP_SUCCESS) { + ESP_MFI_DEBUG(ESP_MFI_DEBUG_ERR, "Setup ID absent"); + return HAP_FAIL; + } else { + ESP_MFI_DEBUG(ESP_MFI_DEBUG_INFO, "Setup ID: %s", hap_priv.setup_id); + } + + if (hap_get_setup_info() != HAP_SUCCESS) { + ESP_MFI_DEBUG(ESP_MFI_DEBUG_ERR, "Setup Info absent"); + return HAP_FAIL; + } + + uint8_t digest[MFI_SHA512_SIZE] = {0}; + esp_mfi_sha_ctx_t ctx = 0; + ctx = esp_mfi_sha512_new(); + if (!ctx) { + ESP_MFI_DEBUG(ESP_MFI_DEBUG_ERR, "Out of Memory"); + return HAP_FAIL; + } + /* Compute setup hash by taking a SHA512 hash of the setup id and device id */ + esp_mfi_sha512_init(ctx); + esp_mfi_sha512_update(ctx, (const uint8_t *)hap_priv.setup_id, strlen(hap_priv.setup_id)); + esp_mfi_sha512_update(ctx, (const uint8_t *)hap_priv.acc_id, strlen(hap_priv.acc_id)); + esp_mfi_sha512_final(ctx, digest); + /* Copy only the first 4 bytes as the setup hash */ + memcpy(hap_priv.setup_hash, digest, SETUP_HASH_LEN); + esp_mfi_sha512_free(ctx); + + int hash_size = sizeof(hap_priv.setup_hash_str); + esp_mfi_base64_encode((const char *)hap_priv.setup_hash, SETUP_HASH_LEN, + hap_priv.setup_hash_str, hash_size, &hash_size); + + hap_check_fw_version(); + + return HAP_SUCCESS; +} + +int hap_database_init(void) +{ + uint8_t id[6]; + size_t val_size = sizeof(id); + if (hap_keystore_get(HAP_KEYSTORE_NAMESPACE_HAPMAIN, HAP_KEY_ACC_ID, id, &val_size) == HAP_SUCCESS) { + val_size = sizeof(hap_priv.ltska); + hap_keystore_get(HAP_KEYSTORE_NAMESPACE_HAPMAIN, HAP_KEY_LTSKA, hap_priv.ltska, &val_size); + val_size = sizeof(hap_priv.ltpka); + hap_keystore_get(HAP_KEYSTORE_NAMESPACE_HAPMAIN, HAP_KEY_LTPKA, hap_priv.ltpka, &val_size); + } else { + /* If the accessory ID is not found in keystore, create and store a new random ID */ + esp_mfi_get_random(id, sizeof(id)); + hap_keystore_set(HAP_KEYSTORE_NAMESPACE_HAPMAIN, HAP_KEY_ACC_ID, id, sizeof(id)); + /* Also create a new ED25519 key pair */ + esp_mfi_get_random(hap_priv.ltska, sizeof(hap_priv.ltska)); + crypto_sign_ed25519_keypair(hap_priv.ltpka, hap_priv.ltska); + hap_keystore_set(HAP_KEYSTORE_NAMESPACE_HAPMAIN, HAP_KEY_LTSKA, hap_priv.ltska, sizeof(hap_priv.ltska)); + hap_keystore_set(HAP_KEYSTORE_NAMESPACE_HAPMAIN, HAP_KEY_LTPKA, hap_priv.ltpka, sizeof(hap_priv.ltpka)); + } + + memcpy(hap_priv.raw_acc_id, id, sizeof(hap_priv.raw_acc_id)); + snprintf(hap_priv.acc_id, sizeof(hap_priv.acc_id), "%02X:%02X:%02X:%02X:%02X:%02X", + id[0], id[1], id[2], id[3], id[4], id[5]); + + hap_controllers_init(); + hap_get_config_number(); + hap_get_cur_aid(); + hap_init_state_number(); + ESP_MFI_DEBUG(ESP_MFI_DEBUG_INFO, "Database initialised. Accessory Device ID: %s", hap_priv.acc_id); + return HAP_SUCCESS; +} + +char *hap_get_acc_id() +{ + return hap_priv.acc_id; +} + +int hap_get_next_aid(char *id) +{ + hap_priv.cur_aid++; + hap_save_cur_aid(); + return hap_priv.cur_aid; +} + +void hap_erase_accessory_info() +{ + hap_keystore_delete_namespace(HAP_KEYSTORE_NAMESPACE_HAPMAIN); +} + +void hap_configure_unique_param(hap_unique_param_t param) +{ + hap_priv.cfg.unique_param = param; +} + +int hap_get_config(hap_cfg_t *cfg) +{ + if (!cfg) { + return HAP_FAIL; + } + *cfg = hap_priv.cfg; + return HAP_SUCCESS; +} + +int hap_set_config(const hap_cfg_t *cfg) +{ + if (!cfg) { + return HAP_FAIL; + } + hap_priv.cfg = *cfg; + return HAP_SUCCESS; +} diff --git a/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_database.h b/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_database.h new file mode 100644 index 000000000..22da74c8e --- /dev/null +++ b/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_database.h @@ -0,0 +1,92 @@ +/* + * ESPRESSIF MIT License + * + * Copyright (c) 2020 + * + * Permission is hereby granted for use on ESPRESSIF SYSTEMS products only, in which case, + * it is 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. + * + */ +#ifndef _HAP_DATABASE_H_ +#define _HAP_DATABASE_H_ + +#include +#include +#include +#include +#include +#include + +#define HAP_KEYSTORE_NAMESPACE_HAPMAIN "hap_main" +#define HAP_FACTORY_NAMESPACE_HAP_SETUP "hap_setup" + +#define HAP_MAX_SESSIONS 8 +#define SETUP_ID_LEN 4 +#define SETUP_HASH_LEN 4 + +#define HAP_ACC_ID_LEN 18 /* AA:BB:CC:XX:YY:ZZ\0 */ +#define ED_KEY_LEN 32 +#define HAP_SW_TOKEN_MAX_LEN 1200 + + +typedef struct { + hap_acc_cfg_t primary_acc; + uint32_t config_num; + uint32_t cur_aid; + uint8_t raw_acc_id[6]; + char acc_id[HAP_ACC_ID_LEN]; + char setup_id[SETUP_ID_LEN + 1]; + uint8_t setup_hash[SETUP_HASH_LEN]; + char setup_hash_str[SETUP_HASH_LEN * 2 + 1]; + uint8_t ltska[ED_KEY_LEN]; + uint8_t ltpka[ED_KEY_LEN]; + hap_cid_t cid; + hap_ctrl_data_t controllers[HAP_MAX_CONTROLLERS]; + hap_secure_session_t *sessions[HAP_MAX_SESSIONS]; + uint8_t pair_attempts; + hap_mdns_handle_t wac_mdns_handle; + hap_mdns_handle_t hap_mdns_handle; + hap_setup_info_t *setup_info; + char *setup_code; + char *ssid; + char *password; + hap_software_token_info_t *token_info; + uint8_t features; + hap_event_handler_t hap_event_handler; + char *softap_ssid; + void (*ext_nw_prov_start)(void *data, const char *name); + void (*ext_nw_prov_stop)(void *data); + void *ext_nw_prov_data; + hap_cfg_t cfg; + hap_transport_t transport; + uint32_t pairing_flags; + httpd_handle_t server; + uint8_t *product_data; + uint16_t state_num; + bool disconnected_event_sent; + hap_mfi_auth_type_t auth_type; +} hap_priv_t; + +extern hap_priv_t hap_priv; +int hap_database_init(void); +char *hap_get_acc_id(); +int hap_get_next_aid(); +int hap_acc_setup_init(); +void hap_erase_accessory_info(); +void hap_increment_and_save_config_num(); +void hap_increment_and_save_state_num(); +#endif /* _HAP_DATABASE_H_ */ diff --git a/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_ip_services.c b/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_ip_services.c new file mode 100644 index 000000000..4f5031a64 --- /dev/null +++ b/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_ip_services.c @@ -0,0 +1,1630 @@ +/* + * ESPRESSIF MIT License + * + * Copyright (c) 2020 + * + * Permission is hereby granted for use on ESPRESSIF SYSTEMS products only, in which case, + * it is 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include //??? + +#ifdef ESP_MFI_DEBUG_ENABLE +#define ESP_MFI_DEBUG_PLAIN(fmt, ...) \ + if (http_debug) { \ + printf("\e[1;35m" fmt "\e[0m", ##__VA_ARGS__); \ + } +#else /* ESP_MFI_DEBUG_ENABLE */ +#define ESP_MFI_DEBUG_PLAIN(fmt, ...) +#endif /* ESP_MFI_DEBUG_ENABLE */ + +static bool http_debug; + +int hap_http_session_not_authorized(httpd_req_t *req) +{ + char buf[50]; + httpd_resp_set_status(req, "470 Connection Authorization Required"); + httpd_resp_set_type(req, "application/hap+json"); + snprintf(buf, sizeof(buf),"{\"status\":-70401}"); + httpd_resp_send(req, buf, strlen(buf)); + return HAP_SUCCESS; + +} + +int hap_httpd_get_data(httpd_req_t *req, char *buffer, int len) +{ + int read_len = 0; + while (read_len < len) { + int tmp_len = httpd_req_recv(req, buffer + read_len, len - read_len); + if (tmp_len <= 0) { + return read_len; + } + read_len += tmp_len; + } + return read_len; +} + +static int hap_http_pair_setup_handler(httpd_req_t *req) +{ + uint8_t buf[1200]; + int ret, ret1, outlen; + void *ctx = (hap_secure_session_t *)hap_platform_httpd_get_sess_ctx(req); + int fd = httpd_req_to_sockfd(req); + ESP_MFI_DEBUG_PLAIN("Socket fd: %d; HTTP Request %s %s\n", httpd_req_to_sockfd(req), hap_platform_httpd_get_req_method(req), hap_platform_httpd_get_req_uri(req)); + if (!ctx) { + if (hap_pair_setup_context_init(fd, &ctx, buf, sizeof(buf), &outlen) == HAP_SUCCESS) { + hap_platform_httpd_set_sess_ctx(req, ctx, hap_pair_setup_ctx_clean, true); + } else { + httpd_resp_set_type(req, "application/pairing+tlv8"); + httpd_resp_send(req, (char *)buf, outlen); + return HAP_SUCCESS; + } + } + int data_len = httpd_req_recv(req, (char *)buf, sizeof(buf)); + ret = hap_pair_setup_process(&ctx, buf, data_len, sizeof(buf), &outlen); + httpd_resp_set_type(req, "application/pairing+tlv8"); + ret1 = httpd_resp_send(req, (char *)buf, outlen); + if (ret != HAP_SUCCESS) { + hap_pair_setup_ctx_clean(ctx); + ctx = NULL; + } else { + /* A pair verify function is called here, because for Software Token Authentication, + * secure session keys are generated at the step M4 of Pair Setup, and there onwards, + * the behavior is like a pair verified session. + */ + if (hap_pair_verify_get_state(ctx) == STATE_VERIFIED) { + /* Saving socket fd since it will later be required for + * event notifications. + */ + ((hap_secure_session_t *)ctx)->conn_identifier = fd; + hap_platform_httpd_set_sess_ctx(req, ctx, hap_free_session, true); + httpd_sess_set_send_override(hap_priv.server, fd, hap_httpd_send); + httpd_sess_set_recv_override(hap_priv.server, fd, hap_httpd_recv); + } + } + /* Context will be NULL, either if there was an error and a cleanup was required, + * or if the pair_setup_process cleared it after successful pairing. + * For both the cases, we will set the sess_ctx and free_ctx to NULL + */ + if (!ctx) { + hap_platform_httpd_set_sess_ctx(req, NULL, NULL, true); + } + return ret1; +} +static struct httpd_uri hap_pair_setup = { + .uri = "/pair-setup", + .method = HTTP_POST, + .handler = hap_http_pair_setup_handler, +}; + +static int hap_http_pair_verify_handler(httpd_req_t *req) +{ + uint8_t buf[512]; + int ret, outlen; + void *ctx = hap_platform_httpd_get_sess_ctx(req); + ESP_MFI_DEBUG_PLAIN("Socket fd: %d; HTTP Request %s %s\n", httpd_req_to_sockfd(req), hap_platform_httpd_get_req_method(req), hap_platform_httpd_get_req_uri(req)); + if (!ctx) { + if (hap_pair_verify_context_init(&ctx, buf, sizeof(buf), &outlen) == HAP_SUCCESS) { + hap_platform_httpd_set_sess_ctx(req, ctx, NULL, true); + } + } + int data_len = httpd_req_recv(req, (char *)buf, sizeof(buf)); + ret = hap_pair_verify_process(&ctx, buf, data_len, sizeof(buf), &outlen); + httpd_resp_set_type(req, "application/pairing+tlv8"); + int ret1 = httpd_resp_send(req, (char *)buf, outlen); + if (ret == HAP_SUCCESS) { + if (hap_pair_verify_get_state(ctx) == STATE_VERIFIED) { + /* Saving socket fd since it will later be required for + * event notifications. + */ + int fd = httpd_req_to_sockfd(req); + ((hap_secure_session_t *)ctx)->conn_identifier = fd; + + struct timeval timeout; + timeout.tv_sec = hap_priv.cfg.recv_timeout; + timeout.tv_usec = 0; + if (setsockopt (fd, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, + sizeof(timeout)) < 0) { + ESP_MFI_DEBUG(ESP_MFI_DEBUG_ERR, "setsockopt on pair verified socket failed for SO_RCVTIMEO"); + } + + timeout.tv_sec = hap_priv.cfg.send_timeout; + timeout.tv_usec = 0; + if (setsockopt (fd, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeout, + sizeof(timeout)) < 0) { + ESP_MFI_DEBUG(ESP_MFI_DEBUG_ERR, "setsockopt on pair verified socket failed for SO_SNDTIMEO"); + } + + + // ---- + const int s = fd; + const int yes = 1; /* enable sending keepalive probes for socket */ + setsockopt(s, SOL_SOCKET, SO_KEEPALIVE, &yes, sizeof(yes)); + + const int idle = 15; /* 180 sec idle before start sending probes */ + setsockopt(s, IPPROTO_TCP, TCP_KEEPIDLE, &idle, sizeof(idle)); + + const int interval = 5; /* 30 sec between probes */ + setsockopt(s, IPPROTO_TCP, TCP_KEEPINTVL, &interval, sizeof(interval)); + + const int maxpkt = 3; /* Drop connection after 4 probes without response */ + setsockopt(s, IPPROTO_TCP, TCP_KEEPCNT, &maxpkt, sizeof(maxpkt)); + // ---- + + hap_platform_httpd_set_sess_ctx(req, ctx, hap_free_session, true); + httpd_sess_set_send_override(hap_priv.server, fd, hap_httpd_send); + httpd_sess_set_recv_override(hap_priv.server, fd, hap_httpd_recv); + + + hap_secure_session_t* session = (hap_secure_session_t *)ctx; + int socket = session->conn_identifier; + + //struct sockaddr_storage addr; + struct sockaddr_in6 addr; + socklen_t len = sizeof addr; + getpeername(fd, (struct sockaddr*)&addr, &len); + /* + struct sockaddr_in *sockaddr = (struct sockaddr_in *)&addr; + in_addr_t a = sockaddr->sin_addr.s_addr; + union { + uint8_t ui8[4]; + uint32_t ui32; + }ip; + ip.ui32 = (uint32_t)a; + */ + //uint16_t port = ntohs(sockaddr->sin6_port); + uint16_t port = addr.sin6_port; + printf("---- STATE_VERIFIED ----\n"); + //printf("ip32: %u\n", a); + //printf("fd: %d, %u.%u.%u.%u:%u \n", socket, + //ip.ui8[0], ip.ui8[1], ip.ui8[2], ip.ui8[3], port); + //https://github.com/espressif/esp-idf/issues/4863 + printf("fd: %d, remote: %s:%u\n", fd, inet_ntoa(addr.sin6_addr.un.u32_addr[3]), port); + printf("ctrl: %s\n", session->ctrl->info.id); + + printf("------------------------\n"); + } + } + return ret1; +} + +static struct httpd_uri hap_pair_verify = { + .uri = "/pair-verify", + .method = HTTP_POST, + .handler = hap_http_pair_verify_handler, +}; + +static int hap_add_char_val_json(hap_char_format_t format, char *key, + hap_val_t *val, json_gen_str_t *jptr) +{ + switch (format) { + case HAP_CHAR_FORMAT_BOOL : { + json_gen_obj_set_bool(jptr, key, val->b); + break; + } + case HAP_CHAR_FORMAT_UINT8: + case HAP_CHAR_FORMAT_UINT16: + case HAP_CHAR_FORMAT_UINT32: + case HAP_CHAR_FORMAT_INT: { + json_gen_obj_set_int(jptr, key, val->i); + break; + } + case HAP_CHAR_FORMAT_FLOAT : { + json_gen_obj_set_float(jptr, key, val->f); + break; + } + case HAP_CHAR_FORMAT_STRING : { + if (val->s) { + json_gen_obj_set_string(jptr, key, val->s); + } else { + json_gen_obj_set_null(jptr, key); + } + break; + } + case HAP_CHAR_FORMAT_DATA: + case HAP_CHAR_FORMAT_TLV8: { + if (val->d.buf) { + json_gen_obj_start_long_string(jptr, key, NULL); + uint8_t *buf = val->d.buf; + uint32_t buflen = val->d.buflen; + char tmp[100]; + while (buflen) { + int tmp_len = sizeof(tmp); + if (buflen > 60) { + esp_mfi_base64_encode((char *)buf, 60, tmp, tmp_len, &tmp_len); + buflen -= 60; + buf += 60; + } else { + esp_mfi_base64_encode((char *)buf, buflen, tmp, tmp_len, &tmp_len); + buflen -= buflen; + } + tmp[tmp_len] = 0; + json_gen_add_to_long_string(jptr, tmp); + } + json_gen_end_long_string(jptr); + } else { + json_gen_obj_set_null(jptr, key); + } + break; + } + default : + break; + } + return HAP_SUCCESS; +} + +static int hap_add_char_format_json(__hap_char_t *hc, json_gen_str_t *jptr) +{ + switch (hc->format) { + case HAP_CHAR_FORMAT_UINT8: + return json_gen_obj_set_string(jptr, "format", "uint8"); + case HAP_CHAR_FORMAT_UINT16: + return json_gen_obj_set_string(jptr, "format", "uint16"); + case HAP_CHAR_FORMAT_UINT32: + return json_gen_obj_set_string(jptr, "format", "uint32"); + case HAP_CHAR_FORMAT_INT: + return json_gen_obj_set_string(jptr, "format", "int"); + case HAP_CHAR_FORMAT_BOOL: + return json_gen_obj_set_string(jptr, "format", "bool"); + case HAP_CHAR_FORMAT_STRING: + return json_gen_obj_set_string(jptr, "format", "string"); + case HAP_CHAR_FORMAT_FLOAT: + return json_gen_obj_set_string(jptr, "format", "float"); + case HAP_CHAR_FORMAT_DATA: + return json_gen_obj_set_string(jptr, "format", "data"); + case HAP_CHAR_FORMAT_TLV8: + return json_gen_obj_set_string(jptr, "format", "tlv8"); + default: + break; + } + return HAP_SUCCESS; +} + +static int hap_add_char_type(__hap_char_t *hc, json_gen_str_t *jptr) +{ + return json_gen_obj_set_string(jptr, "type", (char *)hc->type_uuid); +} + +static int hap_add_char_meta(__hap_char_t *hc, json_gen_str_t *jptr) +{ + hap_add_char_format_json(hc, jptr); + + if (hc->constraint_flags & HAP_CHAR_MIN_FLAG) + hap_add_char_val_json(hc->format, "minValue", &hc->min, jptr); + if (hc->constraint_flags & HAP_CHAR_MAX_FLAG) + hap_add_char_val_json(hc->format, "maxValue", &hc->max, jptr); + if (hc->constraint_flags & HAP_CHAR_STEP_FLAG) + hap_add_char_val_json(hc->format, "minStep", &hc->step, jptr); + + /* maxLen and maxDataLen are constraints for "string" and "data" format + * of characteristics, respectively. However, the constraints themselves + * are integers. So, we pass the format as HAP_CHAR_FORMAT_INT + */ + if (hc->constraint_flags & HAP_CHAR_MAXLEN_FLAG) + hap_add_char_val_json(HAP_CHAR_FORMAT_INT, "maxLen", &hc->max, jptr); + if (hc->constraint_flags & HAP_CHAR_MAXDATALEN_FLAG) + hap_add_char_val_json(HAP_CHAR_FORMAT_INT, "maxDataLen", &hc->max, jptr); + + if (hc->description) + json_gen_obj_set_string(jptr, "description", hc->description); + if (hc->unit) + json_gen_obj_set_string(jptr, "unit", hc->unit); + + return HAP_SUCCESS; +} + +static int hap_add_char_perms(__hap_char_t *hc, json_gen_str_t *jptr) +{ + json_gen_push_array(jptr, "perms"); + if (hc->permission & HAP_CHAR_PERM_PR) + json_gen_arr_set_string(jptr, "pr"); + if (hc->permission & HAP_CHAR_PERM_PW) + json_gen_arr_set_string(jptr, "pw"); + if (hc->permission & HAP_CHAR_PERM_EV) + json_gen_arr_set_string(jptr, "ev"); + if (hc->permission & HAP_CHAR_PERM_AA) + json_gen_arr_set_string(jptr, "aa"); + if (hc->permission & HAP_CHAR_PERM_TW) + json_gen_arr_set_string(jptr, "tw"); + if (hc->permission & HAP_CHAR_PERM_HD) + json_gen_arr_set_string(jptr, "hd"); + json_gen_pop_array(jptr); + return HAP_SUCCESS; +} + +static int hap_add_char_ev(__hap_char_t *hc, json_gen_str_t *jptr, uint8_t session_index) +{ + if (hap_char_is_ctrl_subscribed((hap_char_t *)hc, session_index)) { + return json_gen_obj_set_bool(jptr, "ev", true); + } else { + return json_gen_obj_set_bool(jptr, "ev", false); + } +} + +static int hap_add_char_valid_vals(__hap_char_t *hc, json_gen_str_t *jptr) +{ + if (hc->valid_vals) { + json_gen_push_array(jptr, "valid-values"); + int i; + for (i = 0; i < hc->valid_vals_cnt; i++) { + json_gen_arr_set_int(jptr, hc->valid_vals[i]); + } + json_gen_pop_array(jptr); + } + if (hc->valid_vals_range) { + json_gen_push_array(jptr, "valid-values-range"); + json_gen_arr_set_int(jptr, hc->valid_vals_range[0]); + json_gen_arr_set_int(jptr, hc->valid_vals_range[1]); + json_gen_pop_array(jptr); + } + return HAP_SUCCESS; +} + +static int hap_prepare_char_db(__hap_char_t *hc, json_gen_str_t *jptr, int session_index) +{ + json_gen_start_object(jptr); + + json_gen_obj_set_int(jptr, "iid", hc->iid); + + /* If the Update API has not been called from the service read routine, + * reset the owner controller value. + * Else, the controller will miss the next notification. + */ + if (!hc->update_called) { + hc->owner_ctrl = 0; + } + hc->update_called = false; + + if (hc->permission & HAP_CHAR_PERM_PR) { + if (hc->permission & HAP_CHAR_PERM_SPECIAL_READ) { + json_gen_obj_set_null(jptr, "value"); + } else { + hap_add_char_val_json(hc->format, "value", &hc->val, jptr); + } + } + hap_add_char_type(hc, jptr); + hap_add_char_perms(hc, jptr); + hap_add_char_ev(hc, jptr, session_index); + hap_add_char_meta(hc, jptr); + hap_add_char_valid_vals(hc, jptr); + + json_gen_end_object(jptr); + + return HAP_SUCCESS; +} + +static int hap_prepare_serv_db(__hap_serv_t *hs, json_gen_str_t *jptr, int session_index) +{ + json_gen_start_object(jptr); + json_gen_obj_set_int(jptr, "iid", hs->iid); + json_gen_obj_set_string(jptr, "type", hs->type_uuid); + if (hs->hidden) + json_gen_obj_set_bool(jptr, "hidden", "true"); + if (hs->primary) + json_gen_obj_set_bool(jptr, "primary", "true"); + if (hs->linked_servs) { + hap_linked_serv_t *linked = hs->linked_servs; + json_gen_push_array(jptr, "linked"); + while (linked) { + json_gen_arr_set_int(jptr, ((__hap_serv_t *)linked->hs)->iid); + linked = linked->next; + } + json_gen_pop_array(jptr); + } + + json_gen_push_array(jptr, "characteristics"); + int char_cnt = 0; + hap_char_t *hc; + for (hc = hap_serv_get_first_char((hap_serv_t *)hs); hc; hc = hap_char_get_next(hc)) { + if (((__hap_char_t *)hc)->permission & HAP_CHAR_PERM_PR) { + char_cnt++; + } + } + if (char_cnt) { + hap_read_data_t *read_arr = hap_platform_memory_calloc(char_cnt, sizeof(hap_read_data_t)); + if (!read_arr) { + return HAP_FAIL; + } + + hap_status_t *status_codes = hap_platform_memory_calloc(char_cnt, sizeof(hap_status_t)); + if (!status_codes) { + hap_platform_memory_free(read_arr); + return HAP_FAIL; + } + + /* Create an array of characteristics to read, and then read them in one go */ + char_cnt = 0; + for (hc = hap_serv_get_first_char((hap_serv_t *)hs); hc; hc = hap_char_get_next(hc)) { + if (((__hap_char_t *)hc)->permission & HAP_CHAR_PERM_PR) { + hap_char_set_owner_ctrl(hc, session_index); + ((__hap_char_t *)hc)->update_called = false; + read_arr[char_cnt].hc = hc; + status_codes[char_cnt] = HAP_STATUS_SUCCESS; + read_arr[char_cnt].status = &status_codes[char_cnt]; + char_cnt++; + } + } + + hs->bulk_read(&read_arr[0], char_cnt, hs->priv, NULL); + hap_platform_memory_free(read_arr); + hap_platform_memory_free(status_codes); + } + for (hc = hap_serv_get_first_char((hap_serv_t *)hs); hc; hc = hap_char_get_next(hc)) { + hap_prepare_char_db((__hap_char_t *)hc, jptr, session_index); + } + + json_gen_pop_array(jptr); + json_gen_end_object(jptr); + return HAP_SUCCESS; +} + +static int hap_prepare_acc_db(__hap_acc_t *ha, json_gen_str_t *jptr, int session_index) +{ + json_gen_start_object(jptr); + json_gen_obj_set_int(jptr, "aid", ha->aid); + json_gen_push_array(jptr, "services"); + hap_serv_t *hs; + for (hs = hap_acc_get_first_serv((hap_acc_t *)ha); hs; hs = hap_serv_get_next(hs)) { + hap_prepare_serv_db((__hap_serv_t *)hs, jptr, session_index); + } + json_gen_pop_array(jptr); + json_gen_end_object(jptr); + return HAP_SUCCESS; +} + +static int hap_prepare_json_database(char *buf, int bufsize, json_gen_flush_cb_t flush_cb, httpd_req_t *req) +{ + if (!req) { + return HAP_FAIL; + } + hap_secure_session_t *session = (hap_secure_session_t *)hap_platform_httpd_get_sess_ctx(req); + if (!session) { + return HAP_FAIL; + } + json_gen_str_t jstr; + json_gen_str_start(&jstr, buf, bufsize, flush_cb, req); + json_gen_start_object(&jstr); + json_gen_push_array(&jstr, "accessories"); + hap_acc_t *ha; + for (ha = hap_get_first_acc(); ha; ha = hap_acc_get_next(ha)) { + hap_prepare_acc_db((__hap_acc_t *)ha, &jstr, hap_get_ctrl_session_index(session)); + } + json_gen_pop_array(&jstr); + json_gen_end_object(&jstr); + json_gen_str_end(&jstr); + return HAP_SUCCESS; +} + +static void hap_http_json_flush_chunk(char *data, void *priv) +{ + ESP_MFI_DEBUG_PLAIN("%s", data); + httpd_resp_send_chunk((httpd_req_t *)priv, data, strlen(data)); +} + +static int hap_http_get_accessories(httpd_req_t *req) +{ + char buf[1000]; + ESP_MFI_DEBUG_PLAIN("Socket fd: %d; HTTP Request %s %s\n", httpd_req_to_sockfd(req), hap_platform_httpd_get_req_method(req), hap_platform_httpd_get_req_uri(req)); + hap_secure_session_t *session = (hap_secure_session_t *)hap_platform_httpd_get_sess_ctx(req); + if (!hap_is_req_secure(session)) { + return hap_http_session_not_authorized(req); + } + httpd_resp_set_type(req, "application/hap+json"); + ESP_MFI_DEBUG_PLAIN("Generating HTTP Response\n"); + /* Using chunked encoding since the response can be large, especially for bridges */ + hap_prepare_json_database(buf, sizeof(buf), hap_http_json_flush_chunk, req); + /* This indicates the last chunk */ + httpd_resp_send_chunk(req, NULL, 0); + ESP_MFI_DEBUG_PLAIN("\n"); + + hap_report_event(HAP_EVENT_GET_ACC_COMPLETED, NULL, 0); + return HAP_SUCCESS; +} +static struct httpd_uri hap_accessories = { + .uri = "/accessories", + .method = HTTP_GET, + .handler = hap_http_get_accessories, +}; + +static void hap_set_char_report_status(bool *include_status, json_gen_str_t *jstr, + int aid, int iid, int status) +{ + if (!*include_status) { + json_gen_start_object(jstr); + json_gen_push_array(jstr, "characteristics"); + *include_status = true; + } + json_gen_start_object(jstr); + json_gen_obj_set_int(jstr, "aid", aid); + json_gen_obj_set_int(jstr, "iid", iid); + json_gen_obj_set_int(jstr, "status", status); + json_gen_end_object(jstr); +} + +static int hap_http_handle_set_char(jparse_ctx_t *jctx, char *outbuf, int buf_size, + httpd_req_t *req) +{ + int cnt = 0, char_cnt = 0, i; + bool include_status = false; + uint64_t pid; + bool valid_tw = false; + bool req_tw = false; + hap_secure_session_t *session = (hap_secure_session_t *)hap_platform_httpd_get_sess_ctx(req); + if (!session) + return HAP_FAIL; + + int64_t cur_time = esp_timer_get_time() / 1000; + int64_t prepare_time = session->prepare_time; + if (prepare_time) { + /* If prepare time is non zero, it means that a prepare was received + * before this request, and so this write needs to be timed write + */ + req_tw = true; + /* Reset prepare_time to 0, since a prepare is valid only for the immediate + * following write + */ + session->prepare_time = 0; + } + if (json_obj_get_int64(jctx, "pid", (int64_t *)&pid) == OS_SUCCESS) { + /* If the pid value is present, this must be a timed write. + * However, if there was no preceding prepare, the check below will + * fail (as ttl will be 0) and appropriate error will be reported subsequently + */ + req_tw = true; + if ((pid == session->pid) && ((cur_time - prepare_time) <= session->ttl)) { + valid_tw = true; + } + } + /* Resetting the values so that the session is ready for next prepare or write */ + session->pid = 0; + session->ttl = 0; + + json_obj_get_array(jctx, "characteristics", &cnt); + if (cnt <= 0) + return HAP_FAIL; + + hap_write_data_t *write_arr = hap_platform_memory_calloc(cnt, sizeof(hap_write_data_t)); + hap_status_t *status_arr = hap_platform_memory_calloc(cnt, sizeof(hap_status_t)); + if (!write_arr || !status_arr) + goto set_char_end; + + json_gen_str_t jstr; + json_gen_str_start(&jstr, outbuf, buf_size, hap_http_json_flush_chunk, req); + /* Dummy get, so that the loop can start by leaving the previous + * object and getting newer one + */ + json_arr_get_object(jctx, 0); + /* Loop through all characteristic objects {aid,iid,value}, handle + * errors if any, and if there are no errors, put the characteristic + * pointer and value in an array (with char_cnt) + */ + for (i = 0; i < cnt; i++) { + /* Leave the previous object and get a newer one from the array */ + json_arr_leave_object(jctx); + int aid = 0, iid = 0; + json_arr_get_object(jctx, i); + json_obj_get_int(jctx, "aid", &aid); + json_obj_get_int(jctx, "iid", &iid); + hap_acc_t *ha = hap_acc_get_by_aid(aid); + __hap_char_t *hc = (__hap_char_t *)hap_acc_get_char_by_iid(ha, iid); + if (!ha || !hc) { + hap_set_char_report_status(&include_status, &jstr, + aid, iid, HAP_STATUS_RES_ABSENT); + continue; + } + + /* If the previous request was a prepare, but the current + * one was not a valid timed write, report error. + */ + if (req_tw == true && valid_tw == false) { + hap_set_char_report_status(&include_status, &jstr, + aid, iid, HAP_STATUS_VAL_INVALID); + continue; + } + + /* For characteristic that require a Mandatory Timed Write, return + * error if this write is not a valid timed write + */ + if (hc->permission & HAP_CHAR_PERM_TW) { + if (valid_tw == false) { + hap_set_char_report_status(&include_status, &jstr, + aid, iid, HAP_STATUS_VAL_INVALID); + continue; + } + } + + /* Check if this write is just to enable/disable event notifications. + * This is valid even for read-only characteristics that support event + * notifications (like sensor readings), so we do not check the HAP_CHAR_PERM_PW + * here. + */ + bool ev; + if (json_obj_get_bool(jctx, "ev", &ev) == HAP_SUCCESS) { + if (hc->permission & HAP_CHAR_PERM_EV) { + int index = hap_get_ctrl_session_index(session); + hap_char_manage_notification((hap_char_t *)hc, index, ev); + ESP_MFI_DEBUG(ESP_MFI_DEBUG_INFO, "Events %s for aid=%d iid=%d", + ev ? "Enabled" : "Disabled", aid, iid); + } else { + hap_set_char_report_status(&include_status, &jstr, + aid, iid, HAP_STATUS_NO_NOTIF); + } + continue; + } + + /* Check if the characteristic has write permission */ + if (!(hc->permission & HAP_CHAR_PERM_PW)) { + hap_set_char_report_status(&include_status, &jstr, + aid, iid, HAP_STATUS_WR_ON_RDONLY); + continue; + } + + /* Check if the characteristic needs Authorization Data. + * Actual authData value will be read later. + */ + if (hc->permission & HAP_CHAR_PERM_AA) { + int tmp_len; + if (json_obj_get_strlen(jctx, "authData", &tmp_len) != HAP_SUCCESS) { + hap_set_char_report_status(&include_status, &jstr, + aid, iid, HAP_STATUS_INSUFFICIENT_AUTH); + continue; + } + } + /* If there is no write routine registered, there is no point of having + * this write request. Return an error. + */ + if (!((__hap_serv_t *)(hap_char_get_parent((hap_char_t *)hc)))->write_cb) { + hap_set_char_report_status(&include_status, &jstr, + aid, iid, HAP_STATUS_VAL_INVALID); + continue; + } + + hap_auth_data_t auth_data = { + .data = NULL, + .len = 0, + }; + hap_val_t val; + int json_ret = HAP_FAIL; + switch (hc->format) { + case HAP_CHAR_FORMAT_BOOL: + json_ret = json_obj_get_bool(jctx, "value", &val.b); + break; + case HAP_CHAR_FORMAT_UINT8: + case HAP_CHAR_FORMAT_UINT16: + case HAP_CHAR_FORMAT_UINT32: + case HAP_CHAR_FORMAT_INT: + json_ret = json_obj_get_int(jctx, "value", &val.i); + break; + case HAP_CHAR_FORMAT_FLOAT: + json_ret = json_obj_get_float(jctx, "value", &val.f); + break; + case HAP_CHAR_FORMAT_STRING: { + int str_len = 0; + json_ret = json_obj_get_strlen(jctx, "value", &str_len); + if (json_ret == HAP_SUCCESS) { + /* Increment string length, for NULL termination byte */ + str_len++; + val.s = hap_platform_memory_calloc(str_len, 1); + if (!val.s) { + hap_set_char_report_status(&include_status, &jstr, + aid, iid, HAP_STATUS_OO_RES); + continue; + } + json_obj_get_string(jctx, "value", val.s, str_len); + } + break; + } + case HAP_CHAR_FORMAT_DATA: + case HAP_CHAR_FORMAT_TLV8: { + int str_len = 0; + json_ret = json_obj_get_strlen(jctx, "value", &str_len); + if (json_ret == HAP_SUCCESS) { + val.d.buf = hap_platform_memory_calloc(1, str_len + 1); + if (!val.d.buf) { + hap_set_char_report_status(&include_status, &jstr, + aid, iid, HAP_STATUS_OO_RES); + continue; + } + val.d.buflen = str_len + 1; + json_obj_get_string(jctx, "value", (char *)val.d.buf, val.d.buflen); + if (esp_mfi_base64_decode((const char *)val.d.buf, strlen((char *)val.d.buf), + (char *)val.d.buf, val.d.buflen, (int *)&val.d.buflen) != 0) { + hap_platform_memory_free(val.d.buf); + hap_set_char_report_status(&include_status, &jstr, + aid, iid, HAP_STATUS_VAL_INVALID); + continue; + } + } + break; + } + default: + json_ret = HAP_FAIL; + } + if (json_ret != HAP_SUCCESS) { + hap_set_char_report_status(&include_status, &jstr, + aid, iid, HAP_STATUS_VAL_INVALID); + continue; + } + + /* Check if the value is within constraints */ + if (hap_char_check_val_constraints(hc, &val) != HAP_SUCCESS) { + hap_set_char_report_status(&include_status, &jstr, + aid, iid, HAP_STATUS_VAL_INVALID); + continue; + } + + if (json_obj_get_strlen(jctx, "authData", &auth_data.len) == HAP_SUCCESS) { + auth_data.data = hap_platform_memory_calloc(1, auth_data.len + 1); + json_obj_get_string(jctx, "authData", (char *)auth_data.data, auth_data.len + 1); + esp_mfi_base64_decode((const char *)auth_data.data, auth_data.len, (char *)auth_data.data, auth_data.len + 1, &auth_data.len); + } + bool remote = false; + json_obj_get_bool(jctx, "remote", &remote); + + int index = hap_get_ctrl_session_index(session); + hap_char_set_owner_ctrl((hap_char_t *)hc, index); + /* No errors in the object data itself. Save the characteristic + * pointer and value, to be used later + */ + write_arr[char_cnt].hc = (hap_char_t *)hc; + write_arr[char_cnt].val = val; + write_arr[char_cnt].auth_data = auth_data; + write_arr[char_cnt].remote = remote; + write_arr[char_cnt].status = &status_arr[char_cnt]; + char_cnt++; + } + if (!char_cnt) + goto set_char_end; + + /* The logic here is to loop through all the saved characteristic + * pointers, and invoke a single write callback for all consecutive + * characteristics of the same service. + * The write callback will be invoked if the service changes or + * if the last characteristic in the array is reached + */ + int hs_index = 0; + bool write_err = false; + __hap_serv_t *hs = (__hap_serv_t *)hap_char_get_parent(write_arr[0].hc); + /* The counter here will go till char_cnt instead of char_cnt - 1. + * When i == char_cnt, it will mean that all elements in the array + * have been looped through. + * So, last iteration will invoke the write callback for the last + * set of characteritics. + */ + for (i = 0; i <= char_cnt; i++) { + if ((i < char_cnt) && ((hap_serv_t *)hs == hap_char_get_parent(write_arr[i].hc))) + continue; + else { + /* Passing the pointers to the first elements of the array + * for a given service (indicated by hs_index). + * Number of elements of the array are indicated by + * i - hs_index + */ + if (hs->write_cb(&write_arr[hs_index], i - hs_index, + hs->priv, hap_platform_httpd_get_sess_ctx(req)) != HAP_SUCCESS) + write_err = true; + if (i < char_cnt) { + hs = (__hap_serv_t *)hap_char_get_parent(write_arr[i].hc); + hs_index = i; + } + } + } + if (write_err || include_status) { + for (i = 0; i < char_cnt; i++) { + /* TODO: The code to get aid looks complex. Simplify */ + hap_set_char_report_status(&include_status, &jstr, + ((__hap_acc_t *)hap_serv_get_parent(hap_char_get_parent(write_arr[i].hc)))->aid, + ((__hap_char_t *)(write_arr[i].hc))->iid, *write_arr[i].status); + } + } + + int ret = HAP_SUCCESS; +set_char_end: + if (include_status) { + json_gen_pop_array(&jstr); + json_gen_end_object(&jstr); + json_gen_str_end(&jstr); + ret = HAP_FAIL; + } + + if (write_arr) { + for (i = 0; i < char_cnt; i++) { + if (((__hap_char_t *)write_arr[i].hc)->format == HAP_CHAR_FORMAT_STRING) { + if (write_arr[i].val.s) { + hap_platform_memory_free(write_arr[i].val.s); + } + } else if ((((__hap_char_t *)write_arr[i].hc)->format == HAP_CHAR_FORMAT_DATA) || + (((__hap_char_t *)write_arr[i].hc)->format == HAP_CHAR_FORMAT_TLV8)) { + hap_platform_memory_free(write_arr[i].val.d.buf); + } + if (write_arr[i].auth_data.data) { + hap_platform_memory_free(write_arr[i].auth_data.data); + } + } + } + if (write_arr) + hap_platform_memory_free(write_arr); + if (status_arr) + hap_platform_memory_free(status_arr); + return ret; +} + +static int hap_http_put_characteristics(httpd_req_t *req) +{ + char stack_inbuf[512] = {0}; + char outbuf[512] = {0}; + char *heap_inbuf = NULL; + char *inbuf = stack_inbuf; + + ESP_MFI_DEBUG_PLAIN("Socket fd: %d; HTTP Request %s %s\n", httpd_req_to_sockfd(req), hap_platform_httpd_get_req_method(req), hap_platform_httpd_get_req_uri(req)); + hap_secure_session_t *session = (hap_secure_session_t *)hap_platform_httpd_get_sess_ctx(req); + if (!hap_is_req_secure(session)) { + return hap_http_session_not_authorized(req); + } + + /* If received content is larger than the buffer on stack, allocate one from heap. + * This will mostly be required only in case of bridges, wherein there could be a request to + * control all/many accessories at once. + */ + int content_len = hap_platform_httpd_get_content_len(req); + if (content_len > sizeof(stack_inbuf)) { + heap_inbuf = hap_platform_memory_calloc(content_len + 1, 1); /* Allocating an extra byte for NULL termination */ + if (!heap_inbuf) { + ESP_MFI_DEBUG(ESP_MFI_DEBUG_ERR, "Failed to read HTTPD Data"); + httpd_resp_set_status(req, HTTPD_500); + return httpd_resp_send(req, NULL, 0); + } + ESP_MFI_DEBUG(ESP_MFI_DEBUG_INFO, "Allocated buffer of size %d for the large PUT", + content_len + 1) + inbuf = heap_inbuf; + } + int data_len = hap_httpd_get_data(req, inbuf, content_len); + if (data_len < 0) { + ESP_MFI_DEBUG(ESP_MFI_DEBUG_ERR, "Failed to read HTTPD Data"); + httpd_resp_set_status(req, HTTPD_500); + if (heap_inbuf) { + hap_platform_memory_free(heap_inbuf); + ESP_MFI_DEBUG(ESP_MFI_DEBUG_INFO, "Freed allocated buffer for PUT"); + } + return httpd_resp_send(req, NULL, 0); + } + ESP_MFI_DEBUG_PLAIN("Data Received: %s\n", inbuf); + jparse_ctx_t jctx; + if (json_parse_start(&jctx, inbuf, data_len) != HAP_SUCCESS) { + ESP_MFI_DEBUG(ESP_MFI_DEBUG_ERR, "Failed to parse HTTPD JSON Data"); + httpd_resp_set_status(req, HTTPD_500); + if (heap_inbuf) { + hap_platform_memory_free(heap_inbuf); + ESP_MFI_DEBUG(ESP_MFI_DEBUG_INFO, "Freed allocated buffer for PUT"); + } + return httpd_resp_send(req, NULL, 0); + } + + httpd_resp_set_type(req, "application/hap+json"); + /* Setting response type to indicate error. + * This will be actually sent out only if there is some error + * to be reported while handling the characteristic writes. + * Else, the response type will be set to 204 + */ + httpd_resp_set_status(req, HTTPD_207); + if (hap_http_handle_set_char(&jctx, outbuf, sizeof(outbuf), req) == HAP_SUCCESS) + { + snprintf(outbuf, sizeof(outbuf), "HTTP/1.1 %s\r\n\r\n", HTTPD_204); + httpd_send(req, outbuf, strlen(outbuf)); + } else { + /* If a failure was encountered, it would mean that a response has been generated, + * which will be chunk encoded. So, sending the last chunk here and also printing + * a new line to end the prints of the error string. + */ + httpd_resp_send_chunk(req, NULL, 0); + ESP_MFI_DEBUG_PLAIN("\n"); + } + json_parse_end(&jctx); + + if (heap_inbuf) { + hap_platform_memory_free(heap_inbuf); + ESP_MFI_DEBUG(ESP_MFI_DEBUG_INFO, "Freed allocated buffer for PUT"); + } + + hap_report_event(HAP_EVENT_SET_CHAR_COMPLETED, NULL, 0); + return HAP_SUCCESS; +} + +static bool hap_get_bool_url_param(char *query_str, char *key) +{ + char val[6]; /* Max string will be "false" */ + if (httpd_query_key_value(query_str, key, val, sizeof(val)) == HAP_SUCCESS) { + if (!strcmp(val, "true") || !strcmp(val, "1")) + return true; + } + return false; +} + +static int hap_http_get_characteristics(httpd_req_t *req) +{ + char outbuf[512]; + char stack_val_buf[512] = {0}; + char *heap_val_buf = NULL; + char *val = stack_val_buf; + + ESP_MFI_DEBUG_PLAIN("Socket fd: %d; HTTP Request %s %s\n", httpd_req_to_sockfd(req), hap_platform_httpd_get_req_method(req), hap_platform_httpd_get_req_uri(req)); + + hap_secure_session_t *session = (hap_secure_session_t *)hap_platform_httpd_get_sess_ctx(req); + if (!hap_is_req_secure(session)) { + return hap_http_session_not_authorized(req); + } + const char *uri = hap_platform_httpd_get_req_uri(req); + /* Allocate on heap, if URI is longer */ + if (strlen(uri) > sizeof(stack_val_buf)) { + heap_val_buf = hap_platform_memory_calloc(strlen(uri) + 1, 1); /* Allocating an extra byte for NULL termination */ + if (!heap_val_buf) { + ESP_MFI_DEBUG(ESP_MFI_DEBUG_ERR, "Failed to read URL"); + httpd_resp_set_status(req, HTTPD_500); + return httpd_resp_send(req, NULL, 0); + } + ESP_MFI_DEBUG(ESP_MFI_DEBUG_INFO, "Allocated buffer of size %d for the large GET", + strlen(uri) + 1) + val = heap_val_buf; + } + size_t url_query_str_len = httpd_req_get_url_query_len(req); + char * url_query_str = hap_platform_memory_calloc(1, url_query_str_len + 1); + if (!url_query_str) { + httpd_resp_set_status(req, HTTPD_400); + httpd_resp_set_type(req, "application/hap+json"); + snprintf(outbuf, sizeof(outbuf),"{\"status\":-70409}"); + httpd_resp_send(req, outbuf, strlen(outbuf)); + goto get_char_return; + } + httpd_req_get_url_query_str(req, url_query_str, url_query_str_len + 1); + /* Check for all the optional URL query paramaters */ + bool meta = hap_get_bool_url_param(url_query_str, "meta"); + bool perms = hap_get_bool_url_param(url_query_str, "perms"); + bool type = hap_get_bool_url_param(url_query_str, "type"); + bool ev = hap_get_bool_url_param(url_query_str, "ev"); + + /* Check for the mandatory "id" URL query parameter. + * If not found, return success + */ + if (httpd_query_key_value(url_query_str, "id", val, strlen(uri) + 1) != HAP_SUCCESS) { + httpd_resp_set_status(req, HTTPD_400); + httpd_resp_set_type(req, "application/hap+json"); + snprintf(outbuf, sizeof(outbuf),"{\"status\":-70409}"); + httpd_resp_send(req, outbuf, strlen(outbuf)); + goto get_char_return; + } + + /* Get the total count of characteristics in the request. This will be + * required to decide the size of the characteristic pointers' array + */ + int char_cnt = 0; + char *val_ptr = val; + /* We do not do any error checking here and just assume that the id + * tag has a characteristic list which is a comma separated list + * of . elements + */ + char *p = strsep(&val_ptr, ","); + while (p) { + char_cnt++; + p = strsep(&val_ptr, ","); + } + + /* Normally, it would have been fine to just go on parsing the + * characteristics in the URL, fetch their values and prepare + * the response. However, if there is error for any characteristic + * a "status" field needs to be added for all characteristics. + * + * So, it is better to maintain a list of characteristics pointers, + * read all the values, and only then create the response + */ + hap_read_data_t *read_arr = hap_platform_memory_calloc(char_cnt, sizeof(hap_read_data_t)); + if (!read_arr) { + httpd_resp_set_status(req, HTTPD_500); + httpd_resp_set_type(req, "application/hap+json"); + snprintf(outbuf, sizeof(outbuf),"{\"status\":-70407}"); + httpd_resp_send(req, outbuf, strlen(outbuf)); + goto get_char_return; + } + hap_status_t *status_codes = hap_platform_memory_calloc(char_cnt, sizeof(hap_status_t)); + if (!status_codes) { + hap_platform_memory_free(read_arr); + httpd_resp_set_status(req, HTTPD_500); + httpd_resp_set_type(req, "application/hap+json"); + snprintf(outbuf, sizeof(outbuf),"{\"status\":-70407}"); + httpd_resp_send(req, outbuf, strlen(outbuf)); + goto get_char_return; + } + + ESP_MFI_DEBUG_PLAIN("Generating HTTP Response\n"); + /* Generate the JSON response */ + bool include_status = 0; + httpd_resp_set_status(req, HTTPD_207); + httpd_resp_set_type(req, "application/hap+json"); + json_gen_str_t jstr; + json_gen_str_start(&jstr, outbuf, sizeof(outbuf), hap_http_json_flush_chunk, req); + + /* Get the ids once again. Not checking for success since that + * would be redundant + */ + httpd_query_key_value(url_query_str, "id", val, strlen(uri) + 1); + char_cnt = 0; + int aid, iid; + val_ptr = val; + /* Parse the AIDs and IIDs in the "id" field and fetch the + * characteristic pointer for each + */ + p = strsep(&val_ptr, "."); + while (p) { + aid = atoi(p); + p = strsep(&val_ptr, ","); + iid = atoi(p); + p = strsep(&val_ptr, "."); + hap_char_t *hc = hap_acc_get_char_by_iid(hap_acc_get_by_aid(aid), iid); + if (!hc) { + hap_set_char_report_status(&include_status, &jstr, + aid, iid, HAP_STATUS_RES_ABSENT); + continue; + } + if (!(((__hap_char_t *)hc)->permission & HAP_CHAR_PERM_PR)) { + hap_set_char_report_status(&include_status, &jstr, + aid, iid, HAP_STATUS_RD_ON_WRONLY); + continue; + } + hap_char_set_owner_ctrl(hc, hap_get_ctrl_session_index(session)); + ((__hap_char_t *)hc)->update_called = false; + /* Add the characteristic to the read array */ + read_arr[char_cnt].hc = hc; + status_codes[char_cnt] = HAP_STATUS_SUCCESS; + read_arr[char_cnt].status = &status_codes[char_cnt]; + char_cnt++; + } + + if (!char_cnt) { + goto get_char_end; + } + + + int hs_index = 0; + bool read_err = false; + __hap_serv_t *hs = (__hap_serv_t *)hap_char_get_parent(read_arr[0].hc); + /* Read all the values first, before preparing the response, so that it + * would be known in advance, if any read error is encountered + */ + int i; + /* The counter here will go till char_cnt instead of char_cnt - 1. + * When i == char_cnt, it will mean that all elements in the array + * have been looped through. + * So, last iteration will invoke the read callback for the last + * set of characteritics. + */ + for (i = 0; i <= char_cnt; i++) { + if ((i < char_cnt) && ((hap_serv_t *)hs == hap_char_get_parent(read_arr[i].hc))) + continue; + else { + /* Passing the pointers to the first elements of the array + * for a given service (indicated by hs_index). + * Number of elements of the array are indicated by + * i - hs_index + */ + if (hs->bulk_read(&read_arr[hs_index], i - hs_index, hs->priv, hap_platform_httpd_get_sess_ctx(req)) != HAP_SUCCESS) + read_err = true; + if (i < char_cnt) { + hs = (__hap_serv_t *)hap_char_get_parent(read_arr[i].hc); + hs_index = i; + } + } + } + if (!include_status) { + if (!read_err) { + /* If "include_status" is false, it means there + * were no errors. + * So, set response type to 200 OK + */ + httpd_resp_set_status(req, HTTPD_200); + } + json_gen_start_object(&jstr); + json_gen_push_array(&jstr, "characteristics"); + } + /* Loop through the characteristics and include their data + */ + for (i = 0; i < char_cnt; i++) { + __hap_char_t *hc = (__hap_char_t *)read_arr[i].hc; + /* If the Update API has not been called from the service read routine, + * reset the owner controller value. + * Else, the controller will miss the next notification. + */ + if (!hc->update_called) { + hc->owner_ctrl = 0; + } + hc->update_called = false; + + json_gen_start_object(&jstr); + __hap_acc_t *ha = (__hap_acc_t *)hap_serv_get_parent(hc->parent); + json_gen_obj_set_int(&jstr, "aid", ha->aid); + json_gen_obj_set_int(&jstr, "iid", hc->iid); + + if (hc->permission & HAP_CHAR_PERM_SPECIAL_READ) { + json_gen_obj_set_null(&jstr, "value"); + } else { + /* Include "value" only if status is SUCCESS */ + if (*read_arr[i].status == HAP_STATUS_SUCCESS) { + hap_add_char_val_json(hc->format, "value", &hc->val, &jstr); + } + } + /* Include status only if it was already included because of + * some parsing errors, or if an error was encountered while + * actually reading the characteristics. + */ + if (include_status || read_err) { + json_gen_obj_set_int(&jstr, "status", *read_arr[i].status); + } + if (type) + hap_add_char_type(hc, &jstr); + if (perms) + hap_add_char_perms(hc, &jstr); + if (ev) { + hap_add_char_ev(hc, &jstr, hap_get_ctrl_session_index(session)); + } + if (meta) + hap_add_char_meta(hc, &jstr); + json_gen_end_object(&jstr); + } +get_char_end: + json_gen_pop_array(&jstr); + json_gen_end_object(&jstr); + json_gen_str_end(&jstr); + + hap_platform_memory_free(read_arr); + hap_platform_memory_free(status_codes); + + /* This indicates the last chunk */ + httpd_resp_send_chunk(req, NULL, 0); + ESP_MFI_DEBUG_PLAIN("\n"); +get_char_return: + if (heap_val_buf) { + hap_platform_memory_free(heap_val_buf); + ESP_MFI_DEBUG(ESP_MFI_DEBUG_INFO, "Freed allocated buffer for GET"); + } + + if (url_query_str) { + hap_platform_memory_free(url_query_str); + } + + hap_report_event(HAP_EVENT_GET_CHAR_COMPLETED, NULL, 0); + return HAP_SUCCESS; +} +static struct httpd_uri hap_characteristics_get = { + .uri = "/characteristics", + .method = HTTP_GET, + .handler = hap_http_get_characteristics, +}; +static struct httpd_uri hap_characteristics_put = { + .uri = "/characteristics", + .method = HTTP_PUT, + .handler = hap_http_put_characteristics, +}; + +static int hap_http_pairings_handler(httpd_req_t *req) +{ + uint8_t buf[2048]; /* Large buffer to accommodate 16 pairings list */ + void *ctx = hap_platform_httpd_get_sess_ctx(req); + ESP_MFI_DEBUG_PLAIN("Socket fd: %d; HTTP Request %s %s\n", httpd_req_to_sockfd(req), hap_platform_httpd_get_req_method(req), hap_platform_httpd_get_req_uri(req)); + int data_len = httpd_req_recv(req, (char *)buf, sizeof(buf)); + int outlen; + hap_secure_session_t *session = (hap_secure_session_t *)ctx; + if (!hap_is_req_secure(session)) { + /* Only setting the HTTP status here. Actual error TLV will be added + * by the hap_pairings_process() call + */ + httpd_resp_set_status(req, "470 Connection Authorization Required"); + } + hap_pairings_process(ctx, buf, data_len, sizeof(buf), &outlen); + httpd_resp_set_type(req, "application/pairing+tlv8"); + return httpd_resp_send(req, (char *)buf, outlen); +} +static struct httpd_uri hap_pairings = { + .uri = "/pairings", + .method = HTTP_POST, + .handler = hap_http_pairings_handler, +}; + +static int hap_http_post_identify(httpd_req_t *req) +{ + char buf[100]; + ESP_MFI_DEBUG_PLAIN("Socket fd: %d\nHTTP Request %s %s\n", httpd_req_to_sockfd(req), hap_platform_httpd_get_req_method(req), hap_platform_httpd_get_req_uri(req)); + if (is_accessory_paired()) { + httpd_resp_set_status(req, HTTPD_400); + httpd_resp_set_type(req, "application/hap+json"); + snprintf(buf, sizeof(buf),"{\"status\":-70401}"); + httpd_resp_send(req, buf, strlen(buf)); + } else { + hap_acc_t *ha = hap_get_first_acc(); + __hap_acc_t *_ha = (__hap_acc_t *)ha; + _ha->identify_routine(ha); + snprintf(buf, sizeof(buf), "HTTP/1.1 %s\r\n\r\n", HTTPD_204); + httpd_send(req, buf, strlen(buf)); + } + return HAP_SUCCESS; +} + +static struct httpd_uri hap_identify = { + .uri = "/identify", + .method = HTTP_POST, + .handler = hap_http_post_identify, +}; + +static int hap_http_put_prepare(httpd_req_t *req) +{ + char buf[512] = {0}; + + ESP_MFI_DEBUG_PLAIN("Socket fd: %d; HTTP Request %s %s\n", httpd_req_to_sockfd(req), hap_platform_httpd_get_req_method(req), hap_platform_httpd_get_req_uri(req)); + hap_secure_session_t *session = (hap_secure_session_t *)hap_platform_httpd_get_sess_ctx(req); + if (!hap_is_req_secure(session)) { + return hap_http_session_not_authorized(req); + } + int data_len = httpd_req_recv(req, (char *)buf, sizeof(buf)); + if (data_len < 0) { + ESP_MFI_DEBUG(ESP_MFI_DEBUG_ERR, "Failed to read HTTPD Data"); + httpd_resp_set_status(req, HTTPD_500); + return httpd_resp_send(req, NULL, 0); + } + ESP_MFI_DEBUG_PLAIN("Data Received: %s\n", buf); + jparse_ctx_t jctx; + if (json_parse_start(&jctx, buf, data_len) != HAP_SUCCESS) { + ESP_MFI_DEBUG(ESP_MFI_DEBUG_ERR, "Failed to parse HTTPD JSON Data"); + httpd_resp_set_status(req, HTTPD_500); + return httpd_resp_send(req, NULL, 0); + } + + httpd_resp_set_type(req, "application/hap+json"); + uint64_t pid; + int64_t ttl; + if ((json_obj_get_int64(&jctx, "pid", (int64_t *)&pid) != OS_SUCCESS) || + (json_obj_get_int64(&jctx, "ttl", &ttl) != OS_SUCCESS)) { + snprintf(buf, sizeof(buf),"{\"status\":-70410}"); + } else { + session->pid = pid; + session->ttl = ttl; + session->prepare_time = esp_timer_get_time() / 1000; /* Set current time in msec */ + snprintf(buf, sizeof(buf),"{\"status\":0}"); + } + json_parse_end(&jctx); + httpd_resp_send(req, buf, strlen(buf)); + return HAP_SUCCESS; +} + +static struct httpd_uri hap_prepare = { + .uri = "/prepare", + .method = HTTP_PUT, + .handler = hap_http_put_prepare, +}; + +static void hap_send_notification(void *arg) +{ + int num_char = hap_priv.cfg.max_event_notif_chars; + hap_char_t *hc; + hap_char_t **char_arr = hap_platform_memory_calloc(num_char, sizeof(hap_char_t *)); + + if (!char_arr) { + return; + } + + int i, num_notif_chars; + for (i = 0; i < num_char; i++) { + hc = hap_get_pending_notif_char(); + if (hc) { + char_arr[i] = hc; + } else { + break; + } + } + /* If no characteristic notifications are pending, free char_arr and exit */ + if (i == 0) { + hap_platform_memory_free(char_arr); + return; + } + num_notif_chars = i; + hap_secure_session_t *session; + /* Flag to indicate if any controller was connected */ + bool ctrl_connected = false; + char buf[250]; + for (i = 0; i < HAP_MAX_SESSIONS; i++) { + session = hap_priv.sessions[i]; + if (!session) + continue; + ctrl_connected = true; + int fd = session->conn_identifier; +#define HTTPD_HDR_STR "EVENT/1.0 200 OK\r\n" \ + "Content-Type: application/hap+json\r\n" \ + "Content-Length: %d\r\n" + char notif_json[1024]; + json_gen_str_t jstr; + json_gen_str_start(&jstr, notif_json, sizeof(notif_json), NULL, NULL); + json_gen_start_object(&jstr); + json_gen_push_array(&jstr, "characteristics"); + + int j; + bool notif_to_send = false; + for (j = 0; j < num_notif_chars; j++) { + hc = char_arr[j]; + __hap_char_t *_hc = ( __hap_char_t *)hc; + /* If the controller is the owner, dont send notification to it */ + if (hap_char_is_ctrl_owner(hc, i)) { + /* Since there can be only one owner, which we are anyways skipping, + * we can reset owner value to 0 + */ + _hc->owner_ctrl = 0; + continue; + } + if (!hap_char_is_ctrl_subscribed(hc, i)) + continue; + + json_gen_start_object(&jstr); + hap_acc_t *ha = hap_serv_get_parent(hap_char_get_parent(hc)); + int aid = ((__hap_acc_t *)ha)->aid; + json_gen_obj_set_int(&jstr, "aid", aid); + json_gen_obj_set_int(&jstr, "iid", _hc->iid); + hap_add_char_val_json(_hc->format, "value", &_hc->val, &jstr); + json_gen_end_object(&jstr); + notif_to_send = true; + } + if (!notif_to_send) { + /* No notification required for this controller. Just continue */ + continue; + } + + json_gen_pop_array(&jstr); + json_gen_end_object(&jstr); + json_gen_str_end(&jstr); + + snprintf(buf, sizeof(buf), HTTPD_HDR_STR, + strlen(notif_json)); + hap_httpd_send(hap_priv.server, fd, buf, strlen(buf), 0); + /* Space for sending additional headers based on set_header */ + hap_httpd_send(hap_priv.server, fd, "\r\n", strlen("\r\n"), 0); + hap_httpd_send(hap_priv.server, fd, notif_json, strlen(notif_json), 0); + httpd_sess_update_lru_counter(hap_priv.server, fd); + ESP_MFI_DEBUG(ESP_MFI_DEBUG_INFO, "Notification Sent"); + ESP_MFI_DEBUG_PLAIN("Socket fd: %d; Event message: %s\n", fd, notif_json); + } + /* If no controller was connected and no disconnected event was sent, + * reannaounce mDNS. That will increment state number as required + * by HAP Spec R15. + */ + if (!ctrl_connected && !hap_priv.disconnected_event_sent) { + hap_mdns_announce(false); + hap_priv.disconnected_event_sent = true; + } + hap_platform_memory_free(char_arr); +} + +void hap_http_debug_enable() +{ + http_debug = true; +} + +void hap_http_debug_disable() +{ + http_debug = false; +} + +void hap_http_send_notif() +{ + httpd_queue_work(hap_priv.server, hap_send_notification, NULL); +} + +static bool hap_http_registered; +int hap_register_http_handlers() +{ + if (!hap_http_registered) { + ESP_MFI_DEBUG(ESP_MFI_DEBUG_INFO, "Registering HomeKit web handlers"); + httpd_register_uri_handler(hap_priv.server, &hap_pair_setup); + httpd_register_uri_handler(hap_priv.server, &hap_pair_verify); + httpd_register_uri_handler(hap_priv.server, &hap_pairings); + httpd_register_uri_handler(hap_priv.server, &hap_accessories); + httpd_register_uri_handler(hap_priv.server, &hap_characteristics_get); + httpd_register_uri_handler(hap_priv.server, &hap_characteristics_put); + httpd_register_uri_handler(hap_priv.server, &hap_identify); + httpd_register_uri_handler(hap_priv.server, &hap_prepare); + if (hap_priv.features & HAP_FF_SW_TOKEN_AUTH) { + hap_register_secure_message_handler(hap_priv.server); + } + } + hap_http_registered = true; + return HAP_SUCCESS; +} + +int hap_unregister_http_handlers() +{ + if (hap_http_registered) { + ESP_MFI_DEBUG(ESP_MFI_DEBUG_INFO, "Unegistering HomeKit web handlers"); + httpd_unregister_uri_handler(hap_priv.server, "/pair-setup", HTTP_POST); + httpd_unregister_uri_handler(hap_priv.server, "/pair-verify", HTTP_POST); + httpd_unregister_uri_handler(hap_priv.server, "/pairings", HTTP_POST); + httpd_unregister_uri_handler(hap_priv.server, "/accessories", HTTP_GET); + httpd_unregister_uri_handler(hap_priv.server, "/characteristics", HTTP_GET); + httpd_unregister_uri_handler(hap_priv.server, "/characteristics", HTTP_PUT); + httpd_unregister_uri_handler(hap_priv.server, "/identify", HTTP_POST); + httpd_unregister_uri_handler(hap_priv.server, "/prepare", HTTP_PUT); + if (hap_priv.features & HAP_FF_SW_TOKEN_AUTH) { + hap_unregister_secure_message_handler(hap_priv.server); + } + } + hap_http_registered = false; + return HAP_SUCCESS; +} + +int hap_httpd_start(void) +{ + if (hap_platform_httpd_start(&hap_priv.server) == ESP_OK) { + return HAP_SUCCESS; + } + return HAP_FAIL; +} + +httpd_handle_t * hap_httpd_get_handle() +{ + return &hap_priv.server; +} +static bool first_announce_done; + +int hap_mdns_deannounce(void) +{ + int ret = HAP_SUCCESS; + if (first_announce_done) { + ESP_MFI_DEBUG(ESP_MFI_DEBUG_INFO, "Deannouncing _hap._tcp mDNS service"); + ret = hap_mdns_serv_stop(&hap_priv.hap_mdns_handle); + if (ret == HAP_SUCCESS) { + /* Wait for some time for the packets to go out on network */ + vTaskDelay(2000 / hap_platform_os_get_msec_per_tick()); + first_announce_done = false; + } + } + return ret; +} + +int hap_mdns_announce(bool first) +{ + /* If the API is called with the "first" argument as true, Force announce the service, + * rather than just sending a re-announce packet + */ + if (first) { + first_announce_done = false; + } + static char config_num[6]; /* Max value can be 65535 */ + static char state_num[6]; /* Max value can be 65535 */ + static char ff[4]; + static char sf[4]; + static char ci[4]; + + mdns_txt_item_t txt[9]; + int i = 0; + + snprintf(config_num, sizeof(config_num), "%d", hap_priv.config_num); + txt[i].key = "c#"; + txt[i++].value = config_num; + + + uint8_t features = 0; + /* Either hardware authentication, or software authentication + * can be enabled at a time. + */ + if (hap_priv.features & HAP_FF_HARDWARE_AUTH) { + features |= HAP_FF_HARDWARE_AUTH; + } else if (hap_priv.features & HAP_FF_SW_TOKEN_AUTH) { + features |= HAP_FF_SW_TOKEN_AUTH; + } + snprintf(ff, sizeof(ff), "%d", features); + txt[i].key = "ff"; + txt[i++].value = ff; + + txt[i].key = "id"; + txt[i++].value = hap_priv.acc_id; + + txt[i].key = "md"; + txt[i++].value = hap_priv.primary_acc.model; + + txt[i].key = "pv"; + txt[i++].value = "1.1"; /* As per HAP Spec R10 */ + + if (first_announce_done) { + /* If first announcement was already done, this is a republish. + * Update the state number, since HAP Spec R15 requires that any Bonjour republish + * should update state number. + */ + if (is_accessory_paired()) { + hap_increment_and_save_state_num(); + } + } + snprintf(state_num, sizeof(state_num), "%u", hap_priv.state_num); + txt[i].key = "s#"; + txt[i++].value = state_num; + + uint8_t status_flags = is_accessory_paired() ? 0 : HAP_SF_ACC_UNPAIRED; + if (!hap_is_network_configured()) + status_flags |= HAP_SF_ACC_UNCONFIGURED; + snprintf(sf, sizeof(sf), "%d", status_flags); + txt[i].key = "sf"; + txt[i++].value = sf; + + snprintf(ci, sizeof(ci), "%d", hap_priv.cid); + txt[i].key = "ci"; + txt[i++].value = ci; + + txt[i].key = "sh"; + txt[i++].value = hap_priv.setup_hash_str; + + int ret; + /* If first announce is not done, the service will be added instead of just updating. + * Else, first add the service, instead of just updating. + */ + if (!first_announce_done) { + ESP_MFI_DEBUG(ESP_MFI_DEBUG_INFO, "Announcing _hap._tcp mDNS service"); + ret = hap_mdns_serv_start(&hap_priv.hap_mdns_handle, + hap_priv.primary_acc.name, "_hap", "_tcp", hap_platform_httpd_get_port(), txt, i); + first_announce_done = true; + } else { + /* Else, just update TXT records. Not add new service.*/ + ESP_MFI_DEBUG(ESP_MFI_DEBUG_INFO, "Re-announcing _hap._tcp mDNS service"); + ret = hap_mdns_serv_update_txt(&hap_priv.hap_mdns_handle, txt, i); + } + if (ret != 0) { + ESP_MFI_DEBUG(ESP_MFI_DEBUG_ERR, "Failed to announce _hap mDNS service"); + return HAP_FAIL; + } + return HAP_SUCCESS; +} + +int hap_ip_services_start() +{ + static bool hap_ip_services_started; + if (hap_ip_services_started) { + return HAP_SUCCESS; + } + hap_register_http_handlers(); + if (hap_mdns_announce(false) != HAP_SUCCESS) { + hap_unregister_http_handlers(); + return HAP_FAIL; + } + hap_ip_services_started = true; + return HAP_SUCCESS; +} diff --git a/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_ip_services.h b/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_ip_services.h new file mode 100644 index 000000000..fa65bfa10 --- /dev/null +++ b/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_ip_services.h @@ -0,0 +1,35 @@ +/* + * ESPRESSIF MIT License + * + * Copyright (c) 2020 + * + * Permission is hereby granted for use on ESPRESSIF SYSTEMS products only, in which case, + * it is 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. + * + */ +#ifndef _HAP_IP_SERVICES_H_ +#define _HAP_IP_SERVICES_H_ +#include +#include +int hap_http_session_not_authorized(httpd_req_t *req); +int hap_httpd_get_data(httpd_req_t *req, char *buffer, int len); +int hap_httpd_start(); +int hap_ip_services_start(); +int hap_mdns_announce(bool first); +int hap_mdns_deannounce(); +void hap_http_send_notif(); +#endif /* _HAP_IP_SERVICES_H_ */ diff --git a/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_keystore.c b/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_keystore.c new file mode 100644 index 000000000..43a72021b --- /dev/null +++ b/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_keystore.c @@ -0,0 +1,133 @@ +/* + * ESPRESSIF MIT License + * + * Copyright (c) 2020 + * + * Permission is hereby granted for use on ESPRESSIF SYSTEMS products only, in which case, + * it is 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 +#include +#include + +static bool keystore_init_done; +static char *hap_platform_nvs_partition; +static char *hap_platform_factory_nvs_partition; + +int hap_keystore_init() +{ + if (keystore_init_done) { + return HAP_SUCCESS; + } + + + + hap_platform_nvs_partition = hap_platform_keystore_get_nvs_partition_name(); + + // hap_platfrom_keystore_erase_partition(hap_platform_nvs_partition); + + int err = hap_platform_keystore_init_partition(hap_platform_nvs_partition, false); + if (err != 0) { + ESP_MFI_DEBUG(ESP_MFI_DEBUG_ERR, "Error (%d) NVS init failed", err); + return HAP_FAIL; + } + /* Not cheking the return value, as this partition may be absent */ + hap_platform_factory_nvs_partition = hap_platform_keystore_get_factory_nvs_partition_name(); + hap_platform_keystore_init_partition(hap_platform_factory_nvs_partition, true); + + keystore_init_done = true; + ESP_MFI_DEBUG(ESP_MFI_DEBUG_INFO, "Keystore initialised"); + return HAP_SUCCESS; +} + +int __hap_keystore_get(const char *part_name, const char *name_space, const char *key, uint8_t *val, size_t *val_size) +{ + if (!keystore_init_done) { + return HAP_FAIL; + } + + int err = hap_platform_keystore_get(part_name, name_space, key, val, val_size); + if (err != 0) { + return HAP_FAIL; + } + return HAP_SUCCESS; +} +int hap_keystore_get(const char *name_space, const char *key, uint8_t *val, size_t *val_size) +{ + + return __hap_keystore_get(hap_platform_nvs_partition, name_space, key, val, val_size); +} +int hap_factory_keystore_get(const char *name_space, const char *key, uint8_t *val, size_t *val_size) +{ + return __hap_keystore_get(hap_platform_factory_nvs_partition, name_space, key, val, val_size); +} + +int __hap_keystore_set(const char *part_name, const char *name_space, const char *key, const uint8_t *val, const size_t val_len) + +{ + if (!keystore_init_done) { + return HAP_FAIL; + } + + int err = hap_platform_keystore_set(part_name, name_space, key, val, val_len); + if (err != 0) { + return HAP_FAIL; + } + return HAP_SUCCESS; +} + +int hap_keystore_set(const char *name_space, const char *key, const uint8_t *val, const size_t val_len) +{ + return __hap_keystore_set(hap_platform_nvs_partition, name_space, key, val, val_len); +} + +int hap_factory_keystore_set(const char *name_space, const char *key, const uint8_t *val, const size_t val_len) +{ + return __hap_keystore_set(hap_platform_factory_nvs_partition, name_space, key, val, val_len); +} + +int hap_keystore_delete(const char *name_space, const char *key) +{ + if (!keystore_init_done) { + return HAP_FAIL; + } + + int err = hap_platform_keystore_delete(hap_platform_nvs_partition, name_space, key); + if (err != 0) { + return HAP_FAIL; + } + return HAP_SUCCESS; +} + +int hap_keystore_delete_namespace(const char *name_space) +{ + if (!keystore_init_done) { + return HAP_FAIL; + } + + int err = hap_platform_keystore_delete_namespace(hap_platform_nvs_partition, name_space); + if (err != 0) { + return HAP_FAIL; + } + return HAP_SUCCESS; +} + +void hap_keystore_erase_all_data() +{ + hap_platfrom_keystore_erase_partition(hap_platform_nvs_partition); +} diff --git a/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_keystore.h b/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_keystore.h new file mode 100644 index 000000000..26587e867 --- /dev/null +++ b/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_keystore.h @@ -0,0 +1,34 @@ +/* + * ESPRESSIF MIT License + * + * Copyright (c) 2020 + * + * Permission is hereby granted for use on ESPRESSIF SYSTEMS products only, in which case, + * it is 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. + * + */ +#ifndef _HAP_KEYSTORE_H_ +#define _HAP_KEYSTORE_H_ +#include +int hap_keystore_init(); +int hap_keystore_get(const char *name_space, const char *key, uint8_t *val, size_t *val_size); +int hap_keystore_set(const char *name_space, const char *key, const uint8_t *val, const size_t val_len); +int hap_keystore_delete(const char *name_space, const char *key); +int hap_keystore_delete_namespace(const char *name_space); +int hap_factory_keystore_set(const char *name_space, const char *key, const uint8_t *val, const size_t val_len); +void hap_keystore_erase_all_data(); +#endif /* _HAP_KEYSTORE_H_ */ diff --git a/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_main.c b/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_main.c new file mode 100644 index 000000000..459b6a0ed --- /dev/null +++ b/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_main.c @@ -0,0 +1,372 @@ +/* + * ESPRESSIF MIT License + * + * Copyright (c) 2020 + * + * Permission is hereby granted for use on ESPRESSIF SYSTEMS products only, in which case, + * it is 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 +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include <_esp_hap_config.h> + +static QueueHandle_t xQueue; +ESP_EVENT_DEFINE_BASE(HAP_EVENT); + +const char * hap_get_version(void) +{ + return MFI_VER; +} +static void hap_nw_configured_sm(hap_internal_event_t event, hap_state_t *state) +{ + switch (event) { + case HAP_INTERNAL_EVENT_ACC_PAIRED: + hap_mdns_announce(false); + break; + case HAP_INTERNAL_EVENT_ACC_UNPAIRED: + hap_mdns_announce(false); + break; + case HAP_INTERNAL_EVENT_CONFIG_NUM_UPDATED: + hap_increment_and_save_config_num(); + hap_mdns_announce(false); + break; + case HAP_INTERNAL_EVENT_BCT_CHANGE_NAME: + /* Waiting for sometime to allow the response to reach the host */ + vTaskDelay(1000 / hap_platform_os_get_msec_per_tick()); + hap_handle_bct_change_name(); + break; + case HAP_INTERNAL_EVENT_BCT_HOT_PLUG: + /* Waiting for sometime to allow the response to reach the host */ + vTaskDelay(1000 / hap_platform_os_get_msec_per_tick()); + hap_handle_hot_plug(); + break; + default: + break; + } +} + +static void hap_common_sm(hap_internal_event_t event) +{ + char *reboot_reason = HAP_REBOOT_REASON_UNKNOWN; + switch (event) { + case HAP_INTERNAL_EVENT_RESET_PAIRINGS: + ESP_MFI_DEBUG(ESP_MFI_DEBUG_INFO, "Resetting all Pairing Information"); + /* Wait for some time before erasing the information, so that the callee + * gets some time for any additional operations + */ + vTaskDelay(1000 / hap_platform_os_get_msec_per_tick()); + hap_close_all_sessions(); + hap_mdns_deannounce(); + hap_erase_controller_info(); + hap_erase_accessory_info(); + reboot_reason = HAP_REBOOT_REASON_RESET_PAIRINGS; + break; + case HAP_INTERNAL_EVENT_RESET_TO_FACTORY: + ESP_MFI_DEBUG(ESP_MFI_DEBUG_INFO, "Resetting to Factory Defaults"); + /* Wait for some time before erasing the information, so that the callee + * gets some time for any additional operations + */ + vTaskDelay(1000 / hap_platform_os_get_msec_per_tick()); + hap_close_all_sessions(); + hap_mdns_deannounce(); + hap_keystore_erase_all_data(); + reboot_reason = HAP_REBOOT_REASON_RESET_TO_FACTORY; + break; + case HAP_INTERNAL_EVENT_RESET_HOMEKIT_DATA: + ESP_MFI_DEBUG(ESP_MFI_DEBUG_INFO, "Resetting all HomeKit Data"); + /* Wait for some time before erasing the information, so that the callee + * gets some time for any additional operations + */ + vTaskDelay(1000 / hap_platform_os_get_msec_per_tick()); + hap_close_all_sessions(); + hap_mdns_deannounce(); + hap_erase_controller_info(); + hap_erase_network_info(); + hap_erase_accessory_info(); + reboot_reason = HAP_REBOOT_REASON_RESET_HOMEKIT_DATA; + break; + case HAP_INTERNAL_EVENT_REBOOT: + vTaskDelay(1000 / hap_platform_os_get_msec_per_tick()); + /* Wait for some time and then close all the active sessions + */ + hap_close_all_sessions(); + hap_mdns_deannounce(); + reboot_reason = HAP_REBOOT_REASON_REBOOT_ACC; + break; + case HAP_INTERNAL_EVENT_RESET_NETWORK: + ESP_MFI_DEBUG(ESP_MFI_DEBUG_INFO, "Resetting Network Credentials"); + /* Wait for some time, close all the active sessions and then + * erase network info. + */ + vTaskDelay(1000 / hap_platform_os_get_msec_per_tick()); + hap_close_all_sessions(); + hap_mdns_deannounce(); + hap_erase_network_info(); + reboot_reason = HAP_REBOOT_REASON_RESET_NETWORK; + break; + case HAP_INTERNAL_EVENT_TRIGGER_NOTIF: +/* TODO: Avoid direct http function. Notification could be even for iCloud or BLE. + */ + hap_http_send_notif(); + return; + default: + return; + } + + /* Wait for some time after peeforming the operations and then reboot */ + ESP_MFI_DEBUG(ESP_MFI_DEBUG_INFO, "Rebooting..."); + hap_report_event(HAP_EVENT_ACC_REBOOTING, reboot_reason, strlen(reboot_reason) + 1); + vTaskDelay(1000 / hap_platform_os_get_msec_per_tick()); + esp_restart(); +} + +static void hap_loop_task(void *param) +{ + hap_state_t cur_state = HAP_STATE_NONE; + xQueue = xQueueCreate( 10, sizeof(hap_event_ctx_t) ); + hap_event_ctx_t hap_event; + bool loop_continue = true; + ESP_MFI_DEBUG(ESP_MFI_DEBUG_INFO, "HAP Main Loop Started"); + while (loop_continue) { + if (xQueueReceive(xQueue, &hap_event, portMAX_DELAY) != pdTRUE) { + continue; + } + if (hap_event.event == HAP_INTERNAL_EVENT_LOOP_STOP) { + loop_continue = false; + continue; + } + hap_common_sm(hap_event.event); + hap_nw_configured_sm(hap_event.event, &cur_state); + } + vQueueDelete(xQueue); + xQueue = NULL; + vTaskDelete(NULL); +} + +static bool loop_started; +int hap_loop_start() +{ + if (!loop_started) { + loop_started = true; + xTaskCreate(hap_loop_task, "hap-loop", hap_priv.cfg.task_stack_size, NULL, + hap_priv.cfg.task_priority, NULL); + } + return HAP_SUCCESS; +} + +bool is_hap_loop_started() +{ + return loop_started; +} +int hap_send_event(hap_internal_event_t event) +{ + if (!is_hap_loop_started()) { + return HAP_FAIL; + } + if (!xQueue) { + return HAP_FAIL; + } + hap_event_ctx_t hap_event = { + .event = event, + }; + BaseType_t ret; + if (xPortInIsrContext() == pdTRUE) { + ret = xQueueSendFromISR(xQueue, &hap_event, NULL); + } else { + ret = xQueueSend(xQueue, &hap_event, 0); + } + if (ret == pdTRUE) { + return HAP_SUCCESS; + } + return HAP_FAIL; +} + +int hap_update_config_number() +{ + return hap_send_event(HAP_INTERNAL_EVENT_CONFIG_NUM_UPDATED); +} + +int hap_loop_stop() +{ + return hap_send_event(HAP_INTERNAL_EVENT_LOOP_STOP); +} + +#if 0 +static void hap_network_event_handler(void* arg, esp_event_base_t event_base, + int event_id, void* event_data) +{ + if (((event_base == WIFI_EVENT) && (event_id == WIFI_EVENT_STA_CONNECTED)) || + ((event_base == ETH_EVENT) && (event_id == ETHERNET_EVENT_CONNECTED))){ + hap_send_event(HAP_INTERNAL_EVENT_NETWORK_CONNECTED); + } +} +#endif +int hap_init(hap_transport_t method) +{ + int ret = HAP_SUCCESS; + if (!(method & (HAP_TRANSPORT_WIFI | HAP_TRANSPORT_ETHERNET))) { + ESP_MFI_DEBUG(ESP_MFI_DEBUG_ERR, "Invalid Transport"); + return HAP_FAIL; + } + + hap_priv.transport = method; + + ret = hap_keystore_init(); + if (ret != 0 ) { + ESP_MFI_DEBUG(ESP_MFI_DEBUG_ERR, "HAP Key Store Init failed"); + return ret; + } + + ret = hap_database_init(); + if (ret != 0 ) { + ESP_MFI_DEBUG(ESP_MFI_DEBUG_ERR, "HAP Database Init failed"); + return ret; + } + ESP_MFI_DEBUG(ESP_MFI_DEBUG_INFO, "HAP Initialization succeeded. Version : %s", hap_get_version()); + + return ret; +} + +int hap_deinit(void) +{ + int ret = HAP_SUCCESS; + //todo + return ret; +} + +int hap_reset_to_factory() +{ + return hap_send_event(HAP_INTERNAL_EVENT_RESET_TO_FACTORY); +} + +int hap_reset_homekit_data() +{ + return hap_send_event(HAP_INTERNAL_EVENT_RESET_HOMEKIT_DATA); +} + +int hap_reset_pairings() +{ + return hap_send_event(HAP_INTERNAL_EVENT_RESET_PAIRINGS); +} + +int hap_reboot_accessory() +{ + return hap_send_event(HAP_INTERNAL_EVENT_REBOOT); +} + +int hap_reset_network() +{ + return hap_send_event(HAP_INTERNAL_EVENT_RESET_NETWORK); +} + +int hap_start(void) +{ + int ret = 0; +#ifdef CONFIG_HAP_MFI_ENABLE + if (hap_priv.auth_type == HAP_MFI_AUTH_HW) { + ret = hap_enable_hw_auth(); + } else if (hap_priv.auth_type == HAP_MFI_AUTH_SW) { + ret = hap_enable_sw_auth(); + } +#endif /* CONFIG_HAP_MFI_ENABLE */ + if (ret != 0) { + ESP_MFI_DEBUG(ESP_MFI_DEBUG_ERR, "Failed to enable MFi %s authentication", + hap_priv.auth_type == HAP_MFI_AUTH_HW ? "HW" : "SW"); + return HAP_FAIL; + } + + if (!hap_get_first_acc()) { + ESP_MFI_DEBUG(ESP_MFI_DEBUG_ERR, "Failed to start HAP. Please add an Accessory before hap_start()"); + return HAP_FAIL; + } + + ret = hap_acc_setup_init(); + if (ret != HAP_SUCCESS) { + ESP_MFI_DEBUG(ESP_MFI_DEBUG_ERR, "Accessory Setup init failed"); + return ret; + } + + ret = hap_httpd_start(); + if (ret != HAP_SUCCESS) { + ESP_MFI_DEBUG(ESP_MFI_DEBUG_ERR, "HTTPD START Failed [%d]", ret); + return ret; + } + + ret = hap_event_queue_init(); + if (ret != HAP_SUCCESS) { + ESP_MFI_DEBUG(ESP_MFI_DEBUG_ERR, "Queue Initialisation for Event Notifications Failed"); + return ret; + } + + ret = hap_loop_start(); + if (ret != 0) { + ESP_MFI_DEBUG(ESP_MFI_DEBUG_ERR, "HAP Loop Failed: [%d]", ret); + return ret; + } + ret = hap_mdns_init(); + if (ret != 0 ) { + ESP_MFI_DEBUG(ESP_MFI_DEBUG_ERR, "HAP mDNS Init failed"); + return ret; + } + + ret = hap_ip_services_start(); + if (ret != 0) { + ESP_MFI_DEBUG(ESP_MFI_DEBUG_ERR, "HAP IP Services Start Failed [%d]", ret); + return ret; + } + return HAP_SUCCESS; +} + +int hap_stop(void) +{ + int ret = HAP_SUCCESS; + //todo + return ret; +} + +void hap_report_event(hap_event_t event, void *data, size_t data_size) +{ + if (hap_priv.hap_event_handler) { + hap_priv.hap_event_handler(event, data); + } + esp_event_post(HAP_EVENT, event, data, data_size, portMAX_DELAY); +} + +void hap_register_event_handler(hap_event_handler_t handler) +{ + hap_priv.hap_event_handler = handler; +} diff --git a/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_main.h b/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_main.h new file mode 100644 index 000000000..508c856ef --- /dev/null +++ b/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_main.h @@ -0,0 +1,72 @@ +/* + * ESPRESSIF MIT License + * + * Copyright (c) 2020 + * + * Permission is hereby granted for use on ESPRESSIF SYSTEMS products only, in which case, + * it is 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. + * + */ + +#ifndef _HAP_MAIN_LOOP_H_ +#define _HAP_MAIN_LOOP_H_ +#include +#include + +#define HAP_FF_HARDWARE_AUTH 0x01 +#define HAP_FF_SW_TOKEN_AUTH 0x02 + + +#define HAP_SF_ACC_UNPAIRED 0x01 +#define HAP_SF_ACC_UNCONFIGURED 0x02 +#define HAP_SF_PROBLEM_DETECTED 0x04 + +typedef enum { + HAP_INTERNAL_EVENT_LOOP_STOP = 1, + HAP_INTERNAL_EVENT_ACC_PAIRED, + HAP_INTERNAL_EVENT_ACC_UNPAIRED, + HAP_INTERNAL_EVENT_CONFIG_NUM_UPDATED, + HAP_INTERNAL_EVENT_BCT_CHANGE_NAME, + HAP_INTERNAL_EVENT_BCT_HOT_PLUG, + HAP_INTERNAL_EVENT_RESET_PAIRINGS, + HAP_INTERNAL_EVENT_RESET_TO_FACTORY, + HAP_INTERNAL_EVENT_REBOOT, + HAP_INTERNAL_EVENT_RESET_NETWORK, + HAP_INTERNAL_EVENT_TRIGGER_NOTIF, + HAP_INTERNAL_EVENT_RESET_HOMEKIT_DATA, +} hap_internal_event_t; + +typedef struct { + hap_internal_event_t event; +} hap_event_ctx_t; + +typedef enum { + HAP_STATE_NONE = 0, + HAP_STATE_NW_UNCONFIGURED, + HAP_STATE_NW_CONFIGURED, +} hap_state_t; + +int hap_loop_start(); +int hap_loop_stop(); +int hap_send_event(hap_internal_event_t event); +int hap_update_config_number(); +bool is_hap_loop_started(); +void hap_report_event(hap_event_t event, void *data, size_t data_size); +int hap_enable_hw_auth(void); +int hap_enable_sw_auth(void); + +#endif /* _HAP_MAIN_LOOP_H_ */ diff --git a/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_mdns.c b/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_mdns.c new file mode 100644 index 000000000..2ccda5686 --- /dev/null +++ b/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_mdns.c @@ -0,0 +1,85 @@ +/* + * ESPRESSIF MIT License + * + * Copyright (c) 2020 + * + * Permission is hereby granted for use on ESPRESSIF SYSTEMS products only, in which case, + * it is 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 +#include +#include + +static bool mdns_init_done; + +int hap_mdns_serv_start(hap_mdns_handle_t *handle, const char *name, const char *type, + const char *protocol, int port, mdns_txt_item_t *txt_records, size_t num_txt) +{ + strcpy(handle->type, type); + strcpy(handle->proto, protocol); + if (mdns_service_add(name, type, protocol, port, txt_records, num_txt) != 0) { + return HAP_FAIL; + } + return HAP_SUCCESS; +} + +int hap_mdns_serv_update_txt(hap_mdns_handle_t *handle, mdns_txt_item_t *txt_records, size_t num_txt) +{ + if (mdns_service_txt_set(handle->type, handle->proto, txt_records, num_txt) != 0) { + return HAP_FAIL; + } + return HAP_SUCCESS; +} + +int hap_mdns_serv_name_change(hap_mdns_handle_t *handle, const char * instance_name) +{ + if (mdns_service_instance_name_set(handle->type, handle->proto, instance_name) == ESP_OK) { + return HAP_SUCCESS; + } + return HAP_FAIL; +} + +int hap_mdns_serv_stop(hap_mdns_handle_t *handle) +{ + if (mdns_service_remove(handle->type, handle->proto) == ESP_OK) { + return HAP_SUCCESS; + } + return HAP_FAIL; +} + +int hap_mdns_init() +{ + int ret = HAP_SUCCESS; + if (!mdns_init_done) { + ret = mdns_init(); + if (ret == ESP_OK) { + mdns_hostname_set("MyHost"); + mdns_init_done = true; + ESP_MFI_DEBUG(ESP_MFI_DEBUG_INFO, "mDNS initialised"); + return HAP_SUCCESS; + } + } + return HAP_FAIL; +} + +int hap_mdns_deinit() +{ + mdns_free(); + mdns_init_done = false; + return HAP_SUCCESS; +} diff --git a/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_mdns.h b/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_mdns.h new file mode 100644 index 000000000..c206161ee --- /dev/null +++ b/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_mdns.h @@ -0,0 +1,43 @@ +/* + * ESPRESSIF MIT License + * + * Copyright (c) 2020 + * + * Permission is hereby granted for use on ESPRESSIF SYSTEMS products only, in which case, + * it is 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. + * + */ +#ifndef _HAP_MDNS_H_ +#define _HAP_MDNS_H_ + +#include +#include + +typedef struct { + char type[32]; + char proto[32]; +} hap_mdns_handle_t; + +int hap_mdns_serv_start(hap_mdns_handle_t *handle, const char *name, const char *type, + const char *protocol, int port, mdns_txt_item_t *txt_records, size_t num_txt); +int hap_mdns_serv_update_txt(hap_mdns_handle_t *handle, mdns_txt_item_t *txt_records, size_t num_txt); +int hap_mdns_serv_name_change(hap_mdns_handle_t *handle, const char * instance_name); +int hap_mdns_serv_stop(hap_mdns_handle_t *handle); +int hap_mdns_init(); +int hap_mdns_deinit(); + +#endif /* _HAP_MDNS_H_ */ diff --git a/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_network_io.c b/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_network_io.c new file mode 100644 index 000000000..2342773aa --- /dev/null +++ b/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_network_io.c @@ -0,0 +1,237 @@ +/* + * ESPRESSIF MIT License + * + * Copyright (c) 2020 + * + * Permission is hereby granted for use on ESPRESSIF SYSTEMS products only, in which case, + * it is 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 +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +#define HAP_MAX_NW_FRAME_SIZE 1024 /* As per HAP Specifications */ +#define AUTH_TAG_LEN 16 +typedef struct { + uint8_t pkt_size[2]; + uint8_t data[HAP_MAX_NW_FRAME_SIZE]; + /* The Poly auth tag buffer will get used only if the data length is + * greater than HAP_MAX_NW_FRAME_SIZE - 16. + * Else, the auth tag would be included in the data buffer itself + */ + uint8_t poly_auth_tag[AUTH_TAG_LEN]; +} hap_encrypt_frame_t; + +typedef struct { + uint16_t pkt_size; + uint16_t bytes_read; + uint8_t data[HAP_MAX_NW_FRAME_SIZE + AUTH_TAG_LEN]; + hap_secure_session_t *session; +} hap_decrypt_frame_t; + +typedef int (*hap_decrypt_read_fn_t) (uint8_t *buf, int buf_size, void *context); +static int min(int val1, int val2) +{ + if (val1 < val2) + return val1; + return val2; +} +static int hap_httpd_raw_recv(uint8_t *buf, int buf_size, void *context) +{ + int sock = *((int *)context); + return recv(sock, buf, buf_size, 0); +} + +/* Frame format as per HAP Specifications: + * <2: AAD for Little Endian length of encrypted data (n) in bytes> + * + * <16: authTag according to AEAD algorithm> + */ +int hap_encrypt_data(hap_encrypt_frame_t *frame, hap_secure_session_t *session, + uint8_t *buf, int buflen) +{ + if (!session) + return HAP_FAIL; + put_u16_le(frame->pkt_size, buflen); + /* Encrypt the received data as per Chacha20-Poly1305 AEAD algorithm. + * The authTag will be appended at the end of data. Hence, pointer given as + * frame->data + nlen + */ + unsigned long long mlen = 16; + uint8_t newnonce[12]; + memset(newnonce, 0, sizeof newnonce); + memcpy(newnonce+4, session->encrypt_nonce, 8); + crypto_aead_chacha20poly1305_ietf_encrypt_detached(frame->data, frame->data + buflen, &mlen, + buf, buflen, frame->pkt_size, 2, NULL, newnonce, session->encrypt_key); + + /* Increment nonce after every frame */ + uint64_t int_nonce = get_u64_le(session->encrypt_nonce); + int_nonce++; + put_u64_le(session->encrypt_nonce, int_nonce); + return 2 + buflen + 16; /* Total length of the encrypted data */ +} + +#include +void hap_close_ctrl_sessions_fix(hap_secure_session_t *session) +{ + if (!session) + return; + int i; + printf("---- hap_close_ctrl_sessions_fix begin -----\n"); + for (i = 0; i < HAP_MAX_SESSIONS; i++) { + if (!hap_priv.sessions[i]) + continue; + if (hap_priv.sessions[i] == session) { + hap_report_event(HAP_EVENT_CTRL_DISCONNECTED, (session->ctrl->info.id), + sizeof((session->ctrl->info.id))); + /* TODO: Use some generic function and not a direct HTTPD function + */ + printf("---- trigger_close fd: %d\n", hap_priv.sessions[i]->conn_identifier); + httpd_sess_trigger_close(hap_priv.server, hap_priv.sessions[i]->conn_identifier); + } + } + printf("---- hap_close_ctrl_sessions_fix end ----\n"); +} + +int hap_decrypt_error(hap_secure_session_t *session) +{ + ESP_MFI_DEBUG(ESP_MFI_DEBUG_INFO, "Decryption error/Connection lost. Marking session as invalid"); + if (session) { + session->state = STATE_INVALID; + //hap_close_ctrl_sessions(session->ctrl); + hap_close_ctrl_sessions_fix(session); + } + return HAP_FAIL; +} + +int hap_decrypt_data(hap_decrypt_frame_t *frame, hap_secure_session_t *session, + void *buf, int buf_size, hap_decrypt_read_fn_t read_fn, void *context) +{ + if (!frame || !session) + return -1; + if (frame->session != session) { + memset(frame, 0, sizeof(hap_decrypt_frame_t)); + frame->session = session; + } + if ((frame->pkt_size - frame->bytes_read) == 0) { + int len = read_fn(frame->data, 2, context); + if (len == 0) { //nothing received, but we should NOT consider this is a 'decrypt_error' + return 0; + } + if (len < 2) { + //len is -1 or 1 + //len = -1: socket disconnected + //len = 1: try receiving 2 bytes timeout (SO_RCVTIMEO is set in esp_hap_ip_services.c) + printf("---- error 1 ----, len: %d\n", len); + //Decryption error/Connection lost on ESP32 with multiple Apple devices running Home + //https://github.com/espressif/esp-homekit-sdk/issues/14 + //---- error 1 ----, len: 0 + return hap_decrypt_error(session); + } + + frame->pkt_size = get_u16_le(frame->data); + frame->bytes_read = 0; + uint16_t bytes_to_read = frame->pkt_size + AUTH_TAG_LEN; /* +AUTH_TAG_LEN as the receivedd packet will also have the auth Tag */ + while (bytes_to_read) { + int num_bytes = read_fn(&frame->data[frame->bytes_read], + bytes_to_read, context); + if (num_bytes <= 0) { + printf("---- error 2 ----\n"); + return hap_decrypt_error(session); + } + bytes_to_read -= num_bytes; + frame->bytes_read += num_bytes; + } + frame->bytes_read -= AUTH_TAG_LEN; /* -AUTH_TAG_LEN to get only the data length */ + uint8_t aad[2]; + int ret; + put_u16_le(aad, frame->pkt_size); /* Packet size is the AAD for AEAD */ + uint8_t newnonce[12]; + memset(newnonce, 0, sizeof newnonce); + memcpy(newnonce+4, session->decrypt_nonce, 8); + ret = crypto_aead_chacha20poly1305_ietf_decrypt_detached(frame->data, NULL, frame->data, frame->pkt_size, + &frame->data[frame->bytes_read], aad, 2, newnonce, session->decrypt_key); + if (ret != 0) { + ESP_MFI_DEBUG(ESP_MFI_DEBUG_INFO, "AEAD decryption failure"); + printf("---- error 3 ----\n"); + return hap_decrypt_error(session); + } + frame->bytes_read = 0; + /* Increment nonce after every frame */ + int64_t int_nonce = get_u64_le(session->decrypt_nonce); + int_nonce++; + put_u64_le(session->decrypt_nonce, int_nonce); + } + int bytes = min(frame->pkt_size - frame->bytes_read, buf_size); + memcpy(buf, &frame->data[frame->bytes_read], bytes); + frame->bytes_read += bytes; + return bytes; +} + +int hap_httpd_send(httpd_handle_t hd, int sockfd, const char *buf, unsigned buf_len, int flags) +{ + hap_secure_session_t *session = httpd_sess_get_ctx(hap_priv.server, sockfd); + if (session && (session->state == STATE_VERIFIED)) { + uint8_t *buf_ptr = (uint8_t *)buf; + int tmp_buf_len = buf_len; + while (tmp_buf_len) { + hap_encrypt_frame_t encrypt_frame; + memset(&encrypt_frame, 0, sizeof(encrypt_frame)); + int len = min(tmp_buf_len, HAP_MAX_NW_FRAME_SIZE); + int send_len = hap_encrypt_data(&encrypt_frame, session, buf_ptr, len); + if (send(sockfd, (uint8_t *)&encrypt_frame, send_len, flags) <= 0) + return HAP_FAIL; + tmp_buf_len -= len; + buf_ptr += len; + } + /* Return the total length at the end since this API expects so + */ + return buf_len; + } + return send(sockfd, buf, buf_len, flags); +} + +int hap_httpd_recv(httpd_handle_t hd, int sockfd, char *buf, unsigned buf_len, int flags) +{ + static hap_decrypt_frame_t decrypt_frame; + hap_secure_session_t *session = httpd_sess_get_ctx(hap_priv.server, sockfd); + if (session) { + if (session->state == STATE_VERIFIED) { + return hap_decrypt_data(&decrypt_frame, session, buf, buf_len, + hap_httpd_raw_recv, &sockfd); + } else { + /* If the session state is invalid, we return an error. + * The errno is set here explicitly, so that even if the higher layers + * query for it, they do not get a stale value. + * EACCES means permission denied, which indeed is the case here. + */ + errno = EACCES; + return HAP_FAIL; + } + } + return recv(sockfd, buf, buf_len, sockfd); +} diff --git a/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_network_io.h b/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_network_io.h new file mode 100644 index 000000000..7c8b3ef03 --- /dev/null +++ b/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_network_io.h @@ -0,0 +1,31 @@ +/* + * ESPRESSIF MIT License + * + * Copyright (c) 2020 + * + * Permission is hereby granted for use on ESPRESSIF SYSTEMS products only, in which case, + * it is 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. + * + */ +#ifndef _HAP_NETWORK_IO_H_ +#define _HAP_NETWORK_IO_H_ +#include +#include +int hap_httpd_send(httpd_handle_t hd, int sockfd, const char *buf, unsigned buf_len, int flags); +int hap_httpd_recv(httpd_handle_t hd, int sockfd, char *buf, unsigned buf_len, int flags); + +#endif /* _HAP_NETWORK_IO_H_ */ diff --git a/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_pair_common.c b/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_pair_common.c new file mode 100644 index 000000000..9a003ab6c --- /dev/null +++ b/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_pair_common.c @@ -0,0 +1,127 @@ +/* + * ESPRESSIF MIT License + * + * Copyright (c) 2020 + * + * Permission is hereby granted for use on ESPRESSIF SYSTEMS products only, in which case, + * it is 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 +#include +#include +#include + +void hap_tlv_data_init(hap_tlv_data_t *tlv_data, uint8_t *buf, int buf_size) +{ + tlv_data->bufptr = buf; + tlv_data->bufsize = buf_size; + tlv_data->curlen = 0; +} + +int get_tlv_length(uint8_t *buf, int buflen, uint8_t type) +{ + if (!buf ) + return -1; + int curlen = 0; + int val_len = 0; + bool found = false; + while (buflen > 0) { + if (buf[curlen] == type) { + uint8_t len = buf[curlen + 1]; + if ((buflen - len) < 2) + return -1; + val_len += len; + if (len < 255) + return val_len; + else + found = true; + + } else if (found) + return val_len; + + /* buf[curlen +1] will give the Length */ + buflen -= (2 + buf[curlen + 1]); + curlen += (2 + buf[curlen + 1]); + } + return -1; +} +int get_value_from_tlv(uint8_t *buf, int buflen, uint8_t type, void *val, int val_size) +{ + if (!buf || !val) + return -1; + int curlen = 0; + int val_len = 0; + bool found = false; + while (buflen > 0) { + if (buf[curlen] == type) { + uint8_t len = buf[curlen + 1]; + if ((val_size < len) || ((buflen - len) < 2)) + return -1; + memcpy(val + val_len, &buf[curlen + 2], len); + val_len += len; + val_size -= len; + if (len < 255) + return val_len; + else + found = true; + + } else if (found) + return val_len; + + /* buf[curlen +1] will give the Length */ + buflen -= (2 + buf[curlen + 1]); + curlen += (2 + buf[curlen + 1]); + } + return -1; +} + +int add_tlv(hap_tlv_data_t *tlv_data, uint8_t type, int len, void *val) +{ + if(!tlv_data->bufptr || ((len + 2) > (tlv_data->bufsize - tlv_data->curlen))) + return -1; + uint8_t *buf_ptr = (uint8_t *)val; + int orig_len = tlv_data->curlen; + do { + tlv_data->bufptr[tlv_data->curlen++] = type; + int tmp_len; + if (len > 255) + tmp_len = 255; + else + tmp_len = len; + tlv_data->bufptr[tlv_data->curlen++] = tmp_len; + memcpy(&tlv_data->bufptr[tlv_data->curlen], buf_ptr, tmp_len); + tlv_data->curlen += tmp_len; + buf_ptr += tmp_len; + len -= tmp_len; + } while (len); + return tlv_data->curlen - orig_len; +} +void hap_prepare_error_tlv(uint8_t state, uint8_t error, void *buf, int bufsize, int *outlen) +{ + hap_tlv_data_t tlv_data; + tlv_data.bufptr = buf; + tlv_data.bufsize = bufsize; + tlv_data.curlen = 0; + /* Not doing any error handling because the size required for "state" and "error" will + * be too small to cause any error, and we anyways dont have any specific action to + * do in case if error in add_tlv() + */ + add_tlv(&tlv_data, kTLVType_State, sizeof(state), &state); + add_tlv(&tlv_data, kTLVType_Error, sizeof(error), &error); + *outlen = tlv_data.curlen; +} diff --git a/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_pair_common.h b/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_pair_common.h new file mode 100644 index 000000000..a795d583a --- /dev/null +++ b/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_pair_common.h @@ -0,0 +1,114 @@ +/* + * ESPRESSIF MIT License + * + * Copyright (c) 2020 + * + * Permission is hereby granted for use on ESPRESSIF SYSTEMS products only, in which case, + * it is 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. + * + */ +#ifndef _HAP_PAIR_COMMON_H_ +#define _HAP_PAIR_COMMON_H_ + +#include +#include +#define ENCRYPT_KEY_LEN 32 +#define POLY_AUTHTAG_LEN 16 +#define CURVE_KEY_LEN 32 +#define ED_SIGN_LEN 64 +#define NONCE_LEN 8 + +#define STATE_M0 0 +#define STATE_M1 1 +#define STATE_M2 2 +#define STATE_M3 3 +#define STATE_M4 4 +#define STATE_M5 5 +#define STATE_M6 6 +#define STATE_VERIFIED 0x55 +#define STATE_INVALID 0xaa + +typedef enum { + HAP_METHOD_RESERVED = 0, + HAP_METHOD_PAIR_SETUP = 1, + HAP_METHOD_PAIR_VERIFY = 2, + HAP_METHOD_ADD_PAIRING = 3, + HAP_METHOD_REMOVE_PAIRING = 4, + HAP_METHOD_LIST_PAIRINGS = 5, +} hap_pairing_methods_t; + + +typedef enum { + kTLVError_Unknown = 0x01, + kTLVError_Authentication = 0x02, + kTLVError_Backoff = 0x03, + kTLVError_MaxPeers = 0x04, + kTLVError_MaxTries = 0x05, + kTLVError_Unavailable = 0x06, + kTLVError_Busy = 0x07, +} hap_tlv_error_t; + +typedef enum { + kTLVType_Method = 0x00, + kTLVType_Identifier = 0x01, + kTLVType_Salt = 0x02, + kTLVType_PublicKey = 0x03, + kTLVType_Proof = 0x04, + kTLVType_EncryptedData = 0x05, + kTLVType_State = 0x06, + kTLVType_Error = 0x07, + kTLVType_RetryDelay = 0x08, + kTLVType_Certificate = 0x09, + kTLVType_Signature = 0x0a, + kTLVType_Permissions = 0x0b, + kTLVType_FragmentedData = 0x0c, + kTLVType_FragmentLast = 0x0d, + kTLVType_Flags = 0x13, + kTLVType_OwnershipProofToken = 0x1A, + kTLVType_ProductData = 0x1C, + kTLVType_Separator = 0xff, +} hap_tlv_type_t; + +typedef struct { + uint8_t *bufptr; + int bufsize; + int curlen; +} hap_tlv_data_t; + +typedef struct { + uint8_t state; + uint8_t encrypt_key[ENCRYPT_KEY_LEN]; + uint8_t decrypt_key[ENCRYPT_KEY_LEN]; + uint8_t encrypt_nonce[NONCE_LEN]; + uint8_t decrypt_nonce[NONCE_LEN]; + hap_ctrl_data_t *ctrl; + uint64_t pid; + int64_t ttl; + int64_t prepare_time; + /* TODO: As of now, this identifier will be the socket + * number, since only http is supported. + * Need to make this generic later. + */ + int conn_identifier; +} hap_secure_session_t; + +void hap_tlv_data_init(hap_tlv_data_t *tlv_data, uint8_t *buf, int buf_size); +int get_value_from_tlv(uint8_t *buf, int buf_len, uint8_t type, void *val, int val_size); +int get_tlv_length(uint8_t *buf, int buflen, uint8_t type); +int add_tlv(hap_tlv_data_t *tlv_data, uint8_t type, int len, void *val); +void hap_prepare_error_tlv(uint8_t state, uint8_t error, void *buf, int buf_size, int *out_len); +#endif /* _HAP_PAIR_COMMON_H_ */ diff --git a/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_pair_setup.c b/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_pair_setup.c new file mode 100644 index 000000000..995158d35 --- /dev/null +++ b/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_pair_setup.c @@ -0,0 +1,563 @@ +/* + * ESPRESSIF MIT License + * + * Copyright (c) 2020 + * + * Permission is hereby granted for use on ESPRESSIF SYSTEMS products only, in which case, + * it is 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +/* Maximum attempts allowed for Pair Setup, as per HAP Specifications */ +#define HAP_PAIR_SETUP_MAX_ATTEMPTS 100 + +#define PAIR_SETUP_ENCRYPT_SALT "Pair-Setup-Encrypt-Salt" +#define PAIR_SETUP_ENCRYPT_INFO "Pair-Setup-Encrypt-Info" +#define PAIR_SETUP_CTRL_SIGN_SALT "Pair-Setup-Controller-Sign-Salt" +#define PAIR_SETUP_CTRL_SIGN_INFO "Pair-Setup-Controller-Sign-Info" +#define PAIR_SETUP_ACC_SIGN_SALT "Pair-Setup-Accessory-Sign-Salt" +#define PAIR_SETUP_ACC_SIGN_INFO "Pair-Setup-Accessory-Sign-Info" + +#define PS_CTX_INIT 1 +#define PS_CTX_DEINIT 2 + +/* Timeout if pair setup not completed in 1 minute (60sec)*/ +#define HAP_SETUP_TIMEOUT_IN_TICKS ((40 * 1000) / hap_platform_os_get_msec_per_tick()) + +static int hap_pair_setup_process_srp_start(pair_setup_ctx_t *ps_ctx, uint8_t *buf, int inlen, + int bufsize, int *outlen) +{ + /* Pair setup is not allowed if the accessory is already paired */ + if (is_accessory_paired()) { + ESP_MFI_DEBUG(ESP_MFI_DEBUG_ERR, "Accessory is already paired. " + "Please use \"Add Pairing\" to add more controllers"); + hap_prepare_error_tlv(STATE_M2, kTLVError_Unavailable, buf, bufsize, outlen); + return HAP_FAIL; + } + + /* Pair Setup is not allowed if the failed attempts have exceeded the + * maximum allowed attempts. + */ + if (hap_priv.pair_attempts >= HAP_PAIR_SETUP_MAX_ATTEMPTS) { + ESP_MFI_DEBUG(ESP_MFI_DEBUG_ERR, "Too many attempts. Aborting"); + hap_prepare_error_tlv(STATE_M2, kTLVError_MaxTries, buf, bufsize, outlen); + return HAP_FAIL; + } + + ps_ctx->ctrl = hap_controller_get_empty_loc(); + if (!ps_ctx->ctrl) { + ESP_MFI_DEBUG(ESP_MFI_DEBUG_ERR, "No empty controller slot. Aborting"); + hap_prepare_error_tlv(STATE_M2, kTLVError_Unknown, buf, bufsize, outlen); + return HAP_FAIL; + } + + uint8_t state; + if ((get_value_from_tlv(buf, inlen, kTLVType_State, &state, sizeof(state)) < 0) || + (get_value_from_tlv(buf, inlen, kTLVType_Method, + &ps_ctx->method, sizeof(ps_ctx->method)) < 0)) { + ESP_MFI_DEBUG(ESP_MFI_DEBUG_ERR, "Invalid TLVs received"); + hap_prepare_error_tlv(STATE_M2, kTLVError_Unknown, buf, bufsize, outlen); + return HAP_FAIL; + } + if (state != STATE_M1) { + ESP_MFI_DEBUG(ESP_MFI_DEBUG_ERR, "Incorrect State received"); + hap_prepare_error_tlv(STATE_M2, kTLVError_Unknown, buf, bufsize, outlen); + return HAP_FAIL; + } + ESP_MFI_DEBUG(ESP_MFI_DEBUG_INFO, "Pair Setup M1 Received"); + + int flags_len; + if ((flags_len = get_value_from_tlv(buf, inlen, kTLVType_Flags, &ps_ctx->pairing_flags, sizeof(ps_ctx->pairing_flags))) > 0) { + ps_ctx->pairing_flags_len = flags_len; + ESP_MFI_DEBUG(ESP_MFI_DEBUG_INFO, "Got pairing flags %x", ps_ctx->pairing_flags); + + /* If the Split pairing flag is not set, it is an error */ + if (!(ps_ctx->pairing_flags & PAIR_FLAG_SPLIT)) { + ESP_MFI_DEBUG(ESP_MFI_DEBUG_ERR, "Pairing Flags received, but the Split flag is not set"); + hap_prepare_error_tlv(STATE_M2, kTLVError_Unknown, buf, bufsize, outlen); + return HAP_FAIL; + } + + /* If either the current or the previous request didn't have transient flag set, return authentication error */ + if (!((ps_ctx->pairing_flags | hap_priv.pairing_flags) & PAIR_FLAG_TRANSIENT)) { + ESP_MFI_DEBUG(ESP_MFI_DEBUG_ERR, "Split pairing received before preceding Transient Pairing"); + hap_prepare_error_tlv(STATE_M2, kTLVError_Authentication, buf, bufsize, outlen); + return HAP_FAIL; + } + } + hap_priv.pairing_flags = ps_ctx->pairing_flags; + + int len_B = 0; + char *bytes_B; + + /* Create SRP Salt and Verifier for the provided pairing PIN */ + mu_srp_init(&ps_ctx->srp_hd, MU_NG_3072); + + /* If a setup code is explicitly set, use it */ + if (hap_priv.setup_code) { + ps_ctx->len_s = 16; + mu_srp_srv_pubkey(&ps_ctx->srp_hd, "Pair-Setup", (const char*)hap_priv.setup_code, strlen(hap_priv.setup_code), + ps_ctx->len_s, &bytes_B, &len_B, &ps_ctx->bytes_s); + } else { + /* Else, use the salt and verifier for SRP. This should be the default production case + */ + if (mu_srp_set_salt_verifier(&ps_ctx->srp_hd, (char *)hap_priv.setup_info->salt, sizeof(hap_priv.setup_info->salt), + (char *)hap_priv.setup_info->verifier, sizeof(hap_priv.setup_info->verifier)) < 0) { + ESP_MFI_DEBUG(ESP_MFI_DEBUG_ERR, "SRP-6a Salt-Verifier Init Failed"); + hap_prepare_error_tlv(STATE_M2, kTLVError_Unknown, buf, bufsize, outlen); + return HAP_FAIL; + } + ps_ctx->bytes_s = (char *)hap_priv.setup_info->salt; + ps_ctx->len_s = sizeof(hap_priv.setup_info->salt); + mu_srp_srv_pubkey_from_salt_verifier(&ps_ctx->srp_hd, &bytes_B, &len_B); + } + if (!ps_ctx->bytes_s || !bytes_B) { + ESP_MFI_DEBUG(ESP_MFI_DEBUG_ERR, "SRP-6a Verifier Creation Failed"); + hap_prepare_error_tlv(STATE_M2, kTLVError_Unknown, buf, bufsize, outlen); + return HAP_FAIL; + } + + hex_dbg_with_name("salt", (uint8_t *)ps_ctx->bytes_s, ps_ctx->len_s); + hex_dbg_with_name("acc_srp_public_key", (uint8_t *)bytes_B, len_B); + + /* Construct the response M2 */ + hap_tlv_data_t tlv_data; + tlv_data.bufptr = buf; + tlv_data.bufsize = bufsize; + tlv_data.curlen = 0; + state = STATE_M2; + if ((add_tlv(&tlv_data, kTLVType_State, 1, &state) < 0) || + (add_tlv(&tlv_data, kTLVType_PublicKey, len_B, (void *)bytes_B) < 0) || + (add_tlv(&tlv_data, kTLVType_Salt, ps_ctx->len_s, ps_ctx->bytes_s) < 0 )) { + hap_prepare_error_tlv(STATE_M2, kTLVError_Unknown, buf, bufsize, outlen); + return HAP_FAIL; + } + /* Not adding any error check here, because without the pairing flags, the pairing will + * anyways fail later. + */ + if (ps_ctx->pairing_flags_len) { + add_tlv(&tlv_data, kTLVType_Flags, ps_ctx->pairing_flags_len, &ps_ctx->pairing_flags); + } + *outlen = tlv_data.curlen; + ps_ctx->state = state; + ESP_MFI_DEBUG(ESP_MFI_DEBUG_INFO, "Pair Setup M2 Successful"); + hap_report_event(HAP_EVENT_PAIRING_STARTED, NULL, 0); + return HAP_SUCCESS; +} + + +static int hap_pair_setup_process_srp_verify(pair_setup_ctx_t *ps_ctx, uint8_t *buf, int inlen, + int bufsize, int *outlen) +{ + uint8_t state; + char ctrl_public_key[384]; + int ctrl_public_key_len; + char ctrl_proof[64]; + int ctrl_proof_len; + + if ((get_value_from_tlv(buf, inlen, kTLVType_State, &state, sizeof(state)) < 0) || + ((ctrl_public_key_len = get_value_from_tlv(buf, inlen, kTLVType_PublicKey, + ctrl_public_key, sizeof(ctrl_public_key))) < 0) || + ((ctrl_proof_len = get_value_from_tlv(buf, inlen, kTLVType_Proof, + ctrl_proof, sizeof(ctrl_proof))) < 0)) { + ESP_MFI_DEBUG(ESP_MFI_DEBUG_ERR, "Invalid TLVs received"); + hap_prepare_error_tlv(STATE_M4, kTLVError_Unknown, buf, bufsize, outlen); + return HAP_FAIL; + } + if (state != STATE_M3) { + ESP_MFI_DEBUG(ESP_MFI_DEBUG_ERR, "Incorrect State received"); + hap_prepare_error_tlv(STATE_M4, kTLVError_Unknown, buf, bufsize, outlen); + return HAP_FAIL; + } + ESP_MFI_DEBUG(ESP_MFI_DEBUG_INFO, "Pair Setup M3 Received"); + + hex_dbg_with_name("ctrl_srp_public_key", (uint8_t *)ctrl_public_key, ctrl_public_key_len); + hex_dbg_with_name("ctrl_proof", (uint8_t *)ctrl_proof, ctrl_proof_len); + mu_srp_get_session_key(&ps_ctx->srp_hd, ctrl_public_key, ctrl_public_key_len, &ps_ctx->shared_secret, &ps_ctx->secret_len); + char host_proof[SHA512HashSize]; + int ret = mu_srp_exchange_proofs(&ps_ctx->srp_hd, "Pair-Setup", ctrl_proof, host_proof); + if (ret != 1) { + ESP_MFI_DEBUG(ESP_MFI_DEBUG_ERR, "SRP Verify: Controller Authentication failed"); + hap_prepare_error_tlv(STATE_M4, kTLVError_Authentication, buf, bufsize, outlen); + hap_report_event(HAP_EVENT_PAIRING_ABORTED, NULL, 0); + return HAP_FAIL; + } + int acc_proof_length = SHA512HashSize; + + hkdf(SHA512, (uint8_t *) PAIR_SETUP_ENCRYPT_SALT, strlen(PAIR_SETUP_ENCRYPT_SALT), + (uint8_t *)ps_ctx->shared_secret, ps_ctx->secret_len, + (uint8_t *) PAIR_SETUP_ENCRYPT_INFO, strlen(PAIR_SETUP_ENCRYPT_INFO), + ps_ctx->session_key, sizeof(ps_ctx->session_key)); + + /* Construct the response M4 */ + hap_tlv_data_t tlv_data; + tlv_data.bufptr = buf; + tlv_data.bufsize = bufsize; + tlv_data.curlen = 0; + state = STATE_M4; + if ((add_tlv(&tlv_data, kTLVType_State, 1, &state) < 0) || + (add_tlv(&tlv_data, kTLVType_Proof, acc_proof_length, + (void *)host_proof) < 0)) { + hap_prepare_error_tlv(STATE_M4, kTLVError_Unknown, buf, bufsize, outlen); + ESP_MFI_DEBUG(ESP_MFI_DEBUG_ERR, "TLV creation failed"); + return HAP_FAIL; + } + hap_tlv_error_t tlv_error = 0; + if (hap_pair_setup_manage_mfi_auth(ps_ctx, &tlv_data, &tlv_error) != ESP_OK) { + hap_prepare_error_tlv(STATE_M4, tlv_error, buf, bufsize, outlen); + return HAP_FAIL; + } + *outlen = tlv_data.curlen; + ps_ctx->state = state; + ESP_MFI_DEBUG(ESP_MFI_DEBUG_INFO, "Pair Setup M4 Successful"); + return HAP_SUCCESS; +} +static int hap_pair_setup_process_exchange(pair_setup_ctx_t *ps_ctx, uint8_t *buf, int inlen, + int bufsize, int *outlen) +{ + uint8_t state; + uint8_t edata[220]; + int edata_len; + int ret; + + if ((get_value_from_tlv(buf, inlen, kTLVType_State, &state, sizeof(state)) < 0) || + ((edata_len = get_value_from_tlv(buf, inlen, kTLVType_EncryptedData, + edata, sizeof(edata))) < 0)) { + ESP_MFI_DEBUG(ESP_MFI_DEBUG_ERR, "Invalid TLVs received"); + hap_prepare_error_tlv(STATE_M6, kTLVError_Unknown, buf, bufsize, outlen); + return HAP_FAIL; + } + hex_dbg_with_name("recv_encrypted_data", edata, edata_len); + if (state != STATE_M5) { + ESP_MFI_DEBUG(ESP_MFI_DEBUG_ERR, "Incorrect State received"); + hap_prepare_error_tlv(STATE_M6, kTLVError_Unknown, buf, bufsize, outlen); + return HAP_FAIL; + } + ESP_MFI_DEBUG(ESP_MFI_DEBUG_INFO, "Pair Setup M5 Received"); + edata_len -= 16; /* 16 bytes for the authTag */ + uint8_t newnonce[12]; + memset(newnonce, 0, sizeof newnonce); + memcpy(newnonce+4, (uint8_t *)PS_NONCE2, 8); + ret = crypto_aead_chacha20poly1305_ietf_decrypt_detached(edata, NULL, edata, edata_len, + &edata[edata_len], NULL, 0, newnonce, ps_ctx->session_key); + if (ret != 0) { + ESP_MFI_DEBUG(ESP_MFI_DEBUG_ERR, "Decryption Failed"); + hap_prepare_error_tlv(STATE_M6, kTLVError_Authentication, buf, bufsize, outlen); + return HAP_FAIL; + } + hex_dbg_with_name("subtlv", edata, edata_len); + int ctrl_id_len; + unsigned char ed_sign[64]; + unsigned long long ed_sign_len; + if (((ctrl_id_len = get_value_from_tlv(edata, edata_len, kTLVType_Identifier, + ps_ctx->ctrl->info.id, sizeof(ps_ctx->ctrl->info.id))) < 0) || + (get_value_from_tlv(edata, edata_len, kTLVType_PublicKey, + ps_ctx->ctrl->info.ltpk, ED_KEY_LEN) != ED_KEY_LEN) || + (get_value_from_tlv(edata, edata_len, kTLVType_Signature, + ed_sign, sizeof(ed_sign)) != sizeof(ed_sign))) { + ESP_MFI_DEBUG(ESP_MFI_DEBUG_ERR, "Invalid subTLV received"); + hap_prepare_error_tlv(STATE_M6, kTLVError_Authentication, buf, bufsize, outlen); + return HAP_FAIL; + } + ps_ctx->ctrl->info.id[ctrl_id_len] = 0; /* NULL termination */ + hex_dbg_with_name("ctrl_id", (uint8_t *)ps_ctx->ctrl->info.id, ctrl_id_len); + hex_dbg_with_name("ltpkc", ps_ctx->ctrl->info.ltpk, ED_KEY_LEN); + hex_dbg_with_name("ctrl_sign", ed_sign, sizeof(ed_sign)); + + /* Derive iOSDeviceX from SRP shared secret using HKDF-SHA512 */ + uint8_t ios_device_x[32]; + hkdf(SHA512, (unsigned char *) PAIR_SETUP_CTRL_SIGN_SALT, + strlen(PAIR_SETUP_CTRL_SIGN_SALT), (uint8_t *)ps_ctx->shared_secret, ps_ctx->secret_len, + (unsigned char *) PAIR_SETUP_CTRL_SIGN_INFO, + strlen(PAIR_SETUP_CTRL_SIGN_INFO), + ios_device_x, sizeof(ios_device_x)); + /* Construct iOSDeviceInfo by concatenating + * iOSDeviceX + * iOSDevicePairingID (ctrl_id) + * iOSDeviceLTPK (ltpkc) + */ + uint8_t info_buf[HAP_CTRL_ID_LEN + 32 + ED_KEY_LEN]; + uint8_t *ios_dev_info = info_buf; + int ios_dev_info_len = 0; + memcpy(ios_dev_info, ios_device_x, sizeof(ios_device_x)); + ios_dev_info_len += sizeof(ios_device_x); + memcpy(&ios_dev_info[ios_dev_info_len], ps_ctx->ctrl->info.id, ctrl_id_len); + ios_dev_info_len += ctrl_id_len; + memcpy(&ios_dev_info[ios_dev_info_len], ps_ctx->ctrl->info.ltpk, ED_KEY_LEN); + ios_dev_info_len += ED_KEY_LEN; + + ret = crypto_sign_ed25519_verify_detached(ed_sign, ios_dev_info, ios_dev_info_len, ps_ctx->ctrl->info.ltpk); + /* Verify Signature of constructed iOSDeviceInfo using the iOSDeviceLTPK */ + if (ret != 0) { + ESP_MFI_DEBUG(ESP_MFI_DEBUG_ERR, "Invalid Signature"); + hap_prepare_error_tlv(STATE_M6, kTLVError_Authentication, buf, bufsize, outlen); + return HAP_FAIL; + } + + hex_dbg_with_name("ltpka", hap_priv.ltpka, sizeof(hap_priv.ltpka)); + + /* Derive AccessoryX from the SRP shared secret using HKDF-SHA512 */ + uint8_t acc_x[32]; + hkdf(SHA512, (unsigned char *) PAIR_SETUP_ACC_SIGN_SALT, + strlen(PAIR_SETUP_ACC_SIGN_SALT), (uint8_t *)ps_ctx->shared_secret, ps_ctx->secret_len, + (unsigned char *) PAIR_SETUP_ACC_SIGN_INFO, + strlen(PAIR_SETUP_ACC_SIGN_INFO), + acc_x, sizeof(acc_x)); + /* Construct AccessoryInfo by concatenating + * AccessoryX + * AccessoryPairingID (acc_id) + * AccessoryLTPK (ltpka) + */ + uint8_t *acc_info = info_buf; + int acc_info_len = 0; + memcpy(acc_info, acc_x, sizeof(acc_x)); + acc_info_len += sizeof(acc_x); + memcpy(&ios_dev_info[acc_info_len], hap_priv.acc_id, strlen(hap_priv.acc_id)); + acc_info_len += strlen(hap_priv.acc_id); + memcpy(&ios_dev_info[acc_info_len], hap_priv.ltpka, sizeof(hap_priv.ltpka)); + acc_info_len += sizeof(hap_priv.ltpka); + + /* Generate AccessorySignature by signing AccessoryInfo with AccessoryLTSK + */ + crypto_sign_ed25519_detached(ed_sign, &ed_sign_len, acc_info, acc_info_len, hap_priv.ltska); + hex_dbg_with_name("acc_sign", ed_sign, sizeof(ed_sign)); + + /* Create subTLV with: + * kTLVType_Identifier : Accessory ID (acc_id) + * kTLVType_PublicKey : Accessory LTPK + * kTLVType_Signature : AccessorySignature + */ + + uint8_t subtlv[6 + HAP_ACC_ID_LEN + ED_KEY_LEN + ED_SIGN_LEN + POLY_AUTHTAG_LEN]; + + hap_tlv_data_t tlv_data; + tlv_data.bufptr = subtlv; + tlv_data.bufsize = sizeof(subtlv); + tlv_data.curlen = 0; + add_tlv(&tlv_data, kTLVType_Identifier, strlen(hap_priv.acc_id), hap_priv.acc_id); + add_tlv(&tlv_data, kTLVType_PublicKey, sizeof(hap_priv.ltpka), hap_priv.ltpka); + add_tlv(&tlv_data, kTLVType_Signature, sizeof(ed_sign), ed_sign); + int subtlv_len = tlv_data.curlen; + hex_dbg_with_name("subtlv", subtlv, subtlv_len); + + /* Encrypt the subTLV using the session key */ + + unsigned long long mlen = 16; + memset(newnonce, 0, sizeof newnonce); + memcpy(newnonce+4, (uint8_t *) PS_NONCE3, 8); + crypto_aead_chacha20poly1305_ietf_encrypt_detached(subtlv, &subtlv[subtlv_len], &mlen, subtlv, + subtlv_len, NULL, 0, NULL, newnonce, ps_ctx->session_key); + hex_dbg_with_name("send_encrypt_data", subtlv, subtlv_len + 16); + + /* Construct the response M6 */ + tlv_data.bufptr = buf; + tlv_data.bufsize = bufsize; + tlv_data.curlen = 0; + state = STATE_M6; + if ((add_tlv(&tlv_data, kTLVType_State, 1, &state) < 0) || + (add_tlv(&tlv_data, kTLVType_EncryptedData, subtlv_len + 16, + subtlv) < 0)) { + hap_prepare_error_tlv(STATE_M4, kTLVError_Unknown, buf, bufsize, outlen); + return HAP_FAIL; + } + *outlen = tlv_data.curlen; + ps_ctx->state = state; + ps_ctx->ctrl->info.perms = 1; /* Controller added using pair setup is always an admin */ + ESP_MFI_DEBUG(ESP_MFI_DEBUG_INFO, "Pair Setup Successful for %s", ps_ctx->ctrl->info.id); + /* Reset the Pairing Attempts count */ + hap_priv.pair_attempts = 0; + hap_controller_save(ps_ctx->ctrl); + hap_send_event(HAP_INTERNAL_EVENT_ACC_PAIRED); + return HAP_SUCCESS; +} +static uint8_t hap_pair_setup_get_received_state(uint8_t *buf, int inlen) +{ + uint8_t state = 0; + get_value_from_tlv(buf, inlen, kTLVType_State, &state, sizeof(state)); + return state; +} + +static void hap_pair_setup_timeout(TimerHandle_t handle) +{ + ESP_MFI_DEBUG(ESP_MFI_DEBUG_ERR, "Clearing Pair Setup Context due to inactivity"); + pair_setup_ctx_t *ps_ctx = pvTimerGetTimerID(handle); + if (ps_ctx) { + httpd_sess_trigger_close(hap_priv.server, ps_ctx->sock_fd); + hap_report_event(HAP_EVENT_PAIRING_ABORTED, NULL, 0); + } +} + +/* Pair Setup can have only a single context at a time as the specification does not allow + * multiple controllers to perform Pair Setup Simultaneously. + * + * The purpose of this function is to manage allocation and resetting of the context by + * using a static variable rather than a global variable. + */ +static pair_setup_ctx_t *hap_pair_setup_ctx_action(int action) +{ + static pair_setup_ctx_t *ps_ctx; + /* If the call is to initialise the context, check if it is already + * initialised. + */ + if (action == PS_CTX_INIT) { + /* If the context is already initialised, it means that pair setup + * is already in progress. So, return NULL. + * Else, allocate the context. + */ + if (ps_ctx) + return NULL; + else { + ps_ctx = hap_platform_memory_calloc(sizeof(pair_setup_ctx_t), 1); + if (ps_ctx) { + ps_ctx->timer = xTimerCreate("hap_setup_timer", HAP_SETUP_TIMEOUT_IN_TICKS, + pdFALSE, (void *) ps_ctx, hap_pair_setup_timeout); + xTimerStart(ps_ctx->timer, 0); + } + } + } else if (action == PS_CTX_DEINIT) { + /* If the call is to de-initialise the context, clean it up + * and set the pointer to NULL + */ + if (ps_ctx) { + if (ps_ctx->timer) { + xTimerStop(ps_ctx->timer, 0); + xTimerDelete(ps_ctx->timer, 100); + } + mu_srp_free(&ps_ctx->srp_hd); + hap_platform_memory_free(ps_ctx); + } + ps_ctx = NULL; + } + return ps_ctx; +} + + +void hap_pair_setup_ctx_clean(void *sess_ctx) +{ + if (sess_ctx) { + ESP_MFI_DEBUG(ESP_MFI_DEBUG_INFO, "Cleaning Pair Setup Context"); + hap_pair_setup_ctx_action(PS_CTX_DEINIT); + } +} + +int hap_pair_setup_context_init(int sock_fd, void **ctx, uint8_t *buf, int bufsize, int *outlen) +{ + pair_setup_ctx_t *ps_ctx = hap_pair_setup_ctx_action(PS_CTX_INIT); + + if (!ps_ctx) { + ESP_MFI_DEBUG(ESP_MFI_DEBUG_ERR,"######## Aborted! Pair Setup in Progress with another controller ########"); + hap_prepare_error_tlv(STATE_M2, kTLVError_Busy, buf, bufsize, outlen); + return HAP_FAIL; + } + ps_ctx->sock_fd = sock_fd; + *ctx = ps_ctx; + ESP_MFI_DEBUG(ESP_MFI_DEBUG_INFO, "######## Starting Pair Setup ########"); + return HAP_SUCCESS; + +} +int hap_pair_setup_process(void **ctx, uint8_t *buf, int inlen, int bufsize, int *outlen) +{ + pair_setup_ctx_t *ps_ctx = (pair_setup_ctx_t *)(*ctx); + + uint8_t recv_state = hap_pair_setup_get_received_state(buf, inlen); + if (!ps_ctx) { + hap_prepare_error_tlv(recv_state + 1, kTLVError_Unknown, buf, bufsize, outlen); + return HAP_FAIL; + } + /* Receiving STATE_M1 in the message while the pair-setup was already in progress means + * that pair setup was restarted. Handle it accordingly + */ + if ((recv_state == STATE_M1) && (ps_ctx->state != STATE_M0)) { + ESP_MFI_DEBUG(ESP_MFI_DEBUG_INFO, "Restarting Pair Setup"); + int sock_fd = ps_ctx->sock_fd; + hap_pair_setup_ctx_clean(ps_ctx); + int ret = hap_pair_setup_context_init(sock_fd, ctx, buf, bufsize, outlen); + if (ret != HAP_SUCCESS) + return ret; + ps_ctx = (pair_setup_ctx_t *)(*ctx); + } + if (ps_ctx->state == STATE_M0) { + return hap_pair_setup_process_srp_start(ps_ctx, buf, inlen, bufsize, outlen); + } else if (ps_ctx->state == STATE_M2) { + hap_priv.pair_attempts++; + int ret = hap_pair_setup_process_srp_verify(ps_ctx, buf, inlen, bufsize, outlen); + if (ps_ctx->session) { + *ctx = ps_ctx->session; + hap_pair_setup_ctx_clean(ps_ctx); + } + return ret; + } else if (ps_ctx->state == STATE_M4) { + int ret = hap_pair_setup_process_exchange(ps_ctx, buf, inlen, bufsize, outlen); + /* If last step of pair setup is successful, it means that the context would + * be no more required. Hence, clear it. + */ + if (ret == HAP_SUCCESS) { + hap_pair_setup_ctx_clean(ps_ctx); + *ctx = NULL; + } + return ret; + } + hap_prepare_error_tlv(STATE_M2, kTLVError_Unknown, buf, bufsize, outlen); + return HAP_FAIL; +} + +void hap_set_setup_code(const char *setup_code) +{ + if (hap_priv.setup_code) + hap_platform_memory_free(hap_priv.setup_code); + hap_priv.setup_code = strdup(setup_code); +} + +int hap_set_setup_info(const hap_setup_info_t *setup_info) +{ + if (!setup_info) + return HAP_FAIL; + if (hap_priv.setup_info) + hap_platform_memory_free(hap_priv.setup_info); + hap_priv.setup_info = hap_platform_memory_calloc(1, sizeof(hap_setup_info_t)); + if (!hap_priv.setup_info) + return HAP_FAIL; + memcpy(hap_priv.setup_info, setup_info, sizeof(hap_setup_info_t)); + return HAP_SUCCESS; +} + +int hap_set_setup_id(const char *setup_id) +{ + if (setup_id == NULL || strlen(setup_id) != SETUP_ID_LEN) + return HAP_FAIL; + strcpy(hap_priv.setup_id, setup_id); + return HAP_SUCCESS; +} diff --git a/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_pair_setup.h b/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_pair_setup.h new file mode 100644 index 000000000..a79e27a2f --- /dev/null +++ b/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_pair_setup.h @@ -0,0 +1,60 @@ +/* + * ESPRESSIF MIT License + * + * Copyright (c) 2020 + * + * Permission is hereby granted for use on ESPRESSIF SYSTEMS products only, in which case, + * it is 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. + * + */ +#ifndef _HAP_PAIR_SETUP_H_ +#define _HAP_PAIR_SETUP_H_ +#include +#include +#include +#include +#include + +#define PS_NONCE1 "PS-Msg04" +#define PS_NONCE2 "PS-Msg05" +#define PS_NONCE3 "PS-Msg06" + +#define PAIR_FLAG_TRANSIENT 0x00000010 +#define PAIR_FLAG_SPLIT 0x01000000 + + +typedef struct { + uint8_t state; + uint8_t method; + uint32_t pairing_flags; + int8_t pairing_flags_len; + int len_s; + char *bytes_s; + int secret_len; + char *shared_secret; + mu_srp_handle_t srp_hd; + hap_ctrl_data_t *ctrl; + uint8_t session_key[32]; + TimerHandle_t timer; + hap_secure_session_t *session; + int sock_fd; +} pair_setup_ctx_t; +int hap_pair_setup_context_init(int sock_fd, void **ctx, uint8_t *buf, int bufsize, int *outlen); +int hap_pair_setup_process(void **ctx, uint8_t *buf, int inlen, int bufsize, int *outlen); +void hap_pair_setup_ctx_clean(void *sess_ctx); +int hap_pair_setup_manage_mfi_auth(pair_setup_ctx_t *ps_ctx, hap_tlv_data_t *tlv_data, hap_tlv_error_t *tlv_error); +#endif /* _HAP_PAIR_SETUP_H_ */ diff --git a/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_pair_verify.c b/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_pair_verify.c new file mode 100644 index 000000000..6c62bbfc0 --- /dev/null +++ b/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_pair_verify.c @@ -0,0 +1,464 @@ +/* + * ESPRESSIF MIT License + * + * Copyright (c) 2020 + * + * Permission is hereby granted for use on ESPRESSIF SYSTEMS products only, in which case, + * it is 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 +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#define PAIR_VERIFY_ENCRYPT_SALT "Pair-Verify-Encrypt-Salt" +#define PAIR_VERIFY_ENCRYPT_INFO "Pair-Verify-Encrypt-Info" +#define PV_NONCE1 "PV-Msg02" +#define PV_NONCE2 "PV-Msg03" +#define CONTROL_SALT "Control-Salt" +#define CONTROL_READ_INFO "Control-Read-Encryption-Key" +#define CONTROL_WRITE_INFO "Control-Write-Encryption-Key" + +typedef struct { + /* It is important that "state" should be the first element of the structure. + * It will be the first element, even in hap_secure_session_t. + * This will be useful while checking the state from the context, irrespective + * of whether the context points to pair_verify_ctx_t or hap_secure_session_t. + */ + uint8_t state; + uint8_t ctrl_curve_pk[CURVE_KEY_LEN]; + uint8_t acc_curve_pk[CURVE_KEY_LEN]; + uint8_t hkdf_key[ENCRYPT_KEY_LEN]; + uint8_t shared_secret[CURVE_KEY_LEN]; + hap_secure_session_t *session; +} pair_verify_ctx_t; + +void hap_close_ctrl_sessions(hap_ctrl_data_t *ctrl) +{ + if (!ctrl) + return; + int i; + printf("---- hap_close_ctrl_sessions begin -----\n"); + for (i = 0; i < HAP_MAX_SESSIONS; i++) { + if (!hap_priv.sessions[i]) + continue; + if (hap_priv.sessions[i]->ctrl == ctrl) { + hap_report_event(HAP_EVENT_CTRL_DISCONNECTED, (ctrl->info.id), + sizeof((ctrl->info.id))); + /* TODO: Use some generic function and not a direct HTTPD function + */ + printf("---- trigger_close fd: %d\n", hap_priv.sessions[i]->conn_identifier); + httpd_sess_trigger_close(hap_priv.server, hap_priv.sessions[i]->conn_identifier); + break; + } + } + printf("----hap_close_ctrl_sessions end ----\n"); +} + +int hap_get_ctrl_session_index(hap_secure_session_t *session) +{ + int i; + for (i = 0; i < HAP_MAX_SESSIONS; i++) { + if (hap_priv.sessions[i] == session) + return i; + } + return -1; +} + +void hap_close_all_sessions() +{ + int i; + for (i = 0; i < HAP_MAX_SESSIONS; i++) { + if (hap_priv.sessions[i]) { + ESP_MFI_DEBUG(ESP_MFI_DEBUG_INFO, "Closing Session"); + hap_close_ctrl_sessions(hap_priv.sessions[i]->ctrl); + } + } +} + +static void hap_add_secure_session(hap_secure_session_t *session) +{ + int i; + for (i = 0; i < HAP_MAX_SESSIONS; i++) { + if (hap_priv.sessions[i] == NULL) { + hap_priv.sessions[i] = session; + hap_report_event(HAP_EVENT_CTRL_CONNECTED, session->ctrl->info.id, + sizeof(session->ctrl->info.id)); + /* Set the disconnected_event_sent flag here to false so that an + * event can be sent later for a state change, when no controller + * is connected. + * HAP Spec R15 say that the state number should change only once + * between accessory disconneted (from all controllers) to connected + * state. + */ + hap_priv.disconnected_event_sent = false; + //ESP_MFI_DEBUG(ESP_MFI_DEBUG_INFO, "HomeKit Session active"); + ESP_MFI_DEBUG(ESP_MFI_DEBUG_INFO, "HomeKit Session active, fd: %d", session->conn_identifier); + break; + } + } +} + +void hap_free_session(void *session) +{ + if (!session) + return; + int i; + for (i = 0; i < HAP_MAX_SESSIONS; i++) { + if (hap_priv.sessions[i] == session) { + /* Disable all characteristic notifications on this session */ + int fd = (hap_priv.sessions[i])->conn_identifier; + hap_disable_all_char_notif(i); + hap_priv.sessions[i] = NULL; + //ESP_MFI_DEBUG(ESP_MFI_DEBUG_INFO, "HomeKit Session terminated"); + ESP_MFI_DEBUG(ESP_MFI_DEBUG_INFO, "HomeKit Session terminated, fd: %d", fd); + break; + } + } + hap_platform_memory_free(session); +} + +static int hap_pair_verify_process_start(pair_verify_ctx_t *pv_ctx, uint8_t *buf, int inlen, + int bufsize, int *outlen) +{ + /* Parse the data received from the controller */ + uint8_t state; + if (!pv_ctx) { + ESP_MFI_DEBUG(ESP_MFI_DEBUG_ERR, "No context"); + hap_prepare_error_tlv(STATE_M2, kTLVError_Unknown, buf, bufsize, outlen); + return HAP_FAIL; + } + if ((get_value_from_tlv(buf, inlen, kTLVType_State, &state, sizeof(state)) < 0) || + (get_value_from_tlv(buf, inlen, kTLVType_PublicKey, pv_ctx->ctrl_curve_pk, + CURVE_KEY_LEN) < 0)) { + ESP_MFI_DEBUG(ESP_MFI_DEBUG_ERR, "Invalid TLVs received"); + hap_prepare_error_tlv(STATE_M2, kTLVError_Unknown, buf, bufsize, outlen); + return HAP_FAIL; + } + if (state != STATE_M1) { + ESP_MFI_DEBUG(ESP_MFI_DEBUG_ERR, "Incorrect State received"); + hap_prepare_error_tlv(STATE_M2, kTLVError_Unknown, buf, bufsize, outlen); + return HAP_FAIL; + } + + ESP_MFI_DEBUG(ESP_MFI_DEBUG_INFO, "Pair Verify M1 Received"); + hex_dbg_with_name("ctrl curve pk", pv_ctx->ctrl_curve_pk, 32); + + /* Generate a new Curve25519 Key Pair */ + uint8_t acc_curve_sk[CURVE_KEY_LEN]; + esp_mfi_get_random(acc_curve_sk, CURVE_KEY_LEN); + /* This particular value of basepoint is required to generate the public key + * from secret key + */ + uint8_t basepoint[32] = {9}; + if (crypto_scalarmult_curve25519(pv_ctx->acc_curve_pk, acc_curve_sk, basepoint) == -1) { + ESP_MFI_DEBUG(ESP_MFI_DEBUG_ERR, "Curve25519 Error"); + hap_prepare_error_tlv(STATE_M2, kTLVError_Unknown, buf, bufsize, outlen); + return HAP_FAIL; + } + hex_dbg_with_name("acc curve sk", acc_curve_sk, 32); + hex_dbg_with_name("acc curve pk", pv_ctx->acc_curve_pk, 32); + if (crypto_scalarmult_curve25519(pv_ctx->shared_secret, acc_curve_sk, pv_ctx->ctrl_curve_pk) == -1) { + ESP_MFI_DEBUG(ESP_MFI_DEBUG_ERR, "Curve25519 Error"); + hap_prepare_error_tlv(STATE_M2, kTLVError_Unknown, buf, bufsize, outlen); + return HAP_FAIL; + } + + hex_dbg_with_name("shared secret", pv_ctx->shared_secret, 32); + + /* Construct AccessoryInfo by concatenating + * a. Accessory's Curve25519 Public Key + * b. Accessory ID + * c. Controller's Curve25519 Public Key received in M1 + */ + uint8_t acc_info[2 * CURVE_KEY_LEN + HAP_ACC_ID_LEN]; + int acc_info_len = 0; + memcpy(acc_info, pv_ctx->acc_curve_pk, CURVE_KEY_LEN); + acc_info_len += CURVE_KEY_LEN; + memcpy(acc_info + acc_info_len, hap_priv.acc_id, strlen(hap_priv.acc_id)); + acc_info_len += strlen(hap_priv.acc_id); + memcpy(acc_info + acc_info_len, pv_ctx->ctrl_curve_pk, CURVE_KEY_LEN); + acc_info_len += CURVE_KEY_LEN; + + hex_dbg_with_name("acc_info", acc_info, acc_info_len); + + /* Use Ed25519 to generate AccessorySignature by signing AccessoryInfo + * with its Long Term Secret Key AccessoryLTSK + */ + unsigned char ed_sign[64]; + unsigned long long ed_sign_len; + crypto_sign_ed25519_detached(ed_sign, &ed_sign_len, acc_info, acc_info_len, hap_priv.ltska); + hex_dbg_with_name("sign", ed_sign, 64); + + /* Construct a subTLV with + * kTLVType_Identifier : Accessory Identifier + * kTLVType_Signature : AccessorySignature generated above + */ + uint8_t subtlv[4 + HAP_ACC_ID_LEN + ED_SIGN_LEN + POLY_AUTHTAG_LEN]; + hap_tlv_data_t tlv_data; + tlv_data.bufptr = subtlv; + tlv_data.bufsize = sizeof(subtlv); + tlv_data.curlen = 0; + add_tlv(&tlv_data, kTLVType_Identifier, strlen(hap_priv.acc_id), hap_priv.acc_id); + add_tlv(&tlv_data, kTLVType_Signature, sizeof(ed_sign), ed_sign); + int subtlv_len = tlv_data.curlen; + hex_dbg_with_name("subtlv", subtlv, subtlv_len); + + /* Derive Symmetric Session encryption key SessionKey from the curve + * shared secret using HKDF-SHA-512 + */ + hkdf(SHA512, (unsigned char *) PAIR_VERIFY_ENCRYPT_SALT, + strlen(PAIR_VERIFY_ENCRYPT_SALT), + pv_ctx->shared_secret, sizeof(pv_ctx->shared_secret), + (unsigned char *) PAIR_VERIFY_ENCRYPT_INFO, + strlen(PAIR_VERIFY_ENCRYPT_INFO), + pv_ctx->hkdf_key, sizeof(pv_ctx->hkdf_key)); + /* Encrypt the sub TLV to get encryptedData and an authTag using + * Chacha20-Poly1305 AEAD Algorithm + */ + uint8_t edata[4 + HAP_ACC_ID_LEN + ED_SIGN_LEN + POLY_AUTHTAG_LEN]; + unsigned long long mlen = 16; + uint8_t newnonce[12]; + memset(newnonce, 0, sizeof newnonce); + memcpy(newnonce+4, PV_NONCE1, 8); + + crypto_aead_chacha20poly1305_ietf_encrypt_detached(edata, edata + subtlv_len, &mlen, subtlv, subtlv_len, NULL, 0, NULL, newnonce, pv_ctx->hkdf_key); + + int edata_len = subtlv_len + POLY_AUTHTAG_LEN; + + hex_dbg_with_name("encrypt_data", edata, edata_len); + + /* Construct the response M2 */ + tlv_data.bufptr = buf; + tlv_data.bufsize = bufsize; + tlv_data.curlen = 0; + state = STATE_M2; + if ((add_tlv(&tlv_data, kTLVType_State, 1, &state) < 0) || + (add_tlv(&tlv_data, kTLVType_PublicKey, CURVE_KEY_LEN, + pv_ctx->acc_curve_pk) < 0) || + (add_tlv(&tlv_data, kTLVType_EncryptedData, edata_len, edata) < 0)) { + ESP_MFI_DEBUG(ESP_MFI_DEBUG_ERR, "TLV creation failed"); + hap_prepare_error_tlv(STATE_M2, kTLVError_Unknown, buf, bufsize, outlen); + return HAP_FAIL; + } + *outlen = tlv_data.curlen; + hex_dbg_with_name("M2", buf, *outlen); + pv_ctx->state = STATE_M2; + ESP_MFI_DEBUG(ESP_MFI_DEBUG_INFO, "Pair Verify M2 Successful"); + return HAP_SUCCESS; +} + +static int hap_pair_verify_process_finish(pair_verify_ctx_t *pv_ctx, uint8_t *buf, int inlen, + int bufsize, int *outlen) +{ + /* Parse the data received from the controller */ + uint8_t state; + if (!pv_ctx) { + ESP_MFI_DEBUG(ESP_MFI_DEBUG_ERR, "No context"); + hap_prepare_error_tlv(STATE_M4, kTLVError_Unknown, buf, bufsize, outlen); + return HAP_FAIL; + } + uint8_t edata[4 + HAP_CTRL_ID_LEN + ED_SIGN_LEN + POLY_AUTHTAG_LEN]; + int edata_len; + if ((get_value_from_tlv(buf, inlen, kTLVType_State, &state, sizeof(state)) < 0) || + ((edata_len = get_value_from_tlv(buf, inlen, kTLVType_EncryptedData, + edata, sizeof(edata))) < 0)) { + ESP_MFI_DEBUG(ESP_MFI_DEBUG_ERR, "Invalid TLVs received"); + hap_prepare_error_tlv(STATE_M4, kTLVError_Unknown, buf, bufsize, outlen); + return HAP_FAIL; + } + if (state != STATE_M3) { + ESP_MFI_DEBUG(ESP_MFI_DEBUG_ERR, "Incorrect State received"); + hap_prepare_error_tlv(STATE_M4, kTLVError_Unknown, buf, bufsize, outlen); + return HAP_FAIL; + } + ESP_MFI_DEBUG(ESP_MFI_DEBUG_INFO, "Pair Verify M3 Received"); + + /* Decrypt the received data to get the subTLV */ + uint8_t newnonce[12]; + memset(newnonce, 0, sizeof newnonce); + memcpy(newnonce+4, PV_NONCE2, 8); + int ret; + ret = crypto_aead_chacha20poly1305_ietf_decrypt_detached(edata, NULL, edata, edata_len - POLY_AUTHTAG_LEN, edata + edata_len - POLY_AUTHTAG_LEN, NULL, 0, newnonce, pv_ctx->hkdf_key); + if (ret != 0) { + ESP_MFI_DEBUG(ESP_MFI_DEBUG_ERR, "Decryption error"); + hap_prepare_error_tlv(STATE_M4, kTLVError_Authentication, buf, bufsize, outlen); + return HAP_FAIL; + } + + /* Parse the subTLV to get the iOSDevicePairingID and iOSDeviceSignature + */ + edata_len = edata_len - POLY_AUTHTAG_LEN; + unsigned char ed_sign[64]; + char ctrl_id[HAP_CTRL_ID_LEN]; + memset(ctrl_id, 0, sizeof(ctrl_id)); + if ((get_value_from_tlv(edata, edata_len, kTLVType_Identifier, + ctrl_id, sizeof(ctrl_id)) < 0) || + (get_value_from_tlv(edata, edata_len, kTLVType_Signature, + ed_sign, sizeof(ed_sign)) < 0)) { + ESP_MFI_DEBUG(ESP_MFI_DEBUG_ERR, "Wrong subTLV received"); + hap_prepare_error_tlv(STATE_M4, kTLVError_Unknown, buf, bufsize, outlen); + return HAP_FAIL; + } + + /* Check if the controller is present in the database i.e. check + * if the controller was paired with the accessory + */ + hap_ctrl_data_t *ctrl = hap_get_controller(ctrl_id); + if (!ctrl) { + ESP_MFI_DEBUG(ESP_MFI_DEBUG_ERR, "No ctrl details found"); + hap_prepare_error_tlv(STATE_M4, kTLVError_Authentication, buf, bufsize, outlen); + return HAP_FAIL; + } + + /* Construct iOSDeviceInfo by concatenating + * a. Controllers's Curve25519 Public Key (received in M1) + * b. Controller ID + * c. Accessory's Curve25519 Public Key (sent in M2) + */ + uint8_t ios_dev_info[2 * CURVE_KEY_LEN + HAP_CTRL_ID_LEN]; + int ios_dev_info_len = 0; + memcpy(ios_dev_info, pv_ctx->ctrl_curve_pk, CURVE_KEY_LEN); + ios_dev_info_len += CURVE_KEY_LEN; + memcpy(ios_dev_info + ios_dev_info_len, ctrl_id, strlen(ctrl_id)); + ios_dev_info_len += strlen(ctrl_id); + memcpy(ios_dev_info + ios_dev_info_len, pv_ctx->acc_curve_pk, + CURVE_KEY_LEN); + ios_dev_info_len += CURVE_KEY_LEN; + + /* Validate the signature with the received iOSDeviceSignature */ + if (crypto_sign_ed25519_verify_detached(ed_sign, ios_dev_info, ios_dev_info_len, ctrl->info.ltpk) != 0) { + ESP_MFI_DEBUG(ESP_MFI_DEBUG_ERR, "Signature mismatch"); + hap_prepare_error_tlv(STATE_M4, kTLVError_Authentication, buf, bufsize, outlen); + return HAP_FAIL; + } + + /* Allocate memory for the secure session information */ + hap_secure_session_t *session = hap_platform_memory_calloc(sizeof(hap_secure_session_t), 1); + if (!session) { + hap_prepare_error_tlv(STATE_M4, kTLVError_Unknown, buf, bufsize, outlen); + ESP_MFI_DEBUG(ESP_MFI_DEBUG_ERR, "Memory allocation failed"); + return HAP_FAIL; + } + /* Construct the response M4 */ + hap_tlv_data_t tlv_data; + tlv_data.bufptr = buf; + tlv_data.bufsize = bufsize; + tlv_data.curlen = 0; + state = STATE_M4; + if (add_tlv(&tlv_data, kTLVType_State, 1, &state) < 0) { + hap_prepare_error_tlv(STATE_M4, kTLVError_Unknown, buf, bufsize, outlen); + hap_platform_memory_free(session); + ESP_MFI_DEBUG(ESP_MFI_DEBUG_ERR, "TLV creation failed"); + return HAP_FAIL; + } + *outlen = tlv_data.curlen; + + /* Generate the Encryption and Decryption Keys. + * Since, read and write are from the controller's point of view, + * encryption key uses READ_INFO and decryption key uses WRITE_INFO + * + * Also, set the nonce to zero + */ + hkdf(SHA512, (unsigned char *) CONTROL_SALT, strlen(CONTROL_SALT), + pv_ctx->shared_secret, sizeof(pv_ctx->shared_secret), + (unsigned char *) CONTROL_READ_INFO, strlen(CONTROL_READ_INFO), + session->encrypt_key, sizeof(session->encrypt_key)); + + hkdf(SHA512, (unsigned char *) CONTROL_SALT, strlen(CONTROL_SALT), + pv_ctx->shared_secret, sizeof(pv_ctx->shared_secret), + (unsigned char *) CONTROL_WRITE_INFO, strlen(CONTROL_WRITE_INFO), + session->decrypt_key, sizeof(session->decrypt_key)); + + session->state = STATE_VERIFIED; + pv_ctx->state = STATE_VERIFIED; + + memset(session->encrypt_nonce, 0, sizeof(session->encrypt_nonce)); + memset(session->decrypt_nonce, 0, sizeof(session->decrypt_nonce)); + session->ctrl = ctrl; + + pv_ctx->session = session; + + /* Add the session information to database */ + hap_add_secure_session(session); + ESP_MFI_DEBUG(ESP_MFI_DEBUG_INFO, "Pair Verify Successful for %s", ctrl_id); + return HAP_SUCCESS; +} + +int hap_pair_verify_process(void **ctx, uint8_t *buf, int inlen, int bufsize, int *outlen) +{ + pair_verify_ctx_t *pv_ctx = (pair_verify_ctx_t *)(*ctx); + if (pv_ctx) { + if (pv_ctx->state == STATE_M0) + return hap_pair_verify_process_start(pv_ctx, buf, inlen, + bufsize, outlen); + else if (pv_ctx->state == STATE_M2) { + int ret = hap_pair_verify_process_finish(pv_ctx, buf, inlen, + bufsize, outlen); + /* Successful finish means that the pair verify was successful. + * So, we clear the old context and assign the secure_session + * as the new context + */ + if (ret == HAP_SUCCESS) { + hap_secure_session_t *session = pv_ctx->session; + hap_platform_memory_free(pv_ctx); + *ctx = session; + } + return ret; + } + } + ESP_MFI_DEBUG(ESP_MFI_DEBUG_ERR, "Error processing Pair Verify Data"); + hap_prepare_error_tlv(STATE_M2, kTLVError_Unknown, buf, bufsize, outlen); + return HAP_FAIL; +} + +int hap_pair_verify_context_init(void **ctx, uint8_t *buf, int bufsize, int *outlen) +{ + pair_verify_ctx_t *pv_ctx; + + pv_ctx = (pair_verify_ctx_t *) hap_platform_memory_calloc(sizeof(pair_verify_ctx_t), 1); + if (!pv_ctx) { + ESP_MFI_DEBUG(ESP_MFI_DEBUG_ERR, "Failed to create Pair Verify Context"); + hap_prepare_error_tlv(STATE_M2, kTLVError_Unknown, buf, bufsize, outlen); + return HAP_FAIL; + } + *ctx = pv_ctx; + ESP_MFI_DEBUG(ESP_MFI_DEBUG_INFO, "######## Starting Pair Verify ########"); + return HAP_SUCCESS; +} + +uint8_t hap_pair_verify_get_state(void *ctx) +{ + pair_verify_ctx_t *pv_ctx = (pair_verify_ctx_t *)ctx; + if (pv_ctx) + return pv_ctx->state; + return 0; +} diff --git a/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_pair_verify.h b/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_pair_verify.h new file mode 100644 index 000000000..f40a9908e --- /dev/null +++ b/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_pair_verify.h @@ -0,0 +1,35 @@ +/* + * ESPRESSIF MIT License + * + * Copyright (c) 2020 + * + * Permission is hereby granted for use on ESPRESSIF SYSTEMS products only, in which case, + * it is 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. + * + */ +#ifndef _HAP_PAIR_VERIFY_H_ +#define _HAP_PAIR_VERIFY_H_ +#include +#include +int hap_pair_verify_context_init(void **ctx, uint8_t *buf, int bufsize, int *outlen); +int hap_pair_verify_process(void **ctx, uint8_t *buf, int inlen, int bufsize, int *outlen); +uint8_t hap_pair_verify_get_state(void *ctx); +void hap_free_session(void *session); +int hap_get_ctrl_session_index(hap_secure_session_t *session); +void hap_close_ctrl_sessions(hap_ctrl_data_t *ctrl); +void hap_close_all_sessions(); +#endif /* _HAP_PAIR_VERIFY_H_ */ diff --git a/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_pairings.c b/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_pairings.c new file mode 100644 index 000000000..cffe3353d --- /dev/null +++ b/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_pairings.c @@ -0,0 +1,255 @@ +/* + * ESPRESSIF MIT License + * + * Copyright (c) 2020 + * + * Permission is hereby granted for use on ESPRESSIF SYSTEMS products only, in which case, + * it is 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 +#include +#include + +#include +#include +#include +#include +#include +#include + +bool hap_is_req_admin(void *__session) +{ + hap_secure_session_t *session = (hap_secure_session_t *)__session; + if (!session) { + return false; + } + if ((session->state == STATE_VERIFIED) && (session->ctrl->info.perms == 1)) { + return true; + } + return false; +} + +char *hap_req_get_ctrl_id(void *__session) +{ + hap_secure_session_t *session = (hap_secure_session_t *)__session; + if (!session) + return NULL; + + if (session->state == STATE_VERIFIED) { + return session->ctrl->info.id; + } + return NULL; +} + +bool hap_is_req_secure(hap_secure_session_t *session) +{ + if (!session) { + return false; + } + if (session->state == STATE_VERIFIED) { + return true; + } + return false; +} + +void hap_remove_all_controllers() +{ + int i; + for (i = 0; i < HAP_MAX_CONTROLLERS; i++) { + if (hap_priv.controllers[i].valid) { + hap_close_ctrl_sessions(&hap_priv.controllers[i]); + hap_controller_remove(&hap_priv.controllers[i]); + } + } +} +static int hap_process_pair_remove(uint8_t *buf, int inlen, int bufsize, int *outlen) +{ + bool acc_unpaired = false; + char ctrl_id[HAP_CTRL_ID_LEN]; + memset(ctrl_id, 0, HAP_CTRL_ID_LEN); + if (get_value_from_tlv(buf, inlen, kTLVType_Identifier, + ctrl_id, sizeof(ctrl_id)) < 0) { + ESP_MFI_DEBUG(ESP_MFI_DEBUG_ERR, "Identifier not found"); + hap_prepare_error_tlv(STATE_M2, kTLVError_Unknown, buf, bufsize, outlen); + return HAP_FAIL; + } + + ESP_MFI_DEBUG(ESP_MFI_DEBUG_INFO, "Removing Controller %s", ctrl_id); + hap_ctrl_data_t *ctrl = hap_get_controller(ctrl_id); + hap_close_ctrl_sessions(ctrl); + hap_controller_remove(ctrl); + + if (!is_admin_paired()) { + acc_unpaired = true; + ESP_MFI_DEBUG(ESP_MFI_DEBUG_INFO, "Last Admin controller removed. Removing all other controllers."); + hap_remove_all_controllers(); + } + + hap_tlv_data_t tlv_data = { + .bufptr = buf, + .bufsize = bufsize, + .curlen = 0, + }; + uint8_t state = STATE_M2; + if (add_tlv(&tlv_data, kTLVType_State, sizeof(state), &state) < 0) { + ESP_MFI_DEBUG(ESP_MFI_DEBUG_ERR, "TLV creation failed"); + hap_prepare_error_tlv(STATE_M2, kTLVError_Unknown, buf, bufsize, outlen); + return HAP_FAIL; + } + *outlen = tlv_data.curlen; + if (acc_unpaired) { + hap_send_event(HAP_INTERNAL_EVENT_ACC_UNPAIRED); + } + return HAP_SUCCESS; +} + +static int hap_process_pair_add(uint8_t *buf, int inlen, int bufsize, int *outlen) +{ + char ctrl_id[HAP_CTRL_ID_LEN]; + uint8_t ltpkc[ED_KEY_LEN]; + uint8_t perms; + memset(ctrl_id, 0, HAP_CTRL_ID_LEN); + if ((get_value_from_tlv(buf, inlen, kTLVType_Identifier, + ctrl_id, sizeof(ctrl_id)) < 0) || + (get_value_from_tlv(buf, inlen, kTLVType_PublicKey, + ltpkc, sizeof(ltpkc)) < 0) || + (get_value_from_tlv(buf, inlen, kTLVType_Permissions, + &perms, sizeof(perms)) < 0)) { + ESP_MFI_DEBUG(ESP_MFI_DEBUG_ERR, "Invalid TLVs received"); + hap_prepare_error_tlv(STATE_M4, kTLVError_Unknown, buf, bufsize, outlen); + return HAP_FAIL; + } + + hap_ctrl_data_t *ctrl = hap_get_controller(ctrl_id); + if (ctrl) { + /* If controller already exists, but the key does not match, return error */ + if (memcmp(ltpkc, ctrl->info.ltpk, ED_KEY_LEN)) { + hap_prepare_error_tlv(STATE_M2, kTLVError_Unknown, buf, bufsize, outlen); + return HAP_FAIL; + } else { + /* Else, just change the permissions */ + ctrl->info.perms = perms; + ESP_MFI_DEBUG(ESP_MFI_DEBUG_INFO, "Modifying Existing Controller %s", ctrl_id); + hap_controller_save(ctrl); + } + } else { + /* Check if there is space available for a new controller */ + ctrl = hap_controller_get_empty_loc(); + if (!ctrl) { + hap_prepare_error_tlv(STATE_M2, kTLVError_MaxPeers, buf, bufsize, outlen); + return HAP_FAIL; + } + strcpy(ctrl->info.id, ctrl_id); + memcpy(ctrl->info.ltpk, ltpkc, ED_KEY_LEN); + ctrl->info.perms = perms; + hap_controller_save(ctrl); + ESP_MFI_DEBUG(ESP_MFI_DEBUG_INFO, "Added Controller %s", ctrl_id); + } + hap_tlv_data_t tlv_data = { + .bufptr = buf, + .bufsize = bufsize, + .curlen = 0, + }; + uint8_t state = STATE_M2; + if (add_tlv(&tlv_data, kTLVType_State, sizeof(state), &state) < 0) { + ESP_MFI_DEBUG(ESP_MFI_DEBUG_ERR, "TLV creation failed"); + hap_prepare_error_tlv(STATE_M2, kTLVError_Unknown, buf, bufsize, outlen); + return HAP_FAIL; + } + *outlen = tlv_data.curlen; + return HAP_SUCCESS; + +} +static int hap_process_pair_list(uint8_t *buf, int inlen, int bufsize, int *outlen) +{ + hap_tlv_data_t tlv_data = { + .bufptr = buf, + .bufsize = bufsize, + .curlen = 0, + }; + int i; + hap_ctrl_data_t *ctrl; + hap_ctrl_info_t *ctrl_info; + bool entry_added = false; + for (i = 0; i < HAP_MAX_CONTROLLERS; i++) { + ctrl = &hap_priv.controllers[i]; + if (!ctrl->valid) + continue; + /* If an entry is already added, include a separator */ + if (entry_added) { + if (add_tlv(&tlv_data, kTLVType_Separator, 0, NULL) < 0) { + ESP_MFI_DEBUG(ESP_MFI_DEBUG_ERR, "TLV creation failed"); + hap_prepare_error_tlv(STATE_M2, kTLVError_Unknown, + buf, bufsize, outlen); + return HAP_FAIL; + } + } else { + /* Else, since this is the first entry, add the state */ + uint8_t state = STATE_M2; + if (add_tlv(&tlv_data, kTLVType_State, sizeof(state), &state) < 0) { + ESP_MFI_DEBUG(ESP_MFI_DEBUG_ERR, "TLV creation failed"); + hap_prepare_error_tlv(STATE_M2, kTLVError_Unknown, + buf, bufsize, outlen); + return HAP_FAIL; + } + } + ctrl_info = &ctrl->info; + if ((add_tlv(&tlv_data, kTLVType_Identifier, + strlen(ctrl_info->id), ctrl_info->id) < 0) || + (add_tlv(&tlv_data, kTLVType_PublicKey, + ED_KEY_LEN, ctrl_info->ltpk) < 0) || + (add_tlv(&tlv_data, kTLVType_Permissions, + 1, &ctrl_info->perms) < 0)) { + ESP_MFI_DEBUG(ESP_MFI_DEBUG_ERR, "TLV creation failed"); + hap_prepare_error_tlv(STATE_M2, kTLVError_Unknown, buf, bufsize, outlen); + return HAP_FAIL; + } + entry_added = true; + } + *outlen = tlv_data.curlen; + return HAP_SUCCESS; +} + +int hap_pairings_process(void *ctx, uint8_t *buf, int inlen, int bufsize, int *outlen) +{ + if (!hap_is_req_admin(ctx)) { + hap_prepare_error_tlv(STATE_M2, kTLVError_Authentication, buf, bufsize, outlen); + return HAP_FAIL; + } + uint8_t state, method; + if ((get_value_from_tlv(buf, inlen, kTLVType_State, &state, sizeof(state)) < 0) || + (get_value_from_tlv(buf, inlen, kTLVType_Method, + &method, sizeof(method)) < 0) || + (state != STATE_M1)) { + ESP_MFI_DEBUG(ESP_MFI_DEBUG_ERR, "Invalid TLVs received"); + hap_prepare_error_tlv(STATE_M2, kTLVError_Unknown, buf, bufsize, outlen); + return HAP_FAIL; + } + if (method == HAP_METHOD_ADD_PAIRING) { + ESP_MFI_DEBUG(ESP_MFI_DEBUG_INFO, "Add Pairing received"); + return hap_process_pair_add(buf, inlen, bufsize, outlen); + } else if (method == HAP_METHOD_REMOVE_PAIRING) { + ESP_MFI_DEBUG(ESP_MFI_DEBUG_INFO, "Remove Pairing received"); + return hap_process_pair_remove(buf, inlen, bufsize, outlen); + } else if (method == HAP_METHOD_LIST_PAIRINGS) { + ESP_MFI_DEBUG(ESP_MFI_DEBUG_INFO, "List Pairings received"); + return hap_process_pair_list(buf, inlen, bufsize, outlen); + } + hap_prepare_error_tlv(STATE_M2, kTLVError_Unknown, buf, bufsize, outlen); + return HAP_FAIL; +} diff --git a/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_pairings.h b/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_pairings.h new file mode 100644 index 000000000..7b7eaab83 --- /dev/null +++ b/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_pairings.h @@ -0,0 +1,29 @@ +/* + * ESPRESSIF MIT License + * + * Copyright (c) 2020 + * + * Permission is hereby granted for use on ESPRESSIF SYSTEMS products only, in which case, + * it is 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. + * + */ +#ifndef _HAP_PAIRINGS_H_ +#define _HAP_PAIRINGS_H_ +#include +int hap_pairings_process(void *ctx, uint8_t *buf, int inlen, int bufsize, int *outlen); +bool hap_is_req_secure(hap_secure_session_t *session); +#endif /* _HAP_PAIRINGS_H_ */ diff --git a/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_secure_message.h b/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_secure_message.h new file mode 100644 index 000000000..dbeb4b17e --- /dev/null +++ b/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_secure_message.h @@ -0,0 +1,42 @@ +/* + * ESPRESSIF MIT License + * + * Copyright (c) 2020 + * + * Permission is hereby granted for use on ESPRESSIF SYSTEMS products only, in which case, + * it is 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. + * + */ +#ifndef _HAP_SECURE_MESSAGE_H_ +#define _HAP_SECURE_MESSAGE_H_ +#include +#include +/** Information for Software Token based authentication. + * To be used only if MFi chip is not present on the accessory + */ +typedef struct { + /** UUID for the accessory */ + uint8_t uuid[16]; + /** Token associated with the UUID */ + uint8_t *token; + /* Length of the above token */ + size_t token_len; +} hap_software_token_info_t; + +int hap_register_secure_message_handler(httpd_handle_t handle); +int hap_unregister_secure_message_handler(httpd_handle_t handle); +#endif /* _HAP_SECURE_MESSAGE_H_ */ diff --git a/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_serv.c b/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_serv.c new file mode 100644 index 000000000..8c8bd9f25 --- /dev/null +++ b/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_serv.c @@ -0,0 +1,329 @@ + /* + * ESPRESSIF MIT License + * + * Copyright (c) 2020 + * + * Permission is hereby granted for use on ESPRESSIF SYSTEMS products only, in which case, + * it is 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 +#include + +#include +#include + +void hap_serv_mark_primary(hap_serv_t *hs) +{ + if (hs) { + ((__hap_serv_t *)hs)->primary = true; + } +} + +void hap_serv_mark_hidden(hap_serv_t *hs) +{ + if (hs) { + ((__hap_serv_t *)hs)->hidden = true; + } +} + +/** + * @brief get service hidden attribute + */ +bool hap_serv_get_hidden(hap_serv_t *hs) +{ + if (hs) { + return ((__hap_serv_t *)hs)->hidden; + } + return false; +} + + +void hap_serv_set_iid(hap_serv_t *hs, int32_t iid) +{ + if (hs) { + ((__hap_serv_t *)hs)->iid = iid; + } +} + +/** + * @brief get service "primary" attribute + */ +bool hap_serv_get_primary(hap_serv_t *hs) +{ + if (hs) { + return ((__hap_serv_t *)hs)->primary; + } + return false; +} + +hap_char_t *hap_serv_get_first_char(hap_serv_t *hs) +{ + return ((__hap_serv_t *)hs)->chars; +} +/** + * @brief get target characteristics by it's IID + */ +hap_char_t *hap_serv_get_char_by_iid(hap_serv_t *hs, int32_t iid) +{ + if (!hs) + return NULL; + + hap_char_t *hc; + for (hc = hap_serv_get_first_char(hs); hc; hc = hap_char_get_next(hc)) { + if (((__hap_char_t *)hc)->iid == iid) + return hc; + } + return NULL; +} + +/** + * @brief get target characteristics by it's UUID + */ +hap_char_t *hap_serv_get_char_by_uuid(hap_serv_t *hs, const char *uuid) +{ + if (!hs | !uuid) + return NULL; + + hap_char_t *hc; + for (hc = hap_serv_get_first_char(hs); hc; hc = hap_char_get_next(hc)) { + if (!strcmp(((__hap_char_t *)hc)->type_uuid, uuid)) + return hc; + } + return NULL; +} + +/** + * @brief get characteristics UUID prefix number + */ + char *hap_serv_get_uuid(hap_serv_t *hs) + { + return ((__hap_serv_t *)hs)->type_uuid; + } + +/** + * Default service bulk read callback, which will be registered while creating a service. + * It will internally call the actual read routines + */ +static int hap_serv_def_bulk_read_cb(hap_read_data_t read_data[], int count, + void *serv_priv, void *read_priv) +{ + int i; + if (!count) { + return HAP_FAIL; + } + __hap_serv_t *hs = (__hap_serv_t *)hap_char_get_parent(read_data[0].hc); + /* If no read routine is registered, just return success so that the cached values + * will be used + */ + if (!hs->read_cb) { + return HAP_SUCCESS; + } + + int ret = HAP_SUCCESS; + for (i = 0; i < count; i++) { + if (hs->read_cb(read_data[i].hc, read_data[i].status, serv_priv, read_priv) != HAP_SUCCESS) { + ret = HAP_FAIL; + } + } + return ret; +} +/** + * @brief HAP create a service + */ +hap_serv_t *hap_serv_create(char *type_uuid) +{ + ESP_MFI_ASSERT(type_uuid); + __hap_serv_t *_hs = hap_platform_memory_calloc(1, sizeof(__hap_serv_t)); + if (!_hs) { + return NULL; + } + + _hs->type_uuid = type_uuid; + _hs->bulk_read = hap_serv_def_bulk_read_cb; + + return (hap_serv_t *)_hs; +} + +int hap_serv_link_serv(hap_serv_t *hs, hap_serv_t *linked_serv) +{ + if (!hs || !linked_serv) + return HAP_FAIL; + + hap_linked_serv_t *cur = hap_platform_memory_calloc(1, sizeof(hap_linked_serv_t)); + if (!cur) + return HAP_FAIL; + cur->hs = linked_serv; + + __hap_serv_t *_hs = (__hap_serv_t *)hs; + hap_linked_serv_t *linked = _hs->linked_servs; + + if (!linked) { + _hs->linked_servs = cur; + return HAP_SUCCESS; + } else { + while(linked->next) { + linked = linked->next; + } + linked->next = cur; + return HAP_SUCCESS; + } + return HAP_FAIL; +} + +/** + * @brief HAP get target service IID + */ +uint32_t hap_serv_get_iid(hap_serv_t *hs) +{ + if (!hs) + return 0; + + __hap_serv_t *tmp = (__hap_serv_t *)hs; + + return tmp->iid; +} + +char *hap_serv_get_type_uuid(hap_serv_t *hs) +{ + if (!hs) + return 0; + + __hap_serv_t *tmp = (__hap_serv_t *)hs; + + return tmp->type_uuid; +} + +/** + * @brief HAP delete target service + */ +void hap_serv_delete(hap_serv_t *hs) +{ + /* Returning success even if pointer is NULL, because it means + * that the service is absent and as good as deleted + */ + if (!hs) + return; + __hap_serv_t *_hs = (__hap_serv_t *)hs; + __hap_char_t *_hc = (__hap_char_t *)_hs->chars; + while (_hc) { + _hs->chars = _hc->next_char; + hap_char_delete((hap_char_t *)_hc); + _hc = (__hap_char_t *)_hs->chars; + } + if (_hs->linked_servs) { + hap_linked_serv_t *cur = _hs->linked_servs; + hap_linked_serv_t *next = cur->next; + while (next) { + hap_platform_memory_free(cur); + cur = next; + next = cur->next; + } + hap_platform_memory_free(cur); + } + hap_platform_memory_free(hs); +} + +/** + * @brief add a characteristics to a service + */ +int hap_serv_add_char(hap_serv_t *hs, hap_char_t *hc) +{ + if (!hs || !hc) + return -1; + __hap_serv_t *_hs = (__hap_serv_t *)hs; + __hap_char_t *_hc = (__hap_char_t *)hc; + + if (_hc->parent) { + ESP_MFI_DEBUG(ESP_MFI_DEBUG_ERR, "Characteristic already added"); + return HAP_FAIL; + } + + /* If the service has no characteristics, add this as the first */ + if (!_hs->chars) { + _hs->chars = hc; + } else { + /* Else loop through the characteristics to get to the last one, + * and add this at the end + */ + __hap_char_t *temp = (__hap_char_t *)_hs->chars; + while (temp->next_char) + temp = (__hap_char_t *)temp->next_char; + temp->next_char = hc; + } + if (_hs->parent) { + _hc->iid = ((__hap_acc_t *)(_hs->parent))->next_iid++; + } + _hc->parent = hs; + return 0; +} + +void hap_serv_set_write_cb(hap_serv_t *hs, hap_serv_write_t write) +{ + if (hs) { + ((__hap_serv_t *)hs)->write_cb = write; + } +} + +void hap_serv_set_read_cb(hap_serv_t *hs, hap_serv_read_t read) +{ + if (hs) { + ((__hap_serv_t *)hs)->read_cb = read; + } +} + +void hap_serv_set_bulk_read_cb(hap_serv_t *hs, hap_serv_bulk_read_t read) +{ + if (hs) { + ((__hap_serv_t *)hs)->bulk_read = read; + } +} + + +hap_serv_t *hap_serv_get_next(hap_serv_t *hs) +{ + if (hs) { + return ((__hap_serv_t *)hs)->next_serv; + } else { + return NULL; + } +} + +hap_acc_t *hap_serv_get_parent(hap_serv_t *hs) +{ + if (hs) { + return ((__hap_serv_t *)hs)->parent; + } else { + return NULL; + } +} + +void hap_serv_set_priv(hap_serv_t *hs, void *priv) +{ + if (hs) { + ((__hap_serv_t *)hs)->priv = priv; + } +} + +void *hap_serv_get_priv(hap_serv_t *hs) +{ + if (hs) { + return ((__hap_serv_t *)hs)->priv; + } else { + return NULL; + } +} diff --git a/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_serv.h b/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_serv.h new file mode 100644 index 000000000..8d041d85f --- /dev/null +++ b/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_serv.h @@ -0,0 +1,80 @@ + /* + * ESPRESSIF MIT License + * + * Copyright (c) 2020 + * + * Permission is hereby granted for use on ESPRESSIF SYSTEMS products only, in which case, + * it is 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. + * + */ + +#ifndef _HAP_SERV_H_ +#define _HAP_SERV_H_ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct hap_linked_serv { + hap_serv_t *hs; + struct hap_linked_serv *next; +} hap_linked_serv_t; + +typedef struct hap_linked_serv hap_linked_serv_t; + +/** + * HAP service information + */ +typedef struct { + char *type_uuid; /* String that defines the type of the service. */ + + uint32_t iid; /* service instance ID */ + + bool hidden; /* If set it to be True, the service is not visible to user. */ + bool primary; /* If set it to be True, this is the primary service of the accessory. */ + + /** + * List of Characteristic objects. Must not be empty. The maximum number of characteristics + * allowed is 100, and each characteristic in the array must have a unique type. + */ + hap_char_t *chars; + hap_acc_t *parent; + hap_serv_t *next_serv; + + hap_serv_write_t write_cb; + hap_serv_read_t read_cb; + hap_serv_bulk_read_t bulk_read; + hap_linked_serv_t *linked_servs; + void *priv; +} __hap_serv_t; + +bool hap_serv_get_hidden(hap_serv_t *hs); +bool hap_serv_get_primary(hap_serv_t *hs); +hap_char_t *hap_serv_get_char_by_iid(hap_serv_t *hs, int32_t iid); + char *hap_serv_get_uuid(hap_serv_t *hs); +hap_serv_t *hap_serv_create(char *type_uuid); +void hap_serv_delete(hap_serv_t *hs); +int hap_serv_add_char(hap_serv_t *hs, hap_char_t *hc); +#ifdef __cplusplus +} +#endif + +#endif /* _HAP_SERV_H_ */ diff --git a/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_setup_payload.c b/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_setup_payload.c new file mode 100644 index 000000000..52cc79329 --- /dev/null +++ b/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_setup_payload.c @@ -0,0 +1,81 @@ +/* + * ESPRESSIF MIT License + * + * Copyright (c) 2020 + * + * Permission is hereby granted for use on ESPRESSIF SYSTEMS products only, in which case, + * it is 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 +#include +#include +#include +#include + +#include + +static const char *TAG = "esp_hap_setup_payload"; + +#define SETUP_CODE_MASK 0x0000000007ffffff +#define HAP_OVER_IP_MASK 0x0000000010000000 +#define WAC_MASK 0x0000000040000000 +#define SETUP_PAYLOAD_PREFIX "X-HM://00" + +static void remove_chars(char *str, char c) +{ + int i = 0, j = 0; + while(str[i]) { + if (str[i] != c) { + str[j] = str[i]; + j++; + } + i++; + } + str[j] = 0; +} + +char *esp_hap_get_setup_payload(char *setup_code, char *setup_id, bool wac_support, hap_cid_t cid) +{ + if (!setup_code || !setup_id) { + ESP_LOGE(TAG, "Setup code or Setup ID cannot be NULL"); + return NULL; + } + uint64_t payload = 0; + if (strlen(setup_code) != 10 || strlen(setup_id) != 4) { + ESP_LOGE(TAG, "Setup code or Setup ID not correct. Eg. 111-22-333, ES32"); + return NULL; + } + char setup_code_copy[11]; + strcpy(setup_code_copy, setup_code); + remove_chars(setup_code_copy, '-'); + int64_t code = atoi(setup_code_copy); + int64_t category = cid; + category <<= 31; + + payload |= code; + payload |= category; + payload |= HAP_OVER_IP_MASK; + if (wac_support) { + payload |= WAC_MASK; + } + char *base36_str = base36_to_str(payload); + char setup_payload[24]; + snprintf(setup_payload, sizeof(setup_payload), "%s%s%s", SETUP_PAYLOAD_PREFIX, base36_str, setup_id); + free(base36_str); + return strdup(setup_payload); +} diff --git a/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_wac.h b/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_wac.h new file mode 100644 index 000000000..8ea04f3e8 --- /dev/null +++ b/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_wac.h @@ -0,0 +1,32 @@ +/* + * ESPRESSIF MIT License + * + * Copyright (c) 2020 + * + * Permission is hereby granted for use on ESPRESSIF SYSTEMS products only, in which case, + * it is 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. + * + */ + +#ifndef _HAP_WAC_H_ +#define _HAP_WAC_H_ +int hap_wac_start(void); +int hap_wac2_network_switch(void); +int hap_wac2_finish(void); +int hap_wac2_stop(void); +bool hap_is_mfi_auth_enabled(); +#endif /* _HAP_WAC_H_ */ diff --git a/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_wifi.c b/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_wifi.c new file mode 100644 index 000000000..b46adbc07 --- /dev/null +++ b/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_wifi.c @@ -0,0 +1,121 @@ +/* + * ESPRESSIF MIT License + * + * Copyright (c) 2020 + * + * Permission is hereby granted for use on ESPRESSIF SYSTEMS products only, in which case, + * it is 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 +#include +#include +#include +#include + +esp_err_t hap_wifi_is_provisioned(bool *provisioned) +{ + if (!provisioned) { + return ESP_ERR_INVALID_ARG; + } + + *provisioned = false; + + /* Get Wi-Fi Station configuration */ + wifi_config_t wifi_cfg; + if (esp_wifi_get_config(ESP_IF_WIFI_STA, &wifi_cfg) != ESP_OK) { + return ESP_FAIL; + } + + if (strlen((const char *) wifi_cfg.sta.ssid)) { + *provisioned = true; + } + return ESP_OK; +} +bool hap_is_network_configured(void) +{ + /* If only the Ethernet is enabled, return true */ + if (hap_priv.transport == HAP_TRANSPORT_ETHERNET) { + return true; + } + + bool provisioned = false; + hap_wifi_is_provisioned(&provisioned); + return provisioned; +} + +void hap_erase_network_info(void) +{ + esp_wifi_restore(); +} + +esp_err_t hap_wifi_softap_start(char *ssid) +{ + if (!ssid) { + ESP_MFI_DEBUG(ESP_MFI_DEBUG_ERR, "SSID cannot be NULL"); + } + ESP_MFI_DEBUG(ESP_MFI_DEBUG_INFO, "Starting SoftAP with SSID: %s", ssid); + wifi_config_t wifi_config = { + .ap = { + .ssid = "", + .ssid_len = 0, + .max_connection = 4, + .password = "", + .authmode = WIFI_AUTH_OPEN + }, + }; + size_t ssid_len = strnlen(ssid, sizeof(wifi_config.ap.ssid)); + memcpy(wifi_config.ap.ssid, ssid, ssid_len); + wifi_mode_t mode; + esp_wifi_get_mode(&mode); + if (mode == WIFI_MODE_STA) { + esp_wifi_set_mode(WIFI_MODE_APSTA); + } else { + esp_wifi_set_mode(WIFI_MODE_AP); + } + esp_wifi_set_config(ESP_IF_WIFI_AP, &wifi_config); + esp_wifi_start(); + return ESP_OK; +} + +esp_err_t hap_wifi_softap_stop(void) +{ + ESP_MFI_DEBUG(ESP_MFI_DEBUG_INFO, "Stopping SoftAP."); + wifi_mode_t mode; + esp_wifi_get_mode(&mode); + if (mode == WIFI_MODE_AP) { + esp_wifi_stop(); + } + esp_wifi_set_mode(WIFI_MODE_STA); + return ESP_OK; +} + +esp_err_t hap_wifi_sta_connect(wifi_config_t *config) +{ + ESP_MFI_DEBUG(ESP_MFI_DEBUG_INFO, "Connecting to Wi-Fi."); + wifi_mode_t mode; + esp_wifi_get_mode(&mode); + if (mode == WIFI_MODE_AP || mode == WIFI_MODE_APSTA) { + esp_wifi_set_mode(WIFI_MODE_APSTA); + } else { + esp_wifi_set_mode(WIFI_MODE_STA); + } + esp_wifi_set_config(ESP_IF_WIFI_STA, config); + esp_wifi_start(); + esp_wifi_connect(); + return ESP_OK; +} diff --git a/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_wifi.h b/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_wifi.h new file mode 100644 index 000000000..7b7f95814 --- /dev/null +++ b/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_wifi.h @@ -0,0 +1,30 @@ +/* + * ESPRESSIF MIT License + * + * Copyright (c) 2020 + * + * Permission is hereby granted for use on ESPRESSIF SYSTEMS products only, in which case, + * it is 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. + * + */ +#ifndef _HAP_WIFI_H_ +#define _HAP_WIFI_H_ +#include +bool hap_is_network_configured(); +void hap_wifi_restart(); +void hap_erase_network_info(); +#endif /* _HAP_WIFI_H_ */ diff --git a/lib/libesp32_div/ESP32-HomeKit/src/esp_mfi_aes.c b/lib/libesp32_div/ESP32-HomeKit/src/esp_mfi_aes.c new file mode 100644 index 000000000..a81b34d41 --- /dev/null +++ b/lib/libesp32_div/ESP32-HomeKit/src/esp_mfi_aes.c @@ -0,0 +1,145 @@ +/* + * ESPRESSIF MIT License + * + * Copyright (c) 2020 + * + * Permission is hereby granted for use on ESPRESSIF SYSTEMS products only, in which case, + * it is 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 +#include +#include + +#include "mbedtls/aes.h" +#include "esp_log.h" + +#include "esp_mfi_aes.h" + +static const char* TAG = "mfi_aes_adapter"; + +/*! + * @group AES 128-bit Counter Mode API + + * @abstract API to encrypt or decrypt using AES-128 in counter mode. + * + * Call esp_mfi_aes_ctr_init to initialize the context. Don't use the context until it has been initialized. + * Call esp_mfi_aes_ctr_update to encrypt or decrypt N bytes of input and generate N bytes of output. + * Call esp_mfi_aes_ctr_final to finalize the context. After finalizing, you must call AES_CTR_Init to use it again. +*/ + +typedef struct { + uint8_t key[MFI_AES_CTR_SIZE]; + uint8_t nonce[MFI_AES_CTR_SIZE]; +} aes_ctr_context_t; + +/** + * @bref Create AES context + * + * @param none + * + * @return the AES context point + */ +esp_mfi_aes_ctr_t esp_mfi_aes_ctr_new(void) +{ + aes_ctr_context_t *context = NULL; + context = (aes_ctr_context_t *) malloc(sizeof(aes_ctr_context_t)); + return context; +} + +/** + * @bref Initialize AES context, include initialize the key and nonce + * + * @param incontext AES context point + * inkey AES key + * innonce AES nonce + * + * @return the result + * 0 : sucessful + * others : failed + */ +int esp_mfi_aes_ctr_init(esp_mfi_aes_ctr_t incontext, const uint8_t inkey[MFI_AES_CTR_SIZE], const uint8_t innonce[MFI_AES_CTR_SIZE]) +{ + int ret = 0; + + if (incontext == NULL) + return -EINVAL; + + aes_ctr_context_t *context = incontext; + + memcpy(context->key, inkey, MFI_AES_CTR_SIZE); + memcpy(context->nonce, innonce, MFI_AES_CTR_SIZE); + + return ret; +} + +/** + * @bref Update AES context + * + * @param incontext AES context point + * insrc the data point of update + * insrclen the data length + * indst the data pint of output + * + * @return the result + * 0 : sucessful + * others : failed + */ +int esp_mfi_aes_ctr_update(esp_mfi_aes_ctr_t incontext, const void *insrc, uint16_t insrclen, void *indst) +{ + int ret = 0; + + if (incontext == NULL) + return -EINVAL; + + aes_ctr_context_t *context = incontext; + size_t offset = 0; + uint8_t stream_block[MFI_AES_CTR_SIZE]; + mbedtls_aes_context ctx; + mbedtls_aes_init(&ctx); + + ret = mbedtls_aes_setkey_enc( &ctx, context->key, 128); + + if (ret != 0) { + ESP_LOGE(TAG, "mfi aes setkey[%d]", ret); + ret = -EINVAL; + } else { + ret = mbedtls_aes_crypt_ctr(&ctx, insrclen, &offset, context->nonce, stream_block, (uint8_t *) insrc, indst); + if (ret != 0) { + ESP_LOGE(TAG, "mfi aes crypt[%d]", ret); + ret = -EINVAL; + } + } + + return ret; +} + +/** + * @bref Destory AES context point + * + * @param incontext AES context point + * + * @return none + */ +void esp_mfi_aes_ctr_final(esp_mfi_aes_ctr_t incontext) +{ + if (incontext) { + memset((aes_ctr_context_t *) incontext, 0, sizeof(aes_ctr_context_t)); + free(incontext); + } +} diff --git a/lib/libesp32_div/ESP32-HomeKit/src/esp_mfi_aes.h b/lib/libesp32_div/ESP32-HomeKit/src/esp_mfi_aes.h new file mode 100644 index 000000000..c563ea185 --- /dev/null +++ b/lib/libesp32_div/ESP32-HomeKit/src/esp_mfi_aes.h @@ -0,0 +1,82 @@ +/* + * ESPRESSIF MIT License + * + * Copyright (c) 2020 + * + * Permission is hereby granted for use on ESPRESSIF SYSTEMS products only, in which case, + * it is 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. + * + */ +#ifndef ESP_MFI_AES_H_ +#define ESP_MFI_AES_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define MFI_AES_CTR_SIZE 16 + +typedef void* esp_mfi_aes_ctr_t; + +/** + * @brief Create AES context + * + * @return pointer of the AES context + */ +esp_mfi_aes_ctr_t esp_mfi_aes_ctr_new(void); + +/** + * @brief Initialize AES context, including the key and nonce + * + * @param incontext pointer of the AES context + * @param inkey AES key + * @param innonce AES nonce + * + * @return + * - 0 : succeed + * - others : fail + */ +int esp_mfi_aes_ctr_init(esp_mfi_aes_ctr_t incontext, const uint8_t inkey[MFI_AES_CTR_SIZE], const uint8_t innonce[MFI_AES_CTR_SIZE]); + +/** + * @brief Update AES context + * + * @param incontext AES context point + * @param insrc pointer of the source data to be updated + * @param insrclen source data length + * @param indst pointer of the updated data + * + * @return + * - 0 : succeed + * - others : fail + */ +int esp_mfi_aes_ctr_update(esp_mfi_aes_ctr_t incontext, const void *insrc, uint16_t insrclen, void *indst); + +/** + * @brief Destroy AES context pointer + * + * @param incontext pointer of the AES context + */ +void esp_mfi_aes_ctr_final(esp_mfi_aes_ctr_t incontext); + +#ifdef __cplusplus +} +#endif + +#endif /* ESP_MFI_AES_H_ */ diff --git a/lib/libesp32_div/ESP32-HomeKit/src/esp_mfi_base64.c b/lib/libesp32_div/ESP32-HomeKit/src/esp_mfi_base64.c new file mode 100644 index 000000000..6d1cb6ffa --- /dev/null +++ b/lib/libesp32_div/ESP32-HomeKit/src/esp_mfi_base64.c @@ -0,0 +1,54 @@ +/* + * ESPRESSIF MIT License + * + * Copyright (c) 2020 + * + * Permission is hereby granted for use on ESPRESSIF SYSTEMS products only, in which case, + * it is 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 + +#include "mbedtls/base64.h" + +/** + * @brief transform bin data to base64 data + */ +int esp_mfi_base64_encode(const char *src, int len, char *dest, int dest_len, int *out_len) +{ + int ret = mbedtls_base64_encode((unsigned char *)dest, dest_len, (size_t *)out_len, (unsigned char *)src, len); + if (ret != 0){ + return -EINVAL; + } else{ + return 0; + } +} + +/** + * @brief transform base64 data to bin data + */ +int esp_mfi_base64_decode(const char *src, int len, char *dest, int dest_len, int *out_len) +{ + int ret = 0; + ret = mbedtls_base64_decode((unsigned char *)dest, dest_len, (size_t *)out_len, (unsigned char *)src, len); + if (ret != 0) { + return -EINVAL; + } else { + return 0; + } +} diff --git a/lib/libesp32_div/ESP32-HomeKit/src/esp_mfi_base64.h b/lib/libesp32_div/ESP32-HomeKit/src/esp_mfi_base64.h new file mode 100644 index 000000000..28e87e78b --- /dev/null +++ b/lib/libesp32_div/ESP32-HomeKit/src/esp_mfi_base64.h @@ -0,0 +1,67 @@ +/* + * ESPRESSIF MIT License + * + * Copyright (c) 2020 + * + * Permission is hereby granted for use on ESPRESSIF SYSTEMS products only, in which case, + * it is 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. + * + */ +#ifndef ESP_MFI_BASE64_H_ +#define ESP_MFI_BASE64_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief transform bin data to base64 data + * + * @param src input data point + * @param len input data length + * @param dest output data point + * @param dest_len output data buffer length + * @param out_len output data length + * + * @return + * - 0 : succeed + * - others : fail + */ +int esp_mfi_base64_encode(const char *src, int len, char *dest, int dest_len, int *out_len); + +/** + * @brief transform base64 data to bin data + * + * @param src input data point + * @param len input data length + * @param dest output data point + * @param dest_len output data buffer length + * @param out_len output data length + * + * @return + * - 0 : succeed + * - others : fail + */ +int esp_mfi_base64_decode(const char *src, int len, char *dest, int dest_len, int *out_len); + +#ifdef __cplusplus +} +#endif + +#endif /* ESP_MFI_BASE64_H_ */ diff --git a/lib/libesp32_div/ESP32-HomeKit/src/esp_mfi_debug.c b/lib/libesp32_div/ESP32-HomeKit/src/esp_mfi_debug.c new file mode 100644 index 000000000..ca8917aad --- /dev/null +++ b/lib/libesp32_div/ESP32-HomeKit/src/esp_mfi_debug.c @@ -0,0 +1,80 @@ +/* + * ESPRESSIF MIT License + * + * Copyright (c) 2020 + * + * Permission is hereby granted for use on ESPRESSIF SYSTEMS products only, in which case, + * it is 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 +#include +#include + +#define RED_CHAR 31 +#define GREEN_CHAR 32 +#define YELLOW_CHAR 33 +#define BLUE_CHAR 34 +#define CYAN_CHAR 36 +#define WHITE_CHAR 37 + +#ifdef CONFIG_MFI_DEBUG_LEVEL_INIT +#define MFI_DEBUG_LEVEL_INIT CONFIG_MFI_DEBUG_LEVEL_INIT +#else /* CONFIG_MFI_DEBUG_LEVEL_INIT */ +#define MFI_DEBUG_LEVEL_INIT 0 +#endif /* CONFIG_MFI_DEBUG_LEVEL_INIT */ + +static uint32_t mfi_debug_level = MFI_DEBUG_LEVEL_INIT; + +/** + * @bref set the MFI debugging level + */ +int esp_mfi_set_debug_level(uint32_t level) +{ + mfi_debug_level = level; + return 0; +} + +/** + * @bref get the MFI debugging level and output data color + */ +uint32_t esp_mfi_get_debug_level(uint32_t level, uint32_t *color) +{ + const uint32_t prospect_table[] = { + 0, /* no */ + WHITE_CHAR, /* information: 1, color(37: white) */ + GREEN_CHAR, /* warn : 3, color(32: green) */ + RED_CHAR, /* error : 3, color(31: red) */ + YELLOW_CHAR, /* assert : 4, color(33: yellow) */ + CYAN_CHAR /* block : 5, color(36: cyan) */ + /* others : n, color(34: blue) */ + }; + const uint32_t prospect_table_size = sizeof(prospect_table) / sizeof(prospect_table[0]); + + if (level < prospect_table_size) + *color = prospect_table[level]; + else + *color = BLUE_CHAR; + + return mfi_debug_level; +} + +void hap_set_debug_level(hap_debug_level_t level) +{ + esp_mfi_set_debug_level(level); +} diff --git a/lib/libesp32_div/ESP32-HomeKit/src/esp_mfi_debug.h b/lib/libesp32_div/ESP32-HomeKit/src/esp_mfi_debug.h new file mode 100644 index 000000000..4c0ae62ee --- /dev/null +++ b/lib/libesp32_div/ESP32-HomeKit/src/esp_mfi_debug.h @@ -0,0 +1,183 @@ +/* + * ESPRESSIF MIT License + * + * Copyright (c) 2020 + * + * Permission is hereby granted for use on ESPRESSIF SYSTEMS products only, in which case, + * it is 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. + * + */ + +#ifndef ESP_MFI_DEBUG_H_ +#define ESP_MFI_DEBUG_H_ + +#include +#include + +#ifdef __cplusplus +extern "C"{ +#endif + +#define ESP_MFI_DEBUG_FL "\n" +#define CONFIG_ESP_MFI_DEBUG_ENABLE +#ifdef CONFIG_ESP_MFI_DEBUG_ENABLE +#define ESP_MFI_DEBUG_ENABLE +#endif /* CONFIG_ESP_MFI_DEBUG_ENABLE */ + +#define CONFIG_ESP_MFI_ASSERT +#ifdef CONFIG_ESP_MFI_ASSERT +#define ESP_MFI_ASSERT_ENABLE +#endif /* CONFIG_ESP_MFI_ASSERT */ + +#define CONFIG_MFI_DEBUG_LEVEL_INIT 0 +#define CONFIG_ESP_MFI_ASSERT_BLOCK +#ifdef CONFIG_ESP_MFI_ASSERT_BLOCK +#define ESP_MFI_ASSERT_BLOCK() while (1) +#else /* CONFIG_ESP_MFI_ASSERT_BLOCK */ +#define ESP_MFI_ASSERT_BLOCK() +#endif /* CONFIG_ESP_MFI_ASSERT_BLOCK */ + +/* debug level with different color */ +#define ESP_MFI_DEBUG_INFO 1 +#define ESP_MFI_DEBUG_WARN 2 +#define ESP_MFI_DEBUG_ERR 3 +#define ESP_MFI_DEBUG_ASSERT 4 +#define ESP_MFI_DEBUG_BLOCK 5 + +/** + * @bref set the MFI debugging level + * + * @param level debugging level + * + * @return the result + * = 0 : OK + * others : failed + */ +int esp_mfi_set_debug_level(uint32_t level); + +/** + * @bref get the MFI debugging level and output data color + * + * @param level input debug level + * @param color data color + * + * @return MFI debugging level + */ +uint32_t esp_mfi_get_debug_level(uint32_t level, uint32_t *color); + +/** + * @bref format the string and data, then output it + * + * @param level if level > MFI_DEBUG_LEVEL then output it + * @param fmt format string + * @param ... parameters of format string + * + * @return none + * + * void ESP_MFI_DEBUG(unsigned int level, const char *fmt, ...); + */ +#ifdef ESP_MFI_DEBUG_ENABLE +/* +#define ESP_MFI_DEBUG(l, fmt, ...) \ + { \ + uint32_t __color_LINE; \ + if (l > esp_mfi_get_debug_level(l, &__color_LINE)) { \ + printf("\e[1;%dm" fmt "\e[0m" ESP_MFI_DEBUG_FL, \ + __color_LINE, ##__VA_ARGS__); \ + } \ + } +#define ESP_MFI_DEBUG_INTR(l, fmt, ...) \ + { \ + uint32_t __color_LINE; \ + if (l > esp_mfi_get_debug_level(l, &__color_LINE)) { \ + ets_printf("\e[1;%dm" fmt "\e[0m" ESP_MFI_DEBUG_FL, \ + __color_LINE, ##__VA_ARGS__); \ + } \ + } + +#define ESP_MFI_DEBUG(l, fmt, ...) \ + { \ + uint32_t __color_LINE; \ + if (l > esp_mfi_get_debug_level(l, &__color_LINE)) { \ + printf("[%7lu] " fmt "\n", ((unsigned long) (esp_timer_get_time() / 1000ULL)), ##__VA_ARGS__); \ + } \ + } +#define ESP_MFI_DEBUG_INTR(l, fmt, ...) \ + { \ + uint32_t __color_LINE; \ + if (l > esp_mfi_get_debug_level(l, &__color_LINE)) { \ + printf("[%7lu] " fmt "\n", ((unsigned long) (esp_timer_get_time() / 1000ULL)), ##__VA_ARGS__); \ + } \ + }*/ + +#define ESP_MFI_DEBUG(l, fmt, ...) \ + { \ + printf("[%7lu] " fmt "\n", ((unsigned long) (esp_timer_get_time() / 1000ULL)), ##__VA_ARGS__); \ + } +#define ESP_MFI_DEBUG_INTR(l, fmt, ...) \ + { \ + printf("[%7lu] " fmt "\n", ((unsigned long) (esp_timer_get_time() / 1000ULL)), ##__VA_ARGS__); \ + } +#else /* ESP_MFI_DEBUG_ENABLE */ +#define ESP_MFI_DEBUG(l, fmt, ...) +#define ESP_MFI_DEBUG_INTR(l, fmt, ...) +#endif /* ESP_MFI_DEBUG_ENABLE */ + +/** + * @bref if the signal is false(0) do something depended on configuration + * + * @param conditions checking conditions + * + * @return none + * + * void ESP_MFI_ASSERT(int conditions); + */ +#ifdef ESP_MFI_ASSERT_ENABLE +#define ESP_MFI_ASSERT(cond) \ +{ \ + if (!(cond)) { \ + printf("\e[1;33m" "ESP_MFI assert file %s line %d" ESP_MFI_DEBUG_FL, \ + __FILE__, __LINE__); \ + ESP_MFI_ASSERT_BLOCK(); \ + } \ +} +#else +#define ESP_MFI_ASSERT(cond) +#endif + +/** + * @bref check if data length matches given length + * + * @param optlen data length + * @param opttype data + * + * @return none + * + * void ESP_MFI_CHECK_OPTLEN(int conditions, (all type) data); + */ +#define ESP_MFI_CHECK_OPTLEN(optlen, opttype) \ + do { \ + if ((optlen) > sizeof(opttype)) { \ + return -1; \ + } \ + } while(0) \ + +#ifdef __cplusplus +} +#endif + +#endif /* ESP_MFI_DEBUG_H_ */ diff --git a/lib/libesp32_div/ESP32-HomeKit/src/esp_mfi_dummy.c b/lib/libesp32_div/ESP32-HomeKit/src/esp_mfi_dummy.c new file mode 100644 index 000000000..9ddcd1fc0 --- /dev/null +++ b/lib/libesp32_div/ESP32-HomeKit/src/esp_mfi_dummy.c @@ -0,0 +1,84 @@ +/* + * ESPRESSIF MIT License + * + * Copyright (c) 2020 + * + * Permission is hereby granted for use on ESPRESSIF SYSTEMS products only, in which case, + * it is 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 +#include +#include +#include +#include +#include +#include + +ESP_EVENT_DEFINE_BASE(HAP_WAC_EVENT); + +int hap_pair_setup_manage_mfi_auth(pair_setup_ctx_t *ps_ctx, hap_tlv_data_t *tlv_data, hap_tlv_error_t *tlv_error) +{ + + if (ps_ctx->method == HAP_METHOD_PAIR_SETUP) { + ESP_MFI_DEBUG(ESP_MFI_DEBUG_ERR, "Secure pair setup not supported. Please use MFi variant of the SDK."); + *tlv_error = kTLVError_Unknown; + return HAP_FAIL; + } + ESP_MFI_DEBUG(ESP_MFI_DEBUG_WARN, "Using pair-setup without MFi."); + return ESP_OK; +} + +int hap_enable_mfi_auth(hap_mfi_auth_type_t auth_type) +{ + ESP_MFI_DEBUG(ESP_MFI_DEBUG_WARN, "MFi auth not supported. Falling back to HAP_MFI_AUTH_NONE"); + hap_priv.auth_type = HAP_MFI_AUTH_NONE; + return 0; +} + +int hap_wac_start(void) +{ + ESP_MFI_DEBUG(ESP_MFI_DEBUG_ERR, "WAC not supported. Please use MFi variant of the SDK."); + return ESP_FAIL; +} + +int hap_wac_stop(void) +{ + ESP_MFI_DEBUG(ESP_MFI_DEBUG_ERR, "WAC not supported. Please use MFi variant of the SDK."); + return ESP_FAIL; +} +int hap_enable_hw_auth(void) +{ + ESP_MFI_DEBUG(ESP_MFI_DEBUG_ERR, "MFi HW Auth not supported. Please use MFi variant of the SDK."); + return ESP_FAIL; + +} +int hap_enable_sw_auth(void) +{ + ESP_MFI_DEBUG(ESP_MFI_DEBUG_ERR, "MFi SW Auth not supported. Please use MFi variant of the SDK."); + return ESP_FAIL; +} +int hap_register_secure_message_handler(httpd_handle_t handle) +{ + ESP_MFI_DEBUG(ESP_MFI_DEBUG_ERR, "MFi SW Auth not supported. Please use MFi variant of the SDK."); + return ESP_FAIL; +} +int hap_unregister_secure_message_handler(httpd_handle_t handle) +{ + ESP_MFI_DEBUG(ESP_MFI_DEBUG_ERR, "MFi SW Auth not supported. Please use MFi variant of the SDK."); + return ESP_FAIL; +} diff --git a/lib/libesp32_div/ESP32-HomeKit/src/esp_mfi_i2c.c.0 b/lib/libesp32_div/ESP32-HomeKit/src/esp_mfi_i2c.c.0 new file mode 100644 index 000000000..c75e8b6f9 --- /dev/null +++ b/lib/libesp32_div/ESP32-HomeKit/src/esp_mfi_i2c.c.0 @@ -0,0 +1,689 @@ +/* + * ESPRESSIF MIT License + * + * Copyright (c) 2020 + * + * Permission is hereby granted for use on ESPRESSIF SYSTEMS products only, in which case, + * it is 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 +#include +#include +#ifdef CONFIG_IDF_TARGET_ESP32S2 +#include "esp32s2/rom/ets_sys.h" +#else +#include "esp32/rom/ets_sys.h" +#endif + +#ifdef CONFIG_I2C_SOFTWARE +#include "driver/gpio.h" +#else +#include "driver/i2c.h" +#endif + +#include "esp_log.h" +#include "esp_mfi_i2c.h" + +static const char *TAG = "mfi_i2c"; + +#ifndef CONFIG_I2C_SOFTWARE + +#define I2C_MASTER_NUM I2C_NUM_0 +#define I2C_MASTER_FREQ_HZ CONFIG_IC2_SPEED +#define I2C_MASTER_RX_BUF_DISABLE 0 +#define I2C_MASTER_TX_BUF_DISABLE 0 +#define ACK_CHECK_EN 1 +#define ACK_VAL 0 +#define NACK_VAL 1 + +/* To use GPIOs 17/18 for the Hardware I2C, replace the numbers 26/27 below + */ +#define I2C_MASTER_SDA_GPIO CONFIG_SDA_GPIO +#define I2C_MASTER_SCL_GPIO CONFIG_SCL_GPIO + +#define I2C_MASTER_MAX_READ CONFIG_I2C_MAX_READ_COUNT +#define I2C_MASTER_RETRY_TIMES 500 +#define I2C_MASTER_TICKS_TIMES 2 * I2C_MASTER_RETRY_TIMES +#define I2C_MASTER_MAX_RETRY 10 +#define I2C_MASTER_INTERNAL_TIMES 8 * I2C_MASTER_RETRY_TIMES +/** + * @brief Initialize I2C information + */ +int esp_mfi_i2c_init(void) +{ + int ret = 0; + i2c_config_t conf; + int i2c_master_port = I2C_MASTER_NUM; + + conf.mode = I2C_MODE_MASTER; + conf.sda_io_num = I2C_MASTER_SDA_GPIO; + conf.sda_pullup_en = GPIO_PULLUP_ENABLE; + conf.scl_io_num = I2C_MASTER_SCL_GPIO; + conf.scl_pullup_en = GPIO_PULLUP_ENABLE; + conf.master.clk_speed = I2C_MASTER_FREQ_HZ; + + ret = i2c_param_config(i2c_master_port, &conf); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "I2C parameter initial fail %d", ret); + return -EINVAL; + } + + ret = i2c_driver_install(i2c_master_port, conf.mode, I2C_MASTER_RX_BUF_DISABLE, I2C_MASTER_TX_BUF_DISABLE, 0); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "I2C driver initial fail %d", ret); + return -EINVAL; + } + + return 0; +} +/** + * @brief write data buffer to slave + */ +int esp_mfi_i2c_write(uint8_t slvaddr, uint8_t regaddr, uint8_t *buff, uint32_t len) +{ + uint16_t i; + + if (!buff) + return -EINVAL; + + ESP_LOGI(TAG, "Writing to HW I2C"); + + int ret = 0; + i2c_cmd_handle_t cmd = NULL; + i = 0; + + do { + cmd = i2c_cmd_link_create(); + i2c_master_start(cmd); + + // Send write address of the CP + i2c_master_write_byte(cmd, slvaddr, ACK_CHECK_EN); + // Send register address to slave. + i2c_master_write_byte(cmd, regaddr, ACK_CHECK_EN); + // Send data out. + i2c_master_write(cmd, buff, len, ACK_CHECK_EN); + + i2c_master_stop(cmd); + ret = i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, I2C_MASTER_TICKS_TIMES / portTICK_RATE_MS); + i ++; + i2c_cmd_link_delete(cmd); + ets_delay_us(I2C_MASTER_RETRY_TIMES); + } while(ret != ESP_OK && i < I2C_MASTER_MAX_RETRY); + + if (ret != ESP_OK) { + ESP_LOGE(TAG, "Write data to slave fail %d.", ret); + } + return ret; +} + +/** + * @brief read data form slave + */ +int esp_mfi_i2c_read(uint8_t slvaddr, uint8_t regaddr, uint8_t *buff, uint32_t len) +{ + uint16_t i, j = 0; + + if (!buff) + return -EINVAL; + + ESP_LOGI(TAG, "Reading from HW I2C"); + + int ret = 0; + i2c_cmd_handle_t cmd = NULL; + i = 0; + + do { + for (j = 0; j < I2C_MASTER_MAX_READ; j++) { + cmd = i2c_cmd_link_create(); + i2c_master_start(cmd); + + // Send write address of the CP + i2c_master_write_byte(cmd, slvaddr, ACK_CHECK_EN); + // Send register address to slave. + i2c_master_write_byte(cmd, regaddr, ACK_CHECK_EN); + + i2c_master_stop(cmd); + ret = i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, I2C_MASTER_TICKS_TIMES / portTICK_RATE_MS); + i2c_cmd_link_delete(cmd); + if (ret == ESP_OK) { + break; + } else { + ets_delay_us(I2C_MASTER_INTERNAL_TIMES); + } + } + + ets_delay_us(I2C_MASTER_INTERNAL_TIMES); + + cmd = i2c_cmd_link_create(); + i2c_master_start(cmd); + + i2c_master_write_byte(cmd, slvaddr + 1, ACK_CHECK_EN); + if (len == 1) + i2c_master_read_byte(cmd, buff, NACK_VAL); + else { + i2c_master_read(cmd, buff, len - 1, ACK_VAL); + i2c_master_read_byte(cmd, buff + len - 1, NACK_VAL); + } + + i2c_master_stop(cmd); + ret = i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, I2C_MASTER_TICKS_TIMES / portTICK_RATE_MS); + i ++; + i2c_cmd_link_delete(cmd); + } while (ret != ESP_OK && i < I2C_MASTER_MAX_RETRY); + + if (ret != ESP_OK) { + ESP_LOGE(TAG, "Read data from slave fail %d.", ret); + } + + return ret; +} + +#else + +#define MFI_CP_BUSY_RETRY_TIMES CONFIG_I2C_RETRY_COUNT + +#define GPIO_Pin_26 GPIO_SEL_26 +#define GPIO_Pin_27 GPIO_SEL_27 + +#define gpio_set_output_level(a, b) gpio_set_level(a, b) +#define gpio_get_input_level(a) gpio_get_level(a) + +#define GPIO_Mode_Input_OutOD GPIO_MODE_INPUT_OUTPUT_OD +#define GPIO_PullDown_DIS GPIO_PULLDOWN_DISABLE +#define GPIO_PullUp_EN GPIO_PULLUP_ENABLE +#define GPIO_Mode_Out_OD GPIO_MODE_OUTPUT_OD + +#define I2C_MASTER_SDA_MUX PERIPHS_IO_MUX_GPIO26_U +#define I2C_MASTER_SCL_MUX PERIPHS_IO_MUX_GPIO27_U +#define I2C_MASTER_SDA_GPIO 26 +#define I2C_MASTER_SDA_PIN GPIO_Pin_26 +#define I2C_MASTER_SDA_FUNC FUNC_GPIO26_GPIO26 +#define I2C_MASTER_SCL_GPIO 27 +#define I2C_MASTER_SCL_PIN GPIO_Pin_27 +#define I2C_MASTER_SCL_FUNC FUNC_GPIO27_GPIO27 + +#define I2C_MASTER_SDA_HIGH_SCL_HIGH() \ + gpio_set_output_level(I2C_MASTER_SDA_GPIO,1); \ + gpio_set_output_level(I2C_MASTER_SCL_GPIO,1); + +#define I2C_MASTER_SDA_HIGH_SCL_LOW() \ + gpio_set_output_level(I2C_MASTER_SDA_GPIO,1); \ + gpio_set_output_level(I2C_MASTER_SCL_GPIO,0); + +#define I2C_MASTER_SDA_LOW_SCL_HIGH() \ + gpio_set_output_level(I2C_MASTER_SDA_GPIO,0); \ + gpio_set_output_level(I2C_MASTER_SCL_GPIO,1); + +#define I2C_MASTER_SDA_LOW_SCL_LOW() \ + gpio_set_output_level(I2C_MASTER_SDA_GPIO,0); \ + gpio_set_output_level(I2C_MASTER_SCL_GPIO,0); + +#define i2c_master_wait ets_delay_us + +static void i2c_master_init(void); +static void i2c_master_stop(void); + +static uint8_t s_last_sda; +static uint8_t s_last_scl; + +/** + * @brief set I2C SDA and SCL bit value for half CLK cycle + */ +static void i2c_master_setDC(uint8_t SDA, uint8_t SCL) +{ + SDA &= 0x01; + SCL &= 0x01; + s_last_sda = SDA; + s_last_scl = SCL; + + if ((0 == SDA) && (0 == SCL)) { + I2C_MASTER_SDA_LOW_SCL_LOW(); + } else if ((0 == SDA) && (1 == SCL)) { + I2C_MASTER_SDA_LOW_SCL_HIGH(); + } else if ((1 == SDA) && (0 == SCL)) { + I2C_MASTER_SDA_HIGH_SCL_LOW(); + } else { + I2C_MASTER_SDA_HIGH_SCL_HIGH(); + } +} + +/** + * @brief get I2C SDA bit value + */ +static uint8_t i2c_master_getDC(void) +{ + uint8_t sda_out; + + sda_out = gpio_get_input_level(GPIO_ID_PIN(I2C_MASTER_SDA_GPIO)); + + return sda_out; +} + +/** + * @brief initialize I2C bus to enable i2c operations + */ +static void i2c_master_init(void) +{ + uint8_t i; + + i2c_master_setDC(1, 0); + i2c_master_wait(5); + + // when SCL = 0, toggle SDA to clear up + i2c_master_setDC(0, 0) ; + i2c_master_wait(5); + i2c_master_setDC(1, 0) ; + i2c_master_wait(5); + + // set data_cnt to max value + for (i = 0; i < 28; i++) { + i2c_master_setDC(1, 0); + i2c_master_wait(5); // sda 1, scl 0 + i2c_master_setDC(1, 1); + i2c_master_wait(5); // sda 1, scl 1 + } + + // reset all + i2c_master_stop(); +} + +/** + * @brief configure SDA and SCL GPIO to open-drain output mode + */ +static void i2c_master_gpio_init(void) +{ + + gpio_config_t io_config; + io_config.intr_type = GPIO_PIN_INTR_DISABLE; + io_config.mode = GPIO_MODE_INPUT_OUTPUT_OD; + io_config.pin_bit_mask = I2C_MASTER_SDA_PIN; + io_config.pull_down_en = GPIO_PULLDOWN_DISABLE; + io_config.pull_up_en = GPIO_PULLUP_ENABLE; + + gpio_config(&io_config); + + io_config.intr_type = GPIO_PIN_INTR_DISABLE; + io_config.mode = GPIO_MODE_OUTPUT_OD; + io_config.pin_bit_mask = I2C_MASTER_SCL_PIN; + io_config.pull_down_en = GPIO_PULLDOWN_DISABLE; + io_config.pull_up_en = GPIO_PULLUP_ENABLE; + + + gpio_config(&io_config); + + gpio_pullup_en(I2C_MASTER_SDA_GPIO); + gpio_pullup_en(I2C_MASTER_SCL_GPIO); + gpio_pulldown_dis(I2C_MASTER_SDA_GPIO); + gpio_pulldown_dis(I2C_MASTER_SCL_GPIO); + + i2c_master_init(); +} + +/** + * @brief set I2C to start operation + */ +static void i2c_master_start(void) +{ + i2c_master_setDC(1, s_last_scl); + i2c_master_wait(5); + i2c_master_setDC(1, 1); + i2c_master_wait(5); // sda 1, scl 1 + i2c_master_setDC(0, 1); + i2c_master_wait(5); // sda 0, scl 1 +} + +/** + * @brief set i2c to stop sending state + */ +static void i2c_master_stop(void) +{ + i2c_master_wait(5); + + i2c_master_setDC(0, s_last_scl); + i2c_master_wait(5); // sda 0 + i2c_master_setDC(0, 1); + i2c_master_wait(5); // sda 0, scl 1 + i2c_master_setDC(1, 1); + i2c_master_wait(5); // sda 1, scl 1 +} + +/** + * @brief set ack to i2c bus as level value + */ +static void i2c_master_setAck(uint8_t level) +{ + i2c_master_setDC(s_last_sda, 0); + i2c_master_wait(5); + i2c_master_setDC(level, 0); + i2c_master_wait(5); // sda level, scl 0 + i2c_master_setDC(level, 1); + i2c_master_wait(8); // sda level, scl 1 + i2c_master_setDC(level, 0); + i2c_master_wait(5); // sda level, scl 0 + i2c_master_setDC(1, 0); + i2c_master_wait(5); +} + +/** + * @brief confirm if peer send ack + */ +static uint8_t i2c_master_getAck(void) +{ + uint8_t retVal; + + i2c_master_setDC(s_last_sda, 0); + i2c_master_wait(5); + i2c_master_setDC(1, 0); + i2c_master_wait(5); + i2c_master_setDC(1, 1); + i2c_master_wait(5); + + retVal = i2c_master_getDC(); + i2c_master_wait(5); + i2c_master_setDC(1, 0); + i2c_master_wait(5); + + return retVal; +} + +/** + * @brief get I2C response + */ +static bool i2c_master_checkAck(void) +{ + if (i2c_master_getAck()) { + return false; + } else { + return true; + } +} + +/** + * @brief send I2C ack signal + */ +static void i2c_master_send_ack(void) +{ + i2c_master_setAck(0x0); +} + +/** + * @brief send I2C not ack signal + */ +static void i2c_master_send_nack(void) +{ + i2c_master_setAck(0x1); +} + +/** + * @brief read byte from i2c bus + */ +static uint8_t i2c_master_readByte(void) +{ + uint8_t retVal = 0; + uint8_t k, i; + + i2c_master_wait(5); + i2c_master_setDC(s_last_sda, 0); + i2c_master_wait(5); // sda 1, scl 0 + + for (i = 0; i < 8; i++) { + i2c_master_wait(5); + i2c_master_setDC(1, 0); + i2c_master_wait(5); // sda 1, scl 0 + i2c_master_setDC(1, 1); + i2c_master_wait(5); // sda 1, scl 1 + + k = i2c_master_getDC(); + i2c_master_wait(5); + + if (i == 7) { + i2c_master_wait(3); + } + + k <<= (7 - i); + retVal |= k; + } + + i2c_master_setDC(1, 0); + i2c_master_wait(5); // sda 1, scl 0 + + return retVal; +} + +/** + * @brief write byte to i2c + */ +static void i2c_master_writeByte(uint8_t wrdata) +{ + uint8_t dat; + int8_t i; + + i2c_master_wait(5); + i2c_master_setDC(s_last_sda, 0); + i2c_master_wait(5); + + for (i = 7; i >= 0; i--) { + dat = wrdata >> i; + i2c_master_setDC(dat, 0); + i2c_master_wait(5); + i2c_master_setDC(dat, 1); + i2c_master_wait(5); + + if (i == 0) { + i2c_master_wait(3); //// + } + + i2c_master_setDC(dat, 0); + i2c_master_wait(5); + } + +} + +/** + * @brief write byte to i2c and get check ack + */ +static bool i2c_write_byte(uint8_t data, uint8_t iter) +{ + if (iter == 0) { + iter = 1; + } + + while (iter--) { + i2c_master_writeByte(data); + + if (i2c_master_getAck()) { + i2c_master_stop(); + ets_delay_us(500); // Wait 500us and retry. + i2c_master_start(); + } else { + return true; + } + } + i2c_master_stop(); + return false; +} + +/** + * @brief write byte to target register of target I2C slave + */ +static void i2c_write_reg(uint8_t slave_add, uint8_t reg_add, uint16_t data) +{ + i2c_master_start(); + if (false == i2c_write_byte(slave_add, 30)) { + ESP_LOGE(TAG, "1Slave is busy, [%02x]TIME OUT\n", slave_add); + } + if (false == i2c_write_byte(reg_add, 30)) { + ESP_LOGE(TAG, "2Slave is busy, [%02x]TIME OUT\n", reg_add); + } + if (false == i2c_write_byte((data >> 8), 30)) { + ESP_LOGE(TAG, "3Slave is busy, [%02x]TIME OUT\n", data); + } + if (false == i2c_write_byte((data & 0xFF), 30)) { + ESP_LOGE(TAG, "3Slave is busy, [%02x]TIME OUT\n", data); + } + i2c_master_stop(); +} + +/** + * @brief a block of data to I2C + */ +static void i2s_write_arr(const uint8_t *data, size_t len) +{ + if (data == NULL || len <= 0) return; + + i2c_master_start(); + + int i = 0; + for (i = 0; i < len; ++i) { + if (false == i2c_write_byte(data[i], 30)) { + ESP_LOGE(TAG, "Slave is busy, [%02x]TIME OUT\n", data[i]); + } + } + i2c_master_stop(); +} + +/** + * @brief Initialize I2C information + */ +int esp_mfi_i2c_init(void) +{ + i2c_master_gpio_init(); + return 0; +} + +/** + * @brief Finish I2C information + */ +int esp_mfi_i2c_end(void) +{ + return 0; +} + +/** + * @brief write one byte data to slave + */ +static int esp_mfi_i2c_write_byte(uint8_t data, uint16_t retrytimes) +{ + uint16_t times = retrytimes; + if (0 == times) { + times = 1; + } + + while (times--) { + i2c_master_writeByte(data); + if (i2c_master_getAck()) { + i2c_master_wait(500); /**< Wait 500us and retry */ + i2c_master_stop(); + i2c_master_wait(500); /**< Wait 500us and retry */ + i2c_master_start(); + } else { + return 0; + } + } + + i2c_master_stop(); + + return -ETIME; +} + +/** + * @brief write data buffer to slave + */ +int esp_mfi_i2c_write(uint8_t slvaddr, uint8_t regaddr, uint8_t *buff, uint32_t len) +{ + uint16_t i; + + if (!buff) + return -EINVAL; + + ESP_LOGI(TAG, "Writing to SW I2C"); + + i2c_master_start(); + + /**< Send write address of the CP */ + if (esp_mfi_i2c_write_byte(slvaddr, MFI_CP_BUSY_RETRY_TIMES) != 0) { + ESP_LOGE(TAG, "Slave is busy, time out."); + return -ETIME; + } + + /**< Send register address to slave */ + if (esp_mfi_i2c_write_byte(regaddr, 0) != 0) { + ESP_LOGE(TAG, "Write register address[0x%02x] to slave.", regaddr); + return -ENODATA; + } + + /**< Send data out */ + for (i = 0; i < len; ++i) { + if (esp_mfi_i2c_write_byte(*buff++, 0) != 0) { + ESP_LOGE(TAG, "Write data[0x%02x] to slave.", *buff); + return -ENODATA; + } + } + + i2c_master_stop(); + + return 0; +} + +/** + * @brief read data form slave + */ +int esp_mfi_i2c_read(uint8_t slvaddr, uint8_t regaddr, uint8_t *buff, uint32_t len) +{ + uint16_t i; + + if (!buff) + return -EINVAL; + + ESP_LOGI(TAG, "Reading from SW I2C"); + + i2c_master_start(); + + /**< Send write address of the CP */ + if (esp_mfi_i2c_write_byte(slvaddr, MFI_CP_BUSY_RETRY_TIMES) != 0) { + ESP_LOGE(TAG, "Slave is busy, time out."); + return -ETIME; + } + + /**< Send register address to slave */ + if (esp_mfi_i2c_write_byte(regaddr, 0) != 0) { + ESP_LOGE(TAG, "Write register address[0x%02x] to slave.", regaddr); + return -ENODATA; + } + i2c_master_stop(); + + i2c_master_wait(4000); + + /**< Send read address of the CP */ + if (esp_mfi_i2c_write_byte((slvaddr + 1), MFI_CP_BUSY_RETRY_TIMES) != 0) { + ESP_LOGE(TAG, "Slave is busy, time out."); + return -ETIME; + } + + for (i = 0; i < len; ++i) { + buff[i] = i2c_master_readByte(); + + i2c_master_setAck((i == (len - 1)) ? 1 : 0); + } + + i2c_master_stop(); + + return 0; +} +#endif diff --git a/lib/libesp32_div/ESP32-HomeKit/src/esp_mfi_i2c.h.0 b/lib/libesp32_div/ESP32-HomeKit/src/esp_mfi_i2c.h.0 new file mode 100644 index 000000000..4813bc01e --- /dev/null +++ b/lib/libesp32_div/ESP32-HomeKit/src/esp_mfi_i2c.h.0 @@ -0,0 +1,84 @@ +/* + * ESPRESSIF MIT License + * + * Copyright (c) 2020 + * + * Permission is hereby granted for use on ESPRESSIF SYSTEMS products only, in which case, + * it is 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. + * + */ + +#ifndef ESP_MFI_I2C_H_ +#define ESP_MFI_I2C_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Initialize I2C + * + * @return + * - 0 : succeed + * - others : fail + */ +int esp_mfi_i2c_init(void); + +/** + * @brief I2C operation end + * + * @return + * - 0 : succeed + * - others : fail + */ +int esp_mfi_i2c_end(void); + +/** + * @brief Write data to I2C slave + * + * @param slvaddr address of slave + * @param regaddr address of register + * @param buff pointer of data to write + * @param len the data length + * + * @return + * - 0 : succeed + * - others : fail + */ +int esp_mfi_i2c_write(uint8_t slvaddr, uint8_t regaddr, uint8_t *buff, uint32_t len); + +/** + * @brief Read data from I2C slave + * + * @param slvaddr address of slave + * @param regaddr address of register + * @param buff pointer of data read + * @param len the data length + * + * @return + * - 0 : succeed + * - others : fail + */ +int esp_mfi_i2c_read(uint8_t slvaddr, uint8_t regaddr, uint8_t *buff, uint32_t len); + +#ifdef __cplusplus +} +#endif + +#endif /* ESP_MFI_I2C_H_ */ diff --git a/lib/libesp32_div/ESP32-HomeKit/src/esp_mfi_rand.c b/lib/libesp32_div/ESP32-HomeKit/src/esp_mfi_rand.c new file mode 100644 index 000000000..437da0fc8 --- /dev/null +++ b/lib/libesp32_div/ESP32-HomeKit/src/esp_mfi_rand.c @@ -0,0 +1,56 @@ +/* + * ESPRESSIF MIT License + * + * Copyright (c) 2020 + * + * Permission is hereby granted for use on ESPRESSIF SYSTEMS products only, in which case, + * it is 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 +#include + +/** + * @bref Obtain a series of random bytes + * + * @param buf the random bytes were copied point + * len the number of bytes requested + * + * @return the result + * > 0 : the number of bytes that were copied to the buffer + * others : failed + */ +int esp_mfi_get_random(uint8_t *buf, uint16_t len) +{ + int i, j; + unsigned long tmp; + + for (i = 0; i < ((len + 3) & ~3) / 4; i++) { + tmp = esp_random(); + + for (j = 0; j < 4; j++) { + if ((i * 4 + j) < len) { + buf[i * 4 + j] = (uint8_t) (tmp >> (j * 8)); + } else { + break; + } + } + } + + return len; +} diff --git a/lib/libesp32_div/ESP32-HomeKit/src/esp_mfi_rand.h b/lib/libesp32_div/ESP32-HomeKit/src/esp_mfi_rand.h new file mode 100644 index 000000000..ad2808af9 --- /dev/null +++ b/lib/libesp32_div/ESP32-HomeKit/src/esp_mfi_rand.h @@ -0,0 +1,50 @@ +/* + * ESPRESSIF MIT License + * + * Copyright (c) 2020 + * + * Permission is hereby granted for use on ESPRESSIF SYSTEMS products only, in which case, + * it is 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. + * + */ + +#ifndef ESP_MFI_RAND_H_ +#define ESP_MFI_RAND_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Get a random number of bytes specified. + * + * @param buf pointer of the random number it gets + * @param len specified bytes of the random number + * + * @return + * - > 0 : the actual length(bytes) of the random number + * - others : failure + */ +int esp_mfi_get_random(uint8_t *buf, uint16_t len); + +#ifdef __cplusplus +} +#endif + +#endif /* ESP_MFI_RAND_H_ */ diff --git a/lib/libesp32_div/ESP32-HomeKit/src/esp_mfi_sha.c b/lib/libesp32_div/ESP32-HomeKit/src/esp_mfi_sha.c new file mode 100644 index 000000000..5bf80b0b3 --- /dev/null +++ b/lib/libesp32_div/ESP32-HomeKit/src/esp_mfi_sha.c @@ -0,0 +1,279 @@ +/* + * ESPRESSIF MIT License + * + * Copyright (c) 2020 + * + * Permission is hereby granted for use on ESPRESSIF SYSTEMS products only, in which case, + * it is 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 + +#include "mbedtls/sha1.h" +#include "mbedtls/sha256.h" +#include "mbedtls/sha512.h" + +#include "esp_mfi_sha.h" + +#ifdef CONFIG_IDF_TARGET_ESP8266 +#define mbedtls_sha512_starts mbedtls_sha512_starts_ret +#define mbedtls_sha512_update mbedtls_sha512_update_ret +#define mbedtls_sha512_finish mbedtls_sha512_finish_ret +#endif + +/** + * @bref Create SHA1 context + * + * @param none + * + * @return the SHA1 context point + */ +esp_mfi_sha_ctx_t esp_mfi_sha1_new(void) +{ + mbedtls_sha1_context *context = NULL; + context = (mbedtls_sha1_context *) malloc(sizeof(mbedtls_sha1_context)); + mbedtls_sha1_init(context); + return context; +} + +/** + * @bref Free SHA1 context + * + * @param ctx the SHA1 context point + * + * @return none + */ +void esp_mfi_sha1_free(esp_mfi_sha_ctx_t ctx) +{ + if (ctx) { + mbedtls_sha1_free( (mbedtls_sha1_context *)ctx); + free(ctx); + } +} + +/** + * @bref Init SHA1 context + * + * @param ctx the SHA1 context point + * + * @return none + */ +void esp_mfi_sha1_init(esp_mfi_sha_ctx_t ctx) +{ + if (ctx == NULL) + return; + + mbedtls_sha1_starts((mbedtls_sha1_context *) ctx); +} + +/** + * @bref Update SHA1 context + * + * @param ctx the SHA1 context point + * msg input data point + * len input data length + * + * @return none + */ +void esp_mfi_sha1_update(esp_mfi_sha_ctx_t ctx, const uint8_t * msg, int len) +{ + if (ctx == NULL || msg == NULL) + return; + + mbedtls_sha1_update((mbedtls_sha1_context *) ctx, msg, len); +} + +/** + * @bref Final SHA1 context + * + * @param digest output data point + * ctx the SHA1 context point + * + * @return none + */ +void esp_mfi_sha1_final(esp_mfi_sha_ctx_t ctx, uint8_t *digest) +{ + if (ctx == NULL || digest == NULL) + return; + + mbedtls_sha1_finish((mbedtls_sha1_context *) ctx, digest); +} + +/* + * SHA256 declarations + */ + +/** + * @bref Create SHA256 context + * + * @param none + * + * @return the SHA256 context point + */ +esp_mfi_sha_ctx_t esp_mfi_sha256_new(void) +{ + mbedtls_sha256_context *context = NULL; + context = (mbedtls_sha256_context *) malloc(sizeof(mbedtls_sha256_context)); + mbedtls_sha256_init(context); + return context; +} + +/** + * @bref Free SHA256 context + * + * @param ctx the SHA256 context point + * + * @return none + */ +void esp_mfi_sha256_free(esp_mfi_sha_ctx_t ctx) +{ + if (ctx) { + mbedtls_sha256_free((mbedtls_sha256_context *)ctx); + free(ctx); + } +} + +/** + * @bref Init SHA256 context + * + * @param ctx the SHA256 context point + * + * @return none + */ +void esp_mfi_sha256_init(esp_mfi_sha_ctx_t ctx) +{ + if (ctx == NULL) + return; + + mbedtls_sha256_starts((mbedtls_sha256_context *) ctx, 0); +} + +/** + * @bref Update SHA256 context + * + * @param ctx the SHA256 context point + * msg input data point + * len input data length + * + * @return none + */ +void esp_mfi_sha256_update(esp_mfi_sha_ctx_t ctx, const uint8_t *input, int len) +{ + if (ctx == NULL || input == NULL) + return; + + mbedtls_sha256_update((mbedtls_sha256_context *) ctx, input, len); +} + +/** + * @bref Final SHA256 context + * + * @param digest output data point + * ctx the SHA256 context point + * + * @return none + */ +void esp_mfi_sha256_final(esp_mfi_sha_ctx_t ctx, uint8_t *digest) +{ + if (ctx == NULL || digest == NULL) + return; + + mbedtls_sha256_finish((mbedtls_sha256_context *) ctx, digest); +} + +/* + * SHA512 declarations + */ + +/** + * @bref Create SHA512 context + * + * @param none + * + * @return the SHA512 context point + */ +esp_mfi_sha_ctx_t esp_mfi_sha512_new(void) +{ + mbedtls_sha512_context *context = NULL; + context = (mbedtls_sha512_context *) malloc(sizeof(mbedtls_sha512_context)); + mbedtls_sha512_init(context); + return context; +} + +/** + * @bref Free SHA512 context + * + * @param ctx the SHA512 context point + * + * @return none + */ +void esp_mfi_sha512_free(esp_mfi_sha_ctx_t ctx) +{ + if (ctx) { + mbedtls_sha512_free((mbedtls_sha512_context *)ctx); + free(ctx); + } +} + +/** + * @bref Init SHA512 context + * + * @param ctx the SHA512 context point + * + * @return none + */ +void esp_mfi_sha512_init(esp_mfi_sha_ctx_t ctx) +{ + if (ctx == NULL) + return; + + mbedtls_sha512_starts((mbedtls_sha512_context *) ctx, 0); +} + +/** + * @bref Update SHA512 context + * + * @param ctx the SHA512 context point + * msg input data point + * len input data length + * + * @return none + */ +void esp_mfi_sha512_update(esp_mfi_sha_ctx_t ctx, const uint8_t *input, int len) +{ + if (ctx == NULL || input == NULL) + return; + + mbedtls_sha512_update((mbedtls_sha512_context *) ctx, input, len); +} + +/** + * @bref Final SHA512 context + * + * @param digest output data point + * ctx the SHA512 context point + * + * @return none + */ +void esp_mfi_sha512_final(esp_mfi_sha_ctx_t ctx, uint8_t *digest) +{ + if (ctx == NULL || digest == NULL) + return; + + mbedtls_sha512_finish((mbedtls_sha512_context *) ctx, digest); +} diff --git a/lib/libesp32_div/ESP32-HomeKit/src/esp_mfi_sha.h b/lib/libesp32_div/ESP32-HomeKit/src/esp_mfi_sha.h new file mode 100644 index 000000000..87d4058c6 --- /dev/null +++ b/lib/libesp32_div/ESP32-HomeKit/src/esp_mfi_sha.h @@ -0,0 +1,172 @@ +/* + * ESPRESSIF MIT License + * + * Copyright (c) 2020 + * + * Permission is hereby granted for use on ESPRESSIF SYSTEMS products only, in which case, + * it is 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. + * + */ + +#ifndef ESP_MFI_SHA_H_ +#define ESP_MFI_SHA_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef void* esp_mfi_sha_ctx_t; + +/* + * SHA1 declarations + */ + +#define MFI_SHA1_SIZE 20 + +/** + * @brief Create SHA1 context + * + * @return pointer of the SHA1 context + */ +esp_mfi_sha_ctx_t esp_mfi_sha1_new(void); + +/** + * @brief Init SHA1 context + * + * @param ctx pointer of the SHA1 context + */ +void esp_mfi_sha1_init(esp_mfi_sha_ctx_t ctx); + +/** + * @brief Update SHA1 context + * + * @param ctx pointer of the SHA1 context + * @param msg pointer of the input data + * @param len input data length + */ +void esp_mfi_sha1_update(esp_mfi_sha_ctx_t ctx, const uint8_t *msg, int len); + +/** + * @brief Final SHA1 context + * + * @param digest pointer of output data + * @param ctx pointer of the SHA1 context + */ +void esp_mfi_sha1_final(esp_mfi_sha_ctx_t ctx, uint8_t *digest); + +/** + * @brief Free SHA1 context + * + * @param ctx pointer of the SHA1 context + */ +void esp_mfi_sha1_free(esp_mfi_sha_ctx_t ctx); + +/* + * SHA256 declarations + */ + +#define MFI_SHA256_SIZE 32 + +/** + * @brief Create SHA256 context + * + * @return pointer of the SHA256 context + */ +esp_mfi_sha_ctx_t esp_mfi_sha256_new(void); + +/** + * @brief Init SHA256 context + * + * @param ctx pointer of the SHA256 context + */ +void esp_mfi_sha256_init(esp_mfi_sha_ctx_t ctx); + +/** + * @brief Update SHA256 context + * + * @param ctx pointer of the SHA256 context + * @param msg pointer of input data + * @param len input data length + */ +void esp_mfi_sha256_update(esp_mfi_sha_ctx_t ctx, const uint8_t *input, int len); + +/** + * @brief Final SHA256 context + * + * @param digest pointer of output data + * @param ctx pointer of the SHA256 context + */ +void esp_mfi_sha256_final(esp_mfi_sha_ctx_t ctx, uint8_t *digest); + +/** + * @brief Free SHA256 context + * + * @param ctx pointer of the SHA256 context + */ +void esp_mfi_sha256_free(esp_mfi_sha_ctx_t ctx); + +/* + * SHA512 declarations + */ + +#define MFI_SHA512_SIZE 64 + +/** + * @brief Create SHA512 context + * + * @return pointer of the SHA512 context + */ +esp_mfi_sha_ctx_t esp_mfi_sha512_new(void); + +/** + * @brief Init SHA512 context + * + * @param ctx pointer of the SHA512 context + */ +void esp_mfi_sha512_init(esp_mfi_sha_ctx_t ctx); + +/** + * @brief Update SHA512 context + * + * @param ctx pointer of the SHA512 context + * @param msg pointer of input data + * @param len input data length + */ +void esp_mfi_sha512_update(esp_mfi_sha_ctx_t ctx, const uint8_t *input, int len); + +/** + * @brief Final SHA512 context + * + * @param digest pointer of output data + * @param ctx pointer of the SHA512 context + */ +void esp_mfi_sha512_final(esp_mfi_sha_ctx_t ctx, uint8_t *digest); + +/** + * @brief Free SHA512 context + * + * @param ctx pointer of the SHA512 context + */ +void esp_mfi_sha512_free(esp_mfi_sha_ctx_t ctx); + +#ifdef __cplusplus +} +#endif + +#endif /* ESP_MFI_SHA_H_ */ diff --git a/lib/libesp32_div/ESP32-HomeKit/src/hap.h b/lib/libesp32_div/ESP32-HomeKit/src/hap.h new file mode 100644 index 000000000..fdd80f528 --- /dev/null +++ b/lib/libesp32_div/ESP32-HomeKit/src/hap.h @@ -0,0 +1,1572 @@ +/* + * ESPRESSIF MIT License + * + * Copyright (c) 2020 + * + * Permission is hereby granted for use on ESPRESSIF SYSTEMS products only, in which case, + * it is 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. + * + */ + +#ifndef _HAP_H_ +#define _HAP_H_ + +#include +#include +#include +#include +#ifdef __cplusplus +extern "C" { +#endif + +#define HAP_CHAR_STRING_MAX_LEN 256 +#define HAP_CHAR_STRING_MAX_DEF_LEN 64 + +#define HAP_SUCCESS 0 +#define HAP_FAIL -1 + +typedef enum { + HAP_MFI_AUTH_NONE = 0, + HAP_MFI_AUTH_HW, + HAP_MFI_AUTH_SW +} hap_mfi_auth_type_t; + +/** HomeKit Transports to be enabled */ +typedef enum { + /** Unknown. Default uninitialized value */ + HAP_TRANSPORT_UNKNOWN = 0x00, + /** HAP over Wi-Fi */ + HAP_TRANSPORT_WIFI = 0x01, + /** HAP Over Ethernet (Wi-Fi disabled). + * To enable both Wi-Fi and Ethernet, use (HAP_TRANSPORT_WIFI | HAP_TRANSPORT_ETHERNET) for hap_init() + */ + HAP_TRANSPORT_ETHERNET = 0x02, +} hap_transport_t; + +/** + * HAP characteristic value formats + */ +typedef enum { + /** No Type/Invalid type */ + HAP_CHAR_FORMAT_NONE = 0, + /** Boolean (true or false)*/ + HAP_CHAR_FORMAT_BOOL, + /** Unsigned 8-bit integer */ + HAP_CHAR_FORMAT_UINT8, + /** Unsigned 16-bit integer */ + HAP_CHAR_FORMAT_UINT16, + /** Unsigned 32-bit integer */ + HAP_CHAR_FORMAT_UINT32, + /** Unsigned 64-bit integer */ + HAP_CHAR_FORMAT_UINT64, + /** Signed 32-bit integer */ + HAP_CHAR_FORMAT_INT, + /** Signed 32-bit floating point number */ + HAP_CHAR_FORMAT_FLOAT, + /** Unicode string */ + HAP_CHAR_FORMAT_STRING, + /** Base64 encoded set of one or more TLV8s */ + HAP_CHAR_FORMAT_TLV8, + /** base64 encoded data blob */ + HAP_CHAR_FORMAT_DATA, +} hap_char_format_t; + +/** Data value */ +typedef struct { + /** Pointer to an allocated buffer holding the data. This should remain valid + * throughout the lifetime of the characteristic. + */ + uint8_t *buf; + /** Length of the data */ + uint32_t buflen; +} hap_data_val_t; + +/** TLV8 value (Same as \ref hap_data_val_t) */ +typedef hap_data_val_t hap_tlv8_val_t; + +/** HAP Value */ +typedef union { + /** Boolean */ + bool b; + /** Unsigned integer (uint8, uint16, uint32) */ + uint32_t u; + /** Signed integer */ + int i; + /** 64 bit Unsigned integer */ + uint64_t i64; + /** Floating point number */ + float f; + /** Pointer to string */ + char *s; + /** Structure for Data */ + hap_data_val_t d; + /** Structure for TLV8 */ + hap_tlv8_val_t t; +} hap_val_t; + +/** Information about the Provisioned Network to which the accessory will connect */ +typedef struct { + /** SSID for the network */ + uint8_t ssid[64]; + /** Length of the SSID */ + size_t ssid_len; + /** Password for the network. Can be NULL for Open networks */ + uint8_t password[64]; + /** Length of the Password. Can be 0 for Open networks */ + size_t password_len; +} hap_provisioned_nw_t; + +/** + * HAP characteristics unit types + */ +#define HAP_CHAR_UNIT_CELSIUS "celsius" +#define HAP_CHAR_UNIT_PERCENTAGE "percentage" +#define HAP_CHAR_UNIT_ARCDEGREES "arcdegrees" +#define HAP_CHAR_UNIT_LUX "lux" +#define HAP_CHAR_UNIT_SECONDS "seconds" + +/** HAP Characteristic properties/permissions */ +/** Characteristic supports Paired Read */ +#define HAP_CHAR_PERM_PR (1 << 0) +/** Characteristic supports Paired Write */ +#define HAP_CHAR_PERM_PW (1 << 1) +/** Characteristic supports Event Notifications */ +#define HAP_CHAR_PERM_EV (1 << 2) +/** Characteristic supports Additional Authorization Data */ +#define HAP_CHAR_PERM_AA (1 << 3) +/** Characteristic supports Timed Writes */ +#define HAP_CHAR_PERM_TW (1 << 4) +/** Characteristic is hidden from the user */ +#define HAP_CHAR_PERM_HD (1 << 5) +/** Characterictic is of special read only type. + * Valid for characteristics like "Programmable Switch Event" wherein the value + * needs to be reported as NULL for a read, even when it is a uint8. Actual value + * is reported only using event notifications. + */ +#define HAP_CHAR_PERM_SPECIAL_READ (1 << 6) + +/** HAP object handle */ +typedef size_t hap_handle_t; + +/** HAP Characteristic handle */ +typedef hap_handle_t hap_char_t; +/** HAP Service handle */ +typedef hap_handle_t hap_serv_t; +/** HAP Accessory handle */ +typedef hap_handle_t hap_acc_t; + +/** HAP Status codes as per the HAP Specifications */ +typedef enum { + /** This specifies a success for the request. */ + HAP_STATUS_SUCCESS = 0, + /** Request denied due to insufficient privileges. */ + HAP_STATUS_NO_PRIVILEGE = -70401, + /** Unable to communicate with requested service. */ + HAP_STATUS_COMM_ERR = -70402, + /** Resource is busy, try again. */ + HAP_STATUS_RES_BUSY = -70403, + /** Cannot write to read only characteristic. */ + HAP_STATUS_WR_ON_RDONLY = -70404, + /** Cannot read from a write only characteristic. */ + HAP_STATUS_RD_ON_WRONLY = -70405, + /** Notification is not supported for characteristic */ + HAP_STATUS_NO_NOTIF = -70406, + /** Out of resources to process request. */ + HAP_STATUS_OO_RES = -70407, + /** Operation timed out. */ + HAP_STATUS_TIMEOUT = -70408, + /** Resource does not exist. */ + HAP_STATUS_RES_ABSENT = -70409, + /** Accessory received an invalid value in a write request. */ + HAP_STATUS_VAL_INVALID = -70410, + /** Insufficient Authorization. */ + HAP_STATUS_INSUFFICIENT_AUTH = -70411, +} hap_status_t; + +typedef enum { + HAP_CID_NONE = 0, + HAP_CID_OTHER, + HAP_CID_BRIDGE, + HAP_CID_FAN, + HAP_CID_GARAGE_DOOR_OPENER, + HAP_CID_LIGHTING, + HAP_CID_LOCK, + HAP_CID_OUTLET, + HAP_CID_SWITCH, + HAP_CID_THERMOSTAT, + HAP_CID_SENSOR, + HAP_CID_SECURITY_SYSTEM, + HAP_CID_DOOR, + HAP_CID_WINDOW, + HAP_CID_WINDOW_COVERING, + HAP_CID_PROGRAMMABLE_SWITCH, + HAP_CID_RESERVED, + HAP_CID_IP_CAMERA, + HAP_CID_VIDEO_DOORBELL, + HAP_CID_AIR_PURIFIER, + HAP_CID_HEATER, + HAP_CID_AIR_CONDITIONER, + HAP_CID_HUMIDIFIER, + HAP_CID_DEHUMIDIFIER, + HAP_CID_MAX, +} hap_cid_t; + +/** Prototype for Identify routine for the accessory + * + * @param[in] acc Handle of the accessory object + */ +typedef int (*hap_identify_routine_t) (hap_acc_t *acc); + +/** HAP Accessory configuration */ +typedef struct { + /** Name (Mandatory) */ + char *name; + /** Model (Mandatory) */ + char *model; + /** Manufacturer (Mandatory) */ + char *manufacturer; + /** Serial Number (Mandatory) */ + char *serial_num; + /** Firmware Revision number in format x[.y[.z]] (Mandatory) */ + char *fw_rev; + /** Hardware revision number in format x[.y[.z]] (Optional. Can be NULL )*/ + char *hw_rev; + /** HAP Protocol version supported by the accessory. Should be set to "1.1" + * @note The value set here will currently be ignored and assumed to be 1.1 + * as it is the only protocol version currently supported. + * This is valid only for the Primary accessory. + */ + char *pv; + /** Category Identifier for the Accessory. This is valid only for the + * primary accessory + */ + hap_cid_t cid; + /** Identify routine for the accessory (Mandatory) */ + hap_identify_routine_t identify_routine; +} hap_acc_cfg_t; + +/** HomeKit Debug prints level + */ +typedef enum { + /** Basic information indicating what's happening in the HomeKit core */ + HAP_DEBUG_LEVEL_INFO = 0, + /** Warnings for incidents that can affect behavior, but not necessarily cause a failure*/ + HAP_DEBUG_LEVEL_WARN, + /** Errors which will affect the working, and may even halt the process */ + HAP_DEBUG_LEVEL_ERR, + /** Asserts for failures which will definitely cause system to halt */ + HAP_DEBUG_LEVEL_ASSERT +} hap_debug_level_t; + +/** + * @brief Set the HomeKit Debug prints level. + * + * This indicates the maximum level for which the debug messages + * will be printed. Default value is \ref HAP_DEBUG_LEVEL_INFO which means + * that all information, warnings, errors and asserts will be printed, as + * this is the lowest level. You can change it to any suitable higher level + * to reduce the prints. For Eg. Setting this to HAP_DEBUG_LEVEL_WARN will + * print all warnings, errors and asserts, but not the basic information. + * + * @param[in] level Maximum debug print level as per \ref hap_debug_level_t + */ +void hap_set_debug_level(hap_debug_level_t level); + +/** + * + * @brief Get the HAP SDK Version from the hap core + * + * @return Pointer to a NULL terminated Version string (Eg. 2.0.r1-0136161) + */ +const char *hap_get_version(); + +/** Unique Paramaters for HomeKit */ +typedef enum { + /** Nothing unique. + * Application code should ensure uniqueness of name and ssid. + * HAP Core will not change anything. + */ + UNIQUE_NONE = 0, + /** Unique SSID (default configuration). + * 3 bytes of MAC will be added to accessory name to create unique WAC SSID (Eg. Name-xxyyzz) */ + UNIQUE_SSID, + /** Unique Name. + * Name will be changed by adding 3 bytes of MAC to original name. + * Thi swill automatically make the SSID unique as the accessory name will be used as SSID. + */ + UNIQUE_NAME, +} hap_unique_param_t; + +/** HomeKit Configuration. + * Please do not change unless you understand the purpose of these */ +typedef struct { + /** Internal HomeKit Task's stack size */ + uint32_t task_stack_size; + /** Internal HomeKit Task's priority */ + uint8_t task_priority; + /** Maximum characteristics to which event notifications can be sent simultaneously. + * Default value is enough for standalone accessories. Change may be required only + * for bridges. + */ + uint8_t max_event_notif_chars; + /** Indicates what paramaters will be made unique by the HAP Core */ + hap_unique_param_t unique_param; + /** Timeout (in seconds) after which a socket data receive call will return for a pair verified + * socket, in case the call blocks. This has been added to avoid the webserver getting stalled on a read, + * especially in case wherein some garbage data is received on a pair verified connection. + */ + uint8_t recv_timeout; + /** Timeout (in seconds) after which a socket data send call will return for a pair verified + * socket, in case the call blocks. This has been added to avoid the webserver getting stalled on a write. + */ + uint8_t send_timeout; + /** Max length of the buffer to be used for handling SW Token Requests. The Default value has been kept + * as 1200 to help pass HCA Tests. This can be changed to 512 for practical purposes as the actual Apple + * tokens never really need more than that. + */ + size_t sw_token_max_len; + /** By default, config number (c#) incremenents on addition/removal of every bridged accessory after + * hap_start(). Setting this flag to true will disable this. Use hap_update_config_number() + * to increment c#. Note thar c# will still increment on a firmware upgrade though. + */ + bool disable_config_num_update; +} hap_cfg_t; + +/** Get HomeKit Configuration + * + * Gets the configuration that will be used by the HomeKit core. + * + * @param[out] cfg Pointer to an allocated \ref hap_cfg_t structure which will be populated + * with the configuration information. + * + * @return HAP_SUCCESS on success + * @return HAP_FAIL on error + */ +int hap_get_config(hap_cfg_t *cfg); + +/** Set HomeKit Configuration + * + * This sets the HomeKit configuration. Please use hap_get_config() to get the old + * configuration first, before modifying any values. Eg. + * + * @code + * hap_cfg_t hap_cfg; + * hap_get_config(&hap_cfg); + * hap_cfg.unique_param = UNIQUE_NAME; + * hap_set_config(&hap_cfg); + * @endcode + * + * @note This should be called before hap_init(). + * + * @param[in] cfg Pointer to an allocated \ref hap_cfg_t structure which has the new values + * to set. + * + * @return HAP_SUCCESS on success + * @return HAP_FAIL on error + */ +int hap_set_config(const hap_cfg_t *cfg); + +/* Update config number (c#) + * + * This increments the config number (c#) by 1 + * + * @return HAP_SUCCESS on success + * @return HAP_FAIL on error + */ +int hap_update_config_number(); + +/** + * @brief Initialize HAP Framework + * + * This internally initializes the MFi auth chip, TCP-IP stack, HomeKit Key Store, + * HomeKit database, Wi-Fi and mDNS. + * + * @return HAP_SUCCESS on success + * @return others on error + */ +int hap_init(hap_transport_t transport); + +/** + * @brief De-initialize HAP Framework. + * + * @note This currently does not do anything + * + * @return HAP_SUCCESS on success + * @return others on error + */ +int hap_deinit(); + +/** + * @brief Start the HAP framework + * + * This starts the webserver and also initializes WAC or HomeKit services + * as per the state of the accessory. + * + * @return HAP_SUCCESS on success + * @return others on error + */ +int hap_start(void); + +/** + * @brief Stop HAP framework and free all relevant resources + * + * @note This currently does not do anything + * + * @return HAP_SUCCESS on success + * @return others on error + */ +int hap_stop(void); + +/** + * @brief Create a HAP accessory object + * + * @param[in] acc_cfg Pointer to the accessory configuration \ref hap_acc_cfg_t + * + * @return Handle for the accessory object pre-populated with + * the Accessory Information Service (and Protocol Information Service + * for the first accessory created) + * + * @return NULL on error + */ +hap_acc_t *hap_acc_create(hap_acc_cfg_t *acc_cfg); + +/** + * @brief Add Accessory flags to the Accessory Info service + * + * This adds the optional Accessory Information Flag to the given accessory, + * with the value set to the one specified. Typically, the flags will be + * initialised with a value of 1, meaning that additional manufacturer specific + * setup is required. Once the setup is done, the flags should be reset to 0 + * using hap_acc_update_accessory_flags() + * + * @note Use of these flags requires explicit approval from Apple. + * + * @param[in] ha HAP Accessory object handle + * @param[in] flags Initial value of flags. Check the specs for valid values + * + * @return HAP_SUCCESS on success + * @return HAP_FAIL on failure + */ +int hap_acc_add_accessory_flags(hap_acc_t *ha, uint32_t flags); + +/** + * @brief Update the Accessory flags + * + * This updates the Accessory flags characteristic of the Accessory Info service + * of the given accessory, if it has been added using hap_acc_add_accessory_flags(). + * + * @param[in] ha HAP Accessory object handle + * @param[in] flags New value of flags. Check the specs for valid values + * + * @return HAP_SUCCESS on success + * @return HAP_FAIL on failure + */ +int hap_acc_update_accessory_flags(hap_acc_t *ha, uint32_t flags); + +/** + * @brief Add Product data + * + * As per HAP specs R15, this is the 8 byte product data assigned to the Product Plan. + * + * @param[in] ha HAP Accessory object handle + * @param[in] product_data Pointer to the product data value buffer + * @param[in] data_size Size of the buffer (should be 8 as per HAP Spec R15) + * + * @return HAP_SUCCESS on success + * @return HAP_FAIL on failure + */ +int hap_acc_add_product_data(hap_acc_t *ha, uint8_t *product_data, size_t data_size); + +/** + * @brief Add accessory to the HAP Object database + * + * @param[in] ha HAP Accessory object handle + */ +void hap_add_accessory(hap_acc_t *ha); + +/** + * @brief Add a bridged accessory to the HAP Object database + * + * This adds a bridged accessory to the Homekit Object database and assigns + * it the given AID. HomeKit requires that each accessory gets assigned a unique aid. + * To ensure this, a helper API hap_get_unique_aid() has been provided. This API + * requires some unique identifier of the accessory, say mac address, serial number, etc. + * + * Example: hap_add_bridged_accessory(ha, hap_get_unique_aid(mac_addr)); + * + * @param[in] aid The AID desired for the bridged accessory. If a 0 is passed, the + * next available AID will be assigned. However, this should be used only for + * evaluation, not production. + * + * @param[in] ha HAP Accessory object handle + */ +void hap_add_bridged_accessory(hap_acc_t *ha, int aid); + +/** + * @brief Remove a bridged accessory from the HAP Object database + * + * @param[in] ha HAP Accessory object handle + */ +void hap_remove_bridged_accessory(hap_acc_t *ha); + +/** + * @brief Delete HAP Accessory Object + * + * @note Primary accessory cannot be deleted + * + * @param[in] ha HAP Accessory object handle + * + */ +void hap_acc_delete(hap_acc_t *ha); + +/** + * @brief Delete all accessories + */ +void hap_delete_all_accessories(void); + +/** + * Get unique AID for the given identifier + * + * This API can be used to ensure that the same AID gets assigned to an accessory + * every time, even across reboots and irrespective of when it is added to the + * HomeKit database. It requires a unique identifier of the accessory, say a + * mac addtess, serial number, etc. If it is a new accessory, a new AID gets + * assigned and the id:aid combination gets stored in NVS (Non Volatile Storage). + * If the accessory was already added some time later, the original AID is fetched + * from the NVS and returned. This API should be used as the "aid" argument for + * hap_add_bridged_accessory() + * + * @param[in] id Unique identifier for the accessory + * + * @return Unique AID for the accessory + * @return -1 on error (NULL id) + */ +int hap_get_unique_aid(const char *id); + +/** + * @brief Get Accessory using AID + * + * @param[in] aid Accessory ID of the required accessory + * + * @return Handle for the accessory with given aid + * @return NULL if accessory not found + */ +hap_acc_t *hap_acc_get_by_aid(int32_t aid); + +/** + * @brief Get first accessory in the database + * + * @return Handle for the first accessory + */ +hap_acc_t *hap_get_first_acc(); + +/** + * @brief Get next accessory in the database + * + * @param[in] ha Current HAP Accessory object handle + * + * @return Pointer to the next accessory + * @return NULL if the current accessory is the last + */ +hap_acc_t *hap_acc_get_next(hap_acc_t *ha); + +/** + * @brief Get Service using IID + * + * @param[in] ha HAP Accessory object handle in which the service should be searched + * @param[in] iid Instance ID of the required service + * + * @return Handle for the service with given iid + * @return NULL if service not found + */ +hap_serv_t *hap_acc_get_serv_by_iid(hap_acc_t *ha, int32_t iid); + +/** + * @brief Get Service using Type UUID + * + * @param[in] ha HAP Accessory object handle in which the service should be searched + * @param[in] type_uuid UUID of the required service + * + * @return Handle for the service with given type_uuid + * @return NULL if service not found + */ +hap_serv_t *hap_acc_get_serv_by_uuid(hap_acc_t *ha, const char *type_uuid); + +/** + * @brief Get characteristic using IID + * + * @param[in] ha HAP Accessory object handle in which the characteristic should be searched + * @param[in] iid Instance ID of the required characteristic + * + * @return Handle for the characteristic with given iid + * @return NULL if characteristic not found + */ +hap_char_t *hap_acc_get_char_by_iid(hap_acc_t *ha, int32_t iid); + +/** + * @brief Get first service in a given accessory object + * + * This is useful for iterating over all services of an accessory. + * The subsequent services of the accessory can be iterated by using + * hap_serv_get_next(). + * + * @param[in] ha HAP Accessory object handle + * + * @return Handle for the first service in the accessory object + */ +hap_serv_t *hap_acc_get_first_serv(hap_acc_t *ha); + +/** + * @brief Create a Boolean Characteristic Object + * + * @param[in] type_uuid UUID for the characteristic as per the HAP Specs + * @param[in] perms Logically OR of the various permissions supported by the characteristic + * @param[in] val Initial value of the characteristic + * + * @return Handle for the characteristic object created + * @return NULL on error + */ +hap_char_t *hap_char_bool_create(char *type_uuid, uint16_t perms, bool val); + +/** + * @brief Create an 8-bit unsigned integer Characteristic Object + * + * @param[in] type_uuid UUID for the characteristic as per the HAP Specs + * @param[in] perms Logically OR of the various permissions supported by the characteristic + * @param[in] val Initial value of the characteristic + * + * @return Handle for the characteristic object created + * @return NULL on error + */ +hap_char_t *hap_char_uint8_create(char *type_uuid, uint16_t perms, uint8_t val); + +/** + * @brief Create a 16-bit unsigned integer Characteristic Object + * + * @param[in] type_uuid UUID for the characteristic as per the HAP Specs + * @param[in] perms Logically OR of the various permissions supported by the characteristic + * @param[in] val Initial value of the characteristic + * + * @return Handle for the characteristic object created + * @return NULL on error + */ +hap_char_t *hap_char_uint16_create(char *type_uuid, uint16_t perms, uint16_t val); + +/** + * @brief Create a 32-bit unsigned integer Characteristic Object + * + * @param[in] type_uuid UUID for the characteristic as per the HAP Specs + * @param[in] perms Logically OR of the various permissions supported by the characteristic + * @param[in] val Initial value of the characteristic + * + * @return Handle for the characteristic object created + * @return NULL on error + */ +hap_char_t *hap_char_uint32_create(char *type_uuid, uint16_t perms, uint32_t val); + +/** + * @brief Create a 64-bit unsigned integer Characteristic Object + * + * @param[in] type_uuid UUID for the characteristic as per the HAP Specs + * @param[in] perms Logically OR of the various permissions supported by the characteristic + * @param[in] val Initial value of the characteristic + * + * @return Handle for the characteristic object created + * @return NULL on error + */ +hap_char_t *hap_char_uint64_create(char *type_uuid, uint16_t perms, uint64_t val); + +/** + * @brief Create a 32-bit signed integer Characteristic Object + * + * @param[in] type_uuid UUID for the characteristic as per the HAP Specs + * @param[in] perms Logically OR of the various permissions supported by the characteristic + * @param[in] val Initial value of the characteristic + * + * @return Handle for the characteristic object created + * @return NULL on error + */ +hap_char_t *hap_char_int_create(char *type_uuid, uint16_t perms, int val); + +/** + * @brief Create a Floating point Characteristic Object + * + * @param[in] type_uuid UUID for the characteristic as per the HAP Specs + * @param[in] perms Logically OR of the various permissions supported by the characteristic + * @param[in] val Initial value of the characteristic + * + * @return Handle for the characteristic object created + * @return NULL on error + */ +hap_char_t *hap_char_float_create(char *type_uuid, uint16_t perms, float val); + +/** + * @brief Create a String Characteristic Object + * + * @param[in] type_uuid UUID for the characteristic as per the HAP Specs + * @param[in] perms Logically OR of the various permissions supported by the characteristic + * @param[in] val Initial value of the characteristic + * + * @return Handle for the characteristic object created + * @return NULL on error + */ +hap_char_t *hap_char_string_create(char *type_uuid, uint16_t perms, char *val); + +/** + * @brief Create a Data Characteristic Object + * + * @param[in] type_uuid UUID for the characteristic as per the HAP Specs + * @param[in] perms Logically OR of the various permissions supported by the characteristic + * @param[in] val Pointer to initial value of the characteristic + * + * @return Handle for the characteristic object created + * @return NULL on error + */ +hap_char_t *hap_char_data_create(char *type_uuid, uint16_t perms, hap_data_val_t *val); + +/** + * @brief Create a TLV8 Characteristic Object + * + * @param[in] type_uuid UUID for the characteristic as per the HAP Specs + * @param[in] perms Logically OR of the various permissions supported by the characteristic + * @param[in] val Pointer to initial value of the characteristic + * + * @return Handle for the characteristic object created + * @return NULL on error + */ +hap_char_t *hap_char_tlv8_create(char *type_uuid, uint16_t perms, hap_tlv8_val_t *val); + +/** + * @brief Delete a characteristic object + * + * @param[in] hc HAP Characteristic Object handle + */ +void hap_char_delete(hap_char_t *hc); + +/** + * @brief Create a HAP Service Object + * + * @param[in] type_uuid UUID for the service as per the HAP Specs + * + * @return Handle for the service object created + * @return NULL on error + */ +hap_serv_t *hap_serv_create(char *type_uuid); + +/** + * @brief Delete a service object + * + * @param[in] hs HAP Service Object handle + */ +void hap_serv_delete(hap_serv_t *hs); + +/** + * @brief Get the AID for the given accessory + * + * @param[in] ha HAP Accessory Object handle + * + * @return aid for the accessory + */ +uint32_t hap_acc_get_aid(hap_acc_t *ha); + +/** + * @brief Get Characteristic using Type UUID + * + * @param[in] hs HAP Service object handle in which the characteristic should be searched + * @param[in] type_uuid UUID of the required characteristic + * + * @return Handle for the characteristic with given type_uuid + * @return NULL if characteristic not found + */ +hap_char_t *hap_serv_get_char_by_uuid(hap_serv_t *hs, const char *type_uuid); + +/** + * @brief Get parent Accessory for given Service + * + * @param[in] hs HAP Service object handle + * + * @return Handle for the parent accessory + * @return NULL if the service is not added in any accessory + */ +hap_acc_t *hap_serv_get_parent(hap_serv_t *hs); + +/** + * @brief Get the next service in a given accessory object + * + * This is useful for iterating over all services of an accessory. + * + * @param[in] Current service object handle + * + * @return Handle for next service in the accessory object + * @return NULL if the current service was the last one in the accessory + */ +hap_serv_t *hap_serv_get_next(hap_serv_t *hs); + +/** + * @brief Get first characteristic in a given service object + * + * This is useful for iterating over all characteristics of a service. + * The subsequent characteristics of the service can be + * iterated by using hap_char_get_next(). + * + * @param[in] hs HAP Service object handle + * + * @return Handle for the first chatracteristic in the service object + */ +hap_char_t *hap_serv_get_first_char(hap_serv_t *hs); + +/** + * @brief Get the IID for the given characteristic + * + * @param[in] hc HAP Characteristic Object handle + * + * @return iid for the characteristic + */ +uint32_t hap_char_get_iid(hap_char_t *hc); + +/** + * @brief Get the type UUID for the given characteristic + * + * @param[in] hc HAP Characteristic Object handle + * + * @return Type UUID for the characteristic + */ +const char * hap_char_get_type_uuid(hap_char_t *hc); + + +/** + * @brief Get the Permissions for the given characteristic + * + * @param[in] hc HAP Characteristic Object handle + * + * @return The permissions for the characteristics, the same as the ones passed while creating it. + * It will be a logically OR of the various permissions supported by the characteristic. + */ +uint16_t hap_char_get_perm(hap_char_t *hc); + + +/** + * @brief Get the format for the given characteristic + * + * @param[in] hc HAP Characteristic Object handle + * + * @return Format of the characteristic value + */ +hap_char_format_t hap_char_get_format(hap_char_t *hc); + +/** + * @brief Get the IID for the given service + * + * @param[in] hs HAP Service Object handle + * + * @return iid for the service + */ +uint32_t hap_serv_get_iid(hap_serv_t *hs); + +/** + * @brief Get the type UUID for the given service + * + * @param[in] hs HAP Service Object handle + * + * @return Type UUID for the service + */ +char *hap_serv_get_type_uuid(hap_serv_t *hs); +/** + * @brief Get parent Service for given Characteristic + * + * @param[in] hc HAP Characteristic object handle + * + * @return Handle for the parent service + * @return NULL if the characteristic is not added in any service + */ +hap_serv_t *hap_char_get_parent(hap_char_t *hc); + +/** + * @brief Get the next characteristic in a given service object + * + * This is useful for iterating over all characteristics of a service. + * + * @param[in] Current characteristic object handle + * + * @return Handle for next characteristic in the service object + * @return NULL if the current characteristic was the last one in the service + */ +hap_char_t *hap_char_get_next(hap_char_t *hc); + +/** + * @brief Add Integer characteristic constraints + * + * @param[in] hc HAP Characteristic Object handle + * @param[in] min Minimum Value + * @param[in] max Maximum Value + * @param[in] step Step Value + */ +void hap_char_int_set_constraints(hap_char_t *hc, int min, int max, int step); + +/** + * @brief Add Integer characteristic constraints + * + * @param[in] hc HAP Characteristic Object handle + * @param[in] min Minimum Value + * @param[in] max Maximum Value + * @param[in] step Step Value + */ +void hap_char_float_set_constraints(hap_char_t *hc, float min, float max, float step); + +/** + * @brief Add String characteristic constraints + * + * @param[in] hc HAP Characteristic Object handle + * @param[in] maxlen Maximum Length of the string (default: 64, max: 256) + */ +void hap_char_string_set_maxlen(hap_char_t *hc, int maxlen); + +/** + * @brief Add Characteristic Description + * + * @param[in] hc HAP Characteristic Object handle + * @param[in] description Manufacturer defined String description for the characteristic + */ +void hap_char_add_description(hap_char_t *hc, const char *description); + +/** + * @brief Add Characteristic Unit + * + * @param[in] hc HAP Characteristic Object handle + * @param[in] unit Unit for the characteristic. Please see specs for valid strings. + */ +void hap_char_add_unit(hap_char_t *hc, const char *unit); + +/** + * @brief Add Valid Values for Characteristic + * + * Using this API will just add the valid-values metadata for a characteristic + * + * @param[in] hc HAP Characteristic Object handle + * @param[in] valid_vals Pointer to an array of valid values + * @param[in] valid_val_cnt Number of entries in the array + */ +void hap_char_add_valid_vals(hap_char_t *hc, const uint8_t *valid_vals, size_t valid_val_cnt); + +/** + * @brief Add Valid Values Range for Characteristic + * + * Using this API will just add the valid-values-range metadata for a characteristic + * + * @param[in] hc HAP Characteristic Object handle + * @param[in] start_val Start value of the range + * @param[in] end_val End value of the range + */ +void hap_char_add_valid_vals_range(hap_char_t *hc, uint8_t start_val, uint8_t end_val); +/** + * @brief Set IID for a given characteristic + * + * HomeKit specifications require that the IID for a given characteristic should remain the same, + * even after a firmware upgrade. Since the HomeKit core assigns the IIDs internally, + * it is possible that a different IID is getting assigned because of removal of + * some old service/characteristic or addition of a newer one in between. In such a case, + * in order to maintain the same IID, this API can be used. + * + * @note This must be used only if actually required, and that too after adding all services/ + * characteristics to an accessory, but before hap_start(). + * + * @param[in] hc HAP Characteristic Object Handle + * @param[in] iid Desired IID + */ +void hap_char_set_iid(hap_char_t *hc, int32_t iid); + +/** + * @brief Add a characteristic to a service + * + * @param[in] hs HAP service object handle + * @param[in] hc HAP characteristic object handle + * + * @return 0 on success + * @return other on error + */ +int hap_serv_add_char(hap_serv_t *hs, hap_char_t *hc); + +/** + * @brief HAP add a service to an accessory + * + * @param[in] ha HAP Accessory object handle + * @param[in] hs HAP Service object handle + * + * @return 0 on success + * @return other on error + */ +int hap_acc_add_serv(hap_acc_t *ha, hap_serv_t *hs); + +/** + * @brief Update characteristic value + * + * This should be called within service read/write callbacks to update the + * value of characteristic maintained by the HAP Core. This can also be called + * from some other thread, for accessories like sensors that periodically + * monitor some paramters. + * + * @param[in] hc HAP characteristic object handle + * @param[in] val Pointer to new value + * + * @return 0 on success + * @return other on error + */ +int hap_char_update_val(hap_char_t *hc, hap_val_t *val); + +/** + * @brief Get the current value of characteristic + * + * @param[in] hc HAP characteristic object handle + * + * @return Pointer to the current value + */ +const hap_val_t *hap_char_get_val(hap_char_t *hc); + +/** Authorization Data received in a write reqest + */ +typedef struct { + /** Pointer to the data. Will be NULL if no auth data was present */ + uint8_t *data; + /** Length of the data. Will be 0 if no auth data was present */ + int len; +} hap_auth_data_t; + +/** Write data for a characteristics received over HAP + */ +typedef struct { + /** Pointer to the characteristic object */ + hap_char_t *hc; + /** Value received in the write request. + * Appropriate value in the \ref hap_val_t union will be set as per the format. + */ + hap_val_t val; + /** Authorization data \ref hap_auth_data_t id any, received in the write request. + * It is the application's responsibility to handle and validate this data and + * report the status accordingly. + */ + hap_auth_data_t auth_data; + /** Indicates if the received request was a remote write + */ + bool remote; + /** This is an output parameter, which should be set in the service write + * routine as per the status of the write. + */ + hap_status_t *status; +} hap_write_data_t; + +/** Read data for a characteristic + */ +typedef struct { + /** Pointer to the characteristic object */ + hap_char_t *hc; + /** This is an output parameter, which should be set in the service read + * routine as per the status of the read + */ + hap_status_t *status; +} hap_read_data_t; + + +/** Service Write Function Prototype + * + * A function with this prototype must be registered with the HAP framework to handle + * writes for the characteristics in the given service + * + * @note For writes, an array is sent instead of individual writes to avoid cases wherein + * writes to multiple properties of a single accessory can cause unexpected behavior. + * Eg. For a light which is off, a write could ask it to be turned on at 50% brightness, + * with blue color. If 3 writes are issued for this, the light could first turn on to + * 100% with white color, then dim down to 50% and then change color. A single write will + * ensure that the hardware control takes care of all these at the same time. + * + * @param[in] write_data Array of characteristic write objects of type \ref hap_write_data_t + * which has relevant information like the characteristic object handle, new value received, etc. + * @param[in] count Number of entries in the write_data array. + * @param[in] serv_priv The private data for the service set using hap_serv_set_priv() + * @param[in] write_priv Can be used with hap_is_req_admin() + * + * @return HAP_SUCCESS on success + * @return HAP_FAIL if an error is encountered even for a single characteristic. Actual error + * value must be reported in the status under \ref hap_write_data_t. + */ +typedef int (*hap_serv_write_t) (hap_write_data_t write_data[], int count, + void *serv_priv, void *write_priv); + +/** Service Read Function Prototype + * + * A function with this prototype must be registered with the HAP framework to handle + * reads for the characteristics in the given service. The new value must be set + * by invoking hap_char_update_val(). + * + * @param[in] hc HAP Characteristic Object Handle. + * @param[out] status_code Status of the read, to be populated by the callback with + * values from \ref hap_status_t. + * @param[in] serv_priv The private data for the service set using hap_serv_set_priv() + * @param[in] read_priv Can be used with hap_is_req_admin() + * + * @return HAP_SUCCESS on success + * @return HAP_FAIL if an error is encountered while reading. Actual error + * value must be reported in the status_code + */ +typedef int (*hap_serv_read_t) (hap_char_t *hc, hap_status_t *status_code, + void *serv_priv, void *read_priv); + +/** Service Bulk Read Function Prototype + * + * A function with this prototype can be registered with the HAP framework to handle + * bulk reads for the characteristics in the given service. The new values must be set + * by invoking hap_char_update_val() for each characteristic. + * + * @note This should be used only under special circumstances for cases like + * bridges, wherein fetching individual values from bridged accessories could + * be time consuming. If this is used, it will override the handler of + * type \ref hap_serv_read_t registered for the same service. + * + * @param[in] read_data Array of characteristic write objects of type \ref hap_read_data_t + * which has characteristic object handle and read status pointer. + * @param[in] count Number of entries in the read_data array. + * @param[in] serv_priv The private data for the service set using hap_serv_set_priv() + * @param[in] read_priv Can be used with hap_is_req_admin() + * + * @return HAP_SUCCESS on success + * @return HAP_FAIL if an error is encountered even for a single characteristic. + * Actual error value must be reported in the status under \ref hap_read_data_t. + */ +typedef int (*hap_serv_bulk_read_t) (hap_read_data_t read_data[], int count, + void *serv_priv, void *read_priv); + +/** + * @brief Register Service Write callback + * + * @param[in] hs HAP Service Object Handle + * @param[in] write Callback of type \ref hap_serv_write_t + */ +void hap_serv_set_write_cb(hap_serv_t *hs, hap_serv_write_t write); + +/** + * @brief Register Service Read callback + * + * @param[in] hs HAP Service Object Handle + * @param[in] read Callback of type \ref hap_serv_read_t + */ +void hap_serv_set_read_cb(hap_serv_t *hs, hap_serv_read_t read); + +/** + * @brief Register Service Bulk read callback + * + * @note This should be used only under special circumstances for cases like + * bridges, wherein fetching individual values from bridged accessories could + * be time consuming. If this is used, the callback registered using + * @ref hap_serv_set_read_cb() will be overriden. + * + * @param[in] hs HAP Service Object Handle + * @param[in] read Callback of type \ref hap_serv_bulk_read_t + */ +void hap_serv_set_bulk_read_cb(hap_serv_t *hs, hap_serv_bulk_read_t read); + +/** + * @brief Set service private data + * + * This will be available in the read/write callbacks + * + * @param[in] hs HAP Service Object Handle + * @param[in] priv Private data for the service + */ +void hap_serv_set_priv(hap_serv_t *hs, void *priv); + +/** + * @brief Get Service private + * + * This will get the private data associated with the service, which + * was set using hap_serv_set_priv(). + * + * @param[in] hs HAP Service Object Handle + * + * @return Pointer to the private data (can be NULL) + */ +void *hap_serv_get_priv(hap_serv_t *hs); + +/** + * @brief Mark service as primary + * + * @param[in] hs HAP Service Object Handle + */ +void hap_serv_mark_primary(hap_serv_t *hs); + +/** + * @brief Mark service as hidden + * + * @param[in] hs HAP Service Object Handle + */ +void hap_serv_mark_hidden(hap_serv_t *hs); + +/** + * @brief Link a HomeKit service to other service + * + * @param[in] hs HAP Service Object Handle + * @param[in] linked_serv HAP Service Object Handle of the service to be linked + * + * @return HAP_SUCCESS on success + * @return HAP_FAIL on failure + */ +int hap_serv_link_serv(hap_serv_t *hs, hap_serv_t *linked_serv); + +/** + * @brief Set IID for a given sService + * + * HomeKit specifications require that the IID for a given service should remain the same, + * even after a firmware upgrade. Since the HomeKit core assigns the IIDs internally, + * it is possible that a different IID is getting assigned because of removal of + * some old service/characteristic or addition of a newer one in between. In such a case, + * in order to maintain the same IID, this API can be used. + * + * @note This must be used only if actually required, and that too after adding all services/ + * characteristics to a service, but before hap_start(). + * + * @param[in] hs HAP Service Object Handle + * @param[in] iid Desired IID + */ +void hap_serv_set_iid(hap_serv_t *hs, int32_t iid); + +/** HomeKit Setup Information */ +typedef struct { + /** SRP Salt */ + uint8_t salt[16]; + /** SRP Verifier */ + uint8_t verifier[384]; +} hap_setup_info_t; + +/** + * @brief Set the Setup info for HomeKit Pairing + * + * HomeKit Pairing/Accessory Setup uses a Setup Code (Also called Pairing PIN). + * However, the specs recommend that, instead of storing the PIN on the accessory, + * the salt and verifier for the PIN should be stored. + * + * This API should be used to provide this information. + * + * @param[in] setup_info Pointer to the Setup Information structure which has + * the Salt and Verifier. + * + * @return HAP_SUCCESS on success + * @return HAP_FAIL on failure (like setup_info being NULL); + */ +int hap_set_setup_info(const hap_setup_info_t *setup_info); + +/** + * @brief Set the setup code (i.e. pairing pin) + * + * @note Ideally, the PIN should not be present in the firmware. Instead, + * the salt and verifier should be stored on the accessory and provided using + * hap_set_setup_info(). This API should be used only for testing purposes. + * + * Using this API overrides the setup information provided by hap_set_setup_info(). + * + * @param[in] setup_code NULL terminated Setup code of the format xxx-xx-xxx where each + * x is a number + */ +void hap_set_setup_code(const char *setup_code); + +/** + * @brief Set the setup ID + * + * @param[in] setup_id NULL terminated Setup ID, which will be a 4 character + * long alpha numeric string (with capital alphabets) + * + * @return HAP_SUCCESS on success + * @return HAP_FAIL on failure + */ +int hap_set_setup_id(const char *setup_id); + +/** + * Check if the MFi authentication co-processor is connected + * + * @note This should be called before hap_init() + * + * @return HAP_SUCCESS if an MFi co-processor is detected + * @return HAP_FAIL if no MFi co-processor is detected + */ +int hap_check_mfi_chip(); + +/** + * @brief Reboot the accessory + * + * This closes all the active HomeKit sessions and reboots the accessory. + * It is recommended to use this API instead of the standard platform reboot/restart + * APIs, for cleaner operation. + * + * @note This is an asynchronous API (actual action executed in HomeKit core thread context) + * and can be invoked even from interrupt context. The \ref HAP_EVENT_ACC_REBOOTING + * event will be invoked after this. + * + * @return HAP_SUCCESS on success + * @return HAP_FAIL on failure + */ +int hap_reboot_accessory(); + +/** + * @brief Reset to Factory Settings + * + * This resets the accessory to factory settings and reboots it. + * All pairing information, network information and accessory specific information + * (like accessory ID, keys, config number, etc.) is erased. Even all application + * data written to NVS partition is erased. + * + * @note This is an asynchronous API (actual action executed in HomeKit core thread context) + * and can be invoked even from interrupt context. The \ref HAP_EVENT_ACC_REBOOTING + * event will be invoked after this. + * + * @return HAP_SUCCESS on success + * @return HAP_FAIL on failure + */ +int hap_reset_to_factory(); + +/** + * @brief Reset the Network Credentials + * + * This resets only the network credntials (keeping the pairing and any other information + * intact) and reboots the accessory. + * + * @note This is an asynchronous API (actual action executed in HomeKit core thread context) + * and can be invoked even from interrupt context. The \ref HAP_EVENT_ACC_REBOOTING + * event will be invoked after this. + * + * @return HAP_SUCCESS on success + * @return HAP_FAIL on failure + */ +int hap_reset_network(); + +/** + * @brief Reset HomeKit Data + * + * This resets all the data stored by the HomeKit Framework, which includes + * all pairing information, network information and accessory specific information + * (like accessory ID, keys, config number, etc.) + * + * @note This is an asynchronous API (actual action executed in HomeKit core thread context) + * and can be invoked even from interrupt context. The \ref HAP_EVENT_ACC_REBOOTING + * event will be invoked after this. + * + * @return HAP_SUCCESS on success + * @return HAP_FAIL on failure + */ +int hap_reset_homekit_data(); + +/** + * @brief Reset HomeKit Pairings + * + * This API resets the HomeKit Pairing Information and also the accessory specific + * information (like accessory ID, keys, config number, etc.). The accessory id is + * reset because else, the paired controllers would consider the accessory as paired, + * as they would still have the keys for the given accessory id. + * + * @note This is an asynchronous API (actual action executed in HomeKit core thread context) + * and can be invoked even from interrupt context. The \ref HAP_EVENT_ACC_REBOOTING + * event will be invoked after this. + * + * @return HAP_SUCCESS on success + * @return HAP_FAIL on failure + */ +int hap_reset_pairings(); + +/** + * @brief Check if the request is from Admin Controller + * + * This API can be used inside service read (\ref hap_serv_read_t) and service write + * (\ref hap_serv_write_t) callbacks to check if the request was from an admin controller. + * Pass the write_priv or read_priv pointer to this API + * + * @return true if request is from an admin controller + * @return false if request is from a non-admin controller + */ +bool hap_is_req_admin(void *priv); + +/** + * @brief Get the ID of the controller who sent the request + * + * This API can be used inside service read (\ref hap_serv_read_t) and service write + * (\ref hap_serv_write_t) callbacks to check the id of the controller who sent the request. + * Pass the write_priv or read_priv pointer to this API + * + * @return pointer to a null terminated controller id string on success. + * @return NULL on failure. + */ +char *hap_req_get_ctrl_id(void *priv); + +/** + * + * @brief Get a value from factory NVS keystore + * + * This API can be used to fetch information from the factory_nvs flash partition. + * This is treated as a Read-Only partition and so, no "set" API has been provided. + * + * @param[in] name_space NVS name space from which the value needs to be read. + * @param[in] key The NVS key for the value + * @param[out] val Buffer which will be used to hold the value, if found + * @param[in,out] val_size Holds the size of the val buffer. Will be populated with the length of + * the value by this function. + * + * @return HAP_SUCCESS on success + * @return HAP_FAIL on failure + */ +int hap_factory_keystore_get(const char *name_space, const char *key, uint8_t *val, size_t *val_size); + +/** + * Enable MFi authentication + * + * @param[in] auth_type The authentication type desired. + * + * @return HAP_SUCCESS on success + * @return HAP_FAIL on failure + */ +int hap_enable_mfi_auth(hap_mfi_auth_type_t auth_type); + +/** + * @brief Enable Software Token based authentication. + * + * This is valid for HomeKit Accessory Protocol Spec R12 (or later) and works with iOS 11.3 (or later) only. + * + * This API enables the Software Token based authentication for HomeKit pairing. It requires the accessory + * UUID and Token to be programmed in the factory_nvs partition. Please check the README for more details. + * + * Please refer HomeKit Software Authentication Server Specification to understand the server side + * implications of using this method for HomeKit Pairing. The tokens fetched from Apple server need to + * be programmed on the accessory + * + * @note Software Authentication is not recommended for new accessories. It should be used only if HomeKit + * functionality needs to be enabled on accessories which are already in field, or if an existing hardware + * design needs to be re-used for cost or other considerations. For any other use cases, please get in touch + * with your Apple contact. + * + * @return HAP_SUCCESS on success + * @return HAP_FAIL if the correct UUID or Token is not provided in the factory_nvs partition + */ +static inline int hap_enable_software_auth() +{ + return hap_enable_mfi_auth(HAP_MFI_AUTH_SW); +} + +#define HAP_REBOOT_REASON_UNKNOWN "unknown" +#define HAP_REBOOT_REASON_RESET_TO_FACTORY "reset_to_factory" +#define HAP_REBOOT_REASON_REBOOT_ACC "reboot_acc" +#define HAP_REBOOT_REASON_RESET_NETWORK "reset_network" +#define HAP_REBOOT_REASON_RESET_PAIRINGS "reset_pairings" +#define HAP_REBOOT_REASON_RESET_HOMEKIT_DATA "reset_homekit_data" + +/** HomeKit Event Base */ +ESP_EVENT_DECLARE_BASE(HAP_EVENT); +/** HomeKit Events */ +typedef enum { + /** A new controller was paired/added/modified. + * Associated data is a NULL terminated controller identifier string. + */ + HAP_EVENT_CTRL_PAIRED = 1, + /** A controller was removed + * Associated data is a NULL terminated controller identifier string. + */ + HAP_EVENT_CTRL_UNPAIRED, + /** A paired controller connected to the accessory (extablished a pair verified session). + * Associated data is a NULL terminated controller identifier string. + */ + HAP_EVENT_CTRL_CONNECTED, + /** A controller disconnected from the accessory. This event is reported before the + * actual disconnection, because for cases like pair-remove, the controller information + * gets erased before the disconnection, and so the controller id is not available + * after disconnection. + * Associated data is a NULL terminated controller identifier string. + */ + HAP_EVENT_CTRL_DISCONNECTED, + /** A Pair Setup attempt has started. Waiting for Setup Code */ + HAP_EVENT_PAIRING_STARTED, + /** Pair Setup was aborted because of inactivity or a wrong setup code */ + HAP_EVENT_PAIRING_ABORTED, + /** A GET on /accessories was successfully completed */ + HAP_EVENT_GET_ACC_COMPLETED, + /** A GET on /characteristics was successfully completed */ + HAP_EVENT_GET_CHAR_COMPLETED, + /** A PUT (Set value) on /characteristics was successfully completed. + * This event can also mean that notifications were enabled for some + * characteristics as the same is also done in PUT /characteristics */ + HAP_EVENT_SET_CHAR_COMPLETED, + /* Accessory is about to reboot. Will be triggered for operations like hap_reset_to_factory(), + * hap_reboot_accessory(), hap_reset_network(), hap_reset_pairings() and hap_reset_homekit_data() + * just before rebooting. Associated data is a pointer to a string indicating the reboot reason. + * Reefer the HAP_REBOOT_REASON_* macros for possible values. + */ + HAP_EVENT_ACC_REBOOTING, +} hap_event_t; + +/** Prototype for HomeKit Event handler + * + * @param[in] event The event id of type \ref hap_event_t + * @param[in] data Data associated with the event (if applicable). + * Please refer \ref hap_event_t documentation for information regarding + * data for each event. + */ +typedef void (*hap_event_handler_t) (hap_event_t event, void *data); + +/** Register HomeKit Event Handler + * + * If applications are interested in HomeKit specific events, they can + * write their own event handler and register with HomeKit core using + * this API. + * + * @param[in] handler Application specific HomeKit event handler. + */ +void hap_register_event_handler(hap_event_handler_t handler); + +/** Get Paired controller count + * + * This API can be used to get a count of number of paired controllers. + * Thi can be used only after hap_init(). + * + * @return Number of paired controllers + */ +int hap_get_paired_controller_count(); + +/* + * Enable Simple HTTP Debugging + * + * Calling this API will enable HTTP Debugging which will show some HomeKit HTTP Debug + * info like the URL and data. + */ +void hap_http_debug_enable(); + +/** + * Disable Simple HTTP Debugging + * + * Calling this API will disable HTTP Debugging which was enabled by hap_enable_http_debug() + */ +void hap_http_debug_disable(); + +/** Get Setup payload + * + * This gives the setup payload for the given information + * + * @param[in] setup_code NULL terminated setup code. Eg. "111-22-333" + * @param[in] setup_id NULL terminated setup id. Eg. "ES32" + * @param[in] wac_support Boolean indicating if WAC provisioning is supported. + * @param[in] cid Accessory category identifier. + * + * @return On success, an allocated NULL terminal setup paylod string. Eg. "X-HM://003363Z4TES32". Should be freed by the caller. + * @return NULL on failure. + */ +char *esp_hap_get_setup_payload(char *setup_code, char *setup_id, bool wac_support, hap_cid_t cid); +#ifdef __cplusplus +} +#endif + +#endif /* _ESP_HAP_H_ */ diff --git a/lib/libesp32_div/ESP32-HomeKit/src/hap_apple_chars.c b/lib/libesp32_div/ESP32-HomeKit/src/hap_apple_chars.c new file mode 100644 index 000000000..773cf31fd --- /dev/null +++ b/lib/libesp32_div/ESP32-HomeKit/src/hap_apple_chars.c @@ -0,0 +1,1482 @@ +/* + * ESPRESSIF MIT License + * + * Copyright (c) 2020 + * + * Permission is hereby granted for use on ESPRESSIF SYSTEMS products only, in which case, + * it is 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 +#include + +/* Char: Brightness */ +hap_char_t *hap_char_brightness_create(int brightness) +{ + hap_char_t *hc = hap_char_int_create(HAP_CHAR_UUID_BRIGHTNESS, + HAP_CHAR_PERM_PR | HAP_CHAR_PERM_PW | HAP_CHAR_PERM_EV, brightness); + if (!hc) { + return NULL; + } + + hap_char_int_set_constraints(hc, 0, 100, 1); + hap_char_add_unit(hc, HAP_CHAR_UNIT_PERCENTAGE); + + return hc; +} + +/* Char: Cooling Threshold Temperature */ +hap_char_t *hap_char_cooling_threshold_temperature_create(float cooling_threshold_temp) +{ + hap_char_t *hc = hap_char_float_create(HAP_CHAR_UUID_COOLING_THRESHOLD_TEMPERATURE, + HAP_CHAR_PERM_PR | HAP_CHAR_PERM_PW | HAP_CHAR_PERM_EV, cooling_threshold_temp); + if (!hc) { + return NULL; + } + + hap_char_float_set_constraints(hc, 10.0, 35.0, 0.1); + hap_char_add_unit(hc, HAP_CHAR_UNIT_CELSIUS); + + return hc; +} + +/* Char: Current Door State */ +hap_char_t *hap_char_current_door_state_create(uint8_t curr_door_state) +{ + hap_char_t *hc = hap_char_uint8_create(HAP_CHAR_UUID_CURRENT_DOOR_STATE, + HAP_CHAR_PERM_PR | HAP_CHAR_PERM_EV, curr_door_state); + if (!hc) { + return NULL; + } + + hap_char_int_set_constraints(hc, 0, 4, 1); + + return hc; +} + +/* Char: Current Heating Cooling State */ +hap_char_t *hap_char_current_heating_cooling_state_create(uint8_t curr_heating_cooling_state) +{ + hap_char_t *hc = hap_char_uint8_create(HAP_CHAR_UUID_CURRENT_HEATING_COOLING_STATE, + HAP_CHAR_PERM_PR | HAP_CHAR_PERM_EV, curr_heating_cooling_state); + if (!hc) { + return NULL; + } + + hap_char_int_set_constraints(hc, 0, 2, 1); + + return hc; +} + +/* Char: Current Relative Humidity */ +hap_char_t *hap_char_current_relative_humidity_create(float curr_rel_humidity) +{ + hap_char_t *hc = hap_char_float_create(HAP_CHAR_UUID_CURRENT_RELATIVE_HUMIDITY, + HAP_CHAR_PERM_PR | HAP_CHAR_PERM_EV, curr_rel_humidity); + if (!hc) { + return NULL; + } + + hap_char_float_set_constraints(hc, 0.0, 100.0, 1.0); + hap_char_add_unit(hc, HAP_CHAR_UNIT_PERCENTAGE); + + return hc; +} + +/* Char: Current Temperature */ +hap_char_t *hap_char_current_temperature_create(float curr_temp) +{ + hap_char_t *hc = hap_char_float_create(HAP_CHAR_UUID_CURRENT_TEMPERATURE, + HAP_CHAR_PERM_PR | HAP_CHAR_PERM_EV, curr_temp); + if (!hc) { + return NULL; + } + + hap_char_float_set_constraints(hc, 0.0, 100.0, 0.1); + hap_char_add_unit(hc, HAP_CHAR_UNIT_CELSIUS); + + return hc; +} + +/* Char: Firmware Revision */ +hap_char_t *hap_char_firmware_revision_create(char *fw_rev) +{ + hap_char_t *hc = hap_char_string_create(HAP_CHAR_UUID_FIRMWARE_REVISION, + HAP_CHAR_PERM_PR, fw_rev); + if (!hc) { + return NULL; + } + return hc; +} + +/* Char: Hardware Revision */ +hap_char_t *hap_char_hardware_revision_create(char *hw_rev) +{ + hap_char_t *hc = hap_char_string_create(HAP_CHAR_UUID_HARDWARE_REVISION, + HAP_CHAR_PERM_PR, hw_rev); + if (!hc) { + return NULL; + } + return hc; +} + +/* Char: Heating Threshold Temperature */ +hap_char_t *hap_char_heating_threshold_temperature_create(float heating_threshold_temp) +{ + hap_char_t *hc = hap_char_float_create(HAP_CHAR_UUID_HEATING_THRESHOLD_TEMPERATURE, + HAP_CHAR_PERM_PR | HAP_CHAR_PERM_PW | HAP_CHAR_PERM_EV, heating_threshold_temp); + if (!hc) { + return NULL; + } + + hap_char_float_set_constraints(hc, 0.0, 25.0, 0.1); + hap_char_add_unit(hc, HAP_CHAR_UNIT_CELSIUS); + + return hc; +} + +/* Char: Hue */ +hap_char_t *hap_char_hue_create(float hue) +{ + hap_char_t *hc = hap_char_float_create(HAP_CHAR_UUID_HUE, + HAP_CHAR_PERM_PR | HAP_CHAR_PERM_PW | HAP_CHAR_PERM_EV, hue); + if (!hc) { + return NULL; + } + + hap_char_float_set_constraints(hc, 0.0, 360.0, 1.0); + hap_char_add_unit(hc, HAP_CHAR_UNIT_ARCDEGREES); + + return hc; +} + +/* Char: Identify */ +hap_char_t *hap_char_identify_create(void) +{ + hap_char_t *hc = hap_char_bool_create(HAP_CHAR_UUID_IDENTIFY, HAP_CHAR_PERM_PW, false); + if (!hc) { + return NULL; + } + return hc; +} + +/* Char: Lock Current State */ +hap_char_t *hap_char_lock_current_state_create(uint8_t lock_curr_state) +{ + hap_char_t *hc = hap_char_uint8_create(HAP_CHAR_UUID_LOCK_CURRENT_STATE, + HAP_CHAR_PERM_PR | HAP_CHAR_PERM_EV, lock_curr_state); + if (!hc) { + return NULL; + } + + hap_char_int_set_constraints(hc, 0, 3, 1); + + return hc; +} + +/* Char: Lock Target State */ +hap_char_t *hap_char_lock_target_state_create(uint8_t lock_targ_state) +{ + hap_char_t *hc = hap_char_uint8_create(HAP_CHAR_UUID_LOCK_TARGET_STATE, + HAP_CHAR_PERM_PR | HAP_CHAR_PERM_PW | HAP_CHAR_PERM_EV, lock_targ_state); + if (!hc) { + return NULL; + } + + hap_char_int_set_constraints(hc, 0, 1, 1); + + return hc; +} + +/* Char: Manufacturer */ +hap_char_t *hap_char_manufacturer_create(char *manufacturer) +{ + hap_char_t *hc = hap_char_string_create(HAP_CHAR_UUID_MANUFACTURER, + HAP_CHAR_PERM_PR, manufacturer); + if (!hc) { + return NULL; + } + return hc; +} + +/* Char: Model */ +hap_char_t *hap_char_model_create(char *model) +{ + hap_char_t *hc = hap_char_string_create(HAP_CHAR_UUID_MODEL, + HAP_CHAR_PERM_PR, model); + if (!hc) { + return NULL; + } + return hc; +} + +/* Char: Motion Detected */ +hap_char_t *hap_char_motion_detected_create(bool motion_detected) +{ + hap_char_t *hc = hap_char_bool_create(HAP_CHAR_UUID_MOTION_DETECTED, + HAP_CHAR_PERM_PR | HAP_CHAR_PERM_EV, motion_detected); + if (!hc) { + return NULL; + } + + return hc; +} + +/* Char: Name */ +hap_char_t *hap_char_name_create(char *name) +{ + hap_char_t *hc = hap_char_string_create(HAP_CHAR_UUID_NAME, + HAP_CHAR_PERM_PR, name); + if (!hc) { + return NULL; + } + return hc; +} + +/* Char: Obstruction Detected */ +hap_char_t *hap_char_obstruction_detect_create(bool obstr_detect) +{ + hap_char_t *hc = hap_char_bool_create(HAP_CHAR_UUID_OBSTRUCTION_DETECTED, + HAP_CHAR_PERM_PR | HAP_CHAR_PERM_EV, obstr_detect); + if (!hc) { + return NULL; + } + + return hc; +} + +/* Char: On */ +hap_char_t *hap_char_on_create(bool on) +{ + hap_char_t *hc = hap_char_bool_create(HAP_CHAR_UUID_ON, + HAP_CHAR_PERM_PR | HAP_CHAR_PERM_PW | HAP_CHAR_PERM_EV, on); + if (!hc) { + return NULL; + } + return hc; +} + +/* Char: Outlet in Use */ +hap_char_t *hap_char_outlet_in_use_create(bool outlet_in_use) +{ + hap_char_t *hc = hap_char_bool_create(HAP_CHAR_UUID_OUTLET_IN_USE, + HAP_CHAR_PERM_PR | HAP_CHAR_PERM_EV, outlet_in_use); + if (!hc) { + return NULL; + } + return hc; +} + +/* Char: Rotation Direction */ +hap_char_t *hap_char_rotation_direction_create(int rotation_direction) +{ + hap_char_t *hc = hap_char_int_create(HAP_CHAR_UUID_ROTATION_DIRECTION, + HAP_CHAR_PERM_PR | HAP_CHAR_PERM_PW | HAP_CHAR_PERM_EV, rotation_direction); + if (!hc) { + return NULL; + } + + hap_char_int_set_constraints(hc, 0, 1, 1); + + return hc; +} + +/* Char: Rotation Speed */ +hap_char_t *hap_char_rotation_speed_create(float rotation_speed) +{ + hap_char_t *hc = hap_char_float_create(HAP_CHAR_UUID_ROTATION_SPEED, + HAP_CHAR_PERM_PR | HAP_CHAR_PERM_PW | HAP_CHAR_PERM_EV, rotation_speed); + if (!hc) { + return NULL; + } + + hap_char_float_set_constraints(hc, 0.0, 100.0, 1.0); + hap_char_add_unit(hc, HAP_CHAR_UNIT_PERCENTAGE); + + return hc; +} + +/* Char: Saturation */ +hap_char_t *hap_char_saturation_create(float saturation) +{ + hap_char_t *hc = hap_char_float_create(HAP_CHAR_UUID_SATURATION, + HAP_CHAR_PERM_PR | HAP_CHAR_PERM_PW | HAP_CHAR_PERM_EV, saturation); + if (!hc) { + return NULL; + } + + hap_char_float_set_constraints(hc, 0.0, 100.0, 1.0); + hap_char_add_unit(hc, HAP_CHAR_UNIT_PERCENTAGE); + + return hc; +} + +/* Char: Serial Number */ +hap_char_t *hap_char_serial_number_create(char *serial_num) +{ + hap_char_t *hc = hap_char_string_create(HAP_CHAR_UUID_SERIAL_NUMBER, + HAP_CHAR_PERM_PR, serial_num); + if (!hc) { + return NULL; + } + return hc; +} + +/* Char: Target Door State */ +hap_char_t *hap_char_target_door_state_create(uint8_t targ_door_state) +{ + hap_char_t *hc = hap_char_uint8_create(HAP_CHAR_UUID_TARGET_DOOR_STATE, + HAP_CHAR_PERM_PR | HAP_CHAR_PERM_PW | HAP_CHAR_PERM_EV, targ_door_state); + if (!hc) { + return NULL; + } + + hap_char_int_set_constraints(hc, 0, 1, 1); + + return hc; +} + +/* Char: Target Heating Cooling State */ +hap_char_t *hap_char_target_heating_cooling_state_create(uint8_t targ_heating_cooling_state) +{ + hap_char_t *hc = hap_char_uint8_create(HAP_CHAR_UUID_TARGET_HEATING_COOLING_STATE, + HAP_CHAR_PERM_PR | HAP_CHAR_PERM_PW | HAP_CHAR_PERM_EV, targ_heating_cooling_state); + if (!hc) { + return NULL; + } + + hap_char_int_set_constraints(hc, 0, 3, 1); + + return hc; +} + +/* Char: Target Relative Humidity */ +hap_char_t *hap_char_target_relative_humidity_create(float targ_rel_humidity) +{ + hap_char_t *hc = hap_char_float_create(HAP_CHAR_UUID_TARGET_RELATIVE_HUMIDITY, + HAP_CHAR_PERM_PR | HAP_CHAR_PERM_PW | HAP_CHAR_PERM_EV, targ_rel_humidity); + if (!hc) { + return NULL; + } + + hap_char_float_set_constraints(hc, 0.0, 100.0, 1.0); + hap_char_add_unit(hc, HAP_CHAR_UNIT_PERCENTAGE); + + return hc; +} + +/* Char: Target Temperature */ +hap_char_t *hap_char_target_temperature_create(float targ_temp) +{ + hap_char_t *hc = hap_char_float_create(HAP_CHAR_UUID_TARGET_TEMPERATURE, + HAP_CHAR_PERM_PR | HAP_CHAR_PERM_PW | HAP_CHAR_PERM_EV, targ_temp); + if (!hc) { + return NULL; + } + + hap_char_float_set_constraints(hc, 10.0, 38.0, 0.1); + hap_char_add_unit(hc, HAP_CHAR_UNIT_CELSIUS); + + return hc; +} + +/* Char: Temperature Display Units */ +hap_char_t *hap_char_temperature_display_units_create(uint8_t temp_disp_units) +{ + hap_char_t *hc = hap_char_uint8_create(HAP_CHAR_UUID_TEMPERATURE_DISPLAY_UNITS, + HAP_CHAR_PERM_PR | HAP_CHAR_PERM_PW | HAP_CHAR_PERM_EV, temp_disp_units); + if (!hc) { + return NULL; + } + + hap_char_int_set_constraints(hc, 0, 1, 1); + + return hc; +} + +/* Char: Version */ +hap_char_t *hap_char_version_create(char *version) +{ + hap_char_t *hc = hap_char_string_create(HAP_CHAR_UUID_VERSION, + HAP_CHAR_PERM_PR, version); + if (!hc) { + return NULL; + } + return hc; +} + +/* Char: Security System Current State */ +hap_char_t *hap_char_security_system_current_state_create(uint8_t security_sys_curr_state) +{ + hap_char_t *hc = hap_char_uint8_create(HAP_CHAR_UUID_SECURITY_SYSTEM_CURRENT_STATE, + HAP_CHAR_PERM_PR | HAP_CHAR_PERM_EV, security_sys_curr_state); + if (!hc) { + return NULL; + } + + hap_char_int_set_constraints(hc, 0, 4, 1); + + return hc; +} + +/* Char: Security System Target State */ +hap_char_t *hap_char_security_system_target_state_create(uint8_t security_sys_targ_state) +{ + hap_char_t *hc = hap_char_uint8_create(HAP_CHAR_UUID_SECURITY_SYSTEM_TARGET_STATE, + HAP_CHAR_PERM_PR | HAP_CHAR_PERM_PW | HAP_CHAR_PERM_EV, security_sys_targ_state); + if (!hc) { + return NULL; + } + + hap_char_int_set_constraints(hc, 0, 3, 1); + + return hc; +} + +/* Char: Battery Level */ +hap_char_t *hap_char_battery_level_create(uint8_t battery_level) +{ + hap_char_t *hc = hap_char_uint8_create(HAP_CHAR_UUID_BATTERY_LEVEL, + HAP_CHAR_PERM_PR | HAP_CHAR_PERM_EV, battery_level); + if (!hc) { + return NULL; + } + + hap_char_int_set_constraints(hc, 0, 100, 1); + hap_char_add_unit(hc, HAP_CHAR_UNIT_PERCENTAGE); + + return hc; +} + +/* Char: Carbon Monoxide Detected */ +hap_char_t *hap_char_carbon_monoxide_detected_create(uint8_t carbon_monoxide_detected) +{ + hap_char_t *hc = hap_char_uint8_create(HAP_CHAR_UUID_CARBON_MONOXIDE_DETECTED, + HAP_CHAR_PERM_PR | HAP_CHAR_PERM_EV, carbon_monoxide_detected); + if (!hc) { + return NULL; + } + + hap_char_int_set_constraints(hc, 0, 1, 1); + + return hc; +} + +/* Char: Contact Sensor State */ +hap_char_t *hap_char_contact_sensor_state_create(uint8_t contact_sensor_state) +{ + hap_char_t *hc = hap_char_uint8_create(HAP_CHAR_UUID_CONTACT_SENSOR_STATE, + HAP_CHAR_PERM_PR | HAP_CHAR_PERM_EV, contact_sensor_state); + if (!hc) { + return NULL; + } + + hap_char_int_set_constraints(hc, 0, 1, 1); + + return hc; +} + +/* Char: Current Ambient Light Level */ +hap_char_t *hap_char_current_ambient_light_level_create(float curr_ambient_light_level) +{ + hap_char_t *hc = hap_char_float_create(HAP_CHAR_UUID_CURRENT_AMBIENT_LIGHT_LEVEL, + HAP_CHAR_PERM_PR | HAP_CHAR_PERM_EV, curr_ambient_light_level); + if (!hc) { + return NULL; + } + + hap_char_float_set_constraints(hc, 0.0001, 100000.0, 0.0); + hap_char_add_unit(hc, HAP_CHAR_UNIT_LUX); + + return hc; +} + +/* Char: Current Horizontal Tilt Angle */ +hap_char_t *hap_char_current_horizontal_tilt_angle_create(int curr_horiz_tilt_angle) +{ + hap_char_t *hc = hap_char_int_create(HAP_CHAR_UUID_CURRENT_HORIZONTAL_TILT_ANGLE, + HAP_CHAR_PERM_PR | HAP_CHAR_PERM_EV, curr_horiz_tilt_angle); + if (!hc) { + return NULL; + } + + hap_char_int_set_constraints(hc, -90, 90, 1); + hap_char_add_unit(hc, HAP_CHAR_UNIT_ARCDEGREES); + + return hc; +} + +/* Char: Current Position */ +hap_char_t *hap_char_current_position_create(uint8_t curr_pos) +{ + hap_char_t *hc = hap_char_uint8_create(HAP_CHAR_UUID_CURRENT_POSITION, + HAP_CHAR_PERM_PR | HAP_CHAR_PERM_EV, curr_pos); + if (!hc) { + return NULL; + } + + hap_char_int_set_constraints(hc, 0, 100, 1); + hap_char_add_unit(hc, HAP_CHAR_UNIT_PERCENTAGE); + + return hc; +} + +/* Char: Current Vertical Tilt Angle */ +hap_char_t *hap_char_current_vertical_tilt_angle_create(int curr_vert_tilt_angle) +{ + hap_char_t *hc = hap_char_int_create(HAP_CHAR_UUID_CURRENT_VERTICAL_TILT_ANGLE, + HAP_CHAR_PERM_PR | HAP_CHAR_PERM_EV, curr_vert_tilt_angle); + if (!hc) { + return NULL; + } + + hap_char_int_set_constraints(hc, -90, 90, 1); + hap_char_add_unit(hc, HAP_CHAR_UNIT_ARCDEGREES); + + return hc; +} + +/* Char: Hold Position */ +hap_char_t *hap_char_hold_position_create(bool hold_pos) +{ + hap_char_t *hc = hap_char_bool_create(HAP_CHAR_UUID_HOLD_POSITION, + HAP_CHAR_PERM_PW, hold_pos); + if (!hc) { + return NULL; + } + + return hc; +} + +/* Char: Leak Detected */ +hap_char_t *hap_char_leak_detected_create(uint8_t leak_detected) +{ + hap_char_t *hc = hap_char_uint8_create(HAP_CHAR_UUID_LEAK_DETECTED, + HAP_CHAR_PERM_PR | HAP_CHAR_PERM_EV, leak_detected); + if (!hc) { + return NULL; + } + + hap_char_int_set_constraints(hc, 0, 1, 1); + + return hc; +} + +/* Char: Occupancy Detected */ +hap_char_t *hap_char_occupancy_detected_create(uint8_t occupancy_detected) +{ + hap_char_t *hc = hap_char_uint8_create(HAP_CHAR_UUID_OCCUPANCY_DETECTED, + HAP_CHAR_PERM_PR | HAP_CHAR_PERM_EV, occupancy_detected); + if (!hc) { + return NULL; + } + + hap_char_int_set_constraints(hc, 0, 1, 1); + + return hc; +} + +/* Char: Position State */ +hap_char_t *hap_char_position_state_create(uint8_t pos_state) +{ + hap_char_t *hc = hap_char_uint8_create(HAP_CHAR_UUID_POSITION_STATE, + HAP_CHAR_PERM_PR | HAP_CHAR_PERM_EV, pos_state); + if (!hc) { + return NULL; + } + + hap_char_int_set_constraints(hc, 0, 2, 1); + + return hc; +} + +/* Char: Programmable Switch Event */ +hap_char_t *hap_char_programmable_switch_event_create(uint8_t programmable_switch_event) +{ + hap_char_t *hc = hap_char_uint8_create(HAP_CHAR_UUID_PROGRAMMABLE_SWITCH_EVENT, + HAP_CHAR_PERM_PR | HAP_CHAR_PERM_EV | HAP_CHAR_PERM_SPECIAL_READ, + programmable_switch_event); + if (!hc) { + return NULL; + } + + hap_char_int_set_constraints(hc, 0, 2, 1); + + return hc; +} + +/* Char: Status Active */ +hap_char_t *hap_char_status_active_create(bool status_active) +{ + hap_char_t *hc = hap_char_bool_create(HAP_CHAR_UUID_STATUS_ACTIVE, + HAP_CHAR_PERM_PR | HAP_CHAR_PERM_EV, status_active); + if (!hc) { + return NULL; + } + + return hc; +} + +/* Char: Smoke Detected */ +hap_char_t *hap_char_smoke_detected_create(uint8_t smoke_detected) +{ + hap_char_t *hc = hap_char_uint8_create(HAP_CHAR_UUID_SMOKE_DETECTED, + HAP_CHAR_PERM_PR | HAP_CHAR_PERM_EV, smoke_detected); + if (!hc) { + return NULL; + } + + hap_char_int_set_constraints(hc, 0, 1, 1); + + return hc; +} + +/* Char: Status Fault */ +hap_char_t *hap_char_status_fault_create(uint8_t status_fault) +{ + hap_char_t *hc = hap_char_uint8_create(HAP_CHAR_UUID_STATUS_FAULT, + HAP_CHAR_PERM_PR | HAP_CHAR_PERM_EV, status_fault); + if (!hc) { + return NULL; + } + + hap_char_int_set_constraints(hc, 0, 1, 1); + + return hc; +} + +/* Char: Status Low Battery */ +hap_char_t *hap_char_status_low_battery_create(uint8_t status_low_battery) +{ + hap_char_t *hc = hap_char_uint8_create(HAP_CHAR_UUID_STATUS_LOW_BATTERY, + HAP_CHAR_PERM_PR | HAP_CHAR_PERM_EV, status_low_battery); + if (!hc) { + return NULL; + } + + hap_char_int_set_constraints(hc, 0, 1, 1); + + return hc; +} + +/* Char: Status Tampered */ +hap_char_t *hap_char_status_tampered_create(uint8_t status_tampered) +{ + hap_char_t *hc = hap_char_uint8_create(HAP_CHAR_UUID_STATUS_TAMPERED, + HAP_CHAR_PERM_PR | HAP_CHAR_PERM_EV, status_tampered); + if (!hc) { + return NULL; + } + + hap_char_int_set_constraints(hc, 0, 1, 1); + + return hc; +} + +/* Char: Target Horizontal Tilt Angle */ +hap_char_t *hap_char_target_horizontal_tilt_angle_create(int targ_horiz_tilt_angle) +{ + hap_char_t *hc = hap_char_int_create(HAP_CHAR_UUID_TARGET_HORIZONTAL_TILT_ANGLE, + HAP_CHAR_PERM_PR | HAP_CHAR_PERM_PW | HAP_CHAR_PERM_EV, targ_horiz_tilt_angle); + if (!hc) { + return NULL; + } + + hap_char_int_set_constraints(hc, -90, 90, 1); + hap_char_add_unit(hc, HAP_CHAR_UNIT_ARCDEGREES); + + return hc; +} + +/* Char: Target Position */ +hap_char_t *hap_char_target_position_create(uint8_t targ_pos) +{ + hap_char_t *hc = hap_char_uint8_create(HAP_CHAR_UUID_TARGET_POSITION, + HAP_CHAR_PERM_PR | HAP_CHAR_PERM_PW | HAP_CHAR_PERM_EV, targ_pos); + if (!hc) { + return NULL; + } + + hap_char_int_set_constraints(hc, 0, 100, 1); + hap_char_add_unit(hc, HAP_CHAR_UNIT_PERCENTAGE); + + return hc; +} + +/* Char: Target Vertical Tilt Angle */ +hap_char_t *hap_char_target_vertical_tilt_angle_create(int targ_vert_tilt_angle) +{ + hap_char_t *hc = hap_char_int_create(HAP_CHAR_UUID_TARGET_VERTICAL_TILT_ANGLE, + HAP_CHAR_PERM_PR | HAP_CHAR_PERM_PW | HAP_CHAR_PERM_EV, targ_vert_tilt_angle); + if (!hc) { + return NULL; + } + + hap_char_int_set_constraints(hc, -90, 90, 1); + hap_char_add_unit(hc, HAP_CHAR_UNIT_ARCDEGREES); + + return hc; +} + +/* Char: Security System Alarm Type */ +hap_char_t *hap_char_security_system_alarm_type_create(uint8_t security_sys_alarm_type) +{ + hap_char_t *hc = hap_char_uint8_create(HAP_CHAR_UUID_STATUS_SECURITY_SYSTEM_ALARM_TYPE, + HAP_CHAR_PERM_PR | HAP_CHAR_PERM_EV, security_sys_alarm_type); + if (!hc) { + return NULL; + } + + hap_char_int_set_constraints(hc, 0, 1, 1); + + return hc; +} + +/* Char: Charging State */ +hap_char_t *hap_char_charging_state_create(uint8_t charging_state) +{ + hap_char_t *hc = hap_char_uint8_create(HAP_CHAR_UUID_CHARGING_STATE, + HAP_CHAR_PERM_PR | HAP_CHAR_PERM_EV, charging_state); + if (!hc) { + return NULL; + } + + hap_char_int_set_constraints(hc, 0, 2, 1); + + return hc; +} + +/* Char: Carbon Monoxide Level */ +hap_char_t *hap_char_carbon_monoxide_level_create(float carbon_monoxide_level) +{ + hap_char_t *hc = hap_char_float_create(HAP_CHAR_UUID_CARBON_MONOXIDE_LEVEL, + HAP_CHAR_PERM_PR | HAP_CHAR_PERM_EV, carbon_monoxide_level); + if (!hc) { + return NULL; + } + + hap_char_float_set_constraints(hc, 0.0, 100.0, 0.0); + + return hc; +} + +/* Char: Carbon Monoxide Peak Level */ +hap_char_t *hap_char_carbon_monoxide_peak_level_create(float carbon_monoxide_peak_level) +{ + hap_char_t *hc = hap_char_float_create(HAP_CHAR_UUID_CARBON_MONOXIDE_PEAK_LEVEL, + HAP_CHAR_PERM_PR | HAP_CHAR_PERM_EV, carbon_monoxide_peak_level); + if (!hc) { + return NULL; + } + + hap_char_float_set_constraints(hc, 0.0, 100.0, 0.0); + + return hc; +} + +/* Char: Carbon Dioxide Detected */ +hap_char_t *hap_char_carbon_dioxide_detected_create(uint8_t carbon_dioxide_detected) +{ + hap_char_t *hc = hap_char_uint8_create(HAP_CHAR_UUID_CARBON_DIOXIDE_DETECTED, + HAP_CHAR_PERM_PR | HAP_CHAR_PERM_EV, carbon_dioxide_detected); + if (!hc) { + return NULL; + } + + hap_char_int_set_constraints(hc, 0, 1, 1); + + return hc; +} + +/* Char: Carbon Dioxide Level */ +hap_char_t *hap_char_carbon_dioxide_level_create(float carbon_dioxide_level) +{ + hap_char_t *hc = hap_char_float_create(HAP_CHAR_UUID_CARBON_DIOXIDE_LEVEL, + HAP_CHAR_PERM_PR | HAP_CHAR_PERM_EV, carbon_dioxide_level); + if (!hc) { + return NULL; + } + + hap_char_float_set_constraints(hc, 0.0, 100000.0, 0.0); + + return hc; +} + +/* Char: Carbon Dioxide Peak Level */ +hap_char_t *hap_char_carbon_dioxide_peak_level_create(float carbon_dioxide_peak_level) +{ + hap_char_t *hc = hap_char_float_create(HAP_CHAR_UUID_CARBON_DIOXIDE_PEAK_LEVEL, + HAP_CHAR_PERM_PR | HAP_CHAR_PERM_EV, carbon_dioxide_peak_level); + if (!hc) { + return NULL; + } + + hap_char_float_set_constraints(hc, 0.0, 100000.0, 0.0); + + return hc; +} + + +/* Char: Air Quality */ +hap_char_t *hap_char_air_quality_create(uint8_t air_quality) +{ + hap_char_t *hc = hap_char_uint8_create(HAP_CHAR_UUID_AIR_QUALITY, + HAP_CHAR_PERM_PR | HAP_CHAR_PERM_EV, air_quality); + if (!hc) { + return NULL; + } + + hap_char_int_set_constraints(hc, 0, 5, 1); + + return hc; +} + +/* Char: Accessory Flags */ +hap_char_t *hap_char_accessory_flags_create(uint32_t flags) +{ + hap_char_t *hc = hap_char_uint32_create(HAP_CHAR_UUID_ACCESSORY_FLAGS, + HAP_CHAR_PERM_PR | HAP_CHAR_PERM_EV, flags); + if (!hc) { + return NULL; + } + return hc; +} + +/* Char: Product Data */ +hap_char_t *hap_char_product_data_create(hap_data_val_t *product_data) +{ + hap_char_t *hc = hap_char_data_create(HAP_CHAR_UUID_PRODUCT_DATA, + HAP_CHAR_PERM_PR , product_data); + if (!hc) { + return NULL; + } + return hc; +} + +/* Char: Lock Physical Controls */ +hap_char_t *hap_char_lock_physical_controls_create(uint8_t lock_physical_controls) +{ + hap_char_t *hc = hap_char_uint8_create(HAP_CHAR_UUID_LOCK_PHYSICAL_CONTROLS, + HAP_CHAR_PERM_PR | HAP_CHAR_PERM_PW | HAP_CHAR_PERM_EV, lock_physical_controls); + if (!hc) { + return NULL; + } + + hap_char_int_set_constraints(hc, 0, 1, 1); + + return hc; +} + +/* Char: Current Air Purifier State */ +hap_char_t *hap_char_current_air_purifier_state_create(uint8_t curr_air_purifier_state) +{ + hap_char_t *hc = hap_char_uint8_create(HAP_CHAR_UUID_CURRENT_AIR_PURIFIER_STATE, + HAP_CHAR_PERM_PR | HAP_CHAR_PERM_EV, curr_air_purifier_state); + if (!hc) { + return NULL; + } + + hap_char_int_set_constraints(hc, 0, 2, 1); + + return hc; +} + +/* Char: Current Slat State */ +hap_char_t *hap_char_current_slat_state_create(uint8_t curr_slat_state) +{ + hap_char_t *hc = hap_char_uint8_create(HAP_CHAR_UUID_CURRENT_SLAT_STATE, + HAP_CHAR_PERM_PR | HAP_CHAR_PERM_EV, curr_slat_state); + if (!hc) { + return NULL; + } + + hap_char_int_set_constraints(hc, 0, 2, 1); + + return hc; +} + +/* Char: Slat Type */ +hap_char_t *hap_char_slat_type_create(uint8_t slat_type) +{ + hap_char_t *hc = hap_char_uint8_create(HAP_CHAR_UUID_SLAT_TYPE, + HAP_CHAR_PERM_PR, slat_type); + if (!hc) { + return NULL; + } + + hap_char_int_set_constraints(hc, 0, 1, 1); + + return hc; +} + +/* Char: Filter Life Level */ +hap_char_t *hap_char_filter_life_level_create(float filter_life_level) +{ + hap_char_t *hc = hap_char_float_create(HAP_CHAR_UUID_FILTER_LIFE_LEVEL, + HAP_CHAR_PERM_PR | HAP_CHAR_PERM_EV, filter_life_level); + if (!hc) { + return NULL; + } + + hap_char_float_set_constraints(hc, 0.0, 100.0, 1.0); + + return hc; +} + +/* Char: Filter Change Indication */ +hap_char_t *hap_char_filter_change_indication_create(uint8_t filter_change_indication) +{ + hap_char_t *hc = hap_char_uint8_create(HAP_CHAR_UUID_FILTER_CHANGE_INDICATION, + HAP_CHAR_PERM_PR | HAP_CHAR_PERM_EV, filter_change_indication); + if (!hc) { + return NULL; + } + + hap_char_int_set_constraints(hc, 0, 1, 1); + + return hc; +} + +/* Char: Reset Filter Indication */ +hap_char_t *hap_char_reset_filter_indication_create(uint8_t reset_filter_indication) +{ + hap_char_t *hc = hap_char_uint8_create(HAP_CHAR_UUID_RESET_FILTER_INDICATION, + HAP_CHAR_PERM_PW, reset_filter_indication); + if (!hc) { + return NULL; + } + + hap_char_int_set_constraints(hc, 1, 1, 0); + + return hc; +} + +/* Char: Target Air Purifier State */ +hap_char_t *hap_char_target_air_purifier_state_create(uint8_t targ_air_purifier_state) +{ + hap_char_t *hc = hap_char_uint8_create(HAP_CHAR_UUID_TARGET_AIR_PURIFIER_STATE, + HAP_CHAR_PERM_PR | HAP_CHAR_PERM_PW | HAP_CHAR_PERM_EV, targ_air_purifier_state); + if (!hc) { + return NULL; + } + + hap_char_int_set_constraints(hc, 0, 1, 1); + + return hc; +} + +/* Char: Target Fan State */ +hap_char_t *hap_char_target_fan_state_create(uint8_t targ_fan_state) +{ + hap_char_t *hc = hap_char_uint8_create(HAP_CHAR_UUID_TARGET_FAN_STATE, + HAP_CHAR_PERM_PR | HAP_CHAR_PERM_PW | HAP_CHAR_PERM_EV, targ_fan_state); + if (!hc) { + return NULL; + } + + hap_char_int_set_constraints(hc, 0, 1, 1); + + return hc; +} + +/* Char: Current Fan State */ +hap_char_t *hap_char_current_fan_state_create(uint8_t curr_fan_state) +{ + hap_char_t *hc = hap_char_uint8_create(HAP_CHAR_UUID_CURRENT_FAN_STATE, + HAP_CHAR_PERM_PR | HAP_CHAR_PERM_EV, curr_fan_state); + if (!hc) { + return NULL; + } + + hap_char_int_set_constraints(hc, 0, 2, 1); + + return hc; +} + +/* Char: Active State */ +hap_char_t *hap_char_active_create(uint8_t active) +{ + hap_char_t *hc = hap_char_uint8_create(HAP_CHAR_UUID_ACTIVE, + HAP_CHAR_PERM_PR | HAP_CHAR_PERM_PW | HAP_CHAR_PERM_EV, active); + if (!hc) { + return NULL; + } + + hap_char_int_set_constraints(hc, 0, 1, 1); + + return hc; +} + +/* Char: Swing Mode */ +hap_char_t *hap_char_swing_mode_create(uint8_t swing_mode) +{ + hap_char_t *hc = hap_char_uint8_create(HAP_CHAR_UUID_SWING_MODE, + HAP_CHAR_PERM_PR | HAP_CHAR_PERM_PW | HAP_CHAR_PERM_EV, swing_mode); + if (!hc) { + return NULL; + } + + hap_char_int_set_constraints(hc, 0, 1, 1); + + return hc; +} + +/* Char: Current Tilt Angle */ +hap_char_t *hap_char_current_tilt_angle_create(int curr_tilt_angle) +{ + hap_char_t *hc = hap_char_int_create(HAP_CHAR_UUID_CURRENT_TILT_ANGLE, + HAP_CHAR_PERM_PR | HAP_CHAR_PERM_EV, curr_tilt_angle); + if (!hc) { + return NULL; + } + + hap_char_int_set_constraints(hc, -90, 90, 1); + hap_char_add_unit(hc, HAP_CHAR_UNIT_ARCDEGREES); + + return hc; +} + +/* Char: Target Tilt Angle */ +hap_char_t *hap_char_target_tilt_angle_create(int targ_tilt_angle) +{ + hap_char_t *hc = hap_char_int_create(HAP_CHAR_UUID_TARGET_TILT_ANGLE, + HAP_CHAR_PERM_PR | HAP_CHAR_PERM_PW | HAP_CHAR_PERM_EV, targ_tilt_angle); + if (!hc) { + return NULL; + } + + hap_char_int_set_constraints(hc, -90, 90, 1); + hap_char_add_unit(hc, HAP_CHAR_UNIT_ARCDEGREES); + + return hc; +} + +/* Char: Ozone Density */ +hap_char_t *hap_char_ozone_density_create(float ozone_density) +{ + hap_char_t *hc = hap_char_float_create(HAP_CHAR_UUID_OZONE_DENSITY, + HAP_CHAR_PERM_PR | HAP_CHAR_PERM_EV, ozone_density); + if (!hc) { + return NULL; + } + + hap_char_float_set_constraints(hc, 0.0, 1000.0, 0.0); + + return hc; +} + +/* Char: Nitrogen Dioxide Density */ +hap_char_t *hap_char_nitrogen_dioxide_density_create(float nitrogen_dioxide_density) +{ + hap_char_t *hc = hap_char_float_create(HAP_CHAR_UUID_NITROGEN_DIOXIDE_DENSITY, + HAP_CHAR_PERM_PR | HAP_CHAR_PERM_EV, nitrogen_dioxide_density); + if (!hc) { + return NULL; + } + + hap_char_float_set_constraints(hc, 0.0, 1000.0, 0.0); + + return hc; +} + +/* Char: Sulphur Dioxide Density */ +hap_char_t *hap_char_sulphur_dioxide_density_create(float sulphur_dioxide_density) +{ + hap_char_t *hc = hap_char_float_create(HAP_CHAR_UUID_SULPHUR_DIOXIDE_DENSITY, + HAP_CHAR_PERM_PR | HAP_CHAR_PERM_EV, sulphur_dioxide_density); + if (!hc) { + return NULL; + } + + hap_char_float_set_constraints(hc, 0.0, 1000.0, 0.0); + + return hc; +} + +/* Char: PM2.5 Density */ +hap_char_t *hap_char_pm_2_5_density_create(float pm_2_5_density) +{ + hap_char_t *hc = hap_char_float_create(HAP_CHAR_UUID_PM_2_5_DENSITY, + HAP_CHAR_PERM_PR | HAP_CHAR_PERM_EV, pm_2_5_density); + if (!hc) { + return NULL; + } + + hap_char_float_set_constraints(hc, 0.0, 1000.0, 0.0); + + return hc; +} + +/* Char: PM10 Density */ +hap_char_t *hap_char_pm_10_density_create(float pm_10_density) +{ + hap_char_t *hc = hap_char_float_create(HAP_CHAR_UUID_PM_10_DENSITY, + HAP_CHAR_PERM_PR | HAP_CHAR_PERM_EV, pm_10_density); + if (!hc) { + return NULL; + } + + hap_char_float_set_constraints(hc, 0.0, 1000.0, 0.0); + + return hc; +} + +/* Char: VOC Density */ +hap_char_t *hap_char_voc_density_create(float voc_density) +{ + hap_char_t *hc = hap_char_float_create(HAP_CHAR_UUID_VOC_DENSITY, + HAP_CHAR_PERM_PR | HAP_CHAR_PERM_EV, voc_density); + if (!hc) { + return NULL; + } + + hap_char_float_set_constraints(hc, 0.0, 1000.0, 0.0); + + return hc; +} + +/* Char: Service Label Index */ +hap_char_t *hap_char_service_label_index_create(uint8_t service_label_index) +{ + hap_char_t *hc = hap_char_uint8_create(HAP_CHAR_UUID_SERVICE_LABEL_INDEX, + HAP_CHAR_PERM_PR, service_label_index); + if (!hc) { + return NULL; + } + + return hc; +} + +/* Char: Service Label Namespace */ +hap_char_t *hap_char_service_label_namespace_create(uint8_t service_label_namespace) +{ + hap_char_t *hc = hap_char_uint8_create(HAP_CHAR_UUID_SERVICE_LABEL_NAMESPACE, + HAP_CHAR_PERM_PR, service_label_namespace); + if (!hc) { + return NULL; + } + + hap_char_int_set_constraints(hc, 0, 1, 1); + + return hc; +} + +/* Char: Color Temperature */ +hap_char_t *hap_char_color_temperature_create(uint32_t color_temp) +{ + hap_char_t *hc = hap_char_uint32_create(HAP_CHAR_UUID_COLOR_TEMPERATURE, + HAP_CHAR_PERM_PR | HAP_CHAR_PERM_PW | HAP_CHAR_PERM_EV, color_temp); + if (!hc) { + return NULL; + } + + hap_char_int_set_constraints(hc, 50, 400, 1); + + return hc; +} + +/* Char: Current Heater Cooler State */ +hap_char_t *hap_char_current_heater_cooler_state_create(uint8_t curr_heater_cooler_state) +{ + hap_char_t *hc = hap_char_uint8_create(HAP_CHAR_UUID_CURRENT_HEATER_COOLER_STATE, + HAP_CHAR_PERM_PR | HAP_CHAR_PERM_EV, curr_heater_cooler_state); + if (!hc) { + return NULL; + } + + hap_char_int_set_constraints(hc, 0, 3, 1); + + return hc; +} + +/* Char: Target Heater Cooler State */ +hap_char_t *hap_char_target_heater_cooler_state_create(uint8_t targ_heater_cooler_state) +{ + hap_char_t *hc = hap_char_uint8_create(HAP_CHAR_UUID_TARGET_HEATER_COOLER_STATE, + HAP_CHAR_PERM_PR | HAP_CHAR_PERM_PW | HAP_CHAR_PERM_EV, targ_heater_cooler_state); + if (!hc) { + return NULL; + } + + hap_char_int_set_constraints(hc, 0, 2, 1); + + return hc; +} + +/* Char: Current Humidifier Dehumidifier State */ +hap_char_t *hap_char_current_humidifier_dehumidifier_state_create(uint8_t curr_humidifier_dehumidifier_state) +{ + hap_char_t *hc = hap_char_uint8_create(HAP_CHAR_UUID_CURRENT_HUMIDIFIER_DEHUMIDIFIER_STATE, + HAP_CHAR_PERM_PR | HAP_CHAR_PERM_EV, curr_humidifier_dehumidifier_state); + if (!hc) { + return NULL; + } + + hap_char_int_set_constraints(hc, 0, 3, 1); + + return hc; +} + +/* Char: Target Humidifier Dehumidifier State */ +hap_char_t *hap_char_target_humidifier_dehumidifier_state_create(uint8_t targ_humidifier_dehumidifier_state) +{ + hap_char_t *hc = hap_char_uint8_create(HAP_CHAR_UUID_TARGET_HUMIDIFIER_DEHUMIDIFIER_STATE, + HAP_CHAR_PERM_PR | HAP_CHAR_PERM_PW | HAP_CHAR_PERM_EV, targ_humidifier_dehumidifier_state); + if (!hc) { + return NULL; + } + + hap_char_int_set_constraints(hc, 0, 2, 1); + + return hc; +} + +/* Char: Water Level */ +hap_char_t *hap_char_water_level_create(float water_level) +{ + hap_char_t *hc = hap_char_float_create(HAP_CHAR_UUID_WATER_LEVEL, + HAP_CHAR_PERM_PR | HAP_CHAR_PERM_EV, water_level); + if (!hc) { + return NULL; + } + + hap_char_float_set_constraints(hc, 0.0, 100.0, 1.0); + + return hc; +} + +/* Char: Relative Humidity Dehumidifier Threshold */ +hap_char_t *hap_char_relative_humidity_dehumidifier_threshold_create(float rel_humidity_dehumidifier_threshold) +{ + hap_char_t *hc = hap_char_float_create(HAP_CHAR_UUID_RELATIVE_HUMIDITY_DEHUMIDIFIER_THRESHOLD, + HAP_CHAR_PERM_PR | HAP_CHAR_PERM_PW | HAP_CHAR_PERM_EV, rel_humidity_dehumidifier_threshold); + if (!hc) { + return NULL; + } + + hap_char_float_set_constraints(hc, 0.0, 100.0, 1.0); + hap_char_add_unit(hc, HAP_CHAR_UNIT_PERCENTAGE); + + return hc; +} + +/* Char: Relative Humidity Humidifier Threshold */ +hap_char_t *hap_char_relative_humidity_humidifier_threshold_create(float rel_humidity_humidifier_threshold) +{ + hap_char_t *hc = hap_char_float_create(HAP_CHAR_UUID_RELATIVE_HUMIDITY_HUMIDIFIER_THRESHOLD, + HAP_CHAR_PERM_PR | HAP_CHAR_PERM_PW | HAP_CHAR_PERM_EV, rel_humidity_humidifier_threshold); + if (!hc) { + return NULL; + } + + hap_char_float_set_constraints(hc, 0.0, 100.0, 1.0); + hap_char_add_unit(hc, HAP_CHAR_UNIT_PERCENTAGE); + + return hc; +} + +/* Char: Program Mode */ +hap_char_t *hap_char_program_mode_create(uint8_t prog_mode) +{ + hap_char_t *hc = hap_char_uint8_create(HAP_CHAR_UUID_PROGRAM_MODE, + HAP_CHAR_PERM_PR | HAP_CHAR_PERM_EV, prog_mode); + if (!hc) { + return NULL; + } + + hap_char_int_set_constraints(hc, 0, 2, 1); + + return hc; +} + +/* Char: In Use */ +hap_char_t *hap_char_in_use_create(uint8_t in_use) +{ + hap_char_t *hc = hap_char_uint8_create(HAP_CHAR_UUID_IN_USE, + HAP_CHAR_PERM_PR | HAP_CHAR_PERM_EV, in_use); + if (!hc) { + return NULL; + } + + hap_char_int_set_constraints(hc, 0, 1, 1); + + return hc; +} + +/* Char: Set Duration */ +hap_char_t *hap_char_set_duration_create(uint32_t set_duration) +{ + hap_char_t *hc = hap_char_uint32_create(HAP_CHAR_UUID_SET_DURATION, + HAP_CHAR_PERM_PR | HAP_CHAR_PERM_PW | HAP_CHAR_PERM_EV, set_duration); + if (!hc) { + return NULL; + } + + hap_char_int_set_constraints(hc, 0, 3600, 1); + + return hc; +} + +/* Char: Remaining Duration */ +hap_char_t *hap_char_remaining_duration_create(uint32_t remaining_duration) +{ + hap_char_t *hc = hap_char_uint32_create(HAP_CHAR_UUID_REMAINING_DURATION, + HAP_CHAR_PERM_PR | HAP_CHAR_PERM_EV, remaining_duration); + if (!hc) { + return NULL; + } + + hap_char_int_set_constraints(hc, 0, 3600, 1); + + return hc; +} + +/* Char: Valve Type */ +hap_char_t *hap_char_valve_type_create(uint8_t valve_type) +{ + hap_char_t *hc = hap_char_uint8_create(HAP_CHAR_UUID_VALVE_TYPE, + HAP_CHAR_PERM_PR | HAP_CHAR_PERM_EV, valve_type); + if (!hc) { + return NULL; + } + + hap_char_int_set_constraints(hc, 0, 3, 1); + + return hc; +} + +/* Char: Is Configured */ +hap_char_t *hap_char_is_configured_create(uint8_t is_configured) +{ + hap_char_t *hc = hap_char_uint8_create(HAP_CHAR_UUID_IS_CONFIGURED, + HAP_CHAR_PERM_PR | HAP_CHAR_PERM_PW | HAP_CHAR_PERM_EV, is_configured); + if (!hc) { + return NULL; + } + + hap_char_int_set_constraints(hc, 0, 1, 1); + + return hc; +} + +/* Char: Status Jammed */ +hap_char_t *hap_char_status_jammed_create(uint8_t status_jammed) +{ + hap_char_t *hc = hap_char_uint8_create(HAP_CHAR_UUID_STATUS_JAMMED, + HAP_CHAR_PERM_PR | HAP_CHAR_PERM_EV, status_jammed); + if (!hc) { + return NULL; + } + + hap_char_int_set_constraints(hc, 0, 1, 1); + + return hc; +} + +/* Char: Administrator Only Access */ +hap_char_t *hap_char_administrator_only_access_create(bool administrator_only_access) +{ + hap_char_t *hc = hap_char_bool_create(HAP_CHAR_UUID_ADMINISTRATOR_ONLY_ACCESS, + HAP_CHAR_PERM_PR | HAP_CHAR_PERM_PW | HAP_CHAR_PERM_EV, + administrator_only_access); + if (!hc) { + return NULL; + } + + return hc; +} + +/* Char: Lock Control Point */ +hap_char_t *hap_char_lock_control_point_create(hap_tlv8_val_t *lock_control_point) +{ + hap_char_t *hc = hap_char_tlv8_create(HAP_CHAR_UUID_LOCK_CONTROL_POINT, + HAP_CHAR_PERM_PW , lock_control_point); + if (!hc) { + return NULL; + } + + return hc; +} + +/* Char: Lock Last Known Action */ +hap_char_t *hap_char_lock_last_known_action_create(uint8_t lock_last_known_action) +{ + hap_char_t *hc = hap_char_uint8_create(HAP_CHAR_UUID_LOCK_LAST_KNOWN_ACTION, + HAP_CHAR_PERM_PR | HAP_CHAR_PERM_EV , lock_last_known_action); + if (!hc) { + return NULL; + } + + hap_char_int_set_constraints(hc, 0, 8, 1); + + return hc; +} + +/* Char: Lock Management Auto Security Timeout */ +hap_char_t *hap_char_lock_management_auto_security_timeout_create(uint32_t lock_management_auto_security_timeout) +{ + hap_char_t *hc = hap_char_uint32_create(HAP_CHAR_UUID_LOCK_MANAGEMENT_AUTO_SECURITY_TIMEOUT, + HAP_CHAR_PERM_PR | HAP_CHAR_PERM_PW | HAP_CHAR_PERM_EV, + lock_management_auto_security_timeout); + if (!hc) { + return NULL; + } + + hap_char_add_unit(hc, HAP_CHAR_UNIT_SECONDS); + + return hc; +} + +/* Char: Logs */ +hap_char_t *hap_char_logs_create(hap_tlv8_val_t *logs) +{ + hap_char_t *hc = hap_char_tlv8_create(HAP_CHAR_UUID_LOGS, + HAP_CHAR_PERM_PR | HAP_CHAR_PERM_EV , logs); + if (!hc) { + return NULL; + } + + return hc; +} + +/* Char: Air Particulate Density */ +hap_char_t *hap_char_air_particulate_density_create(float air_particulate_density) +{ + hap_char_t *hc = hap_char_float_create(HAP_CHAR_UUID_AIR_PARTICULATE_DENSITY, + HAP_CHAR_PERM_PR | HAP_CHAR_PERM_EV , air_particulate_density); + if (!hc) { + return NULL; + } + + hap_char_float_set_constraints(hc, 0, 1000, 0.0); + + return hc; +} + +/* Char: Air Particulate Size */ +hap_char_t *hap_char_air_particulate_size_create(uint8_t air_particulate_size) +{ + hap_char_t *hc = hap_char_uint8_create(HAP_CHAR_UUID_AIR_PARTICULATE_SIZE, + HAP_CHAR_PERM_PR | HAP_CHAR_PERM_EV , air_particulate_size); + if (!hc) { + return NULL; + } + + hap_char_int_set_constraints(hc, 0, 1, 1); + + return hc; +} diff --git a/lib/libesp32_div/ESP32-HomeKit/src/hap_apple_chars.h b/lib/libesp32_div/ESP32-HomeKit/src/hap_apple_chars.h new file mode 100644 index 000000000..e734a6e57 --- /dev/null +++ b/lib/libesp32_div/ESP32-HomeKit/src/hap_apple_chars.h @@ -0,0 +1,1422 @@ +/* + * ESPRESSIF MIT License + * + * Copyright (c) 2020 + * + * Permission is hereby granted for use on ESPRESSIF SYSTEMS products only, in which case, + * it is 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. + * + */ +/** HAP Apple Characteristics + * + * This offers helper APIs for all the standard HomeKit Characteristics defined by Apple + */ +#ifndef _HAP_APPLE_CHARS_H_ +#define _HAP_APPLE_CHARS_H_ + +#include +#include + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define HAP_CHAR_UUID_ADMINISTRATOR_ONLY_ACCESS "1" +#define HAP_CHAR_UUID_BRIGHTNESS "8" +#define HAP_CHAR_UUID_COOLING_THRESHOLD_TEMPERATURE "D" +#define HAP_CHAR_UUID_CURRENT_DOOR_STATE "E" +#define HAP_CHAR_UUID_CURRENT_HEATING_COOLING_STATE "F" +#define HAP_CHAR_UUID_CURRENT_RELATIVE_HUMIDITY "10" +#define HAP_CHAR_UUID_CURRENT_TEMPERATURE "11" +#define HAP_CHAR_UUID_FIRMWARE_REVISION "52" +#define HAP_CHAR_UUID_HARDWARE_REVISION "53" +#define HAP_CHAR_UUID_HEATING_THRESHOLD_TEMPERATURE "12" +#define HAP_CHAR_UUID_HUE "13" +#define HAP_CHAR_UUID_IDENTIFY "14" +#define HAP_CHAR_UUID_LOCK_CONTROL_POINT "19" +#define HAP_CHAR_UUID_LOCK_CURRENT_STATE "1D" +#define HAP_CHAR_UUID_LOCK_LAST_KNOWN_ACTION "1C" +#define HAP_CHAR_UUID_LOCK_MANAGEMENT_AUTO_SECURITY_TIMEOUT "1A" +#define HAP_CHAR_UUID_LOCK_TARGET_STATE "1E" +#define HAP_CHAR_UUID_LOGS "1F" +#define HAP_CHAR_UUID_MANUFACTURER "20" +#define HAP_CHAR_UUID_MODEL "21" +#define HAP_CHAR_UUID_MOTION_DETECTED "22" +#define HAP_CHAR_UUID_NAME "23" +#define HAP_CHAR_UUID_OBSTRUCTION_DETECTED "24" +#define HAP_CHAR_UUID_ON "25" +#define HAP_CHAR_UUID_OUTLET_IN_USE "26" +#define HAP_CHAR_UUID_ROTATION_DIRECTION "28" +#define HAP_CHAR_UUID_ROTATION_SPEED "29" +#define HAP_CHAR_UUID_SATURATION "2F" +#define HAP_CHAR_UUID_SERIAL_NUMBER "30" +#define HAP_CHAR_UUID_TARGET_DOOR_STATE "32" +#define HAP_CHAR_UUID_TARGET_HEATING_COOLING_STATE "33" +#define HAP_CHAR_UUID_TARGET_RELATIVE_HUMIDITY "34" +#define HAP_CHAR_UUID_TARGET_TEMPERATURE "35" +#define HAP_CHAR_UUID_TEMPERATURE_DISPLAY_UNITS "36" +#define HAP_CHAR_UUID_VERSION "37" +#define HAP_CHAR_UUID_AIR_PARTICULATE_DENSITY "64" +#define HAP_CHAR_UUID_AIR_PARTICULATE_SIZE "65" +#define HAP_CHAR_UUID_SECURITY_SYSTEM_CURRENT_STATE "66" +#define HAP_CHAR_UUID_SECURITY_SYSTEM_TARGET_STATE "67" +#define HAP_CHAR_UUID_BATTERY_LEVEL "68" +#define HAP_CHAR_UUID_CARBON_MONOXIDE_DETECTED "69" +#define HAP_CHAR_UUID_CONTACT_SENSOR_STATE "6A" +#define HAP_CHAR_UUID_CURRENT_AMBIENT_LIGHT_LEVEL "6B" +#define HAP_CHAR_UUID_CURRENT_HORIZONTAL_TILT_ANGLE "6C" +#define HAP_CHAR_UUID_CURRENT_POSITION "6D" +#define HAP_CHAR_UUID_CURRENT_VERTICAL_TILT_ANGLE "6E" +#define HAP_CHAR_UUID_HOLD_POSITION "6F" +#define HAP_CHAR_UUID_LEAK_DETECTED "70" +#define HAP_CHAR_UUID_OCCUPANCY_DETECTED "71" +#define HAP_CHAR_UUID_POSITION_STATE "72" +#define HAP_CHAR_UUID_PROGRAMMABLE_SWITCH_EVENT "73" +#define HAP_CHAR_UUID_STATUS_ACTIVE "75" +#define HAP_CHAR_UUID_SMOKE_DETECTED "76" +#define HAP_CHAR_UUID_STATUS_FAULT "77" +#define HAP_CHAR_UUID_STATUS_JAMMED "78" +#define HAP_CHAR_UUID_STATUS_LOW_BATTERY "79" +#define HAP_CHAR_UUID_STATUS_TAMPERED "7A" +#define HAP_CHAR_UUID_TARGET_HORIZONTAL_TILT_ANGLE "7B" +#define HAP_CHAR_UUID_TARGET_POSITION "7C" +#define HAP_CHAR_UUID_TARGET_VERTICAL_TILT_ANGLE "7D" +#define HAP_CHAR_UUID_STATUS_SECURITY_SYSTEM_ALARM_TYPE "8E" +#define HAP_CHAR_UUID_CHARGING_STATE "8F" +#define HAP_CHAR_UUID_CARBON_MONOXIDE_LEVEL "90" +#define HAP_CHAR_UUID_CARBON_MONOXIDE_PEAK_LEVEL "91" +#define HAP_CHAR_UUID_CARBON_DIOXIDE_DETECTED "92" +#define HAP_CHAR_UUID_CARBON_DIOXIDE_LEVEL "93" +#define HAP_CHAR_UUID_CARBON_DIOXIDE_PEAK_LEVEL "94" +#define HAP_CHAR_UUID_AIR_QUALITY "95" +#define HAP_CHAR_UUID_ACCESSORY_FLAGS "A6" +#define HAP_CHAR_UUID_LOCK_PHYSICAL_CONTROLS "A7" +#define HAP_CHAR_UUID_CURRENT_AIR_PURIFIER_STATE "A9" +#define HAP_CHAR_UUID_CURRENT_SLAT_STATE "AA" +#define HAP_CHAR_UUID_SLAT_TYPE "C0" +#define HAP_CHAR_UUID_FILTER_LIFE_LEVEL "AB" +#define HAP_CHAR_UUID_FILTER_CHANGE_INDICATION "AC" +#define HAP_CHAR_UUID_RESET_FILTER_INDICATION "AD" +#define HAP_CHAR_UUID_TARGET_AIR_PURIFIER_STATE "A8" +#define HAP_CHAR_UUID_TARGET_FAN_STATE "BF" +#define HAP_CHAR_UUID_CURRENT_FAN_STATE "AF" +#define HAP_CHAR_UUID_ACTIVE "B0" +#define HAP_CHAR_UUID_SWING_MODE "B6" +#define HAP_CHAR_UUID_CURRENT_TILT_ANGLE "C1" +#define HAP_CHAR_UUID_TARGET_TILT_ANGLE "C2" +#define HAP_CHAR_UUID_OZONE_DENSITY "C3" +#define HAP_CHAR_UUID_NITROGEN_DIOXIDE_DENSITY "C4" +#define HAP_CHAR_UUID_SULPHUR_DIOXIDE_DENSITY "C5" +#define HAP_CHAR_UUID_PM_2_5_DENSITY "C6" +#define HAP_CHAR_UUID_PM_10_DENSITY "C7" +#define HAP_CHAR_UUID_VOC_DENSITY "C8" +#define HAP_CHAR_UUID_SERVICE_LABEL_INDEX "CB" +#define HAP_CHAR_UUID_SERVICE_LABEL_NAMESPACE "CD" +#define HAP_CHAR_UUID_COLOR_TEMPERATURE "CE" +#define HAP_CHAR_UUID_CURRENT_HEATER_COOLER_STATE "B1" +#define HAP_CHAR_UUID_TARGET_HEATER_COOLER_STATE "B2" +#define HAP_CHAR_UUID_CURRENT_HUMIDIFIER_DEHUMIDIFIER_STATE "B3" +#define HAP_CHAR_UUID_TARGET_HUMIDIFIER_DEHUMIDIFIER_STATE "B4" +#define HAP_CHAR_UUID_WATER_LEVEL "B5" +#define HAP_CHAR_UUID_RELATIVE_HUMIDITY_DEHUMIDIFIER_THRESHOLD "C9" +#define HAP_CHAR_UUID_RELATIVE_HUMIDITY_HUMIDIFIER_THRESHOLD "CA" +#define HAP_CHAR_UUID_PROGRAM_MODE "D1" +#define HAP_CHAR_UUID_IN_USE "D2" +#define HAP_CHAR_UUID_SET_DURATION "D3" +#define HAP_CHAR_UUID_REMAINING_DURATION "D4" +#define HAP_CHAR_UUID_VALVE_TYPE "D5" +#define HAP_CHAR_UUID_IS_CONFIGURED "D6" +#define HAP_CHAR_UUID_PRODUCT_DATA "220" + +/** Create Brightness Characteristic + * + * This API creates the Brightness characteristic object with other metadata + * (format, constraints, permissions, etc.) set as per the HAP Specs + * + * @param[in] brightness Initial value of brightness + * + * @return Pointer to the characteristic object on success + * @return NULL on failure + */ +hap_char_t *hap_char_brightness_create(int brightness); + +/** Cooling Threshold Temperature Characteristic + * + * This API creates the Cooling Threshold Temperature characteristic object with other metadata + * (format, constraints, permissions, etc.) set as per the HAP Specs + * + * @param[in] cooling_threshold_temp Cooling Threshold Value of Cooling Threshold Temperature characteristic + * + * @return Pointer to the characteristic object on success + * @return NULL on failure + */ +hap_char_t *hap_char_cooling_threshold_temperature_create(float cooling_threshold_temp); + +/** Create Current Door State Characteristic + * + * This API creates the Current Door State characteristic object with other metadata + * (format, constraints, permissions, etc.) set as per the HAP Specs + * + * @param[in] curr_door_state Initial value of Current Door State + * + * @return Pointer to the characteristic object on success + * @return NULL on failure + */ +hap_char_t *hap_char_current_door_state_create(uint8_t curr_door_state); + +/** Create Current Heating Cooling State Characteristic + * + * This API creates the Current Heating Cooling State characteristic object with other metadata + * (format, constraints, permissions, etc.) set as per the HAP Specs + * + * @param[in] curr_heating_cooling_state Initial value of current heating cooling state characteristic + * + * @return Pointer to the characteristic object on success + * @return NULL on failure + */ +hap_char_t *hap_char_current_heating_cooling_state_create(uint8_t curr_heating_cooling_state); + +/** Current Relative Humidity Characteristic + * + * This API creates the Current Relative Humidity characteristic object with other metadata + * (format, constraints, permissions, etc.) set as per the HAP Specs + * + * @param[in] curr_rel_humidity Current Relative Humidity Value + * + * @return Pointer to the characteristic object on success + * @return NULL on failure + */ +hap_char_t *hap_char_current_relative_humidity_create(float curr_rel_humidity); + +/** Current Temperature Characteristic + * + * This API creates the Current Temperature characteristic object with other metadata + * (format, constraints, permissions, etc.) set as per the HAP Specs + * + * @param[in] curr_temp Initial value of current temperature characteristic + * + * @return Pointer to the characteristic object on success + * @return NULL on failure + */ +hap_char_t *hap_char_current_temperature_create(float curr_temp); + +/** Create Firmware Revision Characteristic + * + * This API creates the firmware revision characteristic object with other metadata + * (format, constraints, permissions, etc.) set as per the HAP Specs + * + * @param[in] fw_rev Firmware Revision string + * + * @return Pointer to the characteristic object on success + * @return NULL on failure + */ +hap_char_t *hap_char_firmware_revision_create(char *fw_rev); + +/** Create Hardware Revision Characteristic + * + * This API creates the name characteristic object with other metadata + * (format, constraints, permissions, etc.) set as per the HAP Specs + * + * @param[in] hw_rev Hardware Revision string + * + * @return Pointer to the characteristic object on success + * @return NULL on failure + */ +hap_char_t *hap_char_hardware_revision_create(char *hw_rev); + +/** Heating Threshold Temperature Characteristic + * + * This API creates the Heating Threshold Temperature characteristic object with other metadata + * (format, constraints, permissions, etc.) set as per the HAP Specs + * + * @param[in] heating_threshold_temp Heating Threshold Value of Heating Threshold Temperature characteristic + * + * @return Pointer to the characteristic object on success + * @return NULL on failure + */ +hap_char_t *hap_char_heating_threshold_temperature_create(float heating_threshold_temp); + +/** Create Hue Characteristic + * + * This API creates the hue characteristic object with other metadata + * (format, constraints, permissions, etc.) set as per the HAP Specs + * + * @param[in] hue Initial value of hue + * + * @return Pointer to the characteristic object on success + * @return NULL on failure + */ +hap_char_t *hap_char_hue_create(float hue); + +/** Create Identify Characteristic + * + * This API creates the Identify characteristic object with other metadata + * (format, constraints, permissions, etc.) set as per the HAP Specs + * + * @return Pointer to the characteristic object on success + * @return NULL on failure + */ +hap_char_t *hap_char_identify_create(void); + +/** Lock Current State Characteristic + * + * This API creates the Lock Current State characteristic object with other metadata + * (format, constraints, permissions, etc.) set as per the HAP Specs + * + * @param[in] lock_curr_state Current lock state value of characteristic + * + * @return Pointer to the characteristic object on success + * @return NULL on failure + */ +hap_char_t *hap_char_lock_current_state_create(uint8_t lock_curr_state); + +/** Lock Target State Characteristic + * + * This API creates the Lock Target State characteristic object with other metadata + * (format, constraints, permissions, etc.) set as per the HAP Specs + * + * @param[in] lock_targ_state Target lock state value of characteristic + * + * @return Pointer to the characteristic object on success + * @return NULL on failure + */ +hap_char_t *hap_char_lock_target_state_create(uint8_t lock_targ_state); + +/** Create Manufacturer Characteristic + * + * This API creates the Manufacturer characteristic object with other metadata + * (format, constraints, permissions, etc.) set as per the HAP Specs + * + * @param[in] manufacturer Manufacturer string + * + * @return Pointer to the characteristic object on success + * @return NULL on failure + */ +hap_char_t *hap_char_manufacturer_create(char *manufacturer); + +/** Create Model Characteristic + * + * This API creates the Model characteristic object with other metadata + * (format, constraints, permissions, etc.) set as per the HAP Specs + * + * @param[in] model Model string + * + * @return Pointer to the characteristic object on success + * @return NULL on failure + */ +hap_char_t *hap_char_model_create(char *model); + +/** Create Motion Detected Characteristic + * + * This API creates the Motion Detected characteristic object with other metadata + * (format, constraints, permissions, etc.) set as per the HAP Specs + * + * @param[in] motion_detected Value of Motion Detected Charateristic + * + * @return Pointer to the characteristic object on success + * @return NULL on failure + */ +hap_char_t *hap_char_motion_detected_create(bool motion_detected); + +/** Create Name Characteristic + * + * This API creates the Name characteristic object with other metadata + * (format, constraints, permissions, etc.) set as per the HAP Specs + * + * @param[in] name Name string + * + * @return Pointer to the characteristic object on success + * @return NULL on failure + */ +hap_char_t *hap_char_name_create(char *name); + +/** Create Obstruction Detected Characteristic + * + * This API creates the Obstruction Detected characteristic object with other metadata + * (format, constraints, permissions, etc.) set as per the HAP Specs + * + * @param[in] obstr_detect Initial value of obstruction detected characteristic + * + * @return Pointer to the characteristic object on success + * @return NULL on failure + */ +hap_char_t *hap_char_obstruction_detect_create(bool obstr_detect); + +/** Create On Characteristic + * + * This API creates the On characteristic object with other metadata + * (format, constraints, permissions, etc.) set as per the HAP Specs + * + * @param[in] on Initial value of on + * + * @return Pointer to the characteristic object on success + * @return NULL on failure + */ +hap_char_t *hap_char_on_create(bool on); + +/** Create Outlet in Use Characteristic + * + * This API creates the Outlet in Use characteristic object with other metadata + * (format, constraints, permissions, etc.) set as per the HAP Specs + * + * @param[in] outlet_in_use Initial value of outlet in use + * + * @return Pointer to the characteristic object on success + * @return NULL on failure + */ +hap_char_t *hap_char_outlet_in_use_create(bool outlet_in_use); + +/** Create Rotation Direction Characteristic + * + * This API creates the Rotation Direction characteristic object with other metadata + * (format, constraints, permissions, etc.) set as per the HAP Specs + * + * @param[in] rotation_direction Initial value of Rotation Direction + * + * @return Pointer to the characteristic object on success + * @return NULL on failure + */ +hap_char_t *hap_char_rotation_direction_create(int rotation_direction); + +/** Create Rotation Speed Characteristic + * + * This API creates the Rotation Speed characteristic object with other metadata + * (format, constraints, permissions, etc.) set as per the HAP Specs + * + * @param[in] rotation_speed Initial value of Rotation Speed + * + * @return Pointer to the characteristic object on success + * @return NULL on failure + */ +hap_char_t *hap_char_rotation_speed_create(float rotation_speed); + +/** Create Saturation Characteristic + * + * This API creates the saturation characteristic object with other metadata + * (format, constraints, permissions, etc.) set as per the HAP Specs + * + * @param[in] saturation Initial value of saturation + * + * @return Pointer to the characteristic object on success + * @return NULL on failure + */ +hap_char_t *hap_char_saturation_create(float saturation); + +/** Create Serial Number Characteristic + * + * This API creates the serial number characteristic object with other metadata + * (format, constraints, permissions, etc.) set as per the HAP Specs + * + * @param[in] serial_num Serial Number string + * + * @return Pointer to the characteristic object on success + * @return NULL on failure + */ +hap_char_t *hap_char_serial_number_create(char *serial_num); + +/** Create Target Door State Characteristic + * + * This API creates the Target Door State characteristic object with other metadata + * (format, constraints, permissions, etc.) set as per the HAP Specs + * + * @param[in] targ_door_state Initial value of Target Door State + * + * @return Pointer to the characteristic object on success + * @return NULL on failure + */ +hap_char_t *hap_char_target_door_state_create(uint8_t targ_door_state); + +/** Create Target Heating Cooling State Characteristic + * + * This API creates the Target Heating Cooling State characteristic object with other metadata + * (format, constraints, permissions, etc.) set as per the HAP Specs + * + * @param[in] targ_heating_cooling_state Value of target heating cooling state characteristic + * + * @return Pointer to the characteristic object on success + * @return NULL on failure + */ +hap_char_t *hap_char_target_heating_cooling_state_create(uint8_t targ_heating_cooling_state); + +/** Target Relative Humidity Characteristic + * + * This API creates the Target Relative Humidity characteristic object with other metadata + * (format, constraints, permissions, etc.) set as per the HAP Specs + * + * @param[in] targ_rel_humidity Target Relative Humidity Value + * + * @return Pointer to the characteristic object on success + * @return NULL on failure + */ +hap_char_t *hap_char_target_relative_humidity_create(float targ_rel_humidity); + +/** Target Temperature Characteristic + * + * This API creates the Target Temperature characteristic object with other metadata + * (format, constraints, permissions, etc.) set as per the HAP Specs + * + * @param[in] targ_temp Target value of target temperature characteristic + * + * @return Pointer to the characteristic object on success + * @return NULL on failure + */ +hap_char_t *hap_char_target_temperature_create(float targ_temp); + +/** Temperature Display Units Characteristic + * + * This API creates the Temperature Display Units characteristic object with other metadata + * (format, constraints, permissions, etc.) set as per the HAP Specs + * + * @param[in] temp_disp_units Initial value of Temperature Display Units characteristic + * + * @return Pointer to the characteristic object on success + * @return NULL on failure + */ +hap_char_t *hap_char_temperature_display_units_create(uint8_t temp_disp_units); + +/** Create Version Characteristic + * + * This API creates the version characteristic object with other metadata + * (format, constraints, permissions, etc.) set as per the HAP Specs + * + * @param[in] version Version String + * + * @return Pointer to the characteristic object on success + * @return NULL on failure + */ +hap_char_t *hap_char_version_create(char *version); + +/** Create Security System Current State Characteristic + * + * This API creates the Security System Current State characteristic object with other metadata + * (format, constraints, permissions, etc.) set as per the HAP Specs + * + * @param[in] security_sys_curr_state Initial value of Security System Current State characteristic + * + * @return Pointer to the characteristic object on success + * @return NULL on failure + */ +hap_char_t *hap_char_security_system_current_state_create(uint8_t security_sys_curr_state); + +/** Create Security System Target State Characteristic + * + * This API creates the Security System Target State characteristic object with other metadata + * (format, constraints, permissions, etc.) set as per the HAP Specs + * + * @param[in] security_sys_targ_state Initial value of Security System Target State characteristic + * + * @return Pointer to the characteristic object on success + * @return NULL on failure + */ +hap_char_t *hap_char_security_system_target_state_create(uint8_t security_sys_targ_state); + +/** Create Battery Level Characteristic + * + * This API creates the Battery Level characteristic object with other metadata + * (format, constraints, permissions, etc.) set as per the HAP Specs + * + * @param[in] battery_level Initial value of Battery Level characteristic + * + * @return Pointer to the characteristic object on success + * @return NULL on failure + */ +hap_char_t *hap_char_battery_level_create(uint8_t battery_level); + +/** Current Position Characteristic + * + * This API creates the Current Position characteristic object with other metadata + * (format, constraints, permissions, etc.) set as per the HAP Specs + * + * @param[in] curr_pos Initial value of Cuurent Position characteristic + * + * @return Pointer to the characteristic object on success + * @return NULL on failure + */ +hap_char_t *hap_char_current_position_create(uint8_t curr_pos); + +/** Current Vertical Tilt Angle Characteristic + * + * This API creates the Current Vertical Tilt Angle characteristic object with other metadata + * (format, constraints, permissions, etc.) set as per the HAP Specs + * + * @param[in] curr_vert_tilt_angle Initial value of Current Vertical Tilt Angle characteristic + * + * @return Pointer to the characteristic object on success + * @return NULL on failure + */ +hap_char_t *hap_char_current_vertical_tilt_angle_create(int curr_vert_tilt_angle); + +/** Hold Position Characteristic + * + * This API creates the Hold Position characteristic object with other metadata + * (format, constraints, permissions, etc.) set as per the HAP Specs + * + * @param[in] hold_pos Initial value of Hold Position characteristic + * + * @return Pointer to the characteristic object on success + * @return NULL on failure + */ +hap_char_t *hap_char_hold_position_create(bool hold_pos); + +/** Leak Detected Characteristic + * + * This API creates the Leak Detected characteristic object with other metadata + * (format, constraints, permissions, etc.) set as per the HAP Specs + * + * @param[in] leak_detected Initial value of Leak Detected characteristic + * + * @return Pointer to the characteristic object on success + * @return NULL on failure + */ +hap_char_t *hap_char_leak_detected_create(uint8_t leak_detected); + +/** Occupancy Detected Characteristic + * + * This API creates the Occupancy Detected characteristic object with other metadata + * (format, constraints, permissions, etc.) set as per the HAP Specs + * + * @param[in] occupancy_detected Initial value of Occupancy Detected characteristic + * + * @return Pointer to the characteristic object on success + * @return NULL on failure + */ +hap_char_t *hap_char_occupancy_detected_create(uint8_t occupancy_detected); + +/** Status Active Characteristic + * + * This API creates the Status Active characteristic object with other metadata + * (format, constraints, permissions, etc.) set as per the HAP Specs + * + * @param[in] status_active Initial value of Status Active characteristic + * + * @return Pointer to the characteristic object on success + * @return NULL on failure + */ +hap_char_t *hap_char_status_active_create(bool status_active); + +/** Smoke Detected Characteristic + * + * This API creates the Smoke Detected characteristic object with other metadata + * (format, constraints, permissions, etc.) set as per the HAP Specs + * + * @param[in] smoke_detected Initial value of Smoke Detected characteristic + * + * @return Pointer to the characteristic object on success + * @return NULL on failure + */ +hap_char_t *hap_char_smoke_detected_create(uint8_t smoke_detected); + +/** Status Fault Characteristic + * + * This API creates the Status Fault characteristic object with other metadata + * (format, constraints, permissions, etc.) set as per the HAP Specs + * + * @param[in] status_fault Initial value of Status Fault characteristic + * + * @return Pointer to the characteristic object on success + * @return NULL on failure + */ +hap_char_t *hap_char_status_fault_create(uint8_t status_fault); + +/** Status Low Battery Characteristic + * + * This API creates the Status Low Battery characteristic object with other metadata + * (format, constraints, permissions, etc.) set as per the HAP Specs + * + * @param[in] status_low_battery Initial value of Status Low Battery characteristic + * + * @return Pointer to the characteristic object on success + * @return NULL on failure + */ +hap_char_t *hap_char_status_low_battery_create(uint8_t status_low_battery); + +/** Status Tampered Characteristic + * + * This API creates the Status Tampered characteristic object with other metadata + * (format, constraints, permissions, etc.) set as per the HAP Specs + * + * @param[in] status_tampered Initial value of Status Tampered characteristic + * + * @return Pointer to the characteristic object on success + * @return NULL on failure + */ +hap_char_t *hap_char_status_tampered_create(uint8_t status_tampered); + +/** Target Horizontal Tilt Angle Characteristic + * + * This API creates the Target Horizontal Tilt Angle characteristic object with other metadata + * (format, constraints, permissions, etc.) set as per the HAP Specs + * + * @param[in] targ_horiz_tilt_angle Initial value of Target Horizontal Tilt Angle characteristic + * + * @return Pointer to the characteristic object on success + * @return NULL on failure + */ +hap_char_t *hap_char_target_horizontal_tilt_angle_create(int targ_horiz_tilt_angle); + +/** Target Position Characteristic + * + * This API creates the Target Position characteristic object with other metadata + * (format, constraints, permissions, etc.) set as per the HAP Specs + * + * @param[in] targ_pos Initial value of Target Position characteristic + * + * @return Pointer to the characteristic object on success + * @return NULL on failure + */ +hap_char_t *hap_char_target_position_create(uint8_t targ_pos); + +/** Target Vertical Tilt Angle Characteristic + * + * This API creates the Target Vertical Tilt Angle characteristic object with other metadata + * (format, constraints, permissions, etc.) set as per the HAP Specs + * + * @param[in] targ_vert_tilt_angle Initial value of Target Vertical Tilt Angle characteristic + * + * @return Pointer to the characteristic object on success + * @return NULL on failure + */ +hap_char_t *hap_char_target_vertical_tilt_angle_create(int targ_vert_tilt_angle); + +/** Security System Alarm Type Characteristic + * + * This API creates the Security System Alarm Type characteristic object with other metadata + * (format, constraints, permissions, etc.) set as per the HAP Specs + * + * @param[in] security_sys_alarm_type Initial value of Security System Alarm Type characteristic + * + * @return Pointer to the characteristic object on success + * @return NULL on failure + */ +hap_char_t *hap_char_security_system_alarm_type_create(uint8_t security_sys_alarm_type); + +/** Charging State Characteristic + * + * This API creates the Charging State characteristic object with other metadata + * (format, constraints, permissions, etc.) set as per the HAP Specs + * + * @param[in] charging_state Charging State characteristic + * + * @return Pointer to the characteristic object on success + * @return NULL on failure + */ +hap_char_t *hap_char_charging_state_create(uint8_t charging_state); + +/** Carbon Monoxide Level Characteristic + * + * This API creates the Carbon Monoxide Level characteristic object with other metadata + * (format, constraints, permissions, etc.) set as per the HAP Specs + * + * @param[in] carbon_monoxide_level Initial value of Carbon Monoxide Level characteristic + * + * @return Pointer to the characteristic object on success + * @return NULL on failure + */ +hap_char_t *hap_char_carbon_monoxide_level_create(float carbon_monoxide_level); + +/** Carbon Monoxide Peak Level Characteristic + * + * This API creates the Carbon Monoxide Peak Level characteristic object with other metadata + * (format, constraints, permissions, etc.) set as per the HAP Specs + * + * @param[in] carbon_monoxide_peak_level Initial value of Carbon Monoxide Peak Level characteristic + * + * @return Pointer to the characteristic object on success + * @return NULL on failure + */ +hap_char_t *hap_char_carbon_monoxide_peak_level_create(float carbon_monoxide_peak_level); + +/** Carbon Dioxide Detected Characteristic + * + * This API creates the Carbon Dioxide Detected characteristic object with other metadata + * (format, constraints, permissions, etc.) set as per the HAP Specs + * + * @param[in] carbon_dioxide_detected Initial value of Carbon Dioxide Detected characteristic + * + * @return Pointer to the characteristic object on success + * @return NULL on failure + */ +hap_char_t *hap_char_carbon_dioxide_detected_create(uint8_t carbon_dioxide_detected); + +/** Carbon Dioxide Level Characteristic + * + * This API creates the Carbon Dioxide Level characteristic object with other metadata + * (format, constraints, permissions, etc.) set as per the HAP Specs + * + * @param[in] carbon_dioxide_level Initial value of Carbon Dioxide Level characteristic + * + * @return Pointer to the characteristic object on success + * @return NULL on failure + */ +hap_char_t *hap_char_carbon_dioxide_level_create(float carbon_dioxide_level); + +/** Carbon Dioxide Peak Level Characteristic + * + * This API creates the Carbon Dioxide Peak Level characteristic object with other metadata + * (format, constraints, permissions, etc.) set as per the HAP Specs + * + * @param[in] carbon_dioxide_peak_level Initial value of Carbon Dioxide Peak Level characteristic + * + * @return Pointer to the characteristic object on success + * @return NULL on failure + */ +hap_char_t *hap_char_carbon_dioxide_peak_level_create(float carbon_dioxide_peak_level); + +/** Carbon Monoxide Detected Characteristic + * + * This API creates the Carbon Monoxide Detected characteristic object with other metadata + * (format, constraints, permissions, etc.) set as per the HAP Specs + * + * @param[in] carbon_monoxide_detected Initial value of Carbon Monoxide Detected characteristic + * + * @return Pointer to the characteristic object on success + * @return NULL on failure + */ +hap_char_t *hap_char_carbon_monoxide_detected_create(uint8_t carbon_monoxide_detected); + +/** Contact Sensor State Characteristic + * + * This API creates the Contact Sensor State characteristic object with other metadata + * (format, constraints, permissions, etc.) set as per the HAP Specs + * + * @param[in] contact_sensor_state Initial value of Contact Sensor State characteristic + * + * @return Pointer to the characteristic object on success + * @return NULL on failure + */ +hap_char_t *hap_char_contact_sensor_state_create(uint8_t contact_sensor_state); + +/** Current Ambient Light Level Characteristic + * + * This API creates the Current Ambient Light Level characteristic object with other metadata + * (format, constraints, permissions, etc.) set as per the HAP Specs + * + * @param[in] curr_ambient_light_level Initial value of Current Ambient Light Level characteristic + * + * @return Pointer to the characteristic object on success + * @return NULL on failure + */ +hap_char_t *hap_char_current_ambient_light_level_create(float curr_ambient_light_level); + +/** Current Horizontal Tilt Angle Characteristic + * + * This API creates the Current Horizontal Tilt Angle characteristic object with other metadata + * (format, constraints, permissions, etc.) set as per the HAP Specs + * + * @param[in] curr_horiz_tilt_angle Initial value of Current Horizontal Tilt Angle characteristic + * + * @return Pointer to the characteristic object on success + * @return NULL on failure + */ +hap_char_t *hap_char_current_horizontal_tilt_angle_create(int curr_horiz_tilt_angle); + +/** Air Quality Characteristic + * + * This API creates the Air Quality characteristic object with other metadata + * (format, constraints, permissions, etc.) set as per the HAP Specs + * + * @param[in] air_quality Initial value of Air Quality characteristic + * + * @return Pointer to the characteristic object on success + * @return NULL on failure + */ +hap_char_t *hap_char_air_quality_create(uint8_t air_quality); + +/** Create Accessory Flags Characteristic + * + * This API creates the Accessory Flags characteristic object with other metadata + * (format, constraints, permissions, etc.) set as per the HAP Specs + * + * @param[in] flags Initial value of flags + * + * @return Pointer to the characteristic object on success + * @return NULL on failure + */ +hap_char_t *hap_char_accessory_flags_create(uint32_t flags); + + +/** Create Product Data Characteristic + * + * This API creates the Product Data characteristic object with other metadata + * (format, constraints, permissions, etc.) set as per the HAP Specs + * + * @param[in] product_data Value of the product data + * + * @return Pointer to the characteristic object on success + * @return NULL on failure + */ +hap_char_t *hap_char_product_data_create(hap_data_val_t *product_data); + +/** Create Lock Physical Controls Characteristic + * + * This API creates the Lock Physical Controls characteristic object with other metadata + * (format, constraints, permissions, etc.) set as per the HAP Specs + * + * @param[in] lock_physical_controls Initial value of Lock Physical Controls characteristic + * + * @return Pointer to the characteristic object on success + * @return NULL on failure + */ +hap_char_t *hap_char_lock_physical_controls_create(uint8_t lock_physical_controls); + +/** Current Air Purifier State Characteristic + * + * This API creates the Current Air Purifier State characteristic object with other metadata + * (format, constraints, permissions, etc.) set as per the HAP Specs + * + * @param[in] curr_air_purifier_state Initial value of Current Air Purifier State characteristic + * + * @return Pointer to the characteristic object on success + * @return NULL on failure + */ +hap_char_t *hap_char_current_air_purifier_state_create(uint8_t curr_air_purifier_state); + +/** Current Slat State Characteristic + * + * This API creates the Current Slat State characteristic object with other metadata + * (format, constraints, permissions, etc.) set as per the HAP Specs + * + * @param[in] curr_slat_state Initial value of Current Slat State characteristic + * + * @return Pointer to the characteristic object on success + * @return NULL on failure + */ +hap_char_t *hap_char_current_slat_state_create(uint8_t curr_slat_state); + +/** Slat Type Characteristic + * + * This API creates the Slat Type characteristic object with other metadata + * (format, constraints, permissions, etc.) set as per the HAP Specs + * + * @param[in] slat_type Value of Slat Type characteristic + * + * @return Pointer to the characteristic object on success + * @return NULL on failure + */ +hap_char_t *hap_char_slat_type_create(uint8_t slat_type); + +/** Filter Life Level Characteristic + * + * This API creates the Filter Life Level characteristic object with other metadata + * (format, constraints, permissions, etc.) set as per the HAP Specs + * + * @param[in] filter_life_level Initial value of Filter Life Level characteristic + * + * @return Pointer to the characteristic object on success + * @return NULL on failure + */ +hap_char_t *hap_char_filter_life_level_create(float filter_life_level); + +/** Current Filter Change Indication Characteristic + * + * This API creates the Filter Change Indication characteristic object with other metadata + * (format, constraints, permissions, etc.) set as per the HAP Specs + * + * @param[in] filter_change_indication Initial value of Filter Change Indication characteristic + * + * @return Pointer to the characteristic object on success + * @return NULL on failure + */ +hap_char_t *hap_char_filter_change_indication_create(uint8_t filter_change_indication); + +/** Reset Filter Indication Characteristic + * + * This API creates the Reset Filter Indication characteristic object with other metadata + * (format, constraints, permissions, etc.) set as per the HAP Specs + * + * @param[in] reset_filter_indication Initial value of Reset Filter Indication characteristic + * + * @return Pointer to the characteristic object on success + * @return NULL on failure + */ +hap_char_t *hap_char_reset_filter_indication_create(uint8_t reset_filter_indication); + +/** Target Air Purifier State Characteristic + * + * This API creates the Target Air Purifier State characteristic object with other metadata + * (format, constraints, permissions, etc.) set as per the HAP Specs + * + * @param[in] targ_air_purifier_state Initial value of Target Air Purifier State characteristic + * + * @return Pointer to the characteristic object on success + * @return NULL on failure + */ +hap_char_t *hap_char_target_air_purifier_state_create(uint8_t targ_air_purifier_state); + +/** Target Fan State Characteristic + * + * This API creates the Target Fan State characteristic object with other metadata + * (format, constraints, permissions, etc.) set as per the HAP Specs + * + * @param[in] targ_fan_state Initial value of Target Fan State characteristic + * + * @return Pointer to the characteristic object on success + * @return NULL on failure + */ +hap_char_t *hap_char_target_fan_state_create(uint8_t targ_fan_state); + +/** Current Fan State Characteristic + * + * This API creates the Current Fan State characteristic object with other metadata + * (format, constraints, permissions, etc.) set as per the HAP Specs + * + * @param[in] curr_fan_state Initial value of Current Fan State characteristic + * + * @return Pointer to the characteristic object on success + * @return NULL on failure + */ +hap_char_t *hap_char_current_fan_state_create(uint8_t curr_fan_state); + +/** Position State Characteristic + * + * This API creates the Position State characteristic object with other metadata + * (format, constraints, permissions, etc.) set as per the HAP Specs + * + * @param[in] pos_state Initial value of Position State characteristic + * + * @return Pointer to the characteristic object on success + * @return NULL on failure + */ +hap_char_t *hap_char_position_state_create(uint8_t pos_state); + +/** Programmable Switch Event Characteristic + * + * This API creates the Programmable Switch Event characteristic object with other metadata + * (format, constraints, permissions, etc.) set as per the HAP Specs + * + * @param[in] programmable_switch_event Initial value of Programmable Switch Event characteristic + * + * @return Pointer to the characteristic object on success + * @return NULL on failure + */ +hap_char_t *hap_char_programmable_switch_event_create(uint8_t programmable_switch_event); + +/** Active Characteristic + * + * This API creates the Active characteristic object with other metadata + * (format, constraints, permissions, etc.) set as per the HAP Specs + * + * @param[in] active Initial value of active characteristic + * + * @return Pointer to the characteristic object on success + * @return NULL on failure + */ +hap_char_t *hap_char_active_create(uint8_t active); + +/** Swing Mode Characteristic + * + * This API creates the Swing Mode characteristic object with other metadata + * (format, constraints, permissions, etc.) set as per the HAP Specs + * + * @param[in] swing_mode Initial value of Swing Mode characteristic + * + * @return Pointer to the characteristic object on success + * @return NULL on failure + */ +hap_char_t *hap_char_swing_mode_create(uint8_t swing_mode); + +/** Current Tilt Angle Characteristic + * + * This API creates the Current Tilt Angle characteristic object with other metadata + * (format, constraints, permissions, etc.) set as per the HAP Specs + * + * @param[in] curr_tilt_angle Initial value of Current Tilt Angle characteristic + * + * @return Pointer to the characteristic object on success + * @return NULL on failure + */ +hap_char_t *hap_char_current_tilt_angle_create(int curr_tilt_angle); + +/** Target Tilt Angle Characteristic + * + * This API creates the Target Tilt Angle characteristic object with other metadata + * (format, constraints, permissions, etc.) set as per the HAP Specs + * + * @param[in] targ_tilt_angle Initial value of Target Tilt Angle characteristic + * + * @return Pointer to the characteristic object on success + * @return NULL on failure + */ + hap_char_t *hap_char_target_tilt_angle_create(int targ_tilt_angle); + +/** Ozone Density Characteristic + * + * This API creates the Ozone Density characteristic object with other metadata + * (format, constraints, permissions, etc.) set as per the HAP Specs + * + * @param[in] ozone_density Initial value of Ozone Density characteristic + * + * @return Pointer to the characteristic object on success + * @return NULL on failure + */ +hap_char_t *hap_char_ozone_density_create(float ozone_density); + +/** Nitrogen Dioxide Density Characteristic + * + * This API creates the Nitrogen Dioxide Density characteristic object with other metadata + * (format, constraints, permissions, etc.) set as per the HAP Specs + * + * @param[in] nitrogen_dioxide_density Initial value of Nitrogen Dioxide Density characteristic + * + * @return Pointer to the characteristic object on success + * @return NULL on failure + */ +hap_char_t *hap_char_nitrogen_dioxide_density_create(float nitrogen_dioxide_density); + +/** Sulphur Dioxide Density Characteristic + * + * This API creates the Sulphur Dioxide Density characteristic object with other metadata + * (format, constraints, permissions, etc.) set as per the HAP Specs + * + * @param[in] sulphur_dioxide_density Initial value of Sulphur Dioxide Density characteristic + * + * @return Pointer to the characteristic object on success + * @return NULL on failure + */ +hap_char_t *hap_char_sulphur_dioxide_density_create(float sulphur_dioxide_density); + +/** PM2.5 Density Characteristic + * + * This API creates the PM2.5 Density characteristic object with other metadata + * (format, constraints, permissions, etc.) set as per the HAP Specs + * + * @param[in] pm_2_5_density Initial value of PM2.5 Density characteristic + * + * @return Pointer to the characteristic object on success + * @return NULL on failure + */ +hap_char_t *hap_char_pm_2_5_density_create(float pm_2_5_density); + +/** PM10 Density Characteristic + * + * This API creates the PM10 Density characteristic object with other metadata + * (format, constraints, permissions, etc.) set as per the HAP Specs + * + * @param[in] pm_10_density Initial value of PM10 Density characteristic + * + * @return Pointer to the characteristic object on success + * @return NULL on failure + */ +hap_char_t *hap_char_pm_10_density_create(float pm_10_density); + +/** VOC Density Characteristic + * + * This API creates the VOC Density characteristic object with other metadata + * (format, constraints, permissions, etc.) set as per the HAP Specs + * + * @param[in] voc_density Initial value of VOC Density characteristic + * + * @return Pointer to the characteristic object on success + * @return NULL on failure + */ +hap_char_t *hap_char_voc_density_create(float voc_density); + +/** Create Service Label Index Characteristic + * + * This API creates the Service Label Index characteristic object with other metadata + * (format, constraints, permissions, etc.) set as per the HAP Specs + * + * @param[in] service_label_index Initial value of Service Label Index characteristic + * + * @return Pointer to the characteristic object on success + * @return NULL on failure + */ +hap_char_t *hap_char_service_label_index_create(uint8_t service_label_index); + +/** Create Service Label Namespace Characteristic + * + * This API creates the Service Label Namespace characteristic object with other metadata + * (format, constraints, permissions, etc.) set as per the HAP Specs + * + * @param[in] service_label_namespace Initial value of Service Label Namespace characteristic + * + * @return Pointer to the characteristic object on success + * @return NULL on failure + */ +hap_char_t *hap_char_service_label_namespace_create(uint8_t service_label_namespace); + +/** Create Color Temperature Characteristic + * + * This API creates the color temperature characteristic object with other metadata + * (format, constraints, permissions, etc.) set as per the HAP Specs + * + * @param[in] color_temp Initial value of Color Temperature + * + * @return Pointer to the characteristic object on success + * @return NULL on failure + */ +hap_char_t *hap_char_color_temperature_create(uint32_t color_temp); + +/** Create Curr Heater Cooler State Characteristic + * + * This API creates the Curr Heater Cooler State characteristic object with other metadata + * (format, constraints, permissions, etc.) set as per the HAP Specs + * + * @param[in] curr_heater_cooler_state Initial value of Curr Heater Cooler State + * + * @return Pointer to the characteristic object on success + * @return NULL on failure + */ +hap_char_t *hap_char_current_heater_cooler_state_create(uint8_t curr_heater_cooler_state); + +/** Create Target Heater Cooler State Characteristic + * + * This API creates the Target Heater Cooler State characteristic object with other metadata + * (format, constraints, permissions, etc.) set as per the HAP Specs + * + * @param[in] targ_heater_cooler_state Initial value of Target Heater Cooler State + * + * @return Pointer to the characteristic object on success + * @return NULL on failure + */ +hap_char_t *hap_char_target_heater_cooler_state_create(uint8_t targ_heater_cooler_state); + +/** Create Current Humidifier Dehumidifier State Characteristic + * + * This API creates the Current Humidifier Dehumidifier State characteristic object with other metadata + * (format, constraints, permissions, etc.) set as per the HAP Specs + * + * @param[in] curr_humidifier_dehumidifier_state Initial value of Current Humidifier Dehumidifier State characteristic + * + * @return Pointer to the characteristic object on success + * @return NULL on failure + */ +hap_char_t *hap_char_current_humidifier_dehumidifier_state_create(uint8_t curr_humidifier_dehumidifier_state); + +/** Create Target Humidifier Dehumidifier State Characteristic + * + * This API creates the Target Humidifier Dehumidifier State characteristic object with other metadata + * (format, constraints, permissions, etc.) set as per the HAP Specs + * + * @param[in] targ_humidifier_dehumidifier_state Initial value of Target Humidifier Dehumidifier State characteristic + * + * @return Pointer to the characteristic object on success + * @return NULL on failure + */ +hap_char_t *hap_char_target_humidifier_dehumidifier_state_create(uint8_t targ_humidifier_dehumidifier_state); + +/** Create Water Level Characteristic + * + * This API creates the Water Level characteristic object with other metadata + * (format, constraints, permissions, etc.) set as per the HAP Specs + * + * @param[in] water_level Initial value of Water Level characteristic + * + * @return Pointer to the characteristic object on success + * @return NULL on failure + */ +hap_char_t *hap_char_water_level_create(float water_level); + +/** Create Relative Humidity Dehumidifier Threshold Characteristic + * + * This API creates the Relative Humidity Dehumidifier Threshold characteristic object with other metadata + * (format, constraints, permissions, etc.) set as per the HAP Specs + * + * @param[in] rel_humidity_dehumidifier_threshold Initial value of Relative Humidity Dehumidifier Threshold characteristic + * + * @return Pointer to the characteristic object on success + * @return NULL on failure + */ +hap_char_t *hap_char_relative_humidity_dehumidifier_threshold_create(float rel_humidity_dehumidifier_threshold); + +/** Create Relative Humidity Humidifier Threshold Characteristic + * + * This API creates the Relative Humidity Humidifier Threshold characteristic object with other metadata + * (format, constraints, permissions, etc.) set as per the HAP Specs + * + * @param[in] rel_humidity_humidifier_threshold Initial value of Relative Humidity Humidifier Threshold characteristic + * + * @return Pointer to the characteristic object on success + * @return NULL on failure + */ +hap_char_t *hap_char_relative_humidity_humidifier_threshold_create(float rel_humidity_humidifier_threshold); + +/** Create Program Mode Characteristic + * + * This API creates the Program Mode characteristic object with other metadata + * (format, constraints, permissions, etc.) set as per the HAP Specs + * + * @param[in] prog_mode Initial value of Program Mode characteristic + * + * @return Pointer to the characteristic object on success + * @return NULL on failure + */ +hap_char_t *hap_char_program_mode_create(uint8_t prog_mode); + +/** Create In Use Characteristic + * + * This API creates the In Use characteristic object with other metadata + * (format, constraints, permissions, etc.) set as per the HAP Specs + * + * @param[in] in_use Initial value of In Use characteristic + * + * @return Pointer to the characteristic object on success + * @return NULL on failure + */ +hap_char_t *hap_char_in_use_create(uint8_t in_use); + +/** Create Set Duration Characteristic + * + * This API creates the Set Duration characteristic object with other metadata + * (format, constraints, permissions, etc.) set as per the HAP Specs + * + * @param[in] set_duration Initial value of Set Duration characteristic + * + * @return Pointer to the characteristic object on success + * @return NULL on failure + */ +hap_char_t *hap_char_set_duration_create(uint32_t set_duration); + +/** Create Remaining Duration Characteristic + * + * This API creates the Remaining Duration characteristic object with other metadata + * (format, constraints, permissions, etc.) set as per the HAP Specs + * + * @param[in] remaining_duration Initial value of Remaining Duration characteristic + * + * @return Pointer to the characteristic object on success + * @return NULL on failure + */ +hap_char_t *hap_char_remaining_duration_create(uint32_t remaining_duration); + +/** Create Valve Type Characteristic + * + * This API creates the Valve Type characteristic object with other metadata + * (format, constraints, permissions, etc.) set as per the HAP Specs + * + * @param[in] valve_type Initial value of Valve Type characteristic + * + * @return Pointer to the characteristic object on success + * @return NULL on failure + */ +hap_char_t *hap_char_valve_type_create(uint8_t valve_type); + +/** Create Is Configured Characteristic + * + * This API creates the Is Configured characteristic object with other metadata + * (format, constraints, permissions, etc.) set as per the HAP Specs + * + * @param[in] is_configured Initial value of Is Configured characteristic + * + * @return Pointer to the characteristic object on success + * @return NULL on failure + */ +hap_char_t *hap_char_is_configured_create(uint8_t is_configured); + +/** Status Jammed Characteristic + * + * This API creates the Status Jammed characteristic object with other metadata + * (format, constraints, permissions, etc.) set as per the HAP Specs + * + * @param[in] status_jammed Initial value of Status Jammed characteristic + * + * @return Pointer to the characteristic object on success + * @return NULL on failure + */ +hap_char_t *hap_char_status_jammed_create(uint8_t status_jammed); + +/** Administrator Only Access Characteristic + * + * This API creates the Administrator Only Access characteristic object with other metadata + * (format, constraints, permissions, etc.) set as per the HAP Specs + * + * @param[in] administrator_only_access Initial value of Administrator Only Access characteristic + * + * @return Pointer to the characteristic object on success + * @return NULL on failure + */ +hap_char_t *hap_char_administrator_only_access_create(bool administrator_only_access); + +/** Lock Control Point Characteristic + * + * This API creates the Lock Control Point characteristic object with other metadata + * (format, constraints, permissions, etc.) set as per the HAP Specs + * + * @param[in] lock_control_point Initial value of Lock Control Point characteristic + * + * @return Pointer to the characteristic object on success + * @return NULL on failure + */ +hap_char_t *hap_char_lock_control_point_create(hap_tlv8_val_t *lock_control_point); + +/** Lock Last Known Action Characteristic + * + * This API creates the Lock Last Known Action characteristic object with other metadata + * (format, constraints, permissions, etc.) set as per the HAP Specs + * + * @param[in] lock_last_known_action Initial value of Lock Last Known Action characteristic + * + * @return Pointer to the characteristic object on success + * @return NULL on failure + */ +hap_char_t *hap_char_lock_last_known_action_create(uint8_t lock_last_known_action); + +/** Lock Management Auto Security Timeout Characteristic + * + * This API creates the Lock Management Auto Security Timeout characteristic object with other metadata + * (format, constraints, permissions, etc.) set as per the HAP Specs + * + * @param[in] lock_management_auto_security_timeout Initial value of Lock Management Auto Security Timeout characteristic + * + * @return Pointer to the characteristic object on success + * @return NULL on failure + */ +hap_char_t *hap_char_lock_management_auto_security_timeout_create(uint32_t lock_management_auto_security_timeout); + +/** Logs Characteristic + * + * This API creates the Logs characteristic object with other metadata + * (format, constraints, permissions, etc.) set as per the HAP Specs + * + * @param[in] logs Initial value of Logs characteristic + * + * @return Pointer to the characteristic object on success + * @return NULL on failure + */ +hap_char_t *hap_char_logs_create(hap_tlv8_val_t *logs); + +/** Air Particulate Density Characteristic + * + * This API creates the Air Particulate Density characteristic object with other metadata + * (format, constraints, permissions, etc.) set as per the HAP Specs + * + * @param[in] air_particulate_density Initial value of Air Particulate Density characteristic + * + * @return Pointer to the characteristic object on success + * @return NULL on failure + */ +hap_char_t *hap_char_air_particulate_density_create(float air_particulate_density); + +/** Air Particulate Size Characteristic + * + * This API creates the Air Particulate Size characteristic object with other metadata + * (format, constraints, permissions, etc.) set as per the HAP Specs + * + * @param[in] air_particulate_size Initial value of Air Particulate Size characteristic + * + * @return Pointer to the characteristic object on success + * @return NULL on failure + */ +hap_char_t *hap_char_air_particulate_size_create(uint8_t air_particulate_size); + +#ifdef __cplusplus +} +#endif + +#endif /* _HAP_APPLE_CHARS_H_ */ diff --git a/lib/libesp32_div/ESP32-HomeKit/src/hap_apple_servs.c b/lib/libesp32_div/ESP32-HomeKit/src/hap_apple_servs.c new file mode 100644 index 000000000..b8783695f --- /dev/null +++ b/lib/libesp32_div/ESP32-HomeKit/src/hap_apple_servs.c @@ -0,0 +1,706 @@ +/* + * ESPRESSIF MIT License + * + * Copyright (c) 2020 + * + * Permission is hereby granted for use on ESPRESSIF SYSTEMS products only, in which case, + * it is 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 +#include +#include + +hap_serv_t *hap_serv_accessory_information_create(hap_acc_cfg_t *cfg) +{ + hap_serv_t *hs = hap_serv_create(HAP_SERV_UUID_ACCESSORY_INFORMATION); + if (!hs) { + return NULL; + } + if (hap_serv_add_char(hs, hap_char_name_create(cfg->name)) != HAP_SUCCESS) { + goto err; + } + + if (hap_serv_add_char(hs, hap_char_model_create(cfg->model)) != HAP_SUCCESS) { + goto err; + } + + if (hap_serv_add_char(hs, hap_char_manufacturer_create(cfg->manufacturer)) != HAP_SUCCESS) { + goto err; + } + + if (hap_serv_add_char(hs, hap_char_serial_number_create(cfg->serial_num)) != HAP_SUCCESS) { + goto err; + } + + if (hap_serv_add_char(hs, hap_char_firmware_revision_create(cfg->fw_rev)) != HAP_SUCCESS) { + goto err; + } + + if (hap_serv_add_char(hs, hap_char_identify_create()) != HAP_SUCCESS) { + goto err; + } + + if (cfg->hw_rev) { + if (hap_serv_add_char(hs, hap_char_hardware_revision_create(cfg->hw_rev)) != HAP_SUCCESS) { + goto err; + } + } + + return hs; +err: + hap_serv_delete(hs); + return NULL; +} + +hap_serv_t *hap_serv_protocol_information_create(char *version) +{ + hap_serv_t *hs = hap_serv_create(HAP_SERV_UUID_PROTOCOL_INFORMATION); + if (!hs) { + return NULL; + } + if (hap_serv_add_char(hs, hap_char_version_create(version)) != HAP_SUCCESS) { + goto err; + } + return hs; +err: + hap_serv_delete(hs); + return NULL; +} + +hap_serv_t *hap_serv_fan_create(bool on) +{ + hap_serv_t *hs = hap_serv_create(HAP_SERV_UUID_FAN); + if (!hs) { + return NULL; + } + if (hap_serv_add_char(hs, hap_char_on_create(on)) != HAP_SUCCESS) { + goto err; + } + return hs; +err: + hap_serv_delete(hs); + return NULL; +} + +hap_serv_t *hap_serv_garage_door_opener_create(uint8_t curr_door_state, uint8_t targ_door_state, bool obstr_detect) +{ + hap_serv_t *hs = hap_serv_create(HAP_SERV_UUID_GARAGE_DOOR_OPENER); + if (!hs) { + return NULL; + } + if (hap_serv_add_char(hs, hap_char_current_door_state_create(curr_door_state)) != HAP_SUCCESS) { + goto err; + } + if (hap_serv_add_char(hs, hap_char_target_door_state_create(targ_door_state)) != HAP_SUCCESS) { + goto err; + } + if (hap_serv_add_char(hs, hap_char_obstruction_detect_create(obstr_detect)) != HAP_SUCCESS) { + goto err; + } + return hs; +err: + hap_serv_delete(hs); + return NULL; +} + +hap_serv_t *hap_serv_lightbulb_create(bool on) +{ + hap_serv_t *hs = hap_serv_create(HAP_SERV_UUID_LIGHTBULB); + if (!hs) { + return NULL; + } + if (hap_serv_add_char(hs, hap_char_on_create(on)) != HAP_SUCCESS) { + goto err; + } + return hs; +err: + hap_serv_delete(hs); + return NULL; +} + +hap_serv_t *hap_serv_lock_management_create(hap_tlv8_val_t *lock_control_point, char * version) +{ + hap_serv_t *hs = hap_serv_create(HAP_SERV_UUID_LOCK_MANAGEMENT); + if (!hs) { + return NULL; + } + if (hap_serv_add_char(hs, hap_char_lock_control_point_create(lock_control_point)) != HAP_SUCCESS) { + goto err; + } + if (hap_serv_add_char(hs, hap_char_version_create(version)) != HAP_SUCCESS) { + goto err; + } + return hs; +err: + hap_serv_delete(hs); + return NULL; +} + +hap_serv_t *hap_serv_lock_mechanism_create(uint8_t lock_curr_state, uint8_t lock_targ_state) +{ + hap_serv_t *hs = hap_serv_create(HAP_SERV_UUID_LOCK_MECHANISM); + if (!hs) { + return NULL; + } + if (hap_serv_add_char(hs, hap_char_lock_current_state_create(lock_curr_state)) != HAP_SUCCESS) { + goto err; + } + if (hap_serv_add_char(hs, hap_char_lock_target_state_create(lock_targ_state)) != HAP_SUCCESS) { + goto err; + } + return hs; +err: + hap_serv_delete(hs); + return NULL; +} + +hap_serv_t *hap_serv_outlet_create(bool on, bool outlet_in_use) +{ + hap_serv_t *hs = hap_serv_create(HAP_SERV_UUID_OUTLET); + if (!hs) { + return NULL; + } + if (hap_serv_add_char(hs, hap_char_on_create(on)) != HAP_SUCCESS) { + goto err; + } + if (hap_serv_add_char(hs, hap_char_outlet_in_use_create(outlet_in_use)) != HAP_SUCCESS) { + goto err; + } + return hs; +err: + hap_serv_delete(hs); + return NULL; +} + +hap_serv_t *hap_serv_switch_create(bool on) +{ + hap_serv_t *hs = hap_serv_create(HAP_SERV_UUID_SWITCH); + if (!hs) { + return NULL; + } + if (hap_serv_add_char(hs, hap_char_on_create(on)) != HAP_SUCCESS) { + goto err; + } + return hs; +err: + hap_serv_delete(hs); + return NULL; +} + +hap_serv_t *hap_serv_thermostat_create(uint8_t curr_heating_cooling_state, uint8_t targ_heating_cooling_state, float curr_temp, + float targ_temp, uint8_t temp_disp_units) +{ + hap_serv_t *hs = hap_serv_create(HAP_SERV_UUID_THERMOSTAT); + if (!hs) { + return NULL; + } + if (hap_serv_add_char(hs, hap_char_current_heating_cooling_state_create(curr_heating_cooling_state)) != HAP_SUCCESS) { + goto err; + } + if (hap_serv_add_char(hs, hap_char_target_heating_cooling_state_create(targ_heating_cooling_state)) != HAP_SUCCESS) { + goto err; + } + if (hap_serv_add_char(hs, hap_char_current_temperature_create(curr_temp)) != HAP_SUCCESS) { + goto err; + } + if (hap_serv_add_char(hs, hap_char_target_temperature_create(targ_temp)) != HAP_SUCCESS) { + goto err; + } + if (hap_serv_add_char(hs, hap_char_temperature_display_units_create(temp_disp_units)) != HAP_SUCCESS) { + goto err; + } + return hs; +err: + hap_serv_delete(hs); + return NULL; +} + +hap_serv_t *hap_serv_air_quality_sensor_create(uint8_t air_quality) +{ + hap_serv_t *hs = hap_serv_create(HAP_SERV_UUID_AIR_QUALITY_SENSOR); + if (!hs) { + return NULL; + } + if (hap_serv_add_char(hs, hap_char_air_quality_create(air_quality)) != HAP_SUCCESS) { + goto err; + } + return hs; +err: + hap_serv_delete(hs); + return NULL; +} + +hap_serv_t *hap_serv_security_system_create(uint8_t security_sys_curr_state, uint8_t security_sys_targ_state) +{ + hap_serv_t *hs = hap_serv_create(HAP_SERV_UUID_SECURITY_SYSTEM); + if (!hs) { + return NULL; + } + if (hap_serv_add_char(hs, hap_char_security_system_current_state_create(security_sys_curr_state)) != HAP_SUCCESS) { + goto err; + } + if (hap_serv_add_char(hs, hap_char_security_system_target_state_create(security_sys_targ_state)) != HAP_SUCCESS) { + goto err; + } + return hs; +err: + hap_serv_delete(hs); + return NULL; +} + +hap_serv_t *hap_serv_carbon_monoxide_sensor_create(uint8_t carbon_monoxide_detected) +{ + hap_serv_t *hs = hap_serv_create(HAP_SERV_UUID_CARBON_MONOXIDE_SENSOR); + if (!hs) { + return NULL; + } + if (hap_serv_add_char(hs, hap_char_carbon_monoxide_detected_create(carbon_monoxide_detected)) != HAP_SUCCESS) { + goto err; + } + return hs; +err: + hap_serv_delete(hs); + return NULL; +} + +hap_serv_t *hap_serv_contact_sensor_create(uint8_t contact_sensor_state) +{ + hap_serv_t *hs = hap_serv_create(HAP_SERV_UUID_CONTACT_SENSOR); + if (!hs) { + return NULL; + } + if (hap_serv_add_char(hs, hap_char_contact_sensor_state_create(contact_sensor_state)) != HAP_SUCCESS) { + goto err; + } + return hs; +err: + hap_serv_delete(hs); + return NULL; +} + +hap_serv_t *hap_serv_door_create(uint8_t curr_pos, uint8_t targ_pos, uint8_t pos_state) +{ + hap_serv_t *hs = hap_serv_create(HAP_SERV_UUID_DOOR); + if (!hs) { + return NULL; + } + if (hap_serv_add_char(hs, hap_char_current_position_create(curr_pos)) != HAP_SUCCESS) { + goto err; + } + if (hap_serv_add_char(hs, hap_char_target_position_create(targ_pos)) != HAP_SUCCESS) { + goto err; + } + if (hap_serv_add_char(hs, hap_char_position_state_create(pos_state)) != HAP_SUCCESS) { + goto err; + } + return hs; +err: + hap_serv_delete(hs); + return NULL; +} + +hap_serv_t *hap_serv_humidity_sensor_create(float curr_rel_humidity) +{ + hap_serv_t *hs = hap_serv_create(HAP_SERV_UUID_HUMIDITY_SENSOR); + if (!hs) { + return NULL; + } + if (hap_serv_add_char(hs, hap_char_current_relative_humidity_create(curr_rel_humidity)) != HAP_SUCCESS) { + goto err; + } + return hs; +err: + hap_serv_delete(hs); + return NULL; +} + +hap_serv_t *hap_serv_leak_sensor_create(uint8_t leak_detected) +{ + hap_serv_t *hs = hap_serv_create(HAP_SERV_UUID_LEAK_SENSOR); + if (!hs) { + return NULL; + } + if (hap_serv_add_char(hs, hap_char_leak_detected_create(leak_detected)) != HAP_SUCCESS) { + goto err; + } + return hs; +err: + hap_serv_delete(hs); + return NULL; +} + +hap_serv_t *hap_serv_light_sensor_create(float curr_ambient_light_level) +{ + hap_serv_t *hs = hap_serv_create(HAP_SERV_UUID_LIGHT_SENSOR); + if (!hs) { + return NULL; + } + if (hap_serv_add_char(hs, hap_char_current_ambient_light_level_create(curr_ambient_light_level)) != HAP_SUCCESS) { + goto err; + } + return hs; +err: + hap_serv_delete(hs); + return NULL; +} + +hap_serv_t *hap_serv_motion_sensor_create(bool motion_detected) +{ + hap_serv_t *hs = hap_serv_create(HAP_SERV_UUID_MOTION_SENSOR); + if (!hs) { + return NULL; + } + if (hap_serv_add_char(hs, hap_char_motion_detected_create(motion_detected)) != HAP_SUCCESS) { + goto err; + } + return hs; +err: + hap_serv_delete(hs); + return NULL; +} + +hap_serv_t *hap_serv_occupancy_sensor_create(uint8_t occupancy_detected) +{ + hap_serv_t *hs = hap_serv_create(HAP_SERV_UUID_OCCUPANCY_SENSOR); + if (!hs) { + return NULL; + } + if (hap_serv_add_char(hs, hap_char_occupancy_detected_create(occupancy_detected)) != HAP_SUCCESS) { + goto err; + } + return hs; +err: + hap_serv_delete(hs); + return NULL; +} + +hap_serv_t *hap_serv_smoke_sensor_create(uint8_t smoke_detected) +{ + hap_serv_t *hs = hap_serv_create(HAP_SERV_UUID_SMOKE_SENSOR); + if (!hs) { + return NULL; + } + if (hap_serv_add_char(hs, hap_char_smoke_detected_create(smoke_detected)) != HAP_SUCCESS) { + goto err; + } + return hs; +err: + hap_serv_delete(hs); + return NULL; +} + +hap_serv_t *hap_serv_stateless_programmable_switch_create(uint8_t programmable_switch_event) +{ + hap_serv_t *hs = hap_serv_create(HAP_SERV_UUID_STATLESS_PROGRAMMABLE_SWITCH); + if (!hs) { + return NULL; + } + if (hap_serv_add_char(hs, hap_char_programmable_switch_event_create(programmable_switch_event)) != HAP_SUCCESS) { + goto err; + } + return hs; +err: + hap_serv_delete(hs); + return NULL; +} + +hap_serv_t *hap_serv_temperature_sensor_create(float curr_temp) +{ + hap_serv_t *hs = hap_serv_create(HAP_SERV_UUID_TEMPERATURE_SENSOR); + if (!hs) { + return NULL; + } + if (hap_serv_add_char(hs, hap_char_current_temperature_create(curr_temp)) != HAP_SUCCESS) { + goto err; + } + return hs; +err: + hap_serv_delete(hs); + return NULL; +} + +hap_serv_t *hap_serv_window_create(uint8_t curr_pos, uint8_t targ_pos, uint8_t pos_state) +{ + hap_serv_t *hs = hap_serv_create(HAP_SERV_UUID_WINDOW); + if (!hs) { + return NULL; + } + if (hap_serv_add_char(hs, hap_char_current_position_create(curr_pos)) != HAP_SUCCESS) { + goto err; + } + if (hap_serv_add_char(hs, hap_char_target_position_create(targ_pos)) != HAP_SUCCESS) { + goto err; + } + if (hap_serv_add_char(hs, hap_char_position_state_create(pos_state)) != HAP_SUCCESS) { + goto err; + } + return hs; +err: + hap_serv_delete(hs); + return NULL; +} + +hap_serv_t *hap_serv_window_covering_create(uint8_t targ_pos, uint8_t curr_pos, uint8_t pos_state) +{ + hap_serv_t *hs = hap_serv_create(HAP_SERV_UUID_WINDOW_COVERING); + if (!hs) { + return NULL; + } + if (hap_serv_add_char(hs, hap_char_target_position_create(targ_pos)) != HAP_SUCCESS) { + goto err; + } + if (hap_serv_add_char(hs, hap_char_current_position_create(curr_pos)) != HAP_SUCCESS) { + goto err; + } + if (hap_serv_add_char(hs, hap_char_position_state_create(pos_state)) != HAP_SUCCESS) { + goto err; + } + return hs; +err: + hap_serv_delete(hs); + return NULL; +} + +hap_serv_t *hap_serv_battery_service_create(uint8_t battery_level, uint8_t charging_state, uint8_t status_low_battery) +{ + hap_serv_t *hs = hap_serv_create(HAP_SERV_UUID_BATTERY_SERVICE); + if (!hs) { + return NULL; + } + if (hap_serv_add_char(hs, hap_char_battery_level_create(battery_level)) != HAP_SUCCESS) { + goto err; + } + if (hap_serv_add_char(hs, hap_char_charging_state_create(charging_state)) != HAP_SUCCESS) { + goto err; + } + if (hap_serv_add_char(hs, hap_char_status_low_battery_create(status_low_battery)) != HAP_SUCCESS) { + goto err; + } + return hs; +err: + hap_serv_delete(hs); + return NULL; +} + +hap_serv_t *hap_serv_carbon_dioxide_sensor_create(uint8_t carbon_dioxide_detected) +{ + hap_serv_t *hs = hap_serv_create(HAP_SERV_UUID_CARBON_DIOXIDE_SENSOR); + if (!hs) { + return NULL; + } + if (hap_serv_add_char(hs, hap_char_carbon_dioxide_detected_create(carbon_dioxide_detected)) != HAP_SUCCESS) { + goto err; + } + return hs; +err: + hap_serv_delete(hs); + return NULL; +} + +hap_serv_t *hap_serv_fan_v2_create(uint8_t active) +{ + hap_serv_t *hs = hap_serv_create(HAP_SERV_UUID_FAN_V2); + if (!hs) { + return NULL; + } + if (hap_serv_add_char(hs, hap_char_active_create(active)) != HAP_SUCCESS) { + goto err; + } + return hs; +err: + hap_serv_delete(hs); + return NULL; +} + +hap_serv_t *hap_serv_slat_create(uint8_t curr_slat_state, uint8_t slat_type) +{ + hap_serv_t *hs = hap_serv_create(HAP_SERV_UUID_SLAT); + if (!hs) { + return NULL; + } + if (hap_serv_add_char(hs, hap_char_current_slat_state_create(curr_slat_state)) != HAP_SUCCESS) { + goto err; + } + if (hap_serv_add_char(hs, hap_char_slat_type_create(slat_type)) != HAP_SUCCESS) { + goto err; + } + return hs; +err: + hap_serv_delete(hs); + return NULL; +} + +hap_serv_t *hap_serv_filter_maintenance_create(uint8_t filter_change_indication) +{ + hap_serv_t *hs = hap_serv_create(HAP_SERV_UUID_FILTER_MAINTENANCE); + if (!hs) { + return NULL; + } + if (hap_serv_add_char(hs, hap_char_filter_change_indication_create(filter_change_indication)) != HAP_SUCCESS) { + goto err; + } + return hs; +err: + hap_serv_delete(hs); + return NULL; +} + +hap_serv_t *hap_serv_air_purifier_create(uint8_t active, uint8_t curr_air_purifier_state, uint8_t + targ_air_purifier_state) +{ + hap_serv_t *hs = hap_serv_create(HAP_SERV_UUID_AIR_PURIFIER); + if (!hs) { + return NULL; + } + if (hap_serv_add_char(hs, hap_char_active_create(active)) != HAP_SUCCESS) { + goto err; + } + if (hap_serv_add_char(hs, hap_char_current_air_purifier_state_create(curr_air_purifier_state)) != HAP_SUCCESS) { + goto err; + } + if (hap_serv_add_char(hs, hap_char_target_air_purifier_state_create(targ_air_purifier_state)) != HAP_SUCCESS) { + goto err; + } + return hs; +err: + hap_serv_delete(hs); + return NULL; +} + +hap_serv_t *hap_serv_heater_cooler_create(uint8_t active, float curr_temp, uint8_t curr_heater_cooler_state, uint8_t targ_heater_cooler_state) +{ + hap_serv_t *hs = hap_serv_create(HAP_SERV_UUID_HEATER_COOLER); + if (!hs) { + return NULL; + } + if (hap_serv_add_char(hs, hap_char_active_create(active)) != HAP_SUCCESS) { + goto err; + } + if (hap_serv_add_char(hs, hap_char_current_temperature_create(curr_temp)) != HAP_SUCCESS) { + goto err; + } + if (hap_serv_add_char(hs, hap_char_current_heater_cooler_state_create(curr_heater_cooler_state)) != HAP_SUCCESS) { + goto err; + } + if (hap_serv_add_char(hs, hap_char_target_heater_cooler_state_create(targ_heater_cooler_state)) != HAP_SUCCESS) { + goto err; + } + + return hs; +err: + hap_serv_delete(hs); + return NULL; +} + +hap_serv_t *hap_serv_humidifier_dehumidifier_create(uint8_t active, float curr_rel_humidity, uint8_t + curr_humid_dehumid_state, uint8_t targ_humid_dehumid_state) +{ + hap_serv_t *hs = hap_serv_create(HAP_SERV_UUID_HUMIDIFIER_DEHUMIDIFIER); + if (!hs) { + return NULL; + } + if (hap_serv_add_char(hs, hap_char_active_create(active)) != HAP_SUCCESS) { + goto err; + } + if (hap_serv_add_char(hs, hap_char_current_relative_humidity_create(curr_rel_humidity)) != HAP_SUCCESS) { + goto err; + } + if (hap_serv_add_char(hs, hap_char_current_humidifier_dehumidifier_state_create(curr_humid_dehumid_state)) != HAP_SUCCESS) { + goto err; + } + if (hap_serv_add_char(hs, hap_char_target_humidifier_dehumidifier_state_create(targ_humid_dehumid_state)) != HAP_SUCCESS) { + goto err; + } + return hs; +err: + hap_serv_delete(hs); + return NULL; +} + +hap_serv_t *hap_serv_service_label_create(uint8_t service_label_namespace) +{ + hap_serv_t *hs = hap_serv_create(HAP_SERV_UUID_SERVICE_LABEL); + if (!hs) { + return NULL; + } + if (hap_serv_add_char(hs, hap_char_service_label_namespace_create(service_label_namespace)) != HAP_SUCCESS) { + goto err; + } + return hs; +err: + hap_serv_delete(hs); + return NULL; +} + +hap_serv_t *hap_serv_irrigation_system_create(uint8_t active, uint8_t prog_mode, uint8_t in_use) +{ + hap_serv_t *hs = hap_serv_create(HAP_SERV_UUID_IRRIGATION_SYSTEM); + if (!hs) { + return NULL; + } + if (hap_serv_add_char(hs, hap_char_active_create(active)) != HAP_SUCCESS) { + goto err; + } + if (hap_serv_add_char(hs, hap_char_program_mode_create(prog_mode)) != HAP_SUCCESS) { + goto err; + } + if (hap_serv_add_char(hs, hap_char_in_use_create(in_use)) != HAP_SUCCESS) { + goto err; + } + return hs; +err: + hap_serv_delete(hs); + return NULL; +} + +hap_serv_t *hap_serv_valve_create(uint8_t active, uint8_t in_use, uint8_t valve_type) +{ + hap_serv_t *hs = hap_serv_create(HAP_SERV_UUID_VALVE); + if (!hs) { + return NULL; + } + if (hap_serv_add_char(hs, hap_char_active_create(active)) != HAP_SUCCESS) { + goto err; + } + if (hap_serv_add_char(hs, hap_char_in_use_create(in_use)) != HAP_SUCCESS) { + goto err; + } + if (hap_serv_add_char(hs, hap_char_valve_type_create(valve_type)) != HAP_SUCCESS) { + goto err; + } + return hs; +err: + hap_serv_delete(hs); + return NULL; +} + +hap_serv_t *hap_serv_faucet_create(uint8_t active) +{ + hap_serv_t *hs = hap_serv_create(HAP_SERV_UUID_FAUCET); + if (!hs) { + return NULL; + } + if (hap_serv_add_char(hs, hap_char_active_create(active)) != HAP_SUCCESS) { + goto err; + } + return hs; +err: + hap_serv_delete(hs); + return NULL; +} + diff --git a/lib/libesp32_div/ESP32-HomeKit/src/hap_apple_servs.h b/lib/libesp32_div/ESP32-HomeKit/src/hap_apple_servs.h new file mode 100644 index 000000000..e3f6101f9 --- /dev/null +++ b/lib/libesp32_div/ESP32-HomeKit/src/hap_apple_servs.h @@ -0,0 +1,560 @@ +/* + * ESPRESSIF MIT License + * + * Copyright (c) 2020 + * + * Permission is hereby granted for use on ESPRESSIF SYSTEMS products only, in which case, + * it is 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. + * + */ +/** HAP Apple Services + * + * This offers helper APIs for all the standard HomeKit Services defined by Apple + */ +#ifndef _HAP_APPLE_SERVS_H_ +#define _HAP_APPLE_SERVS_H_ + +#include +#include + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define HAP_SERV_UUID_ACCESSORY_INFORMATION "3E" +#define HAP_SERV_UUID_PROTOCOL_INFORMATION "A2" +#define HAP_SERV_UUID_FAN "40" +#define HAP_SERV_UUID_GARAGE_DOOR_OPENER "41" +#define HAP_SERV_UUID_LIGHTBULB "43" +#define HAP_SERV_UUID_LOCK_MANAGEMENT "44" +#define HAP_SERV_UUID_LOCK_MECHANISM "45" +#define HAP_SERV_UUID_SWITCH "49" +#define HAP_SERV_UUID_OUTLET "47" +#define HAP_SERV_UUID_THERMOSTAT "4A" +#define HAP_SERV_UUID_AIR_QUALITY_SENSOR "8D" +#define HAP_SERV_UUID_SECURITY_SYSTEM "7E" +#define HAP_SERV_UUID_CARBON_MONOXIDE_SENSOR "7F" +#define HAP_SERV_UUID_CONTACT_SENSOR "80" +#define HAP_SERV_UUID_DOOR "81" +#define HAP_SERV_UUID_HUMIDITY_SENSOR "82" +#define HAP_SERV_UUID_LEAK_SENSOR "83" +#define HAP_SERV_UUID_LIGHT_SENSOR "84" +#define HAP_SERV_UUID_MOTION_SENSOR "85" +#define HAP_SERV_UUID_OCCUPANCY_SENSOR "86" +#define HAP_SERV_UUID_SMOKE_SENSOR "87" +#define HAP_SERV_UUID_STATLESS_PROGRAMMABLE_SWITCH "89" +#define HAP_SERV_UUID_TEMPERATURE_SENSOR "8A" +#define HAP_SERV_UUID_WINDOW "8B" +#define HAP_SERV_UUID_WINDOW_COVERING "8C" +#define HAP_SERV_UUID_BATTERY_SERVICE "96" +#define HAP_SERV_UUID_CARBON_DIOXIDE_SENSOR "97" +#define HAP_SERV_UUID_FAN_V2 "B7" +#define HAP_SERV_UUID_SLAT "B9" +#define HAP_SERV_UUID_FILTER_MAINTENANCE "BA" +#define HAP_SERV_UUID_AIR_PURIFIER "BB" +#define HAP_SERV_UUID_HEATER_COOLER "BC" +#define HAP_SERV_UUID_HUMIDIFIER_DEHUMIDIFIER "BD" +#define HAP_SERV_UUID_SERVICE_LABEL "CC" +#define HAP_SERV_UUID_IRRIGATION_SYSTEM "CF" +#define HAP_SERV_UUID_VALVE "D0" +#define HAP_SERV_UUID_FAUCET "D7" + +/** Create Accessory Information Service + * + * This API will create the Accessory Information Service with the mandatory + * characteristics as per the HAP Specs. + * + * @param[in] cfg The accessory configuration to be used to create the service + * + * @return Pointer to the service object on success + * @return NULL on failure + */ +hap_serv_t *hap_serv_accessory_information_create(hap_acc_cfg_t *cfg); + +/** Create Protocol Information Service + * + * This API will create the Protocol Information Service with the mandatory + * characteristics as per the HAP Specs. + * + * @param[in] version The Protocol Version string + * + * @return Pointer to the service object on success + * @return NULL on failure + */ +hap_serv_t *hap_serv_protocol_information_create(char *version); + +/** Create Fan Service + * + * This API will create the Fan Service with the mandatory + * characteristics as per the HAP Specs. + * + * @param[in] on Initial "On" state of the service + * + * @return Pointer to the service object on success + * @return NULL on failure + */ +hap_serv_t *hap_serv_fan_create(bool on); + +/** Create Garage Door Opener Service + * + * This API will create the Garage Door Opener Service with the mandatory + * characteristics as per the HAP Specs. + * + * @param[in] curr_door_state Initial value of the current door state characteristic + * @param[in] targ_door_state Value of the target door state characteristic + * @param[in] obstr_detect Value of the obstruction detected characteristic + * + * @return Pointer to the service object on success + * @return NULL on failure + */ +hap_serv_t *hap_serv_garage_door_opener_create(uint8_t curr_door_state, uint8_t targ_door_state, bool obstr_detect) +; + +/** Create Light Bulb Service + * + * This API will create the Light Bulb Service with the mandatory + * characteristics as per the HAP Specs. + * + * @param[in] on Initial "On" state of the service + * + * @return Pointer to the service object on success + * @return NULL on failure + */ +hap_serv_t *hap_serv_lightbulb_create(bool on); + +/** Create Lock Management Service + * + * This API will create the Lock Management Service with the mandatory + * characteristics as per the HAP Specs. + * + * @param[in] lock_control_point Accepts data from TLV8 commands + * @param[in] version The Protocol Version string + * + * @return Pointer to the service object on success + * @return NULL on failure + */ +hap_serv_t *hap_serv_lock_management_create(hap_tlv8_val_t *lock_control_point, char * version); + +/** Create Lock Mechanism Service + * + * This API will create the Lock Mechanism Service with the mandatory + * characteristics as per the HAP Specs. + * + * @param[in] lock_curr_state Current lock state of the service + * @param[in] lock_targ_state Target lock state of the service + * + * @return Pointer to the service object on success + * @return NULL on failure + */ +hap_serv_t *hap_serv_lock_mechanism_create(uint8_t lock_curr_state, uint8_t lock_targ_state); + +/** Create Outlet Service + * + * This API will create the Outlet Service with the mandatory + * characteristics as per the HAP Specs. + * + * @param[in] on Initial "On" state of the service + * @param[in] outlet_in_use Initial value of the outlet in use characteristic + * + * @return Pointer to the service object on success + * @return NULL on failure + */ +hap_serv_t *hap_serv_outlet_create(bool on, bool outlet_in_use); + +/** Create Switch Service + * + * This API will create the Switch Service with the mandatory + * characteristics as per the HAP Specs. + * + * @param[in] on Initial "On" state of the service + * + * @return Pointer to the service object on success + * @return NULL on failure + */ +hap_serv_t *hap_serv_switch_create(bool on); + +/** Create Thermostat Service + * + * This API will create the Thermostat Service with the mandatory + * characteristics as per the HAP Specs. + * + * @param[in] curr_heating_cooling_state Initial value of Current Heating Cooling State characteristic + * @param[in] targ_heating_cooling_state Initial value of Target Heating Cooling State characteristic + * @param[in] curr_temp Initial value of Current Temperature characteristic + * @param[in] targ_temp Initial value of Target Temperature characteristic + * @param[in] temp_disp_units Initial value of Temperature Display Units characteristic + * + * @return Pointer to the service object on success + * @return NULL on failure + */ +hap_serv_t *hap_serv_thermostat_create(uint8_t curr_heating_cooling_state, uint8_t targ_heating_cooling_state, float curr_temp, float targ_temp, uint8_t temp_disp_units); + +/** Create Air Quality Sensor Service + * + * This API will create the Air Quality Sensor Service with the mandatory + * characteristics as per the HAP Specs. + * + * @param[in] air_quality Initial value of Air Quality characteristic + * + * @return Pointer to the service object on success + * @return NULL on failure + */ +hap_serv_t *hap_serv_air_quality_sensor_create(uint8_t air_quality); + +/** Create Security System Current State Service + * + * This API will create the Security System Current State Service with the mandatory + * characteristics as per the HAP Specs. + * + * @param[in] security_sys_curr_state Initial value of Security System Current State characteristic + * @param[in] security_sys_targ_state Initial value of Security System Target State characteristic + * + * @return Pointer to the service object on success + * @return NULL on failure + */ +hap_serv_t *hap_serv_security_system_create(uint8_t security_sys_curr_state, uint8_t security_sys_targ_state); + +/** Create Carbon Monoxide Sensor Service + * + * This API will create the Carbon Monoxide Sensor Service with the mandatory + * characteristics as per the HAP Specs. + * + * @param[in] carbon_monoxide_detected Initial value of Carbon Monoxide Sensor characteristic + * + * @return Pointer to the service object on success + * @return NULL on failure + */ +hap_serv_t *hap_serv_carbon_monoxide_sensor_create(uint8_t carbon_monoxide_detected); + +/** Create Contact Sensor Service + * + * This API will create the Contact Sensor Service with the mandatory + * characteristics as per the HAP Specs. + * + * @param[in] contact_sensor_state Initial value of Contact Sensor State characteristic + * + * @return Pointer to the service object on success + * @return NULL on failure + */ +hap_serv_t *hap_serv_contact_sensor_create(uint8_t contact_sensor_state); + +/** Create Door Service + * + * This API will create the Door Service with the mandatory + * characteristics as per the HAP Specs. + * + * @param[in] curr_pos Initial value of Current Position characteristic + * @param[in] targ_pos Initial value of Target Position characteristic + * @param[in] pos_state Initial value of Position State characteristic + * + * @return Pointer to the service object on success + * @return NULL on failure + */ +hap_serv_t *hap_serv_door_create(uint8_t curr_pos, uint8_t targ_pos, uint8_t pos_state); + +/** Create Humidity Sensor Service + * + * This API will create the Humidity Sensor Service with the mandatory + * characteristics as per the HAP Specs. + * + * @param[in] curr_relative_humidity Initial value of Humidity Sensor State characteristic + * + * @return Pointer to the service object on success + * @return NULL on failure + */ +hap_serv_t *hap_serv_humidity_sensor_create(float curr_relative_humidity); + +/** Leak Sensor Service + * + * This API will create the Leak Sensor Service with the mandatory + * characteristics as per the HAP Specs. + * + * @param[in] leak_detected Initial value of Leak Detected State characteristic + * + * @return Pointer to the service object on success + * @return NULL on failure + */ +hap_serv_t *hap_serv_leak_sensor_create(uint8_t leak_detected); + +/** Light Sensor Service + * + * This API will create the Light Sensor Service with the mandatory + * characteristics as per the HAP Specs. + * + * @param[in] curr_ambient_light_level Initial value of Current Ambient Light Level characteristic + * + * @return Pointer to the service object on success + * @return NULL on failure + */ +hap_serv_t *hap_serv_light_sensor_create(float curr_ambient_light_level); + +/** Motion Sensor Service + * + * This API will create the Motion Sensor Service with the mandatory + * characteristics as per the HAP Specs. + * + * @param[in] motion_detected Initial value of Motion Detected characteristic + * + * @return Pointer to the service object on success + * @return NULL on failure + */ +hap_serv_t *hap_serv_motion_sensor_create(bool motion_detected); + +/** Occupancy Sensor Service + * + * This API will create the Occupancy Sensor Service with the mandatory + * characteristics as per the HAP Specs. + * + * @param[in] occupancy_detected Initial value of Occupancy Detected characteristic + * + * @return Pointer to the service object on success + * @return NULL on failure + */ +hap_serv_t *hap_serv_occupancy_sensor_create(uint8_t occupancy_detected); + +/** Smoke Sensor Service + * + * This API will create the Smoke Sensor Service with the mandatory + * characteristics as per the HAP Specs. + * + * @param[in] smoke_detected Initial value of Smoke Detected characteristic + * + * @return Pointer to the service object on success + * @return NULL on failure + */ +hap_serv_t *hap_serv_smoke_sensor_create(uint8_t smoke_detected); + +/** Stateless Programmable Switch Service + * + * This API will create the Stateless Programmable Switch Service with the mandatory + * characteristics as per the HAP Specs. + * + * @param[in] programmable_switch_event Initial value of Programmable Switch Event characteristic + * + * @return Pointer to the service object on success + * @return NULL on failure + */ +hap_serv_t *hap_serv_stateless_programmable_switch_create(uint8_t programmable_switch_event); + +/** Temperature Sensor Service + * + * This API will create the Temperature Sensor Service with the mandatory + * characteristics as per the HAP Specs. + * + * @param[in] curr_temp Initial value of Current Temprature characteristic + * + * @return Pointer to the service object on success + * @return NULL on failure + */ +hap_serv_t *hap_serv_temperature_sensor_create(float curr_temp); + +/** Window Service + * + * This API will create the Window Service with the mandatory + * characteristics as per the HAP Specs. + * + * @param[in] curr_pos Initial value of Current Position characteristic + * @param[in] targ_pos Initial value of Target Position characteristic + * @param[in] pos_state Initial value of Position State characteristic + * + * @return Pointer to the service object on success + * @return NULL on failure + */ +hap_serv_t *hap_serv_window_create(uint8_t curr_pos, uint8_t targ_pos, uint8_t pos_state); + +/** Window Covering Service + * + * This API will create the Window Covering Service with the mandatory + * characteristics as per the HAP Specs. + * + * @param[in] targ_pos Initial value of Target Position characteristic + * @param[in] curr_pos Initial value of Current Position characteristic + * @param[in] pos_state Initial value of Position State characteristic + * + * @return Pointer to the service object on success + * @return NULL on failure + */ +hap_serv_t *hap_serv_window_covering_create(uint8_t targ_pos, uint8_t curr_pos, uint8_t pos_state); + +/** Battery Service + * + * This API will create the Battery Service with the mandatory + * characteristics as per the HAP Specs. + * + * @param[in] battery_level Initial value of Battery Level characteristic + * @param[in] charging_state Initial value of Charging State characteristic + * @param[in] status_low_battery Initial value of Status Low Battery characteristic + * + * @return Pointer to the service object on success + * @return NULL on failure + */ +hap_serv_t *hap_serv_battery_service_create(uint8_t battery_level, uint8_t charging_state, uint8_t status_low_battery); + +/** Create Carbon Dioxide Sensor Service + * + * This API will create the Carbon Dioxide Sensor Service with the mandatory + * characteristics as per the HAP Specs. + * + * @param[in] carbon_dioxide_detected Initial value of Carbon Dioxide Sensor characteristic + * + * @return Pointer to the service object on success + * @return NULL on failure + */ +hap_serv_t *hap_serv_carbon_dioxide_sensor_create(uint8_t carbon_dioxide_detected); + +/** Fan v2 Service + * + * This API will create the Fan v2 Service with the mandatory + * characteristics as per the HAP Specs. + * + * @param[in] active Value of Active characteristic + * + * @return Pointer to the service object on success + * @return NULL on failure + */ +hap_serv_t *hap_serv_fan_v2_create(uint8_t active); + +/** Slat Service + * + * This API will create the Slat Service with the mandatory + * characteristics as per the HAP Specs. + * + * @param[in] curr_slat_state Value of Current Slat State characteristic + * @param[in] slat_type Value of Slat Type characteristic + * + * @return Pointer to the service object on success + * @return NULL on failure + */ +hap_serv_t *hap_serv_slat_create(uint8_t curr_slat_state, uint8_t slat_type); + +/** Filter Maintenance Service + * + * This API will create the Filter Maintenance Service with the mandatory + * characteristics as per the HAP Specs. + * + * @param[in] filter_change_indication Value of Filter Change Indication characteristic + * + * @return Pointer to the service object on success + * @return NULL on failure + */ +hap_serv_t *hap_serv_filter_maintenance_create(uint8_t filter_change_indication); + +/** Air Purifier Service + * + * This API will create the Air Purifier Service with the mandatory + * characteristics as per the HAP Specs. + * + * @param[in] active Value of Active characteristic + * @param[in] curr_air_purifier_state Value of Current Air Purifier State characteristic + * @param[in] targ_air_purifier_state Value of Target Air Purifier State characteristic + * + * @return Pointer to the service object on success + * @return NULL on failure + */ +hap_serv_t *hap_serv_air_purifier_create(uint8_t active, uint8_t curr_air_purifier_state, uint8_t + targ_air_purifier_state); + +/** Heater Cooler Service + * + * This API will create the Heater Cooler Service with the mandatory + * characteristics as per the HAP Specs. + * + * @param[in] active Value of Active characteristic + * @param[in] curr_temp Value of Current Temperature characteristic + * @param[in] curr_heater_cooler_state Value of Current Heater Cooler State characteristic + * @param[in] targ_heater_cooler_state Value of Target Heater Cooler State characteristic + * + * @return Pointer to the service object on success + * @return NULL on failure + */ +hap_serv_t *hap_serv_heater_cooler_create(uint8_t active, float curr_temp, uint8_t curr_heater_cooler_state, uint8_t targ_heater_cooler_state); + +/** Create Humidifer Dehumidfier Service + * + * This API will create the Humidifer Dehumidfier Service with the mandatory + * characteristics as per the HAP Specs. + * + * @param[in] active Initial value of Active characteristic + * @param[in] curr_rel_humid Initial value of Current Relative Humidity characteristic + * @param[in] curr_humid_dehumid_state Initial value of Current Humidifier Dehumidifier State characteristic + * @param[in] targ_humid_dehumid_state Initial value of Target Humidifier Dehumidifier State characteristic + * + * @return Pointer to the service object on success + * @return NULL on failure + */ +hap_serv_t *hap_serv_humidifier_dehumidifier_create(uint8_t active, float curr_rel_humid, uint8_t + curr_humid_dehumid_state, uint8_t targ_humid_dehumid_state); + +/** Create Service Label Service + * + * This API will create the Service Label Service with the mandatory + * characteristics as per the HAP Specs. + * + * @param[in] service_label_namespace Initial value of Service Label Service characteristic + * + * @return Pointer to the service object on success + * @return NULL on failure + */ +hap_serv_t *hap_serv_service_label_create(uint8_t service_label_namespace); + +/** Create Irrigation System Service + * + * This API will create the Irrigation System Service with the mandatory + * characteristics as per the HAP Specs. + * + * @param[in] active Initial value of active characteristic + * @param[in] prog_mode Initial value of Program Mode characteristic + * @param[in] in_use Initial value of In Use characteristic + * + * @return Pointer to the service object on success + * @return NULL on failure + */ +hap_serv_t *hap_serv_irrigation_system_create(uint8_t active, uint8_t prog_mode, uint8_t in_use); + +/** Create Valve Service + * + * This API will create the Valve Service with the mandatory + * characteristics as per the HAP Specs. + * + * @param[in] active Initial value of active characteristic + * @param[in] in_use Initial value of In Use characteristic + * @param[in] valve_type Initial value of Valve Type characteristic + * + * @return Pointer to the service object on success + * @return NULL on failure + */ +hap_serv_t *hap_serv_valve_create(uint8_t active, uint8_t in_use, uint8_t valve_type); + +/** Create Faucet Service + * + * This API will create the Faucet Service with the mandatory + * characteristics as per the HAP Specs. + * + * @param[in] active Initial value of active characteristic + * + * @return Pointer to the service object on success + * @return NULL on failure + */ +hap_serv_t *hap_serv_faucet_create(uint8_t active); + +#ifdef __cplusplus +} +#endif + +#endif /* _HAP_APPLE_SERVS_H_ */ diff --git a/lib/libesp32_div/ESP32-HomeKit/src/hap_bct.h b/lib/libesp32_div/ESP32-HomeKit/src/hap_bct.h new file mode 100644 index 000000000..6a65e5588 --- /dev/null +++ b/lib/libesp32_div/ESP32-HomeKit/src/hap_bct.h @@ -0,0 +1,54 @@ +/* + * ESPRESSIF MIT License + * + * Copyright (c) 2020 + * + * Permission is hereby granted for use on ESPRESSIF SYSTEMS products only, in which case, + * it is 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. + * + */ +#ifndef _HAP_BCT_H_ +#define _HAP_BCT_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Change the name of the Bonjour Service for BCT + * + * This is required as per the "Manual Name Change" step of "Tester Interaction" + * section of Bonjour Conformance Test. + * + * @param[in] name The desired new name for the service. For BCT 1.4 or earlier: "New - Bonjour Service Name". + * For BCT 1.5 or later: "New-BCT" + */ +void hap_bct_change_name(const char *name); + +/** + * @brief Trigger a Hot plug of the network interface for BCT + * + * This is required as per the "Cable Change Handling" and "Hot Plugging" steps + * of "Tester Interaction" section of Bonjout Conformance Test + */ +void hap_bct_hot_plug(); + +#ifdef __cplusplus +} +#endif + +#endif /* _HAP_BCT_H_ */ diff --git a/lib/libesp32_div/ESP32-HomeKit/src/hap_platform_httpd.c b/lib/libesp32_div/ESP32-HomeKit/src/hap_platform_httpd.c new file mode 100644 index 000000000..9bd679da4 --- /dev/null +++ b/lib/libesp32_div/ESP32-HomeKit/src/hap_platform_httpd.c @@ -0,0 +1,126 @@ +/* + * ESPRESSIF MIT License + * + * Copyright (c) 2019 + * + * Permission is hereby granted for use on ESPRESSIF SYSTEMS products only, in which case, + * it is 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 +#include <_esp_hap_config.h> + +httpd_handle_t *int_handle; +int hap_platform_httpd_start(httpd_handle_t *handle) +{ + httpd_config_t config = { + .task_priority = tskIDLE_PRIORITY+5, + .stack_size = CONFIG_HAP_HTTP_STACK_SIZE, + .server_port = CONFIG_HAP_HTTP_SERVER_PORT, + .ctrl_port = CONFIG_HAP_HTTP_CONTROL_PORT, + .max_open_sockets = CONFIG_HAP_HTTP_MAX_OPEN_SOCKETS, + .max_uri_handlers = CONFIG_HAP_HTTP_MAX_URI_HANDLERS, + .max_resp_headers = 8, + .backlog_conn = 5, + .lru_purge_enable = true, + .recv_wait_timeout = 5, + .send_wait_timeout = 5, + }; + esp_err_t err = httpd_start(handle, &config); + if (err == ESP_OK) { + int_handle = handle; + } + return err; +} + +int hap_platform_httpd_stop(httpd_handle_t *handle) +{ + esp_err_t err = httpd_stop(*handle); + if (err == ESP_OK) { + int_handle = NULL; + } + return err; +} + +int hap_platform_httpd_get_port() +{ + return CONFIG_HAP_HTTP_SERVER_PORT; +} + +void * hap_platform_httpd_get_sess_ctx(httpd_req_t *req) +{ + if (req) { + return req->sess_ctx; + } + return NULL; +} + +esp_err_t hap_platform_httpd_set_sess_ctx(httpd_req_t *req, void *ctx, httpd_free_ctx_fn_t free_ctx, bool ignore_ctx_changes) +{ + if (req) { + req->sess_ctx = ctx; + req->free_ctx = free_ctx; +#ifndef CONFIG_IDF_TARGET_ESP8266 + req->ignore_sess_ctx_changes = ignore_ctx_changes; +#endif + return ESP_OK; + } + return ESP_FAIL; +} + +static char * hap_platform_httpd_rqtype_to_string(int method) +{ + switch (method) { + case HTTP_GET: + return "GET"; + case HTTP_POST: + return "POST"; + case HTTP_PUT: + return "PUT"; + default: + return "INVALID"; + } +} + +const char *hap_platform_httpd_get_req_method(httpd_req_t *req) +{ + if (req) { + return hap_platform_httpd_rqtype_to_string(req->method); + } + return NULL; +} + +const char *hap_platform_httpd_get_req_uri(httpd_req_t *req) +{ + if (req) { + return req->uri; + } + return NULL; +} + +int hap_platform_httpd_get_content_len(httpd_req_t *req) +{ + if (req) { + return req->content_len; + } + return -1; +} + +httpd_handle_t *hap_platform_httpd_get_handle() +{ + return int_handle; +} diff --git a/lib/libesp32_div/ESP32-HomeKit/src/hap_platform_httpd.h b/lib/libesp32_div/ESP32-HomeKit/src/hap_platform_httpd.h new file mode 100644 index 000000000..ce5b0dc1f --- /dev/null +++ b/lib/libesp32_div/ESP32-HomeKit/src/hap_platform_httpd.h @@ -0,0 +1,136 @@ + +/* + * ESPRESSIF MIT License + * + * Copyright (c) 2019 + * + * Permission is hereby granted for use on ESPRESSIF SYSTEMS products only, in which case, + * it is 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. + * + */ +#ifndef _HAP_PLATFORM_HTTPD_H_ +#define _HAP_PLATFORM_HTTPD_H_ +#include +#ifdef __cplusplus +extern "C" { +#endif + +/** Start the webserver + * + * This API will be called by the HAP Core to start the webserver. + * + * @param[out] handle Pointer to the handle that should be populated by this + * function on a success. + * + * @return ESP_OK on success + * @return error code otherwise + */ +int hap_platform_httpd_start(httpd_handle_t *handle); + +/** Stop the webserver + * + * This API will be called by the HAP Core to stop the webserver. + * + * @param[in] handle Pointer to the handle created in hap_platform_httpd_start + * + * @return ESP_OK on success + * @return error code otherwise + */ +int hap_platform_httpd_stop(httpd_handle_t *handle); + +/** Get the current HTTP Port + * + * This API will be called by the HAP Core to get the HTTP Port being used. This will + * be used for the mDNS announcement + * + * @return Configured HTTP Port + */ +int hap_platform_httpd_get_port(); + +/** Get the HTTPD session context + * + * This API will be called by the HAP Core to get the context associated with a given + * session. It is generally used to maintain pairing information. + * + * @param[in] req HTTPD Request structure. + * + * @return pointer to the session context. + */ +void * hap_platform_httpd_get_sess_ctx(httpd_req_t *req); + +/** Set the HTTPD session context + * + * This API will be called by the HAP Core to set the context associated with a given + * session. It is generally used to maintain pairing information. + * + * @param[in] req HTTPD Request structure. + * @param[in] ctx The context to be set for the given session. + * @param[in] free_fn Pointer to a function that will be used by the HTTP Server to clear the context when the session closes + * @param[in] ignore_ctx_changes Flag to indicate if the HTTP Server should ignore changes to the context across different requests. + * If set to false, the server will try clearing the old context, if it detects any change. + * + * @return ESP_OK in success + * @return ESP_FAIL if req is nULL + */ +esp_err_t hap_platform_httpd_set_sess_ctx(httpd_req_t *req, void *ctx, httpd_free_ctx_fn_t free_ctx, bool ignore_ctx_changes); + +/** Get the HTTP request method + * + * This API will be called by the HAP Core to get the HTTP request method + * in string format (Eg. GET, POST, etc.) + * + * @param[in] HTTPD Request structure. + * + * @return Pointer to a string indicating the HTTP method. + */ +const char *hap_platform_httpd_get_req_method(httpd_req_t *req); + +/** Get the HTTP request URI + * + * This API will be called by the HAP Core to get the request URI string. + * + * @param[in] HTTPD Request structure. + * + * @return Pointer to the URI string. + */ +const char *hap_platform_httpd_get_req_uri(httpd_req_t *req); + +/** Get the HTTP request content length + * + * This API will be called by the HAP Core to get the content length of the request. + * + * @param[in] HTTPD Request structure. + * + * @return Content length. + */ +int hap_platform_httpd_get_content_len(httpd_req_t *req); + +/** + * Get the HAP HTTPD Handle + * + * If an application wants to register additional HTTPD endpoints on the same server + * instance being used by HomeKit, this API can be used to get the handle. This + * should be used only after hap_start(). + * + * @return HomeKit HTTPD Handle + */ +httpd_handle_t *hap_platform_httpd_get_handle(); + +#ifdef __cplusplus +} +#endif +#endif /* _HAP_PLATFORM_HTTPD_H_ */ diff --git a/lib/libesp32_div/ESP32-HomeKit/src/hap_platform_keystore.c b/lib/libesp32_div/ESP32-HomeKit/src/hap_platform_keystore.c new file mode 100644 index 000000000..b82457ca5 --- /dev/null +++ b/lib/libesp32_div/ESP32-HomeKit/src/hap_platform_keystore.c @@ -0,0 +1,187 @@ +/* + * ESPRESSIF MIT License + * + * Copyright (c) 2020 + * + * Permission is hereby granted for use on ESPRESSIF SYSTEMS products only, in which case, + * it is 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 +#include +#include + +#define HAP_PLATFORM_DEF_NVS_PARTITION "nvs" +#define HAP_PLATFORM_DEF_FACTORY_NVS_PARTITION "factory_nvs" + +static const char *TAG = "hap_platform_keystore"; + +char * hap_platform_keystore_get_nvs_partition_name() +{ + return HAP_PLATFORM_DEF_NVS_PARTITION; +} + +char * hap_platform_keystore_get_factory_nvs_partition_name() +{ + return HAP_PLATFORM_DEF_FACTORY_NVS_PARTITION; +} + +#ifdef CONFIG_NVS_ENCRYPTION +int hap_platform_keystore_init_partition(const char *part_name, bool read_only) +{ + esp_err_t err; + nvs_sec_cfg_t *cfg = NULL; + nvs_sec_cfg_t sec_cfg; + esp_partition_iterator_t iterator = esp_partition_find(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_NVS_KEYS, NULL); + if (iterator) { + const esp_partition_t *partition = esp_partition_get(iterator); + err = nvs_flash_read_security_cfg(partition, &sec_cfg); + if (err == ESP_OK) { + cfg = &sec_cfg; + } else { + ESP_LOGE(TAG, "No NVS keys found"); + } + } else { + ESP_LOGE(TAG, "No NVS keys partition found"); + } + if (!cfg) { + ESP_LOGE(TAG, "NVS partition '%s' not encrypted", part_name); + } else { + ESP_LOGI(TAG, "NVS partition '%s' is encrypted", part_name); + } + if (read_only) { + err = nvs_flash_secure_init_partition(part_name, cfg); + } else { + err = nvs_flash_secure_init_partition(part_name, cfg); + if (err == ESP_ERR_NVS_NO_FREE_PAGES) { + ESP_ERROR_CHECK(nvs_flash_erase_partition(part_name)); + err = nvs_flash_secure_init_partition(part_name, cfg); + } + } + if (err == ESP_OK) { + return 0; + } + return -1; +} +#else +int hap_platform_keystore_init_partition(const char *part_name, bool read_only) +{ + esp_err_t err; + if (read_only) { + err = nvs_flash_init_partition(part_name); + } else { + err = nvs_flash_init_partition(part_name); + if (err == ESP_ERR_NVS_NO_FREE_PAGES) { + ESP_ERROR_CHECK(nvs_flash_erase_partition(part_name)); + err = nvs_flash_init_partition(part_name); + } + } + if (err == ESP_OK) { + return 0; + } + return -1; +} +#endif /* CONFIG_NVS_ENCRYPTION */ + +int hap_platform_keystore_get(const char *part_name, const char *name_space, const char *key, uint8_t *val, size_t *val_size) +{ + nvs_handle handle; + esp_err_t err = nvs_open_from_partition(part_name, name_space, NVS_READONLY, &handle); + if (err != ESP_OK) { + return -1; + } else { + err = nvs_get_blob(handle, key, val, val_size); + nvs_close(handle); + } + if (err == ESP_OK) { + return 0; + } + return -1; +} + +int hap_platform_keystore_set(const char *part_name, const char *name_space, const char *key, const uint8_t *val, const size_t val_len) + +{ + nvs_handle handle; + esp_err_t err = nvs_open_from_partition(part_name, name_space, NVS_READWRITE, &handle); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Error (%d) opening NVS handle!", err); + } else { + err = nvs_set_blob(handle, key, val, val_len); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Failed to write %s", key); + } else { + nvs_commit(handle); + } + nvs_close(handle); + } + if (err == ESP_OK) { + return 0; + } + return -1; +} + +int hap_platform_keystore_delete(const char *part_name, const char *name_space, const char *key) +{ + nvs_handle handle; + esp_err_t err = nvs_open_from_partition(part_name, name_space, NVS_READWRITE, &handle); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Error (%d) opening NVS handle!", err); + } else { + err = nvs_erase_key(handle, key); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Failed to delete %s", key); + } else { + nvs_commit(handle); + } + nvs_close(handle); + } + if (err == ESP_OK) { + return 0; + } + return -1; +} + +int hap_platform_keystore_delete_namespace(const char *part_name, const char *name_space) +{ + nvs_handle handle; + esp_err_t err = nvs_open_from_partition(part_name, name_space, NVS_READWRITE, &handle); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Error (%d) opening NVS handle!", err); + } else { + err = nvs_erase_all(handle); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Failed to delete %s", name_space); + } else { + nvs_commit(handle); + } + nvs_close(handle); + } + if (err == ESP_OK) { + return 0; + } + return -1; +} + +int hap_platfrom_keystore_erase_partition(const char *part_name) +{ + esp_err_t err = nvs_flash_erase_partition(part_name); + if (err == ESP_OK) { + return 0; + } + return -1; +} diff --git a/lib/libesp32_div/ESP32-HomeKit/src/hap_platform_keystore.h b/lib/libesp32_div/ESP32-HomeKit/src/hap_platform_keystore.h new file mode 100644 index 000000000..6be1c47cb --- /dev/null +++ b/lib/libesp32_div/ESP32-HomeKit/src/hap_platform_keystore.h @@ -0,0 +1,115 @@ +/* + * ESPRESSIF MIT License + * + * Copyright (c) 2020 + * + * Permission is hereby granted for use on ESPRESSIF SYSTEMS products only, in which case, + * it is 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. + * + */ + +#ifndef _HAP_PLATFORM_KEYSTORE_H_ +#define _HAP_PLATFORM_KEYSTORE_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** Get NVS Partition Name + * + * @return pointer to an allocated string indicating NVS partition Name + */ +char * hap_platform_keystore_get_nvs_partition_name(); + + +/** Get Factory NVS Partition Name + * + * @return pointer to an allocated string indicating Factory NVS partition Name + */ +char * hap_platform_keystore_get_factory_nvs_partition_name(); + +/** Initialise Key Store Partition + * + * @param[in] part_name Name of Partition + * @param[in] read_only True for Read-Only, False for Read-Write + * + * @return 0 on success + * @return -1 on error + */ +int hap_platform_keystore_init_partition(const char *part_name, bool read_only); + +/** Get Value from Key Store + * + * @param[in] part_name Name of Partition + * @param[in] name_space Name space for the key + * @param[in] key Name of the key + * @param[out] val Allocated buffer into which the value will be read + * @param[in,out] val_size Size of the allocated value buffer. Will hold the size of value read on success + * + * @return 0 on success + * @return -1 on error + */ +int hap_platform_keystore_get(const char *part_name, const char *name_space, const char *key, uint8_t *val, size_t *val_size); + +/** Set Value in Key Store + * + * @param[in] part_name Name of Partition + * @param[in] name_space Name space for the key + * @param[in] key Name of the key + * @param[in] val Pointer to the value buffer + * @param[in] val_len Length of the value buffer + * + * @return 0 on success + * @return -1 on error + */ +int hap_platform_keystore_set(const char *part_name, const char *name_space, const char *key, const uint8_t *val, const size_t val_len); + +/** Delete Entry from Key Store + * + * @param[in] part_name Name of Partition + * @param[in] name_space Name space for the key + * @param[in] key Name of the key + * + * @return 0 on success + * @return -1 on error + */ +int hap_platform_keystore_delete(const char *part_name, const char *name_space, const char *key); + +/** Delete Name space from Key Store + * + * @param[in] part_name Name of Partition + * @param[in] name_space Name space for the key + * + * @return 0 on success + * @return -1 on error + */ +int hap_platform_keystore_delete_namespace(const char *part_name, const char *name_space); + +/** Erase a Key Store partition + * + * @param[in] part_name Name of Partition + * + * @return 0 on success + * @return -1 on error + */ +int hap_platfrom_keystore_erase_partition(const char *part_name); +#ifdef __cplusplus +} +#endif +#endif /* _HAP_PLATFORM_KEYSTORE_H_ */ diff --git a/lib/libesp32_div/ESP32-HomeKit/src/hap_platform_memory.c b/lib/libesp32_div/ESP32-HomeKit/src/hap_platform_memory.c new file mode 100644 index 000000000..361cd3e5f --- /dev/null +++ b/lib/libesp32_div/ESP32-HomeKit/src/hap_platform_memory.c @@ -0,0 +1,39 @@ +/* + * ESPRESSIF MIT License + * + * Copyright (c) 2019 + * + * Permission is hereby granted for use on ESPRESSIF SYSTEMS products only, in which case, + * it is 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 + +void * hap_platform_memory_malloc(size_t size) +{ + return malloc(size); +} + +void * hap_platform_memory_calloc(size_t count, size_t size) +{ + return calloc(count, size); +} + +void hap_platform_memory_free(void *ptr) +{ + free(ptr); +} diff --git a/lib/libesp32_div/ESP32-HomeKit/src/hap_platform_memory.h b/lib/libesp32_div/ESP32-HomeKit/src/hap_platform_memory.h new file mode 100644 index 000000000..ce8f39ec2 --- /dev/null +++ b/lib/libesp32_div/ESP32-HomeKit/src/hap_platform_memory.h @@ -0,0 +1,67 @@ +/* + * ESPRESSIF MIT License + * + * Copyright (c) 2019 + * + * Permission is hereby granted for use on ESPRESSIF SYSTEMS products only, in which case, + * it is 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. + * + */ +#ifndef _HAP_PLATFORM_MEMORY_H_ +#define _HAP_PLATFORM_MEMORY_H_ +#include +#ifdef __cplusplus +extern "C" { +#endif + + +/** Allocate memory + * + * This API allocates "size" bytes of memory and returns a pointer to the allocated memory. + * + * @param[in] size Number of bytes to be allocated + * + * @return pointer to the allocated memory + * @return NULL on failure + */ +void * hap_platform_memory_malloc(size_t size); + +/** Allocate contiguous memory for items + * + * This API contiguously allocates enough space for "count" objects that are "size" bytes of memory each + * and returns a pointer to the allocated memory. The allocated memory is filled with bytes of value zero. + * + * @param[in] count Number of items + * @param[in] size Size of each item + * + * @return pointer to the allocated memory + * @return NULL on failure + */ +void * hap_platform_memory_calloc(size_t count, size_t size); + +/** Free allocate memory + * + * This API frees the memory allocated by hap_platform_memory_malloc() or hap_platform_memory_calloc() + * + * @param[in] ptr Pointer to the allocated memory + */ +void hap_platform_memory_free(void *ptr); + +#ifdef __cplusplus +} +#endif +#endif /* _HAP_PLATFORM_MEMORY_H_ */ diff --git a/lib/libesp32_div/ESP32-HomeKit/src/hap_platform_os.c b/lib/libesp32_div/ESP32-HomeKit/src/hap_platform_os.c new file mode 100644 index 000000000..29e23b11b --- /dev/null +++ b/lib/libesp32_div/ESP32-HomeKit/src/hap_platform_os.c @@ -0,0 +1,32 @@ +/* + * ESPRESSIF MIT License + * + * Copyright (c) 2019 + * + * Permission is hereby granted for use on ESPRESSIF SYSTEMS products only, in which case, + * it is 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 +#include +#include +#include + +uint16_t hap_platform_os_get_msec_per_tick() +{ + return portTICK_PERIOD_MS; +} diff --git a/lib/libesp32_div/ESP32-HomeKit/src/hap_platform_os.h b/lib/libesp32_div/ESP32-HomeKit/src/hap_platform_os.h new file mode 100644 index 000000000..1270ba76d --- /dev/null +++ b/lib/libesp32_div/ESP32-HomeKit/src/hap_platform_os.h @@ -0,0 +1,41 @@ +/* + * ESPRESSIF MIT License + * + * Copyright (c) 2019 + * + * Permission is hereby granted for use on ESPRESSIF SYSTEMS products only, in which case, + * it is 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. + * + */ +#ifndef _HAP_PLATFORM_OS_H_ +#define _HAP_PLATFORM_OS_H_ +#include +#ifdef __cplusplus +extern "C" { +#endif + + +/** Return the OS tick period in milliseconds + * + * @return the milliseconds per tick as configured for the OS + */ +uint16_t hap_platform_os_get_msec_per_tick(); + +#ifdef __cplusplus +} +#endif +#endif /* _HAP_PLATFORM_OS_H_ */ diff --git a/lib/libesp32_div/ESP32-HomeKit/src/hap_wac.h b/lib/libesp32_div/ESP32-HomeKit/src/hap_wac.h new file mode 100644 index 000000000..e106c2389 --- /dev/null +++ b/lib/libesp32_div/ESP32-HomeKit/src/hap_wac.h @@ -0,0 +1,121 @@ +/* + * ESPRESSIF MIT License + * + * Copyright (c) 2020 + * + * Permission is hereby granted for use on ESPRESSIF SYSTEMS products only, in which case, + * it is 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. + * + */ + +#ifndef _HAP_WAC_H_ +#define _HAP_WAC_H_ +#include +#include +#include +#include +/** HomeKit Event Base */ +ESP_EVENT_DECLARE_BASE(HAP_WAC_EVENT); +/** HomeKit Events */ +typedef enum { + /* WAC has started. Associated data is NULL */ + HAP_WAC_EVENT_STARTED, + /** WAC has timed out because of inactivity. Associated data is NULL. + * Appropriate indications should be given to the user, so that the accessory can be rebooted + * for restarting WAC. + */ + HAP_WAC_EVENT_TIMEOUT, + /** WAC was successful and will stop after some time. Associated data is NULL. + */ + HAP_WAC_EVENT_SUCCESS, + /** WAC is requesting to start SoftAP. Associated data is a pointer to a NULL terminated SSID. + * Using this SSID isn't required, but recommended. The network security should be "Open" for + * WAC to work. If SoftAP has already been started, nothing needs to be done for this event. + * The helper function hap_wifi_softap_start() can be used for this. + */ + HAP_WAC_EVENT_REQ_SOFTAP_START, + /** WAC is requesting to stop SoftAP. Associated data is NULL. + * The helper function hap_wifi_softap_stop() can be used for this. + */ + HAP_WAC_EVENT_REQ_SOFTAP_STOP, + /** WAC has received the Wi-Fi credentials. Associated data is a pointer to wifi_config_t + * structure. This should be used to connect to the Wi-Fi network. + * The helper function hap_wifi_sta_connect() can be used for this. + */ + HAP_WAC_EVENT_RECV_CRED, + /** WAC has stopped */ + HAP_WAC_EVENT_STOPPED +} hap_wac_event_t; + +/** Start WAC Provisioning. + * + * This should be called when the accessory boots up in an unprovisioned mode. + * The helper function hap_wifi_is_provisioned() function can be used to find + * if the accessory is provisioned or not. + * + * @return 0 on success. + * @return -1 on failure. + */ +int hap_wac_start(void); + +/** Stop WAC Provisioning. + * + * This should be used only if WAC needs to be stopped explicitly (say, after + * provisioning was done using some other means). Else, WAC stops automatically, + * either after the timeout or after successful provisioning. + * + * @return 0 on success. + * @return -1 on failure. + */ +int hap_wac_stop(void); + +/** Check is accessory is provisioned + * + * @param[out] provisioned Pointer to an allocated boolean variable. Will + * be set to true if accessory is provisioned, else false. + * + * @return ESP_OK on success. + * @return error on failure. + */ +esp_err_t hap_wifi_is_provisioned(bool *provisioned); + +/** Start SoftAP + * + * @param[in] ssid NULL terminated ssid string. + * + * @return ESP_OK on success. + * @return error on failure. + */ +esp_err_t hap_wifi_softap_start(char *ssid); + +/** Stop Soft AP + * + * @return ESP_OK on success. + * @return error on failure. + */ +esp_err_t hap_wifi_softap_stop(void); + +/** Connect to Wi-Fi network with given configuration + * + * @param[in] config Pointer to \ref wifi_config_t structure. + * + * @return ESP_OK on success. + * @return error on failure. + */ +esp_err_t hap_wifi_sta_connect(wifi_config_t *config); + +#endif /* _HAP_WAC_H_ */ diff --git a/lib/libesp32_div/ESP32-HomeKit/src/hexbin.c b/lib/libesp32_div/ESP32-HomeKit/src/hexbin.c new file mode 100644 index 000000000..745152519 --- /dev/null +++ b/lib/libesp32_div/ESP32-HomeKit/src/hexbin.c @@ -0,0 +1,51 @@ +// Copyright 2020 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#include +static int hex2bin_byte(uint8_t *byte) +{ + if (*byte >= '0' && *byte <= '9') + *byte -= '0'; + else if (*byte >= 'a' && *byte <= 'f') + *byte -= ('a' - 0x0a); + else if (*byte >= 'A' && *byte <= 'F') + *byte -= ('A' - 0x0a); + else + return -1; + return 0; +} + +int hex2bin(const char *ihex, size_t ilen, uint8_t *obin, size_t *olen) +{ + if (ilen > (2 * (*olen))) { + return -1; + } else if (ilen % 2) { + return -1; + } + int i, j; + uint8_t byte; + for (i = 0, j = 0; i < ilen / 2; i++) { + byte = ihex[j++]; + if (hex2bin_byte(&byte) < 0) { + return -1; + } + obin[i] = (byte << 4); + byte = ihex[j++]; + if (hex2bin_byte(&byte) < 0) { + return -1; + } + obin[i] |= byte; + } + *olen = i; + return 0; +} diff --git a/lib/libesp32_div/ESP32-HomeKit/src/hexbin.h b/lib/libesp32_div/ESP32-HomeKit/src/hexbin.h new file mode 100644 index 000000000..ced744bab --- /dev/null +++ b/lib/libesp32_div/ESP32-HomeKit/src/hexbin.h @@ -0,0 +1,19 @@ +// Copyright 2020 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#ifndef _HEXBIN_H_ +#define _HEXBIN_H_ +#include +#include +int hex2bin(const char *ihex, size_t ilen, uint8_t *obin, size_t *olen); +#endif /* _HEXBIN_H_ */ diff --git a/lib/libesp32_div/ESP32-HomeKit/src/hexdump.c b/lib/libesp32_div/ESP32-HomeKit/src/hexdump.c new file mode 100644 index 000000000..f6e7e0aef --- /dev/null +++ b/lib/libesp32_div/ESP32-HomeKit/src/hexdump.c @@ -0,0 +1,34 @@ +// Copyright 2020 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#include + +//#define HEX_DBG_ENABLE + +#ifdef HEX_DBG_ENABLE +void hex_dbg_with_name(char *name, unsigned char *buf, int buf_len) +{ + int i; + printf("%s: ", name); + for (i = 0; i < buf_len; i++) { + if (i % 16 == 0) + printf("\r\n"); + printf("%02x ", buf[i]); + } + printf("\r\n"); +} +#else +void hex_dbg_with_name(char *name, unsigned char *buf, int buf_len) +{ +} +#endif /* HEX_DBG_ENABLED */ diff --git a/lib/libesp32_div/ESP32-HomeKit/src/hexdump.h b/lib/libesp32_div/ESP32-HomeKit/src/hexdump.h new file mode 100644 index 000000000..a64bc7c18 --- /dev/null +++ b/lib/libesp32_div/ESP32-HomeKit/src/hexdump.h @@ -0,0 +1,18 @@ +// Copyright 2020 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#ifndef _HEXDUMP_H_ +#define _HEXDUMP_H_ +void hex_dbg_with_name(char *name, unsigned char *buf, int buf_len); + +#endif /* _HEXDUMP_H_ */ diff --git a/lib/libesp32_div/ESP32-HomeKit/src/hkdf-sha.h b/lib/libesp32_div/ESP32-HomeKit/src/hkdf-sha.h new file mode 100644 index 000000000..276c3685b --- /dev/null +++ b/lib/libesp32_div/ESP32-HomeKit/src/hkdf-sha.h @@ -0,0 +1,358 @@ +/**************************** sha.h ****************************/ +/***************** See RFC 6234 for details. *******************/ +/* + Copyright (c) 2011 IETF Trust and the persons identified as + authors of the code. 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 Internet Society, IETF or IETF Trust, nor + the names of specific 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 OWNER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +#ifndef _SHA_H_ +#define _SHA_H_ + +/* + * Description: + * This file implements the Secure Hash Algorithms + * as defined in the U.S. National Institute of Standards + * and Technology Federal Information Processing Standards + * Publication (FIPS PUB) 180-3 published in October 2008 + * and formerly defined in its predecessors, FIPS PUB 180-1 + * and FIP PUB 180-2. + * + * A combined document showing all algorithms is available at + * http://csrc.nist.gov/publications/fips/ + * fips180-3/fips180-3_final.pdf + * + * The five hashes are defined in these sizes: + * SHA-1 20 byte / 160 bit + * SHA-224 28 byte / 224 bit + * SHA-256 32 byte / 256 bit + * SHA-384 48 byte / 384 bit + * SHA-512 64 byte / 512 bit + * + * Compilation Note: + * These files may be compiled with two options: + * USE_32BIT_ONLY - use 32-bit arithmetic only, for systems + * without 64-bit integers + * + * USE_MODIFIED_MACROS - use alternate form of the SHA_Ch() + * and SHA_Maj() macros that are equivalent + * and potentially faster on many systems + * + */ + +#include +/* + * If you do not have the ISO standard stdint.h header file, then you + * must typedef the following: + * name meaning + * uint64_t unsigned 64-bit integer + * uint32_t unsigned 32-bit integer + * uint8_t unsigned 8-bit integer (i.e., unsigned char) + * int_least16_t integer of >= 16 bits + * + * See stdint-example.h + */ + +#ifndef _SHA_enum_ +#define _SHA_enum_ +/* + * All SHA functions return one of these values. + */ +enum { + shaSuccess = 0, + shaNull, /* Null pointer parameter */ + shaInputTooLong, /* input data too long */ + shaStateError, /* called Input after FinalBits or Result */ + shaBadParam /* passed a bad parameter */ +}; +#endif /* _SHA_enum_ */ + +/* + * These constants hold size information for each of the SHA + * hashing operations + */ +enum { + SHA1_Message_Block_Size = 64, SHA224_Message_Block_Size = 64, + SHA256_Message_Block_Size = 64, SHA384_Message_Block_Size = 128, + SHA512_Message_Block_Size = 128, + USHA_Max_Message_Block_Size = SHA512_Message_Block_Size, + + SHA1HashSize = 20, SHA224HashSize = 28, SHA256HashSize = 32, + SHA384HashSize = 48, SHA512HashSize = 64, + USHAMaxHashSize = SHA512HashSize, + + SHA1HashSizeBits = 160, SHA224HashSizeBits = 224, + SHA256HashSizeBits = 256, SHA384HashSizeBits = 384, + SHA512HashSizeBits = 512, USHAMaxHashSizeBits = SHA512HashSizeBits +}; + +/* + * These constants are used in the USHA (Unified SHA) functions. + */ +typedef enum SHAversion { + SHA1, SHA224, SHA256, SHA384, SHA512 +} SHAversion; + +/* + * This structure will hold context information for the SHA-1 + * hashing operation. + */ +typedef struct SHA1Context { + uint32_t Intermediate_Hash[SHA1HashSize/4]; /* Message Digest */ + + uint32_t Length_High; /* Message length in bits */ + uint32_t Length_Low; /* Message length in bits */ + + int_least16_t Message_Block_Index; /* Message_Block array index */ + /* 512-bit message blocks */ + uint8_t Message_Block[SHA1_Message_Block_Size]; + + int Computed; /* Is the hash computed? */ + int Corrupted; /* Cumulative corruption code */ +} SHA1Context; + +/* + * This structure will hold context information for the SHA-256 + * hashing operation. + */ +typedef struct SHA256Context { + uint32_t Intermediate_Hash[SHA256HashSize/4]; /* Message Digest */ + + uint32_t Length_High; /* Message length in bits */ + uint32_t Length_Low; /* Message length in bits */ + + int_least16_t Message_Block_Index; /* Message_Block array index */ + /* 512-bit message blocks */ + uint8_t Message_Block[SHA256_Message_Block_Size]; + + int Computed; /* Is the hash computed? */ + int Corrupted; /* Cumulative corruption code */ +} SHA256Context; + +/* + * This structure will hold context information for the SHA-512 + * hashing operation. + */ +typedef struct SHA512Context { +#ifdef USE_32BIT_ONLY + uint32_t Intermediate_Hash[SHA512HashSize/4]; /* Message Digest */ + uint32_t Length[4]; /* Message length in bits */ +#else /* !USE_32BIT_ONLY */ + uint64_t Intermediate_Hash[SHA512HashSize/8]; /* Message Digest */ + uint64_t Length_High, Length_Low; /* Message length in bits */ +#endif /* USE_32BIT_ONLY */ + + int_least16_t Message_Block_Index; /* Message_Block array index */ + /* 1024-bit message blocks */ + uint8_t Message_Block[SHA512_Message_Block_Size]; + + int Computed; /* Is the hash computed?*/ + int Corrupted; /* Cumulative corruption code */ +} SHA512Context; + +/* + * This structure will hold context information for the SHA-224 + * hashing operation. It uses the SHA-256 structure for computation. + */ +typedef struct SHA256Context SHA224Context; + +/* + * This structure will hold context information for the SHA-384 + * hashing operation. It uses the SHA-512 structure for computation. + */ +typedef struct SHA512Context SHA384Context; + +/* + * This structure holds context information for all SHA + * hashing operations. + */ +typedef struct USHAContext { + int whichSha; /* which SHA is being used */ + union { + SHA1Context sha1Context; + SHA224Context sha224Context; SHA256Context sha256Context; + SHA384Context sha384Context; SHA512Context sha512Context; + } ctx; + +} USHAContext; + +/* + * This structure will hold context information for the HMAC + * keyed-hashing operation. + */ +typedef struct HMACContext { + int whichSha; /* which SHA is being used */ + int hashSize; /* hash size of SHA being used */ + int blockSize; /* block size of SHA being used */ + USHAContext shaContext; /* SHA context */ + unsigned char k_opad[USHA_Max_Message_Block_Size]; + /* outer padding - key XORd with opad */ + int Computed; /* Is the MAC computed? */ + int Corrupted; /* Cumulative corruption code */ + +} HMACContext; + +/* + * This structure will hold context information for the HKDF + * extract-and-expand Key Derivation Functions. + */ +typedef struct HKDFContext { + int whichSha; /* which SHA is being used */ + HMACContext hmacContext; + int hashSize; /* hash size of SHA being used */ + unsigned char prk[USHAMaxHashSize]; + /* pseudo-random key - output of hkdfInput */ + int Computed; /* Is the key material computed? */ + int Corrupted; /* Cumulative corruption code */ +} HKDFContext; + +/* + * Function Prototypes + */ + +/* SHA-1 */ +extern int SHA1Reset(SHA1Context *); +extern int SHA1Input(SHA1Context *, const uint8_t *bytes, + unsigned int bytecount); +extern int SHA1FinalBits(SHA1Context *, uint8_t bits, + unsigned int bit_count); +extern int SHA1Result(SHA1Context *, + uint8_t Message_Digest[SHA1HashSize]); + +/* SHA-224 */ +extern int SHA224Reset(SHA224Context *); +extern int SHA224Input(SHA224Context *, const uint8_t *bytes, + unsigned int bytecount); +extern int SHA224FinalBits(SHA224Context *, uint8_t bits, + unsigned int bit_count); +extern int SHA224Result(SHA224Context *, + uint8_t Message_Digest[SHA224HashSize]); + +/* SHA-256 */ +extern int SHA256Reset(SHA256Context *); +extern int SHA256Input(SHA256Context *, const uint8_t *bytes, + unsigned int bytecount); +extern int SHA256FinalBits(SHA256Context *, uint8_t bits, + unsigned int bit_count); +extern int SHA256Result(SHA256Context *, + uint8_t Message_Digest[SHA256HashSize]); + +/* SHA-384 */ +extern int SHA384Reset(SHA384Context *); +extern int SHA384Input(SHA384Context *, const uint8_t *bytes, + unsigned int bytecount); +extern int SHA384FinalBits(SHA384Context *, uint8_t bits, + unsigned int bit_count); +extern int SHA384Result(SHA384Context *, + uint8_t Message_Digest[SHA384HashSize]); + +/* SHA-512 */ +extern int SHA512Reset(SHA512Context *); +extern int SHA512Input(SHA512Context *, const uint8_t *bytes, + unsigned int bytecount); +extern int SHA512FinalBits(SHA512Context *, uint8_t bits, + unsigned int bit_count); +extern int SHA512Result(SHA512Context *, + uint8_t Message_Digest[SHA512HashSize]); + +/* Unified SHA functions, chosen by whichSha */ +extern int USHAReset(USHAContext *context, SHAversion whichSha); +extern int USHAInput(USHAContext *context, + const uint8_t *bytes, unsigned int bytecount); +extern int USHAFinalBits(USHAContext *context, + uint8_t bits, unsigned int bit_count); +extern int USHAResult(USHAContext *context, + uint8_t Message_Digest[USHAMaxHashSize]); +extern int USHABlockSize(enum SHAversion whichSha); +extern int USHAHashSize(enum SHAversion whichSha); +extern int USHAHashSizeBits(enum SHAversion whichSha); +extern const char *USHAHashName(enum SHAversion whichSha); + +/* + * HMAC Keyed-Hashing for Message Authentication, RFC 2104, + * for all SHAs. + * This interface allows a fixed-length text input to be used. + */ +extern int hmac(SHAversion whichSha, /* which SHA algorithm to use */ + const unsigned char *text, /* pointer to data stream */ + int text_len, /* length of data stream */ + const unsigned char *key, /* pointer to authentication key */ + int key_len, /* length of authentication key */ + uint8_t digest[USHAMaxHashSize]); /* caller digest to fill in */ + +/* + * HMAC Keyed-Hashing for Message Authentication, RFC 2104, + * for all SHAs. + * This interface allows any length of text input to be used. + */ +extern int hmacReset(HMACContext *context, enum SHAversion whichSha, + const unsigned char *key, int key_len); +extern int hmacInput(HMACContext *context, const unsigned char *text, + int text_len); +extern int hmacFinalBits(HMACContext *context, uint8_t bits, + unsigned int bit_count); +extern int hmacResult(HMACContext *context, + uint8_t digest[USHAMaxHashSize]); + +/* + * HKDF HMAC-based Extract-and-Expand Key Derivation Function, + * RFC 5869, for all SHAs. + */ +extern int hkdf(SHAversion whichSha, const unsigned char *salt, + int salt_len, const unsigned char *ikm, int ikm_len, + const unsigned char *info, int info_len, + uint8_t okm[ ], int okm_len); +extern int hkdfExtract(SHAversion whichSha, const unsigned char *salt, + int salt_len, const unsigned char *ikm, + int ikm_len, uint8_t prk[USHAMaxHashSize]); +extern int hkdfExpand(SHAversion whichSha, const uint8_t prk[ ], + int prk_len, const unsigned char *info, + int info_len, uint8_t okm[ ], int okm_len); + +/* + * HKDF HMAC-based Extract-and-Expand Key Derivation Function, + * RFC 5869, for all SHAs. + * This interface allows any length of text input to be used. + */ +extern int hkdfReset(HKDFContext *context, enum SHAversion whichSha, + const unsigned char *salt, int salt_len); +extern int hkdfInput(HKDFContext *context, const unsigned char *ikm, + int ikm_len); +extern int hkdfFinalBits(HKDFContext *context, uint8_t ikm_bits, + unsigned int ikm_bit_count); +extern int hkdfResult(HKDFContext *context, + uint8_t prk[USHAMaxHashSize], + const unsigned char *info, int info_len, + uint8_t okm[USHAMaxHashSize], int okm_len); +#endif /* _SHA_H_ */ + diff --git a/lib/libesp32_div/ESP32-HomeKit/src/hkdf.c b/lib/libesp32_div/ESP32-HomeKit/src/hkdf.c new file mode 100644 index 000000000..bd12ef2e1 --- /dev/null +++ b/lib/libesp32_div/ESP32-HomeKit/src/hkdf.c @@ -0,0 +1,335 @@ +/**************************** hkdf.c ***************************/ +/***************** See RFC 6234 for details. *******************/ +/* Copyright (c) 2011 IETF Trust and the persons identified as */ +/* authors of the code. All rights reserved. */ +/* See sha.h for terms of use and redistribution. */ + +/* + * Description: + * This file implements the HKDF algorithm (HMAC-based + * Extract-and-Expand Key Derivation Function, RFC 5869), + * expressed in terms of the various SHA algorithms. + */ + +#include "sha.h" +#include +#include + +/* + * hkdf + * + * Description: + * This function will generate keying material using HKDF. + * + * Parameters: + * whichSha: [in] + * One of SHA1, SHA224, SHA256, SHA384, SHA512 + * salt[ ]: [in] + * The optional salt value (a non-secret random value); + * if not provided (salt == NULL), it is set internally + * to a string of HashLen(whichSha) zeros. + * salt_len: [in] + * The length of the salt value. (Ignored if salt == NULL.) + * ikm[ ]: [in] + * Input keying material. + * ikm_len: [in] + * The length of the input keying material. + * info[ ]: [in] + * The optional context and application specific information. + * If info == NULL or a zero-length string, it is ignored. + * info_len: [in] + * The length of the optional context and application specific + * information. (Ignored if info == NULL.) + * okm[ ]: [out] + * Where the HKDF is to be stored. + * okm_len: [in] + * The length of the buffer to hold okm. + * okm_len must be <= 255 * USHABlockSize(whichSha) + * + * Notes: + * Calls hkdfExtract() and hkdfExpand(). + * + * Returns: + * sha Error Code. + * + */ +int hkdf(SHAversion whichSha, + const unsigned char *salt, int salt_len, + const unsigned char *ikm, int ikm_len, + const unsigned char *info, int info_len, + uint8_t okm[ ], int okm_len) +{ + uint8_t prk[USHAMaxHashSize]; + return hkdfExtract(whichSha, salt, salt_len, ikm, ikm_len, prk) || + hkdfExpand(whichSha, prk, USHAHashSize(whichSha), info, + info_len, okm, okm_len); +} + +/* + * hkdfExtract + * + * Description: + * This function will perform HKDF extraction. + * + * Parameters: + * whichSha: [in] + * One of SHA1, SHA224, SHA256, SHA384, SHA512 + * salt[ ]: [in] + * The optional salt value (a non-secret random value); + * if not provided (salt == NULL), it is set internally + * to a string of HashLen(whichSha) zeros. + * salt_len: [in] + * The length of the salt value. (Ignored if salt == NULL.) + * ikm[ ]: [in] + * Input keying material. + * ikm_len: [in] + * The length of the input keying material. + * prk[ ]: [out] + * Array where the HKDF extraction is to be stored. + * Must be larger than USHAHashSize(whichSha); + * + * Returns: + * sha Error Code. + * + */ +int hkdfExtract(SHAversion whichSha, + const unsigned char *salt, int salt_len, + const unsigned char *ikm, int ikm_len, + uint8_t prk[USHAMaxHashSize]) +{ + unsigned char nullSalt[USHAMaxHashSize]; + if (salt == 0) { + salt = nullSalt; + salt_len = USHAHashSize(whichSha); + memset(nullSalt, '\0', salt_len); + } else if (salt_len < 0) { + return shaBadParam; + } + return hmac(whichSha, ikm, ikm_len, salt, salt_len, prk); +} + +/* + * hkdfExpand + * + * Description: + * This function will perform HKDF expansion. + * + * Parameters: + * whichSha: [in] + * One of SHA1, SHA224, SHA256, SHA384, SHA512 + * prk[ ]: [in] + * The pseudo-random key to be expanded; either obtained + * directly from a cryptographically strong, uniformly + * distributed pseudo-random number generator, or as the + * output from hkdfExtract(). + * prk_len: [in] + * The length of the pseudo-random key in prk; + * should at least be equal to USHAHashSize(whichSHA). + * info[ ]: [in] + * The optional context and application specific information. + * If info == NULL or a zero-length string, it is ignored. + * info_len: [in] + * The length of the optional context and application specific + * information. (Ignored if info == NULL.) + * okm[ ]: [out] + * Where the HKDF is to be stored. + * okm_len: [in] + * The length of the buffer to hold okm. + * okm_len must be <= 255 * USHABlockSize(whichSha) + * + * Returns: + * sha Error Code. + * + */ +int hkdfExpand(SHAversion whichSha, const uint8_t prk[ ], int prk_len, + const unsigned char *info, int info_len, + uint8_t okm[ ], int okm_len) +{ + int hash_len, N; + unsigned char T[USHAMaxHashSize]; + int Tlen, where, i; + + if (info == 0) { + info = (const unsigned char *)""; + info_len = 0; + } else if (info_len < 0) { + return shaBadParam; + } + if (okm_len <= 0) return shaBadParam; + if (!okm) return shaBadParam; + + hash_len = USHAHashSize(whichSha); + if (prk_len < hash_len) return shaBadParam; + N = okm_len / hash_len; + if ((okm_len % hash_len) != 0) N++; + if (N > 255) return shaBadParam; + + Tlen = 0; + where = 0; + for (i = 1; i <= N; i++) { + HMACContext context; + unsigned char c = i; + int ret = hmacReset(&context, whichSha, prk, prk_len) || + hmacInput(&context, T, Tlen) || + hmacInput(&context, info, info_len) || + hmacInput(&context, &c, 1) || + hmacResult(&context, T); + if (ret != shaSuccess) return ret; + memcpy(okm + where, T, + (i != N) ? hash_len : (okm_len - where)); + where += hash_len; + Tlen = hash_len; + } + return shaSuccess; +} + +/* + * hkdfReset + * + * Description: + * This function will initialize the hkdfContext in preparation + * for key derivation using the modular HKDF interface for + * arbitrary length inputs. + * + * Parameters: + * context: [in/out] + * The context to reset. + * whichSha: [in] + * One of SHA1, SHA224, SHA256, SHA384, SHA512 + * salt[ ]: [in] + * The optional salt value (a non-secret random value); + * if not provided (salt == NULL), it is set internally + * to a string of HashLen(whichSha) zeros. + * salt_len: [in] + * The length of the salt value. (Ignored if salt == NULL.) + * + * Returns: + * sha Error Code. + * + */ +int hkdfReset(HKDFContext *context, enum SHAversion whichSha, + const unsigned char *salt, int salt_len) +{ + unsigned char nullSalt[USHAMaxHashSize]; + if (!context) return shaNull; + + context->whichSha = whichSha; + context->hashSize = USHAHashSize(whichSha); + if (salt == 0) { + salt = nullSalt; + salt_len = context->hashSize; + memset(nullSalt, '\0', salt_len); + } + + return hmacReset(&context->hmacContext, whichSha, salt, salt_len); +} + +/* + * hkdfInput + * + * Description: + * This function accepts an array of octets as the next portion + * of the input keying material. It may be called multiple times. + * + * Parameters: + * context: [in/out] + * The HKDF context to update. + * ikm[ ]: [in] + * An array of octets representing the next portion of + * the input keying material. + * ikm_len: [in] + * The length of ikm. + * + * Returns: + * sha Error Code. + * + */ +int hkdfInput(HKDFContext *context, const unsigned char *ikm, + int ikm_len) +{ + if (!context) return shaNull; + if (context->Corrupted) return context->Corrupted; + if (context->Computed) return context->Corrupted = shaStateError; + return hmacInput(&context->hmacContext, ikm, ikm_len); +} + +/* + * hkdfFinalBits + * + * Description: + * This function will add in any final bits of the + * input keying material. + * + * Parameters: + * context: [in/out] + * The HKDF context to update + * ikm_bits: [in] + * The final bits of the input keying material, in the upper + * portion of the byte. (Use 0b###00000 instead of 0b00000### + * to input the three bits ###.) + * ikm_bit_count: [in] + * The number of bits in message_bits, between 1 and 7. + * + * Returns: + * sha Error Code. + */ +int hkdfFinalBits(HKDFContext *context, uint8_t ikm_bits, + unsigned int ikm_bit_count) +{ + if (!context) return shaNull; + if (context->Corrupted) return context->Corrupted; + if (context->Computed) return context->Corrupted = shaStateError; + return hmacFinalBits(&context->hmacContext, ikm_bits, ikm_bit_count); +} + +/* + * hkdfResult + * + * Description: + * This function will finish the HKDF extraction and perform the + * final HKDF expansion. + * + * Parameters: + * context: [in/out] + * The HKDF context to use to calculate the HKDF hash. + * prk[ ]: [out] + * An optional location to store the HKDF extraction. + * Either NULL, or pointer to a buffer that must be + * larger than USHAHashSize(whichSha); + * info[ ]: [in] + * The optional context and application specific information. + * If info == NULL or a zero-length string, it is ignored. + * info_len: [in] + * The length of the optional context and application specific + * information. (Ignored if info == NULL.) + * okm[ ]: [out] + * Where the HKDF is to be stored. + * okm_len: [in] + * The length of the buffer to hold okm. + * okm_len must be <= 255 * USHABlockSize(whichSha) + * + * Returns: + * sha Error Code. + * + */ +int hkdfResult(HKDFContext *context, + uint8_t prk[USHAMaxHashSize], + const unsigned char *info, int info_len, + uint8_t okm[ ], int okm_len) +{ + uint8_t prkbuf[USHAMaxHashSize]; + int ret; + + if (!context) return shaNull; + if (context->Corrupted) return context->Corrupted; + if (context->Computed) return context->Corrupted = shaStateError; + if (!okm) return context->Corrupted = shaBadParam; + if (!prk) prk = prkbuf; + + ret = hmacResult(&context->hmacContext, prk) || + hkdfExpand(context->whichSha, prk, context->hashSize, info, + info_len, okm, okm_len); + context->Computed = 1; + return context->Corrupted = ret; +} + diff --git a/lib/libesp32_div/ESP32-HomeKit/src/hmac.c b/lib/libesp32_div/ESP32-HomeKit/src/hmac.c new file mode 100644 index 000000000..b09c50e54 --- /dev/null +++ b/lib/libesp32_div/ESP32-HomeKit/src/hmac.c @@ -0,0 +1,249 @@ +/**************************** hmac.c ***************************/ +/***************** See RFC 6234 for details. *******************/ +/* Copyright (c) 2011 IETF Trust and the persons identified as */ +/* authors of the code. All rights reserved. */ +/* See sha.h for terms of use and redistribution. */ + +/* + * Description: + * This file implements the HMAC algorithm (Keyed-Hashing for + * Message Authentication, [RFC 2104]), expressed in terms of + * the various SHA algorithms. + */ + +#include "sha.h" + +/* + * hmac + * + * Description: + * This function will compute an HMAC message digest. + * + * Parameters: + * whichSha: [in] + * One of SHA1, SHA224, SHA256, SHA384, SHA512 + * message_array[ ]: [in] + * An array of octets representing the message. + * Note: in RFC 2104, this parameter is known + * as 'text'. + * length: [in] + * The length of the message in message_array. + * key[ ]: [in] + * The secret shared key. + * key_len: [in] + * The length of the secret shared key. + * digest[ ]: [out] + * Where the digest is to be returned. + * NOTE: The length of the digest is determined by + * the value of whichSha. + * + * Returns: + * sha Error Code. + * + */ + +int hmac(SHAversion whichSha, + const unsigned char *message_array, int length, + const unsigned char *key, int key_len, + uint8_t digest[USHAMaxHashSize]) +{ + HMACContext context; + return hmacReset(&context, whichSha, key, key_len) || + hmacInput(&context, message_array, length) || + hmacResult(&context, digest); +} + +/* + * hmacReset + * + * Description: + * This function will initialize the hmacContext in preparation + * for computing a new HMAC message digest. + * + * Parameters: + * context: [in/out] + * The context to reset. + * whichSha: [in] + * One of SHA1, SHA224, SHA256, SHA384, SHA512 + * key[ ]: [in] + * The secret shared key. + * key_len: [in] + * The length of the secret shared key. + * + * Returns: + * sha Error Code. + * + */ +int hmacReset(HMACContext *context, enum SHAversion whichSha, + const unsigned char *key, int key_len) +{ + int i, blocksize, hashsize, ret; + + /* inner padding - key XORd with ipad */ + unsigned char k_ipad[USHA_Max_Message_Block_Size]; + + /* temporary buffer when keylen > blocksize */ + unsigned char tempkey[USHAMaxHashSize]; + + if (!context) return shaNull; + context->Computed = 0; + context->Corrupted = shaSuccess; + + blocksize = context->blockSize = USHABlockSize(whichSha); + hashsize = context->hashSize = USHAHashSize(whichSha); + context->whichSha = whichSha; + + /* + * If key is longer than the hash blocksize, + * reset it to key = HASH(key). + */ + if (key_len > blocksize) { + USHAContext tcontext; + int err = USHAReset(&tcontext, whichSha) || + USHAInput(&tcontext, key, key_len) || + USHAResult(&tcontext, tempkey); + if (err != shaSuccess) return err; + + key = tempkey; + key_len = hashsize; + } + + /* + * The HMAC transform looks like: + * + * SHA(K XOR opad, SHA(K XOR ipad, text)) + * + * where K is an n byte key, 0-padded to a total of blocksize bytes, + * ipad is the byte 0x36 repeated blocksize times, + * opad is the byte 0x5c repeated blocksize times, + * and text is the data being protected. + */ + + /* store key into the pads, XOR'd with ipad and opad values */ + for (i = 0; i < key_len; i++) { + k_ipad[i] = key[i] ^ 0x36; + context->k_opad[i] = key[i] ^ 0x5c; + } + /* remaining pad bytes are '\0' XOR'd with ipad and opad values */ + for ( ; i < blocksize; i++) { + k_ipad[i] = 0x36; + context->k_opad[i] = 0x5c; + } + + /* perform inner hash */ + /* init context for 1st pass */ + ret = USHAReset(&context->shaContext, whichSha) || + /* and start with inner pad */ + USHAInput(&context->shaContext, k_ipad, blocksize); + return context->Corrupted = ret; +} + +/* + * hmacInput + * + * Description: + * This function accepts an array of octets as the next portion + * of the message. It may be called multiple times. + * + * Parameters: + * context: [in/out] + * The HMAC context to update. + * text[ ]: [in] + * An array of octets representing the next portion of + * the message. + * text_len: [in] + * The length of the message in text. + * + * Returns: + * sha Error Code. + * + */ +int hmacInput(HMACContext *context, const unsigned char *text, + int text_len) +{ + if (!context) return shaNull; + if (context->Corrupted) return context->Corrupted; + if (context->Computed) return context->Corrupted = shaStateError; + /* then text of datagram */ + return context->Corrupted = + USHAInput(&context->shaContext, text, text_len); +} + +/* + * hmacFinalBits + * + * Description: + * This function will add in any final bits of the message. + * + * Parameters: + * context: [in/out] + * The HMAC context to update. + * message_bits: [in] + * The final bits of the message, in the upper portion of the + * byte. (Use 0b###00000 instead of 0b00000### to input the + * three bits ###.) + * length: [in] + * The number of bits in message_bits, between 1 and 7. + * + * Returns: + * sha Error Code. + */ +int hmacFinalBits(HMACContext *context, + uint8_t bits, unsigned int bit_count) +{ + if (!context) return shaNull; + if (context->Corrupted) return context->Corrupted; + if (context->Computed) return context->Corrupted = shaStateError; + /* then final bits of datagram */ + return context->Corrupted = + USHAFinalBits(&context->shaContext, bits, bit_count); +} + +/* + * hmacResult + * + * Description: + * This function will return the N-byte message digest into the + * Message_Digest array provided by the caller. + * + * Parameters: + * context: [in/out] + * The context to use to calculate the HMAC hash. + * digest[ ]: [out] + * Where the digest is returned. + * NOTE 2: The length of the hash is determined by the value of + * whichSha that was passed to hmacReset(). + * + * Returns: + * sha Error Code. + * + */ +int hmacResult(HMACContext *context, uint8_t *digest) +{ + int ret; + if (!context) return shaNull; + if (context->Corrupted) return context->Corrupted; + if (context->Computed) return context->Corrupted = shaStateError; + + /* finish up 1st pass */ + /* (Use digest here as a temporary buffer.) */ + ret = + USHAResult(&context->shaContext, digest) || + + /* perform outer SHA */ + /* init context for 2nd pass */ + USHAReset(&context->shaContext, context->whichSha) || + + /* start with outer pad */ + USHAInput(&context->shaContext, context->k_opad, + context->blockSize) || + + /* then results of 1st hash */ + USHAInput(&context->shaContext, digest, context->hashSize) || + /* finish up 2nd pass */ + USHAResult(&context->shaContext, digest); + + context->Computed = 1; + return context->Corrupted = ret; +} + diff --git a/lib/libesp32_div/ESP32-HomeKit/src/jsmn/jsmn.h b/lib/libesp32_div/ESP32-HomeKit/src/jsmn/jsmn.h new file mode 100644 index 000000000..3178dcc97 --- /dev/null +++ b/lib/libesp32_div/ESP32-HomeKit/src/jsmn/jsmn.h @@ -0,0 +1,471 @@ +/* + * MIT License + * + * Copyright (c) 2010 Serge Zaitsev + * + * 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. + */ +#ifndef JSMN_H +#define JSMN_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef JSMN_STATIC +#define JSMN_API static +#else +#define JSMN_API extern +#endif + +/** + * JSON type identifier. Basic types are: + * o Object + * o Array + * o String + * o Other primitive: number, boolean (true/false) or null + */ +typedef enum { + JSMN_UNDEFINED = 0, + JSMN_OBJECT = 1, + JSMN_ARRAY = 2, + JSMN_STRING = 3, + JSMN_PRIMITIVE = 4 +} jsmntype_t; + +enum jsmnerr { + /* Not enough tokens were provided */ + JSMN_ERROR_NOMEM = -1, + /* Invalid character inside JSON string */ + JSMN_ERROR_INVAL = -2, + /* The string is not a full JSON packet, more bytes expected */ + JSMN_ERROR_PART = -3 +}; + +/** + * JSON token description. + * type type (object, array, string etc.) + * start start position in JSON data string + * end end position in JSON data string + */ +typedef struct jsmntok { + jsmntype_t type; + int start; + int end; + int size; +#ifdef JSMN_PARENT_LINKS + int parent; +#endif +} jsmntok_t; + +/** + * JSON parser. Contains an array of token blocks available. Also stores + * the string being parsed now and current position in that string. + */ +typedef struct jsmn_parser { + unsigned int pos; /* offset in the JSON string */ + unsigned int toknext; /* next token to allocate */ + int toksuper; /* superior token node, e.g. parent object or array */ +} jsmn_parser; + +/** + * Create JSON parser over an array of tokens + */ +JSMN_API void jsmn_init(jsmn_parser *parser); + +/** + * Run JSON parser. It parses a JSON data string into and array of tokens, each + * describing + * a single JSON object. + */ +JSMN_API int jsmn_parse(jsmn_parser *parser, const char *js, const size_t len, + jsmntok_t *tokens, const unsigned int num_tokens); + +#ifndef JSMN_HEADER +/** + * Allocates a fresh unused token from the token pool. + */ +static jsmntok_t *jsmn_alloc_token(jsmn_parser *parser, jsmntok_t *tokens, + const size_t num_tokens) { + jsmntok_t *tok; + if (parser->toknext >= num_tokens) { + return NULL; + } + tok = &tokens[parser->toknext++]; + tok->start = tok->end = -1; + tok->size = 0; +#ifdef JSMN_PARENT_LINKS + tok->parent = -1; +#endif + return tok; +} + +/** + * Fills token type and boundaries. + */ +static void jsmn_fill_token(jsmntok_t *token, const jsmntype_t type, + const int start, const int end) { + token->type = type; + token->start = start; + token->end = end; + token->size = 0; +} + +/** + * Fills next available token with JSON primitive. + */ +static int jsmn_parse_primitive(jsmn_parser *parser, const char *js, + const size_t len, jsmntok_t *tokens, + const size_t num_tokens) { + jsmntok_t *token; + int start; + + start = parser->pos; + + for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) { + switch (js[parser->pos]) { +#ifndef JSMN_STRICT + /* In strict mode primitive must be followed by "," or "}" or "]" */ + case ':': +#endif + case '\t': + case '\r': + case '\n': + case ' ': + case ',': + case ']': + case '}': + goto found; + default: + /* to quiet a warning from gcc*/ + break; + } + if (js[parser->pos] < 32 || js[parser->pos] >= 127) { + parser->pos = start; + return JSMN_ERROR_INVAL; + } + } +#ifdef JSMN_STRICT + /* In strict mode primitive must be followed by a comma/object/array */ + parser->pos = start; + return JSMN_ERROR_PART; +#endif + +found: + if (tokens == NULL) { + parser->pos--; + return 0; + } + token = jsmn_alloc_token(parser, tokens, num_tokens); + if (token == NULL) { + parser->pos = start; + return JSMN_ERROR_NOMEM; + } + jsmn_fill_token(token, JSMN_PRIMITIVE, start, parser->pos); +#ifdef JSMN_PARENT_LINKS + token->parent = parser->toksuper; +#endif + parser->pos--; + return 0; +} + +/** + * Fills next token with JSON string. + */ +static int jsmn_parse_string(jsmn_parser *parser, const char *js, + const size_t len, jsmntok_t *tokens, + const size_t num_tokens) { + jsmntok_t *token; + + int start = parser->pos; + + parser->pos++; + + /* Skip starting quote */ + for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) { + char c = js[parser->pos]; + + /* Quote: end of string */ + if (c == '\"') { + if (tokens == NULL) { + return 0; + } + token = jsmn_alloc_token(parser, tokens, num_tokens); + if (token == NULL) { + parser->pos = start; + return JSMN_ERROR_NOMEM; + } + jsmn_fill_token(token, JSMN_STRING, start + 1, parser->pos); +#ifdef JSMN_PARENT_LINKS + token->parent = parser->toksuper; +#endif + return 0; + } + + /* Backslash: Quoted symbol expected */ + if (c == '\\' && parser->pos + 1 < len) { + int i; + parser->pos++; + switch (js[parser->pos]) { + /* Allowed escaped symbols */ + case '\"': + case '/': + case '\\': + case 'b': + case 'f': + case 'r': + case 'n': + case 't': + break; + /* Allows escaped symbol \uXXXX */ + case 'u': + parser->pos++; + for (i = 0; i < 4 && parser->pos < len && js[parser->pos] != '\0'; + i++) { + /* If it isn't a hex character we have an error */ + if (!((js[parser->pos] >= 48 && js[parser->pos] <= 57) || /* 0-9 */ + (js[parser->pos] >= 65 && js[parser->pos] <= 70) || /* A-F */ + (js[parser->pos] >= 97 && js[parser->pos] <= 102))) { /* a-f */ + parser->pos = start; + return JSMN_ERROR_INVAL; + } + parser->pos++; + } + parser->pos--; + break; + /* Unexpected symbol */ + default: + parser->pos = start; + return JSMN_ERROR_INVAL; + } + } + } + parser->pos = start; + return JSMN_ERROR_PART; +} + +/** + * Parse JSON string and fill tokens. + */ +JSMN_API int jsmn_parse(jsmn_parser *parser, const char *js, const size_t len, + jsmntok_t *tokens, const unsigned int num_tokens) { + int r; + int i; + jsmntok_t *token; + int count = parser->toknext; + + for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) { + char c; + jsmntype_t type; + + c = js[parser->pos]; + switch (c) { + case '{': + case '[': + count++; + if (tokens == NULL) { + break; + } + token = jsmn_alloc_token(parser, tokens, num_tokens); + if (token == NULL) { + return JSMN_ERROR_NOMEM; + } + if (parser->toksuper != -1) { + jsmntok_t *t = &tokens[parser->toksuper]; +#ifdef JSMN_STRICT + /* In strict mode an object or array can't become a key */ + if (t->type == JSMN_OBJECT) { + return JSMN_ERROR_INVAL; + } +#endif + t->size++; +#ifdef JSMN_PARENT_LINKS + token->parent = parser->toksuper; +#endif + } + token->type = (c == '{' ? JSMN_OBJECT : JSMN_ARRAY); + token->start = parser->pos; + parser->toksuper = parser->toknext - 1; + break; + case '}': + case ']': + if (tokens == NULL) { + break; + } + type = (c == '}' ? JSMN_OBJECT : JSMN_ARRAY); +#ifdef JSMN_PARENT_LINKS + if (parser->toknext < 1) { + return JSMN_ERROR_INVAL; + } + token = &tokens[parser->toknext - 1]; + for (;;) { + if (token->start != -1 && token->end == -1) { + if (token->type != type) { + return JSMN_ERROR_INVAL; + } + token->end = parser->pos + 1; + parser->toksuper = token->parent; + break; + } + if (token->parent == -1) { + if (token->type != type || parser->toksuper == -1) { + return JSMN_ERROR_INVAL; + } + break; + } + token = &tokens[token->parent]; + } +#else + for (i = parser->toknext - 1; i >= 0; i--) { + token = &tokens[i]; + if (token->start != -1 && token->end == -1) { + if (token->type != type) { + return JSMN_ERROR_INVAL; + } + parser->toksuper = -1; + token->end = parser->pos + 1; + break; + } + } + /* Error if unmatched closing bracket */ + if (i == -1) { + return JSMN_ERROR_INVAL; + } + for (; i >= 0; i--) { + token = &tokens[i]; + if (token->start != -1 && token->end == -1) { + parser->toksuper = i; + break; + } + } +#endif + break; + case '\"': + r = jsmn_parse_string(parser, js, len, tokens, num_tokens); + if (r < 0) { + return r; + } + count++; + if (parser->toksuper != -1 && tokens != NULL) { + tokens[parser->toksuper].size++; + } + break; + case '\t': + case '\r': + case '\n': + case ' ': + break; + case ':': + parser->toksuper = parser->toknext - 1; + break; + case ',': + if (tokens != NULL && parser->toksuper != -1 && + tokens[parser->toksuper].type != JSMN_ARRAY && + tokens[parser->toksuper].type != JSMN_OBJECT) { +#ifdef JSMN_PARENT_LINKS + parser->toksuper = tokens[parser->toksuper].parent; +#else + for (i = parser->toknext - 1; i >= 0; i--) { + if (tokens[i].type == JSMN_ARRAY || tokens[i].type == JSMN_OBJECT) { + if (tokens[i].start != -1 && tokens[i].end == -1) { + parser->toksuper = i; + break; + } + } + } +#endif + } + break; +#ifdef JSMN_STRICT + /* In strict mode primitives are: numbers and booleans */ + case '-': + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case 't': + case 'f': + case 'n': + /* And they must not be keys of the object */ + if (tokens != NULL && parser->toksuper != -1) { + const jsmntok_t *t = &tokens[parser->toksuper]; + if (t->type == JSMN_OBJECT || + (t->type == JSMN_STRING && t->size != 0)) { + return JSMN_ERROR_INVAL; + } + } +#else + /* In non-strict mode every unquoted value is a primitive */ + default: +#endif + r = jsmn_parse_primitive(parser, js, len, tokens, num_tokens); + if (r < 0) { + return r; + } + count++; + if (parser->toksuper != -1 && tokens != NULL) { + tokens[parser->toksuper].size++; + } + break; + +#ifdef JSMN_STRICT + /* Unexpected char in strict mode */ + default: + return JSMN_ERROR_INVAL; +#endif + } + } + + if (tokens != NULL) { + for (i = parser->toknext - 1; i >= 0; i--) { + /* Unmatched opened object or array */ + if (tokens[i].start != -1 && tokens[i].end == -1) { + return JSMN_ERROR_PART; + } + } + } + + return count; +} + +/** + * Creates a new parser based over a given buffer with an array of tokens + * available. + */ +JSMN_API void jsmn_init(jsmn_parser *parser) { + parser->pos = 0; + parser->toknext = 0; + parser->toksuper = -1; +} + +#endif /* JSMN_HEADER */ + +#ifdef __cplusplus +} +#endif + +#endif /* JSMN_H */ diff --git a/lib/libesp32_div/ESP32-HomeKit/src/json_generator.c b/lib/libesp32_div/ESP32-HomeKit/src/json_generator.c new file mode 100644 index 000000000..947fb62b5 --- /dev/null +++ b/lib/libesp32_div/ESP32-HomeKit/src/json_generator.c @@ -0,0 +1,300 @@ +/* + * Copyright 2020 Piyush Shah + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include + +#include + +#define MAX_INT_IN_STR 24 +#define MAX_FLOAT_IN_STR 30 + +static inline int json_gen_get_empty_len(json_gen_str_t *jstr) +{ + return (jstr->buf_size - (jstr->free_ptr - jstr->buf) - 1); +} + +/* This will add the incoming string to the JSON string buffer + * and flush it out if the buffer is full. Note that the data being + * flushed out will always be equal to the size of the buffer unless + * this is the last chunk being flushed out on json_gen_end_str() + */ +static int json_gen_add_to_str(json_gen_str_t *jstr, char *str) +{ + if (!str) { + return 0; + } + int len = strlen(str); + char *cur_ptr = str; + while (1) { + int len_remaining = json_gen_get_empty_len(jstr); + int copy_len = len_remaining > len ? len : len_remaining; + memmove(jstr->free_ptr, cur_ptr, copy_len); + cur_ptr += copy_len; + jstr->free_ptr += copy_len; + len -= copy_len; + if (len) { + *jstr->free_ptr = '\0'; + /* Report error if the buffer is full and no flush callback + * is registered + */ + if (!jstr->flush_cb) { + return -1; + } + jstr->flush_cb(jstr->buf, jstr->priv); + jstr->free_ptr = jstr->buf; + } else + break; + } + return 0; +} + + +void json_gen_str_start(json_gen_str_t *jstr, char *buf, int buf_size, + json_gen_flush_cb_t flush_cb, void *priv) +{ + memset(jstr, 0, sizeof(json_gen_str_t)); + jstr->buf = buf; + jstr->buf_size = buf_size; + jstr->flush_cb = flush_cb; + jstr->free_ptr = buf; + jstr->priv = priv; +} + +void json_gen_str_end(json_gen_str_t *jstr) +{ + *jstr->free_ptr = '\0'; + if (jstr->flush_cb) + jstr->flush_cb(jstr->buf, jstr->priv); + memset(jstr, 0, sizeof(json_gen_str_t)); +} + +static inline void json_gen_handle_comma(json_gen_str_t *jstr) +{ + if (jstr->comma_req) + json_gen_add_to_str(jstr, ","); +} + + +static int json_gen_handle_name(json_gen_str_t *jstr, char *name) +{ + json_gen_add_to_str(jstr, "\""); + json_gen_add_to_str(jstr, name); + return json_gen_add_to_str(jstr, "\":"); +} + + +int json_gen_start_object(json_gen_str_t *jstr) +{ + json_gen_handle_comma(jstr); + jstr->comma_req = false; + return json_gen_add_to_str(jstr, "{"); +} + +int json_gen_end_object(json_gen_str_t *jstr) +{ + jstr->comma_req = true; + return json_gen_add_to_str(jstr, "}"); +} + + +int json_gen_start_array(json_gen_str_t *jstr) +{ + json_gen_handle_comma(jstr); + jstr->comma_req = false; + return json_gen_add_to_str(jstr, "["); +} + +int json_gen_end_array(json_gen_str_t *jstr) +{ + jstr->comma_req = true; + return json_gen_add_to_str(jstr, "]"); +} + +int json_gen_push_object(json_gen_str_t *jstr, char *name) +{ + json_gen_handle_comma(jstr); + json_gen_handle_name(jstr, name); + jstr->comma_req = false; + return json_gen_add_to_str(jstr, "{"); +} + +int json_gen_pop_object(json_gen_str_t *jstr) +{ + jstr->comma_req = true; + return json_gen_add_to_str(jstr, "}"); +} + +int json_gen_push_object_str(json_gen_str_t *jstr, char *name, char *object_str) +{ + json_gen_handle_comma(jstr); + json_gen_handle_name(jstr, name); + jstr->comma_req = true; + return json_gen_add_to_str(jstr, object_str); +} + +int json_gen_push_array(json_gen_str_t *jstr, char *name) +{ + json_gen_handle_comma(jstr); + json_gen_handle_name(jstr, name); + jstr->comma_req = false; + return json_gen_add_to_str(jstr, "["); +} +int json_gen_pop_array(json_gen_str_t *jstr) +{ + jstr->comma_req = true; + return json_gen_add_to_str(jstr, "]"); +} + +int json_gen_push_array_str(json_gen_str_t *jstr, char *name, char *array_str) +{ + json_gen_handle_comma(jstr); + json_gen_handle_name(jstr, name); + jstr->comma_req = true; + return json_gen_add_to_str(jstr, array_str); +} + +static int json_gen_set_bool(json_gen_str_t *jstr, bool val) +{ + jstr->comma_req = true; + if (val) + return json_gen_add_to_str(jstr, "true"); + else + return json_gen_add_to_str(jstr, "false"); +} +int json_gen_obj_set_bool(json_gen_str_t *jstr, char *name, bool val) +{ + json_gen_handle_comma(jstr); + json_gen_handle_name(jstr, name); + return json_gen_set_bool(jstr, val); +} + +int json_gen_arr_set_bool(json_gen_str_t *jstr, bool val) +{ + json_gen_handle_comma(jstr); + return json_gen_set_bool(jstr, val); +} + +static int json_gen_set_int(json_gen_str_t *jstr, int val) +{ + jstr->comma_req = true; + char str[MAX_INT_IN_STR]; + snprintf(str, MAX_INT_IN_STR, "%d", val); + return json_gen_add_to_str(jstr, str); +} + +int json_gen_obj_set_int(json_gen_str_t *jstr, char *name, int val) +{ + json_gen_handle_comma(jstr); + json_gen_handle_name(jstr, name); + return json_gen_set_int(jstr, val); +} + +int json_gen_arr_set_int(json_gen_str_t *jstr, int val) +{ + json_gen_handle_comma(jstr); + return json_gen_set_int(jstr, val); +} + + +static int json_gen_set_float(json_gen_str_t *jstr, float val) +{ + jstr->comma_req = true; + char str[MAX_FLOAT_IN_STR]; + snprintf(str, MAX_FLOAT_IN_STR, "%.*f", JSON_FLOAT_PRECISION, val); + return json_gen_add_to_str(jstr, str); +} +int json_gen_obj_set_float(json_gen_str_t *jstr, char *name, float val) +{ + json_gen_handle_comma(jstr); + json_gen_handle_name(jstr, name); + return json_gen_set_float(jstr, val); +} +int json_gen_arr_set_float(json_gen_str_t *jstr, float val) +{ + json_gen_handle_comma(jstr); + return json_gen_set_float(jstr, val); +} + +static int json_gen_set_string(json_gen_str_t *jstr, char *val) +{ + jstr->comma_req = true; + json_gen_add_to_str(jstr, "\""); + json_gen_add_to_str(jstr, val); + return json_gen_add_to_str(jstr, "\""); +} + +int json_gen_obj_set_string(json_gen_str_t *jstr, char *name, char *val) +{ + json_gen_handle_comma(jstr); + json_gen_handle_name(jstr, name); + return json_gen_set_string(jstr, val); +} + +int json_gen_arr_set_string(json_gen_str_t *jstr, char *val) +{ + json_gen_handle_comma(jstr); + return json_gen_set_string(jstr, val); +} + +static int json_gen_set_long_string(json_gen_str_t *jstr, char *val) +{ + jstr->comma_req = true; + json_gen_add_to_str(jstr, "\""); + return json_gen_add_to_str(jstr, val); +} + +int json_gen_obj_start_long_string(json_gen_str_t *jstr, char *name, char *val) +{ + json_gen_handle_comma(jstr); + json_gen_handle_name(jstr, name); + return json_gen_set_long_string(jstr, val); +} + +int json_gen_arr_start_long_string(json_gen_str_t *jstr, char *val) +{ + json_gen_handle_comma(jstr); + return json_gen_set_long_string(jstr, val); +} + +int json_gen_add_to_long_string(json_gen_str_t *jstr, char *val) +{ + return json_gen_add_to_str(jstr, val); +} + +int json_gen_end_long_string(json_gen_str_t *jstr) +{ + return json_gen_add_to_str(jstr, "\""); +} +static int json_gen_set_null(json_gen_str_t *jstr) +{ + jstr->comma_req = true; + return json_gen_add_to_str(jstr, "null"); +} +int json_gen_obj_set_null(json_gen_str_t *jstr, char *name) +{ + json_gen_handle_comma(jstr); + json_gen_handle_name(jstr, name); + return json_gen_set_null(jstr); +} + +int json_gen_arr_set_null(json_gen_str_t *jstr) +{ + json_gen_handle_comma(jstr); + return json_gen_set_null(jstr); +} diff --git a/lib/libesp32_div/ESP32-HomeKit/src/json_generator.h b/lib/libesp32_div/ESP32-HomeKit/src/json_generator.h new file mode 100644 index 000000000..540e12461 --- /dev/null +++ b/lib/libesp32_div/ESP32-HomeKit/src/json_generator.h @@ -0,0 +1,507 @@ +/* + * Copyright 2020 Piyush Shah + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * JSON String Generator + * + * This module can be used to create JSON strings with a facility + * to flush out data if the destination buffer is full. All commas + * and colons as required are automatically added by the APIs + * + */ +#ifndef _JSON_GENERATOR_H +#define _JSON_GENERATOR_H + +#include +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + +/** Float precision i.e. number of digits after decimal point */ +#ifndef JSON_FLOAT_PRECISION +#define JSON_FLOAT_PRECISION 5 +#endif + +/** JSON string flush callback prototype + * + * This is a prototype of the function that needs to be passed to + * json_gen_str_start() and which will be invoked by the JSON generator + * module either when the buffer is full or json_gen_str_end() ins invoked. + * + * \param[in] buf Pointer to a NULL terminated JSON string + * \param[in] priv Private data to be passed to the flush callback. Will + * be the same as the one passed to json_gen_str_start() + */ +typedef void (*json_gen_flush_cb_t) (char *buf, void *priv); + +/** JSON String structure + * + * Please do not set/modify any elements. + * Just define this structure and pass a pointer to it in the APIs below + */ +typedef struct { + /** Pointer to the JSON buffer provided by the calling function */ + char *buf; + /** Size of the above buffer */ + int buf_size; + /** (Optional) callback function to invoke when the buffer gets full */ + json_gen_flush_cb_t flush_cb; + /** (Optional) Private data to pass to the callback function */ + void *priv; + /** (For Internal use only) */ + bool comma_req; + /** (For Internal use only) */ + char *free_ptr; +} json_gen_str_t; + +/** Start a JSON String + * + * This is the first function to be called for creating a JSON string. + * It initializes the internal data structures. After the JSON string + * generation is over, the json_gen_str_end() function should be called. + * + * \param[out] jstr Pointer to an allocated \ref json_gen_str_t structure. + * This will be initialised internally and needs to be passed to all + * subsequent function calls + * \param[out] buf Pointer to an allocated buffer into which the JSON + * string will be written + * \param[in] buf_size Size of the buffer + * \param[in] flush_cb Pointer to the flushing function of type \ref json_gen_flush_cb_t + * which will be invoked either when the buffer is full or when json_gen_str_end() + * is invoked. Can be left NULL. + * \param[in] priv Private data to be passed to the flushing function callback. + * Can be something like a session identifier (Eg. socket). Can be left NULL. + */ +void json_gen_str_start(json_gen_str_t *jstr, char *buf, int buf_size, + json_gen_flush_cb_t flush_cb, void *priv); + +/** End JSON string + * + * This should be the last function to be called after the entire JSON string + * has been generated. + * + * \param[in] jstr Pointer to the \ref json_gen_str_t structure initialised by + * json_gen_str_start() + */ +void json_gen_str_end(json_gen_str_t *jstr); + +/** Start a JSON object + * + * This starts a JSON object by adding a '{' + * + * \param[in] jstr Pointer to the \ref json_gen_str_t structure initialised by + * json_gen_str_start() + * + * \return 0 on Success + * \return -1 if buffer is out of space (possible only if no callback function + * is passed to json_gen_str_start(). Else, buffer will be flushed out and new data + * added after that + */ +int json_gen_start_object(json_gen_str_t *jstr); + +/** End a JSON object + * + * This ends a JSON object by adding a '}' + * + * \param[in] jstr Pointer to the \ref json_gen_str_t structure initialised by + * json_gen_str_start() + * + * \return 0 on Success + * \return -1 if buffer is out of space (possible only if no callback function + * is passed to json_gen_str_start(). Else, buffer will be flushed out and new data + * added after that + */ +int json_gen_end_object(json_gen_str_t *jstr); + +/** Start a JSON array + * + * This starts a JSON object by adding a '[' + * + * \param[in] jstr Pointer to the \ref json_gen_str_t structure initialised by + * json_gen_str_start() + * + * \return 0 on Success + * \return -1 if buffer is out of space (possible only if no callback function + * is passed to json_gen_str_start(). Else, buffer will be flushed out and new data + * added after that + */ +int json_gen_start_array(json_gen_str_t *jstr); + +/** End a JSON object + * + * This ends a JSON object by adding a ']' + * + * \param[in] jstr Pointer to the \ref json_gen_str_t structure initialised by + * json_gen_str_start() + * + * \return 0 on Success + * \return -1 if buffer is out of space (possible only if no callback function + * is passed to json_gen_str_start(). Else, buffer will be flushed out and new data + * added after that + */ +int json_gen_end_array(json_gen_str_t *jstr); + +/** Push a named JSON object + * + * This adds a JSON object like "name":{ + * + * \param[in] jstr Pointer to the \ref json_gen_str_t structure initialised by + * json_gen_str_start() + * \param[in] name Name of the object + * + * \return 0 on Success + * \return -1 if buffer is out of space (possible only if no callback function + * is passed to json_gen_str_start(). Else, buffer will be flushed out and new data + * added after that + */ +int json_gen_push_object(json_gen_str_t *jstr, char *name); + +/** Pop a named JSON object + * + * This ends a JSON object by adding a '}'. This is basically same as + * json_gen_end_object() but included so as to complement json_gen_push_object() + * + * \param[in] jstr Pointer to the \ref json_gen_str_t structure initialised by + * json_gen_str_start() + * + * \return 0 on Success + * \return -1 if buffer is out of space (possible only if no callback function + * is passed to json_gen_str_start(). Else, buffer will be flushed out and new data + * added after that + */ +int json_gen_pop_object(json_gen_str_t *jstr); + +/** Push a JSON object string + * + * This adds a complete pre-formatted JSON object string to the JSON object. + * + * Eg. json_gen_push_object_str(jstr, "pre-formatted", "{\"a\":1,\"b\":2}"); + * This will add "pre-formatted":{"a":1,"b":2} + * + * \param[in] jstr Pointer to the \ref json_gen_str_t structure initialised by + * json_gen_str_start() + * \param[in] name Name of the JSON object string + * \param[in] object_str The pre-formatted JSON object string + * + * \return 0 on Success + * \return -1 if buffer is out of space (possible only if no callback function + * is passed to json_gen_str_start(). Else, buffer will be flushed out and new data + * added after that. + */ +int json_gen_push_object_str(json_gen_str_t *jstr, char *name, char *object_str); + +/** Push a named JSON array + * + * This adds a JSON array like "name":[ + * + * \param[in] jstr Pointer to the \ref json_gen_str_t structure initialised by + * json_gen_str_start() + * \param[in] name Name of the array + * + * \return 0 on Success + * \return -1 if buffer is out of space (possible only if no callback function + * is passed to json_gen_str_start(). Else, buffer will be flushed out and new data + * added after that + */ +int json_gen_push_array(json_gen_str_t *jstr, char *name); + +/** Pop a named JSON array + * + * This ends a JSON array by adding a ']'. This is basically same as + * json_gen_end_array() but included so as to complement json_gen_push_array() + * + * \param[in] jstr Pointer to the \ref json_gen_str_t structure initialised by + * json_gen_str_start() + * + * \return 0 on Success + * \return -1 if buffer is out of space (possible only if no callback function + * is passed to json_gen_str_start(). Else, buffer will be flushed out and new data + * added after that + */ +int json_gen_pop_array(json_gen_str_t *jstr); + +/** Push a JSON array string + * + * This adds a complete pre-formatted JSON array string to the JSON object. + * + * Eg. json_gen_push_object_str(jstr, "pre-formatted", "[1,2,3]"); + * This will add "pre-formatted":[1,2,3] + * + * \param[in] jstr Pointer to the \ref json_gen_str_t structure initialised by + * json_gen_str_start() + * \param[in] name Name of the JSON array string + * \param[in] array_str The pre-formatted JSON array string + * + * \return 0 on Success + * \return -1 if buffer is out of space (possible only if no callback function + * is passed to json_gen_str_start(). Else, buffer will be flushed out and new data + * added after that. + */ +int json_gen_push_array_str(json_gen_str_t *jstr, char *name, char *array_str); + +/** Add a boolean element to an object + * + * This adds a boolean element to an object. Eg. "bool_val":true + * + * \note This must be called between json_gen_start_object()/json_gen_push_object() + * and json_gen_end_object()/json_gen_pop_object() + * + * \param[in] jstr Pointer to the \ref json_gen_str_t structure initialised by + * json_gen_str_start() + * \param[in] name Name of the element + * \param[in] val Boolean value of the element + * + * \return 0 on Success + * \return -1 if buffer is out of space (possible only if no callback function + * is passed to json_gen_str_start(). Else, buffer will be flushed out and new data + * added after that + */ +int json_gen_obj_set_bool(json_gen_str_t *jstr, char *name, bool val); + +/** Add an integer element to an object + * + * This adds an integer element to an object. Eg. "int_val":28 + * + * \note This must be called between json_gen_start_object()/json_gen_push_object() + * and json_gen_end_object()/json_gen_pop_object() + * + * \param[in] jstr Pointer to the \ref json_gen_str_t structure initialised by + * json_gen_str_start() + * \param[in] name Name of the element + * \param[in] val Integer value of the element + * + * \return 0 on Success + * \return -1 if buffer is out of space (possible only if no callback function + * is passed to json_gen_str_start(). Else, buffer will be flushed out and new data + * added after that + */ +int json_gen_obj_set_int(json_gen_str_t *jstr, char *name, int val); + +/** Add a float element to an object + * + * This adds a float element to an object. Eg. "float_val":23.8 + * + * \note This must be called between json_gen_start_object()/json_gen_push_object() + * and json_gen_end_object()/json_gen_pop_object() + * + * \param[in] jstr Pointer to the \ref json_gen_str_t structure initialised by + * json_gen_str_start() + * \param[in] name Name of the element + * \param[in] val Float value of the element + * + * \return 0 on Success + * \return -1 if buffer is out of space (possible only if no callback function + * is passed to json_gen_str_start(). Else, buffer will be flushed out and new data + * added after that + */ +int json_gen_obj_set_float(json_gen_str_t *jstr, char *name, float val); + +/** Add a string element to an object + * + * This adds a string element to an object. Eg. "string_val":"my_string" + * + * \note This must be called between json_gen_start_object()/json_gen_push_object() + * and json_gen_end_object()/json_gen_pop_object() + * + * \param[in] jstr Pointer to the \ref json_gen_str_t structure initialised by + * json_gen_str_start() + * \param[in] name Name of the element + * \param[in] val Null terminated string value of the element + * + * \return 0 on Success + * \return -1 if buffer is out of space (possible only if no callback function + * is passed to json_gen_str_start(). Else, buffer will be flushed out and new data + * added after that + */ +int json_gen_obj_set_string(json_gen_str_t *jstr, char *name, char *val); + +/** Add a NULL element to an object + * + * This adds a NULL element to an object. Eg. "null_val":null + * + * \note This must be called between json_gen_start_object()/json_gen_push_object() + * and json_gen_end_object()/json_gen_pop_object() + * + * \param[in] jstr Pointer to the \ref json_gen_str_t structure initialised by + * json_gen_str_start() + * \param[in] name Name of the element + * + * \return 0 on Success + * \return -1 if buffer is out of space (possible only if no callback function + * is passed to json_gen_str_start(). Else, buffer will be flushed out and new data + * added after that + */ +int json_gen_obj_set_null(json_gen_str_t *jstr, char *name); + +/** Add a boolean element to an array + * + * \note This must be called between json_gen_start_array()/json_gen_push_array() + * and json_gen_end_array()/json_gen_pop_array() + * + * \param[in] jstr Pointer to the \ref json_gen_str_t structure initialised by + * json_gen_str_start() + * \param[in] val Boolean value of the element + * + * \return 0 on Success + * \return -1 if buffer is out of space (possible only if no callback function + * is passed to json_gen_str_start(). Else, buffer will be flushed out and new data + * added after that + */ +int json_gen_arr_set_bool(json_gen_str_t *jstr, bool val); + +/** Add an integer element to an array + * + * \note This must be called between json_gen_start_array()/json_gen_push_array() + * and json_gen_end_array()/json_gen_pop_array() + * + * \param[in] jstr Pointer to the \ref json_gen_str_t structure initialised by + * json_gen_str_start() + * \param[in] val Integer value of the element + * + * \return 0 on Success + * \return -1 if buffer is out of space (possible only if no callback function + * is passed to json_gen_str_start(). Else, buffer will be flushed out and new data + * added after that + */ +int json_gen_arr_set_int(json_gen_str_t *jstr, int val); + +/** Add a float element to an array + * + * \note This must be called between json_gen_start_array()/json_gen_push_array() + * and json_gen_end_array()/json_gen_pop_array() + * + * \param[in] jstr Pointer to the \ref json_gen_str_t structure initialised by + * json_gen_str_start() + * \param[in] val Float value of the element + * + * \return 0 on Success + * \return -1 if buffer is out of space (possible only if no callback function + * is passed to json_gen_str_start(). Else, buffer will be flushed out and new data + * added after that + */ +int json_gen_arr_set_float(json_gen_str_t *jstr, float val); + +/** Add a string element to an array + * + * \note This must be called between json_gen_start_array()/json_gen_push_array() + * and json_gen_end_array()/json_gen_pop_array() + * + * \param[in] jstr Pointer to the \ref json_gen_str_t structure initialised by + * json_gen_str_start() + * \param[in] val Null terminated string value of the element + * + * \return 0 on Success + * \return -1 if buffer is out of space (possible only if no callback function + * is passed to json_gen_str_start(). Else, buffer will be flushed out and new data + * added after that + */ +int json_gen_arr_set_string(json_gen_str_t *jstr, char *val); + +/** Add a NULL element to an array + * + * \note This must be called between json_gen_start_array()/json_gen_push_array() + * and json_gen_end_array()/json_gen_pop_array() + * + * \param[in] jstr Pointer to the \ref json_gen_str_t structure initialised by + * json_gen_str_start() + * + * \return 0 on Success + * \return -1 if buffer is out of space (possible only if no callback function + * is passed to json_gen_str_start(). Else, buffer will be flushed out and new data + * added after that + */ +int json_gen_arr_set_null(json_gen_str_t *jstr); + +/** Start a Long string in an object + * + * This starts a string in an object, but does not end it (i.e., does not add the + * terminating quotes. This is useful for long strings. Eg. "string_val":"my_string. + * The API json_gen_add_to_long_string() must be used to add to this string and the API + * json_gen_end_long_string() must be used to terminate it (i.e. add the ending quotes). + * + * \note This must be called between json_gen_start_object()/json_gen_push_object() + * and json_gen_end_object()/json_gen_pop_object() + * + * \param[in] jstr Pointer to the \ref json_gen_str_t structure initialised by + * json_gen_str_start() + * \param[in] name Name of the element + * \param[in] val Null terminated initial part of the string value. It can also be NULL + * + * \return 0 on Success + * \return -1 if buffer is out of space (possible only if no callback function + * is passed to json_gen_str_start(). Else, buffer will be flushed out and new data + * added after that + */ +int json_gen_obj_start_long_string(json_gen_str_t *jstr, char *name, char *val); + +/** Start a Long string in an array + * + * This starts a string in an arrayt, but does not end it (i.e., does not add the + * terminating quotes. This is useful for long strings. + * The API json_gen_add_to_long_string() must be used to add to this string and the API + * json_gen_end_long_string() must be used to terminate it (i.e. add the ending quotes). + * + * \note This must be called between json_gen_start_array()/json_gen_push_array() + * and json_gen_end_array()/json_gen_pop_array() + * + * \param[in] jstr Pointer to the \ref json_gen_str_t structure initialised by + * json_gen_str_start() + * \param[in] val Null terminated initial part of the string value. It can also be NULL + * + * \return 0 on Success + * \return -1 if buffer is out of space (possible only if no callback function + * is passed to json_gen_str_start(). Else, buffer will be flushed out and new data + * added after that + */ +int json_gen_arr_start_long_string(json_gen_str_t *jstr, char *val); + +/** Add to a JSON Long string + * + * This extends the string initialised by json_gen_obj_start_long_string() or + * json_gen_arr_start_long_string(). After the entire string is created, it should be terminated + * with json_gen_end_long_string(). + * + * \param[in] jstr Pointer to the \ref json_gen_str_t structure initialised by json_gen_str_start() + * \param[in] val Null terminated extending part of the string value. + * + * \return 0 on Success + * \return -1 if buffer is out of space (possible only if no callback function + * is passed to json_gen_str_start(). Else, buffer will be flushed out and new data + * added after that + */ +int json_gen_add_to_long_string(json_gen_str_t *jstr, char *val); + +/** End a JSON Long string + * + * This ends the string initialised by json_gen_obj_start_long_string() or + * json_gen_arr_start_long_string() by adding the ending quotes. + * + * \param[in] jstr Pointer to the \ref json_gen_str_t structure initialised by json_gen_str_start() + * + * + * \return 0 on Success + * \return -1 if buffer is out of space (possible only if no callback function + * is passed to json_gen_str_start(). Else, buffer will be flushed out and new data + * added after that + */ +int json_gen_end_long_string(json_gen_str_t *jstr); +#ifdef __cplusplus +} +#endif +#endif diff --git a/lib/libesp32_div/ESP32-HomeKit/src/json_parser.c b/lib/libesp32_div/ESP32-HomeKit/src/json_parser.c new file mode 100644 index 000000000..65a915591 --- /dev/null +++ b/lib/libesp32_div/ESP32-HomeKit/src/json_parser.c @@ -0,0 +1,398 @@ +/* + * Copyright 2020 Piyush Shah + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include +#include +#include +#include +#define JSMN_PARENT_LINKS +#define JSMN_STRICT +#define JSMN_STATIC +#include +#include + +static bool token_matches_str(jparse_ctx_t *ctx, json_tok_t *tok, char *str) +{ + char *js = ctx->js; + return ((strncmp(js + tok->start, str, strlen(str)) == 0) + && (strlen(str) == (size_t) (tok->end - tok->start))); +} + +static json_tok_t *json_skip_elem(json_tok_t *token) +{ + json_tok_t *cur = token; + int cnt = cur->size; + while (cnt--) { + cur++; + cur = json_skip_elem(cur); + } + return cur; +} + +static int json_tok_to_bool(jparse_ctx_t *jctx, json_tok_t *tok, bool *val) +{ + if (token_matches_str(jctx, tok, "true") || token_matches_str(jctx, tok, "1")) { + *val = true; + } else if (token_matches_str(jctx, tok, "false") || token_matches_str(jctx, tok, "0")) { + *val = false; + } else + return -OS_FAIL; + return OS_SUCCESS; +} + +static int json_tok_to_int(jparse_ctx_t *jctx, json_tok_t *tok, int *val) +{ + char *tok_start = &jctx->js[tok->start]; + char *tok_end = &jctx->js[tok->end]; + char *endptr; + int i = strtoul(tok_start, &endptr, 10); + if (endptr == tok_end) { + *val = i; + return OS_SUCCESS; + } + return -OS_FAIL; +} + +static int json_tok_to_int64(jparse_ctx_t *jctx, json_tok_t *tok, int64_t *val) +{ + char *tok_start = &jctx->js[tok->start]; + char *tok_end = &jctx->js[tok->end]; + char *endptr; + int64_t i64 = strtoull(tok_start, &endptr, 10); + if (endptr == tok_end) { + *val = i64; + return OS_SUCCESS; + } + return -OS_FAIL; +} + +static int json_tok_to_float(jparse_ctx_t *jctx, json_tok_t *tok, float *val) +{ + char *tok_start = &jctx->js[tok->start]; + char *tok_end = &jctx->js[tok->end]; + char *endptr; + float f = strtof(tok_start, &endptr); + if (endptr == tok_end) { + *val = f; + return OS_SUCCESS; + } + return -OS_FAIL; +} + +static int json_tok_to_string(jparse_ctx_t *jctx, json_tok_t *tok, char *val, int size) +{ + if ((tok->end - tok->start) > (size - 1)) + return -OS_FAIL; + strncpy(val, jctx->js + tok->start, tok->end - tok->start); + val[tok->end - tok->start] = 0; + return OS_SUCCESS; +} + +static json_tok_t *json_obj_search(jparse_ctx_t *jctx, char *key) +{ + json_tok_t *tok = jctx->cur; + int size = tok->size; + if (size <= 0) + return NULL; + if (tok->type != JSMN_OBJECT) + return NULL; + + while (size--) { + tok++; + if (token_matches_str(jctx, tok, key)) + return tok; + tok = json_skip_elem(tok); + } + return NULL; +} + +static json_tok_t *json_obj_get_val_tok(jparse_ctx_t *jctx, char *name, jsmntype_t type) +{ + json_tok_t *tok = json_obj_search(jctx, name); + if (!tok) + return NULL; + tok++; + if (tok->type != type) + return NULL; + return tok; +} + +int json_obj_get_array(jparse_ctx_t *jctx, char *name, int *num_elem) +{ + json_tok_t *tok = json_obj_get_val_tok(jctx, name, JSMN_ARRAY); + if (!tok) + return -OS_FAIL; + jctx->cur = tok; + *num_elem = tok->size; + return OS_SUCCESS; +} + +int json_obj_leave_array(jparse_ctx_t *jctx) +{ + /* The array's parent will be the key */ + if (jctx->cur->parent < 0) + return -OS_FAIL; + jctx->cur = &jctx->tokens[jctx->cur->parent]; + + /* The key's parent will be the actual parent object */ + if (jctx->cur->parent < 0) + return -OS_FAIL; + jctx->cur = &jctx->tokens[jctx->cur->parent]; + return OS_SUCCESS; +} + +int json_obj_get_object(jparse_ctx_t *jctx, char *name) +{ + json_tok_t *tok = json_obj_get_val_tok(jctx, name, JSMN_OBJECT); + if (!tok) + return -OS_FAIL; + jctx->cur = tok; + return OS_SUCCESS; +} + +int json_obj_leave_object(jparse_ctx_t *jctx) +{ + /* The objects's parent will be the key */ + if (jctx->cur->parent < 0) + return -OS_FAIL; + jctx->cur = &jctx->tokens[jctx->cur->parent]; + + /* The key's parent will be the actual parent object */ + if (jctx->cur->parent < 0) + return -OS_FAIL; + jctx->cur = &jctx->tokens[jctx->cur->parent]; + return OS_SUCCESS; +} + +int json_obj_get_bool(jparse_ctx_t *jctx, char *name, bool *val) +{ + json_tok_t *tok = json_obj_get_val_tok(jctx, name, JSMN_PRIMITIVE); + if (!tok) + return -OS_FAIL; + return json_tok_to_bool(jctx, tok, val); +} + +int json_obj_get_int(jparse_ctx_t *jctx, char *name, int *val) +{ + json_tok_t *tok = json_obj_get_val_tok(jctx, name, JSMN_PRIMITIVE); + if (!tok) + return -OS_FAIL; + return json_tok_to_int(jctx, tok, val); +} + +int json_obj_get_int64(jparse_ctx_t *jctx, char *name, int64_t *val) +{ + json_tok_t *tok = json_obj_get_val_tok(jctx, name, JSMN_PRIMITIVE); + if (!tok) + return -OS_FAIL; + return json_tok_to_int64(jctx, tok, val); +} + +int json_obj_get_float(jparse_ctx_t *jctx, char *name, float *val) +{ + json_tok_t *tok = json_obj_get_val_tok(jctx, name, JSMN_PRIMITIVE); + if (!tok) + return -OS_FAIL; + return json_tok_to_float(jctx, tok, val); +} + +int json_obj_get_string(jparse_ctx_t *jctx, char *name, char *val, int size) +{ + json_tok_t *tok = json_obj_get_val_tok(jctx, name, JSMN_STRING); + if (!tok) + return -OS_FAIL; + return json_tok_to_string(jctx, tok, val, size); +} + +int json_obj_get_strlen(jparse_ctx_t *jctx, char *name, int *strlen) +{ + json_tok_t *tok = json_obj_get_val_tok(jctx, name, JSMN_STRING); + if (!tok) + return -OS_FAIL; + *strlen = tok->end - tok->start; + return OS_SUCCESS; +} + +int json_obj_get_object_str(jparse_ctx_t *jctx, char *name, char *val, int size) +{ + json_tok_t *tok = json_obj_get_val_tok(jctx, name, JSMN_OBJECT); + if (!tok) + return -OS_FAIL; + return json_tok_to_string(jctx, tok, val, size); +} + +int json_obj_get_object_strlen(jparse_ctx_t *jctx, char *name, int *strlen) +{ + json_tok_t *tok = json_obj_get_val_tok(jctx, name, JSMN_OBJECT); + if (!tok) + return -OS_FAIL; + *strlen = tok->end - tok->start; + return OS_SUCCESS; +} +int json_obj_get_array_str(jparse_ctx_t *jctx, char *name, char *val, int size) +{ + json_tok_t *tok = json_obj_get_val_tok(jctx, name, JSMN_ARRAY); + if (!tok) + return -OS_FAIL; + return json_tok_to_string(jctx, tok, val, size); +} + +int json_obj_get_array_strlen(jparse_ctx_t *jctx, char *name, int *strlen) +{ + json_tok_t *tok = json_obj_get_val_tok(jctx, name, JSMN_ARRAY); + if (!tok) + return -OS_FAIL; + *strlen = tok->end - tok->start; + return OS_SUCCESS; +} + +static json_tok_t *json_arr_search(jparse_ctx_t *ctx, uint32_t index) +{ + json_tok_t *tok = ctx->cur; + if ((tok->type != JSMN_ARRAY) || (tok->size <= 0)) + return NULL; + if (index > (uint32_t)(tok->size - 1)) + return NULL; + /* Increment by 1, so that token points to index 0 */ + tok++; + while (index--) { + tok = json_skip_elem(tok); + tok++; + } + return tok; +} +static json_tok_t *json_arr_get_val_tok(jparse_ctx_t *jctx, uint32_t index, jsmntype_t type) +{ + json_tok_t *tok = json_arr_search(jctx, index); + if (!tok) + return NULL; + if (tok->type != type) + return NULL; + return tok; +} + +int json_arr_get_array(jparse_ctx_t *jctx, uint32_t index) +{ + json_tok_t *tok = json_arr_get_val_tok(jctx, index, JSMN_ARRAY); + if (!tok) + return -OS_FAIL; + jctx->cur = tok; + return OS_SUCCESS; +} + +int json_arr_leave_array(jparse_ctx_t *jctx) +{ + if (jctx->cur->parent < 0) + return -OS_FAIL; + jctx->cur = &jctx->tokens[jctx->cur->parent]; + return OS_SUCCESS; +} + +int json_arr_get_object(jparse_ctx_t *jctx, uint32_t index) +{ + json_tok_t *tok = json_arr_get_val_tok(jctx, index, JSMN_OBJECT); + if (!tok) + return -OS_FAIL; + jctx->cur = tok; + return OS_SUCCESS; +} + +int json_arr_leave_object(jparse_ctx_t *jctx) +{ + if (jctx->cur->parent < 0) + return -OS_FAIL; + jctx->cur = &jctx->tokens[jctx->cur->parent]; + return OS_SUCCESS; +} + +int json_arr_get_bool(jparse_ctx_t *jctx, uint32_t index, bool *val) +{ + json_tok_t *tok = json_arr_get_val_tok(jctx, index, JSMN_PRIMITIVE); + if (!tok) + return -OS_FAIL; + return json_tok_to_bool(jctx, tok, val); +} + +int json_arr_get_int(jparse_ctx_t *jctx, uint32_t index, int *val) +{ + json_tok_t *tok = json_arr_get_val_tok(jctx, index, JSMN_PRIMITIVE); + if (!tok) + return -OS_FAIL; + return json_tok_to_int(jctx, tok, val); +} + +int json_arr_get_int64(jparse_ctx_t *jctx, uint32_t index, int64_t *val) +{ + json_tok_t *tok = json_arr_get_val_tok(jctx, index, JSMN_PRIMITIVE); + if (!tok) + return -OS_FAIL; + return json_tok_to_int64(jctx, tok, val); +} + +int json_arr_get_float(jparse_ctx_t *jctx, uint32_t index, float *val) +{ + json_tok_t *tok = json_arr_get_val_tok(jctx, index, JSMN_PRIMITIVE); + if (!tok) + return -OS_FAIL; + return json_tok_to_float(jctx, tok, val); +} + +int json_arr_get_string(jparse_ctx_t *jctx, uint32_t index, char *val, int size) +{ + json_tok_t *tok = json_arr_get_val_tok(jctx, index, JSMN_STRING); + if (!tok) + return -OS_FAIL; + return json_tok_to_string(jctx, tok, val, size); +} + +int json_arr_get_strlen(jparse_ctx_t *jctx, uint32_t index, int *strlen) +{ + json_tok_t *tok = json_arr_get_val_tok(jctx, index, JSMN_STRING); + if (!tok) + return -OS_FAIL; + *strlen = tok->end - tok->start; + return OS_SUCCESS; +} + +int json_parse_start(jparse_ctx_t *jctx, char *js, int len) +{ + memset(jctx, 0, sizeof(jparse_ctx_t)); + jsmn_init(&jctx->parser); + int num_tokens = jsmn_parse(&jctx->parser, js, len, NULL, 0); + if (num_tokens <= 0) + return -OS_FAIL; + jctx->num_tokens = num_tokens; + jctx->tokens = calloc(num_tokens, sizeof(json_tok_t)); + if (!jctx->tokens) + return -OS_FAIL; + jctx->js = js; + jsmn_init(&jctx->parser); + int ret = jsmn_parse(&jctx->parser, js, len, jctx->tokens, jctx->num_tokens); + if (ret <= 0) { + free(jctx->tokens); + memset(jctx, 0, sizeof(jparse_ctx_t)); + return -OS_FAIL; + } + jctx->cur = jctx->tokens; + return OS_SUCCESS; +} + +int json_parse_end(jparse_ctx_t *jctx) +{ + if (jctx->tokens) + free(jctx->tokens); + memset(jctx, 0, sizeof(jparse_ctx_t)); + return OS_SUCCESS; +} diff --git a/lib/libesp32_div/ESP32-HomeKit/src/json_parser.h b/lib/libesp32_div/ESP32-HomeKit/src/json_parser.h new file mode 100644 index 000000000..3e982fe14 --- /dev/null +++ b/lib/libesp32_div/ESP32-HomeKit/src/json_parser.h @@ -0,0 +1,76 @@ +/* + * Copyright 2020 Piyush Shah + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef _JSON_PARSER_H_ +#define _JSON_PARSER_H_ + +#define JSMN_HEADER +#include +#include +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + +#define OS_SUCCESS 0 +#define OS_FAIL -1 + +typedef jsmn_parser json_parser_t; +typedef jsmntok_t json_tok_t; + +typedef struct { + json_parser_t parser; + char *js; + json_tok_t *tokens; + json_tok_t *cur; + int num_tokens; +} jparse_ctx_t; + +int json_parse_start(jparse_ctx_t *jctx, char *js, int len); +int json_parse_end(jparse_ctx_t *jctx); + +int json_obj_get_array(jparse_ctx_t *jctx, char *name, int *num_elem); +int json_obj_leave_array(jparse_ctx_t *jctx); +int json_obj_get_object(jparse_ctx_t *jctx, char *name); +int json_obj_leave_object(jparse_ctx_t *jctx); +int json_obj_get_bool(jparse_ctx_t *jctx, char *name, bool *val); +int json_obj_get_int(jparse_ctx_t *jctx, char *name, int *val); +int json_obj_get_int64(jparse_ctx_t *jctx, char *name, int64_t *val); +int json_obj_get_float(jparse_ctx_t *jctx, char *name, float *val); +int json_obj_get_string(jparse_ctx_t *jctx, char *name, char *val, int size); +int json_obj_get_strlen(jparse_ctx_t *jctx, char *name, int *strlen); +int json_obj_get_object_str(jparse_ctx_t *jctx, char *name, char *val, int size); +int json_obj_get_object_strlen(jparse_ctx_t *jctx, char *name, int *strlen); +int json_obj_get_array_str(jparse_ctx_t *jctx, char *name, char *val, int size); +int json_obj_get_array_strlen(jparse_ctx_t *jctx, char *name, int *strlen); + +int json_arr_get_array(jparse_ctx_t *jctx, uint32_t index); +int json_arr_leave_array(jparse_ctx_t *jctx); +int json_arr_get_object(jparse_ctx_t *jctx, uint32_t index); +int json_arr_leave_object(jparse_ctx_t *jctx); +int json_arr_get_bool(jparse_ctx_t *jctx, uint32_t index, bool *val); +int json_arr_get_int(jparse_ctx_t *jctx, uint32_t index, int *val); +int json_arr_get_int64(jparse_ctx_t *jctx, uint32_t index, int64_t *val); +int json_arr_get_float(jparse_ctx_t *jctx, uint32_t index, float *val); +int json_arr_get_string(jparse_ctx_t *jctx, uint32_t index, char *val, int size); +int json_arr_get_strlen(jparse_ctx_t *jctx, uint32_t index, int *strlen); + +#ifdef __cplusplus +} +#endif + +#endif /* _JSON_PARSER_H_ */ diff --git a/lib/libesp32_div/ESP32-HomeKit/src/mu_bignum.h b/lib/libesp32_div/ESP32-HomeKit/src/mu_bignum.h new file mode 100644 index 000000000..1bc60995a --- /dev/null +++ b/lib/libesp32_div/ESP32-HomeKit/src/mu_bignum.h @@ -0,0 +1,232 @@ +#ifndef _MU_BIGNUM_H_ +#define _MU_BIGNUM_H_ + +#define BIGNUM_MBEDTLS + +#ifdef BIGNUM_OPENSSL +#include + + +typedef BIGNUM mu_bn_t; +typedef BN_CTX mu_bn_ctx_t; + + +static inline mu_bn_t *mu_bn_new_from_hex(const char *hex) +{ + mu_bn_t *a = BN_new(); + if (a) + BN_hex2bn(&a, hex); + return a; +} + +static inline mu_bn_t *mu_bn_new_from_bin(const char *str, int str_len) +{ + return BN_bin2bn((unsigned char *)str, str_len, NULL); +} + +static inline mu_bn_t *mu_bn_new() +{ + return BN_new(); +} + +static inline void mu_bn_free(mu_bn_t *bn) +{ + return BN_free(bn); +} + +static inline mu_bn_ctx_t *mu_bn_ctx_new() +{ + return BN_CTX_new(); +} + +static inline void mu_bn_ctx_free(mu_bn_ctx_t *ctx) +{ + return BN_CTX_free(ctx); +} + +static inline unsigned int mu_bn_sizeof(mu_bn_t *bn) +{ + return BN_num_bytes(bn); +} + + +static inline char *mu_bn_to_bin(mu_bn_t *bn, int *len) +{ + *len = mu_bn_sizeof(bn); + char *p = malloc(*len); + if (p) { + BN_bn2bin(bn, (unsigned char *)p); + } + return p; +} + +static inline int mu_bn_get_rand(mu_bn_t *bn, int bits, int top, int bottom) +{ + return BN_rand(bn, bits, top, bottom); +} + +static inline int mu_bn_a_exp_b_mod_c(mu_bn_t *result, mu_bn_t *a, mu_bn_t *b, mu_bn_t *c, mu_bn_ctx_t *ctx) +{ + return BN_mod_exp(result, a, b, c, ctx); +} + +static inline int mu_bn_a_mul_b_mod_c(mu_bn_t *result, mu_bn_t *a, mu_bn_t *b, mu_bn_t *c, mu_bn_ctx_t *ctx) +{ + return BN_mod_mul(result, a, b, c, ctx); +} + +static inline int mu_bn_a_add_b_mod_c(mu_bn_t *result, mu_bn_t *a, mu_bn_t *b, mu_bn_t *c, mu_bn_ctx_t *ctx) +{ + if (BN_add(result, a, b) != 1) + return 1; + return BN_mod(result, result, c, ctx); +} +#endif /* BIGNUM_OPENSSL */ + + +#ifdef BIGNUM_MBEDTLS +#include +#include +#ifdef CONFIG_IDF_TARGET_ESP8266 +#include +#endif +typedef mbedtls_mpi mu_bn_t; +typedef mu_bn_t mu_bn_ctx_t; + +static inline mu_bn_t *mu_bn_new() +{ + mu_bn_t *a = malloc(sizeof (mu_bn_t)); + if (!a) + return NULL; + mbedtls_mpi_init(a); + return a; +} +static inline mu_bn_t *mu_bn_new_from_hex(const char *hex) +{ + mu_bn_t *a = mu_bn_new(); + if (!a) + return NULL; + + mbedtls_mpi_read_string(a, 16, hex); + return a; +} + +static inline mu_bn_t *mu_bn_new_from_bin(const char *str, int str_len) +{ + + mu_bn_t *a = mu_bn_new(); + if (!a) { + return NULL; + } + mbedtls_mpi_read_binary(a, (unsigned char *)str, str_len); + return a; +} + + +static inline void mu_bn_free(mu_bn_t *bn) +{ + if (bn) { + mbedtls_mpi_free(bn); + free(bn); + } +} + +static inline mu_bn_ctx_t *mu_bn_ctx_new() +{ + mu_bn_t *bn = mu_bn_new(); + return ( mu_bn_ctx_t *)bn; +} + +static inline void mu_bn_ctx_free(mu_bn_ctx_t *ctx) +{ + mu_bn_free((mu_bn_t *)ctx); +} + +static inline unsigned int mu_bn_sizeof(mu_bn_t *bn) +{ + return mbedtls_mpi_size(bn); +} + + +static inline char *mu_bn_to_bin(mu_bn_t *bn, int *len) +{ + *len = mu_bn_sizeof(bn); + char *p = malloc(*len); + if (p) { + mbedtls_mpi_write_binary(bn, (unsigned char *)p, *len); + } + return p; +} + +static inline int mu_get_random(void *ctx, unsigned char *data, size_t len) +{ + esp_fill_random(data, len); + return 0; +} +static inline int mu_bn_get_rand(mu_bn_t *bn, int bits, int top, int bottom) +{ + + return mbedtls_mpi_fill_random(bn, bits / 8, mu_get_random, NULL); +} + +#ifdef CONFIG_IDF_TARGET_ESP8266 +static inline int mu_bn_a_exp_b_mod_c(mu_bn_t *result, mu_bn_t *a, mu_bn_t *b, mu_bn_t *c, mu_bn_ctx_t *ctx) +{ + int ret; + rtc_clk_cpu_freq_set(RTC_CPU_FREQ_160M); + ret = mbedtls_mpi_exp_mod(result, a, b, c, (mu_bn_t *) ctx); + rtc_clk_cpu_freq_set(RTC_CPU_FREQ_80M); + return ret; +} +static inline int mu_bn_a_mul_b_mod_c(mu_bn_t *result, mu_bn_t *a, mu_bn_t *b, mu_bn_t *c, mu_bn_ctx_t *ctx) +{ + mbedtls_mpi tmp_result; + rtc_clk_cpu_freq_set(RTC_CPU_FREQ_160M); + mbedtls_mpi_init(&tmp_result); + mbedtls_mpi_mul_mpi(&tmp_result, a, b); + mbedtls_mpi_mod_mpi(result, &tmp_result, c); + mbedtls_mpi_free(&tmp_result); + rtc_clk_cpu_freq_set(RTC_CPU_FREQ_80M); + return 0; +} +#else + +#include "port/bignum.h" +#include "port/bignum_impl.h" + +static inline int mu_bn_a_exp_b_mod_c(mu_bn_t *result, mu_bn_t *a, mu_bn_t *b, mu_bn_t *c, mu_bn_ctx_t *ctx) +{ + //return mbedtls_mpi_exp_mod(result, a, b, c, (mu_bn_t *) ctx); + // wangbin changed + printf("esp_mpi_exp_mod\n"); + return esp_mpi_exp_mod(result, a, b, c, (mu_bn_t *) ctx); +} + + +static inline int mu_bn_a_mul_b_mod_c(mu_bn_t *result, mu_bn_t *a, mu_bn_t *b, mu_bn_t *c, mu_bn_ctx_t *ctx) +{ + printf("esp_mpi_mul_mpi_mod\n"); + return esp_mpi_mul_mpi_mod(result, a, b, c); +} +#endif /* !CONFIG_IDF_TARGET_ESP8266 */ + +static inline int mu_bn_a_add_b_mod_c(mu_bn_t *result, mu_bn_t *a, mu_bn_t *b, mu_bn_t *c, mu_bn_ctx_t *ctx) +{ + int res; + mbedtls_mpi t; +#ifdef CONFIG_IDF_TARGET_ESP8266 + rtc_clk_cpu_freq_set(RTC_CPU_FREQ_160M); +#endif + mbedtls_mpi_init(&t); + res = mbedtls_mpi_add_mpi(&t, a, b); + if (res == 0) { + res = mbedtls_mpi_mod_mpi(result, &t, c); + } + mbedtls_mpi_free(&t); +#ifdef CONFIG_IDF_TARGET_ESP8266 + rtc_clk_cpu_freq_set(RTC_CPU_FREQ_80M); +#endif + return res; +} +#endif /* BIGNUM_MBEDTLS */ +#endif /* ! _MU_BIGNUM_H_ */ diff --git a/lib/libesp32_div/ESP32-HomeKit/src/mu_srp.c b/lib/libesp32_div/ESP32-HomeKit/src/mu_srp.c new file mode 100644 index 000000000..7a14b93e0 --- /dev/null +++ b/lib/libesp32_div/ESP32-HomeKit/src/mu_srp.c @@ -0,0 +1,489 @@ +#include +#include "hkdf-sha.h" +#include "mu_bignum.h" +#include "mu_srp.h" + +#ifdef SRP_DEBUG +#include +#define srp_print printf +static void hex_dbg(char *name, void *buf, int buf_len) +{ + char *p = (char *)buf; + int i; + srp_print("%s (%d): ", name, buf_len); + for (i = 0; i < buf_len; i++) { + if (i % 16 == 0) + srp_print("\r\n"); + srp_print("%02x ", (unsigned)(unsigned char)p[i]); + } + srp_print("\r\n"); +} + +static void hex_dbg_bn(char *name, mu_bn_t *bn) +{ + int len; + char *str = mu_bn_to_bin(bn, &len); + if (str) { + hex_dbg(name, str, len); + free(str); + } +} +#else +#define srp_print(...) +#define hex_dbg(...) +#define hex_dbg_bn(...) +#endif + +static inline void SHA512_hash(const uint8_t *bytes, unsigned int byte_count, + uint8_t digest[SHA512HashSize]) +{ + SHA512Context ctx; + SHA512Reset(&ctx); + SHA512Input(&ctx, bytes, byte_count); + SHA512Result(&ctx, digest); +} + +/************************* SRP Stuff */ +char N_3072[] = { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, + 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, + 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, + 0x34, 0x04, 0xDD, 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D, + 0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, 0xE4, 0x85, 0xB5, + 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, + 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, + 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, + 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, + 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F, 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, + 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB, 0x9E, 0xD5, 0x29, 0x07, 0x70, + 0x96, 0x96, 0x6D, 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, 0xF1, 0x74, 0x6C, 0x08, + 0xCA, 0x18, 0x21, 0x7C, 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B, 0xE3, 0x9E, 0x77, + 0x2C, 0x18, 0x0E, 0x86, 0x03, 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F, 0xB5, 0xC5, + 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, 0x39, + 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10, + 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D, 0xAD, 0x33, 0x17, 0x0D, 0x04, 0x50, 0x7A, + 0x33, 0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64, 0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, + 0xEF, 0x0A, 0x8A, 0xEA, 0x71, 0x57, 0x5D, 0x06, 0x0C, 0x7D, 0xB3, 0x97, 0x0F, 0x85, 0xA6, + 0xE1, 0xE4, 0xC7, 0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7, 0x1E, 0x8C, 0x94, 0xE0, + 0x4A, 0x25, 0x61, 0x9D, 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B, 0xF1, 0x2F, 0xFA, + 0x06, 0xD9, 0x8A, 0x08, 0x64, 0xD8, 0x76, 0x02, 0x73, 0x3E, 0xC8, 0x6A, 0x64, 0x52, 0x1F, + 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C, 0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C, 0x77, + 0x09, 0x88, 0xC0, 0xBA, 0xD9, 0x46, 0xE2, 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31, + 0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E, 0x4B, 0x82, 0xD1, 0x20, 0xA9, 0x3A, 0xD2, + 0xCA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF +}; +char g_3072[] = { 5 }; + + +int mu_srp_init(mu_srp_handle_t *hd, mu_ng_type_t ng) +{ + if (hd->allocated) + mu_srp_free(hd); + + memset(hd, 0, sizeof(*hd)); + hd->allocated = 1; + + hd->ctx = mu_bn_ctx_new(); + if (! hd->ctx) + goto error; + if (ng != MU_NG_3072) + goto error; + + hd->n = mu_bn_new_from_bin(N_3072, sizeof(N_3072)); + hd->bytes_n = N_3072; + hd->len_n = sizeof(N_3072); + if (! hd->n) + goto error; + + hd->g = mu_bn_new_from_bin(g_3072, sizeof(g_3072)); + hd->bytes_g = g_3072; + hd->len_g = sizeof(g_3072); + if (! hd->g) + goto error; + hd->type = ng; + return 0; + error: + mu_srp_free(hd); + return -1; +} + +void mu_srp_free(mu_srp_handle_t *hd) +{ + if (hd->allocated != 1) + return; + + if (hd->ctx) + mu_bn_ctx_free(hd->ctx); + if (hd->n) + mu_bn_free(hd->n); + if (hd->g) + mu_bn_free(hd->g); + if (hd->s) + mu_bn_free(hd->s); + if (hd->bytes_s) + free(hd->bytes_s); + if (hd->v) + mu_bn_free(hd->v); + if (hd->B) + mu_bn_free(hd->B); + if (hd->bytes_B) + free(hd->bytes_B); + if (hd->b) + mu_bn_free(hd->b); + if (hd->A) + mu_bn_free(hd->A); + if (hd->bytes_A) + free(hd->bytes_A); + if (hd->session_key) + free(hd->session_key); + memset(hd, 0, sizeof(*hd)); +} + +static mu_bn_t *calculate_x(char *bytes_salt, int salt_len, const char *username, const char *pass, int pass_len) +{ + unsigned char digest[SHA512HashSize]; + SHA512Context ctx; + srp_print("username:%s:\npass:%s:\npass_len:%d:\n", username, pass, pass_len); + hex_dbg("salt", bytes_salt, salt_len); + SHA512Reset(&ctx); + SHA512Input(&ctx, (unsigned char *)username, strlen(username)); + SHA512Input(&ctx, (unsigned char *)":", 1); + SHA512Input(&ctx, (unsigned char *)pass, pass_len); + SHA512Result(&ctx, digest); + + SHA512Reset(&ctx); + SHA512Input(&ctx, (unsigned char *)bytes_salt, salt_len); + SHA512Input(&ctx, digest, sizeof(digest)); + SHA512Result(&ctx, digest); + + hex_dbg("Digest", digest, sizeof(digest)); + return mu_bn_new_from_bin((char *)digest, sizeof(digest)); +} + +static mu_bn_t *calculate_padded_hash(mu_srp_handle_t *hd, char *a, int len_a, char *b, int len_b) +{ + unsigned char digest[SHA512HashSize]; + SHA512Context ctx; + int pad_len; + char *s = NULL; + + if (len_a > len_b) { + pad_len = hd->len_n - len_b; + } else { + pad_len = hd->len_n - len_a; + } + + if (pad_len) { + s = malloc(pad_len); + if (s) { + memset(s, 0, pad_len); + } + } + + SHA512Reset(&ctx); + /* PAD (a) */ + if (s && (len_a != hd->len_n)) { + SHA512Input(&ctx, (unsigned char *)s, hd->len_n - len_a); + } + + SHA512Input(&ctx, (unsigned char *)a, len_a); + + /* PAD (b) */ + if (s && (len_b != hd->len_n)) { + SHA512Input(&ctx, (unsigned char *)s, hd->len_n - len_b); + } + + SHA512Input(&ctx, (unsigned char *)b, len_b); + + SHA512Result(&ctx, digest); + + if (s) { + free(s); + } + + hex_dbg("value", digest, sizeof(digest)); + return mu_bn_new_from_bin((char *)digest, sizeof(digest)); +} + +/* k = SHA (N, PAD(g)) + * + * https://tools.ietf.org/html/draft-ietf-tls-srp-08 + */ +static mu_bn_t *calculate_k(mu_srp_handle_t *hd) +{ + srp_print("k-->"); + return calculate_padded_hash(hd, hd->bytes_n, hd->len_n, hd->bytes_g, hd->len_g); +} + +static mu_bn_t *calculate_u(mu_srp_handle_t *hd, char *A, int len_A) +{ + srp_print("u-->"); + return calculate_padded_hash(hd, A, len_A, hd->bytes_B, hd->len_B); +} + +int __mu_srp_srv_pubkey(mu_srp_handle_t *hd, char **bytes_B, int *len_B) +{ + mu_bn_t *k = calculate_k(hd); + mu_bn_t *kv = NULL; + mu_bn_t *gb = NULL; + if (!k) + goto error; + + hd->b = mu_bn_new(); + if (!hd->b) + goto error; + mu_bn_get_rand(hd->b, 256, -1, 0); + hex_dbg_bn("b", hd->b); + + /* B = kv + g^b */ + kv = mu_bn_new(); + gb = mu_bn_new(); + hd->B = mu_bn_new(); + if (!kv || !gb || ! hd->B) + goto error; + mu_bn_a_mul_b_mod_c(kv, k, hd->v, hd->n, hd->ctx); + mu_bn_a_exp_b_mod_c(gb, hd->g, hd->b, hd->n, hd->ctx); + mu_bn_a_add_b_mod_c(hd->B, kv, gb, hd->n, hd->ctx); + hd->bytes_B = mu_bn_to_bin(hd->B, len_B); + hd->len_B = *len_B; + *bytes_B = hd->bytes_B; + + mu_bn_free(k); + mu_bn_free(kv); + mu_bn_free(gb); + return 0; + error: + if (k) + mu_bn_free(k); + if (kv) + mu_bn_free(kv); + if (gb) + mu_bn_free(gb); + if (hd->B) { + mu_bn_free(hd->B); + hd->B = NULL; + } + if (hd->b) { + mu_bn_free(hd->b); + hd->b = NULL; + } + return -1; + +} + +int mu_srp_srv_pubkey(mu_srp_handle_t *hd, const char *username, const char *pass, int pass_len, int salt_len, + char **bytes_B, int *len_B, char **bytes_salt) +{ + /* Get Salt */ + int str_salt_len; + mu_bn_t *x = NULL; + hd->s = mu_bn_new(); + if (! hd->s) + goto error; + mu_bn_get_rand(hd->s, 8 * salt_len, -1, 0); + *bytes_salt = mu_bn_to_bin(hd->s, &str_salt_len); + if (! *bytes_salt) + goto error; + hd->bytes_s = *bytes_salt; + hd->len_s = salt_len; + hex_dbg("Salt", *bytes_salt, str_salt_len); + + /* Calculate X which is simply a hash for all these things */ + x = calculate_x(*bytes_salt, str_salt_len, username, pass, pass_len); + if (! x) + goto error; + hex_dbg_bn("x", x); + + /* v = g^x % N */ + hd->v = mu_bn_new(); + if (! hd->v) + goto error; + mu_bn_a_exp_b_mod_c(hd->v, hd->g, x, hd->n, hd->ctx); + hex_dbg_bn("Verifier", hd->v); + + if (__mu_srp_srv_pubkey(hd, bytes_B, len_B) < 0 ) + goto error; + + mu_bn_free(x); + return 0; + +error: + if (hd->s) { + mu_bn_free(hd->s); + hd->s = NULL; + } + if (*bytes_salt) { + free(*bytes_salt); + *bytes_salt = NULL; + hd->bytes_s = NULL; + hd->len_s = 0; + } + if (x) { + mu_bn_free(x); + x = NULL; + } + if (hd->v) { + mu_bn_free(hd->v); + hd->v = NULL; + } + return -1; +} + +int mu_srp_srv_pubkey_from_salt_verifier(mu_srp_handle_t *hd, char **bytes_B, int *len_B) +{ + return __mu_srp_srv_pubkey(hd, bytes_B, len_B); +} + +int mu_srp_set_salt_verifier(mu_srp_handle_t *hd, const char *salt, int salt_len, + const char *verifier, int verifier_len) +{ + hd->bytes_s = malloc(salt_len); + if (!hd->bytes_s) { + goto error; + } + memcpy(hd->bytes_s, salt, salt_len); + hd->len_s = salt_len; + + hd->s = mu_bn_new_from_bin(salt, salt_len); + if (!hd->s) { + goto error; + } + + hd->v = mu_bn_new_from_bin(verifier, verifier_len); + if (!hd->v) { + goto error; + } + return 0; + +error: + if (hd->bytes_s) { + free(hd->bytes_s); + hd->bytes_s = NULL; + hd->len_s = 0; + } + if (hd->s) { + mu_bn_free(hd->s); + hd->s = NULL; + } + if (hd->v) { + mu_bn_free(hd->v); + hd->v = NULL; + } + return -1; +} + +int mu_srp_get_session_key(mu_srp_handle_t *hd, char *bytes_A, int len_A, char **bytes_key, int *len_key) +{ + mu_bn_t *u, *vu, *avu, *S; + char *bytes_S; + int len_S; + + u = vu = avu = S = NULL; + bytes_S = NULL; + + hd->bytes_A = malloc(len_A); + if (! hd->bytes_A) + goto error; + memcpy(hd->bytes_A, bytes_A, len_A); + hd->len_A = len_A; + + hd->A = mu_bn_new_from_bin(bytes_A, len_A); + if (! hd->A) + goto error; + u = calculate_u(hd, bytes_A, len_A); + if (! u) + goto error; + + /* S = (A v^u)^b */ + vu = mu_bn_new(); + avu = mu_bn_new(); + S = mu_bn_new(); + if (!vu || !avu || !S ) + goto error; + + mu_bn_a_exp_b_mod_c(vu, hd->v, u, hd->n, hd->ctx); + mu_bn_a_mul_b_mod_c(avu, hd->A, vu, hd->n, hd->ctx); + mu_bn_a_exp_b_mod_c(S, avu, hd->b, hd->n, hd->ctx); + hex_dbg_bn("S", S); + + bytes_S = mu_bn_to_bin(S, &len_S); + hd->session_key = malloc(SHA512HashSize); + if (!hd->session_key || ! bytes_S) + goto error; + + SHA512_hash((unsigned char *)bytes_S, len_S, (unsigned char *)hd->session_key); + *bytes_key = hd->session_key; + *len_key = SHA512HashSize; + + free(bytes_S); + mu_bn_free(vu); + mu_bn_free(avu); + mu_bn_free(S); + mu_bn_free(u); + return 0; + error: + if (bytes_S) + free(bytes_S); + if (vu) + mu_bn_free(vu); + if (avu) + mu_bn_free(avu); + if (S) + mu_bn_free(S); + if (u) + mu_bn_free(u); + if (hd->session_key) { + free(hd->session_key); + hd->session_key = NULL; + } + if (hd->A) { + mu_bn_free(hd->A); + hd->A = NULL; + } + if (hd->bytes_A) { + free(hd->bytes_A); + hd->bytes_A = NULL; + } + return -1; +} + +int mu_srp_exchange_proofs(mu_srp_handle_t *hd, char *username, char *bytes_user_proof, char *bytes_host_proof) +{ + /* First calculate M */ + unsigned char hash_n[SHA512HashSize]; + unsigned char hash_g[SHA512HashSize]; + unsigned char hash_n_xor_g[SHA512HashSize]; + int i; + SHA512_hash((unsigned char *)hd->bytes_n, hd->len_n, (unsigned char *)hash_n); + SHA512_hash((unsigned char *)hd->bytes_g, hd->len_g, (unsigned char *)hash_g); + for (i = 0; i < SHA512HashSize; i++) + hash_n_xor_g[i] = hash_n[i] ^ hash_g[i]; + + unsigned char hash_I[SHA512HashSize]; + SHA512_hash((unsigned char *)username, strlen(username), (unsigned char *)hash_I); + + SHA512Context ctx; + unsigned char digest[SHA512HashSize]; + SHA512Reset(&ctx); + SHA512Input(&ctx, hash_n_xor_g, SHA512HashSize); + SHA512Input(&ctx, hash_I, SHA512HashSize); + SHA512Input(&ctx, (unsigned char *)hd->bytes_s, hd->len_s); + SHA512Input(&ctx, (unsigned char *)hd->bytes_A, hd->len_A); + SHA512Input(&ctx, (unsigned char *)hd->bytes_B, hd->len_B); + SHA512Input(&ctx, (unsigned char *)hd->session_key, SHA512HashSize); + SHA512Result(&ctx, digest); + + hex_dbg("M", digest, sizeof(digest)); + if (memcmp(bytes_user_proof, digest, SHA512HashSize) != 0) + return false; + /* M is now validated, let's proceed to H(AMK) */ + SHA512Reset(&ctx); + SHA512Input(&ctx, (unsigned char *)hd->bytes_A, hd->len_A); + SHA512Input(&ctx, digest, SHA512HashSize); + SHA512Input(&ctx, (unsigned char *)hd->session_key, SHA512HashSize); + SHA512Result(&ctx, (unsigned char *)bytes_host_proof); + hex_dbg("AMK", bytes_host_proof, SHA512HashSize); + + return true; +} +/************************* SRP Stuff Ends */ diff --git a/lib/libesp32_div/ESP32-HomeKit/src/mu_srp.h b/lib/libesp32_div/ESP32-HomeKit/src/mu_srp.h new file mode 100644 index 000000000..8463ea318 --- /dev/null +++ b/lib/libesp32_div/ESP32-HomeKit/src/mu_srp.h @@ -0,0 +1,91 @@ +#ifndef _MU_SRP_H_ +#define _MU_SRP_H_ + +#include +#include "mu_bignum.h" + +typedef enum { + MU_NG_3072 = 0, +} mu_ng_type_t; + +typedef struct mu_srp_handle { + int allocated; + mu_ng_type_t type; + mu_bn_ctx_t *ctx; + + /* N + * the bytes_n simply points to the static array + */ + mu_bn_t *n; + char *bytes_n; + int len_n; + + /* g + * the bytes_g simply points to the static array + */ + mu_bn_t *g; + char *bytes_g; + int len_g; + + /* Salt */ + mu_bn_t *s; + char *bytes_s; + int len_s; + /* Verifier */ + mu_bn_t *v; + /* B */ + mu_bn_t *B; + char *bytes_B; + int len_B; + /* b */ + mu_bn_t *b; + /* A */ + mu_bn_t *A; + char *bytes_A; + int len_A; + /* K - session key*/ + char *session_key; +} mu_srp_handle_t; + +int mu_srp_init(mu_srp_handle_t *hd, mu_ng_type_t ng); + +void mu_srp_free(mu_srp_handle_t *hd); +/* Returns B (pub key) and salt + * + * *bytes_B MUST NOT BE FREED BY THE CALLER + * *bytes_salt MUST NOT BE FREE BY THE CALLER + * + */ +int mu_srp_srv_pubkey(mu_srp_handle_t *hd, const char *username, const char *pass, int pass_len, int salt_len, + char **bytes_B, int *len_B, char **bytes_salt); + +/* Set the Salt and Verifier pre-generated for a given password. + * This should be used only if the actual password is not available. + * The public key can then be generated using mu_srp_srv_pubkey_from_salt_verifier() + * and not mu_srp_srv_pubkey() + */ +int mu_srp_set_salt_verifier(mu_srp_handle_t *hd, const char *salt, int salt_len, + const char *verifier, int verifier_len); + +/* Returns B (pub key) when the salt and verifier are set using mu_srp_set_salt_verifier() + * + * *bytes_B MUST NOT BE FREED BY THE CALLER + */ +int mu_srp_srv_pubkey_from_salt_verifier(mu_srp_handle_t *hd, char **bytes_B, int *len_B); + +/* Returns bytes_key + * *bytes_key MUST NOT BE FREED BY THE CALLER + */ +int mu_srp_get_session_key(mu_srp_handle_t *hd, char *bytes_A, int len_A, char **bytes_key, int *len_key); + +/* Exchange proofs + * Returns 1 if user's proof is ok. Also 1 when is returned, bytes_host_proof contains our proof. + * + * bytes_user_proof is parameter in + * bytes_host_proof is parameter out (should be SHA512_DIGEST_LENGTH) bytes in size + */ +int mu_srp_exchange_proofs(mu_srp_handle_t *hd, char *username, char *bytes_user_proof, char *bytes_host_proof); + + + +#endif /* ! _MU_SRP_H_ */ diff --git a/lib/libesp32_div/ESP32-HomeKit/src/port/bignum.c b/lib/libesp32_div/ESP32-HomeKit/src/port/bignum.c new file mode 100644 index 000000000..32c593262 --- /dev/null +++ b/lib/libesp32_div/ESP32-HomeKit/src/port/bignum.c @@ -0,0 +1,279 @@ +/** + * \brief Multi-precision integer library, ESP-IDF hardware accelerated parts + * + * based on mbedTLS implementation + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Additions Copyright (C) 2016-2020, Espressif Systems (Shanghai) PTE Ltd + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +//#include "soc/hwcrypto_periph.h" +#include "soc/hwcrypto_reg.h" +#include "driver/periph_ctrl.h" +#include +#include "bignum_impl.h" +#include +#include + +static _lock_t mpi_lock; + +/* Round up number of words to nearest + 512 bit (16 word) block count. +*/ +size_t esp_mpi_hardware_words(size_t words) +{ + return (words + 0xF) & ~0xF; +} + +void esp_mpi_enable_hardware_hw_op( void ) +{ + /* newlib locks lazy initialize on ESP-IDF */ + _lock_acquire(&mpi_lock); + + /* Enable RSA hardware */ + periph_module_enable(PERIPH_RSA_MODULE); + DPORT_REG_CLR_BIT(DPORT_RSA_PD_CTRL_REG, DPORT_RSA_PD); + + while (DPORT_REG_READ(RSA_CLEAN_REG) != 1) + { } + // Note: from enabling RSA clock to here takes about 1.3us +} + +void esp_mpi_disable_hardware_hw_op( void ) +{ + DPORT_REG_SET_BIT(DPORT_RSA_PD_CTRL_REG, DPORT_RSA_PD); + + /* Disable RSA hardware */ + periph_module_disable(PERIPH_RSA_MODULE); + + _lock_release(&mpi_lock); +} + + +/* Copy mbedTLS MPI bignum 'mpi' to hardware memory block at 'mem_base'. + + If hw_words is higher than the number of words in the bignum then + these additional words will be zeroed in the memory buffer. + +*/ +static inline void mpi_to_mem_block(uint32_t mem_base, const mbedtls_mpi *mpi, size_t hw_words) +{ + uint32_t *pbase = (uint32_t *)mem_base; + uint32_t copy_words = MIN(hw_words, mpi->n); + + /* Copy MPI data to memory block registers */ + for (int i = 0; i < copy_words; i++) { + pbase[i] = mpi->p[i]; + } + + /* Zero any remaining memory block data */ + for (int i = copy_words; i < hw_words; i++) { + pbase[i] = 0; + } +} + +/* Read mbedTLS MPI bignum back from hardware memory block. + + Reads num_words words from block. + + Bignum 'x' should already be grown to at least num_words by caller (can be done while + calculation is in progress, to save some cycles) +*/ +static inline void mem_block_to_mpi(mbedtls_mpi *x, uint32_t mem_base, int num_words) +{ + assert(x->n >= num_words); + + /* Copy data from memory block registers */ + esp_dport_access_read_buffer(x->p, mem_base, num_words); + + /* Zero any remaining limbs in the bignum, if the buffer is bigger + than num_words */ + for (size_t i = num_words; i < x->n; i++) { + x->p[i] = 0; + } +} + + +/* Begin an RSA operation. op_reg specifies which 'START' register + to write to. +*/ +static inline void start_op(uint32_t op_reg) +{ + /* Clear interrupt status */ + DPORT_REG_WRITE(RSA_INTERRUPT_REG, 1); + + /* Note: above REG_WRITE includes a memw, so we know any writes + to the memory blocks are also complete. */ + + DPORT_REG_WRITE(op_reg, 1); +} + +/* Wait for an RSA operation to complete. +*/ +static inline void wait_op_complete(void) +{ + while (DPORT_REG_READ(RSA_INTERRUPT_REG) != 1) + { } + + /* clear the interrupt */ + DPORT_REG_WRITE(RSA_INTERRUPT_REG, 1); +} + +/* Read result from last MPI operation */ +void esp_mpi_read_result_hw_op(mbedtls_mpi *Z, size_t z_words) +{ + wait_op_complete(); + mem_block_to_mpi(Z, RSA_MEM_Z_BLOCK_BASE, z_words); +} + +/* Z = (X * Y) mod M */ +void esp_mpi_mul_mpi_mod_hw_op(const mbedtls_mpi *X, const mbedtls_mpi *Y, const mbedtls_mpi *M, const mbedtls_mpi *Rinv, mbedtls_mpi_uint Mprime, size_t hw_words) +{ + /* Load M, X, Rinv, Mprime (Mprime is mod 2^32) */ + mpi_to_mem_block(RSA_MEM_M_BLOCK_BASE, M, hw_words); + mpi_to_mem_block(RSA_MEM_X_BLOCK_BASE, X, hw_words); + mpi_to_mem_block(RSA_MEM_RB_BLOCK_BASE, Rinv, hw_words); + DPORT_REG_WRITE(RSA_M_DASH_REG, (uint32_t)Mprime); + + /* "mode" register loaded with number of 512-bit blocks, minus 1 */ + DPORT_REG_WRITE(RSA_MULT_MODE_REG, (hw_words / 16) - 1); + + /* Execute first stage montgomery multiplication */ + start_op(RSA_MULT_START_REG); + + wait_op_complete(); + + /* execute second stage */ + /* Load Y to X input memory block, rerun */ + mpi_to_mem_block(RSA_MEM_X_BLOCK_BASE, Y, hw_words); + + start_op(RSA_MULT_START_REG); +} + +/* Z = X * Y */ +void esp_mpi_mul_mpi_hw_op(const mbedtls_mpi *X, const mbedtls_mpi *Y, size_t hw_words) +{ + /* Copy X (right-extended) & Y (left-extended) to memory block */ + mpi_to_mem_block(RSA_MEM_X_BLOCK_BASE, X, hw_words); + mpi_to_mem_block(RSA_MEM_Z_BLOCK_BASE + hw_words * 4, Y, hw_words); + /* NB: as Y is left-extended, we don't zero the bottom words_mult words of Y block. + This is OK for now because zeroing is done by hardware when we do esp_mpi_acquire_hardware(). + */ + + DPORT_REG_WRITE(RSA_M_DASH_REG, 0); + + /* "mode" register loaded with number of 512-bit blocks in result, + plus 7 (for range 9-12). (this is ((N~ / 32) - 1) + 8)) + */ + DPORT_REG_WRITE(RSA_MULT_MODE_REG, ((hw_words * 2) / 16) + 7); + + start_op(RSA_MULT_START_REG); + +} + + +int esp_mont_hw_op(mbedtls_mpi *Z, const mbedtls_mpi *X, const mbedtls_mpi *Y, const mbedtls_mpi *M, + mbedtls_mpi_uint Mprime, + size_t hw_words, + bool again) +{ + // Note Z may be the same pointer as X or Y + int ret = 0; + + // montgomery mult prepare + if (again == false) { + mpi_to_mem_block(RSA_MEM_M_BLOCK_BASE, M, hw_words); + DPORT_REG_WRITE(RSA_M_DASH_REG, Mprime); + DPORT_REG_WRITE(RSA_MULT_MODE_REG, hw_words / 16 - 1); + } + + mpi_to_mem_block(RSA_MEM_X_BLOCK_BASE, X, hw_words); + mpi_to_mem_block(RSA_MEM_RB_BLOCK_BASE, Y, hw_words); + + start_op(RSA_MULT_START_REG); + Z->s = 1; // The sign of Z will be = M->s (but M->s is always 1) + MBEDTLS_MPI_CHK( mbedtls_mpi_grow(Z, hw_words) ); + + wait_op_complete(); + + /* Read back the result */ + mem_block_to_mpi(Z, RSA_MEM_Z_BLOCK_BASE, hw_words); + + + /* from HAC 14.36 - 3. If Z >= M then Z = Z - M */ + if (mbedtls_mpi_cmp_mpi(Z, M) >= 0) { + MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(Z, Z, M)); + } +cleanup: + return ret; +} + + + +/* Special-case of mbedtls_mpi_mult_mpi(), where we use hardware montgomery mod + multiplication to calculate an mbedtls_mpi_mult_mpi result where either + A or B are >2048 bits so can't use the standard multiplication method. + + Result (z_words, based on A bits + B bits) must still be less than 4096 bits. + + This case is simpler than the general case modulo multiply of + esp_mpi_mul_mpi_mod() because we can control the other arguments: + + * Modulus is chosen with M=(2^num_bits - 1) (ie M=R-1), so output + isn't actually modulo anything. + * Mprime and Rinv are therefore predictable as follows: + Mprime = 1 + Rinv = 1 + + (See RSA Accelerator section in Technical Reference for more about Mprime, Rinv) +*/ +void esp_mpi_mult_mpi_failover_mod_mult_hw_op(const mbedtls_mpi *X, const mbedtls_mpi *Y, size_t num_words) +{ + size_t hw_words = num_words; + + /* M = 2^num_words - 1, so block is entirely FF */ + for (int i = 0; i < hw_words; i++) { + DPORT_REG_WRITE(RSA_MEM_M_BLOCK_BASE + i * 4, UINT32_MAX); + } + /* Mprime = 1 */ + DPORT_REG_WRITE(RSA_M_DASH_REG, 1); + + /* "mode" register loaded with number of 512-bit blocks, minus 1 */ + DPORT_REG_WRITE(RSA_MULT_MODE_REG, (hw_words / 16) - 1); + + /* Load X */ + mpi_to_mem_block(RSA_MEM_X_BLOCK_BASE, X, hw_words); + + /* Rinv = 1, write first word */ + DPORT_REG_WRITE(RSA_MEM_RB_BLOCK_BASE, 1); + + /* Zero out rest of the Rinv words */ + for (int i = 1; i < hw_words; i++) { + DPORT_REG_WRITE(RSA_MEM_RB_BLOCK_BASE + i * 4, 0); + } + + start_op(RSA_MULT_START_REG); + + wait_op_complete(); + + /* finish the modular multiplication */ + /* Load Y to X input memory block, rerun */ + mpi_to_mem_block(RSA_MEM_X_BLOCK_BASE, Y, hw_words); + + start_op(RSA_MULT_START_REG); + +} diff --git a/lib/libesp32_div/ESP32-HomeKit/src/port/bignum.h b/lib/libesp32_div/ESP32-HomeKit/src/port/bignum.h new file mode 100644 index 000000000..5ead8cc6f --- /dev/null +++ b/lib/libesp32_div/ESP32-HomeKit/src/port/bignum.h @@ -0,0 +1,80 @@ +// Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#pragma once + +#include_next "mbedtls/bignum.h" +#include "sdkconfig.h" + +/** + * This is a wrapper for the main mbedtls/bignum.h. This wrapper + * provides a few additional ESP32-only functions. + * + * This is because we don't set MBEDTLS_BIGNUM_ALT in the same way we + * do for AES, SHA, etc. Because we still use most of the bignum.h + * implementation and just replace a few hardware accelerated + * functions (see MBEDTLS_MPI_EXP_MOD_ALT & MBEDTLS_MPI_MUL_MPI_ALT in + * esp_config.h). + * + * @note Unlike the other hardware accelerator support functions in esp32/hwcrypto, there is no + * generic "hwcrypto/bignum.h" header for using these functions without mbedTLS. The reason for this + * is that all of the function implementations depend strongly upon the mbedTLS MPI implementation. + */ + +/** + * @brief Lock access to RSA Accelerator (MPI/bignum operations) + * + * RSA Accelerator hardware unit can only be used by one + * consumer at a time. + * + * @note This function is non-recursive (do not call it twice from the + * same task.) + * + * @note You do not need to call this if you are using the mbedTLS bignum.h + * API or esp_mpi_xxx functions. This function is only needed if you + * want to call ROM RSA functions or access the registers directly. + * + */ +void esp_mpi_acquire_hardware(void); + +/** + * @brief Unlock access to RSA Accelerator (MPI/bignum operations) + * + * Has to be called once for each call to esp_mpi_acquire_hardware(). + * + * @note You do not need to call this if you are using the mbedTLS bignum.h + * API or esp_mpi_xxx functions. This function is only needed if you + * want to call ROM RSA functions or access the registers directly. + */ +void esp_mpi_release_hardware(void); + +//#if CONFIG_MBEDTLS_HARDWARE_MPI + +/* @brief MPI modular mupltiplication function + * + * Calculates Z = (X * Y) mod M using MPI hardware acceleration. + * + * This is not part of the standard mbedTLS bignum API. + * + * @note All of X, Y & Z should be less than 4096 bit long or an error is returned. + * + * @param Z Result bignum, should be pre-initialised with mbedtls_mpi_init(). + * @param X First multiplication argument. + * @param Y Second multiplication argument. + * @param M Modulus value for result. + * + * @return 0 on success, mbedTLS MPI error codes on failure. + */ +int esp_mpi_mul_mpi_mod(mbedtls_mpi *Z, const mbedtls_mpi *X, const mbedtls_mpi *Y, const mbedtls_mpi *M); + +//#endif // CONFIG_MBEDTLS_HARDWARE_MPI diff --git a/lib/libesp32_div/ESP32-HomeKit/src/port/bignum_impl.h b/lib/libesp32_div/ESP32-HomeKit/src/port/bignum_impl.h new file mode 100644 index 000000000..0c70fa339 --- /dev/null +++ b/lib/libesp32_div/ESP32-HomeKit/src/port/bignum_impl.h @@ -0,0 +1,92 @@ +#ifndef _ESP_BIGNUM_H_ +#define _ESP_BIGNUM_H_ + +#include +#include + +/* Use montgomery exponentiation (HAC 14.94) for calculating X ^ Y mod M, + this may be faster for some targets. The hardware acceleration support for modular + exponentiation on the ESP32 is slow for public key operations, so use montgomery + exponentiation instead. +*/ + +#define CONFIG_IDF_TARGET_ESP32 1 + +#if CONFIG_IDF_TARGET_ESP32 +#define ESP_MPI_USE_MONT_EXP + +#define MBEDTLS_MPI_EXP_MOD_ALT +//#define MBEDTLS_MPI_MUL_MPI_ALT +#endif + + +int esp_mpi_exp_mod( mbedtls_mpi *Z, const mbedtls_mpi *X, const mbedtls_mpi *Y, const mbedtls_mpi *M, mbedtls_mpi *_Rinv ); + +/** + * @brief Enable the MPI hardware and acquire the lock + * + */ +void esp_mpi_enable_hardware_hw_op( void ); + +/** + * @brief Disable the MPI hardware and release the lock + * + */ +void esp_mpi_disable_hardware_hw_op( void ); + +/** + * @brief Calculate the number of words needed to represent the input word in hardware + * + * @param words The number of words to be represented + * + * @return size_t Number of words required + */ +size_t esp_mpi_hardware_words(size_t words); + +/** + * @brief Starts a (X * Y) Mod M calculation in hardware. Rinv and M_prime needs to be precalculated in software. + * + */ +void esp_mpi_mul_mpi_mod_hw_op(const mbedtls_mpi *X, const mbedtls_mpi *Y, const mbedtls_mpi *M, const mbedtls_mpi *Rinv, mbedtls_mpi_uint Mprime, size_t hw_words); + +/** + * @brief Starts a (X * Y) calculation in hardware. + * + */ +void esp_mpi_mul_mpi_hw_op(const mbedtls_mpi *X, const mbedtls_mpi *Y, size_t num_words); + +/** + * @brief Special-case of (X * Y), where we use hardware montgomery mod + multiplication to calculate result where either A or B are >2048 bits so + can't use the standard multiplication method. + * + */ +void esp_mpi_mult_mpi_failover_mod_mult_hw_op(const mbedtls_mpi *X, const mbedtls_mpi *Y, size_t num_words); + +/** + * @brief Read out the result from the previous calculation. + * + */ +void esp_mpi_read_result_hw_op(mbedtls_mpi *Z, size_t z_words); + +#ifdef ESP_MPI_USE_MONT_EXP +/** + * @brief Starts a montgomery multiplication calculation in hardware + * + */ +int esp_mont_hw_op(mbedtls_mpi* Z, const mbedtls_mpi* X, const mbedtls_mpi* Y, const mbedtls_mpi* M, + mbedtls_mpi_uint Mprime, + size_t hw_words, + bool again); + +#else + +/** + * @brief Starts a (X ^ Y) Mod M calculation in hardware. Rinv and M_prime needs to be precalculated in software. + * + */ +void esp_mpi_exp_mpi_mod_hw_op(const mbedtls_mpi *X, const mbedtls_mpi *Y, const mbedtls_mpi *M, const mbedtls_mpi *Rinv, mbedtls_mpi_uint Mprime, size_t hw_words); + +#endif //ESP_MPI_USE_MONT_EXP + +#endif diff --git a/lib/libesp32_div/ESP32-HomeKit/src/port/esp_bignum.c b/lib/libesp32_div/ESP32-HomeKit/src/port/esp_bignum.c new file mode 100644 index 000000000..22cd126cc --- /dev/null +++ b/lib/libesp32_div/ESP32-HomeKit/src/port/esp_bignum.c @@ -0,0 +1,536 @@ +/** + * \brief Multi-precision integer library, ESP32 hardware accelerated parts + * + * based on mbedTLS implementation + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Additions Copyright (C) 2016, Espressif Systems (Shanghai) PTE Ltd + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#include +#include +#include +#include +#include +#include +#include +//#include "soc/hwcrypto_periph.h" +#include "esp_system.h" +#include "esp_log.h" +#include "esp_attr.h" +#include "bignum_impl.h" +//#include "soc/soc_caps.h" + +#include + +// wangbin added +#if !defined(SOC_RSA_MAX_BIT_LEN) +#define SOC_RSA_MAX_BIT_LEN (4096) +#endif + + +/* Some implementation notes: + * + * - Naming convention x_words, y_words, z_words for number of words (limbs) used in a particular + * bignum. This number may be less than the size of the bignum + * + * - Naming convention hw_words for the hardware length of the operation. This number maybe be rounded up + * for targets that requres this (e.g. ESP32), and may be larger than any of the numbers + * involved in the calculation. + * + * - Timing behaviour of these functions will depend on the length of the inputs. This is fundamentally + * the same constraint as the software mbedTLS implementations, and relies on the same + * countermeasures (exponent blinding, etc) which are used in mbedTLS. + */ + +static const __attribute__((unused)) char *TAG = "bignum"; + +#define ciL (sizeof(mbedtls_mpi_uint)) /* chars in limb */ +#define biL (ciL << 3) /* bits in limb */ + + +/* Convert bit count to word count + */ +static inline size_t bits_to_words(size_t bits) +{ + return (bits + 31) / 32; +} + +/* Return the number of words actually used to represent an mpi + number. +*/ +#if defined(MBEDTLS_MPI_EXP_MOD_ALT) +static size_t mpi_words(const mbedtls_mpi *mpi) +{ + for (size_t i = mpi->n; i > 0; i--) { + if (mpi->p[i - 1] != 0) { + return i; + } + } + return 0; +} + +#endif //MBEDTLS_MPI_EXP_MOD_ALT + +/** + * + * There is a need for the value of integer N' such that B^-1(B-1)-N^-1N'=1, + * where B^-1(B-1) mod N=1. Actually, only the least significant part of + * N' is needed, hence the definition N0'=N' mod b. We reproduce below the + * simple algorithm from an article by Dusse and Kaliski to efficiently + * find N0' from N0 and b + */ +static mbedtls_mpi_uint modular_inverse(const mbedtls_mpi *M) +{ + int i; + uint64_t t = 1; + uint64_t two_2_i_minus_1 = 2; /* 2^(i-1) */ + uint64_t two_2_i = 4; /* 2^i */ + uint64_t N = M->p[0]; + + for (i = 2; i <= 32; i++) { + if ((mbedtls_mpi_uint) N * t % two_2_i >= two_2_i_minus_1) { + t += two_2_i_minus_1; + } + + two_2_i_minus_1 <<= 1; + two_2_i <<= 1; + } + + return (mbedtls_mpi_uint)(UINT32_MAX - t + 1); +} + +/* Calculate Rinv = RR^2 mod M, where: + * + * R = b^n where b = 2^32, n=num_words, + * R = 2^N (where N=num_bits) + * RR = R^2 = 2^(2*N) (where N=num_bits=num_words*32) + * + * This calculation is computationally expensive (mbedtls_mpi_mod_mpi) + * so caller should cache the result where possible. + * + * DO NOT call this function while holding esp_mpi_enable_hardware_hw_op(). + * + */ +static int calculate_rinv(mbedtls_mpi *Rinv, const mbedtls_mpi *M, int num_words) +{ + int ret; + size_t num_bits = num_words * 32; + mbedtls_mpi RR; + mbedtls_mpi_init(&RR); + MBEDTLS_MPI_CHK(mbedtls_mpi_set_bit(&RR, num_bits * 2, 1)); + MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(Rinv, &RR, M)); + +cleanup: + mbedtls_mpi_free(&RR); + + return ret; +} + + + + + + +/* Z = (X * Y) mod M + + Not an mbedTLS function +*/ +int esp_mpi_mul_mpi_mod(mbedtls_mpi *Z, const mbedtls_mpi *X, const mbedtls_mpi *Y, const mbedtls_mpi *M) +{ + int ret = 0; + + size_t x_bits = mbedtls_mpi_bitlen(X); + size_t y_bits = mbedtls_mpi_bitlen(Y); + size_t m_bits = mbedtls_mpi_bitlen(M); + size_t z_bits = MIN(m_bits, x_bits + y_bits); + size_t x_words = bits_to_words(x_bits); + size_t y_words = bits_to_words(y_bits); + size_t m_words = bits_to_words(m_bits); + size_t z_words = bits_to_words(z_bits); + size_t hw_words = esp_mpi_hardware_words(MAX(x_words, MAX(y_words, m_words))); /* longest operand */ + mbedtls_mpi Rinv; + mbedtls_mpi_uint Mprime; + + /* Calculate and load the first stage montgomery multiplication */ + mbedtls_mpi_init(&Rinv); + MBEDTLS_MPI_CHK(calculate_rinv(&Rinv, M, hw_words)); + Mprime = modular_inverse(M); + + esp_mpi_enable_hardware_hw_op(); + /* Load and start a (X * Y) mod M calculation */ + esp_mpi_mul_mpi_mod_hw_op(X, Y, M, &Rinv, Mprime, hw_words); + + MBEDTLS_MPI_CHK(mbedtls_mpi_grow(Z, z_words)); + + esp_mpi_read_result_hw_op(Z, z_words); + Z->s = X->s * Y->s; + +cleanup: + mbedtls_mpi_free(&Rinv); + esp_mpi_disable_hardware_hw_op(); + + return ret; +} + +#if defined(MBEDTLS_MPI_EXP_MOD_ALT) + +#ifdef ESP_MPI_USE_MONT_EXP +/* + * Return the most significant one-bit. + */ +static size_t mbedtls_mpi_msb( const mbedtls_mpi *X ) +{ + int i, j; + if (X != NULL && X->n != 0) { + for (i = X->n - 1; i >= 0; i--) { + if (X->p[i] != 0) { + for (j = biL - 1; j >= 0; j--) { + if ((X->p[i] & (1 << j)) != 0) { + return (i * biL) + j; + } + } + } + } + } + return 0; +} + +/* + * Montgomery exponentiation: Z = X ^ Y mod M (HAC 14.94) + */ +static int mpi_montgomery_exp_calc( mbedtls_mpi *Z, const mbedtls_mpi *X, const mbedtls_mpi *Y, const mbedtls_mpi *M, + mbedtls_mpi *Rinv, + size_t hw_words, + mbedtls_mpi_uint Mprime ) +{ + int ret = 0; + mbedtls_mpi X_, one; + + mbedtls_mpi_init(&X_); + mbedtls_mpi_init(&one); + if ( ( ( ret = mbedtls_mpi_grow(&one, hw_words) ) != 0 ) || + ( ( ret = mbedtls_mpi_set_bit(&one, 0, 1) ) != 0 ) ) { + goto cleanup2; + } + + // Algorithm from HAC 14.94 + { + // 0 determine t (highest bit set in y) + int t = mbedtls_mpi_msb(Y); + + esp_mpi_enable_hardware_hw_op(); + + // 1.1 x_ = mont(x, R^2 mod m) + // = mont(x, rb) + MBEDTLS_MPI_CHK( esp_mont_hw_op(&X_, X, Rinv, M, Mprime, hw_words, false) ); + + // 1.2 z = R mod m + // now z = R mod m = Mont (R^2 mod m, 1) mod M (as Mont(x) = X&R^-1 mod M) + MBEDTLS_MPI_CHK( esp_mont_hw_op(Z, Rinv, &one, M, Mprime, hw_words, true) ); + + // 2 for i from t down to 0 + for (int i = t; i >= 0; i--) { + // 2.1 z = mont(z,z) + if (i != t) { // skip on the first iteration as is still unity + MBEDTLS_MPI_CHK( esp_mont_hw_op(Z, Z, Z, M, Mprime, hw_words, true) ); + } + + // 2.2 if y[i] = 1 then z = mont(A, x_) + if (mbedtls_mpi_get_bit(Y, i)) { + MBEDTLS_MPI_CHK( esp_mont_hw_op(Z, Z, &X_, M, Mprime, hw_words, true) ); + } + } + + // 3 z = Mont(z, 1) + MBEDTLS_MPI_CHK( esp_mont_hw_op(Z, Z, &one, M, Mprime, hw_words, true) ); + } + +cleanup: + esp_mpi_disable_hardware_hw_op(); + +cleanup2: + mbedtls_mpi_free(&X_); + mbedtls_mpi_free(&one); + return ret; +} + +#endif //USE_MONT_EXPONENATIATION + +/* + * Z = X ^ Y mod M + * + * _Rinv is optional pre-calculated version of Rinv (via calculate_rinv()). + * + * (See RSA Accelerator section in Technical Reference for more about Mprime, Rinv) + * + */ +// wangbin changed mbedtls_mpi_exp_mod -> esp_mpi_exp_mod +int esp_mpi_exp_mod( mbedtls_mpi *Z, const mbedtls_mpi *X, const mbedtls_mpi *Y, const mbedtls_mpi *M, mbedtls_mpi *_Rinv ) +{ + int ret = 0; + size_t x_words = mpi_words(X); + size_t y_words = mpi_words(Y); + size_t m_words = mpi_words(M); + + + /* "all numbers must be the same length", so choose longest number + as cardinal length of operation... + */ + size_t num_words = esp_mpi_hardware_words(MAX(m_words, MAX(x_words, y_words))); + + mbedtls_mpi Rinv_new; /* used if _Rinv == NULL */ + mbedtls_mpi *Rinv; /* points to _Rinv (if not NULL) othwerwise &RR_new */ + mbedtls_mpi_uint Mprime; + + if (mbedtls_mpi_cmp_int(M, 0) <= 0 || (M->p[0] & 1) == 0) { + return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; + } + + if (mbedtls_mpi_cmp_int(Y, 0) < 0) { + return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; + } + + if (mbedtls_mpi_cmp_int(Y, 0) == 0) { + return mbedtls_mpi_lset(Z, 1); + } + + if (num_words * 32 > SOC_RSA_MAX_BIT_LEN) { + return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE; + } + + /* Determine RR pointer, either _RR for cached value + or local RR_new */ + if (_Rinv == NULL) { + mbedtls_mpi_init(&Rinv_new); + Rinv = &Rinv_new; + } else { + Rinv = _Rinv; + } + if (Rinv->p == NULL) { + MBEDTLS_MPI_CHK(calculate_rinv(Rinv, M, num_words)); + } + + Mprime = modular_inverse(M); + + // Montgomery exponentiation: Z = X ^ Y mod M (HAC 14.94) +#ifdef ESP_MPI_USE_MONT_EXP + ret = mpi_montgomery_exp_calc(Z, X, Y, M, Rinv, num_words, Mprime) ; + MBEDTLS_MPI_CHK(ret); +#else + esp_mpi_enable_hardware_hw_op(); + + esp_mpi_exp_mpi_mod_hw_op(X, Y, M, Rinv, Mprime, num_words); + ret = mbedtls_mpi_grow(Z, m_words); + if (ret != 0) { + esp_mpi_disable_hardware_hw_op(); + goto cleanup; + } + esp_mpi_read_result_hw_op(Z, m_words); + esp_mpi_disable_hardware_hw_op(); +#endif + + // Compensate for negative X + if (X->s == -1 && (Y->p[0] & 1) != 0) { + Z->s = -1; + MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(Z, M, Z)); + } else { + Z->s = 1; + } + +cleanup: + if (_Rinv == NULL) { + mbedtls_mpi_free(&Rinv_new); + } + return ret; +} + +#endif /* MBEDTLS_MPI_EXP_MOD_ALT */ + + + +#if defined(MBEDTLS_MPI_MUL_MPI_ALT) /* MBEDTLS_MPI_MUL_MPI_ALT */ + +static int mpi_mult_mpi_failover_mod_mult( mbedtls_mpi *Z, const mbedtls_mpi *X, const mbedtls_mpi *Y, size_t z_words); +static int mpi_mult_mpi_overlong(mbedtls_mpi *Z, const mbedtls_mpi *X, const mbedtls_mpi *Y, size_t y_words, size_t z_words); + +/* Z = X * Y */ +int mbedtls_mpi_mul_mpi( mbedtls_mpi *Z, const mbedtls_mpi *X, const mbedtls_mpi *Y ) +{ + int ret = 0; + size_t x_bits = mbedtls_mpi_bitlen(X); + size_t y_bits = mbedtls_mpi_bitlen(Y); + size_t x_words = bits_to_words(x_bits); + size_t y_words = bits_to_words(y_bits); + size_t z_words = bits_to_words(x_bits + y_bits); + size_t hw_words = esp_mpi_hardware_words(MAX(x_words, y_words)); // length of one operand in hardware + + /* Short-circuit eval if either argument is 0 or 1. + + This is needed as the mpi modular division + argument will sometimes call in here when one + argument is too large for the hardware unit, but the other + argument is zero or one. + */ + if (x_bits == 0 || y_bits == 0) { + mbedtls_mpi_lset(Z, 0); + return 0; + } + if (x_bits == 1) { + ret = mbedtls_mpi_copy(Z, Y); + Z->s *= X->s; + return ret; + } + if (y_bits == 1) { + ret = mbedtls_mpi_copy(Z, X); + Z->s *= Y->s; + return ret; + } + + /* Grow Z to result size early, avoid interim allocations */ + MBEDTLS_MPI_CHK( mbedtls_mpi_grow(Z, z_words) ); + + /* If either factor is over 2048 bits, we can't use the standard hardware multiplier + (it assumes result is double longest factor, and result is max 4096 bits.) + + However, we can fail over to mod_mult for up to 4096 bits of result (modulo + multiplication doesn't have the same restriction, so result is simply the + number of bits in X plus number of bits in in Y.) + */ + if (hw_words * 32 > SOC_RSA_MAX_BIT_LEN/2) { + if (z_words * 32 <= SOC_RSA_MAX_BIT_LEN) { + /* Note: it's possible to use mpi_mult_mpi_overlong + for this case as well, but it's very slightly + slower and requires a memory allocation. + */ + return mpi_mult_mpi_failover_mod_mult(Z, X, Y, z_words); + } else { + /* Still too long for the hardware unit... */ + if (y_words > x_words) { + return mpi_mult_mpi_overlong(Z, X, Y, y_words, z_words); + } else { + return mpi_mult_mpi_overlong(Z, Y, X, x_words, z_words); + } + } + } + + /* Otherwise, we can use the (faster) multiply hardware unit */ + esp_mpi_enable_hardware_hw_op(); + + esp_mpi_mul_mpi_hw_op(X, Y, hw_words); + esp_mpi_read_result_hw_op(Z, z_words); + + esp_mpi_disable_hardware_hw_op(); + + Z->s = X->s * Y->s; + +cleanup: + return ret; +} + + + +/* Deal with the case when X & Y are too long for the hardware unit, by splitting one operand + into two halves. + + Y must be the longer operand + + Slice Y into Yp, Ypp such that: + Yp = lower 'b' bits of Y + Ypp = upper 'b' bits of Y (right shifted) + + Such that + Z = X * Y + Z = X * (Yp + Ypp<p, + .n = words_slice, + .s = Y->s + }; + /* Ypp holds upper bits of Y, right shifted (also reuses Y's array contents) */ + const mbedtls_mpi Ypp = { + .p = Y->p + words_slice, + .n = y_words - words_slice, + .s = Y->s + }; + mbedtls_mpi_init(&Ztemp); + + /* Get result Ztemp = Yp * X (need temporary variable Ztemp) */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi(&Ztemp, X, &Yp) ); + + /* Z = Ypp * Y */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi(Z, X, &Ypp) ); + + /* Z = Z << b */ + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l(Z, words_slice * 32) ); + + /* Z += Ztemp */ + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi(Z, Z, &Ztemp) ); + +cleanup: + mbedtls_mpi_free(&Ztemp); + + return ret; +} + +/* Special-case of mbedtls_mpi_mult_mpi(), where we use hardware montgomery mod + multiplication to calculate an mbedtls_mpi_mult_mpi result where either + A or B are >2048 bits so can't use the standard multiplication method. + + Result (number of words, based on A bits + B bits) must still be less than 4096 bits. + + This case is simpler than the general case modulo multiply of + esp_mpi_mul_mpi_mod() because we can control the other arguments: + + * Modulus is chosen with M=(2^num_bits - 1) (ie M=R-1), so output + * Mprime and Rinv are therefore predictable as follows: + isn't actually modulo anything. + Mprime 1 + Rinv 1 + + (See RSA Accelerator section in Technical Reference for more about Mprime, Rinv) +*/ + +static int mpi_mult_mpi_failover_mod_mult( mbedtls_mpi *Z, const mbedtls_mpi *X, const mbedtls_mpi *Y, size_t z_words) +{ + int ret; + size_t hw_words = esp_mpi_hardware_words(z_words); + + esp_mpi_enable_hardware_hw_op(); + + esp_mpi_mult_mpi_failover_mod_mult_hw_op(X, Y, hw_words ); + MBEDTLS_MPI_CHK( mbedtls_mpi_grow(Z, hw_words) ); + esp_mpi_read_result_hw_op(Z, hw_words); + + Z->s = X->s * Y->s; +cleanup: + esp_mpi_disable_hardware_hw_op(); + return ret; +} + +#endif /* MBEDTLS_MPI_MUL_MPI_ALT */ diff --git a/lib/libesp32_div/ESP32-HomeKit/src/sha-private.h b/lib/libesp32_div/ESP32-HomeKit/src/sha-private.h new file mode 100644 index 000000000..9ccc8dd26 --- /dev/null +++ b/lib/libesp32_div/ESP32-HomeKit/src/sha-private.h @@ -0,0 +1,29 @@ +/************************ sha-private.h ************************/ +/***************** See RFC 6234 for details. *******************/ +#ifndef _SHA_PRIVATE__H +#define _SHA_PRIVATE__H +/* + * These definitions are defined in FIPS 180-3, section 4.1. + * Ch() and Maj() are defined identically in sections 4.1.1, + * 4.1.2, and 4.1.3. + * + * The definitions used in FIPS 180-3 are as follows: + */ + +#ifndef USE_MODIFIED_MACROS +#define SHA_Ch(x,y,z) (((x) & (y)) ^ ((~(x)) & (z))) +#define SHA_Maj(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z))) +#else /* USE_MODIFIED_MACROS */ +/* + * The following definitions are equivalent and potentially faster. + */ + +#define SHA_Ch(x, y, z) (((x) & ((y) ^ (z))) ^ (z)) +#define SHA_Maj(x, y, z) (((x) & ((y) | (z))) | ((y) & (z))) + +#endif /* USE_MODIFIED_MACROS */ + +#define SHA_Parity(x, y, z) ((x) ^ (y) ^ (z)) + +#endif /* _SHA_PRIVATE__H */ + diff --git a/lib/libesp32_div/ESP32-HomeKit/src/sha.h b/lib/libesp32_div/ESP32-HomeKit/src/sha.h new file mode 100644 index 000000000..276c3685b --- /dev/null +++ b/lib/libesp32_div/ESP32-HomeKit/src/sha.h @@ -0,0 +1,358 @@ +/**************************** sha.h ****************************/ +/***************** See RFC 6234 for details. *******************/ +/* + Copyright (c) 2011 IETF Trust and the persons identified as + authors of the code. 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 Internet Society, IETF or IETF Trust, nor + the names of specific 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 OWNER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +#ifndef _SHA_H_ +#define _SHA_H_ + +/* + * Description: + * This file implements the Secure Hash Algorithms + * as defined in the U.S. National Institute of Standards + * and Technology Federal Information Processing Standards + * Publication (FIPS PUB) 180-3 published in October 2008 + * and formerly defined in its predecessors, FIPS PUB 180-1 + * and FIP PUB 180-2. + * + * A combined document showing all algorithms is available at + * http://csrc.nist.gov/publications/fips/ + * fips180-3/fips180-3_final.pdf + * + * The five hashes are defined in these sizes: + * SHA-1 20 byte / 160 bit + * SHA-224 28 byte / 224 bit + * SHA-256 32 byte / 256 bit + * SHA-384 48 byte / 384 bit + * SHA-512 64 byte / 512 bit + * + * Compilation Note: + * These files may be compiled with two options: + * USE_32BIT_ONLY - use 32-bit arithmetic only, for systems + * without 64-bit integers + * + * USE_MODIFIED_MACROS - use alternate form of the SHA_Ch() + * and SHA_Maj() macros that are equivalent + * and potentially faster on many systems + * + */ + +#include +/* + * If you do not have the ISO standard stdint.h header file, then you + * must typedef the following: + * name meaning + * uint64_t unsigned 64-bit integer + * uint32_t unsigned 32-bit integer + * uint8_t unsigned 8-bit integer (i.e., unsigned char) + * int_least16_t integer of >= 16 bits + * + * See stdint-example.h + */ + +#ifndef _SHA_enum_ +#define _SHA_enum_ +/* + * All SHA functions return one of these values. + */ +enum { + shaSuccess = 0, + shaNull, /* Null pointer parameter */ + shaInputTooLong, /* input data too long */ + shaStateError, /* called Input after FinalBits or Result */ + shaBadParam /* passed a bad parameter */ +}; +#endif /* _SHA_enum_ */ + +/* + * These constants hold size information for each of the SHA + * hashing operations + */ +enum { + SHA1_Message_Block_Size = 64, SHA224_Message_Block_Size = 64, + SHA256_Message_Block_Size = 64, SHA384_Message_Block_Size = 128, + SHA512_Message_Block_Size = 128, + USHA_Max_Message_Block_Size = SHA512_Message_Block_Size, + + SHA1HashSize = 20, SHA224HashSize = 28, SHA256HashSize = 32, + SHA384HashSize = 48, SHA512HashSize = 64, + USHAMaxHashSize = SHA512HashSize, + + SHA1HashSizeBits = 160, SHA224HashSizeBits = 224, + SHA256HashSizeBits = 256, SHA384HashSizeBits = 384, + SHA512HashSizeBits = 512, USHAMaxHashSizeBits = SHA512HashSizeBits +}; + +/* + * These constants are used in the USHA (Unified SHA) functions. + */ +typedef enum SHAversion { + SHA1, SHA224, SHA256, SHA384, SHA512 +} SHAversion; + +/* + * This structure will hold context information for the SHA-1 + * hashing operation. + */ +typedef struct SHA1Context { + uint32_t Intermediate_Hash[SHA1HashSize/4]; /* Message Digest */ + + uint32_t Length_High; /* Message length in bits */ + uint32_t Length_Low; /* Message length in bits */ + + int_least16_t Message_Block_Index; /* Message_Block array index */ + /* 512-bit message blocks */ + uint8_t Message_Block[SHA1_Message_Block_Size]; + + int Computed; /* Is the hash computed? */ + int Corrupted; /* Cumulative corruption code */ +} SHA1Context; + +/* + * This structure will hold context information for the SHA-256 + * hashing operation. + */ +typedef struct SHA256Context { + uint32_t Intermediate_Hash[SHA256HashSize/4]; /* Message Digest */ + + uint32_t Length_High; /* Message length in bits */ + uint32_t Length_Low; /* Message length in bits */ + + int_least16_t Message_Block_Index; /* Message_Block array index */ + /* 512-bit message blocks */ + uint8_t Message_Block[SHA256_Message_Block_Size]; + + int Computed; /* Is the hash computed? */ + int Corrupted; /* Cumulative corruption code */ +} SHA256Context; + +/* + * This structure will hold context information for the SHA-512 + * hashing operation. + */ +typedef struct SHA512Context { +#ifdef USE_32BIT_ONLY + uint32_t Intermediate_Hash[SHA512HashSize/4]; /* Message Digest */ + uint32_t Length[4]; /* Message length in bits */ +#else /* !USE_32BIT_ONLY */ + uint64_t Intermediate_Hash[SHA512HashSize/8]; /* Message Digest */ + uint64_t Length_High, Length_Low; /* Message length in bits */ +#endif /* USE_32BIT_ONLY */ + + int_least16_t Message_Block_Index; /* Message_Block array index */ + /* 1024-bit message blocks */ + uint8_t Message_Block[SHA512_Message_Block_Size]; + + int Computed; /* Is the hash computed?*/ + int Corrupted; /* Cumulative corruption code */ +} SHA512Context; + +/* + * This structure will hold context information for the SHA-224 + * hashing operation. It uses the SHA-256 structure for computation. + */ +typedef struct SHA256Context SHA224Context; + +/* + * This structure will hold context information for the SHA-384 + * hashing operation. It uses the SHA-512 structure for computation. + */ +typedef struct SHA512Context SHA384Context; + +/* + * This structure holds context information for all SHA + * hashing operations. + */ +typedef struct USHAContext { + int whichSha; /* which SHA is being used */ + union { + SHA1Context sha1Context; + SHA224Context sha224Context; SHA256Context sha256Context; + SHA384Context sha384Context; SHA512Context sha512Context; + } ctx; + +} USHAContext; + +/* + * This structure will hold context information for the HMAC + * keyed-hashing operation. + */ +typedef struct HMACContext { + int whichSha; /* which SHA is being used */ + int hashSize; /* hash size of SHA being used */ + int blockSize; /* block size of SHA being used */ + USHAContext shaContext; /* SHA context */ + unsigned char k_opad[USHA_Max_Message_Block_Size]; + /* outer padding - key XORd with opad */ + int Computed; /* Is the MAC computed? */ + int Corrupted; /* Cumulative corruption code */ + +} HMACContext; + +/* + * This structure will hold context information for the HKDF + * extract-and-expand Key Derivation Functions. + */ +typedef struct HKDFContext { + int whichSha; /* which SHA is being used */ + HMACContext hmacContext; + int hashSize; /* hash size of SHA being used */ + unsigned char prk[USHAMaxHashSize]; + /* pseudo-random key - output of hkdfInput */ + int Computed; /* Is the key material computed? */ + int Corrupted; /* Cumulative corruption code */ +} HKDFContext; + +/* + * Function Prototypes + */ + +/* SHA-1 */ +extern int SHA1Reset(SHA1Context *); +extern int SHA1Input(SHA1Context *, const uint8_t *bytes, + unsigned int bytecount); +extern int SHA1FinalBits(SHA1Context *, uint8_t bits, + unsigned int bit_count); +extern int SHA1Result(SHA1Context *, + uint8_t Message_Digest[SHA1HashSize]); + +/* SHA-224 */ +extern int SHA224Reset(SHA224Context *); +extern int SHA224Input(SHA224Context *, const uint8_t *bytes, + unsigned int bytecount); +extern int SHA224FinalBits(SHA224Context *, uint8_t bits, + unsigned int bit_count); +extern int SHA224Result(SHA224Context *, + uint8_t Message_Digest[SHA224HashSize]); + +/* SHA-256 */ +extern int SHA256Reset(SHA256Context *); +extern int SHA256Input(SHA256Context *, const uint8_t *bytes, + unsigned int bytecount); +extern int SHA256FinalBits(SHA256Context *, uint8_t bits, + unsigned int bit_count); +extern int SHA256Result(SHA256Context *, + uint8_t Message_Digest[SHA256HashSize]); + +/* SHA-384 */ +extern int SHA384Reset(SHA384Context *); +extern int SHA384Input(SHA384Context *, const uint8_t *bytes, + unsigned int bytecount); +extern int SHA384FinalBits(SHA384Context *, uint8_t bits, + unsigned int bit_count); +extern int SHA384Result(SHA384Context *, + uint8_t Message_Digest[SHA384HashSize]); + +/* SHA-512 */ +extern int SHA512Reset(SHA512Context *); +extern int SHA512Input(SHA512Context *, const uint8_t *bytes, + unsigned int bytecount); +extern int SHA512FinalBits(SHA512Context *, uint8_t bits, + unsigned int bit_count); +extern int SHA512Result(SHA512Context *, + uint8_t Message_Digest[SHA512HashSize]); + +/* Unified SHA functions, chosen by whichSha */ +extern int USHAReset(USHAContext *context, SHAversion whichSha); +extern int USHAInput(USHAContext *context, + const uint8_t *bytes, unsigned int bytecount); +extern int USHAFinalBits(USHAContext *context, + uint8_t bits, unsigned int bit_count); +extern int USHAResult(USHAContext *context, + uint8_t Message_Digest[USHAMaxHashSize]); +extern int USHABlockSize(enum SHAversion whichSha); +extern int USHAHashSize(enum SHAversion whichSha); +extern int USHAHashSizeBits(enum SHAversion whichSha); +extern const char *USHAHashName(enum SHAversion whichSha); + +/* + * HMAC Keyed-Hashing for Message Authentication, RFC 2104, + * for all SHAs. + * This interface allows a fixed-length text input to be used. + */ +extern int hmac(SHAversion whichSha, /* which SHA algorithm to use */ + const unsigned char *text, /* pointer to data stream */ + int text_len, /* length of data stream */ + const unsigned char *key, /* pointer to authentication key */ + int key_len, /* length of authentication key */ + uint8_t digest[USHAMaxHashSize]); /* caller digest to fill in */ + +/* + * HMAC Keyed-Hashing for Message Authentication, RFC 2104, + * for all SHAs. + * This interface allows any length of text input to be used. + */ +extern int hmacReset(HMACContext *context, enum SHAversion whichSha, + const unsigned char *key, int key_len); +extern int hmacInput(HMACContext *context, const unsigned char *text, + int text_len); +extern int hmacFinalBits(HMACContext *context, uint8_t bits, + unsigned int bit_count); +extern int hmacResult(HMACContext *context, + uint8_t digest[USHAMaxHashSize]); + +/* + * HKDF HMAC-based Extract-and-Expand Key Derivation Function, + * RFC 5869, for all SHAs. + */ +extern int hkdf(SHAversion whichSha, const unsigned char *salt, + int salt_len, const unsigned char *ikm, int ikm_len, + const unsigned char *info, int info_len, + uint8_t okm[ ], int okm_len); +extern int hkdfExtract(SHAversion whichSha, const unsigned char *salt, + int salt_len, const unsigned char *ikm, + int ikm_len, uint8_t prk[USHAMaxHashSize]); +extern int hkdfExpand(SHAversion whichSha, const uint8_t prk[ ], + int prk_len, const unsigned char *info, + int info_len, uint8_t okm[ ], int okm_len); + +/* + * HKDF HMAC-based Extract-and-Expand Key Derivation Function, + * RFC 5869, for all SHAs. + * This interface allows any length of text input to be used. + */ +extern int hkdfReset(HKDFContext *context, enum SHAversion whichSha, + const unsigned char *salt, int salt_len); +extern int hkdfInput(HKDFContext *context, const unsigned char *ikm, + int ikm_len); +extern int hkdfFinalBits(HKDFContext *context, uint8_t ikm_bits, + unsigned int ikm_bit_count); +extern int hkdfResult(HKDFContext *context, + uint8_t prk[USHAMaxHashSize], + const unsigned char *info, int info_len, + uint8_t okm[USHAMaxHashSize], int okm_len); +#endif /* _SHA_H_ */ + diff --git a/lib/libesp32_div/ESP32-HomeKit/src/sha1.c b/lib/libesp32_div/ESP32-HomeKit/src/sha1.c new file mode 100644 index 000000000..53f187212 --- /dev/null +++ b/lib/libesp32_div/ESP32-HomeKit/src/sha1.c @@ -0,0 +1,414 @@ +/**************************** sha1.c ***************************/ +/***************** See RFC 6234 for details. *******************/ +/* Copyright (c) 2011 IETF Trust and the persons identified as */ +/* authors of the code. All rights reserved. */ +/* See sha.h for terms of use and redistribution. */ + +/* + * Description: + * This file implements the Secure Hash Algorithm SHA-1 + * as defined in the U.S. National Institute of Standards + * and Technology Federal Information Processing Standards + * Publication (FIPS PUB) 180-3 published in October 2008 + * and formerly defined in its predecessors, FIPS PUB 180-1 + * and FIP PUB 180-2. + * + * A combined document showing all algorithms is available at + * http://csrc.nist.gov/publications/fips/ + * fips180-3/fips180-3_final.pdf + * + * The SHA-1 algorithm produces a 160-bit message digest for a + * given data stream that can serve as a means of providing a + * "fingerprint" for a message. + * + * Portability Issues: + * SHA-1 is defined in terms of 32-bit "words". This code + * uses (included via "sha.h") to define 32- and + * 8-bit unsigned integer types. If your C compiler does + * not support 32-bit unsigned integers, this code is not + * appropriate. + * + * Caveats: + * SHA-1 is designed to work with messages less than 2^64 bits + * long. This implementation uses SHA1Input() to hash the bits + * that are a multiple of the size of an 8-bit octet, and then + * optionally uses SHA1FinalBits() to hash the final few bits of + * the input. + */ + +#include "sha.h" +#include "sha-private.h" + +/* + * Define the SHA1 circular left shift macro + */ +#define SHA1_ROTL(bits,word) \ + (((word) << (bits)) | ((word) >> (32-(bits)))) + +/* + * Add "length" to the length. + * Set Corrupted when overflow has occurred. + */ +static uint32_t addTemp; +#define SHA1AddLength(context, length) \ + (addTemp = (context)->Length_Low, \ + (context)->Corrupted = \ + (((context)->Length_Low += (length)) < addTemp) && \ + (++(context)->Length_High == 0) ? shaInputTooLong \ + : (context)->Corrupted ) + +/* Local Function Prototypes */ +static void SHA1ProcessMessageBlock(SHA1Context *context); +static void SHA1Finalize(SHA1Context *context, uint8_t Pad_Byte); +static void SHA1PadMessage(SHA1Context *context, uint8_t Pad_Byte); + +/* + * SHA1Reset + * + * Description: + * This function will initialize the SHA1Context in preparation + * for computing a new SHA1 message digest. + * + * Parameters: + * context: [in/out] + * The context to reset. + * + * Returns: + * sha Error Code. + * + */ +int SHA1Reset(SHA1Context *context) +{ + if (!context) return shaNull; + + context->Length_High = context->Length_Low = 0; + context->Message_Block_Index = 0; + + /* Initial Hash Values: FIPS 180-3 section 5.3.1 */ + context->Intermediate_Hash[0] = 0x67452301; + context->Intermediate_Hash[1] = 0xEFCDAB89; + context->Intermediate_Hash[2] = 0x98BADCFE; + context->Intermediate_Hash[3] = 0x10325476; + context->Intermediate_Hash[4] = 0xC3D2E1F0; + + context->Computed = 0; + context->Corrupted = shaSuccess; + + return shaSuccess; +} + +/* + * SHA1Input + * + * Description: + * This function accepts an array of octets as the next portion + * of the message. + * + * Parameters: + * context: [in/out] + * The SHA context to update. + * message_array[ ]: [in] + * An array of octets representing the next portion of + * the message. + * length: [in] + * The length of the message in message_array. + * + * Returns: + * sha Error Code. + * + */ +int SHA1Input(SHA1Context *context, + const uint8_t *message_array, unsigned length) +{ + if (!context) return shaNull; + if (!length) return shaSuccess; + if (!message_array) return shaNull; + if (context->Computed) return context->Corrupted = shaStateError; + if (context->Corrupted) return context->Corrupted; + + while (length--) { + context->Message_Block[context->Message_Block_Index++] = + *message_array; + + if ((SHA1AddLength(context, 8) == shaSuccess) && + (context->Message_Block_Index == SHA1_Message_Block_Size)) + SHA1ProcessMessageBlock(context); + + message_array++; + } + + return context->Corrupted; +} + +/* + * SHA1FinalBits + * + * Description: + * This function will add in any final bits of the message. + * + * Parameters: + * context: [in/out] + * The SHA context to update. + * message_bits: [in] + * The final bits of the message, in the upper portion of the + * byte. (Use 0b###00000 instead of 0b00000### to input the + * three bits ###.) + * length: [in] + * The number of bits in message_bits, between 1 and 7. + * + * Returns: + * sha Error Code. + */ +int SHA1FinalBits(SHA1Context *context, uint8_t message_bits, + unsigned int length) +{ + static uint8_t masks[8] = { + /* 0 0b00000000 */ 0x00, /* 1 0b10000000 */ 0x80, + /* 2 0b11000000 */ 0xC0, /* 3 0b11100000 */ 0xE0, + /* 4 0b11110000 */ 0xF0, /* 5 0b11111000 */ 0xF8, + /* 6 0b11111100 */ 0xFC, /* 7 0b11111110 */ 0xFE + }; + + static uint8_t markbit[8] = { + /* 0 0b10000000 */ 0x80, /* 1 0b01000000 */ 0x40, + /* 2 0b00100000 */ 0x20, /* 3 0b00010000 */ 0x10, + /* 4 0b00001000 */ 0x08, /* 5 0b00000100 */ 0x04, + /* 6 0b00000010 */ 0x02, /* 7 0b00000001 */ 0x01 + }; + + if (!context) return shaNull; + if (!length) return shaSuccess; + if (context->Corrupted) return context->Corrupted; + if (context->Computed) return context->Corrupted = shaStateError; + if (length >= 8) return context->Corrupted = shaBadParam; + + SHA1AddLength(context, length); + SHA1Finalize(context, + (uint8_t) ((message_bits & masks[length]) | markbit[length])); + + return context->Corrupted; +} + +/* + * SHA1Result + * + * Description: + * This function will return the 160-bit message digest + * into the Message_Digest array provided by the caller. + * NOTE: + * The first octet of hash is stored in the element with index 0, + * the last octet of hash in the element with index 19. + * + * Parameters: + * context: [in/out] + * The context to use to calculate the SHA-1 hash. + * Message_Digest[ ]: [out] + * Where the digest is returned. + * + * Returns: + * sha Error Code. + * + */ +int SHA1Result(SHA1Context *context, + uint8_t Message_Digest[SHA1HashSize]) +{ + int i; + + if (!context) return shaNull; + if (!Message_Digest) return shaNull; + if (context->Corrupted) return context->Corrupted; + + if (!context->Computed) + SHA1Finalize(context, 0x80); + + for (i = 0; i < SHA1HashSize; ++i) + Message_Digest[i] = (uint8_t) (context->Intermediate_Hash[i>>2] + >> (8 * ( 3 - ( i & 0x03 ) ))); + + return shaSuccess; +} + +/* + * SHA1ProcessMessageBlock + * + * Description: + * This helper function will process the next 512 bits of the + * message stored in the Message_Block array. + * + * Parameters: + * context: [in/out] + * The SHA context to update. + * + * Returns: + * Nothing. + * + * Comments: + * Many of the variable names in this code, especially the + * single character names, were used because those were the + * names used in the Secure Hash Standard. + */ +static void SHA1ProcessMessageBlock(SHA1Context *context) +{ + /* Constants defined in FIPS 180-3, section 4.2.1 */ + const uint32_t K[4] = { + 0x5A827999, 0x6ED9EBA1, 0x8F1BBCDC, 0xCA62C1D6 + }; + + int t; /* Loop counter */ + uint32_t temp; /* Temporary word value */ + uint32_t W[80]; /* Word sequence */ + uint32_t A, B, C, D, E; /* Word buffers */ + + /* + * Initialize the first 16 words in the array W + */ + for (t = 0; t < 16; t++) { + W[t] = ((uint32_t)context->Message_Block[t * 4]) << 24; + W[t] |= ((uint32_t)context->Message_Block[t * 4 + 1]) << 16; + W[t] |= ((uint32_t)context->Message_Block[t * 4 + 2]) << 8; + W[t] |= ((uint32_t)context->Message_Block[t * 4 + 3]); + } + + for (t = 16; t < 80; t++) + W[t] = SHA1_ROTL(1, W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]); + + A = context->Intermediate_Hash[0]; + B = context->Intermediate_Hash[1]; + C = context->Intermediate_Hash[2]; + D = context->Intermediate_Hash[3]; + E = context->Intermediate_Hash[4]; + + for (t = 0; t < 20; t++) { + temp = SHA1_ROTL(5,A) + SHA_Ch(B, C, D) + E + W[t] + K[0]; + E = D; + D = C; + C = SHA1_ROTL(30,B); + B = A; + A = temp; + } + + for (t = 20; t < 40; t++) { + temp = SHA1_ROTL(5,A) + SHA_Parity(B, C, D) + E + W[t] + K[1]; + E = D; + D = C; + C = SHA1_ROTL(30,B); + B = A; + A = temp; + } + + for (t = 40; t < 60; t++) { + temp = SHA1_ROTL(5,A) + SHA_Maj(B, C, D) + E + W[t] + K[2]; + E = D; + D = C; + C = SHA1_ROTL(30,B); + B = A; + A = temp; + } + + for (t = 60; t < 80; t++) { + temp = SHA1_ROTL(5,A) + SHA_Parity(B, C, D) + E + W[t] + K[3]; + E = D; + D = C; + C = SHA1_ROTL(30,B); + B = A; + A = temp; + } + + context->Intermediate_Hash[0] += A; + context->Intermediate_Hash[1] += B; + context->Intermediate_Hash[2] += C; + context->Intermediate_Hash[3] += D; + context->Intermediate_Hash[4] += E; + context->Message_Block_Index = 0; +} + +/* + * SHA1Finalize + * + * Description: + * This helper function finishes off the digest calculations. + * + * Parameters: + * context: [in/out] + * The SHA context to update. + * Pad_Byte: [in] + * The last byte to add to the message block before the 0-padding + * and length. This will contain the last bits of the message + * followed by another single bit. If the message was an + * exact multiple of 8-bits long, Pad_Byte will be 0x80. + * + * Returns: + * sha Error Code. + * + */ +static void SHA1Finalize(SHA1Context *context, uint8_t Pad_Byte) +{ + int i; + SHA1PadMessage(context, Pad_Byte); + /* message may be sensitive, clear it out */ + for (i = 0; i < SHA1_Message_Block_Size; ++i) + context->Message_Block[i] = 0; + context->Length_High = 0; /* and clear length */ + context->Length_Low = 0; + context->Computed = 1; +} + +/* + * SHA1PadMessage + * + * Description: + * According to the standard, the message must be padded to the next + * even multiple of 512 bits. The first padding bit must be a '1'. + * The last 64 bits represent the length of the original message. + * All bits in between should be 0. This helper function will pad + * the message according to those rules by filling the Message_Block + * array accordingly. When it returns, it can be assumed that the + * message digest has been computed. + * + * Parameters: + * context: [in/out] + * The context to pad. + * Pad_Byte: [in] + * The last byte to add to the message block before the 0-padding + * and length. This will contain the last bits of the message + * followed by another single bit. If the message was an + * exact multiple of 8-bits long, Pad_Byte will be 0x80. + * + * Returns: + * Nothing. + */ +static void SHA1PadMessage(SHA1Context *context, uint8_t Pad_Byte) +{ + /* + * Check to see if the current message block is too small to hold + * the initial padding bits and length. If so, we will pad the + * block, process it, and then continue padding into a second + * block. + */ + if (context->Message_Block_Index >= (SHA1_Message_Block_Size - 8)) { + context->Message_Block[context->Message_Block_Index++] = Pad_Byte; + while (context->Message_Block_Index < SHA1_Message_Block_Size) + context->Message_Block[context->Message_Block_Index++] = 0; + + SHA1ProcessMessageBlock(context); + } else + context->Message_Block[context->Message_Block_Index++] = Pad_Byte; + + while (context->Message_Block_Index < (SHA1_Message_Block_Size - 8)) + context->Message_Block[context->Message_Block_Index++] = 0; + + /* + * Store the message length as the last 8 octets + */ + context->Message_Block[56] = (uint8_t) (context->Length_High >> 24); + context->Message_Block[57] = (uint8_t) (context->Length_High >> 16); + context->Message_Block[58] = (uint8_t) (context->Length_High >> 8); + context->Message_Block[59] = (uint8_t) (context->Length_High); + context->Message_Block[60] = (uint8_t) (context->Length_Low >> 24); + context->Message_Block[61] = (uint8_t) (context->Length_Low >> 16); + context->Message_Block[62] = (uint8_t) (context->Length_Low >> 8); + context->Message_Block[63] = (uint8_t) (context->Length_Low); + + SHA1ProcessMessageBlock(context); +} + diff --git a/lib/libesp32_div/ESP32-HomeKit/src/sha224-256.c b/lib/libesp32_div/ESP32-HomeKit/src/sha224-256.c new file mode 100644 index 000000000..2c9bc9c14 --- /dev/null +++ b/lib/libesp32_div/ESP32-HomeKit/src/sha224-256.c @@ -0,0 +1,581 @@ +/************************* sha224-256.c ************************/ +/***************** See RFC 6234 for details. *******************/ +/* Copyright (c) 2011 IETF Trust and the persons identified as */ +/* authors of the code. All rights reserved. */ +/* See sha.h for terms of use and redistribution. */ + +/* + * Description: + * This file implements the Secure Hash Algorithms SHA-224 and + * SHA-256 as defined in the U.S. National Institute of Standards + * and Technology Federal Information Processing Standards + * Publication (FIPS PUB) 180-3 published in October 2008 + * and formerly defined in its predecessors, FIPS PUB 180-1 + * and FIP PUB 180-2. + * + * A combined document showing all algorithms is available at + * http://csrc.nist.gov/publications/fips/ + * fips180-3/fips180-3_final.pdf + * + * The SHA-224 and SHA-256 algorithms produce 224-bit and 256-bit + * message digests for a given data stream. It should take about + * 2**n steps to find a message with the same digest as a given + * message and 2**(n/2) to find any two messages with the same + * digest, when n is the digest size in bits. Therefore, this + * algorithm can serve as a means of providing a + * "fingerprint" for a message. + * + * Portability Issues: + * SHA-224 and SHA-256 are defined in terms of 32-bit "words". + * This code uses (included via "sha.h") to define 32- + * and 8-bit unsigned integer types. If your C compiler does not + * support 32-bit unsigned integers, this code is not + * appropriate. + * + * Caveats: + * SHA-224 and SHA-256 are designed to work with messages less + * than 2^64 bits long. This implementation uses SHA224/256Input() + * to hash the bits that are a multiple of the size of an 8-bit + * octet, and then optionally uses SHA224/256FinalBits() + * to hash the final few bits of the input. + */ + +#include "sha.h" +#include "sha-private.h" + +/* Define the SHA shift, rotate left, and rotate right macros */ +#define SHA256_SHR(bits,word) ((word) >> (bits)) +#define SHA256_ROTL(bits,word) \ + (((word) << (bits)) | ((word) >> (32-(bits)))) +#define SHA256_ROTR(bits,word) \ + (((word) >> (bits)) | ((word) << (32-(bits)))) + +/* Define the SHA SIGMA and sigma macros */ +#define SHA256_SIGMA0(word) \ + (SHA256_ROTR( 2,word) ^ SHA256_ROTR(13,word) ^ SHA256_ROTR(22,word)) +#define SHA256_SIGMA1(word) \ + (SHA256_ROTR( 6,word) ^ SHA256_ROTR(11,word) ^ SHA256_ROTR(25,word)) +#define SHA256_sigma0(word) \ + (SHA256_ROTR( 7,word) ^ SHA256_ROTR(18,word) ^ SHA256_SHR( 3,word)) +#define SHA256_sigma1(word) \ + (SHA256_ROTR(17,word) ^ SHA256_ROTR(19,word) ^ SHA256_SHR(10,word)) + +/* + * Add "length" to the length. + * Set Corrupted when overflow has occurred. + */ +static uint32_t addTemp; +#define SHA224_256AddLength(context, length) \ + (addTemp = (context)->Length_Low, (context)->Corrupted = \ + (((context)->Length_Low += (length)) < addTemp) && \ + (++(context)->Length_High == 0) ? shaInputTooLong : \ + (context)->Corrupted ) + +/* Local Function Prototypes */ +static int SHA224_256Reset(SHA256Context *context, uint32_t *H0); +static void SHA224_256ProcessMessageBlock(SHA256Context *context); +static void SHA224_256Finalize(SHA256Context *context, + uint8_t Pad_Byte); +static void SHA224_256PadMessage(SHA256Context *context, + uint8_t Pad_Byte); +static int SHA224_256ResultN(SHA256Context *context, + uint8_t Message_Digest[ ], int HashSize); + +/* Initial Hash Values: FIPS 180-3 section 5.3.2 */ +static uint32_t SHA224_H0[SHA256HashSize/4] = { + 0xC1059ED8, 0x367CD507, 0x3070DD17, 0xF70E5939, + 0xFFC00B31, 0x68581511, 0x64F98FA7, 0xBEFA4FA4 +}; + +/* Initial Hash Values: FIPS 180-3 section 5.3.3 */ +static uint32_t SHA256_H0[SHA256HashSize/4] = { + 0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A, + 0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19 +}; + +/* + * SHA224Reset + * + * Description: + * This function will initialize the SHA224Context in preparation + * for computing a new SHA224 message digest. + * + * Parameters: + * context: [in/out] + * The context to reset. + * + * Returns: + * sha Error Code. + */ +int SHA224Reset(SHA224Context *context) +{ + return SHA224_256Reset(context, SHA224_H0); +} + +/* + * SHA224Input + * + * Description: + * This function accepts an array of octets as the next portion + * of the message. + * + * Parameters: + * context: [in/out] + * The SHA context to update. + * message_array[ ]: [in] + * An array of octets representing the next portion of + * the message. + * length: [in] + * The length of the message in message_array. + * + * Returns: + * sha Error Code. + * + */ +int SHA224Input(SHA224Context *context, const uint8_t *message_array, + unsigned int length) +{ + return SHA256Input(context, message_array, length); +} + +/* + * SHA224FinalBits + * + * Description: + * This function will add in any final bits of the message. + * + * Parameters: + * context: [in/out] + * The SHA context to update. + * message_bits: [in] + * The final bits of the message, in the upper portion of the + * byte. (Use 0b###00000 instead of 0b00000### to input the + * three bits ###.) + * length: [in] + * The number of bits in message_bits, between 1 and 7. + * + * Returns: + * sha Error Code. + */ +int SHA224FinalBits(SHA224Context *context, + uint8_t message_bits, unsigned int length) +{ + return SHA256FinalBits(context, message_bits, length); +} + +/* + * SHA224Result + * + * Description: + * This function will return the 224-bit message digest + * into the Message_Digest array provided by the caller. + * NOTE: + * The first octet of hash is stored in the element with index 0, + * the last octet of hash in the element with index 27. + * + * Parameters: + * context: [in/out] + * The context to use to calculate the SHA hash. + * Message_Digest[ ]: [out] + * Where the digest is returned. + * + * Returns: + * sha Error Code. + */ +int SHA224Result(SHA224Context *context, + uint8_t Message_Digest[SHA224HashSize]) +{ + return SHA224_256ResultN(context, Message_Digest, SHA224HashSize); +} + +/* + * SHA256Reset + * + * Description: + * This function will initialize the SHA256Context in preparation + * for computing a new SHA256 message digest. + * + * Parameters: + * context: [in/out] + * The context to reset. + * + * Returns: + * sha Error Code. + */ +int SHA256Reset(SHA256Context *context) +{ + return SHA224_256Reset(context, SHA256_H0); +} + +/* + * SHA256Input + * + * Description: + * This function accepts an array of octets as the next portion + * of the message. + * + * Parameters: + * context: [in/out] + * The SHA context to update. + * message_array[ ]: [in] + * An array of octets representing the next portion of + * the message. + * length: [in] + * The length of the message in message_array. + * + * Returns: + * sha Error Code. + */ +int SHA256Input(SHA256Context *context, const uint8_t *message_array, + unsigned int length) +{ + if (!context) return shaNull; + if (!length) return shaSuccess; + if (!message_array) return shaNull; + if (context->Computed) return context->Corrupted = shaStateError; + if (context->Corrupted) return context->Corrupted; + + while (length--) { + context->Message_Block[context->Message_Block_Index++] = + *message_array; + + if ((SHA224_256AddLength(context, 8) == shaSuccess) && + (context->Message_Block_Index == SHA256_Message_Block_Size)) + SHA224_256ProcessMessageBlock(context); + + message_array++; + } + + return context->Corrupted; + +} + +/* + * SHA256FinalBits + * + * Description: + * This function will add in any final bits of the message. + * + * Parameters: + * context: [in/out] + * The SHA context to update. + * message_bits: [in] + * The final bits of the message, in the upper portion of the + * byte. (Use 0b###00000 instead of 0b00000### to input the + * three bits ###.) + * length: [in] + * The number of bits in message_bits, between 1 and 7. + * + * Returns: + * sha Error Code. + */ +int SHA256FinalBits(SHA256Context *context, + uint8_t message_bits, unsigned int length) +{ + static uint8_t masks[8] = { + /* 0 0b00000000 */ 0x00, /* 1 0b10000000 */ 0x80, + /* 2 0b11000000 */ 0xC0, /* 3 0b11100000 */ 0xE0, + /* 4 0b11110000 */ 0xF0, /* 5 0b11111000 */ 0xF8, + /* 6 0b11111100 */ 0xFC, /* 7 0b11111110 */ 0xFE + }; + static uint8_t markbit[8] = { + /* 0 0b10000000 */ 0x80, /* 1 0b01000000 */ 0x40, + /* 2 0b00100000 */ 0x20, /* 3 0b00010000 */ 0x10, + /* 4 0b00001000 */ 0x08, /* 5 0b00000100 */ 0x04, + /* 6 0b00000010 */ 0x02, /* 7 0b00000001 */ 0x01 + }; + + if (!context) return shaNull; + if (!length) return shaSuccess; + if (context->Corrupted) return context->Corrupted; + if (context->Computed) return context->Corrupted = shaStateError; + if (length >= 8) return context->Corrupted = shaBadParam; + + SHA224_256AddLength(context, length); + SHA224_256Finalize(context, (uint8_t) + ((message_bits & masks[length]) | markbit[length])); + + return context->Corrupted; +} + +/* + * SHA256Result + * + * Description: + * This function will return the 256-bit message digest + * into the Message_Digest array provided by the caller. + * NOTE: + * The first octet of hash is stored in the element with index 0, + * the last octet of hash in the element with index 31. + * + * Parameters: + * context: [in/out] + * The context to use to calculate the SHA hash. + * Message_Digest[ ]: [out] + * Where the digest is returned. + * + * Returns: + * sha Error Code. + */ +int SHA256Result(SHA256Context *context, + uint8_t Message_Digest[SHA256HashSize]) +{ + return SHA224_256ResultN(context, Message_Digest, SHA256HashSize); +} + +/* + * SHA224_256Reset + * + * Description: + * This helper function will initialize the SHA256Context in + * preparation for computing a new SHA-224 or SHA-256 message digest. + * + * Parameters: + * context: [in/out] + * The context to reset. + * H0[ ]: [in] + * The initial hash value array to use. + * + * Returns: + * sha Error Code. + */ +static int SHA224_256Reset(SHA256Context *context, uint32_t *H0) +{ + if (!context) return shaNull; + + context->Length_High = context->Length_Low = 0; + context->Message_Block_Index = 0; + + context->Intermediate_Hash[0] = H0[0]; + context->Intermediate_Hash[1] = H0[1]; + context->Intermediate_Hash[2] = H0[2]; + context->Intermediate_Hash[3] = H0[3]; + context->Intermediate_Hash[4] = H0[4]; + context->Intermediate_Hash[5] = H0[5]; + context->Intermediate_Hash[6] = H0[6]; + context->Intermediate_Hash[7] = H0[7]; + + context->Computed = 0; + context->Corrupted = shaSuccess; + + return shaSuccess; +} + +/* + * SHA224_256ProcessMessageBlock + * + * Description: + * This helper function will process the next 512 bits of the + * message stored in the Message_Block array. + * + * Parameters: + * context: [in/out] + * The SHA context to update. + * + * Returns: + * Nothing. + * + * Comments: + * Many of the variable names in this code, especially the + * single character names, were used because those were the + * names used in the Secure Hash Standard. + */ +static void SHA224_256ProcessMessageBlock(SHA256Context *context) +{ + /* Constants defined in FIPS 180-3, section 4.2.2 */ + static const uint32_t K[64] = { + 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, + 0x59f111f1, 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, + 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, + 0xc19bf174, 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, + 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 0x983e5152, + 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, + 0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, + 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, + 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, + 0xd6990624, 0xf40e3585, 0x106aa070, 0x19a4c116, 0x1e376c08, + 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, + 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, + 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 + }; + int t, t4; /* Loop counter */ + uint32_t temp1, temp2; /* Temporary word value */ + uint32_t W[64]; /* Word sequence */ + uint32_t A, B, C, D, E, F, G, H; /* Word buffers */ + + /* + * Initialize the first 16 words in the array W + */ + for (t = t4 = 0; t < 16; t++, t4 += 4) + W[t] = (((uint32_t)context->Message_Block[t4]) << 24) | + (((uint32_t)context->Message_Block[t4 + 1]) << 16) | + (((uint32_t)context->Message_Block[t4 + 2]) << 8) | + (((uint32_t)context->Message_Block[t4 + 3])); + for (t = 16; t < 64; t++) + W[t] = SHA256_sigma1(W[t-2]) + W[t-7] + + SHA256_sigma0(W[t-15]) + W[t-16]; + + A = context->Intermediate_Hash[0]; + B = context->Intermediate_Hash[1]; + C = context->Intermediate_Hash[2]; + D = context->Intermediate_Hash[3]; + E = context->Intermediate_Hash[4]; + F = context->Intermediate_Hash[5]; + G = context->Intermediate_Hash[6]; + H = context->Intermediate_Hash[7]; + + for (t = 0; t < 64; t++) { + temp1 = H + SHA256_SIGMA1(E) + SHA_Ch(E,F,G) + K[t] + W[t]; + temp2 = SHA256_SIGMA0(A) + SHA_Maj(A,B,C); + H = G; + G = F; + F = E; + E = D + temp1; + D = C; + C = B; + B = A; + A = temp1 + temp2; + } + + context->Intermediate_Hash[0] += A; + context->Intermediate_Hash[1] += B; + context->Intermediate_Hash[2] += C; + context->Intermediate_Hash[3] += D; + context->Intermediate_Hash[4] += E; + context->Intermediate_Hash[5] += F; + context->Intermediate_Hash[6] += G; + context->Intermediate_Hash[7] += H; + + context->Message_Block_Index = 0; +} + +/* + * SHA224_256Finalize + * + * Description: + * This helper function finishes off the digest calculations. + * + * Parameters: + * context: [in/out] + * The SHA context to update. + * Pad_Byte: [in] + * The last byte to add to the message block before the 0-padding + * and length. This will contain the last bits of the message + * followed by another single bit. If the message was an + * exact multiple of 8-bits long, Pad_Byte will be 0x80. + * + * Returns: + * sha Error Code. + */ +static void SHA224_256Finalize(SHA256Context *context, + uint8_t Pad_Byte) +{ + int i; + SHA224_256PadMessage(context, Pad_Byte); + /* message may be sensitive, so clear it out */ + for (i = 0; i < SHA256_Message_Block_Size; ++i) + context->Message_Block[i] = 0; + context->Length_High = 0; /* and clear length */ + context->Length_Low = 0; + context->Computed = 1; +} + +/* + * SHA224_256PadMessage + * + * Description: + * According to the standard, the message must be padded to the next + * even multiple of 512 bits. The first padding bit must be a '1'. + * The last 64 bits represent the length of the original message. + * All bits in between should be 0. This helper function will pad + * the message according to those rules by filling the + * Message_Block array accordingly. When it returns, it can be + * assumed that the message digest has been computed. + * + * Parameters: + * context: [in/out] + * The context to pad. + * Pad_Byte: [in] + * The last byte to add to the message block before the 0-padding + * and length. This will contain the last bits of the message + * followed by another single bit. If the message was an + * exact multiple of 8-bits long, Pad_Byte will be 0x80. + * + * Returns: + * Nothing. + */ +static void SHA224_256PadMessage(SHA256Context *context, + uint8_t Pad_Byte) +{ + /* + * Check to see if the current message block is too small to hold + * the initial padding bits and length. If so, we will pad the + * block, process it, and then continue padding into a second + * block. + */ + if (context->Message_Block_Index >= (SHA256_Message_Block_Size-8)) { + context->Message_Block[context->Message_Block_Index++] = Pad_Byte; + while (context->Message_Block_Index < SHA256_Message_Block_Size) + context->Message_Block[context->Message_Block_Index++] = 0; + SHA224_256ProcessMessageBlock(context); + } else + context->Message_Block[context->Message_Block_Index++] = Pad_Byte; + + while (context->Message_Block_Index < (SHA256_Message_Block_Size-8)) + context->Message_Block[context->Message_Block_Index++] = 0; + + /* + * Store the message length as the last 8 octets + */ + context->Message_Block[56] = (uint8_t)(context->Length_High >> 24); + context->Message_Block[57] = (uint8_t)(context->Length_High >> 16); + context->Message_Block[58] = (uint8_t)(context->Length_High >> 8); + context->Message_Block[59] = (uint8_t)(context->Length_High); + context->Message_Block[60] = (uint8_t)(context->Length_Low >> 24); + context->Message_Block[61] = (uint8_t)(context->Length_Low >> 16); + context->Message_Block[62] = (uint8_t)(context->Length_Low >> 8); + context->Message_Block[63] = (uint8_t)(context->Length_Low); + + SHA224_256ProcessMessageBlock(context); +} + +/* + * SHA224_256ResultN + * + * Description: + * This helper function will return the 224-bit or 256-bit message + * digest into the Message_Digest array provided by the caller. + * NOTE: + * The first octet of hash is stored in the element with index 0, + * the last octet of hash in the element with index 27/31. + * + * Parameters: + * context: [in/out] + * The context to use to calculate the SHA hash. + * Message_Digest[ ]: [out] + * Where the digest is returned. + * HashSize: [in] + * The size of the hash, either 28 or 32. + * + * Returns: + * sha Error Code. + */ +static int SHA224_256ResultN(SHA256Context *context, + uint8_t Message_Digest[ ], int HashSize) +{ + int i; + + if (!context) return shaNull; + if (!Message_Digest) return shaNull; + if (context->Corrupted) return context->Corrupted; + + if (!context->Computed) + SHA224_256Finalize(context, 0x80); + + for (i = 0; i < HashSize; ++i) + Message_Digest[i] = (uint8_t) + (context->Intermediate_Hash[i>>2] >> 8 * ( 3 - ( i & 0x03 ) )); + + return shaSuccess; +} + diff --git a/lib/libesp32_div/ESP32-HomeKit/src/sha384-512.c b/lib/libesp32_div/ESP32-HomeKit/src/sha384-512.c new file mode 100644 index 000000000..de5956f08 --- /dev/null +++ b/lib/libesp32_div/ESP32-HomeKit/src/sha384-512.c @@ -0,0 +1,1032 @@ +/************************* sha384-512.c ************************/ +/***************** See RFC 6234 for details. *******************/ +/* Copyright (c) 2011 IETF Trust and the persons identified as */ +/* authors of the code. All rights reserved. */ +/* See sha.h for terms of use and redistribution. */ + +/* + * Description: + * This file implements the Secure Hash Algorithms SHA-384 and + * SHA-512 as defined in the U.S. National Institute of Standards + * and Technology Federal Information Processing Standards + * Publication (FIPS PUB) 180-3 published in October 2008 + * and formerly defined in its predecessors, FIPS PUB 180-1 + * and FIP PUB 180-2. + * + * A combined document showing all algorithms is available at + * http://csrc.nist.gov/publications/fips/ + * fips180-3/fips180-3_final.pdf + * + * The SHA-384 and SHA-512 algorithms produce 384-bit and 512-bit + * message digests for a given data stream. It should take about + * 2**n steps to find a message with the same digest as a given + * message and 2**(n/2) to find any two messages with the same + * digest, when n is the digest size in bits. Therefore, this + * algorithm can serve as a means of providing a + * "fingerprint" for a message. + * + * Portability Issues: + * SHA-384 and SHA-512 are defined in terms of 64-bit "words", + * but if USE_32BIT_ONLY is #defined, this code is implemented in + * terms of 32-bit "words". This code uses (included + * via "sha.h") to define the 64-, 32- and 8-bit unsigned integer + * types. If your C compiler does not support 64-bit unsigned + * integers and you do not #define USE_32BIT_ONLY, this code is + * not appropriate. + * + * Caveats: + * SHA-384 and SHA-512 are designed to work with messages less + * than 2^128 bits long. This implementation uses SHA384/512Input() + * to hash the bits that are a multiple of the size of an 8-bit + * octet, and then optionally uses SHA384/256FinalBits() + * to hash the final few bits of the input. + * + */ + +#include "sha.h" + +#ifdef USE_32BIT_ONLY +/* + * Define 64-bit arithmetic in terms of 32-bit arithmetic. + * Each 64-bit number is represented in a 2-word array. + * All macros are defined such that the result is the last parameter. + */ + +/* + * Define shift, rotate left, and rotate right functions + */ +#define SHA512_SHR(bits, word, ret) ( \ + /* (((uint64_t)((word))) >> (bits)) */ \ + (ret)[0] = (((bits) < 32) && ((bits) >= 0)) ? \ + ((word)[0] >> (bits)) : 0, \ + (ret)[1] = ((bits) > 32) ? ((word)[0] >> ((bits) - 32)) : \ + ((bits) == 32) ? (word)[0] : \ + ((bits) >= 0) ? \ + (((word)[0] << (32 - (bits))) | \ + ((word)[1] >> (bits))) : 0 ) + +#define SHA512_SHL(bits, word, ret) ( \ + /* (((uint64_t)(word)) << (bits)) */ \ + (ret)[0] = ((bits) > 32) ? ((word)[1] << ((bits) - 32)) : \ + ((bits) == 32) ? (word)[1] : \ + ((bits) >= 0) ? \ + (((word)[0] << (bits)) | \ + ((word)[1] >> (32 - (bits)))) : \ + 0, \ + (ret)[1] = (((bits) < 32) && ((bits) >= 0)) ? \ + ((word)[1] << (bits)) : 0 ) + +/* + * Define 64-bit OR + */ +#define SHA512_OR(word1, word2, ret) ( \ + (ret)[0] = (word1)[0] | (word2)[0], \ + (ret)[1] = (word1)[1] | (word2)[1] ) + +/* + * Define 64-bit XOR + */ +#define SHA512_XOR(word1, word2, ret) ( \ + (ret)[0] = (word1)[0] ^ (word2)[0], \ + (ret)[1] = (word1)[1] ^ (word2)[1] ) + +/* + * Define 64-bit AND + */ +#define SHA512_AND(word1, word2, ret) ( \ + (ret)[0] = (word1)[0] & (word2)[0], \ + (ret)[1] = (word1)[1] & (word2)[1] ) + +/* + * Define 64-bit TILDA + */ +#define SHA512_TILDA(word, ret) \ + ( (ret)[0] = ~(word)[0], (ret)[1] = ~(word)[1] ) + +/* + * Define 64-bit ADD + */ +#define SHA512_ADD(word1, word2, ret) ( \ + (ret)[1] = (word1)[1], (ret)[1] += (word2)[1], \ + (ret)[0] = (word1)[0] + (word2)[0] + ((ret)[1] < (word1)[1]) ) + +/* + * Add the 4word value in word2 to word1. + */ +static uint32_t ADDTO4_temp, ADDTO4_temp2; +#define SHA512_ADDTO4(word1, word2) ( \ + ADDTO4_temp = (word1)[3], \ + (word1)[3] += (word2)[3], \ + ADDTO4_temp2 = (word1)[2], \ + (word1)[2] += (word2)[2] + ((word1)[3] < ADDTO4_temp), \ + ADDTO4_temp = (word1)[1], \ + (word1)[1] += (word2)[1] + ((word1)[2] < ADDTO4_temp2), \ + (word1)[0] += (word2)[0] + ((word1)[1] < ADDTO4_temp) ) + +/* + * Add the 2word value in word2 to word1. + */ +static uint32_t ADDTO2_temp; +#define SHA512_ADDTO2(word1, word2) ( \ + ADDTO2_temp = (word1)[1], \ + (word1)[1] += (word2)[1], \ + (word1)[0] += (word2)[0] + ((word1)[1] < ADDTO2_temp) ) + +/* + * SHA rotate ((word >> bits) | (word << (64-bits))) + */ +static uint32_t ROTR_temp1[2], ROTR_temp2[2]; +#define SHA512_ROTR(bits, word, ret) ( \ + SHA512_SHR((bits), (word), ROTR_temp1), \ + SHA512_SHL(64-(bits), (word), ROTR_temp2), \ + SHA512_OR(ROTR_temp1, ROTR_temp2, (ret)) ) + +/* + * Define the SHA SIGMA and sigma macros + * + * SHA512_ROTR(28,word) ^ SHA512_ROTR(34,word) ^ SHA512_ROTR(39,word) + */ +static uint32_t SIGMA0_temp1[2], SIGMA0_temp2[2], + SIGMA0_temp3[2], SIGMA0_temp4[2]; +#define SHA512_SIGMA0(word, ret) ( \ + SHA512_ROTR(28, (word), SIGMA0_temp1), \ + SHA512_ROTR(34, (word), SIGMA0_temp2), \ + SHA512_ROTR(39, (word), SIGMA0_temp3), \ + SHA512_XOR(SIGMA0_temp2, SIGMA0_temp3, SIGMA0_temp4), \ + SHA512_XOR(SIGMA0_temp1, SIGMA0_temp4, (ret)) ) + +/* + * SHA512_ROTR(14,word) ^ SHA512_ROTR(18,word) ^ SHA512_ROTR(41,word) + */ +static uint32_t SIGMA1_temp1[2], SIGMA1_temp2[2], + SIGMA1_temp3[2], SIGMA1_temp4[2]; +#define SHA512_SIGMA1(word, ret) ( \ + SHA512_ROTR(14, (word), SIGMA1_temp1), \ + SHA512_ROTR(18, (word), SIGMA1_temp2), \ + SHA512_ROTR(41, (word), SIGMA1_temp3), \ + SHA512_XOR(SIGMA1_temp2, SIGMA1_temp3, SIGMA1_temp4), \ + SHA512_XOR(SIGMA1_temp1, SIGMA1_temp4, (ret)) ) + +/* + * (SHA512_ROTR( 1,word) ^ SHA512_ROTR( 8,word) ^ SHA512_SHR( 7,word)) + */ +static uint32_t sigma0_temp1[2], sigma0_temp2[2], + sigma0_temp3[2], sigma0_temp4[2]; +#define SHA512_sigma0(word, ret) ( \ + SHA512_ROTR( 1, (word), sigma0_temp1), \ + SHA512_ROTR( 8, (word), sigma0_temp2), \ + SHA512_SHR( 7, (word), sigma0_temp3), \ + SHA512_XOR(sigma0_temp2, sigma0_temp3, sigma0_temp4), \ + SHA512_XOR(sigma0_temp1, sigma0_temp4, (ret)) ) + +/* + * (SHA512_ROTR(19,word) ^ SHA512_ROTR(61,word) ^ SHA512_SHR( 6,word)) + */ +static uint32_t sigma1_temp1[2], sigma1_temp2[2], + sigma1_temp3[2], sigma1_temp4[2]; +#define SHA512_sigma1(word, ret) ( \ + SHA512_ROTR(19, (word), sigma1_temp1), \ + SHA512_ROTR(61, (word), sigma1_temp2), \ + SHA512_SHR( 6, (word), sigma1_temp3), \ + SHA512_XOR(sigma1_temp2, sigma1_temp3, sigma1_temp4), \ + SHA512_XOR(sigma1_temp1, sigma1_temp4, (ret)) ) + +#ifndef USE_MODIFIED_MACROS +/* + * These definitions are the ones used in FIPS 180-3, section 4.1.3 + * Ch(x,y,z) ((x & y) ^ (~x & z)) + */ +static uint32_t Ch_temp1[2], Ch_temp2[2], Ch_temp3[2]; +#define SHA_Ch(x, y, z, ret) ( \ + SHA512_AND(x, y, Ch_temp1), \ + SHA512_TILDA(x, Ch_temp2), \ + SHA512_AND(Ch_temp2, z, Ch_temp3), \ + SHA512_XOR(Ch_temp1, Ch_temp3, (ret)) ) + +/* + * Maj(x,y,z) (((x)&(y)) ^ ((x)&(z)) ^ ((y)&(z))) + */ +static uint32_t Maj_temp1[2], Maj_temp2[2], + Maj_temp3[2], Maj_temp4[2]; +#define SHA_Maj(x, y, z, ret) ( \ + SHA512_AND(x, y, Maj_temp1), \ + SHA512_AND(x, z, Maj_temp2), \ + SHA512_AND(y, z, Maj_temp3), \ + SHA512_XOR(Maj_temp2, Maj_temp3, Maj_temp4), \ + SHA512_XOR(Maj_temp1, Maj_temp4, (ret)) ) +#else /* !USE_MODIFIED_MACROS */ +/* + * These definitions are potentially faster equivalents for the ones + * used in FIPS 180-3, section 4.1.3. + * ((x & y) ^ (~x & z)) becomes + * ((x & (y ^ z)) ^ z) + */ +#define SHA_Ch(x, y, z, ret) ( \ + (ret)[0] = (((x)[0] & ((y)[0] ^ (z)[0])) ^ (z)[0]), \ + (ret)[1] = (((x)[1] & ((y)[1] ^ (z)[1])) ^ (z)[1]) ) + +/* + * ((x & y) ^ (x & z) ^ (y & z)) becomes + * ((x & (y | z)) | (y & z)) + */ +#define SHA_Maj(x, y, z, ret) ( \ + ret[0] = (((x)[0] & ((y)[0] | (z)[0])) | ((y)[0] & (z)[0])), \ + ret[1] = (((x)[1] & ((y)[1] | (z)[1])) | ((y)[1] & (z)[1])) ) +#endif /* USE_MODIFIED_MACROS */ + +/* + * Add "length" to the length. + * Set Corrupted when overflow has occurred. + */ +static uint32_t addTemp[4] = { 0, 0, 0, 0 }; +#define SHA384_512AddLength(context, length) ( \ + addTemp[3] = (length), SHA512_ADDTO4((context)->Length, addTemp), \ + (context)->Corrupted = (((context)->Length[3] < (length)) && \ + ((context)->Length[2] == 0) && ((context)->Length[1] == 0) && \ + ((context)->Length[0] == 0)) ? shaInputTooLong : \ + (context)->Corrupted ) + +/* Local Function Prototypes */ +static int SHA384_512Reset(SHA512Context *context, + uint32_t H0[SHA512HashSize/4]); +static void SHA384_512ProcessMessageBlock(SHA512Context *context); +static void SHA384_512Finalize(SHA512Context *context, + uint8_t Pad_Byte); +static void SHA384_512PadMessage(SHA512Context *context, + uint8_t Pad_Byte); +static int SHA384_512ResultN( SHA512Context *context, + uint8_t Message_Digest[ ], int HashSize); + +/* Initial Hash Values: FIPS 180-3 sections 5.3.4 and 5.3.5 */ +static uint32_t SHA384_H0[SHA512HashSize/4] = { + 0xCBBB9D5D, 0xC1059ED8, 0x629A292A, 0x367CD507, 0x9159015A, + 0x3070DD17, 0x152FECD8, 0xF70E5939, 0x67332667, 0xFFC00B31, + 0x8EB44A87, 0x68581511, 0xDB0C2E0D, 0x64F98FA7, 0x47B5481D, + 0xBEFA4FA4 +}; +static uint32_t SHA512_H0[SHA512HashSize/4] = { + 0x6A09E667, 0xF3BCC908, 0xBB67AE85, 0x84CAA73B, 0x3C6EF372, + 0xFE94F82B, 0xA54FF53A, 0x5F1D36F1, 0x510E527F, 0xADE682D1, + 0x9B05688C, 0x2B3E6C1F, 0x1F83D9AB, 0xFB41BD6B, 0x5BE0CD19, + 0x137E2179 +}; + +#else /* !USE_32BIT_ONLY */ + +#include "sha-private.h" + +/* Define the SHA shift, rotate left and rotate right macros */ +#define SHA512_SHR(bits,word) (((uint64_t)(word)) >> (bits)) +#define SHA512_ROTR(bits,word) ((((uint64_t)(word)) >> (bits)) | \ + (((uint64_t)(word)) << (64-(bits)))) + +/* + * Define the SHA SIGMA and sigma macros + * + * SHA512_ROTR(28,word) ^ SHA512_ROTR(34,word) ^ SHA512_ROTR(39,word) + */ +#define SHA512_SIGMA0(word) \ + (SHA512_ROTR(28,word) ^ SHA512_ROTR(34,word) ^ SHA512_ROTR(39,word)) +#define SHA512_SIGMA1(word) \ + (SHA512_ROTR(14,word) ^ SHA512_ROTR(18,word) ^ SHA512_ROTR(41,word)) +#define SHA512_sigma0(word) \ + (SHA512_ROTR( 1,word) ^ SHA512_ROTR( 8,word) ^ SHA512_SHR( 7,word)) +#define SHA512_sigma1(word) \ + (SHA512_ROTR(19,word) ^ SHA512_ROTR(61,word) ^ SHA512_SHR( 6,word)) + +/* + * Add "length" to the length. + * Set Corrupted when overflow has occurred. + */ +static uint64_t addTemp; +#define SHA384_512AddLength(context, length) \ + (addTemp = context->Length_Low, context->Corrupted = \ + ((context->Length_Low += length) < addTemp) && \ + (++context->Length_High == 0) ? shaInputTooLong : \ + (context)->Corrupted) + +/* Local Function Prototypes */ +static int SHA384_512Reset(SHA512Context *context, + uint64_t H0[SHA512HashSize/8]); +static void SHA384_512ProcessMessageBlock(SHA512Context *context); +static void SHA384_512Finalize(SHA512Context *context, + uint8_t Pad_Byte); +static void SHA384_512PadMessage(SHA512Context *context, + uint8_t Pad_Byte); +static int SHA384_512ResultN(SHA512Context *context, + uint8_t Message_Digest[ ], int HashSize); + +/* Initial Hash Values: FIPS 180-3 sections 5.3.4 and 5.3.5 */ +static uint64_t SHA384_H0[ ] = { + 0xCBBB9D5DC1059ED8ll, 0x629A292A367CD507ll, 0x9159015A3070DD17ll, + 0x152FECD8F70E5939ll, 0x67332667FFC00B31ll, 0x8EB44A8768581511ll, + 0xDB0C2E0D64F98FA7ll, 0x47B5481DBEFA4FA4ll +}; +static uint64_t SHA512_H0[ ] = { + 0x6A09E667F3BCC908ll, 0xBB67AE8584CAA73Bll, 0x3C6EF372FE94F82Bll, + 0xA54FF53A5F1D36F1ll, 0x510E527FADE682D1ll, 0x9B05688C2B3E6C1Fll, + 0x1F83D9ABFB41BD6Bll, 0x5BE0CD19137E2179ll +}; + +#endif /* USE_32BIT_ONLY */ + +/* + * SHA384Reset + * + * Description: + * This function will initialize the SHA384Context in preparation + * for computing a new SHA384 message digest. + * + * Parameters: + * context: [in/out] + * The context to reset. + * + * Returns: + * sha Error Code. + * + */ +int SHA384Reset(SHA384Context *context) +{ + return SHA384_512Reset(context, SHA384_H0); +} + +/* + * SHA384Input + * + * Description: + * This function accepts an array of octets as the next portion + * of the message. + * + * Parameters: + * context: [in/out] + * The SHA context to update. + * message_array[ ]: [in] + * An array of octets representing the next portion of + * the message. + * length: [in] + * The length of the message in message_array. + * + * Returns: + * sha Error Code. + * + */ +int SHA384Input(SHA384Context *context, + const uint8_t *message_array, unsigned int length) +{ + return SHA512Input(context, message_array, length); +} + +/* + * SHA384FinalBits + * + * Description: + * This function will add in any final bits of the message. + * + * Parameters: + * context: [in/out] + * The SHA context to update. + * message_bits: [in] + * The final bits of the message, in the upper portion of the + * byte. (Use 0b###00000 instead of 0b00000### to input the + * three bits ###.) + * length: [in] + * The number of bits in message_bits, between 1 and 7. + * + * Returns: + * sha Error Code. + * + */ +int SHA384FinalBits(SHA384Context *context, + uint8_t message_bits, unsigned int length) +{ + return SHA512FinalBits(context, message_bits, length); +} + +/* + * SHA384Result + * + * Description: + * This function will return the 384-bit message digest + * into the Message_Digest array provided by the caller. + * NOTE: + * The first octet of hash is stored in the element with index 0, + * the last octet of hash in the element with index 47. + * + * Parameters: + * context: [in/out] + * The context to use to calculate the SHA hash. + * Message_Digest[ ]: [out] + * Where the digest is returned. + * + * Returns: + * sha Error Code. + * + */ +int SHA384Result(SHA384Context *context, + uint8_t Message_Digest[SHA384HashSize]) +{ + return SHA384_512ResultN(context, Message_Digest, SHA384HashSize); +} + +/* + * SHA512Reset + * + * Description: + * This function will initialize the SHA512Context in preparation + * for computing a new SHA512 message digest. + * + * Parameters: + * context: [in/out] + * The context to reset. + * + * Returns: + * sha Error Code. + * + */ +int SHA512Reset(SHA512Context *context) +{ + return SHA384_512Reset(context, SHA512_H0); +} + +/* + * SHA512Input + * + * Description: + * This function accepts an array of octets as the next portion + * of the message. + * + * Parameters: + * context: [in/out] + * The SHA context to update. + * message_array[ ]: [in] + * An array of octets representing the next portion of + * the message. + * length: [in] + * The length of the message in message_array. + * + * Returns: + * sha Error Code. + * + */ +int SHA512Input(SHA512Context *context, + const uint8_t *message_array, + unsigned int length) +{ + if (!context) return shaNull; + if (!length) return shaSuccess; + if (!message_array) return shaNull; + if (context->Computed) return context->Corrupted = shaStateError; + if (context->Corrupted) return context->Corrupted; + + while (length--) { + context->Message_Block[context->Message_Block_Index++] = + *message_array; + + if ((SHA384_512AddLength(context, 8) == shaSuccess) && + (context->Message_Block_Index == SHA512_Message_Block_Size)) + SHA384_512ProcessMessageBlock(context); + + message_array++; + } + + return context->Corrupted; +} + +/* + * SHA512FinalBits + * + * Description: + * This function will add in any final bits of the message. + * + * Parameters: + * context: [in/out] + * The SHA context to update. + * message_bits: [in] + * The final bits of the message, in the upper portion of the + * byte. (Use 0b###00000 instead of 0b00000### to input the + * three bits ###.) + * length: [in] + * The number of bits in message_bits, between 1 and 7. + * + * Returns: + * sha Error Code. + * + */ +int SHA512FinalBits(SHA512Context *context, + uint8_t message_bits, unsigned int length) +{ + static uint8_t masks[8] = { + /* 0 0b00000000 */ 0x00, /* 1 0b10000000 */ 0x80, + /* 2 0b11000000 */ 0xC0, /* 3 0b11100000 */ 0xE0, + /* 4 0b11110000 */ 0xF0, /* 5 0b11111000 */ 0xF8, + /* 6 0b11111100 */ 0xFC, /* 7 0b11111110 */ 0xFE + }; + static uint8_t markbit[8] = { + /* 0 0b10000000 */ 0x80, /* 1 0b01000000 */ 0x40, + /* 2 0b00100000 */ 0x20, /* 3 0b00010000 */ 0x10, + /* 4 0b00001000 */ 0x08, /* 5 0b00000100 */ 0x04, + /* 6 0b00000010 */ 0x02, /* 7 0b00000001 */ 0x01 + }; + + if (!context) return shaNull; + if (!length) return shaSuccess; + if (context->Corrupted) return context->Corrupted; + if (context->Computed) return context->Corrupted = shaStateError; + if (length >= 8) return context->Corrupted = shaBadParam; + + SHA384_512AddLength(context, length); + SHA384_512Finalize(context, (uint8_t) + ((message_bits & masks[length]) | markbit[length])); + + return context->Corrupted; +} + +/* + * SHA512Result + * + * Description: + * This function will return the 512-bit message digest + * into the Message_Digest array provided by the caller. + * NOTE: + * The first octet of hash is stored in the element with index 0, + * the last octet of hash in the element with index 63. + * + * Parameters: + * context: [in/out] + * The context to use to calculate the SHA hash. + * Message_Digest[ ]: [out] + * Where the digest is returned. + * + * Returns: + * sha Error Code. + * + */ +int SHA512Result(SHA512Context *context, + uint8_t Message_Digest[SHA512HashSize]) +{ + return SHA384_512ResultN(context, Message_Digest, SHA512HashSize); +} + +/* + * SHA384_512Reset + * + * Description: + * This helper function will initialize the SHA512Context in + * preparation for computing a new SHA384 or SHA512 message + * digest. + * + * Parameters: + * context: [in/out] + * The context to reset. + * H0[ ]: [in] + * The initial hash value array to use. + * + * Returns: + * sha Error Code. + * + */ +#ifdef USE_32BIT_ONLY +static int SHA384_512Reset(SHA512Context *context, + uint32_t H0[SHA512HashSize/4]) +#else /* !USE_32BIT_ONLY */ +static int SHA384_512Reset(SHA512Context *context, + uint64_t H0[SHA512HashSize/8]) +#endif /* USE_32BIT_ONLY */ +{ + int i; + if (!context) return shaNull; + context->Message_Block_Index = 0; + +#ifdef USE_32BIT_ONLY + context->Length[0] = context->Length[1] = + context->Length[2] = context->Length[3] = 0; + + for (i = 0; i < SHA512HashSize/4; i++) + context->Intermediate_Hash[i] = H0[i]; +#else /* !USE_32BIT_ONLY */ + context->Length_High = context->Length_Low = 0; + + for (i = 0; i < SHA512HashSize/8; i++) + context->Intermediate_Hash[i] = H0[i]; +#endif /* USE_32BIT_ONLY */ + + context->Computed = 0; + context->Corrupted = shaSuccess; + + return shaSuccess; +} + +/* + * SHA384_512ProcessMessageBlock + * + * Description: + * This helper function will process the next 1024 bits of the + * message stored in the Message_Block array. + * + * Parameters: + * context: [in/out] + * The SHA context to update. + * + * Returns: + * Nothing. + * + * Comments: + * Many of the variable names in this code, especially the + * single character names, were used because those were the + * names used in the Secure Hash Standard. + * + * + */ +static void SHA384_512ProcessMessageBlock(SHA512Context *context) +{ +#ifdef USE_32BIT_ONLY + /* Constants defined in FIPS 180-3, section 4.2.3 */ + static const uint32_t K[80*2] = { + 0x428A2F98, 0xD728AE22, 0x71374491, 0x23EF65CD, 0xB5C0FBCF, + 0xEC4D3B2F, 0xE9B5DBA5, 0x8189DBBC, 0x3956C25B, 0xF348B538, + 0x59F111F1, 0xB605D019, 0x923F82A4, 0xAF194F9B, 0xAB1C5ED5, + 0xDA6D8118, 0xD807AA98, 0xA3030242, 0x12835B01, 0x45706FBE, + 0x243185BE, 0x4EE4B28C, 0x550C7DC3, 0xD5FFB4E2, 0x72BE5D74, + 0xF27B896F, 0x80DEB1FE, 0x3B1696B1, 0x9BDC06A7, 0x25C71235, + 0xC19BF174, 0xCF692694, 0xE49B69C1, 0x9EF14AD2, 0xEFBE4786, + 0x384F25E3, 0x0FC19DC6, 0x8B8CD5B5, 0x240CA1CC, 0x77AC9C65, + 0x2DE92C6F, 0x592B0275, 0x4A7484AA, 0x6EA6E483, 0x5CB0A9DC, + 0xBD41FBD4, 0x76F988DA, 0x831153B5, 0x983E5152, 0xEE66DFAB, + 0xA831C66D, 0x2DB43210, 0xB00327C8, 0x98FB213F, 0xBF597FC7, + 0xBEEF0EE4, 0xC6E00BF3, 0x3DA88FC2, 0xD5A79147, 0x930AA725, + 0x06CA6351, 0xE003826F, 0x14292967, 0x0A0E6E70, 0x27B70A85, + 0x46D22FFC, 0x2E1B2138, 0x5C26C926, 0x4D2C6DFC, 0x5AC42AED, + 0x53380D13, 0x9D95B3DF, 0x650A7354, 0x8BAF63DE, 0x766A0ABB, + 0x3C77B2A8, 0x81C2C92E, 0x47EDAEE6, 0x92722C85, 0x1482353B, + 0xA2BFE8A1, 0x4CF10364, 0xA81A664B, 0xBC423001, 0xC24B8B70, + 0xD0F89791, 0xC76C51A3, 0x0654BE30, 0xD192E819, 0xD6EF5218, + 0xD6990624, 0x5565A910, 0xF40E3585, 0x5771202A, 0x106AA070, + 0x32BBD1B8, 0x19A4C116, 0xB8D2D0C8, 0x1E376C08, 0x5141AB53, + 0x2748774C, 0xDF8EEB99, 0x34B0BCB5, 0xE19B48A8, 0x391C0CB3, + 0xC5C95A63, 0x4ED8AA4A, 0xE3418ACB, 0x5B9CCA4F, 0x7763E373, + 0x682E6FF3, 0xD6B2B8A3, 0x748F82EE, 0x5DEFB2FC, 0x78A5636F, + 0x43172F60, 0x84C87814, 0xA1F0AB72, 0x8CC70208, 0x1A6439EC, + 0x90BEFFFA, 0x23631E28, 0xA4506CEB, 0xDE82BDE9, 0xBEF9A3F7, + 0xB2C67915, 0xC67178F2, 0xE372532B, 0xCA273ECE, 0xEA26619C, + 0xD186B8C7, 0x21C0C207, 0xEADA7DD6, 0xCDE0EB1E, 0xF57D4F7F, + 0xEE6ED178, 0x06F067AA, 0x72176FBA, 0x0A637DC5, 0xA2C898A6, + 0x113F9804, 0xBEF90DAE, 0x1B710B35, 0x131C471B, 0x28DB77F5, + 0x23047D84, 0x32CAAB7B, 0x40C72493, 0x3C9EBE0A, 0x15C9BEBC, + 0x431D67C4, 0x9C100D4C, 0x4CC5D4BE, 0xCB3E42B6, 0x597F299C, + 0xFC657E2A, 0x5FCB6FAB, 0x3AD6FAEC, 0x6C44198C, 0x4A475817 + }; + int t, t2, t8; /* Loop counter */ + uint32_t temp1[2], temp2[2], /* Temporary word values */ + temp3[2], temp4[2], temp5[2]; + uint32_t W[2*80]; /* Word sequence */ + uint32_t A[2], B[2], C[2], D[2], /* Word buffers */ + E[2], F[2], G[2], H[2]; + + /* Initialize the first 16 words in the array W */ + for (t = t2 = t8 = 0; t < 16; t++, t8 += 8) { + W[t2++] = ((((uint32_t)context->Message_Block[t8 ])) << 24) | + ((((uint32_t)context->Message_Block[t8 + 1])) << 16) | + ((((uint32_t)context->Message_Block[t8 + 2])) << 8) | + ((((uint32_t)context->Message_Block[t8 + 3]))); + W[t2++] = ((((uint32_t)context->Message_Block[t8 + 4])) << 24) | + ((((uint32_t)context->Message_Block[t8 + 5])) << 16) | + ((((uint32_t)context->Message_Block[t8 + 6])) << 8) | + ((((uint32_t)context->Message_Block[t8 + 7]))); + } + + for (t = 16; t < 80; t++, t2 += 2) { + /* W[t] = SHA512_sigma1(W[t-2]) + W[t-7] + + SHA512_sigma0(W[t-15]) + W[t-16]; */ + uint32_t *Wt2 = &W[t2-2*2]; + uint32_t *Wt7 = &W[t2-7*2]; + uint32_t *Wt15 = &W[t2-15*2]; + uint32_t *Wt16 = &W[t2-16*2]; + SHA512_sigma1(Wt2, temp1); + SHA512_ADD(temp1, Wt7, temp2); + SHA512_sigma0(Wt15, temp1); + SHA512_ADD(temp1, Wt16, temp3); + SHA512_ADD(temp2, temp3, &W[t2]); + } + + A[0] = context->Intermediate_Hash[0]; + A[1] = context->Intermediate_Hash[1]; + B[0] = context->Intermediate_Hash[2]; + B[1] = context->Intermediate_Hash[3]; + C[0] = context->Intermediate_Hash[4]; + C[1] = context->Intermediate_Hash[5]; + D[0] = context->Intermediate_Hash[6]; + D[1] = context->Intermediate_Hash[7]; + E[0] = context->Intermediate_Hash[8]; + E[1] = context->Intermediate_Hash[9]; + F[0] = context->Intermediate_Hash[10]; + F[1] = context->Intermediate_Hash[11]; + G[0] = context->Intermediate_Hash[12]; + G[1] = context->Intermediate_Hash[13]; + H[0] = context->Intermediate_Hash[14]; + H[1] = context->Intermediate_Hash[15]; + + for (t = t2 = 0; t < 80; t++, t2 += 2) { + /* + * temp1 = H + SHA512_SIGMA1(E) + SHA_Ch(E,F,G) + K[t] + W[t]; + */ + SHA512_SIGMA1(E,temp1); + SHA512_ADD(H, temp1, temp2); + SHA_Ch(E,F,G,temp3); + SHA512_ADD(temp2, temp3, temp4); + SHA512_ADD(&K[t2], &W[t2], temp5); + SHA512_ADD(temp4, temp5, temp1); + /* + * temp2 = SHA512_SIGMA0(A) + SHA_Maj(A,B,C); + */ + SHA512_SIGMA0(A,temp3); + SHA_Maj(A,B,C,temp4); + SHA512_ADD(temp3, temp4, temp2); + H[0] = G[0]; H[1] = G[1]; + G[0] = F[0]; G[1] = F[1]; + F[0] = E[0]; F[1] = E[1]; + SHA512_ADD(D, temp1, E); + D[0] = C[0]; D[1] = C[1]; + C[0] = B[0]; C[1] = B[1]; + B[0] = A[0]; B[1] = A[1]; + SHA512_ADD(temp1, temp2, A); + } + + SHA512_ADDTO2(&context->Intermediate_Hash[0], A); + SHA512_ADDTO2(&context->Intermediate_Hash[2], B); + SHA512_ADDTO2(&context->Intermediate_Hash[4], C); + SHA512_ADDTO2(&context->Intermediate_Hash[6], D); + SHA512_ADDTO2(&context->Intermediate_Hash[8], E); + SHA512_ADDTO2(&context->Intermediate_Hash[10], F); + SHA512_ADDTO2(&context->Intermediate_Hash[12], G); + SHA512_ADDTO2(&context->Intermediate_Hash[14], H); + +#else /* !USE_32BIT_ONLY */ + /* Constants defined in FIPS 180-3, section 4.2.3 */ + static const uint64_t K[80] = { + 0x428A2F98D728AE22ll, 0x7137449123EF65CDll, 0xB5C0FBCFEC4D3B2Fll, + 0xE9B5DBA58189DBBCll, 0x3956C25BF348B538ll, 0x59F111F1B605D019ll, + 0x923F82A4AF194F9Bll, 0xAB1C5ED5DA6D8118ll, 0xD807AA98A3030242ll, + 0x12835B0145706FBEll, 0x243185BE4EE4B28Cll, 0x550C7DC3D5FFB4E2ll, + 0x72BE5D74F27B896Fll, 0x80DEB1FE3B1696B1ll, 0x9BDC06A725C71235ll, + 0xC19BF174CF692694ll, 0xE49B69C19EF14AD2ll, 0xEFBE4786384F25E3ll, + 0x0FC19DC68B8CD5B5ll, 0x240CA1CC77AC9C65ll, 0x2DE92C6F592B0275ll, + 0x4A7484AA6EA6E483ll, 0x5CB0A9DCBD41FBD4ll, 0x76F988DA831153B5ll, + 0x983E5152EE66DFABll, 0xA831C66D2DB43210ll, 0xB00327C898FB213Fll, + 0xBF597FC7BEEF0EE4ll, 0xC6E00BF33DA88FC2ll, 0xD5A79147930AA725ll, + 0x06CA6351E003826Fll, 0x142929670A0E6E70ll, 0x27B70A8546D22FFCll, + 0x2E1B21385C26C926ll, 0x4D2C6DFC5AC42AEDll, 0x53380D139D95B3DFll, + 0x650A73548BAF63DEll, 0x766A0ABB3C77B2A8ll, 0x81C2C92E47EDAEE6ll, + 0x92722C851482353Bll, 0xA2BFE8A14CF10364ll, 0xA81A664BBC423001ll, + 0xC24B8B70D0F89791ll, 0xC76C51A30654BE30ll, 0xD192E819D6EF5218ll, + 0xD69906245565A910ll, 0xF40E35855771202All, 0x106AA07032BBD1B8ll, + 0x19A4C116B8D2D0C8ll, 0x1E376C085141AB53ll, 0x2748774CDF8EEB99ll, + 0x34B0BCB5E19B48A8ll, 0x391C0CB3C5C95A63ll, 0x4ED8AA4AE3418ACBll, + 0x5B9CCA4F7763E373ll, 0x682E6FF3D6B2B8A3ll, 0x748F82EE5DEFB2FCll, + 0x78A5636F43172F60ll, 0x84C87814A1F0AB72ll, 0x8CC702081A6439ECll, + 0x90BEFFFA23631E28ll, 0xA4506CEBDE82BDE9ll, 0xBEF9A3F7B2C67915ll, + 0xC67178F2E372532Bll, 0xCA273ECEEA26619Cll, 0xD186B8C721C0C207ll, + 0xEADA7DD6CDE0EB1Ell, 0xF57D4F7FEE6ED178ll, 0x06F067AA72176FBAll, + 0x0A637DC5A2C898A6ll, 0x113F9804BEF90DAEll, 0x1B710B35131C471Bll, + 0x28DB77F523047D84ll, 0x32CAAB7B40C72493ll, 0x3C9EBE0A15C9BEBCll, + 0x431D67C49C100D4Cll, 0x4CC5D4BECB3E42B6ll, 0x597F299CFC657E2All, + 0x5FCB6FAB3AD6FAECll, 0x6C44198C4A475817ll + }; + int t, t8; /* Loop counter */ + uint64_t temp1, temp2; /* Temporary word value */ + uint64_t W[80]; /* Word sequence */ + uint64_t A, B, C, D, E, F, G, H; /* Word buffers */ + + /* + * Initialize the first 16 words in the array W + */ + for (t = t8 = 0; t < 16; t++, t8 += 8) + W[t] = ((uint64_t)(context->Message_Block[t8 ]) << 56) | + ((uint64_t)(context->Message_Block[t8 + 1]) << 48) | + ((uint64_t)(context->Message_Block[t8 + 2]) << 40) | + ((uint64_t)(context->Message_Block[t8 + 3]) << 32) | + ((uint64_t)(context->Message_Block[t8 + 4]) << 24) | + ((uint64_t)(context->Message_Block[t8 + 5]) << 16) | + ((uint64_t)(context->Message_Block[t8 + 6]) << 8) | + ((uint64_t)(context->Message_Block[t8 + 7])); + + for (t = 16; t < 80; t++) + W[t] = SHA512_sigma1(W[t-2]) + W[t-7] + + SHA512_sigma0(W[t-15]) + W[t-16]; + A = context->Intermediate_Hash[0]; + B = context->Intermediate_Hash[1]; + C = context->Intermediate_Hash[2]; + D = context->Intermediate_Hash[3]; + E = context->Intermediate_Hash[4]; + F = context->Intermediate_Hash[5]; + G = context->Intermediate_Hash[6]; + H = context->Intermediate_Hash[7]; + + for (t = 0; t < 80; t++) { + temp1 = H + SHA512_SIGMA1(E) + SHA_Ch(E,F,G) + K[t] + W[t]; + temp2 = SHA512_SIGMA0(A) + SHA_Maj(A,B,C); + H = G; + G = F; + F = E; + E = D + temp1; + D = C; + C = B; + B = A; + A = temp1 + temp2; + } + + context->Intermediate_Hash[0] += A; + context->Intermediate_Hash[1] += B; + context->Intermediate_Hash[2] += C; + context->Intermediate_Hash[3] += D; + context->Intermediate_Hash[4] += E; + context->Intermediate_Hash[5] += F; + context->Intermediate_Hash[6] += G; + context->Intermediate_Hash[7] += H; +#endif /* USE_32BIT_ONLY */ + + context->Message_Block_Index = 0; +} + +/* + * SHA384_512Finalize + * + * Description: + * This helper function finishes off the digest calculations. + * + * Parameters: + * context: [in/out] + * The SHA context to update. + * Pad_Byte: [in] + * The last byte to add to the message block before the 0-padding + * and length. This will contain the last bits of the message + * followed by another single bit. If the message was an + * exact multiple of 8-bits long, Pad_Byte will be 0x80. + * + * Returns: + * sha Error Code. + * + */ +static void SHA384_512Finalize(SHA512Context *context, + uint8_t Pad_Byte) +{ + int_least16_t i; + SHA384_512PadMessage(context, Pad_Byte); + /* message may be sensitive, clear it out */ + for (i = 0; i < SHA512_Message_Block_Size; ++i) + context->Message_Block[i] = 0; +#ifdef USE_32BIT_ONLY /* and clear length */ + context->Length[0] = context->Length[1] = 0; + context->Length[2] = context->Length[3] = 0; +#else /* !USE_32BIT_ONLY */ + context->Length_High = context->Length_Low = 0; +#endif /* USE_32BIT_ONLY */ + context->Computed = 1; +} + +/* + * SHA384_512PadMessage + * + * Description: + * According to the standard, the message must be padded to the next + * even multiple of 1024 bits. The first padding bit must be a '1'. + * The last 128 bits represent the length of the original message. + * All bits in between should be 0. This helper function will + * pad the message according to those rules by filling the + * Message_Block array accordingly. When it returns, it can be + * assumed that the message digest has been computed. + * + * Parameters: + * context: [in/out] + * The context to pad. + * Pad_Byte: [in] + * The last byte to add to the message block before the 0-padding + * and length. This will contain the last bits of the message + * followed by another single bit. If the message was an + * exact multiple of 8-bits long, Pad_Byte will be 0x80. + * + * Returns: + * Nothing. + * + */ +static void SHA384_512PadMessage(SHA512Context *context, + uint8_t Pad_Byte) +{ + /* + * Check to see if the current message block is too small to hold + * the initial padding bits and length. If so, we will pad the + * block, process it, and then continue padding into a second + * block. + */ + if (context->Message_Block_Index >= (SHA512_Message_Block_Size-16)) { + context->Message_Block[context->Message_Block_Index++] = Pad_Byte; + while (context->Message_Block_Index < SHA512_Message_Block_Size) + context->Message_Block[context->Message_Block_Index++] = 0; + + SHA384_512ProcessMessageBlock(context); + } else + context->Message_Block[context->Message_Block_Index++] = Pad_Byte; + + while (context->Message_Block_Index < (SHA512_Message_Block_Size-16)) + context->Message_Block[context->Message_Block_Index++] = 0; + + /* + * Store the message length as the last 16 octets + */ +#ifdef USE_32BIT_ONLY + context->Message_Block[112] = (uint8_t)(context->Length[0] >> 24); + context->Message_Block[113] = (uint8_t)(context->Length[0] >> 16); + context->Message_Block[114] = (uint8_t)(context->Length[0] >> 8); + context->Message_Block[115] = (uint8_t)(context->Length[0]); + context->Message_Block[116] = (uint8_t)(context->Length[1] >> 24); + context->Message_Block[117] = (uint8_t)(context->Length[1] >> 16); + context->Message_Block[118] = (uint8_t)(context->Length[1] >> 8); + context->Message_Block[119] = (uint8_t)(context->Length[1]); + + context->Message_Block[120] = (uint8_t)(context->Length[2] >> 24); + context->Message_Block[121] = (uint8_t)(context->Length[2] >> 16); + context->Message_Block[122] = (uint8_t)(context->Length[2] >> 8); + context->Message_Block[123] = (uint8_t)(context->Length[2]); + context->Message_Block[124] = (uint8_t)(context->Length[3] >> 24); + context->Message_Block[125] = (uint8_t)(context->Length[3] >> 16); + context->Message_Block[126] = (uint8_t)(context->Length[3] >> 8); + context->Message_Block[127] = (uint8_t)(context->Length[3]); +#else /* !USE_32BIT_ONLY */ + context->Message_Block[112] = (uint8_t)(context->Length_High >> 56); + context->Message_Block[113] = (uint8_t)(context->Length_High >> 48); + context->Message_Block[114] = (uint8_t)(context->Length_High >> 40); + context->Message_Block[115] = (uint8_t)(context->Length_High >> 32); + context->Message_Block[116] = (uint8_t)(context->Length_High >> 24); + context->Message_Block[117] = (uint8_t)(context->Length_High >> 16); + context->Message_Block[118] = (uint8_t)(context->Length_High >> 8); + context->Message_Block[119] = (uint8_t)(context->Length_High); + + context->Message_Block[120] = (uint8_t)(context->Length_Low >> 56); + context->Message_Block[121] = (uint8_t)(context->Length_Low >> 48); + context->Message_Block[122] = (uint8_t)(context->Length_Low >> 40); + context->Message_Block[123] = (uint8_t)(context->Length_Low >> 32); + context->Message_Block[124] = (uint8_t)(context->Length_Low >> 24); + context->Message_Block[125] = (uint8_t)(context->Length_Low >> 16); + context->Message_Block[126] = (uint8_t)(context->Length_Low >> 8); + context->Message_Block[127] = (uint8_t)(context->Length_Low); +#endif /* USE_32BIT_ONLY */ + + SHA384_512ProcessMessageBlock(context); +} + +/* + * SHA384_512ResultN + * + * Description: + * This helper function will return the 384-bit or 512-bit message + * digest into the Message_Digest array provided by the caller. + * NOTE: + * The first octet of hash is stored in the element with index 0, + * the last octet of hash in the element with index 47/63. + * + * Parameters: + * context: [in/out] + * The context to use to calculate the SHA hash. + * Message_Digest[ ]: [out] + * Where the digest is returned. + * HashSize: [in] + * The size of the hash, either 48 or 64. + * + * Returns: + * sha Error Code. + * + */ +static int SHA384_512ResultN(SHA512Context *context, + uint8_t Message_Digest[ ], int HashSize) +{ + int i; +#ifdef USE_32BIT_ONLY + int i2; +#endif /* USE_32BIT_ONLY */ + + if (!context) return shaNull; + if (!Message_Digest) return shaNull; + if (context->Corrupted) return context->Corrupted; + + if (!context->Computed) + SHA384_512Finalize(context, 0x80); + +#ifdef USE_32BIT_ONLY + for (i = i2 = 0; i < HashSize; ) { + Message_Digest[i++]=(uint8_t)(context->Intermediate_Hash[i2]>>24); + Message_Digest[i++]=(uint8_t)(context->Intermediate_Hash[i2]>>16); + Message_Digest[i++]=(uint8_t)(context->Intermediate_Hash[i2]>>8); + Message_Digest[i++]=(uint8_t)(context->Intermediate_Hash[i2++]); + Message_Digest[i++]=(uint8_t)(context->Intermediate_Hash[i2]>>24); + Message_Digest[i++]=(uint8_t)(context->Intermediate_Hash[i2]>>16); + Message_Digest[i++]=(uint8_t)(context->Intermediate_Hash[i2]>>8); + Message_Digest[i++]=(uint8_t)(context->Intermediate_Hash[i2++]); + } +#else /* !USE_32BIT_ONLY */ + for (i = 0; i < HashSize; ++i) + Message_Digest[i] = (uint8_t) + (context->Intermediate_Hash[i>>3] >> 8 * ( 7 - ( i % 8 ) )); +#endif /* USE_32BIT_ONLY */ + + return shaSuccess; +} + diff --git a/lib/libesp32_div/ESP32-HomeKit/src/shatest.c b/lib/libesp32_div/ESP32-HomeKit/src/shatest.c new file mode 100644 index 000000000..3924a31d5 --- /dev/null +++ b/lib/libesp32_div/ESP32-HomeKit/src/shatest.c @@ -0,0 +1,1530 @@ +/************************** shatest.c **************************/ +/***************** See RFC 6234 for details. *******************/ +/* Copyright (c) 2011 IETF Trust and the persons identified as */ +/* authors of the code. All rights reserved. */ +/* See sha.h for terms of use and redistribution. */ + +/* + * Description: + * This file will exercise the SHA code performing + * the three tests documented in FIPS PUB 180-3 + * (http://csrc.nist.gov/publications/fips/ + * fips180-2/fips180-2withchangenotice.pdf) + * one that calls SHAInput with an exact multiple of 512 bits + * the seven tests documented for each algorithm in + * "The Secure Hash Algorithm Validation System (SHAVS)" + * (http://csrc.nist.gov/cryptval/shs/SHAVS.pdf), + * three of which are bit-level tests + * + * These tests have subsequently been moved to pages linked from + * http://csrc.nist.gov/groups/ST/toolkit/examples.html + * + * This file will exercise the HMAC SHA1 code performing + * the seven tests documented in RFCs [RFC 2202] and [RFC 4231]. + * + * This file will exercise the HKDF code performing + * the seven tests documented in RFC 4869. + * + * To run the tests and just see PASSED/FAILED, use the -p option. + * + * Other options exercise: + * hashing an arbitrary string + * hashing a file's contents + * a few error test checks + * printing the results in raw format + * + * Portability Issues: + * None. + * + */ + +#include +#include +#include +#include +#include +#include /* defines getopt() and optarg */ +#include "sha.h" + +static int scasecmp(const char *s1, const char *s2); + +/* + * Define patterns for testing + */ +#define TEST1 "abc" +#define TEST2_1 \ + "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" +#define TEST2_2a \ + "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn" +#define TEST2_2b \ + "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu" +#define TEST2_2 TEST2_2a TEST2_2b +#define TEST3 "a" /* times 1000000 */ +#define TEST4a "01234567012345670123456701234567" +#define TEST4b "01234567012345670123456701234567" + /* an exact multiple of 512 bits */ +#define TEST4 TEST4a TEST4b /* times 10 */ +#define TEST7_1 \ + "\x49\xb2\xae\xc2\x59\x4b\xbe\x3a\x3b\x11\x75\x42\xd9\x4a\xc8" +#define TEST8_1 \ + "\x9a\x7d\xfd\xf1\xec\xea\xd0\x6e\xd6\x46\xaa\x55\xfe\x75\x71\x46" +#define TEST9_1 \ + "\x65\xf9\x32\x99\x5b\xa4\xce\x2c\xb1\xb4\xa2\xe7\x1a\xe7\x02\x20" \ + "\xaa\xce\xc8\x96\x2d\xd4\x49\x9c\xbd\x7c\x88\x7a\x94\xea\xaa\x10" \ + "\x1e\xa5\xaa\xbc\x52\x9b\x4e\x7e\x43\x66\x5a\x5a\xf2\xcd\x03\xfe" \ + "\x67\x8e\xa6\xa5\x00\x5b\xba\x3b\x08\x22\x04\xc2\x8b\x91\x09\xf4" \ + "\x69\xda\xc9\x2a\xaa\xb3\xaa\x7c\x11\xa1\xb3\x2a" +#define TEST10_1 \ + "\xf7\x8f\x92\x14\x1b\xcd\x17\x0a\xe8\x9b\x4f\xba\x15\xa1\xd5\x9f" \ + "\x3f\xd8\x4d\x22\x3c\x92\x51\xbd\xac\xbb\xae\x61\xd0\x5e\xd1\x15" \ + "\xa0\x6a\x7c\xe1\x17\xb7\xbe\xea\xd2\x44\x21\xde\xd9\xc3\x25\x92" \ + "\xbd\x57\xed\xea\xe3\x9c\x39\xfa\x1f\xe8\x94\x6a\x84\xd0\xcf\x1f" \ + "\x7b\xee\xad\x17\x13\xe2\xe0\x95\x98\x97\x34\x7f\x67\xc8\x0b\x04" \ + "\x00\xc2\x09\x81\x5d\x6b\x10\xa6\x83\x83\x6f\xd5\x56\x2a\x56\xca" \ + "\xb1\xa2\x8e\x81\xb6\x57\x66\x54\x63\x1c\xf1\x65\x66\xb8\x6e\x3b" \ + "\x33\xa1\x08\xb0\x53\x07\xc0\x0a\xff\x14\xa7\x68\xed\x73\x50\x60" \ + "\x6a\x0f\x85\xe6\xa9\x1d\x39\x6f\x5b\x5c\xbe\x57\x7f\x9b\x38\x80" \ + "\x7c\x7d\x52\x3d\x6d\x79\x2f\x6e\xbc\x24\xa4\xec\xf2\xb3\xa4\x27" \ + "\xcd\xbb\xfb" +#define TEST7_224 \ + "\xf0\x70\x06\xf2\x5a\x0b\xea\x68\xcd\x76\xa2\x95\x87\xc2\x8d" +#define TEST8_224 \ + "\x18\x80\x40\x05\xdd\x4f\xbd\x15\x56\x29\x9d\x6f\x9d\x93\xdf\x62" +#define TEST9_224 \ + "\xa2\xbe\x6e\x46\x32\x81\x09\x02\x94\xd9\xce\x94\x82\x65\x69\x42" \ + "\x3a\x3a\x30\x5e\xd5\xe2\x11\x6c\xd4\xa4\xc9\x87\xfc\x06\x57\x00" \ + "\x64\x91\xb1\x49\xcc\xd4\xb5\x11\x30\xac\x62\xb1\x9d\xc2\x48\xc7" \ + "\x44\x54\x3d\x20\xcd\x39\x52\xdc\xed\x1f\x06\xcc\x3b\x18\xb9\x1f" \ + "\x3f\x55\x63\x3e\xcc\x30\x85\xf4\x90\x70\x60\xd2" +#define TEST10_224 \ + "\x55\xb2\x10\x07\x9c\x61\xb5\x3a\xdd\x52\x06\x22\xd1\xac\x97\xd5" \ + "\xcd\xbe\x8c\xb3\x3a\xa0\xae\x34\x45\x17\xbe\xe4\xd7\xba\x09\xab" \ + "\xc8\x53\x3c\x52\x50\x88\x7a\x43\xbe\xbb\xac\x90\x6c\x2e\x18\x37" \ + "\xf2\x6b\x36\xa5\x9a\xe3\xbe\x78\x14\xd5\x06\x89\x6b\x71\x8b\x2a" \ + "\x38\x3e\xcd\xac\x16\xb9\x61\x25\x55\x3f\x41\x6f\xf3\x2c\x66\x74" \ + "\xc7\x45\x99\xa9\x00\x53\x86\xd9\xce\x11\x12\x24\x5f\x48\xee\x47" \ + "\x0d\x39\x6c\x1e\xd6\x3b\x92\x67\x0c\xa5\x6e\xc8\x4d\xee\xa8\x14" \ + "\xb6\x13\x5e\xca\x54\x39\x2b\xde\xdb\x94\x89\xbc\x9b\x87\x5a\x8b" \ + "\xaf\x0d\xc1\xae\x78\x57\x36\x91\x4a\xb7\xda\xa2\x64\xbc\x07\x9d" \ + "\x26\x9f\x2c\x0d\x7e\xdd\xd8\x10\xa4\x26\x14\x5a\x07\x76\xf6\x7c" \ + "\x87\x82\x73" +#define TEST7_256 \ + "\xbe\x27\x46\xc6\xdb\x52\x76\x5f\xdb\x2f\x88\x70\x0f\x9a\x73" +#define TEST8_256 \ + "\xe3\xd7\x25\x70\xdc\xdd\x78\x7c\xe3\x88\x7a\xb2\xcd\x68\x46\x52" +#define TEST9_256 \ + "\x3e\x74\x03\x71\xc8\x10\xc2\xb9\x9f\xc0\x4e\x80\x49\x07\xef\x7c" \ + "\xf2\x6b\xe2\x8b\x57\xcb\x58\xa3\xe2\xf3\xc0\x07\x16\x6e\x49\xc1" \ + "\x2e\x9b\xa3\x4c\x01\x04\x06\x91\x29\xea\x76\x15\x64\x25\x45\x70" \ + "\x3a\x2b\xd9\x01\xe1\x6e\xb0\xe0\x5d\xeb\xa0\x14\xeb\xff\x64\x06" \ + "\xa0\x7d\x54\x36\x4e\xff\x74\x2d\xa7\x79\xb0\xb3" +#define TEST10_256 \ + "\x83\x26\x75\x4e\x22\x77\x37\x2f\x4f\xc1\x2b\x20\x52\x7a\xfe\xf0" \ + "\x4d\x8a\x05\x69\x71\xb1\x1a\xd5\x71\x23\xa7\xc1\x37\x76\x00\x00" \ + "\xd7\xbe\xf6\xf3\xc1\xf7\xa9\x08\x3a\xa3\x9d\x81\x0d\xb3\x10\x77" \ + "\x7d\xab\x8b\x1e\x7f\x02\xb8\x4a\x26\xc7\x73\x32\x5f\x8b\x23\x74" \ + "\xde\x7a\x4b\x5a\x58\xcb\x5c\x5c\xf3\x5b\xce\xe6\xfb\x94\x6e\x5b" \ + "\xd6\x94\xfa\x59\x3a\x8b\xeb\x3f\x9d\x65\x92\xec\xed\xaa\x66\xca" \ + "\x82\xa2\x9d\x0c\x51\xbc\xf9\x33\x62\x30\xe5\xd7\x84\xe4\xc0\xa4" \ + "\x3f\x8d\x79\xa3\x0a\x16\x5c\xba\xbe\x45\x2b\x77\x4b\x9c\x71\x09" \ + "\xa9\x7d\x13\x8f\x12\x92\x28\x96\x6f\x6c\x0a\xdc\x10\x6a\xad\x5a" \ + "\x9f\xdd\x30\x82\x57\x69\xb2\xc6\x71\xaf\x67\x59\xdf\x28\xeb\x39" \ + "\x3d\x54\xd6" +#define TEST7_384 \ + "\x8b\xc5\x00\xc7\x7c\xee\xd9\x87\x9d\xa9\x89\x10\x7c\xe0\xaa" +#define TEST8_384 \ + "\xa4\x1c\x49\x77\x79\xc0\x37\x5f\xf1\x0a\x7f\x4e\x08\x59\x17\x39" +#define TEST9_384 \ + "\x68\xf5\x01\x79\x2d\xea\x97\x96\x76\x70\x22\xd9\x3d\xa7\x16\x79" \ + "\x30\x99\x20\xfa\x10\x12\xae\xa3\x57\xb2\xb1\x33\x1d\x40\xa1\xd0" \ + "\x3c\x41\xc2\x40\xb3\xc9\xa7\x5b\x48\x92\xf4\xc0\x72\x4b\x68\xc8" \ + "\x75\x32\x1a\xb8\xcf\xe5\x02\x3b\xd3\x75\xbc\x0f\x94\xbd\x89\xfe" \ + "\x04\xf2\x97\x10\x5d\x7b\x82\xff\xc0\x02\x1a\xeb\x1c\xcb\x67\x4f" \ + "\x52\x44\xea\x34\x97\xde\x26\xa4\x19\x1c\x5f\x62\xe5\xe9\xa2\xd8" \ + "\x08\x2f\x05\x51\xf4\xa5\x30\x68\x26\xe9\x1c\xc0\x06\xce\x1b\xf6" \ + "\x0f\xf7\x19\xd4\x2f\xa5\x21\xc8\x71\xcd\x23\x94\xd9\x6e\xf4\x46" \ + "\x8f\x21\x96\x6b\x41\xf2\xba\x80\xc2\x6e\x83\xa9" +#define TEST10_384 \ + "\x39\x96\x69\xe2\x8f\x6b\x9c\x6d\xbc\xbb\x69\x12\xec\x10\xff\xcf" \ + "\x74\x79\x03\x49\xb7\xdc\x8f\xbe\x4a\x8e\x7b\x3b\x56\x21\xdb\x0f" \ + "\x3e\x7d\xc8\x7f\x82\x32\x64\xbb\xe4\x0d\x18\x11\xc9\xea\x20\x61" \ + "\xe1\xc8\x4a\xd1\x0a\x23\xfa\xc1\x72\x7e\x72\x02\xfc\x3f\x50\x42" \ + "\xe6\xbf\x58\xcb\xa8\xa2\x74\x6e\x1f\x64\xf9\xb9\xea\x35\x2c\x71" \ + "\x15\x07\x05\x3c\xf4\xe5\x33\x9d\x52\x86\x5f\x25\xcc\x22\xb5\xe8" \ + "\x77\x84\xa1\x2f\xc9\x61\xd6\x6c\xb6\xe8\x95\x73\x19\x9a\x2c\xe6" \ + "\x56\x5c\xbd\xf1\x3d\xca\x40\x38\x32\xcf\xcb\x0e\x8b\x72\x11\xe8" \ + "\x3a\xf3\x2a\x11\xac\x17\x92\x9f\xf1\xc0\x73\xa5\x1c\xc0\x27\xaa" \ + "\xed\xef\xf8\x5a\xad\x7c\x2b\x7c\x5a\x80\x3e\x24\x04\xd9\x6d\x2a" \ + "\x77\x35\x7b\xda\x1a\x6d\xae\xed\x17\x15\x1c\xb9\xbc\x51\x25\xa4" \ + "\x22\xe9\x41\xde\x0c\xa0\xfc\x50\x11\xc2\x3e\xcf\xfe\xfd\xd0\x96" \ + "\x76\x71\x1c\xf3\xdb\x0a\x34\x40\x72\x0e\x16\x15\xc1\xf2\x2f\xbc" \ + "\x3c\x72\x1d\xe5\x21\xe1\xb9\x9b\xa1\xbd\x55\x77\x40\x86\x42\x14" \ + "\x7e\xd0\x96" +#define TEST7_512 \ + "\x08\xec\xb5\x2e\xba\xe1\xf7\x42\x2d\xb6\x2b\xcd\x54\x26\x70" +#define TEST8_512 \ + "\x8d\x4e\x3c\x0e\x38\x89\x19\x14\x91\x81\x6e\x9d\x98\xbf\xf0\xa0" +#define TEST9_512 \ + "\x3a\xdd\xec\x85\x59\x32\x16\xd1\x61\x9a\xa0\x2d\x97\x56\x97\x0b" \ + "\xfc\x70\xac\xe2\x74\x4f\x7c\x6b\x27\x88\x15\x10\x28\xf7\xb6\xa2" \ + "\x55\x0f\xd7\x4a\x7e\x6e\x69\xc2\xc9\xb4\x5f\xc4\x54\x96\x6d\xc3" \ + "\x1d\x2e\x10\xda\x1f\x95\xce\x02\xbe\xb4\xbf\x87\x65\x57\x4c\xbd" \ + "\x6e\x83\x37\xef\x42\x0a\xdc\x98\xc1\x5c\xb6\xd5\xe4\xa0\x24\x1b" \ + "\xa0\x04\x6d\x25\x0e\x51\x02\x31\xca\xc2\x04\x6c\x99\x16\x06\xab" \ + "\x4e\xe4\x14\x5b\xee\x2f\xf4\xbb\x12\x3a\xab\x49\x8d\x9d\x44\x79" \ + "\x4f\x99\xcc\xad\x89\xa9\xa1\x62\x12\x59\xed\xa7\x0a\x5b\x6d\xd4" \ + "\xbd\xd8\x77\x78\xc9\x04\x3b\x93\x84\xf5\x49\x06" +#define TEST10_512 \ + "\xa5\x5f\x20\xc4\x11\xaa\xd1\x32\x80\x7a\x50\x2d\x65\x82\x4e\x31" \ + "\xa2\x30\x54\x32\xaa\x3d\x06\xd3\xe2\x82\xa8\xd8\x4e\x0d\xe1\xde" \ + "\x69\x74\xbf\x49\x54\x69\xfc\x7f\x33\x8f\x80\x54\xd5\x8c\x26\xc4" \ + "\x93\x60\xc3\xe8\x7a\xf5\x65\x23\xac\xf6\xd8\x9d\x03\xe5\x6f\xf2" \ + "\xf8\x68\x00\x2b\xc3\xe4\x31\xed\xc4\x4d\xf2\xf0\x22\x3d\x4b\xb3" \ + "\xb2\x43\x58\x6e\x1a\x7d\x92\x49\x36\x69\x4f\xcb\xba\xf8\x8d\x95" \ + "\x19\xe4\xeb\x50\xa6\x44\xf8\xe4\xf9\x5e\xb0\xea\x95\xbc\x44\x65" \ + "\xc8\x82\x1a\xac\xd2\xfe\x15\xab\x49\x81\x16\x4b\xbb\x6d\xc3\x2f" \ + "\x96\x90\x87\xa1\x45\xb0\xd9\xcc\x9c\x67\xc2\x2b\x76\x32\x99\x41" \ + "\x9c\xc4\x12\x8b\xe9\xa0\x77\xb3\xac\xe6\x34\x06\x4e\x6d\x99\x28" \ + "\x35\x13\xdc\x06\xe7\x51\x5d\x0d\x73\x13\x2e\x9a\x0d\xc6\xd3\xb1" \ + "\xf8\xb2\x46\xf1\xa9\x8a\x3f\xc7\x29\x41\xb1\xe3\xbb\x20\x98\xe8" \ + "\xbf\x16\xf2\x68\xd6\x4f\x0b\x0f\x47\x07\xfe\x1e\xa1\xa1\x79\x1b" \ + "\xa2\xf3\xc0\xc7\x58\xe5\xf5\x51\x86\x3a\x96\xc9\x49\xad\x47\xd7" \ + "\xfb\x40\xd2" +#define SHA1_SEED "\xd0\x56\x9c\xb3\x66\x5a\x8a\x43\xeb\x6e\xa2\x3d" \ + "\x75\xa3\xc4\xd2\x05\x4a\x0d\x7d" +#define SHA224_SEED "\xd0\x56\x9c\xb3\x66\x5a\x8a\x43\xeb\x6e\xa2" \ + "\x3d\x75\xa3\xc4\xd2\x05\x4a\x0d\x7d\x66\xa9\xca\x99\xc9\xce\xb0" \ + "\x27" +#define SHA256_SEED "\xf4\x1e\xce\x26\x13\xe4\x57\x39\x15\x69\x6b" \ + "\x5a\xdc\xd5\x1c\xa3\x28\xbe\x3b\xf5\x66\xa9\xca\x99\xc9\xce\xb0" \ + "\x27\x9c\x1c\xb0\xa7" +#define SHA384_SEED "\x82\x40\xbc\x51\xe4\xec\x7e\xf7\x6d\x18\xe3" \ + "\x52\x04\xa1\x9f\x51\xa5\x21\x3a\x73\xa8\x1d\x6f\x94\x46\x80\xd3" \ + "\x07\x59\x48\xb7\xe4\x63\x80\x4e\xa3\xd2\x6e\x13\xea\x82\x0d\x65" \ + "\xa4\x84\xbe\x74\x53" +#define SHA512_SEED "\x47\x3f\xf1\xb9\xb3\xff\xdf\xa1\x26\x69\x9a" \ + "\xc7\xef\x9e\x8e\x78\x77\x73\x09\x58\x24\xc6\x42\x55\x7c\x13\x99" \ + "\xd9\x8e\x42\x20\x44\x8d\xc3\x5b\x99\xbf\xdd\x44\x77\x95\x43\x92" \ + "\x4c\x1c\xe9\x3b\xc5\x94\x15\x38\x89\x5d\xb9\x88\x26\x1b\x00\x77" \ + "\x4b\x12\x27\x20\x39" + +#define TESTCOUNT 10 +#define HASHCOUNT 5 +#define RANDOMCOUNT 4 +#define HMACTESTCOUNT 7 +#define HKDFTESTCOUNT 7 + +#define PRINTNONE 0 +#define PRINTTEXT 1 +#define PRINTRAW 2 +#define PRINTHEX 3 +#define PRINTBASE64 4 + +#define PRINTPASSFAIL 1 +#define PRINTFAIL 2 + +#define length(x) (sizeof(x)-1) + +/* Test arrays for hashes. */ +struct hash { + const char *name; + SHAversion whichSha; + int hashsize; + struct { + const char *testarray; + int length; + long repeatcount; + int extrabits; + int numberExtrabits; + const char *resultarray; + } tests[TESTCOUNT]; + const char *randomtest; + const char *randomresults[RANDOMCOUNT]; +} hashes[HASHCOUNT] = { + { "SHA1", SHA1, SHA1HashSize, + { + /* 1 */ { TEST1, length(TEST1), 1, 0, 0, + "A9993E364706816ABA3E25717850C26C9CD0D89D" }, + /* 2 */ { TEST2_1, length(TEST2_1), 1, 0, 0, + "84983E441C3BD26EBAAE4AA1F95129E5E54670F1" }, + /* 3 */ { TEST3, length(TEST3), 1000000, 0, 0, + "34AA973CD4C4DAA4F61EEB2BDBAD27316534016F" }, + /* 4 */ { TEST4, length(TEST4), 10, 0, 0, + "DEA356A2CDDD90C7A7ECEDC5EBB563934F460452" }, + /* 5 */ { "", 0, 0, 0x98, 5, + "29826B003B906E660EFF4027CE98AF3531AC75BA" }, + /* 6 */ { "\x5e", 1, 1, 0, 0, + "5E6F80A34A9798CAFC6A5DB96CC57BA4C4DB59C2" }, + /* 7 */ { TEST7_1, length(TEST7_1), 1, 0x80, 3, + "6239781E03729919C01955B3FFA8ACB60B988340" }, + /* 8 */ { TEST8_1, length(TEST8_1), 1, 0, 0, + "82ABFF6605DBE1C17DEF12A394FA22A82B544A35" }, + /* 9 */ { TEST9_1, length(TEST9_1), 1, 0xE0, 3, + "8C5B2A5DDAE5A97FC7F9D85661C672ADBF7933D4" }, + /* 10 */ { TEST10_1, length(TEST10_1), 1, 0, 0, + "CB0082C8F197D260991BA6A460E76E202BAD27B3" } + }, SHA1_SEED, { "E216836819477C7F78E0D843FE4FF1B6D6C14CD4", + "A2DBC7A5B1C6C0A8BCB7AAA41252A6A7D0690DBC", + "DB1F9050BB863DFEF4CE37186044E2EEB17EE013", + "127FDEDF43D372A51D5747C48FBFFE38EF6CDF7B" + } }, + { "SHA224", SHA224, SHA224HashSize, + { + /* 1 */ { TEST1, length(TEST1), 1, 0, 0, + "23097D223405D8228642A477BDA255B32AADBCE4BDA0B3F7E36C9DA7" }, + /* 2 */ { TEST2_1, length(TEST2_1), 1, 0, 0, + "75388B16512776CC5DBA5DA1FD890150B0C6455CB4F58B1952522525" }, + /* 3 */ { TEST3, length(TEST3), 1000000, 0, 0, + "20794655980C91D8BBB4C1EA97618A4BF03F42581948B2EE4EE7AD67" }, + /* 4 */ { TEST4, length(TEST4), 10, 0, 0, + "567F69F168CD7844E65259CE658FE7AADFA25216E68ECA0EB7AB8262" }, + /* 5 */ { "", 0, 0, 0x68, 5, + "E3B048552C3C387BCAB37F6EB06BB79B96A4AEE5FF27F51531A9551C" }, + /* 6 */ { "\x07", 1, 1, 0, 0, + "00ECD5F138422B8AD74C9799FD826C531BAD2FCABC7450BEE2AA8C2A" }, + /* 7 */ { TEST7_224, length(TEST7_224), 1, 0xA0, 3, + "1B01DB6CB4A9E43DED1516BEB3DB0B87B6D1EA43187462C608137150" }, + /* 8 */ { TEST8_224, length(TEST8_224), 1, 0, 0, + "DF90D78AA78821C99B40BA4C966921ACCD8FFB1E98AC388E56191DB1" }, + /* 9 */ { TEST9_224, length(TEST9_224), 1, 0xE0, 3, + "54BEA6EAB8195A2EB0A7906A4B4A876666300EEFBD1F3B8474F9CD57" }, + /* 10 */ { TEST10_224, length(TEST10_224), 1, 0, 0, + "0B31894EC8937AD9B91BDFBCBA294D9ADEFAA18E09305E9F20D5C3A4" } + }, SHA224_SEED, { "100966A5B4FDE0B42E2A6C5953D4D7F41BA7CF79FD" + "2DF431416734BE", "1DCA396B0C417715DEFAAE9641E10A2E99D55A" + "BCB8A00061EB3BE8BD", "1864E627BDB2319973CD5ED7D68DA71D8B" + "F0F983D8D9AB32C34ADB34", "A2406481FC1BCAF24DD08E6752E844" + "709563FB916227FED598EB621F" + } }, + { "SHA256", SHA256, SHA256HashSize, + { + /* 1 */ { TEST1, length(TEST1), 1, 0, 0, "BA7816BF8F01CFEA4141" + "40DE5DAE2223B00361A396177A9CB410FF61F20015AD" }, + /* 2 */ { TEST2_1, length(TEST2_1), 1, 0, 0, "248D6A61D20638B8" + "E5C026930C3E6039A33CE45964FF2167F6ECEDD419DB06C1" }, + /* 3 */ { TEST3, length(TEST3), 1000000, 0, 0, "CDC76E5C9914FB92" + "81A1C7E284D73E67F1809A48A497200E046D39CCC7112CD0" }, + /* 4 */ { TEST4, length(TEST4), 10, 0, 0, "594847328451BDFA" + "85056225462CC1D867D877FB388DF0CE35F25AB5562BFBB5" }, + /* 5 */ { "", 0, 0, 0x68, 5, "D6D3E02A31A84A8CAA9718ED6C2057BE" + "09DB45E7823EB5079CE7A573A3760F95" }, + /* 6 */ { "\x19", 1, 1, 0, 0, "68AA2E2EE5DFF96E3355E6C7EE373E3D" + "6A4E17F75F9518D843709C0C9BC3E3D4" }, + /* 7 */ { TEST7_256, length(TEST7_256), 1, 0x60, 3, "77EC1DC8" + "9C821FF2A1279089FA091B35B8CD960BCAF7DE01C6A7680756BEB972" }, + /* 8 */ { TEST8_256, length(TEST8_256), 1, 0, 0, "175EE69B02BA" + "9B58E2B0A5FD13819CEA573F3940A94F825128CF4209BEABB4E8" }, + /* 9 */ { TEST9_256, length(TEST9_256), 1, 0xA0, 3, "3E9AD646" + "8BBBAD2AC3C2CDC292E018BA5FD70B960CF1679777FCE708FDB066E9" }, + /* 10 */ { TEST10_256, length(TEST10_256), 1, 0, 0, "97DBCA7D" + "F46D62C8A422C941DD7E835B8AD3361763F7E9B2D95F4F0DA6E1CCBC" }, + }, SHA256_SEED, { "83D28614D49C3ADC1D6FC05DB5F48037C056F8D2A4CE44" + "EC6457DEA5DD797CD1", "99DBE3127EF2E93DD9322D6A07909EB33B6399" + "5E529B3F954B8581621BB74D39", "8D4BE295BB64661CA3C7EFD129A2F7" + "25B33072DBDDE32385B9A87B9AF88EA76F", "40AF5D3F9716B040DF9408" + "E31536B70FF906EC51B00447CA97D7DD97C12411F4" + } }, + { "SHA384", SHA384, SHA384HashSize, + { + /* 1 */ { TEST1, length(TEST1), 1, 0, 0, + "CB00753F45A35E8BB5A03D699AC65007272C32AB0EDED163" + "1A8B605A43FF5BED8086072BA1E7CC2358BAECA134C825A7" }, + /* 2 */ { TEST2_2, length(TEST2_2), 1, 0, 0, + "09330C33F71147E83D192FC782CD1B4753111B173B3B05D2" + "2FA08086E3B0F712FCC7C71A557E2DB966C3E9FA91746039" }, + /* 3 */ { TEST3, length(TEST3), 1000000, 0, 0, + "9D0E1809716474CB086E834E310A4A1CED149E9C00F24852" + "7972CEC5704C2A5B07B8B3DC38ECC4EBAE97DDD87F3D8985" }, + /* 4 */ { TEST4, length(TEST4), 10, 0, 0, + "2FC64A4F500DDB6828F6A3430B8DD72A368EB7F3A8322A70" + "BC84275B9C0B3AB00D27A5CC3C2D224AA6B61A0D79FB4596" }, + /* 5 */ { "", 0, 0, 0x10, 5, + "8D17BE79E32B6718E07D8A603EB84BA0478F7FCFD1BB9399" + "5F7D1149E09143AC1FFCFC56820E469F3878D957A15A3FE4" }, + /* 6 */ { "\xb9", 1, 1, 0, 0, + "BC8089A19007C0B14195F4ECC74094FEC64F01F90929282C" + "2FB392881578208AD466828B1C6C283D2722CF0AD1AB6938" }, + /* 7 */ { TEST7_384, length(TEST7_384), 1, 0xA0, 3, + "D8C43B38E12E7C42A7C9B810299FD6A770BEF30920F17532" + "A898DE62C7A07E4293449C0B5FA70109F0783211CFC4BCE3" }, + /* 8 */ { TEST8_384, length(TEST8_384), 1, 0, 0, + "C9A68443A005812256B8EC76B00516F0DBB74FAB26D66591" + "3F194B6FFB0E91EA9967566B58109CBC675CC208E4C823F7" }, + /* 9 */ { TEST9_384, length(TEST9_384), 1, 0xE0, 3, + "5860E8DE91C21578BB4174D227898A98E0B45C4C760F0095" + "49495614DAEDC0775D92D11D9F8CE9B064EEAC8DAFC3A297" }, + /* 10 */ { TEST10_384, length(TEST10_384), 1, 0, 0, + "4F440DB1E6EDD2899FA335F09515AA025EE177A79F4B4AAF" + "38E42B5C4DE660F5DE8FB2A5B2FBD2A3CBFFD20CFF1288C0" } + }, SHA384_SEED, { "CE44D7D63AE0C91482998CF662A51EC80BF6FC68661A3C" + "57F87566112BD635A743EA904DEB7D7A42AC808CABE697F38F", "F9C6D2" + "61881FEE41ACD39E67AA8D0BAD507C7363EB67E2B81F45759F9C0FD7B503" + "DF1A0B9E80BDE7BC333D75B804197D", "D96512D8C9F4A7A4967A366C01" + "C6FD97384225B58343A88264847C18E4EF8AB7AEE4765FFBC3E30BD485D3" + "638A01418F", "0CA76BD0813AF1509E170907A96005938BC985628290B2" + "5FEF73CF6FAD68DDBA0AC8920C94E0541607B0915A7B4457F7" + } }, + { "SHA512", SHA512, SHA512HashSize, + { + /* 1 */ { TEST1, length(TEST1), 1, 0, 0, + "DDAF35A193617ABACC417349AE20413112E6FA4E89A97EA2" + "0A9EEEE64B55D39A2192992A274FC1A836BA3C23A3FEEBBD" + "454D4423643CE80E2A9AC94FA54CA49F" }, + /* 2 */ { TEST2_2, length(TEST2_2), 1, 0, 0, + "8E959B75DAE313DA8CF4F72814FC143F8F7779C6EB9F7FA1" + "7299AEADB6889018501D289E4900F7E4331B99DEC4B5433A" + "C7D329EEB6DD26545E96E55B874BE909" }, + /* 3 */ { TEST3, length(TEST3), 1000000, 0, 0, + "E718483D0CE769644E2E42C7BC15B4638E1F98B13B204428" + "5632A803AFA973EBDE0FF244877EA60A4CB0432CE577C31B" + "EB009C5C2C49AA2E4EADB217AD8CC09B" }, + /* 4 */ { TEST4, length(TEST4), 10, 0, 0, + "89D05BA632C699C31231DED4FFC127D5A894DAD412C0E024" + "DB872D1ABD2BA8141A0F85072A9BE1E2AA04CF33C765CB51" + "0813A39CD5A84C4ACAA64D3F3FB7BAE9" }, + /* 5 */ { "", 0, 0, 0xB0, 5, + "D4EE29A9E90985446B913CF1D1376C836F4BE2C1CF3CADA0" + "720A6BF4857D886A7ECB3C4E4C0FA8C7F95214E41DC1B0D2" + "1B22A84CC03BF8CE4845F34DD5BDBAD4" }, + /* 6 */ { "\xD0", 1, 1, 0, 0, + "9992202938E882E73E20F6B69E68A0A7149090423D93C81B" + "AB3F21678D4ACEEEE50E4E8CAFADA4C85A54EA8306826C4A" + "D6E74CECE9631BFA8A549B4AB3FBBA15" }, + /* 7 */ { TEST7_512, length(TEST7_512), 1, 0x80, 3, + "ED8DC78E8B01B69750053DBB7A0A9EDA0FB9E9D292B1ED71" + "5E80A7FE290A4E16664FD913E85854400C5AF05E6DAD316B" + "7359B43E64F8BEC3C1F237119986BBB6" }, + /* 8 */ { TEST8_512, length(TEST8_512), 1, 0, 0, + "CB0B67A4B8712CD73C9AABC0B199E9269B20844AFB75ACBD" + "D1C153C9828924C3DDEDAAFE669C5FDD0BC66F630F677398" + "8213EB1B16F517AD0DE4B2F0C95C90F8" }, + /* 9 */ { TEST9_512, length(TEST9_512), 1, 0x80, 3, + "32BA76FC30EAA0208AEB50FFB5AF1864FDBF17902A4DC0A6" + "82C61FCEA6D92B783267B21080301837F59DE79C6B337DB2" + "526F8A0A510E5E53CAFED4355FE7C2F1" }, + /* 10 */ { TEST10_512, length(TEST10_512), 1, 0, 0, + "C665BEFB36DA189D78822D10528CBF3B12B3EEF726039909" + "C1A16A270D48719377966B957A878E720584779A62825C18" + "DA26415E49A7176A894E7510FD1451F5" } + }, SHA512_SEED, { "2FBB1E7E00F746BA514FBC8C421F36792EC0E11FF5EFC3" + "78E1AB0C079AA5F0F66A1E3EDBAEB4F9984BE14437123038A452004A5576" + "8C1FD8EED49E4A21BEDCD0", "25CBE5A4F2C7B1D7EF07011705D50C62C5" + "000594243EAFD1241FC9F3D22B58184AE2FEE38E171CF8129E29459C9BC2" + "EF461AF5708887315F15419D8D17FE7949", "5B8B1F2687555CE2D7182B" + "92E5C3F6C36547DA1C13DBB9EA4F73EA4CBBAF89411527906D35B1B06C1B" + "6A8007D05EC66DF0A406066829EAB618BDE3976515AAFC", "46E36B007D" + "19876CDB0B29AD074FE3C08CDD174D42169D6ABE5A1414B6E79707DF5877" + "6A98091CF431854147BB6D3C66D43BFBC108FD715BDE6AA127C2B0E79F" + } + } +}; + +/* Test arrays for HMAC. */ +struct hmachash { + const char *keyarray[5]; + int keylength[5]; + const char *dataarray[5]; + int datalength[5]; + const char *resultarray[5]; + int resultlength[5]; +} hmachashes[HMACTESTCOUNT] = { + { /* 1 */ { + "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" + "\x0b\x0b\x0b\x0b\x0b" + }, { 20 }, { + "\x48\x69\x20\x54\x68\x65\x72\x65" /* "Hi There" */ + }, { 8 }, { + /* HMAC-SHA-1 */ + "B617318655057264E28BC0B6FB378C8EF146BE00", + /* HMAC-SHA-224 */ + "896FB1128ABBDF196832107CD49DF33F47B4B1169912BA4F53684B22", + /* HMAC-SHA-256 */ + "B0344C61D8DB38535CA8AFCEAF0BF12B881DC200C9833DA726E9376C2E32" + "CFF7", + /* HMAC-SHA-384 */ + "AFD03944D84895626B0825F4AB46907F15F9DADBE4101EC682AA034C7CEB" + "C59CFAEA9EA9076EDE7F4AF152E8B2FA9CB6", + /* HMAC-SHA-512 */ + "87AA7CDEA5EF619D4FF0B4241A1D6CB02379F4E2CE4EC2787AD0B30545E1" + "7CDEDAA833B7D6B8A702038B274EAEA3F4E4BE9D914EEB61F1702E696C20" + "3A126854" + }, { SHA1HashSize, SHA224HashSize, SHA256HashSize, + SHA384HashSize, SHA512HashSize } + }, + { /* 2 */ { + "\x4a\x65\x66\x65" /* "Jefe" */ + }, { 4 }, { + "\x77\x68\x61\x74\x20\x64\x6f\x20\x79\x61\x20\x77\x61\x6e\x74" + "\x20\x66\x6f\x72\x20\x6e\x6f\x74\x68\x69\x6e\x67\x3f" + /* "what do ya want for nothing?" */ + }, { 28 }, { + /* HMAC-SHA-1 */ + "EFFCDF6AE5EB2FA2D27416D5F184DF9C259A7C79", + /* HMAC-SHA-224 */ + "A30E01098BC6DBBF45690F3A7E9E6D0F8BBEA2A39E6148008FD05E44", + /* HMAC-SHA-256 */ + "5BDCC146BF60754E6A042426089575C75A003F089D2739839DEC58B964EC" + "3843", + /* HMAC-SHA-384 */ + "AF45D2E376484031617F78D2B58A6B1B9C7EF464F5A01B47E42EC3736322" + "445E8E2240CA5E69E2C78B3239ECFAB21649", + /* HMAC-SHA-512 */ + "164B7A7BFCF819E2E395FBE73B56E0A387BD64222E831FD610270CD7EA25" + "05549758BF75C05A994A6D034F65F8F0E6FDCAEAB1A34D4A6B4B636E070A" + "38BCE737" + }, { SHA1HashSize, SHA224HashSize, SHA256HashSize, + SHA384HashSize, SHA512HashSize } + }, + { /* 3 */ + { + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa" + }, { 20 }, { + "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" + "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" + "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" + "\xdd\xdd\xdd\xdd\xdd" + }, { 50 }, { + /* HMAC-SHA-1 */ + "125D7342B9AC11CD91A39AF48AA17B4F63F175D3", + /* HMAC-SHA-224 */ + "7FB3CB3588C6C1F6FFA9694D7D6AD2649365B0C1F65D69D1EC8333EA", + /* HMAC-SHA-256 */ + "773EA91E36800E46854DB8EBD09181A72959098B3EF8C122D9635514CED5" + "65FE", + /* HMAC-SHA-384 */ + "88062608D3E6AD8A0AA2ACE014C8A86F0AA635D947AC9FEBE83EF4E55966" + "144B2A5AB39DC13814B94E3AB6E101A34F27", + /* HMAC-SHA-512 */ + "FA73B0089D56A284EFB0F0756C890BE9B1B5DBDD8EE81A3655F83E33B227" + "9D39BF3E848279A722C806B485A47E67C807B946A337BEE8942674278859" + "E13292FB" + }, { SHA1HashSize, SHA224HashSize, SHA256HashSize, + SHA384HashSize, SHA512HashSize } + }, + { /* 4 */ { + "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" + "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19" + }, { 25 }, { + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" + "\xcd\xcd\xcd\xcd\xcd" + }, { 50 }, { + /* HMAC-SHA-1 */ + "4C9007F4026250C6BC8414F9BF50C86C2D7235DA", + /* HMAC-SHA-224 */ + "6C11506874013CAC6A2ABC1BB382627CEC6A90D86EFC012DE7AFEC5A", + /* HMAC-SHA-256 */ + "82558A389A443C0EA4CC819899F2083A85F0FAA3E578F8077A2E3FF46729" + "665B", + /* HMAC-SHA-384 */ + "3E8A69B7783C25851933AB6290AF6CA77A9981480850009CC5577C6E1F57" + "3B4E6801DD23C4A7D679CCF8A386C674CFFB", + /* HMAC-SHA-512 */ + "B0BA465637458C6990E5A8C5F61D4AF7E576D97FF94B872DE76F8050361E" + "E3DBA91CA5C11AA25EB4D679275CC5788063A5F19741120C4F2DE2ADEBEB" + "10A298DD" + }, { SHA1HashSize, SHA224HashSize, SHA256HashSize, + SHA384HashSize, SHA512HashSize } + }, + { /* 5 */ { + "\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c" + "\x0c\x0c\x0c\x0c\x0c" + }, { 20 }, { + "Test With Truncation" + }, { 20 }, { + /* HMAC-SHA-1 */ + "4C1A03424B55E07FE7F27BE1", + /* HMAC-SHA-224 */ + "0E2AEA68A90C8D37C988BCDB9FCA6FA8", + /* HMAC-SHA-256 */ + "A3B6167473100EE06E0C796C2955552B", + /* HMAC-SHA-384 */ + "3ABF34C3503B2A23A46EFC619BAEF897", + /* HMAC-SHA-512 */ + "415FAD6271580A531D4179BC891D87A6" + }, { 12, 16, 16, 16, 16 } + }, + { /* 6 */ { + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + }, { 80, 131 }, { + "Test Using Larger Than Block-Size Key - Hash Key First" + }, { 54 }, { + /* HMAC-SHA-1 */ + "AA4AE5E15272D00E95705637CE8A3B55ED402112", + /* HMAC-SHA-224 */ + "95E9A0DB962095ADAEBE9B2D6F0DBCE2D499F112F2D2B7273FA6870E", + /* HMAC-SHA-256 */ + "60E431591EE0B67F0D8A26AACBF5B77F8E0BC6213728C5140546040F0EE3" + "7F54", + /* HMAC-SHA-384 */ + "4ECE084485813E9088D2C63A041BC5B44F9EF1012A2B588F3CD11F05033A" + "C4C60C2EF6AB4030FE8296248DF163F44952", + /* HMAC-SHA-512 */ + "80B24263C7C1A3EBB71493C1DD7BE8B49B46D1F41B4AEEC1121B013783F8" + "F3526B56D037E05F2598BD0FD2215D6A1E5295E64F73F63F0AEC8B915A98" + "5D786598" + }, { SHA1HashSize, SHA224HashSize, SHA256HashSize, + SHA384HashSize, SHA512HashSize } + }, + { /* 7 */ { + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + }, { 80, 131 }, { + "Test Using Larger Than Block-Size Key and " + "Larger Than One Block-Size Data", + "\x54\x68\x69\x73\x20\x69\x73\x20\x61\x20\x74\x65\x73\x74\x20" + "\x75\x73\x69\x6e\x67\x20\x61\x20\x6c\x61\x72\x67\x65\x72\x20" + "\x74\x68\x61\x6e\x20\x62\x6c\x6f\x63\x6b\x2d\x73\x69\x7a\x65" + "\x20\x6b\x65\x79\x20\x61\x6e\x64\x20\x61\x20\x6c\x61\x72\x67" + "\x65\x72\x20\x74\x68\x61\x6e\x20\x62\x6c\x6f\x63\x6b\x2d\x73" + "\x69\x7a\x65\x20\x64\x61\x74\x61\x2e\x20\x54\x68\x65\x20\x6b" + "\x65\x79\x20\x6e\x65\x65\x64\x73\x20\x74\x6f\x20\x62\x65\x20" + "\x68\x61\x73\x68\x65\x64\x20\x62\x65\x66\x6f\x72\x65\x20\x62" + "\x65\x69\x6e\x67\x20\x75\x73\x65\x64\x20\x62\x79\x20\x74\x68" + "\x65\x20\x48\x4d\x41\x43\x20\x61\x6c\x67\x6f\x72\x69\x74\x68" + "\x6d\x2e" + /* "This is a test using a larger than block-size key and a " + "larger than block-size data. The key needs to be hashed " + "before being used by the HMAC algorithm." */ + }, { 73, 152 }, { + /* HMAC-SHA-1 */ + "E8E99D0F45237D786D6BBAA7965C7808BBFF1A91", + /* HMAC-SHA-224 */ + "3A854166AC5D9F023F54D517D0B39DBD946770DB9C2B95C9F6F565D1", + /* HMAC-SHA-256 */ + "9B09FFA71B942FCB27635FBCD5B0E944BFDC63644F0713938A7F51535C3A" + "35E2", + /* HMAC-SHA-384 */ + "6617178E941F020D351E2F254E8FD32C602420FEB0B8FB9ADCCEBB82461E" + "99C5A678CC31E799176D3860E6110C46523E", + /* HMAC-SHA-512 */ + "E37B6A775DC87DBAA4DFA9F96E5E3FFDDEBD71F8867289865DF5A32D20CD" + "C944B6022CAC3C4982B10D5EEB55C3E4DE15134676FB6DE0446065C97440" + "FA8C6A58" + }, { SHA1HashSize, SHA224HashSize, SHA256HashSize, + SHA384HashSize, SHA512HashSize } + } +}; + +/* Test arrays for HKDF. */ +struct hkdfhash { + SHAversion whichSha; + int ikmlength; + const char *ikmarray; + int saltlength; + const char *saltarray; + int infolength; + const char *infoarray; + int prklength; + const char *prkarray; + int okmlength; + const char *okmarray; +} hkdfhashes[HKDFTESTCOUNT] = { + { /* RFC 5869 A.1. Test Case 1 */ + SHA256, + 22, "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" + "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b", + 13, "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c", + 10, "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9", + 32, "077709362C2E32DF0DDC3F0DC47BBA6390B6C73BB50F9C3122EC844A" + "D7C2B3E5", + 42, "3CB25F25FAACD57A90434F64D0362F2A2D2D0A90CF1A5A4C5DB02D56" + "ECC4C5BF34007208D5B887185865" + }, + { /* RFC 5869 A.2. Test Case 2 */ + SHA256, + 80, "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d" + "\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b" + "\x1c\x1d\x1e\x1f\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29" + "\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36\x37" + "\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40\x41\x42\x43\x44\x45" + "\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f", + 80, "\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d" + "\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b" + "\x7c\x7d\x7e\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89" + "\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97" + "\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5" + "\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf", + 80, "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd" + "\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb" + "\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9" + "\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7" + "\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5" + "\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff", + 32, "06A6B88C5853361A06104C9CEB35B45C" + "EF760014904671014A193F40C15FC244", + 82, "B11E398DC80327A1C8E7F78C596A4934" + "4F012EDA2D4EFAD8A050CC4C19AFA97C" + "59045A99CAC7827271CB41C65E590E09" + "DA3275600C2F09B8367793A9ACA3DB71" + "CC30C58179EC3E87C14C01D5C1F3434F" + "1D87" + }, + { /* RFC 5869 A.3. Test Case 3 */ + SHA256, + 22, "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" + "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b", + 0, "", + 0, "", + 32, "19EF24A32C717B167F33A91D6F648BDF" + "96596776AFDB6377AC434C1C293CCB04", + 42, "8DA4E775A563C18F715F802A063C5A31" + "B8A11F5C5EE1879EC3454E5F3C738D2D" + "9D201395FAA4B61A96C8" + }, + { /* RFC 5869 A.4. Test Case 4 */ + SHA1, + 11, "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b", + 13, "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c", + 10, "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9", + 20, "9B6C18C432A7BF8F0E71C8EB88F4B30BAA2BA243", + 42, "085A01EA1B10F36933068B56EFA5AD81" + "A4F14B822F5B091568A9CDD4F155FDA2" + "C22E422478D305F3F896" + }, + { /* RFC 5869 A.5. Test Case 5 */ + SHA1, + 80, "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d" + "\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b" + "\x1c\x1d\x1e\x1f\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29" + "\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36\x37" + "\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40\x41\x42\x43\x44\x45" + "\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f", + 80, "\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6A\x6B\x6C\x6D" + "\x6E\x6F\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7A\x7B" + "\x7C\x7D\x7E\x7F\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89" + "\x8A\x8B\x8C\x8D\x8E\x8F\x90\x91\x92\x93\x94\x95\x96\x97" + "\x98\x99\x9A\x9B\x9C\x9D\x9E\x9F\xA0\xA1\xA2\xA3\xA4\xA5" + "\xA6\xA7\xA8\xA9\xAA\xAB\xAC\xAD\xAE\xAF", + 80, "\xB0\xB1\xB2\xB3\xB4\xB5\xB6\xB7\xB8\xB9\xBA\xBB\xBC\xBD" + "\xBE\xBF\xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xCB" + "\xCC\xCD\xCE\xCF\xD0\xD1\xD2\xD3\xD4\xD5\xD6\xD7\xD8\xD9" + "\xDA\xDB\xDC\xDD\xDE\xDF\xE0\xE1\xE2\xE3\xE4\xE5\xE6\xE7" + "\xE8\xE9\xEA\xEB\xEC\xED\xEE\xEF\xF0\xF1\xF2\xF3\xF4\xF5" + "\xF6\xF7\xF8\xF9\xFA\xFB\xFC\xFD\xFE\xFF", + 20, "8ADAE09A2A307059478D309B26C4115A224CFAF6", + 82, "0BD770A74D1160F7C9F12CD5912A06EB" + "FF6ADCAE899D92191FE4305673BA2FFE" + "8FA3F1A4E5AD79F3F334B3B202B2173C" + "486EA37CE3D397ED034C7F9DFEB15C5E" + "927336D0441F4C4300E2CFF0D0900B52" + "D3B4" + }, + { /* RFC 5869 A.6. Test Case 6 */ + SHA1, + 22, "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" + "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b", + 0, "", + 0, "", + 20, "DA8C8A73C7FA77288EC6F5E7C297786AA0D32D01", + 42, "0AC1AF7002B3D761D1E55298DA9D0506" + "B9AE52057220A306E07B6B87E8DF21D0" + "EA00033DE03984D34918" + }, + { /* RFC 5869 A.7. Test Case 7. */ + SHA1, + 22, "\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c" + "\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c", + 0, 0, + 0, "", + 20, "2ADCCADA18779E7C2077AD2EB19D3F3E731385DD", + 42, "2C91117204D745F3500D636A62F64F0A" + "B3BAE548AA53D423B0D1F27EBBA6F5E5" + "673A081D70CCE7ACFC48" + } +}; + +/* + * Check the hash value against the expected string, expressed in hex + */ +static const char hexdigits[ ] = "0123456789ABCDEF"; +int checkmatch(const unsigned char *hashvalue, + const char *hexstr, int hashsize) +{ + int i; + for (i = 0; i < hashsize; ++i) { + if (*hexstr++ != hexdigits[(hashvalue[i] >> 4) & 0xF]) + return 0; + if (*hexstr++ != hexdigits[hashvalue[i] & 0xF]) return 0; + } + return 1; +} + +/* + * Print the string, converting non-printable characters to "." + */ +void printstr(const char *str, int len) +{ + for ( ; len-- > 0; str++) + putchar(isprint((unsigned char)*str) ? *str : '.'); +} + +/* + * Print the string, converting all characters to hex "## ". + */ +void printxstr(const char *str, int len) +{ + char *sep = ""; + for ( ; len-- > 0; str++) { + printf("%s%c%c", sep, hexdigits[(*str >> 4) & 0xF], + hexdigits[*str & 0xF]); + sep = " "; + } +} + +/* + * Print a usage message. + */ +void usage(const char *argv0) +{ + fprintf(stderr, + "Usage:\n" + "Common options: [-h hash] [-w|-x|-6] [-H]\n" + "Hash a string:\n" + "\t%s [-S expectedresult] -s hashstr [-k key] " + "[-i info -L okm-len]\n" + "Hash a file:\n" + "\t%s [-S expectedresult] -f file [-k key] " + "[-i info -L okm-len]\n" + "Hash a file, ignoring whitespace:\n" + "\t%s [-S expectedresult] -F file [-k key] " + "[-i info -L okm-len]\n" + "Additional bits to add in: [-B bitcount -b bits]\n" + "(If -k,-i&-L are used, run HKDF-SHA###.\n" + " If -k is used, but not -i&-L, run HMAC-SHA###.\n" + " Otherwise, run SHA###.)\n" + "Standard tests:\n" + "\t%s [-m | -d] [-l loopcount] [-t test#] [-e]\n" + "\t\t[-r randomseed] [-R randomloop-count] " + "[-p] [-P|-X]\n" + "-h\thash to test: " + "0|SHA1, 1|SHA224, 2|SHA256, 3|SHA384, 4|SHA512\n" + "-m\tperform hmac standard tests\n" + "-k\tkey for hmac test\n" + "-d\tperform hkdf standard tests\n" + "-t\ttest case to run, 1-10\n" + "-l\thow many times to run the test\n" + "-e\ttest error returns\n" + "-p\tdo not print results\n" + "-P\tdo not print PASSED/FAILED\n" + "-X\tprint FAILED, but not PASSED\n" + "-r\tseed for random test\n" + "-R\thow many times to run random test\n" + "-s\tstring to hash\n" + "-S\texpected result of hashed string, in hex\n" + "-w\toutput hash in raw format\n" + "-x\toutput hash in hex format\n" + "-6\toutput hash in base64 format\n" + "-B\t# extra bits to add in after string or file input\n" + "-b\textra bits to add (high order bits of #, 0# or 0x#)\n" + "-H\tinput hashstr or randomseed is in hex\n" + , argv0, argv0, argv0, argv0); + exit(1); +} + +/* + * Print the results and PASS/FAIL. + */ +void printResult(uint8_t *Message_Digest, int hashsize, + const char *hashname, const char *testtype, const char *testname, + const char *resultarray, int printResults, int printPassFail) +{ + int i, k; + if (printResults == PRINTTEXT) { + printf("\nhashsize=%d\n", hashsize); + putchar('\t'); + for (i = 0; i < hashsize; ++i) { + putchar(hexdigits[(Message_Digest[i] >> 4) & 0xF]); + putchar(hexdigits[Message_Digest[i] & 0xF]); + putchar(' '); + } + putchar('\n'); + } else if (printResults == PRINTRAW) { + fwrite(Message_Digest, 1, hashsize, stdout); + } else if (printResults == PRINTHEX) { + for (i = 0; i < hashsize; ++i) { + putchar(hexdigits[(Message_Digest[i] >> 4) & 0xF]); + putchar(hexdigits[Message_Digest[i] & 0xF]); + } + putchar('\n'); + } else if (printResults == PRINTBASE64) { + unsigned char b; + char *sm = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" + "0123456789+/"; + for (i = 0; i < hashsize; i += 3) { + putchar(sm[Message_Digest[i] >> 2]); + b = (Message_Digest[i] & 0x03) << 4; + if (i+1 < hashsize) b |= Message_Digest[i+1] >> 4; + putchar(sm[b]); + if (i+1 < hashsize) { + b = (Message_Digest[i+1] & 0x0f) << 2; + if (i+2 < hashsize) b |= Message_Digest[i+2] >> 6; + putchar(sm[b]); + } else putchar('='); + if (i+2 < hashsize) putchar(sm[Message_Digest[i+2] & 0x3f]); + else putchar('='); + } + putchar('\n'); + } + + if (printResults && resultarray) { + printf(" Should match:\n\t"); + for (i = 0, k = 0; i < hashsize; i++, k += 2) { + putchar(resultarray[k]); + putchar(resultarray[k+1]); + putchar(' '); + } + putchar('\n'); + } + + if (printPassFail && resultarray) { + int ret = checkmatch(Message_Digest, resultarray, hashsize); + if ((printPassFail == PRINTPASSFAIL) || !ret) + printf("%s %s %s: %s\n", hashname, testtype, testname, + ret ? "PASSED" : "FAILED"); + } +} + +/* + * Exercise a hash series of functions. The input is the testarray, + * repeated repeatcount times, followed by the extrabits. If the + * result is known, it is in resultarray in uppercase hex. + */ +int hash(int testno, int loopno, int hashno, + const char *testarray, int length, long repeatcount, + int numberExtrabits, int extrabits, const unsigned char *keyarray, + int keylen, const unsigned char *info, int infolen, int okmlen, + const char *resultarray, int hashsize, int printResults, + int printPassFail) +{ + USHAContext sha; + HMACContext hmac; + HKDFContext hkdf; + int err, i; + uint8_t Message_Digest_Buf[USHAMaxHashSize]; + uint8_t *Message_Digest = Message_Digest_Buf; + char buf[20]; + + if (printResults == PRINTTEXT) { + printf("\nTest %d: Iteration %d, Repeat %ld\n\t'", testno+1, + loopno, repeatcount); + printstr(testarray, length); + printf("'\n\t'"); + printxstr(testarray, length); + printf("'\n"); + printf(" Length=%d bytes (%d bits), ", length, length * 8); + printf("ExtraBits %d: %2.2x\n", numberExtrabits, extrabits); + } + + if (info) Message_Digest = malloc(okmlen); + memset(&sha, '\343', sizeof(sha)); /* force bad data into struct */ + memset(&hmac, '\343', sizeof(hmac)); + memset(&hkdf, '\343', sizeof(hkdf)); + + err = info ? hkdfReset(&hkdf, hashes[hashno].whichSha, + keyarray, keylen) : + keyarray ? hmacReset(&hmac, hashes[hashno].whichSha, + keyarray, keylen) : + USHAReset(&sha, hashes[hashno].whichSha); + if (err != shaSuccess) { + fprintf(stderr, "hash(): %sReset Error %d.\n", + info ? "hkdf" : keyarray ? "hmac" : "sha", err); + return err; + } + + for (i = 0; i < repeatcount; ++i) { + err = info ? hkdfInput(&hkdf, (const uint8_t *)testarray, length) : + keyarray ? hmacInput(&hmac, (const uint8_t *) testarray, + length) : + USHAInput(&sha, (const uint8_t *) testarray, + length); + if (err != shaSuccess) { + fprintf(stderr, "hash(): %sInput Error %d.\n", + info ? "hkdf" : keyarray ? "hmac" : "sha", err); + return err; + } + } + + if (numberExtrabits > 0) { + err = info ? hkdfFinalBits(&hkdf, extrabits, numberExtrabits) : + keyarray ? hmacFinalBits(&hmac, (uint8_t) extrabits, + numberExtrabits) : + USHAFinalBits(&sha, (uint8_t) extrabits, + numberExtrabits); + if (err != shaSuccess) { + fprintf(stderr, "hash(): %sFinalBits Error %d.\n", + info ? "hkdf" : keyarray ? "hmac" : "sha", err); + return err; + } + } + + err = info ? hkdfResult(&hkdf, 0, info, infolen, + Message_Digest, okmlen) : + keyarray ? hmacResult(&hmac, Message_Digest) : + USHAResult(&sha, Message_Digest); + if (err != shaSuccess) { + fprintf(stderr, "hash(): %s Result Error %d, could not compute " + "message digest.\n", + info ? "hkdf" : keyarray ? "hmac" : "sha", err); + return err; + } + + sprintf(buf, "%d", testno+1); + printResult(Message_Digest, info ? okmlen : hashsize, + hashes[hashno].name, info ? "hkdf standard test" : + keyarray ? "hmac standard test" : "sha standard test", buf, + resultarray, printResults, printPassFail); + + return err; +} + +/* + * Exercise an HKDF series. The input is the testarray, + * repeated repeatcount times, followed by the extrabits. If the + * result is known, it is in resultarray in uppercase hex. + */ +int hashHkdf(int testno, int loopno, int hashno, + int printResults, int printPassFail) +{ + int err; + unsigned char prk[USHAMaxHashSize+1]; + uint8_t okm[255 * USHAMaxHashSize+1]; + char buf[24]; + + if (printResults == PRINTTEXT) { + printf("\nTest %d: Iteration %d\n\tSALT\t'", testno+1, loopno); + printxstr(hkdfhashes[testno].saltarray, + hkdfhashes[testno].saltlength); + printf("'\n\tIKM\t'"); + printxstr(hkdfhashes[testno].ikmarray, + hkdfhashes[testno].ikmlength); + printf("'\n\tINFO\t'"); + printxstr(hkdfhashes[testno].infoarray, + hkdfhashes[testno].infolength); + printf("'\n"); + printf(" L=%d bytes\n", hkdfhashes[testno].okmlength); + } + + /* Run hkdf() against the test vectors */ + err = hkdf(hkdfhashes[testno].whichSha, + (const uint8_t *) hkdfhashes[testno].saltarray, + hkdfhashes[testno].saltlength, + (const uint8_t *) hkdfhashes[testno].ikmarray, + hkdfhashes[testno].ikmlength, + (const uint8_t *) hkdfhashes[testno].infoarray, + hkdfhashes[testno].infolength, okm, + hkdfhashes[testno].okmlength); + if (err != shaSuccess) { + fprintf(stderr, "hashHkdf(): hkdf Error %d.\n", err); + return err; + } + sprintf(buf, "hkdf %d", testno+1); + printResult(okm, hkdfhashes[testno].okmlength, + USHAHashName(hkdfhashes[testno].whichSha), "hkdf standard test", + buf, hkdfhashes[testno].okmarray, printResults, printPassFail); + + /* Now run hkdfExtract() by itself against the test vectors */ + /* to verify the intermediate results. */ + err = hkdfExtract(hkdfhashes[testno].whichSha, + (const uint8_t *) hkdfhashes[testno].saltarray, + hkdfhashes[testno].saltlength, + (const uint8_t *) hkdfhashes[testno].ikmarray, + hkdfhashes[testno].ikmlength, prk); + if (err != shaSuccess) { + fprintf(stderr, "hashHkdf(): hkdfExtract Error %d.\n", err); + return err; + } + sprintf(buf, "hkdfExtract %d", testno+1); + printResult(prk, USHAHashSize(hkdfhashes[testno].whichSha), + USHAHashName(hkdfhashes[testno].whichSha), "hkdf standard test", + buf, hkdfhashes[testno].prkarray, printResults, printPassFail); + + /* Now run hkdfExpand() by itself against the test vectors */ + /* using the intermediate results from hkdfExtract. */ + err = hkdfExpand(hkdfhashes[testno].whichSha, prk, + USHAHashSize(hkdfhashes[testno].whichSha), + (const uint8_t *)hkdfhashes[testno].infoarray, + hkdfhashes[testno].infolength, okm, hkdfhashes[testno].okmlength); + if (err != shaSuccess) { + fprintf(stderr, "hashHkdf(): hkdfExpand Error %d.\n", err); + return err; + } + sprintf(buf, "hkdfExpand %d", testno+1); + printResult(okm, hkdfhashes[testno].okmlength, + USHAHashName(hkdfhashes[testno].whichSha), "hkdf standard test", + buf, hkdfhashes[testno].okmarray, printResults, printPassFail); + + return err; +} + +/* + * Exercise a hash series of functions. The input is a filename. + * If the result is known, it is in resultarray in uppercase hex. + */ +int hashfile(int hashno, const char *hashfilename, int bits, + int bitcount, int skipSpaces, const unsigned char *keyarray, + int keylen, const unsigned char *info, int infolen, int okmlen, + const char *resultarray, int hashsize, + int printResults, int printPassFail) +{ + USHAContext sha; + HMACContext hmac; + HKDFContext hkdf; + int err, nread, c; + unsigned char buf[4096]; + uint8_t Message_Digest_Buf[USHAMaxHashSize]; + uint8_t *Message_Digest = Message_Digest_Buf; + unsigned char cc; + FILE *hashfp = (strcmp(hashfilename, "-") == 0) ? stdin : + fopen(hashfilename, "r"); + + if (!hashfp) { + fprintf(stderr, "cannot open file '%s'\n", hashfilename); + return shaStateError; + } + + if (info) Message_Digest = malloc(okmlen); + memset(&sha, '\343', sizeof(sha)); /* force bad data into struct */ + memset(&hmac, '\343', sizeof(hmac)); + memset(&hkdf, '\343', sizeof(hkdf)); + err = info ? hkdfReset(&hkdf, hashes[hashno].whichSha, + keyarray, keylen) : + keyarray ? hmacReset(&hmac, hashes[hashno].whichSha, + keyarray, keylen) : + USHAReset(&sha, hashes[hashno].whichSha); + if (err != shaSuccess) { + fprintf(stderr, "hashfile(): %sReset Error %d.\n", + info ? "hkdf" : keyarray ? "hmac" : "sha", err); + return err; + } + + if (skipSpaces) + while ((c = getc(hashfp)) != EOF) { + if (!isspace(c)) { + cc = (unsigned char)c; + err = info ? hkdfInput(&hkdf, &cc, 1) : + keyarray ? hmacInput(&hmac, &cc, 1) : + USHAInput(&sha, &cc, 1); + if (err != shaSuccess) { + fprintf(stderr, "hashfile(): %sInput Error %d.\n", + info ? "hkdf" : keyarray ? "hmac" : "sha", err); + if (hashfp != stdin) fclose(hashfp); + return err; + } + } + } + else + while ((nread = fread(buf, 1, sizeof(buf), hashfp)) > 0) { + err = info ? hkdfInput(&hkdf, buf, nread) : + keyarray ? hmacInput(&hmac, buf, nread) : + USHAInput(&sha, buf, nread); + if (err != shaSuccess) { + fprintf(stderr, "hashfile(): %s Error %d.\n", + info ? "hkdf" : keyarray ? "hmacInput" : + "shaInput", err); + if (hashfp != stdin) fclose(hashfp); + return err; + } + } + + if (bitcount > 0) + err = info ? hkdfFinalBits(&hkdf, bits, bitcount) : + keyarray ? hmacFinalBits(&hmac, bits, bitcount) : + USHAFinalBits(&sha, bits, bitcount); + if (err != shaSuccess) { + fprintf(stderr, "hashfile(): %s Error %d.\n", + info ? "hkdf" : keyarray ? "hmacFinalBits" : + "shaFinalBits", err); + if (hashfp != stdin) fclose(hashfp); + return err; + } + + err = info ? hkdfResult(&hkdf, 0, info, infolen, + Message_Digest, okmlen) : + keyarray ? hmacResult(&hmac, Message_Digest) : + USHAResult(&sha, Message_Digest); + if (err != shaSuccess) { + fprintf(stderr, "hashfile(): %s Error %d.\n", + info ? "hkdf" : keyarray ? "hmacResult" : + "shaResult", err); + if (hashfp != stdin) fclose(hashfp); + return err; + } + + printResult(Message_Digest, info ? okmlen : hashsize, + hashes[hashno].name, "file", hashfilename, resultarray, + printResults, printPassFail); + + if (hashfp != stdin) fclose(hashfp); + if (info) free(Message_Digest); + return err; +} + +/* + * Exercise a hash series of functions through multiple permutations. + * The input is an initial seed. That seed is replicated 3 times. + * For 1000 rounds, the previous three results are used as the input. + * This result is then checked, and used to seed the next cycle. + * If the result is known, it is in resultarrays in uppercase hex. + */ +void randomtest(int hashno, const char *seed, int hashsize, + const char **resultarrays, int randomcount, + int printResults, int printPassFail) +{ + int i, j; char buf[20]; + unsigned char SEED[USHAMaxHashSize], MD[1003][USHAMaxHashSize]; + + /* INPUT: Seed - A random seed n bits long */ + memcpy(SEED, seed, hashsize); + if (printResults == PRINTTEXT) { + printf("%s random test seed= '", hashes[hashno].name); + printxstr(seed, hashsize); + printf("'\n"); + } + + for (j = 0; j < randomcount; j++) { + /* MD0 = MD1 = MD2 = Seed; */ + memcpy(MD[0], SEED, hashsize); + memcpy(MD[1], SEED, hashsize); + memcpy(MD[2], SEED, hashsize); + for (i=3; i<1003; i++) { + /* Mi = MDi-3 || MDi-2 || MDi-1; */ + USHAContext Mi; + memset(&Mi, '\343', sizeof(Mi)); /* force bad data into struct */ + USHAReset(&Mi, hashes[hashno].whichSha); + USHAInput(&Mi, MD[i-3], hashsize); + USHAInput(&Mi, MD[i-2], hashsize); + USHAInput(&Mi, MD[i-1], hashsize); + /* MDi = SHA(Mi); */ + USHAResult(&Mi, MD[i]); + } + + /* MDj = Seed = MDi; */ + memcpy(SEED, MD[i-1], hashsize); + + /* OUTPUT: MDj */ + sprintf(buf, "%d", j); + printResult(SEED, hashsize, hashes[hashno].name, "random test", + buf, resultarrays ? resultarrays[j] : 0, printResults, + (j < RANDOMCOUNT) ? printPassFail : 0); + } +} + +/* + * Look up a hash name. + */ +int findhash(const char *argv0, const char *opt) +{ + int i; + const char *names[HASHCOUNT][2] = { + { "0", "sha1" }, { "1", "sha224" }, { "2", "sha256" }, + { "3", "sha384" }, { "4", "sha512" } + }; + for (i = 0; i < HASHCOUNT; i++) + if ((strcmp(opt, names[i][0]) == 0) || + (scasecmp(opt, names[i][1]) == 0)) + return i; + + fprintf(stderr, "%s: Unknown hash name: '%s'\n", argv0, opt); + usage(argv0); + return 0; +} + +/* + * Run some tests that should invoke errors. + */ +void testErrors(int hashnolow, int hashnohigh, int printResults, + int printPassFail) +{ + USHAContext usha; + uint8_t Message_Digest[USHAMaxHashSize]; + int hashno, err; + + for (hashno = hashnolow; hashno <= hashnohigh; hashno++) { + memset(&usha, '\343', sizeof(usha)); /* force bad data */ + USHAReset(&usha, hashno); + USHAResult(&usha, Message_Digest); + err = USHAInput(&usha, (const unsigned char *)"foo", 3); + if (printResults == PRINTTEXT) + printf ("\nError %d. Should be %d.\n", err, shaStateError); + if ((printPassFail == PRINTPASSFAIL) || + ((printPassFail == PRINTFAIL) && (err != shaStateError))) + printf("%s se: %s\n", hashes[hashno].name, + (err == shaStateError) ? "PASSED" : "FAILED"); + + err = USHAFinalBits(&usha, 0x80, 3); + if (printResults == PRINTTEXT) + printf ("\nError %d. Should be %d.\n", err, shaStateError); + if ((printPassFail == PRINTPASSFAIL) || + ((printPassFail == PRINTFAIL) && (err != shaStateError))) + printf("%s se: %s\n", hashes[hashno].name, + (err == shaStateError) ? "PASSED" : "FAILED"); + + err = USHAReset(0, hashes[hashno].whichSha); + if (printResults == PRINTTEXT) + printf("\nError %d. Should be %d.\n", err, shaNull); + if ((printPassFail == PRINTPASSFAIL) || + ((printPassFail == PRINTFAIL) && (err != shaNull))) + printf("%s usha null: %s\n", hashes[hashno].name, + (err == shaNull) ? "PASSED" : "FAILED"); + + switch (hashno) { + case SHA1: err = SHA1Reset(0); break; + case SHA224: err = SHA224Reset(0); break; + case SHA256: err = SHA256Reset(0); break; + case SHA384: err = SHA384Reset(0); break; + case SHA512: err = SHA512Reset(0); break; + } + if (printResults == PRINTTEXT) + printf("\nError %d. Should be %d.\n", err, shaNull); + if ((printPassFail == PRINTPASSFAIL) || + ((printPassFail == PRINTFAIL) && (err != shaNull))) + printf("%s sha null: %s\n", hashes[hashno].name, + (err == shaNull) ? "PASSED" : "FAILED"); + } +} + +/* replace a hex string in place with its value */ +int unhexStr(char *hexstr) +{ + char *o = hexstr; + int len = 0, nibble1 = 0, nibble2 = 0; + if (!hexstr) return 0; + for ( ; *hexstr; hexstr++) { + if (isalpha((int)(unsigned char)(*hexstr))) { + nibble1 = tolower((int)(unsigned char)(*hexstr)) - 'a' + 10; + } else if (isdigit((int)(unsigned char)(*hexstr))) { + nibble1 = *hexstr - '0'; + } else { + printf("\nError: bad hex character '%c'\n", *hexstr); + } + if (!*++hexstr) break; + if (isalpha((int)(unsigned char)(*hexstr))) { + nibble2 = tolower((int)(unsigned char)(*hexstr)) - 'a' + 10; + } else if (isdigit((int)(unsigned char)(*hexstr))) { + nibble2 = *hexstr - '0'; + } else { + printf("\nError: bad hex character '%c'\n", *hexstr); + } + *o++ = (char)((nibble1 << 4) | nibble2); + len++; + } + return len; +} + +int main(int argc, char **argv) +{ + int i, err; + int loopno, loopnohigh = 1; + int hashno, hashnolow = 0, hashnohigh = HASHCOUNT - 1; + int testno, testnolow = 0, testnohigh; + int ntestnohigh = 0; + int printResults = PRINTTEXT; + int printPassFail = 1; + int checkErrors = 0; + char *hashstr = 0; + int hashlen = 0; + const char *resultstr = 0; + char *randomseedstr = 0; + int runHmacTests = 0; + int runHkdfTests = 0; + char *hmacKey = 0; + int hmaclen = 0; + char *info = 0; + int infolen = 0, okmlen = 0; + int randomcount = RANDOMCOUNT; + const char *hashfilename = 0; + const char *hashFilename = 0; + int extrabits = 0, numberExtrabits = 0; + int strIsHex = 0; + + if ('A' != 0x41) { + fprintf(stderr, "%s: these tests require ASCII\n", argv[0]); + } + + while ((i = getopt(argc, argv, + "6b:B:def:F:h:i:Hk:l:L:mpPr:R:s:S:t:wxX")) != -1) + switch (i) { + case 'b': extrabits = strtol(optarg, 0, 0); break; + case 'B': numberExtrabits = atoi(optarg); break; + case 'd': runHkdfTests = 1; break; + case 'e': checkErrors = 1; break; + case 'f': hashfilename = optarg; break; + case 'F': hashFilename = optarg; break; + case 'h': hashnolow = hashnohigh = findhash(argv[0], optarg); + break; + case 'H': strIsHex = 1; break; + case 'i': info = optarg; infolen = strlen(optarg); break; + case 'k': hmacKey = optarg; hmaclen = strlen(optarg); break; + case 'l': loopnohigh = atoi(optarg); break; + case 'L': okmlen = strtol(optarg, 0, 0); break; + case 'm': runHmacTests = 1; break; + case 'P': printPassFail = 0; break; + case 'p': printResults = PRINTNONE; break; + case 'R': randomcount = atoi(optarg); break; + case 'r': randomseedstr = optarg; break; + case 's': hashstr = optarg; hashlen = strlen(hashstr); break; + case 'S': resultstr = optarg; break; + case 't': testnolow = ntestnohigh = atoi(optarg) - 1; break; + case 'w': printResults = PRINTRAW; break; + case 'x': printResults = PRINTHEX; break; + case 'X': printPassFail = 2; break; + case '6': printResults = PRINTBASE64; break; + default: usage(argv[0]); + } + + if (strIsHex) { + hashlen = unhexStr(hashstr); + unhexStr(randomseedstr); + hmaclen = unhexStr(hmacKey); + infolen = unhexStr(info); + } + testnohigh = (ntestnohigh != 0) ? ntestnohigh: + runHmacTests ? (HMACTESTCOUNT-1) : + runHkdfTests ? (HKDFTESTCOUNT-1) : + (TESTCOUNT-1); + if ((testnolow < 0) || + (testnohigh >= (runHmacTests ? HMACTESTCOUNT : TESTCOUNT)) || + (hashnolow < 0) || (hashnohigh >= HASHCOUNT) || + (hashstr && (testnolow == testnohigh)) || + (randomcount < 0) || + (resultstr && (!hashstr && !hashfilename && !hashFilename)) || + ((runHmacTests || hmacKey) && randomseedstr) || + (hashfilename && hashFilename) || + (info && ((infolen <= 0) || (okmlen <= 0))) || + (info && !hmacKey)) + usage(argv[0]); + + /* + * Perform SHA/HMAC tests + */ + for (hashno = hashnolow; hashno <= hashnohigh; ++hashno) { + if (printResults == PRINTTEXT) + printf("Hash %s\n", hashes[hashno].name); + err = shaSuccess; + + for (loopno = 1; (loopno <= loopnohigh) && (err == shaSuccess); + ++loopno) { + if (hashstr) + err = hash(0, loopno, hashno, hashstr, hashlen, 1, + numberExtrabits, extrabits, (const unsigned char *)hmacKey, + hmaclen, (const uint8_t *) info, infolen, okmlen, resultstr, + hashes[hashno].hashsize, printResults, printPassFail); + + else if (randomseedstr) + randomtest(hashno, randomseedstr, hashes[hashno].hashsize, 0, + randomcount, printResults, printPassFail); + + else if (hashfilename) + err = hashfile(hashno, hashfilename, extrabits, + numberExtrabits, 0, + (const unsigned char *)hmacKey, hmaclen, + (const uint8_t *) info, infolen, okmlen, + resultstr, hashes[hashno].hashsize, + printResults, printPassFail); + + else if (hashFilename) + err = hashfile(hashno, hashFilename, extrabits, + numberExtrabits, 1, + (const unsigned char *)hmacKey, hmaclen, + (const uint8_t *) info, infolen, okmlen, + resultstr, hashes[hashno].hashsize, + printResults, printPassFail); + + else /* standard tests */ { + for (testno = testnolow; + (testno <= testnohigh) && (err == shaSuccess); ++testno) { + if (runHmacTests) { + err = hash(testno, loopno, hashno, + hmachashes[testno].dataarray[hashno] ? + hmachashes[testno].dataarray[hashno] : + hmachashes[testno].dataarray[1] ? + hmachashes[testno].dataarray[1] : + hmachashes[testno].dataarray[0], + hmachashes[testno].datalength[hashno] ? + hmachashes[testno].datalength[hashno] : + hmachashes[testno].datalength[1] ? + hmachashes[testno].datalength[1] : + hmachashes[testno].datalength[0], + 1, 0, 0, + (const unsigned char *)( + hmachashes[testno].keyarray[hashno] ? + hmachashes[testno].keyarray[hashno] : + hmachashes[testno].keyarray[1] ? + hmachashes[testno].keyarray[1] : + hmachashes[testno].keyarray[0]), + hmachashes[testno].keylength[hashno] ? + hmachashes[testno].keylength[hashno] : + hmachashes[testno].keylength[1] ? + hmachashes[testno].keylength[1] : + hmachashes[testno].keylength[0], + 0, 0, 0, + hmachashes[testno].resultarray[hashno], + hmachashes[testno].resultlength[hashno], + printResults, printPassFail); + } else if (runHkdfTests) { + err = hashHkdf(testno, loopno, hashno, + printResults, printPassFail); + } else { /* sha tests */ + err = hash(testno, loopno, hashno, + hashes[hashno].tests[testno].testarray, + hashes[hashno].tests[testno].length, + hashes[hashno].tests[testno].repeatcount, + hashes[hashno].tests[testno].numberExtrabits, + hashes[hashno].tests[testno].extrabits, + 0, 0, 0, 0, 0, + hashes[hashno].tests[testno].resultarray, + hashes[hashno].hashsize, + printResults, printPassFail); + } + } + if (!runHmacTests && !runHkdfTests) { + randomtest(hashno, hashes[hashno].randomtest, + hashes[hashno].hashsize, hashes[hashno].randomresults, + RANDOMCOUNT, printResults, printPassFail); + } + } + } + } + + /* Test some error returns */ + if (checkErrors) { + testErrors(hashnolow, hashnohigh, printResults, printPassFail); + } + + return 0; +} + +/* + * Compare two strings, case independently. + * Equivalent to strcasecmp() found on some systems. + */ +int scasecmp(const char *s1, const char *s2) +{ + for (;;) { + char u1 = tolower((int)(unsigned char)(*s1++)); + char u2 = tolower((int)(unsigned char)(*s2++)); + if (u1 != u2) + return u1 - u2; + if (u1 == '\0') + return 0; + } +} + diff --git a/lib/libesp32_div/ESP32-HomeKit/src/usha.c b/lib/libesp32_div/ESP32-HomeKit/src/usha.c new file mode 100644 index 000000000..08d857d99 --- /dev/null +++ b/lib/libesp32_div/ESP32-HomeKit/src/usha.c @@ -0,0 +1,281 @@ +/**************************** usha.c ***************************/ +/***************** See RFC 6234 for details. *******************/ +/* Copyright (c) 2011 IETF Trust and the persons identified as */ +/* authors of the code. All rights reserved. */ +/* See sha.h for terms of use and redistribution. */ + +/* + * Description: + * This file implements a unified interface to the SHA algorithms. + */ + +#include "sha.h" + +/* + * USHAReset + * + * Description: + * This function will initialize the SHA Context in preparation + * for computing a new SHA message digest. + * + * Parameters: + * context: [in/out] + * The context to reset. + * whichSha: [in] + * Selects which SHA reset to call + * + * Returns: + * sha Error Code. + * + */ +int USHAReset(USHAContext *context, enum SHAversion whichSha) +{ + if (!context) return shaNull; + context->whichSha = whichSha; + switch (whichSha) { + case SHA1: return SHA1Reset((SHA1Context*)&context->ctx); + case SHA224: return SHA224Reset((SHA224Context*)&context->ctx); + case SHA256: return SHA256Reset((SHA256Context*)&context->ctx); + case SHA384: return SHA384Reset((SHA384Context*)&context->ctx); + case SHA512: return SHA512Reset((SHA512Context*)&context->ctx); + default: return shaBadParam; + } +} + +/* + * USHAInput + * + * Description: + * This function accepts an array of octets as the next portion + * of the message. + * + * Parameters: + * context: [in/out] + * The SHA context to update. + * message_array: [in] + * An array of octets representing the next portion of + * the message. + * length: [in] + * The length of the message in message_array. + * + * Returns: + * sha Error Code. + * + */ +int USHAInput(USHAContext *context, + const uint8_t *bytes, unsigned int bytecount) +{ + if (!context) return shaNull; + switch (context->whichSha) { + case SHA1: + return SHA1Input((SHA1Context*)&context->ctx, bytes, + bytecount); + case SHA224: + return SHA224Input((SHA224Context*)&context->ctx, bytes, + bytecount); + case SHA256: + return SHA256Input((SHA256Context*)&context->ctx, bytes, + bytecount); + case SHA384: + return SHA384Input((SHA384Context*)&context->ctx, bytes, + bytecount); + case SHA512: + return SHA512Input((SHA512Context*)&context->ctx, bytes, + bytecount); + default: return shaBadParam; + } +} + +/* + * USHAFinalBits + * + * Description: + * This function will add in any final bits of the message. + * + * Parameters: + * context: [in/out] + * The SHA context to update. + * message_bits: [in] + * The final bits of the message, in the upper portion of the + * byte. (Use 0b###00000 instead of 0b00000### to input the + * three bits ###.) + * length: [in] + * The number of bits in message_bits, between 1 and 7. + * + * Returns: + * sha Error Code. + */ +int USHAFinalBits(USHAContext *context, + uint8_t bits, unsigned int bit_count) +{ + if (!context) return shaNull; + switch (context->whichSha) { + case SHA1: + return SHA1FinalBits((SHA1Context*)&context->ctx, bits, + bit_count); + case SHA224: + return SHA224FinalBits((SHA224Context*)&context->ctx, bits, + bit_count); + case SHA256: + return SHA256FinalBits((SHA256Context*)&context->ctx, bits, + bit_count); + case SHA384: + return SHA384FinalBits((SHA384Context*)&context->ctx, bits, + bit_count); + case SHA512: + return SHA512FinalBits((SHA512Context*)&context->ctx, bits, + bit_count); + default: return shaBadParam; + } +} + +/* + * USHAResult + * + * Description: + * This function will return the message digest of the appropriate + * bit size, as returned by USHAHashSizeBits(whichSHA) for the + * 'whichSHA' value used in the preceeding call to USHAReset, + * into the Message_Digest array provided by the caller. + * + * Parameters: + * context: [in/out] + * The context to use to calculate the SHA-1 hash. + * Message_Digest: [out] + * Where the digest is returned. + * + * Returns: + * sha Error Code. + * + */ +int USHAResult(USHAContext *context, + uint8_t Message_Digest[USHAMaxHashSize]) +{ + if (!context) return shaNull; + switch (context->whichSha) { + case SHA1: + return SHA1Result((SHA1Context*)&context->ctx, Message_Digest); + case SHA224: + return SHA224Result((SHA224Context*)&context->ctx, + Message_Digest); + case SHA256: + return SHA256Result((SHA256Context*)&context->ctx, + Message_Digest); + case SHA384: + return SHA384Result((SHA384Context*)&context->ctx, + Message_Digest); + case SHA512: + return SHA512Result((SHA512Context*)&context->ctx, + Message_Digest); + default: return shaBadParam; + } +} + +/* + * USHABlockSize + * + * Description: + * This function will return the blocksize for the given SHA + * algorithm. + * + * Parameters: + * whichSha: + * which SHA algorithm to query + * + * Returns: + * block size + * + */ +int USHABlockSize(enum SHAversion whichSha) +{ + switch (whichSha) { + case SHA1: return SHA1_Message_Block_Size; + case SHA224: return SHA224_Message_Block_Size; + case SHA256: return SHA256_Message_Block_Size; + case SHA384: return SHA384_Message_Block_Size; + default: + case SHA512: return SHA512_Message_Block_Size; + } +} + +/* + * USHAHashSize + * + * Description: + * This function will return the hashsize for the given SHA + * algorithm. + * + * Parameters: + * whichSha: + * which SHA algorithm to query + * + * Returns: + * hash size + * + */ +int USHAHashSize(enum SHAversion whichSha) +{ + switch (whichSha) { + case SHA1: return SHA1HashSize; + case SHA224: return SHA224HashSize; + case SHA256: return SHA256HashSize; + case SHA384: return SHA384HashSize; + default: + case SHA512: return SHA512HashSize; + } +} + +/* + * USHAHashSizeBits + * + * Description: + * This function will return the hashsize for the given SHA + * algorithm, expressed in bits. + * + * Parameters: + * whichSha: + * which SHA algorithm to query + * + * Returns: + * hash size in bits + * + */ +int USHAHashSizeBits(enum SHAversion whichSha) +{ + switch (whichSha) { + case SHA1: return SHA1HashSizeBits; + case SHA224: return SHA224HashSizeBits; + case SHA256: return SHA256HashSizeBits; + case SHA384: return SHA384HashSizeBits; + default: + case SHA512: return SHA512HashSizeBits; + } +} + +/* + * USHAHashName + * + * Description: + * This function will return the name of the given SHA algorithm + * as a string. + * + * Parameters: + * whichSha: + * which SHA algorithm to query + * + * Returns: + * character string with the name in it + * + */ +const char *USHAHashName(enum SHAversion whichSha) +{ + switch (whichSha) { + case SHA1: return "SHA1"; + case SHA224: return "SHA224"; + case SHA256: return "SHA256"; + case SHA384: return "SHA384"; + default: + case SHA512: return "SHA512"; + } +} + diff --git a/lib/libesp32/NimBLE-Arduino/CHANGELOG.md b/lib/libesp32_div/NimBLE-Arduino/CHANGELOG.md similarity index 100% rename from lib/libesp32/NimBLE-Arduino/CHANGELOG.md rename to lib/libesp32_div/NimBLE-Arduino/CHANGELOG.md diff --git a/lib/libesp32/NimBLE-Arduino/LICENSE b/lib/libesp32_div/NimBLE-Arduino/LICENSE similarity index 100% rename from lib/libesp32/NimBLE-Arduino/LICENSE rename to lib/libesp32_div/NimBLE-Arduino/LICENSE diff --git a/lib/libesp32/NimBLE-Arduino/README.md b/lib/libesp32_div/NimBLE-Arduino/README.md similarity index 100% rename from lib/libesp32/NimBLE-Arduino/README.md rename to lib/libesp32_div/NimBLE-Arduino/README.md diff --git a/lib/libesp32/NimBLE-Arduino/docs/Command_line_config.md b/lib/libesp32_div/NimBLE-Arduino/docs/Command_line_config.md similarity index 100% rename from lib/libesp32/NimBLE-Arduino/docs/Command_line_config.md rename to lib/libesp32_div/NimBLE-Arduino/docs/Command_line_config.md diff --git a/lib/libesp32/NimBLE-Arduino/docs/Improvements_and_updates.md b/lib/libesp32_div/NimBLE-Arduino/docs/Improvements_and_updates.md similarity index 100% rename from lib/libesp32/NimBLE-Arduino/docs/Improvements_and_updates.md rename to lib/libesp32_div/NimBLE-Arduino/docs/Improvements_and_updates.md diff --git a/lib/libesp32/NimBLE-Arduino/docs/Migration_guide.md b/lib/libesp32_div/NimBLE-Arduino/docs/Migration_guide.md similarity index 100% rename from lib/libesp32/NimBLE-Arduino/docs/Migration_guide.md rename to lib/libesp32_div/NimBLE-Arduino/docs/Migration_guide.md diff --git a/lib/libesp32/NimBLE-Arduino/docs/New_user_guide.md b/lib/libesp32_div/NimBLE-Arduino/docs/New_user_guide.md similarity index 100% rename from lib/libesp32/NimBLE-Arduino/docs/New_user_guide.md rename to lib/libesp32_div/NimBLE-Arduino/docs/New_user_guide.md diff --git a/lib/libesp32/NimBLE-Arduino/docs/Usage_tips.md b/lib/libesp32_div/NimBLE-Arduino/docs/Usage_tips.md similarity index 100% rename from lib/libesp32/NimBLE-Arduino/docs/Usage_tips.md rename to lib/libesp32_div/NimBLE-Arduino/docs/Usage_tips.md diff --git a/lib/libesp32/NimBLE-Arduino/examples/BLE_Beacon_Scanner/BLE_Beacon_Scanner.ino b/lib/libesp32_div/NimBLE-Arduino/examples/BLE_Beacon_Scanner/BLE_Beacon_Scanner.ino similarity index 100% rename from lib/libesp32/NimBLE-Arduino/examples/BLE_Beacon_Scanner/BLE_Beacon_Scanner.ino rename to lib/libesp32_div/NimBLE-Arduino/examples/BLE_Beacon_Scanner/BLE_Beacon_Scanner.ino diff --git a/lib/libesp32/NimBLE-Arduino/examples/BLE_Beacon_Scanner/BLE_Beacon_Scanner.md b/lib/libesp32_div/NimBLE-Arduino/examples/BLE_Beacon_Scanner/BLE_Beacon_Scanner.md similarity index 100% rename from lib/libesp32/NimBLE-Arduino/examples/BLE_Beacon_Scanner/BLE_Beacon_Scanner.md rename to lib/libesp32_div/NimBLE-Arduino/examples/BLE_Beacon_Scanner/BLE_Beacon_Scanner.md diff --git a/lib/libesp32/NimBLE-Arduino/examples/BLE_EddystoneTLM_Beacon/BLE_EddystoneTLM_Beacon.ino b/lib/libesp32_div/NimBLE-Arduino/examples/BLE_EddystoneTLM_Beacon/BLE_EddystoneTLM_Beacon.ino similarity index 100% rename from lib/libesp32/NimBLE-Arduino/examples/BLE_EddystoneTLM_Beacon/BLE_EddystoneTLM_Beacon.ino rename to lib/libesp32_div/NimBLE-Arduino/examples/BLE_EddystoneTLM_Beacon/BLE_EddystoneTLM_Beacon.ino diff --git a/lib/libesp32/NimBLE-Arduino/examples/BLE_EddystoneTLM_Beacon/BLE_EddystoneTLM_Beacon.md b/lib/libesp32_div/NimBLE-Arduino/examples/BLE_EddystoneTLM_Beacon/BLE_EddystoneTLM_Beacon.md similarity index 100% rename from lib/libesp32/NimBLE-Arduino/examples/BLE_EddystoneTLM_Beacon/BLE_EddystoneTLM_Beacon.md rename to lib/libesp32_div/NimBLE-Arduino/examples/BLE_EddystoneTLM_Beacon/BLE_EddystoneTLM_Beacon.md diff --git a/lib/libesp32/NimBLE-Arduino/examples/BLE_EddystoneURL_Beacon/BLE_EddystoneURL_Beacon.ino b/lib/libesp32_div/NimBLE-Arduino/examples/BLE_EddystoneURL_Beacon/BLE_EddystoneURL_Beacon.ino similarity index 100% rename from lib/libesp32/NimBLE-Arduino/examples/BLE_EddystoneURL_Beacon/BLE_EddystoneURL_Beacon.ino rename to lib/libesp32_div/NimBLE-Arduino/examples/BLE_EddystoneURL_Beacon/BLE_EddystoneURL_Beacon.ino diff --git a/lib/libesp32/NimBLE-Arduino/examples/BLE_EddystoneURL_Beacon/BLE_EddystoneURL_Beacon.md b/lib/libesp32_div/NimBLE-Arduino/examples/BLE_EddystoneURL_Beacon/BLE_EddystoneURL_Beacon.md similarity index 100% rename from lib/libesp32/NimBLE-Arduino/examples/BLE_EddystoneURL_Beacon/BLE_EddystoneURL_Beacon.md rename to lib/libesp32_div/NimBLE-Arduino/examples/BLE_EddystoneURL_Beacon/BLE_EddystoneURL_Beacon.md diff --git a/lib/libesp32/NimBLE-Arduino/examples/NimBLE_Client/NimBLE_Client.ino b/lib/libesp32_div/NimBLE-Arduino/examples/NimBLE_Client/NimBLE_Client.ino similarity index 100% rename from lib/libesp32/NimBLE-Arduino/examples/NimBLE_Client/NimBLE_Client.ino rename to lib/libesp32_div/NimBLE-Arduino/examples/NimBLE_Client/NimBLE_Client.ino diff --git a/lib/libesp32/NimBLE-Arduino/examples/NimBLE_Scan_Continuous/NimBLE_Scan_Continuous.ino b/lib/libesp32_div/NimBLE-Arduino/examples/NimBLE_Scan_Continuous/NimBLE_Scan_Continuous.ino similarity index 100% rename from lib/libesp32/NimBLE-Arduino/examples/NimBLE_Scan_Continuous/NimBLE_Scan_Continuous.ino rename to lib/libesp32_div/NimBLE-Arduino/examples/NimBLE_Scan_Continuous/NimBLE_Scan_Continuous.ino diff --git a/lib/libesp32/NimBLE-Arduino/examples/NimBLE_Secure_Client/NimBLE_Secure_Client.ino b/lib/libesp32_div/NimBLE-Arduino/examples/NimBLE_Secure_Client/NimBLE_Secure_Client.ino similarity index 100% rename from lib/libesp32/NimBLE-Arduino/examples/NimBLE_Secure_Client/NimBLE_Secure_Client.ino rename to lib/libesp32_div/NimBLE-Arduino/examples/NimBLE_Secure_Client/NimBLE_Secure_Client.ino diff --git a/lib/libesp32/NimBLE-Arduino/examples/NimBLE_Secure_Server/NimBLE_Secure_Server.ino b/lib/libesp32_div/NimBLE-Arduino/examples/NimBLE_Secure_Server/NimBLE_Secure_Server.ino similarity index 100% rename from lib/libesp32/NimBLE-Arduino/examples/NimBLE_Secure_Server/NimBLE_Secure_Server.ino rename to lib/libesp32_div/NimBLE-Arduino/examples/NimBLE_Secure_Server/NimBLE_Secure_Server.ino diff --git a/lib/libesp32/NimBLE-Arduino/examples/NimBLE_Server/NimBLE_Server.ino b/lib/libesp32_div/NimBLE-Arduino/examples/NimBLE_Server/NimBLE_Server.ino similarity index 100% rename from lib/libesp32/NimBLE-Arduino/examples/NimBLE_Server/NimBLE_Server.ino rename to lib/libesp32_div/NimBLE-Arduino/examples/NimBLE_Server/NimBLE_Server.ino diff --git a/lib/libesp32/NimBLE-Arduino/examples/NimBLE_Service_Data_Advertiser/NimBLE_Service_Data_Advertiser.ino b/lib/libesp32_div/NimBLE-Arduino/examples/NimBLE_Service_Data_Advertiser/NimBLE_Service_Data_Advertiser.ino similarity index 100% rename from lib/libesp32/NimBLE-Arduino/examples/NimBLE_Service_Data_Advertiser/NimBLE_Service_Data_Advertiser.ino rename to lib/libesp32_div/NimBLE-Arduino/examples/NimBLE_Service_Data_Advertiser/NimBLE_Service_Data_Advertiser.ino diff --git a/lib/libesp32/NimBLE-Arduino/examples/Refactored_original_examples/BLE_client/BLE_client.ino b/lib/libesp32_div/NimBLE-Arduino/examples/Refactored_original_examples/BLE_client/BLE_client.ino similarity index 100% rename from lib/libesp32/NimBLE-Arduino/examples/Refactored_original_examples/BLE_client/BLE_client.ino rename to lib/libesp32_div/NimBLE-Arduino/examples/Refactored_original_examples/BLE_client/BLE_client.ino diff --git a/lib/libesp32/NimBLE-Arduino/examples/Refactored_original_examples/BLE_iBeacon/BLE_iBeacon.ino b/lib/libesp32_div/NimBLE-Arduino/examples/Refactored_original_examples/BLE_iBeacon/BLE_iBeacon.ino similarity index 100% rename from lib/libesp32/NimBLE-Arduino/examples/Refactored_original_examples/BLE_iBeacon/BLE_iBeacon.ino rename to lib/libesp32_div/NimBLE-Arduino/examples/Refactored_original_examples/BLE_iBeacon/BLE_iBeacon.ino diff --git a/lib/libesp32/NimBLE-Arduino/examples/Refactored_original_examples/BLE_notify/BLE_notify.ino b/lib/libesp32_div/NimBLE-Arduino/examples/Refactored_original_examples/BLE_notify/BLE_notify.ino similarity index 100% rename from lib/libesp32/NimBLE-Arduino/examples/Refactored_original_examples/BLE_notify/BLE_notify.ino rename to lib/libesp32_div/NimBLE-Arduino/examples/Refactored_original_examples/BLE_notify/BLE_notify.ino diff --git a/lib/libesp32/NimBLE-Arduino/examples/Refactored_original_examples/BLE_scan/BLE_scan.ino b/lib/libesp32_div/NimBLE-Arduino/examples/Refactored_original_examples/BLE_scan/BLE_scan.ino similarity index 100% rename from lib/libesp32/NimBLE-Arduino/examples/Refactored_original_examples/BLE_scan/BLE_scan.ino rename to lib/libesp32_div/NimBLE-Arduino/examples/Refactored_original_examples/BLE_scan/BLE_scan.ino diff --git a/lib/libesp32/NimBLE-Arduino/examples/Refactored_original_examples/BLE_server/BLE_server.ino b/lib/libesp32_div/NimBLE-Arduino/examples/Refactored_original_examples/BLE_server/BLE_server.ino similarity index 100% rename from lib/libesp32/NimBLE-Arduino/examples/Refactored_original_examples/BLE_server/BLE_server.ino rename to lib/libesp32_div/NimBLE-Arduino/examples/Refactored_original_examples/BLE_server/BLE_server.ino diff --git a/lib/libesp32/NimBLE-Arduino/examples/Refactored_original_examples/BLE_server_multiconnect/BLE_server_multiconnect.ino b/lib/libesp32_div/NimBLE-Arduino/examples/Refactored_original_examples/BLE_server_multiconnect/BLE_server_multiconnect.ino similarity index 100% rename from lib/libesp32/NimBLE-Arduino/examples/Refactored_original_examples/BLE_server_multiconnect/BLE_server_multiconnect.ino rename to lib/libesp32_div/NimBLE-Arduino/examples/Refactored_original_examples/BLE_server_multiconnect/BLE_server_multiconnect.ino diff --git a/lib/libesp32/NimBLE-Arduino/examples/Refactored_original_examples/BLE_uart/BLE_uart.ino b/lib/libesp32_div/NimBLE-Arduino/examples/Refactored_original_examples/BLE_uart/BLE_uart.ino similarity index 100% rename from lib/libesp32/NimBLE-Arduino/examples/Refactored_original_examples/BLE_uart/BLE_uart.ino rename to lib/libesp32_div/NimBLE-Arduino/examples/Refactored_original_examples/BLE_uart/BLE_uart.ino diff --git a/lib/libesp32/NimBLE-Arduino/examples/Refactored_original_examples/BLE_write/BLE_write.ino b/lib/libesp32_div/NimBLE-Arduino/examples/Refactored_original_examples/BLE_write/BLE_write.ino similarity index 100% rename from lib/libesp32/NimBLE-Arduino/examples/Refactored_original_examples/BLE_write/BLE_write.ino rename to lib/libesp32_div/NimBLE-Arduino/examples/Refactored_original_examples/BLE_write/BLE_write.ino diff --git a/lib/libesp32/NimBLE-Arduino/library.json b/lib/libesp32_div/NimBLE-Arduino/library.json similarity index 100% rename from lib/libesp32/NimBLE-Arduino/library.json rename to lib/libesp32_div/NimBLE-Arduino/library.json diff --git a/lib/libesp32/NimBLE-Arduino/library.properties b/lib/libesp32_div/NimBLE-Arduino/library.properties similarity index 100% rename from lib/libesp32/NimBLE-Arduino/library.properties rename to lib/libesp32_div/NimBLE-Arduino/library.properties diff --git a/lib/libesp32/NimBLE-Arduino/src/CODING_STANDARDS.md b/lib/libesp32_div/NimBLE-Arduino/src/CODING_STANDARDS.md similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/CODING_STANDARDS.md rename to lib/libesp32_div/NimBLE-Arduino/src/CODING_STANDARDS.md diff --git a/lib/libesp32/NimBLE-Arduino/src/FreeRTOS.cpp b/lib/libesp32_div/NimBLE-Arduino/src/FreeRTOS.cpp similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/FreeRTOS.cpp rename to lib/libesp32_div/NimBLE-Arduino/src/FreeRTOS.cpp diff --git a/lib/libesp32/NimBLE-Arduino/src/FreeRTOS.h b/lib/libesp32_div/NimBLE-Arduino/src/FreeRTOS.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/FreeRTOS.h rename to lib/libesp32_div/NimBLE-Arduino/src/FreeRTOS.h diff --git a/lib/libesp32/NimBLE-Arduino/src/HIDKeyboardTypes.h b/lib/libesp32_div/NimBLE-Arduino/src/HIDKeyboardTypes.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/HIDKeyboardTypes.h rename to lib/libesp32_div/NimBLE-Arduino/src/HIDKeyboardTypes.h diff --git a/lib/libesp32/NimBLE-Arduino/src/HIDTypes.h b/lib/libesp32_div/NimBLE-Arduino/src/HIDTypes.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/HIDTypes.h rename to lib/libesp32_div/NimBLE-Arduino/src/HIDTypes.h diff --git a/lib/libesp32/NimBLE-Arduino/src/NOTICE b/lib/libesp32_div/NimBLE-Arduino/src/NOTICE similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/NOTICE rename to lib/libesp32_div/NimBLE-Arduino/src/NOTICE diff --git a/lib/libesp32/NimBLE-Arduino/src/NimBLE2904.cpp b/lib/libesp32_div/NimBLE-Arduino/src/NimBLE2904.cpp similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/NimBLE2904.cpp rename to lib/libesp32_div/NimBLE-Arduino/src/NimBLE2904.cpp diff --git a/lib/libesp32/NimBLE-Arduino/src/NimBLE2904.h b/lib/libesp32_div/NimBLE-Arduino/src/NimBLE2904.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/NimBLE2904.h rename to lib/libesp32_div/NimBLE-Arduino/src/NimBLE2904.h diff --git a/lib/libesp32/NimBLE-Arduino/src/NimBLEAddress.cpp b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEAddress.cpp similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/NimBLEAddress.cpp rename to lib/libesp32_div/NimBLE-Arduino/src/NimBLEAddress.cpp diff --git a/lib/libesp32/NimBLE-Arduino/src/NimBLEAddress.h b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEAddress.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/NimBLEAddress.h rename to lib/libesp32_div/NimBLE-Arduino/src/NimBLEAddress.h diff --git a/lib/libesp32/NimBLE-Arduino/src/NimBLEAdvertisedDevice.cpp b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEAdvertisedDevice.cpp similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/NimBLEAdvertisedDevice.cpp rename to lib/libesp32_div/NimBLE-Arduino/src/NimBLEAdvertisedDevice.cpp diff --git a/lib/libesp32/NimBLE-Arduino/src/NimBLEAdvertisedDevice.h b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEAdvertisedDevice.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/NimBLEAdvertisedDevice.h rename to lib/libesp32_div/NimBLE-Arduino/src/NimBLEAdvertisedDevice.h diff --git a/lib/libesp32/NimBLE-Arduino/src/NimBLEAdvertising.cpp b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEAdvertising.cpp similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/NimBLEAdvertising.cpp rename to lib/libesp32_div/NimBLE-Arduino/src/NimBLEAdvertising.cpp diff --git a/lib/libesp32/NimBLE-Arduino/src/NimBLEAdvertising.h b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEAdvertising.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/NimBLEAdvertising.h rename to lib/libesp32_div/NimBLE-Arduino/src/NimBLEAdvertising.h diff --git a/lib/libesp32/NimBLE-Arduino/src/NimBLEBeacon.cpp b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEBeacon.cpp similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/NimBLEBeacon.cpp rename to lib/libesp32_div/NimBLE-Arduino/src/NimBLEBeacon.cpp diff --git a/lib/libesp32/NimBLE-Arduino/src/NimBLEBeacon.h b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEBeacon.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/NimBLEBeacon.h rename to lib/libesp32_div/NimBLE-Arduino/src/NimBLEBeacon.h diff --git a/lib/libesp32/NimBLE-Arduino/src/NimBLECharacteristic.cpp b/lib/libesp32_div/NimBLE-Arduino/src/NimBLECharacteristic.cpp similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/NimBLECharacteristic.cpp rename to lib/libesp32_div/NimBLE-Arduino/src/NimBLECharacteristic.cpp diff --git a/lib/libesp32/NimBLE-Arduino/src/NimBLECharacteristic.h b/lib/libesp32_div/NimBLE-Arduino/src/NimBLECharacteristic.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/NimBLECharacteristic.h rename to lib/libesp32_div/NimBLE-Arduino/src/NimBLECharacteristic.h diff --git a/lib/libesp32/NimBLE-Arduino/src/NimBLEClient.cpp b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEClient.cpp similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/NimBLEClient.cpp rename to lib/libesp32_div/NimBLE-Arduino/src/NimBLEClient.cpp diff --git a/lib/libesp32/NimBLE-Arduino/src/NimBLEClient.h b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEClient.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/NimBLEClient.h rename to lib/libesp32_div/NimBLE-Arduino/src/NimBLEClient.h diff --git a/lib/libesp32/NimBLE-Arduino/src/NimBLEDescriptor.cpp b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEDescriptor.cpp similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/NimBLEDescriptor.cpp rename to lib/libesp32_div/NimBLE-Arduino/src/NimBLEDescriptor.cpp diff --git a/lib/libesp32/NimBLE-Arduino/src/NimBLEDescriptor.h b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEDescriptor.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/NimBLEDescriptor.h rename to lib/libesp32_div/NimBLE-Arduino/src/NimBLEDescriptor.h diff --git a/lib/libesp32/NimBLE-Arduino/src/NimBLEDevice.cpp b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEDevice.cpp similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/NimBLEDevice.cpp rename to lib/libesp32_div/NimBLE-Arduino/src/NimBLEDevice.cpp diff --git a/lib/libesp32/NimBLE-Arduino/src/NimBLEDevice.h b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEDevice.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/NimBLEDevice.h rename to lib/libesp32_div/NimBLE-Arduino/src/NimBLEDevice.h diff --git a/lib/libesp32/NimBLE-Arduino/src/NimBLEEddystoneTLM.cpp b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEEddystoneTLM.cpp similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/NimBLEEddystoneTLM.cpp rename to lib/libesp32_div/NimBLE-Arduino/src/NimBLEEddystoneTLM.cpp diff --git a/lib/libesp32/NimBLE-Arduino/src/NimBLEEddystoneTLM.h b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEEddystoneTLM.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/NimBLEEddystoneTLM.h rename to lib/libesp32_div/NimBLE-Arduino/src/NimBLEEddystoneTLM.h diff --git a/lib/libesp32/NimBLE-Arduino/src/NimBLEEddystoneURL.cpp b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEEddystoneURL.cpp similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/NimBLEEddystoneURL.cpp rename to lib/libesp32_div/NimBLE-Arduino/src/NimBLEEddystoneURL.cpp diff --git a/lib/libesp32/NimBLE-Arduino/src/NimBLEEddystoneURL.h b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEEddystoneURL.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/NimBLEEddystoneURL.h rename to lib/libesp32_div/NimBLE-Arduino/src/NimBLEEddystoneURL.h diff --git a/lib/libesp32/NimBLE-Arduino/src/NimBLEHIDDevice.cpp b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEHIDDevice.cpp similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/NimBLEHIDDevice.cpp rename to lib/libesp32_div/NimBLE-Arduino/src/NimBLEHIDDevice.cpp diff --git a/lib/libesp32/NimBLE-Arduino/src/NimBLEHIDDevice.h b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEHIDDevice.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/NimBLEHIDDevice.h rename to lib/libesp32_div/NimBLE-Arduino/src/NimBLEHIDDevice.h diff --git a/lib/libesp32/NimBLE-Arduino/src/NimBLELog.h b/lib/libesp32_div/NimBLE-Arduino/src/NimBLELog.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/NimBLELog.h rename to lib/libesp32_div/NimBLE-Arduino/src/NimBLELog.h diff --git a/lib/libesp32/NimBLE-Arduino/src/NimBLERemoteCharacteristic.cpp b/lib/libesp32_div/NimBLE-Arduino/src/NimBLERemoteCharacteristic.cpp similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/NimBLERemoteCharacteristic.cpp rename to lib/libesp32_div/NimBLE-Arduino/src/NimBLERemoteCharacteristic.cpp diff --git a/lib/libesp32/NimBLE-Arduino/src/NimBLERemoteCharacteristic.h b/lib/libesp32_div/NimBLE-Arduino/src/NimBLERemoteCharacteristic.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/NimBLERemoteCharacteristic.h rename to lib/libesp32_div/NimBLE-Arduino/src/NimBLERemoteCharacteristic.h diff --git a/lib/libesp32/NimBLE-Arduino/src/NimBLERemoteDescriptor.cpp b/lib/libesp32_div/NimBLE-Arduino/src/NimBLERemoteDescriptor.cpp similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/NimBLERemoteDescriptor.cpp rename to lib/libesp32_div/NimBLE-Arduino/src/NimBLERemoteDescriptor.cpp diff --git a/lib/libesp32/NimBLE-Arduino/src/NimBLERemoteDescriptor.h b/lib/libesp32_div/NimBLE-Arduino/src/NimBLERemoteDescriptor.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/NimBLERemoteDescriptor.h rename to lib/libesp32_div/NimBLE-Arduino/src/NimBLERemoteDescriptor.h diff --git a/lib/libesp32/NimBLE-Arduino/src/NimBLERemoteService.cpp b/lib/libesp32_div/NimBLE-Arduino/src/NimBLERemoteService.cpp similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/NimBLERemoteService.cpp rename to lib/libesp32_div/NimBLE-Arduino/src/NimBLERemoteService.cpp diff --git a/lib/libesp32/NimBLE-Arduino/src/NimBLERemoteService.h b/lib/libesp32_div/NimBLE-Arduino/src/NimBLERemoteService.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/NimBLERemoteService.h rename to lib/libesp32_div/NimBLE-Arduino/src/NimBLERemoteService.h diff --git a/lib/libesp32/NimBLE-Arduino/src/NimBLEScan.cpp b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEScan.cpp similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/NimBLEScan.cpp rename to lib/libesp32_div/NimBLE-Arduino/src/NimBLEScan.cpp diff --git a/lib/libesp32/NimBLE-Arduino/src/NimBLEScan.h b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEScan.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/NimBLEScan.h rename to lib/libesp32_div/NimBLE-Arduino/src/NimBLEScan.h diff --git a/lib/libesp32/NimBLE-Arduino/src/NimBLESecurity.cpp b/lib/libesp32_div/NimBLE-Arduino/src/NimBLESecurity.cpp similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/NimBLESecurity.cpp rename to lib/libesp32_div/NimBLE-Arduino/src/NimBLESecurity.cpp diff --git a/lib/libesp32/NimBLE-Arduino/src/NimBLESecurity.h b/lib/libesp32_div/NimBLE-Arduino/src/NimBLESecurity.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/NimBLESecurity.h rename to lib/libesp32_div/NimBLE-Arduino/src/NimBLESecurity.h diff --git a/lib/libesp32/NimBLE-Arduino/src/NimBLEServer.cpp b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEServer.cpp similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/NimBLEServer.cpp rename to lib/libesp32_div/NimBLE-Arduino/src/NimBLEServer.cpp diff --git a/lib/libesp32/NimBLE-Arduino/src/NimBLEServer.h b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEServer.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/NimBLEServer.h rename to lib/libesp32_div/NimBLE-Arduino/src/NimBLEServer.h diff --git a/lib/libesp32/NimBLE-Arduino/src/NimBLEService.cpp b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEService.cpp similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/NimBLEService.cpp rename to lib/libesp32_div/NimBLE-Arduino/src/NimBLEService.cpp diff --git a/lib/libesp32/NimBLE-Arduino/src/NimBLEService.h b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEService.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/NimBLEService.h rename to lib/libesp32_div/NimBLE-Arduino/src/NimBLEService.h diff --git a/lib/libesp32/NimBLE-Arduino/src/NimBLEUUID.cpp b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEUUID.cpp similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/NimBLEUUID.cpp rename to lib/libesp32_div/NimBLE-Arduino/src/NimBLEUUID.cpp diff --git a/lib/libesp32/NimBLE-Arduino/src/NimBLEUUID.h b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEUUID.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/NimBLEUUID.h rename to lib/libesp32_div/NimBLE-Arduino/src/NimBLEUUID.h diff --git a/lib/libesp32/NimBLE-Arduino/src/NimBLEUtils.cpp b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEUtils.cpp similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/NimBLEUtils.cpp rename to lib/libesp32_div/NimBLE-Arduino/src/NimBLEUtils.cpp diff --git a/lib/libesp32/NimBLE-Arduino/src/NimBLEUtils.h b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEUtils.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/NimBLEUtils.h rename to lib/libesp32_div/NimBLE-Arduino/src/NimBLEUtils.h diff --git a/lib/libesp32/NimBLE-Arduino/src/README.md b/lib/libesp32_div/NimBLE-Arduino/src/README.md similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/README.md rename to lib/libesp32_div/NimBLE-Arduino/src/README.md diff --git a/lib/libesp32/NimBLE-Arduino/src/RELEASE_NOTES.md b/lib/libesp32_div/NimBLE-Arduino/src/RELEASE_NOTES.md similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/RELEASE_NOTES.md rename to lib/libesp32_div/NimBLE-Arduino/src/RELEASE_NOTES.md diff --git a/lib/libesp32/NimBLE-Arduino/src/console/console.h b/lib/libesp32_div/NimBLE-Arduino/src/console/console.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/console/console.h rename to lib/libesp32_div/NimBLE-Arduino/src/console/console.h diff --git a/lib/libesp32/NimBLE-Arduino/src/esp-hci/src/esp_nimble_hci.c b/lib/libesp32_div/NimBLE-Arduino/src/esp-hci/src/esp_nimble_hci.c similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/esp-hci/src/esp_nimble_hci.c rename to lib/libesp32_div/NimBLE-Arduino/src/esp-hci/src/esp_nimble_hci.c diff --git a/lib/libesp32/NimBLE-Arduino/src/esp_compiler.h b/lib/libesp32_div/NimBLE-Arduino/src/esp_compiler.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/esp_compiler.h rename to lib/libesp32_div/NimBLE-Arduino/src/esp_compiler.h diff --git a/lib/libesp32/NimBLE-Arduino/src/esp_nimble_cfg.h b/lib/libesp32_div/NimBLE-Arduino/src/esp_nimble_cfg.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/esp_nimble_cfg.h rename to lib/libesp32_div/NimBLE-Arduino/src/esp_nimble_cfg.h diff --git a/lib/libesp32/NimBLE-Arduino/src/esp_nimble_hci.h b/lib/libesp32_div/NimBLE-Arduino/src/esp_nimble_hci.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/esp_nimble_hci.h rename to lib/libesp32_div/NimBLE-Arduino/src/esp_nimble_hci.h diff --git a/lib/libesp32/NimBLE-Arduino/src/esp_nimble_mem.h b/lib/libesp32_div/NimBLE-Arduino/src/esp_nimble_mem.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/esp_nimble_mem.h rename to lib/libesp32_div/NimBLE-Arduino/src/esp_nimble_mem.h diff --git a/lib/libesp32/NimBLE-Arduino/src/ext/tinycrypt/AUTHORS b/lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/AUTHORS similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/ext/tinycrypt/AUTHORS rename to lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/AUTHORS diff --git a/lib/libesp32/NimBLE-Arduino/src/ext/tinycrypt/LICENSE b/lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/LICENSE similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/ext/tinycrypt/LICENSE rename to lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/LICENSE diff --git a/lib/libesp32/NimBLE-Arduino/src/ext/tinycrypt/README b/lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/README similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/ext/tinycrypt/README rename to lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/README diff --git a/lib/libesp32/NimBLE-Arduino/src/ext/tinycrypt/VERSION b/lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/VERSION similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/ext/tinycrypt/VERSION rename to lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/VERSION diff --git a/lib/libesp32/NimBLE-Arduino/src/ext/tinycrypt/documentation/tinycrypt.rst b/lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/documentation/tinycrypt.rst similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/ext/tinycrypt/documentation/tinycrypt.rst rename to lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/documentation/tinycrypt.rst diff --git a/lib/libesp32/NimBLE-Arduino/src/ext/tinycrypt/src/aes_decrypt.c b/lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/src/aes_decrypt.c similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/ext/tinycrypt/src/aes_decrypt.c rename to lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/src/aes_decrypt.c diff --git a/lib/libesp32/NimBLE-Arduino/src/ext/tinycrypt/src/aes_encrypt.c b/lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/src/aes_encrypt.c similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/ext/tinycrypt/src/aes_encrypt.c rename to lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/src/aes_encrypt.c diff --git a/lib/libesp32/NimBLE-Arduino/src/ext/tinycrypt/src/cbc_mode.c b/lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/src/cbc_mode.c similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/ext/tinycrypt/src/cbc_mode.c rename to lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/src/cbc_mode.c diff --git a/lib/libesp32/NimBLE-Arduino/src/ext/tinycrypt/src/ccm_mode.c b/lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/src/ccm_mode.c similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/ext/tinycrypt/src/ccm_mode.c rename to lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/src/ccm_mode.c diff --git a/lib/libesp32/NimBLE-Arduino/src/ext/tinycrypt/src/cmac_mode.c b/lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/src/cmac_mode.c similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/ext/tinycrypt/src/cmac_mode.c rename to lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/src/cmac_mode.c diff --git a/lib/libesp32/NimBLE-Arduino/src/ext/tinycrypt/src/ctr_mode.c b/lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/src/ctr_mode.c similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/ext/tinycrypt/src/ctr_mode.c rename to lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/src/ctr_mode.c diff --git a/lib/libesp32/NimBLE-Arduino/src/ext/tinycrypt/src/ctr_prng.c b/lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/src/ctr_prng.c similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/ext/tinycrypt/src/ctr_prng.c rename to lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/src/ctr_prng.c diff --git a/lib/libesp32/NimBLE-Arduino/src/ext/tinycrypt/src/ecc.c b/lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/src/ecc.c similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/ext/tinycrypt/src/ecc.c rename to lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/src/ecc.c diff --git a/lib/libesp32/NimBLE-Arduino/src/ext/tinycrypt/src/ecc_dh.c b/lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/src/ecc_dh.c similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/ext/tinycrypt/src/ecc_dh.c rename to lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/src/ecc_dh.c diff --git a/lib/libesp32/NimBLE-Arduino/src/ext/tinycrypt/src/ecc_dsa.c b/lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/src/ecc_dsa.c similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/ext/tinycrypt/src/ecc_dsa.c rename to lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/src/ecc_dsa.c diff --git a/lib/libesp32/NimBLE-Arduino/src/ext/tinycrypt/src/ecc_platform_specific.c b/lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/src/ecc_platform_specific.c similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/ext/tinycrypt/src/ecc_platform_specific.c rename to lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/src/ecc_platform_specific.c diff --git a/lib/libesp32/NimBLE-Arduino/src/ext/tinycrypt/src/hmac.c b/lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/src/hmac.c similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/ext/tinycrypt/src/hmac.c rename to lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/src/hmac.c diff --git a/lib/libesp32/NimBLE-Arduino/src/ext/tinycrypt/src/hmac_prng.c b/lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/src/hmac_prng.c similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/ext/tinycrypt/src/hmac_prng.c rename to lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/src/hmac_prng.c diff --git a/lib/libesp32/NimBLE-Arduino/src/ext/tinycrypt/src/sha256.c b/lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/src/sha256.c similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/ext/tinycrypt/src/sha256.c rename to lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/src/sha256.c diff --git a/lib/libesp32/NimBLE-Arduino/src/ext/tinycrypt/src/utils.c b/lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/src/utils.c similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/ext/tinycrypt/src/utils.c rename to lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/src/utils.c diff --git a/lib/libesp32/NimBLE-Arduino/src/hal/hal_timer.h b/lib/libesp32_div/NimBLE-Arduino/src/hal/hal_timer.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/hal/hal_timer.h rename to lib/libesp32_div/NimBLE-Arduino/src/hal/hal_timer.h diff --git a/lib/libesp32/NimBLE-Arduino/src/host/ble_att.h b/lib/libesp32_div/NimBLE-Arduino/src/host/ble_att.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/host/ble_att.h rename to lib/libesp32_div/NimBLE-Arduino/src/host/ble_att.h diff --git a/lib/libesp32/NimBLE-Arduino/src/host/ble_eddystone.h b/lib/libesp32_div/NimBLE-Arduino/src/host/ble_eddystone.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/host/ble_eddystone.h rename to lib/libesp32_div/NimBLE-Arduino/src/host/ble_eddystone.h diff --git a/lib/libesp32/NimBLE-Arduino/src/host/ble_gap.h b/lib/libesp32_div/NimBLE-Arduino/src/host/ble_gap.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/host/ble_gap.h rename to lib/libesp32_div/NimBLE-Arduino/src/host/ble_gap.h diff --git a/lib/libesp32/NimBLE-Arduino/src/host/ble_gatt.h b/lib/libesp32_div/NimBLE-Arduino/src/host/ble_gatt.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/host/ble_gatt.h rename to lib/libesp32_div/NimBLE-Arduino/src/host/ble_gatt.h diff --git a/lib/libesp32/NimBLE-Arduino/src/host/ble_hs.h b/lib/libesp32_div/NimBLE-Arduino/src/host/ble_hs.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/host/ble_hs.h rename to lib/libesp32_div/NimBLE-Arduino/src/host/ble_hs.h diff --git a/lib/libesp32/NimBLE-Arduino/src/host/ble_hs_adv.h b/lib/libesp32_div/NimBLE-Arduino/src/host/ble_hs_adv.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/host/ble_hs_adv.h rename to lib/libesp32_div/NimBLE-Arduino/src/host/ble_hs_adv.h diff --git a/lib/libesp32/NimBLE-Arduino/src/host/ble_hs_hci.h b/lib/libesp32_div/NimBLE-Arduino/src/host/ble_hs_hci.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/host/ble_hs_hci.h rename to lib/libesp32_div/NimBLE-Arduino/src/host/ble_hs_hci.h diff --git a/lib/libesp32/NimBLE-Arduino/src/host/ble_hs_id.h b/lib/libesp32_div/NimBLE-Arduino/src/host/ble_hs_id.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/host/ble_hs_id.h rename to lib/libesp32_div/NimBLE-Arduino/src/host/ble_hs_id.h diff --git a/lib/libesp32/NimBLE-Arduino/src/host/ble_hs_log.h b/lib/libesp32_div/NimBLE-Arduino/src/host/ble_hs_log.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/host/ble_hs_log.h rename to lib/libesp32_div/NimBLE-Arduino/src/host/ble_hs_log.h diff --git a/lib/libesp32/NimBLE-Arduino/src/host/ble_hs_mbuf.h b/lib/libesp32_div/NimBLE-Arduino/src/host/ble_hs_mbuf.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/host/ble_hs_mbuf.h rename to lib/libesp32_div/NimBLE-Arduino/src/host/ble_hs_mbuf.h diff --git a/lib/libesp32/NimBLE-Arduino/src/host/ble_hs_pvcy.h b/lib/libesp32_div/NimBLE-Arduino/src/host/ble_hs_pvcy.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/host/ble_hs_pvcy.h rename to lib/libesp32_div/NimBLE-Arduino/src/host/ble_hs_pvcy.h diff --git a/lib/libesp32/NimBLE-Arduino/src/host/ble_hs_stop.h b/lib/libesp32_div/NimBLE-Arduino/src/host/ble_hs_stop.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/host/ble_hs_stop.h rename to lib/libesp32_div/NimBLE-Arduino/src/host/ble_hs_stop.h diff --git a/lib/libesp32/NimBLE-Arduino/src/host/ble_ibeacon.h b/lib/libesp32_div/NimBLE-Arduino/src/host/ble_ibeacon.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/host/ble_ibeacon.h rename to lib/libesp32_div/NimBLE-Arduino/src/host/ble_ibeacon.h diff --git a/lib/libesp32/NimBLE-Arduino/src/host/ble_l2cap.h b/lib/libesp32_div/NimBLE-Arduino/src/host/ble_l2cap.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/host/ble_l2cap.h rename to lib/libesp32_div/NimBLE-Arduino/src/host/ble_l2cap.h diff --git a/lib/libesp32/NimBLE-Arduino/src/host/ble_monitor.h b/lib/libesp32_div/NimBLE-Arduino/src/host/ble_monitor.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/host/ble_monitor.h rename to lib/libesp32_div/NimBLE-Arduino/src/host/ble_monitor.h diff --git a/lib/libesp32/NimBLE-Arduino/src/host/ble_sm.h b/lib/libesp32_div/NimBLE-Arduino/src/host/ble_sm.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/host/ble_sm.h rename to lib/libesp32_div/NimBLE-Arduino/src/host/ble_sm.h diff --git a/lib/libesp32/NimBLE-Arduino/src/host/ble_store.h b/lib/libesp32_div/NimBLE-Arduino/src/host/ble_store.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/host/ble_store.h rename to lib/libesp32_div/NimBLE-Arduino/src/host/ble_store.h diff --git a/lib/libesp32/NimBLE-Arduino/src/host/ble_uuid.h b/lib/libesp32_div/NimBLE-Arduino/src/host/ble_uuid.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/host/ble_uuid.h rename to lib/libesp32_div/NimBLE-Arduino/src/host/ble_uuid.h diff --git a/lib/libesp32/NimBLE-Arduino/src/host/util/util.h b/lib/libesp32_div/NimBLE-Arduino/src/host/util/util.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/host/util/util.h rename to lib/libesp32_div/NimBLE-Arduino/src/host/util/util.h diff --git a/lib/libesp32/NimBLE-Arduino/src/log/log.h b/lib/libesp32_div/NimBLE-Arduino/src/log/log.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/log/log.h rename to lib/libesp32_div/NimBLE-Arduino/src/log/log.h diff --git a/lib/libesp32/NimBLE-Arduino/src/mem/mem.h b/lib/libesp32_div/NimBLE-Arduino/src/mem/mem.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/mem/mem.h rename to lib/libesp32_div/NimBLE-Arduino/src/mem/mem.h diff --git a/lib/libesp32/NimBLE-Arduino/src/mesh/access.h b/lib/libesp32_div/NimBLE-Arduino/src/mesh/access.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/mesh/access.h rename to lib/libesp32_div/NimBLE-Arduino/src/mesh/access.h diff --git a/lib/libesp32/NimBLE-Arduino/src/mesh/cfg_cli.h b/lib/libesp32_div/NimBLE-Arduino/src/mesh/cfg_cli.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/mesh/cfg_cli.h rename to lib/libesp32_div/NimBLE-Arduino/src/mesh/cfg_cli.h diff --git a/lib/libesp32/NimBLE-Arduino/src/mesh/cfg_srv.h b/lib/libesp32_div/NimBLE-Arduino/src/mesh/cfg_srv.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/mesh/cfg_srv.h rename to lib/libesp32_div/NimBLE-Arduino/src/mesh/cfg_srv.h diff --git a/lib/libesp32/NimBLE-Arduino/src/mesh/glue.h b/lib/libesp32_div/NimBLE-Arduino/src/mesh/glue.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/mesh/glue.h rename to lib/libesp32_div/NimBLE-Arduino/src/mesh/glue.h diff --git a/lib/libesp32/NimBLE-Arduino/src/mesh/health_cli.h b/lib/libesp32_div/NimBLE-Arduino/src/mesh/health_cli.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/mesh/health_cli.h rename to lib/libesp32_div/NimBLE-Arduino/src/mesh/health_cli.h diff --git a/lib/libesp32/NimBLE-Arduino/src/mesh/health_srv.h b/lib/libesp32_div/NimBLE-Arduino/src/mesh/health_srv.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/mesh/health_srv.h rename to lib/libesp32_div/NimBLE-Arduino/src/mesh/health_srv.h diff --git a/lib/libesp32/NimBLE-Arduino/src/mesh/main.h b/lib/libesp32_div/NimBLE-Arduino/src/mesh/main.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/mesh/main.h rename to lib/libesp32_div/NimBLE-Arduino/src/mesh/main.h diff --git a/lib/libesp32/NimBLE-Arduino/src/mesh/mesh.h b/lib/libesp32_div/NimBLE-Arduino/src/mesh/mesh.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/mesh/mesh.h rename to lib/libesp32_div/NimBLE-Arduino/src/mesh/mesh.h diff --git a/lib/libesp32/NimBLE-Arduino/src/mesh/model_cli.h b/lib/libesp32_div/NimBLE-Arduino/src/mesh/model_cli.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/mesh/model_cli.h rename to lib/libesp32_div/NimBLE-Arduino/src/mesh/model_cli.h diff --git a/lib/libesp32/NimBLE-Arduino/src/mesh/model_srv.h b/lib/libesp32_div/NimBLE-Arduino/src/mesh/model_srv.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/mesh/model_srv.h rename to lib/libesp32_div/NimBLE-Arduino/src/mesh/model_srv.h diff --git a/lib/libesp32/NimBLE-Arduino/src/mesh/porting.h b/lib/libesp32_div/NimBLE-Arduino/src/mesh/porting.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/mesh/porting.h rename to lib/libesp32_div/NimBLE-Arduino/src/mesh/porting.h diff --git a/lib/libesp32/NimBLE-Arduino/src/mesh/proxy.h b/lib/libesp32_div/NimBLE-Arduino/src/mesh/proxy.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/mesh/proxy.h rename to lib/libesp32_div/NimBLE-Arduino/src/mesh/proxy.h diff --git a/lib/libesp32/NimBLE-Arduino/src/mesh/slist.h b/lib/libesp32_div/NimBLE-Arduino/src/mesh/slist.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/mesh/slist.h rename to lib/libesp32_div/NimBLE-Arduino/src/mesh/slist.h diff --git a/lib/libesp32/NimBLE-Arduino/src/mesh/testing.h b/lib/libesp32_div/NimBLE-Arduino/src/mesh/testing.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/mesh/testing.h rename to lib/libesp32_div/NimBLE-Arduino/src/mesh/testing.h diff --git a/lib/libesp32/NimBLE-Arduino/src/modlog/modlog.h b/lib/libesp32_div/NimBLE-Arduino/src/modlog/modlog.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/modlog/modlog.h rename to lib/libesp32_div/NimBLE-Arduino/src/modlog/modlog.h diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/ble.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/ble.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/ble.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/ble.h diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/ble_hci_trans.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/ble_hci_trans.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/ble_hci_trans.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/ble_hci_trans.h diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/hci_common.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/hci_common.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/hci_common.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/hci_common.h diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/access.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/access.c similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/access.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/access.c diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/access.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/access.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/access.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/access.h diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/adv.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/adv.c similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/adv.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/adv.c diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/adv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/adv.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/adv.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/adv.h diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/atomic.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/atomic.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/atomic.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/atomic.h diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/beacon.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/beacon.c similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/beacon.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/beacon.c diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/beacon.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/beacon.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/beacon.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/beacon.h diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/ble_att_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/ble_att_priv.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/ble_att_priv.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/ble_att_priv.h diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/ble_gatt_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/ble_gatt_priv.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/ble_gatt_priv.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/ble_gatt_priv.h diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/ble_hs_conn_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/ble_hs_conn_priv.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/ble_hs_conn_priv.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/ble_hs_conn_priv.h diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/ble_l2cap_coc_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/ble_l2cap_coc_priv.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/ble_l2cap_coc_priv.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/ble_l2cap_coc_priv.h diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/ble_l2cap_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/ble_l2cap_priv.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/ble_l2cap_priv.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/ble_l2cap_priv.h diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/ble_l2cap_sig_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/ble_l2cap_sig_priv.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/ble_l2cap_sig_priv.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/ble_l2cap_sig_priv.h diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/cfg_cli.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/cfg_cli.c similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/cfg_cli.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/cfg_cli.c diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/cfg_srv.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/cfg_srv.c similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/cfg_srv.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/cfg_srv.c diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/crypto.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/crypto.c similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/crypto.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/crypto.c diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/crypto.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/crypto.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/crypto.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/crypto.h diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/foundation.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/foundation.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/foundation.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/foundation.h diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/friend.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/friend.c similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/friend.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/friend.c diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/friend.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/friend.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/friend.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/friend.h diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/glue.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/glue.c similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/glue.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/glue.c diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/health_cli.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/health_cli.c similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/health_cli.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/health_cli.c diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/health_srv.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/health_srv.c similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/health_srv.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/health_srv.c diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/light_model.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/light_model.c similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/light_model.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/light_model.c diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/light_model.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/light_model.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/light_model.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/light_model.h diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/lpn.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/lpn.c similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/lpn.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/lpn.c diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/lpn.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/lpn.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/lpn.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/lpn.h diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/mesh.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/mesh.c similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/mesh.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/mesh.c diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/mesh_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/mesh_priv.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/mesh_priv.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/mesh_priv.h diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/model_cli.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/model_cli.c similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/model_cli.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/model_cli.c diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/model_srv.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/model_srv.c similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/model_srv.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/model_srv.c diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/net.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/net.c similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/net.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/net.c diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/net.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/net.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/net.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/net.h diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/prov.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/prov.c similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/prov.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/prov.c diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/prov.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/prov.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/prov.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/prov.h diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/proxy.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/proxy.c similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/proxy.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/proxy.c diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/proxy.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/proxy.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/proxy.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/proxy.h diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/settings.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/settings.c similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/settings.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/settings.c diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/settings.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/settings.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/settings.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/settings.h diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/shell.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/shell.c similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/shell.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/shell.c diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/shell.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/shell.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/shell.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/shell.h diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_att_cmd_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_att_cmd_priv.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_att_cmd_priv.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_att_cmd_priv.h diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_att_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_att_priv.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_att_priv.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_att_priv.h diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_gap_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_gap_priv.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_gap_priv.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_gap_priv.h diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_gatt_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_gatt_priv.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_gatt_priv.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_gatt_priv.h diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_adv_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_adv_priv.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_adv_priv.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_adv_priv.h diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_atomic_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_atomic_priv.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_atomic_priv.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_atomic_priv.h diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_conn_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_conn_priv.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_conn_priv.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_conn_priv.h diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_dbg_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_dbg_priv.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_dbg_priv.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_dbg_priv.h diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_flow_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_flow_priv.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_flow_priv.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_flow_priv.h diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_hci_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_hci_priv.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_hci_priv.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_hci_priv.h diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_id_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_id_priv.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_id_priv.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_id_priv.h diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_mbuf_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_mbuf_priv.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_mbuf_priv.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_mbuf_priv.h diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_periodic_sync_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_periodic_sync_priv.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_periodic_sync_priv.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_periodic_sync_priv.h diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_priv.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_priv.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_priv.h diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_pvcy_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_pvcy_priv.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_pvcy_priv.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_pvcy_priv.h diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_resolv_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_resolv_priv.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_resolv_priv.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_resolv_priv.h diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_startup_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_startup_priv.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_startup_priv.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_startup_priv.h diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_l2cap_coc_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_l2cap_coc_priv.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_l2cap_coc_priv.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_l2cap_coc_priv.h diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_l2cap_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_l2cap_priv.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_l2cap_priv.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_l2cap_priv.h diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_l2cap_sig_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_l2cap_sig_priv.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_l2cap_sig_priv.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_l2cap_sig_priv.h diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_monitor_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_monitor_priv.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_monitor_priv.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_monitor_priv.h diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_sm_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_sm_priv.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_sm_priv.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_sm_priv.h diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_uuid_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_uuid_priv.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_uuid_priv.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_uuid_priv.h diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/testing.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/testing.c similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/testing.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/testing.c diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/testing.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/testing.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/testing.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/testing.h diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/transport.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/transport.c similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/transport.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/transport.c diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/transport.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/transport.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/transport.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/transport.h diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/services/ans/src/ble_svc_ans.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/services/ans/src/ble_svc_ans.c similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/services/ans/src/ble_svc_ans.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/services/ans/src/ble_svc_ans.c diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/services/bas/src/ble_svc_bas.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/services/bas/src/ble_svc_bas.c similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/services/bas/src/ble_svc_bas.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/services/bas/src/ble_svc_bas.c diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/services/gap/src/ble_svc_gap.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/services/gap/src/ble_svc_gap.c similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/services/gap/src/ble_svc_gap.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/services/gap/src/ble_svc_gap.c diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/services/gatt/src/ble_svc_gatt.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/services/gatt/src/ble_svc_gatt.c similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/services/gatt/src/ble_svc_gatt.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/services/gatt/src/ble_svc_gatt.c diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/services/ias/src/ble_svc_ias.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/services/ias/src/ble_svc_ias.c similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/services/ias/src/ble_svc_ias.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/services/ias/src/ble_svc_ias.c diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/services/ipss/src/ble_svc_ipss.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/services/ipss/src/ble_svc_ipss.c similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/services/ipss/src/ble_svc_ipss.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/services/ipss/src/ble_svc_ipss.c diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/services/lls/src/ble_svc_lls.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/services/lls/src/ble_svc_lls.c similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/services/lls/src/ble_svc_lls.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/services/lls/src/ble_svc_lls.c diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/services/tps/src/ble_hs_hci_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/services/tps/src/ble_hs_hci_priv.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/services/tps/src/ble_hs_hci_priv.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/services/tps/src/ble_hs_hci_priv.h diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/services/tps/src/ble_svc_tps.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/services/tps/src/ble_svc_tps.c similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/services/tps/src/ble_svc_tps.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/services/tps/src/ble_svc_tps.c diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_att.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_att.c similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_att.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_att.c diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_att_clt.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_att_clt.c similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_att_clt.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_att_clt.c diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_att_cmd.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_att_cmd.c similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_att_cmd.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_att_cmd.c diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_att_cmd_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_att_cmd_priv.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_att_cmd_priv.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_att_cmd_priv.h diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_att_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_att_priv.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_att_priv.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_att_priv.h diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_att_svr.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_att_svr.c similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_att_svr.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_att_svr.c diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_eddystone.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_eddystone.c similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_eddystone.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_eddystone.c diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_gap.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_gap.c similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_gap.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_gap.c diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_gap_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_gap_priv.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_gap_priv.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_gap_priv.h diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_gatt_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_gatt_priv.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_gatt_priv.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_gatt_priv.h diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_gattc.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_gattc.c similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_gattc.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_gattc.c diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_gatts.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_gatts.c similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_gatts.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_gatts.c diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_gatts_lcl.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_gatts_lcl.c similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_gatts_lcl.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_gatts_lcl.c diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs.c similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs.c diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_adv.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_adv.c similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_adv.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_adv.c diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_adv_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_adv_priv.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_adv_priv.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_adv_priv.h diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_atomic.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_atomic.c similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_atomic.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_atomic.c diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_atomic_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_atomic_priv.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_atomic_priv.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_atomic_priv.h diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_cfg.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_cfg.c similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_cfg.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_cfg.c diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_conn.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_conn.c similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_conn.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_conn.c diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_conn_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_conn_priv.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_conn_priv.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_conn_priv.h diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_dbg.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_dbg.c similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_dbg.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_dbg.c diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_dbg_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_dbg_priv.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_dbg_priv.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_dbg_priv.h diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_flow.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_flow.c similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_flow.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_flow.c diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_flow_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_flow_priv.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_flow_priv.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_flow_priv.h diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_hci.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_hci.c similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_hci.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_hci.c diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_hci_cmd.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_hci_cmd.c similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_hci_cmd.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_hci_cmd.c diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_hci_evt.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_hci_evt.c similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_hci_evt.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_hci_evt.c diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_hci_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_hci_priv.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_hci_priv.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_hci_priv.h diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_hci_util.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_hci_util.c similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_hci_util.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_hci_util.c diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_id.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_id.c similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_id.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_id.c diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_id_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_id_priv.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_id_priv.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_id_priv.h diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_log.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_log.c similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_log.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_log.c diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_mbuf.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_mbuf.c similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_mbuf.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_mbuf.c diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_mbuf_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_mbuf_priv.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_mbuf_priv.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_mbuf_priv.h diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_misc.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_misc.c similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_misc.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_misc.c diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_mqueue.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_mqueue.c similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_mqueue.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_mqueue.c diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_periodic_sync.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_periodic_sync.c similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_periodic_sync.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_periodic_sync.c diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_periodic_sync_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_periodic_sync_priv.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_periodic_sync_priv.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_periodic_sync_priv.h diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_priv.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_priv.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_priv.h diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_pvcy.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_pvcy.c similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_pvcy.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_pvcy.c diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_pvcy_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_pvcy_priv.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_pvcy_priv.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_pvcy_priv.h diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_resolv.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_resolv.c similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_resolv.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_resolv.c diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_resolv_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_resolv_priv.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_resolv_priv.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_resolv_priv.h diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_shutdown.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_shutdown.c similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_shutdown.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_shutdown.c diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_startup.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_startup.c similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_startup.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_startup.c diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_startup_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_startup_priv.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_startup_priv.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_startup_priv.h diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_stop.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_stop.c similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_stop.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_stop.c diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_ibeacon.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_ibeacon.c similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_ibeacon.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_ibeacon.c diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_l2cap.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_l2cap.c similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_l2cap.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_l2cap.c diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_l2cap_coc.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_l2cap_coc.c similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_l2cap_coc.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_l2cap_coc.c diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_l2cap_coc_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_l2cap_coc_priv.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_l2cap_coc_priv.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_l2cap_coc_priv.h diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_l2cap_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_l2cap_priv.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_l2cap_priv.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_l2cap_priv.h diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_l2cap_sig.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_l2cap_sig.c similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_l2cap_sig.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_l2cap_sig.c diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_l2cap_sig_cmd.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_l2cap_sig_cmd.c similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_l2cap_sig_cmd.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_l2cap_sig_cmd.c diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_l2cap_sig_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_l2cap_sig_priv.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_l2cap_sig_priv.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_l2cap_sig_priv.h diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_monitor.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_monitor.c similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_monitor.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_monitor.c diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_monitor_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_monitor_priv.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_monitor_priv.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_monitor_priv.h diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_sm.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_sm.c similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_sm.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_sm.c diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_sm_alg.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_sm_alg.c similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_sm_alg.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_sm_alg.c diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_sm_cmd.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_sm_cmd.c similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_sm_cmd.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_sm_cmd.c diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_sm_lgcy.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_sm_lgcy.c similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_sm_lgcy.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_sm_lgcy.c diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_sm_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_sm_priv.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_sm_priv.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_sm_priv.h diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_sm_sc.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_sm_sc.c similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_sm_sc.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_sm_sc.c diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_store.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_store.c similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_store.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_store.c diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_store_util.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_store_util.c similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_store_util.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_store_util.c diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_uuid.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_uuid.c similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_uuid.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_uuid.c diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_uuid_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_uuid_priv.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_uuid_priv.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_uuid_priv.h diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/store/config/src/ble_store_config.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/store/config/src/ble_store_config.c similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/store/config/src/ble_store_config.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/store/config/src/ble_store_config.c diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/store/config/src/ble_store_config_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/store/config/src/ble_store_config_priv.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/store/config/src/ble_store_config_priv.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/store/config/src/ble_store_config_priv.h diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/store/config/src/ble_store_nvs.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/store/config/src/ble_store_nvs.c similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/store/config/src/ble_store_nvs.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/store/config/src/ble_store_nvs.c diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/store/ram/src/ble_store_ram.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/store/ram/src/ble_store_ram.c similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/store/ram/src/ble_store_ram.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/store/ram/src/ble_store_ram.c diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/host/util/src/addr.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/util/src/addr.c similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/host/util/src/addr.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/host/util/src/addr.c diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/nimble_npl.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble_npl.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/nimble_npl.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble_npl.h diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/nimble_npl_os.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble_npl_os.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/nimble_npl_os.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble_npl_os.h diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/nimble_opt.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble_opt.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/nimble_opt.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble_opt.h diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/nimble_opt_auto.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble_opt_auto.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/nimble_opt_auto.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble_opt_auto.h diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/nimble_port.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble_port.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/nimble_port.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble_port.h diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/nimble_port_freertos.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble_port_freertos.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/nimble_port_freertos.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble_port_freertos.h diff --git a/lib/libesp32/NimBLE-Arduino/src/nimble/npl_freertos.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/npl_freertos.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimble/npl_freertos.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/npl_freertos.h diff --git a/lib/libesp32/NimBLE-Arduino/src/nimconfig.h b/lib/libesp32_div/NimBLE-Arduino/src/nimconfig.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimconfig.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimconfig.h diff --git a/lib/libesp32/NimBLE-Arduino/src/nimconfig_rename.h b/lib/libesp32_div/NimBLE-Arduino/src/nimconfig_rename.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/nimconfig_rename.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimconfig_rename.h diff --git a/lib/libesp32/NimBLE-Arduino/src/os/endian.h b/lib/libesp32_div/NimBLE-Arduino/src/os/endian.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/os/endian.h rename to lib/libesp32_div/NimBLE-Arduino/src/os/endian.h diff --git a/lib/libesp32/NimBLE-Arduino/src/os/os.h b/lib/libesp32_div/NimBLE-Arduino/src/os/os.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/os/os.h rename to lib/libesp32_div/NimBLE-Arduino/src/os/os.h diff --git a/lib/libesp32/NimBLE-Arduino/src/os/os_cputime.h b/lib/libesp32_div/NimBLE-Arduino/src/os/os_cputime.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/os/os_cputime.h rename to lib/libesp32_div/NimBLE-Arduino/src/os/os_cputime.h diff --git a/lib/libesp32/NimBLE-Arduino/src/os/os_error.h b/lib/libesp32_div/NimBLE-Arduino/src/os/os_error.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/os/os_error.h rename to lib/libesp32_div/NimBLE-Arduino/src/os/os_error.h diff --git a/lib/libesp32/NimBLE-Arduino/src/os/os_mbuf.h b/lib/libesp32_div/NimBLE-Arduino/src/os/os_mbuf.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/os/os_mbuf.h rename to lib/libesp32_div/NimBLE-Arduino/src/os/os_mbuf.h diff --git a/lib/libesp32/NimBLE-Arduino/src/os/os_mempool.h b/lib/libesp32_div/NimBLE-Arduino/src/os/os_mempool.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/os/os_mempool.h rename to lib/libesp32_div/NimBLE-Arduino/src/os/os_mempool.h diff --git a/lib/libesp32/NimBLE-Arduino/src/os/os_trace_api.h b/lib/libesp32_div/NimBLE-Arduino/src/os/os_trace_api.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/os/os_trace_api.h rename to lib/libesp32_div/NimBLE-Arduino/src/os/os_trace_api.h diff --git a/lib/libesp32/NimBLE-Arduino/src/os/queue.h b/lib/libesp32_div/NimBLE-Arduino/src/os/queue.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/os/queue.h rename to lib/libesp32_div/NimBLE-Arduino/src/os/queue.h diff --git a/lib/libesp32/NimBLE-Arduino/src/port/src/esp_nimble_mem.c b/lib/libesp32_div/NimBLE-Arduino/src/port/src/esp_nimble_mem.c similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/port/src/esp_nimble_mem.c rename to lib/libesp32_div/NimBLE-Arduino/src/port/src/esp_nimble_mem.c diff --git a/lib/libesp32/NimBLE-Arduino/src/porting/nimble/include/nimble/nimble_port.h b/lib/libesp32_div/NimBLE-Arduino/src/porting/nimble/include/nimble/nimble_port.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/porting/nimble/include/nimble/nimble_port.h rename to lib/libesp32_div/NimBLE-Arduino/src/porting/nimble/include/nimble/nimble_port.h diff --git a/lib/libesp32/NimBLE-Arduino/src/porting/nimble/src/endian.c b/lib/libesp32_div/NimBLE-Arduino/src/porting/nimble/src/endian.c similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/porting/nimble/src/endian.c rename to lib/libesp32_div/NimBLE-Arduino/src/porting/nimble/src/endian.c diff --git a/lib/libesp32/NimBLE-Arduino/src/porting/nimble/src/hal_timer.c b/lib/libesp32_div/NimBLE-Arduino/src/porting/nimble/src/hal_timer.c similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/porting/nimble/src/hal_timer.c rename to lib/libesp32_div/NimBLE-Arduino/src/porting/nimble/src/hal_timer.c diff --git a/lib/libesp32/NimBLE-Arduino/src/porting/nimble/src/mem.c b/lib/libesp32_div/NimBLE-Arduino/src/porting/nimble/src/mem.c similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/porting/nimble/src/mem.c rename to lib/libesp32_div/NimBLE-Arduino/src/porting/nimble/src/mem.c diff --git a/lib/libesp32/NimBLE-Arduino/src/porting/nimble/src/nimble_port.c b/lib/libesp32_div/NimBLE-Arduino/src/porting/nimble/src/nimble_port.c similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/porting/nimble/src/nimble_port.c rename to lib/libesp32_div/NimBLE-Arduino/src/porting/nimble/src/nimble_port.c diff --git a/lib/libesp32/NimBLE-Arduino/src/porting/nimble/src/os_cputime.c b/lib/libesp32_div/NimBLE-Arduino/src/porting/nimble/src/os_cputime.c similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/porting/nimble/src/os_cputime.c rename to lib/libesp32_div/NimBLE-Arduino/src/porting/nimble/src/os_cputime.c diff --git a/lib/libesp32/NimBLE-Arduino/src/porting/nimble/src/os_cputime_pwr2.c b/lib/libesp32_div/NimBLE-Arduino/src/porting/nimble/src/os_cputime_pwr2.c similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/porting/nimble/src/os_cputime_pwr2.c rename to lib/libesp32_div/NimBLE-Arduino/src/porting/nimble/src/os_cputime_pwr2.c diff --git a/lib/libesp32/NimBLE-Arduino/src/porting/nimble/src/os_mbuf.c b/lib/libesp32_div/NimBLE-Arduino/src/porting/nimble/src/os_mbuf.c similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/porting/nimble/src/os_mbuf.c rename to lib/libesp32_div/NimBLE-Arduino/src/porting/nimble/src/os_mbuf.c diff --git a/lib/libesp32/NimBLE-Arduino/src/porting/nimble/src/os_mempool.c b/lib/libesp32_div/NimBLE-Arduino/src/porting/nimble/src/os_mempool.c similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/porting/nimble/src/os_mempool.c rename to lib/libesp32_div/NimBLE-Arduino/src/porting/nimble/src/os_mempool.c diff --git a/lib/libesp32/NimBLE-Arduino/src/porting/nimble/src/os_msys_init.c b/lib/libesp32_div/NimBLE-Arduino/src/porting/nimble/src/os_msys_init.c similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/porting/nimble/src/os_msys_init.c rename to lib/libesp32_div/NimBLE-Arduino/src/porting/nimble/src/os_msys_init.c diff --git a/lib/libesp32/NimBLE-Arduino/src/porting/npl/freertos/src/nimble_port_freertos.c b/lib/libesp32_div/NimBLE-Arduino/src/porting/npl/freertos/src/nimble_port_freertos.c similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/porting/npl/freertos/src/nimble_port_freertos.c rename to lib/libesp32_div/NimBLE-Arduino/src/porting/npl/freertos/src/nimble_port_freertos.c diff --git a/lib/libesp32/NimBLE-Arduino/src/porting/npl/freertos/src/npl_os_freertos.c b/lib/libesp32_div/NimBLE-Arduino/src/porting/npl/freertos/src/npl_os_freertos.c similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/porting/npl/freertos/src/npl_os_freertos.c rename to lib/libesp32_div/NimBLE-Arduino/src/porting/npl/freertos/src/npl_os_freertos.c diff --git a/lib/libesp32/NimBLE-Arduino/src/services/ans/ble_svc_ans.h b/lib/libesp32_div/NimBLE-Arduino/src/services/ans/ble_svc_ans.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/services/ans/ble_svc_ans.h rename to lib/libesp32_div/NimBLE-Arduino/src/services/ans/ble_svc_ans.h diff --git a/lib/libesp32/NimBLE-Arduino/src/services/bas/ble_svc_bas.h b/lib/libesp32_div/NimBLE-Arduino/src/services/bas/ble_svc_bas.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/services/bas/ble_svc_bas.h rename to lib/libesp32_div/NimBLE-Arduino/src/services/bas/ble_svc_bas.h diff --git a/lib/libesp32/NimBLE-Arduino/src/services/gap/ble_svc_gap.h b/lib/libesp32_div/NimBLE-Arduino/src/services/gap/ble_svc_gap.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/services/gap/ble_svc_gap.h rename to lib/libesp32_div/NimBLE-Arduino/src/services/gap/ble_svc_gap.h diff --git a/lib/libesp32/NimBLE-Arduino/src/services/gatt/ble_svc_gatt.h b/lib/libesp32_div/NimBLE-Arduino/src/services/gatt/ble_svc_gatt.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/services/gatt/ble_svc_gatt.h rename to lib/libesp32_div/NimBLE-Arduino/src/services/gatt/ble_svc_gatt.h diff --git a/lib/libesp32/NimBLE-Arduino/src/services/ias/ble_svc_ias.h b/lib/libesp32_div/NimBLE-Arduino/src/services/ias/ble_svc_ias.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/services/ias/ble_svc_ias.h rename to lib/libesp32_div/NimBLE-Arduino/src/services/ias/ble_svc_ias.h diff --git a/lib/libesp32/NimBLE-Arduino/src/services/ipss/ble_svc_ipss.h b/lib/libesp32_div/NimBLE-Arduino/src/services/ipss/ble_svc_ipss.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/services/ipss/ble_svc_ipss.h rename to lib/libesp32_div/NimBLE-Arduino/src/services/ipss/ble_svc_ipss.h diff --git a/lib/libesp32/NimBLE-Arduino/src/services/lls/ble_svc_lls.h b/lib/libesp32_div/NimBLE-Arduino/src/services/lls/ble_svc_lls.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/services/lls/ble_svc_lls.h rename to lib/libesp32_div/NimBLE-Arduino/src/services/lls/ble_svc_lls.h diff --git a/lib/libesp32/NimBLE-Arduino/src/services/tps/ble_svc_tps.h b/lib/libesp32_div/NimBLE-Arduino/src/services/tps/ble_svc_tps.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/services/tps/ble_svc_tps.h rename to lib/libesp32_div/NimBLE-Arduino/src/services/tps/ble_svc_tps.h diff --git a/lib/libesp32/NimBLE-Arduino/src/src/ble_hs_hci_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/src/ble_hs_hci_priv.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/src/ble_hs_hci_priv.h rename to lib/libesp32_div/NimBLE-Arduino/src/src/ble_hs_hci_priv.h diff --git a/lib/libesp32/NimBLE-Arduino/src/src/ble_sm_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/src/ble_sm_priv.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/src/ble_sm_priv.h rename to lib/libesp32_div/NimBLE-Arduino/src/src/ble_sm_priv.h diff --git a/lib/libesp32/NimBLE-Arduino/src/stats/stats.h b/lib/libesp32_div/NimBLE-Arduino/src/stats/stats.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/stats/stats.h rename to lib/libesp32_div/NimBLE-Arduino/src/stats/stats.h diff --git a/lib/libesp32/NimBLE-Arduino/src/store/config/ble_store_config.h b/lib/libesp32_div/NimBLE-Arduino/src/store/config/ble_store_config.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/store/config/ble_store_config.h rename to lib/libesp32_div/NimBLE-Arduino/src/store/config/ble_store_config.h diff --git a/lib/libesp32/NimBLE-Arduino/src/store/ram/ble_store_ram.h b/lib/libesp32_div/NimBLE-Arduino/src/store/ram/ble_store_ram.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/store/ram/ble_store_ram.h rename to lib/libesp32_div/NimBLE-Arduino/src/store/ram/ble_store_ram.h diff --git a/lib/libesp32/NimBLE-Arduino/src/syscfg/syscfg.h b/lib/libesp32_div/NimBLE-Arduino/src/syscfg/syscfg.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/syscfg/syscfg.h rename to lib/libesp32_div/NimBLE-Arduino/src/syscfg/syscfg.h diff --git a/lib/libesp32/NimBLE-Arduino/src/sysinit/sysinit.h b/lib/libesp32_div/NimBLE-Arduino/src/sysinit/sysinit.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/sysinit/sysinit.h rename to lib/libesp32_div/NimBLE-Arduino/src/sysinit/sysinit.h diff --git a/lib/libesp32/NimBLE-Arduino/src/tinycrypt/AUTHORS b/lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/AUTHORS similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/tinycrypt/AUTHORS rename to lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/AUTHORS diff --git a/lib/libesp32/NimBLE-Arduino/src/tinycrypt/LICENSE b/lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/LICENSE similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/tinycrypt/LICENSE rename to lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/LICENSE diff --git a/lib/libesp32/NimBLE-Arduino/src/tinycrypt/README b/lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/README similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/tinycrypt/README rename to lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/README diff --git a/lib/libesp32/NimBLE-Arduino/src/tinycrypt/VERSION b/lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/VERSION similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/tinycrypt/VERSION rename to lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/VERSION diff --git a/lib/libesp32/NimBLE-Arduino/src/tinycrypt/aes.h b/lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/aes.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/tinycrypt/aes.h rename to lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/aes.h diff --git a/lib/libesp32/NimBLE-Arduino/src/tinycrypt/cbc_mode.h b/lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/cbc_mode.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/tinycrypt/cbc_mode.h rename to lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/cbc_mode.h diff --git a/lib/libesp32/NimBLE-Arduino/src/tinycrypt/ccm_mode.h b/lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/ccm_mode.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/tinycrypt/ccm_mode.h rename to lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/ccm_mode.h diff --git a/lib/libesp32/NimBLE-Arduino/src/tinycrypt/cmac_mode.h b/lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/cmac_mode.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/tinycrypt/cmac_mode.h rename to lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/cmac_mode.h diff --git a/lib/libesp32/NimBLE-Arduino/src/tinycrypt/constants.h b/lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/constants.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/tinycrypt/constants.h rename to lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/constants.h diff --git a/lib/libesp32/NimBLE-Arduino/src/tinycrypt/ctr_mode.h b/lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/ctr_mode.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/tinycrypt/ctr_mode.h rename to lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/ctr_mode.h diff --git a/lib/libesp32/NimBLE-Arduino/src/tinycrypt/ctr_prng.h b/lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/ctr_prng.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/tinycrypt/ctr_prng.h rename to lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/ctr_prng.h diff --git a/lib/libesp32/NimBLE-Arduino/src/tinycrypt/documentation/tinycrypt.rst b/lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/documentation/tinycrypt.rst similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/tinycrypt/documentation/tinycrypt.rst rename to lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/documentation/tinycrypt.rst diff --git a/lib/libesp32/NimBLE-Arduino/src/tinycrypt/ecc.h b/lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/ecc.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/tinycrypt/ecc.h rename to lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/ecc.h diff --git a/lib/libesp32/NimBLE-Arduino/src/tinycrypt/ecc_dh.h b/lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/ecc_dh.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/tinycrypt/ecc_dh.h rename to lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/ecc_dh.h diff --git a/lib/libesp32/NimBLE-Arduino/src/tinycrypt/ecc_dsa.h b/lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/ecc_dsa.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/tinycrypt/ecc_dsa.h rename to lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/ecc_dsa.h diff --git a/lib/libesp32/NimBLE-Arduino/src/tinycrypt/ecc_platform_specific.h b/lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/ecc_platform_specific.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/tinycrypt/ecc_platform_specific.h rename to lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/ecc_platform_specific.h diff --git a/lib/libesp32/NimBLE-Arduino/src/tinycrypt/hmac.h b/lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/hmac.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/tinycrypt/hmac.h rename to lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/hmac.h diff --git a/lib/libesp32/NimBLE-Arduino/src/tinycrypt/hmac_prng.h b/lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/hmac_prng.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/tinycrypt/hmac_prng.h rename to lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/hmac_prng.h diff --git a/lib/libesp32/NimBLE-Arduino/src/tinycrypt/sha256.h b/lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/sha256.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/tinycrypt/sha256.h rename to lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/sha256.h diff --git a/lib/libesp32/NimBLE-Arduino/src/tinycrypt/utils.h b/lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/utils.h similarity index 100% rename from lib/libesp32/NimBLE-Arduino/src/tinycrypt/utils.h rename to lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/utils.h diff --git a/lib/libesp32/TTGO_TWatch_Library/LICENSE b/lib/libesp32_div/TTGO_TWatch_Library/LICENSE old mode 100755 new mode 100644 similarity index 98% rename from lib/libesp32/TTGO_TWatch_Library/LICENSE rename to lib/libesp32_div/TTGO_TWatch_Library/LICENSE index 630942bc6..bc95930d4 --- a/lib/libesp32/TTGO_TWatch_Library/LICENSE +++ b/lib/libesp32_div/TTGO_TWatch_Library/LICENSE @@ -1,21 +1,21 @@ -MIT License - -Copyright (c) 2019 TTGO - -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. +MIT License + +Copyright (c) 2019 TTGO + +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. diff --git a/lib/libesp32/TTGO_TWatch_Library/README.MD b/lib/libesp32_div/TTGO_TWatch_Library/README.MD old mode 100755 new mode 100644 similarity index 98% rename from lib/libesp32/TTGO_TWatch_Library/README.MD rename to lib/libesp32_div/TTGO_TWatch_Library/README.MD index 9e8d6ed0e..102d8cbe3 --- a/lib/libesp32/TTGO_TWatch_Library/README.MD +++ b/lib/libesp32_div/TTGO_TWatch_Library/README.MD @@ -1,62 +1,62 @@ -

🌟LilyGO T-Watch🌟

- -**English | [中文](docs/details_cn.md)** - - -

⭐ News

- -1. In order to be compatible with multiple versions of T-Watch, all examples include a `config.h` file. For the first use, you need to define the **T-Watch** model you use in the `config.h` file -2. In the `config.h` file, you can also see similar definitions, such as **LILYGO_WATCH_LVGL**, **LILYGO_WATCH_HAS_MOTOR**, this type of definition, it will be responsible for opening the defined module function, all definitions Will be available here [View](./docs/defined_en.md) -3. Most of the examples are only used as hardware function demonstrations. This library only completes some initialization work and some demonstrations. For more advanced gameplay, please see [TTGO.h](https://github.com/Xinyuan-LilyGO/TTGO_TWatch_Library/blob/master/src/TTGO.h), to understand how to initialize, after being familiar with it, you can completely leave this library for more advanced gameplay -- About API, please check the source code - -

🚀 Characteristics

- -1. The library already contains all the hardware drivers for `T-Watch` -2. Using **TFT_eSPI** as the display driver, you can directly call **TFT_eSPI** through the construction object. -3. Using **lvgl 7.0.0** as the display graphics framework, the driver method has been implemented, you only need to call lvgl api according to your own needs. -4. For the use of lvgl please refer to **[lvgl docs](https://docs.lvgl.io/v7/en/html/)** - - -

🔷 Install

- -- Download a zipfile from github using the "Download ZIP" button and install it using the IDE ("Sketch" -> "Include Library" -> "Add .ZIP Library..." -- Clone this git repository into your sketchbook/libraries folder. -For more info, see https://www.arduino.cc/en/Guide/Libraries - - -

🔶 How to find the sample program

- -- In the Arduino board select `TTGO T-Watch` -- In the Arduino File -> Examples -> TTGO T-Watch - -

🔷 Note

- -- If you don't have the `TTGO T-Watch` option in your board manager, please update the esp32 board as follows: - - Using Arduino IDE Boards Manager (preferred) - + [Instructions for Boards Manager](docs/arduino-ide/boards_manager.md) - - Using Arduino IDE with the development repository - + [Instructions for Windows](docs/arduino-ide/windows.md) - + [Instructions for Mac](docs/arduino-ide/mac.md) - + [Instructions for Debian/Ubuntu Linux](docs/arduino-ide/debian_ubuntu.md) - + [Instructions for Fedora](docs/arduino-ide/fedora.md) - + [Instructions for openSUSE](docs/arduino-ide/opensuse.md) - -

🔶 Precautions

- -- T-Watch-2019 : Since Twatch uses a special IO as the SD interface, please remove the SD card when downloading the program. - - -

🔷 Other

- -- [Click for details of power consumption](docs/power.md) -- [Pin Map Click to View](docs/pinmap.md) -- [3D Shell](https://github.com/Xinyuan-LilyGO/LilyGo-TWatch-DataSheet/tree/master/3DSHELL) -- [Hardware Resource](https://github.com/Xinyuan-LilyGO/LilyGo-TWatch-DataSheet) -- [Acsip S76/78 Library&Examples](https://github.com/lewisxhe/Acsip-S7xG-Library) - -

🔶 More interesting projects

- -- [Flight Recorder](https://github.com/lyusupov/SoftRF/wiki/Flight-Recorder) -- [TTGO_T_Watch_Baidu_Rec](https://github.com/lixy123/TTGO_T_Watch_Baidu_Rec) -- [TTGO_T_Watch_Alarm_Clock](https://github.com/lixy123/TTGO_T_Watch_Alarm_Clock) +

🌟LilyGO T-Watch🌟

+ +**English | [中文](docs/details_cn.md)** + + +

⭐ News

+ +1. In order to be compatible with multiple versions of T-Watch, all examples include a `config.h` file. For the first use, you need to define the **T-Watch** model you use in the `config.h` file +2. In the `config.h` file, you can also see similar definitions, such as **LILYGO_WATCH_LVGL**, **LILYGO_WATCH_HAS_MOTOR**, this type of definition, it will be responsible for opening the defined module function, all definitions Will be available here [View](./docs/defined_en.md) +3. Most of the examples are only used as hardware function demonstrations. This library only completes some initialization work and some demonstrations. For more advanced gameplay, please see [TTGO.h](https://github.com/Xinyuan-LilyGO/TTGO_TWatch_Library/blob/master/src/TTGO.h), to understand how to initialize, after being familiar with it, you can completely leave this library for more advanced gameplay +- About API, please check the source code + +

🚀 Characteristics

+ +1. The library already contains all the hardware drivers for `T-Watch` +2. Using **TFT_eSPI** as the display driver, you can directly call **TFT_eSPI** through the construction object. +3. Using **lvgl 7.0.0** as the display graphics framework, the driver method has been implemented, you only need to call lvgl api according to your own needs. +4. For the use of lvgl please refer to **[lvgl docs](https://docs.lvgl.io/v7/en/html/)** + + +

🔷 Install

+ +- Download a zipfile from github using the "Download ZIP" button and install it using the IDE ("Sketch" -> "Include Library" -> "Add .ZIP Library..." +- Clone this git repository into your sketchbook/libraries folder. +For more info, see https://www.arduino.cc/en/Guide/Libraries + + +

🔶 How to find the sample program

+ +- In the Arduino board select `TTGO T-Watch` +- In the Arduino File -> Examples -> TTGO T-Watch + +

🔷 Note

+ +- If you don't have the `TTGO T-Watch` option in your board manager, please update the esp32 board as follows: + - Using Arduino IDE Boards Manager (preferred) + + [Instructions for Boards Manager](docs/arduino-ide/boards_manager.md) + - Using Arduino IDE with the development repository + + [Instructions for Windows](docs/arduino-ide/windows.md) + + [Instructions for Mac](docs/arduino-ide/mac.md) + + [Instructions for Debian/Ubuntu Linux](docs/arduino-ide/debian_ubuntu.md) + + [Instructions for Fedora](docs/arduino-ide/fedora.md) + + [Instructions for openSUSE](docs/arduino-ide/opensuse.md) + +

🔶 Precautions

+ +- T-Watch-2019 : Since Twatch uses a special IO as the SD interface, please remove the SD card when downloading the program. + + +

🔷 Other

+ +- [Click for details of power consumption](docs/power.md) +- [Pin Map Click to View](docs/pinmap.md) +- [3D Shell](https://github.com/Xinyuan-LilyGO/LilyGo-TWatch-DataSheet/tree/master/3DSHELL) +- [Hardware Resource](https://github.com/Xinyuan-LilyGO/LilyGo-TWatch-DataSheet) +- [Acsip S76/78 Library&Examples](https://github.com/lewisxhe/Acsip-S7xG-Library) + +

🔶 More interesting projects

+ +- [Flight Recorder](https://github.com/lyusupov/SoftRF/wiki/Flight-Recorder) +- [TTGO_T_Watch_Baidu_Rec](https://github.com/lixy123/TTGO_T_Watch_Baidu_Rec) +- [TTGO_T_Watch_Alarm_Clock](https://github.com/lixy123/TTGO_T_Watch_Alarm_Clock) diff --git a/lib/libesp32/TTGO_TWatch_Library/library.json b/lib/libesp32_div/TTGO_TWatch_Library/library.json old mode 100755 new mode 100644 similarity index 96% rename from lib/libesp32/TTGO_TWatch_Library/library.json rename to lib/libesp32_div/TTGO_TWatch_Library/library.json index b56343ca9..105adc783 --- a/lib/libesp32/TTGO_TWatch_Library/library.json +++ b/lib/libesp32_div/TTGO_TWatch_Library/library.json @@ -1,25 +1,25 @@ -{ - "name": "TTGO TWatch Library", - "keywords": "Device Conterl,TWatch,Watch,TTGO", - "description": "Arduino Library for TTGO T-Watch development kit", - "repository": { - "type": "git", - "url": "https://github.com/Xinyuan-LilyGO/TTGO_TWatch_Library.git" - }, - "authors": [ - { - "name": "Xinyuan Electronics", - "email": "lily@lilygo.cc", - "url": "https://github.com/Xinyuan-LilyGO", - "maintainer": true - }, - { - "name": "lewishe", - "email": "lewishe@outlook.com", - "url": "https://github.com/lewisxhe" - } - ], - "version": "1.2.0", - "frameworks": "arduino", - "platforms": "esp32" +{ + "name": "TTGO TWatch Library", + "keywords": "Device Conterl,TWatch,Watch,TTGO", + "description": "Arduino Library for TTGO T-Watch development kit", + "repository": { + "type": "git", + "url": "https://github.com/Xinyuan-LilyGO/TTGO_TWatch_Library.git" + }, + "authors": [ + { + "name": "Xinyuan Electronics", + "email": "lily@lilygo.cc", + "url": "https://github.com/Xinyuan-LilyGO", + "maintainer": true + }, + { + "name": "lewishe", + "email": "lewishe@outlook.com", + "url": "https://github.com/lewisxhe" + } + ], + "version": "1.2.0", + "frameworks": "arduino", + "platforms": "esp32" } \ No newline at end of file diff --git a/lib/libesp32/TTGO_TWatch_Library/library.properties b/lib/libesp32_div/TTGO_TWatch_Library/library.properties old mode 100755 new mode 100644 similarity index 96% rename from lib/libesp32/TTGO_TWatch_Library/library.properties rename to lib/libesp32_div/TTGO_TWatch_Library/library.properties index ec44a9e27..0a8d63b81 --- a/lib/libesp32/TTGO_TWatch_Library/library.properties +++ b/lib/libesp32_div/TTGO_TWatch_Library/library.properties @@ -1,10 +1,10 @@ -name=TTGO TWatch Library -version=1.2.0 -author=TTGO -maintainer=lewis he -sentence=Library for TTGO T-Watch development kit -paragraph=twatch library -category=Device Control -url=https://github.com/Xinyuan-LilyGO/TTGO_TWatch_Library -architectures=esp32 -includes=* +name=TTGO TWatch Library +version=1.2.0 +author=TTGO +maintainer=lewis he +sentence=Library for TTGO T-Watch development kit +paragraph=twatch library +category=Device Control +url=https://github.com/Xinyuan-LilyGO/TTGO_TWatch_Library +architectures=esp32 +includes=* diff --git a/lib/libesp32/TTGO_TWatch_Library/src/axp20x.cpp b/lib/libesp32_div/TTGO_TWatch_Library/src/axp20x.cpp old mode 100755 new mode 100644 similarity index 96% rename from lib/libesp32/TTGO_TWatch_Library/src/axp20x.cpp rename to lib/libesp32_div/TTGO_TWatch_Library/src/axp20x.cpp index 0adf4faf3..e79820f72 --- a/lib/libesp32/TTGO_TWatch_Library/src/axp20x.cpp +++ b/lib/libesp32_div/TTGO_TWatch_Library/src/axp20x.cpp @@ -1,1800 +1,1800 @@ -///////////////////////////////////////////////////////////////// -/* -MIT License - -Copyright (c) 2019 lewis he - -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. - -axp20x.cpp - Arduino library for X-Power AXP202 chip. -Created by Lewis he on April 1, 2019. -github:https://github.com/lewisxhe/AXP202X_Libraries -*/ -///////////////////////////////////////////////////////////////// - -#include "axp20x.h" -#include - -const uint8_t AXP20X_Class::startupParams[] = { - 0b00000000, - 0b01000000, - 0b10000000, - 0b11000000 -}; - -const uint8_t AXP20X_Class::longPressParams[] = { - 0b00000000, - 0b00010000, - 0b00100000, - 0b00110000 -}; - -const uint8_t AXP20X_Class::shutdownParams[] = { - 0b00000000, - 0b00000001, - 0b00000010, - 0b00000011 -}; - -const uint8_t AXP20X_Class::targetVolParams[] = { - 0b00000000, - 0b00100000, - 0b01000000, - 0b01100000 -}; - - - -// Power Output Control register -uint8_t AXP20X_Class::_outputReg; - -int AXP20X_Class::_axp_probe() -{ - uint8_t data; - if (_isAxp173) { - //!Axp173 does not have a chip ID, read the status register to see if it reads normally - _readByte(0x01, 1, &data); - if (data == 0 || data == 0xFF) { - return AXP_FAIL; - } - _chip_id = AXP173_CHIP_ID; - _readByte(AXP202_LDO234_DC23_CTL, 1, &_outputReg); - AXP_DEBUG("OUTPUT Register 0x%x\n", _outputReg); - _init = true; - return AXP_PASS; - } - _readByte(AXP202_IC_TYPE, 1, &_chip_id); - AXP_DEBUG("chip id detect 0x%x\n", _chip_id); - if (_chip_id == AXP202_CHIP_ID || _chip_id == AXP192_CHIP_ID) { - AXP_DEBUG("Detect CHIP :%s\n", _chip_id == AXP202_CHIP_ID ? "AXP202" : "AXP192"); - _readByte(AXP202_LDO234_DC23_CTL, 1, &_outputReg); - AXP_DEBUG("OUTPUT Register 0x%x\n", _outputReg); - _init = true; - return AXP_PASS; - } - return AXP_FAIL; -} - -int AXP20X_Class::begin(TwoWire &port, uint8_t addr, bool isAxp173) -{ - _i2cPort = &port; //Grab which port the user wants us to use - _address = addr; - _isAxp173 = isAxp173; - - return _axp_probe(); -} - -int AXP20X_Class::begin(axp_com_fptr_t read_cb, axp_com_fptr_t write_cb, uint8_t addr, bool isAxp173) -{ - if (read_cb == nullptr || write_cb == nullptr)return AXP_FAIL; - _read_cb = read_cb; - _write_cb = write_cb; - _address = addr; - _isAxp173 = isAxp173; - return _axp_probe(); -} - -//Only axp192 chip -bool AXP20X_Class::isDCDC1Enable() -{ - if (_chip_id == AXP192_CHIP_ID) - return IS_OPEN(_outputReg, AXP192_DCDC1); - else if (_chip_id == AXP173_CHIP_ID) - return IS_OPEN(_outputReg, AXP173_DCDC1); - return false; -} - -bool AXP20X_Class::isExtenEnable() -{ - if (_chip_id == AXP192_CHIP_ID) - return IS_OPEN(_outputReg, AXP192_EXTEN); - else if (_chip_id == AXP202_CHIP_ID) - return IS_OPEN(_outputReg, AXP202_EXTEN); - else if (_chip_id == AXP173_CHIP_ID) { - uint8_t data; - _readByte(AXP173_EXTEN_DC2_CTL, 1, &data); - return IS_OPEN(data, AXP173_CTL_EXTEN_BIT); - } - return false; -} - -bool AXP20X_Class::isLDO2Enable() -{ - if (_chip_id == AXP173_CHIP_ID) { - return IS_OPEN(_outputReg, AXP173_LDO2); - } - //axp192 same axp202 ldo2 bit - return IS_OPEN(_outputReg, AXP202_LDO2); -} - -bool AXP20X_Class::isLDO3Enable() -{ - if (_chip_id == AXP192_CHIP_ID) - return IS_OPEN(_outputReg, AXP192_LDO3); - else if (_chip_id == AXP202_CHIP_ID) - return IS_OPEN(_outputReg, AXP202_LDO3); - else if (_chip_id == AXP173_CHIP_ID) - return IS_OPEN(_outputReg, AXP173_LDO3); - return false; -} - -bool AXP20X_Class::isLDO4Enable() -{ - if (_chip_id == AXP202_CHIP_ID) - return IS_OPEN(_outputReg, AXP202_LDO4); - if (_chip_id == AXP173_CHIP_ID) - return IS_OPEN(_outputReg, AXP173_LDO4); - return false; -} - -bool AXP20X_Class::isDCDC2Enable() -{ - if (_chip_id == AXP173_CHIP_ID) { - uint8_t data; - _readByte(AXP173_EXTEN_DC2_CTL, 1, &data); - return IS_OPEN(data, AXP173_CTL_DC2_BIT); - } - //axp192 same axp202 dc2 bit - return IS_OPEN(_outputReg, AXP202_DCDC2); -} - -bool AXP20X_Class::isDCDC3Enable() -{ - if (_chip_id == AXP173_CHIP_ID) - return false; - //axp192 same axp202 dc3 bit - return IS_OPEN(_outputReg, AXP202_DCDC3); -} - -int AXP20X_Class::setPowerOutPut(uint8_t ch, bool en) -{ - uint8_t data; - uint8_t val = 0; - if (!_init) - return AXP_NOT_INIT; - - //! Axp173 cannot use the REG12H register to control - //! DC2 and EXTEN. It is necessary to control REG10H separately. - if (_chip_id == AXP173_CHIP_ID) { - _readByte(AXP173_EXTEN_DC2_CTL, 1, &data); - if (ch & AXP173_DCDC2) { - data = en ? data | BIT_MASK(AXP173_CTL_DC2_BIT) : data & (~BIT_MASK(AXP173_CTL_DC2_BIT)); - ch &= (~BIT_MASK(AXP173_DCDC2)); - _writeByte(AXP173_EXTEN_DC2_CTL, 1, &data); - } else if (ch & AXP173_EXTEN) { - data = en ? data | BIT_MASK(AXP173_CTL_EXTEN_BIT) : data & (~BIT_MASK(AXP173_CTL_EXTEN_BIT)); - ch &= (~BIT_MASK(AXP173_EXTEN)); - _writeByte(AXP173_EXTEN_DC2_CTL, 1, &data); - } - } - - _readByte(AXP202_LDO234_DC23_CTL, 1, &data); - if (en) { - data |= (1 << ch); - } else { - data &= (~(1 << ch)); - } - - if (_chip_id == AXP202_CHIP_ID) { - FORCED_OPEN_DCDC3(data); //! Must be forced open in T-Watch - } - - _writeByte(AXP202_LDO234_DC23_CTL, 1, &data); - delay(1); - _readByte(AXP202_LDO234_DC23_CTL, 1, &val); - if (data == val) { - _outputReg = val; - return AXP_PASS; - } - return AXP_FAIL; -} - -bool AXP20X_Class::isChargeing() -{ - uint8_t reg; - if (!_init) - return AXP_NOT_INIT; - _readByte(AXP202_MODE_CHGSTATUS, 1, ®); - return IS_OPEN(reg, 6); -} - -bool AXP20X_Class::isBatteryConnect() -{ - uint8_t reg; - if (!_init) - return AXP_NOT_INIT; - _readByte(AXP202_MODE_CHGSTATUS, 1, ®); - return IS_OPEN(reg, 5); -} - -float AXP20X_Class::getAcinVoltage() -{ - if (!_init) - return AXP_NOT_INIT; - return _getRegistResult(AXP202_ACIN_VOL_H8, AXP202_ACIN_VOL_L4) * AXP202_ACIN_VOLTAGE_STEP; -} - -float AXP20X_Class::getAcinCurrent() -{ - if (!_init) - return AXP_NOT_INIT; - return _getRegistResult(AXP202_ACIN_CUR_H8, AXP202_ACIN_CUR_L4) * AXP202_ACIN_CUR_STEP; -} - -float AXP20X_Class::getVbusVoltage() -{ - if (!_init) - return AXP_NOT_INIT; - return _getRegistResult(AXP202_VBUS_VOL_H8, AXP202_VBUS_VOL_L4) * AXP202_VBUS_VOLTAGE_STEP; -} - -float AXP20X_Class::getVbusCurrent() -{ - if (!_init) - return AXP_NOT_INIT; - return _getRegistResult(AXP202_VBUS_CUR_H8, AXP202_VBUS_CUR_L4) * AXP202_VBUS_CUR_STEP; -} - -float AXP20X_Class::getTemp() -{ - if (!_init) - return AXP_NOT_INIT; - return _getRegistResult(AXP202_INTERNAL_TEMP_H8, AXP202_INTERNAL_TEMP_L4) * AXP202_INTERNAL_TEMP_STEP; -} - -float AXP20X_Class::getTSTemp() -{ - if (!_init) - return AXP_NOT_INIT; - return _getRegistResult(AXP202_TS_IN_H8, AXP202_TS_IN_L4) * AXP202_TS_PIN_OUT_STEP; -} - -float AXP20X_Class::getGPIO0Voltage() -{ - if (!_init) - return AXP_NOT_INIT; - return _getRegistResult(AXP202_GPIO0_VOL_ADC_H8, AXP202_GPIO0_VOL_ADC_L4) * AXP202_GPIO0_STEP; -} - -float AXP20X_Class::getGPIO1Voltage() -{ - if (!_init) - return AXP_NOT_INIT; - return _getRegistResult(AXP202_GPIO1_VOL_ADC_H8, AXP202_GPIO1_VOL_ADC_L4) * AXP202_GPIO1_STEP; -} - -/* -Note: the battery power formula: -Pbat =2* register value * Voltage LSB * Current LSB / 1000. -(Voltage LSB is 1.1mV; Current LSB is 0.5mA, and unit of calculation result is mW.) -*/ -float AXP20X_Class::getBattInpower() -{ - float rslt; - uint8_t hv, mv, lv; - if (!_init) - return AXP_NOT_INIT; - _readByte(AXP202_BAT_POWERH8, 1, &hv); - _readByte(AXP202_BAT_POWERM8, 1, &mv); - _readByte(AXP202_BAT_POWERL8, 1, &lv); - rslt = (hv << 16) | (mv << 8) | lv; - rslt = 2 * rslt * 1.1 * 0.5 / 1000; - return rslt; -} - -float AXP20X_Class::getBattVoltage() -{ - if (!_init) - return AXP_NOT_INIT; - return _getRegistResult(AXP202_BAT_AVERVOL_H8, AXP202_BAT_AVERVOL_L4) * AXP202_BATT_VOLTAGE_STEP; -} - -float AXP20X_Class::getBattChargeCurrent() -{ - if (!_init) - return AXP_NOT_INIT; - switch (_chip_id) { - case AXP202_CHIP_ID: - return _getRegistResult(AXP202_BAT_AVERCHGCUR_H8, AXP202_BAT_AVERCHGCUR_L4) * AXP202_BATT_CHARGE_CUR_STEP; - case AXP192_CHIP_ID: - return _getRegistH8L5(AXP202_BAT_AVERCHGCUR_H8, AXP202_BAT_AVERCHGCUR_L5) * AXP202_BATT_CHARGE_CUR_STEP; - default: - return AXP_FAIL; - } -} - -float AXP20X_Class::getBattDischargeCurrent() -{ - if (!_init) - return AXP_NOT_INIT; - return _getRegistH8L5(AXP202_BAT_AVERDISCHGCUR_H8, AXP202_BAT_AVERDISCHGCUR_L5) * AXP202_BATT_DISCHARGE_CUR_STEP; -} - -float AXP20X_Class::getSysIPSOUTVoltage() -{ - if (!_init) - return AXP_NOT_INIT; - return _getRegistResult(AXP202_APS_AVERVOL_H8, AXP202_APS_AVERVOL_L4); -} - -/* -Coulomb calculation formula: -C= 65536 * current LSB *(charge coulomb counter value - discharge coulomb counter value) / -3600 / ADC sample rate. Refer to REG84H setting for ADC sample rate;the current LSB is -0.5mA;unit of the calculation result is mAh. ) -*/ -uint32_t AXP20X_Class::getBattChargeCoulomb() -{ - uint8_t buffer[4]; - if (!_init) - return AXP_NOT_INIT; - _readByte(0xB0, 4, buffer); - return (buffer[0] << 24) + (buffer[1] << 16) + (buffer[2] << 8) + buffer[3]; -} - -uint32_t AXP20X_Class::getBattDischargeCoulomb() -{ - uint8_t buffer[4]; - if (!_init) - return AXP_NOT_INIT; - _readByte(0xB4, 4, buffer); - return (buffer[0] << 24) + (buffer[1] << 16) + (buffer[2] << 8) + buffer[3]; -} - -float AXP20X_Class::getCoulombData() -{ - if (!_init) - return AXP_NOT_INIT; - uint32_t charge = getBattChargeCoulomb(), discharge = getBattDischargeCoulomb(); - uint8_t rate = getAdcSamplingRate(); - float result = 65536.0 * 0.5 * (charge - discharge) / 3600.0 / rate; - return result; -} - - -//------------------------------------------------------- -// New Coulomb functions by MrFlexi -//------------------------------------------------------- - -uint8_t AXP20X_Class::getCoulombRegister() -{ - uint8_t buffer; - if (!_init) - return AXP_NOT_INIT; - _readByte(AXP202_COULOMB_CTL, 1, &buffer); - return buffer; -} - - -int AXP20X_Class::setCoulombRegister(uint8_t val) -{ - if (!_init) - return AXP_NOT_INIT; - _writeByte(AXP202_COULOMB_CTL, 1, &val); - return AXP_PASS; -} - - -int AXP20X_Class::EnableCoulombcounter(void) -{ - - if (!_init) - return AXP_NOT_INIT; - uint8_t val = 0x80; - _writeByte(AXP202_COULOMB_CTL, 1, &val); - return AXP_PASS; -} - -int AXP20X_Class::DisableCoulombcounter(void) -{ - - if (!_init) - return AXP_NOT_INIT; - uint8_t val = 0x00; - _writeByte(AXP202_COULOMB_CTL, 1, &val); - return AXP_PASS; -} - -int AXP20X_Class::StopCoulombcounter(void) -{ - - if (!_init) - return AXP_NOT_INIT; - uint8_t val = 0xB8; - _writeByte(AXP202_COULOMB_CTL, 1, &val); - return AXP_PASS; -} - - -int AXP20X_Class::ClearCoulombcounter(void) -{ - - if (!_init) - return AXP_NOT_INIT; - uint8_t val = 0xA0; - _writeByte(AXP202_COULOMB_CTL, 1, &val); - return AXP_PASS; -} - -//------------------------------------------------------- -// END -//------------------------------------------------------- - - - -uint8_t AXP20X_Class::getAdcSamplingRate() -{ - //axp192 same axp202 aregister address 0x84 - if (!_init) - return AXP_NOT_INIT; - uint8_t val; - _readByte(AXP202_ADC_SPEED, 1, &val); - return 25 * (int)pow(2, (val & 0xC0) >> 6); -} - -int AXP20X_Class::setAdcSamplingRate(axp_adc_sampling_rate_t rate) -{ - //axp192 same axp202 aregister address 0x84 - if (!_init) - return AXP_NOT_INIT; - if (rate > AXP_ADC_SAMPLING_RATE_200HZ) - return AXP_FAIL; - uint8_t val; - _readByte(AXP202_ADC_SPEED, 1, &val); - uint8_t rw = rate; - val &= 0x3F; - val |= (rw << 6); - _writeByte(AXP202_ADC_SPEED, 1, &val); - return AXP_PASS; -} - -int AXP20X_Class::setTSfunction(axp_ts_pin_function_t func) -{ - //axp192 same axp202 aregister address 0x84 - if (!_init) - return AXP_NOT_INIT; - if (func > AXP_TS_PIN_FUNCTION_ADC) - return AXP_FAIL; - uint8_t val; - _readByte(AXP202_ADC_SPEED, 1, &val); - uint8_t rw = func; - val &= 0xFA; - val |= (rw << 2); - _writeByte(AXP202_ADC_SPEED, 1, &val); - return AXP_PASS; -} - -int AXP20X_Class::setTScurrent(axp_ts_pin_current_t current) -{ - //axp192 same axp202 aregister address 0x84 - if (!_init) - return AXP_NOT_INIT; - if (current > AXP_TS_PIN_CURRENT_80UA) - return AXP_FAIL; - uint8_t val; - _readByte(AXP202_ADC_SPEED, 1, &val); - uint8_t rw = current; - val &= 0xCF; - val |= (rw << 4); - _writeByte(AXP202_ADC_SPEED, 1, &val); - return AXP_PASS; -} - -int AXP20X_Class::setTSmode(axp_ts_pin_mode_t mode) -{ - //axp192 same axp202 aregister address 0x84 - if (!_init) - return AXP_NOT_INIT; - if (mode > AXP_TS_PIN_MODE_ENABLE) - return AXP_FAIL; - uint8_t val; - _readByte(AXP202_ADC_SPEED, 1, &val); - uint8_t rw = mode; - val &= 0xFC; - val |= rw; - _writeByte(AXP202_ADC_SPEED, 1, &val); - - // TS pin ADC function enable/disable - if (mode == AXP_TS_PIN_MODE_DISABLE) - adc1Enable(AXP202_TS_PIN_ADC1, false); - else - adc1Enable(AXP202_TS_PIN_ADC1, true); - return AXP_PASS; -} - -int AXP20X_Class::adc1Enable(uint16_t params, bool en) -{ - if (!_init) - return AXP_NOT_INIT; - uint8_t val; - _readByte(AXP202_ADC_EN1, 1, &val); - if (en) - val |= params; - else - val &= ~(params); - _writeByte(AXP202_ADC_EN1, 1, &val); - return AXP_PASS; -} - -int AXP20X_Class::adc2Enable(uint16_t params, bool en) -{ - if (!_init) - return AXP_NOT_INIT; - uint8_t val; - _readByte(AXP202_ADC_EN2, 1, &val); - if (en) - val |= params; - else - val &= ~(params); - _writeByte(AXP202_ADC_EN2, 1, &val); - return AXP_PASS; -} - -int AXP20X_Class::enableIRQ(uint64_t params, bool en) -{ - if (!_init) - return AXP_NOT_INIT; - uint8_t val, val1; - if (params & 0xFF) { - val1 = params & 0xFF; - _readByte(AXP202_INTEN1, 1, &val); - if (en) - val |= val1; - else - val &= ~(val1); - AXP_DEBUG("%s [0x%x]val:0x%x\n", en ? "enable" : "disable", AXP202_INTEN1, val); - _writeByte(AXP202_INTEN1, 1, &val); - } - if (params & 0xFF00) { - val1 = params >> 8; - _readByte(AXP202_INTEN2, 1, &val); - if (en) - val |= val1; - else - val &= ~(val1); - AXP_DEBUG("%s [0x%x]val:0x%x\n", en ? "enable" : "disable", AXP202_INTEN2, val); - _writeByte(AXP202_INTEN2, 1, &val); - } - - if (params & 0xFF0000) { - val1 = params >> 16; - _readByte(AXP202_INTEN3, 1, &val); - if (en) - val |= val1; - else - val &= ~(val1); - AXP_DEBUG("%s [0x%x]val:0x%x\n", en ? "enable" : "disable", AXP202_INTEN3, val); - _writeByte(AXP202_INTEN3, 1, &val); - } - - if (params & 0xFF000000) { - val1 = params >> 24; - _readByte(AXP202_INTEN4, 1, &val); - if (en) - val |= val1; - else - val &= ~(val1); - AXP_DEBUG("%s [0x%x]val:0x%x\n", en ? "enable" : "disable", AXP202_INTEN4, val); - _writeByte(AXP202_INTEN4, 1, &val); - } - - if (params & 0xFF00000000) { - val1 = params >> 32; - _readByte(AXP202_INTEN5, 1, &val); - if (en) - val |= val1; - else - val &= ~(val1); - AXP_DEBUG("%s [0x%x]val:0x%x\n", en ? "enable" : "disable", AXP202_INTEN5, val); - _writeByte(AXP202_INTEN5, 1, &val); - } - return AXP_PASS; -} - -int AXP20X_Class::readIRQ() -{ - if (!_init) - return AXP_NOT_INIT; - switch (_chip_id) { - case AXP192_CHIP_ID: - for (int i = 0; i < 4; ++i) { - _readByte(AXP192_INTSTS1 + i, 1, &_irq[i]); - } - _readByte(AXP192_INTSTS5, 1, &_irq[4]); - return AXP_PASS; - - case AXP202_CHIP_ID: - for (int i = 0; i < 5; ++i) { - _readByte(AXP202_INTSTS1 + i, 1, &_irq[i]); - } - return AXP_PASS; - default: - return AXP_FAIL; - } -} - -void AXP20X_Class::clearIRQ() -{ - uint8_t val = 0xFF; - switch (_chip_id) { - case AXP192_CHIP_ID: - for (int i = 0; i < 3; i++) { - _writeByte(AXP192_INTSTS1 + i, 1, &val); - } - _writeByte(AXP192_INTSTS5, 1, &val); - break; - case AXP202_CHIP_ID: - for (int i = 0; i < 5; i++) { - _writeByte(AXP202_INTSTS1 + i, 1, &val); - } - break; - default: - break; - } - memset(_irq, 0, sizeof(_irq)); -} - -bool AXP20X_Class::isAcinOverVoltageIRQ() -{ - return (bool)(_irq[0] & BIT_MASK(7)); -} - -bool AXP20X_Class::isAcinPlugInIRQ() -{ - return (bool)(_irq[0] & BIT_MASK(6)); -} - -bool AXP20X_Class::isAcinRemoveIRQ() -{ - return (bool)(_irq[0] & BIT_MASK(5)); -} - -bool AXP20X_Class::isVbusOverVoltageIRQ() -{ - return (bool)(_irq[0] & BIT_MASK(4)); -} - -bool AXP20X_Class::isVbusPlugInIRQ() -{ - return (bool)(_irq[0] & BIT_MASK(3)); -} - -bool AXP20X_Class::isVbusRemoveIRQ() -{ - return (bool)(_irq[0] & BIT_MASK(2)); -} - -bool AXP20X_Class::isVbusLowVHOLDIRQ() -{ - return (bool)(_irq[0] & BIT_MASK(1)); -} - -bool AXP20X_Class::isBattPlugInIRQ() -{ - return (bool)(_irq[1] & BIT_MASK(7)); -} -bool AXP20X_Class::isBattRemoveIRQ() -{ - return (bool)(_irq[1] & BIT_MASK(6)); -} -bool AXP20X_Class::isBattEnterActivateIRQ() -{ - return (bool)(_irq[1] & BIT_MASK(5)); -} -bool AXP20X_Class::isBattExitActivateIRQ() -{ - return (bool)(_irq[1] & BIT_MASK(4)); -} -bool AXP20X_Class::isChargingIRQ() -{ - return (bool)(_irq[1] & BIT_MASK(3)); -} -bool AXP20X_Class::isChargingDoneIRQ() -{ - return (bool)(_irq[1] & BIT_MASK(2)); -} -bool AXP20X_Class::isBattTempLowIRQ() -{ - return (bool)(_irq[1] & BIT_MASK(1)); -} -bool AXP20X_Class::isBattTempHighIRQ() -{ - return (bool)(_irq[1] & BIT_MASK(0)); -} - -bool AXP20X_Class::isPEKShortPressIRQ() -{ - return (bool)(_irq[2] & BIT_MASK(1)); -} - -bool AXP20X_Class::isPEKLongtPressIRQ() -{ - return (bool)(_irq[2] & BIT_MASK(0)); -} - -bool AXP20X_Class::isTimerTimeoutIRQ() -{ - return (bool)(_irq[4] & BIT_MASK(7)); -} - -bool AXP20X_Class::isVBUSPlug() -{ - if (!_init) - return AXP_NOT_INIT; - uint8_t reg; - _readByte(AXP202_STATUS, 1, ®); - return IS_OPEN(reg, 5); -} - -int AXP20X_Class::setDCDC2Voltage(uint16_t mv) -{ - if (!_init) - return AXP_NOT_INIT; - if (mv < 700) { - AXP_DEBUG("DCDC2:Below settable voltage:700mV~2275mV"); - mv = 700; - } - if (mv > 2275) { - AXP_DEBUG("DCDC2:Above settable voltage:700mV~2275mV"); - mv = 2275; - } - uint8_t val = (mv - 700) / 25; - //! axp173/192/202 same register - _writeByte(AXP202_DC2OUT_VOL, 1, &val); - return AXP_PASS; -} - -uint16_t AXP20X_Class::getDCDC2Voltage() -{ - uint8_t val = 0; - //! axp173/192/202 same register - _readByte(AXP202_DC2OUT_VOL, 1, &val); - return val * 25 + 700; -} - -uint16_t AXP20X_Class::getDCDC3Voltage() -{ - if (!_init) - return 0; - if (_chip_id == AXP173_CHIP_ID)return AXP_NOT_SUPPORT; - uint8_t val = 0; - _readByte(AXP202_DC3OUT_VOL, 1, &val); - return val * 25 + 700; -} - -int AXP20X_Class::setDCDC3Voltage(uint16_t mv) -{ - if (!_init) - return AXP_NOT_INIT; - if (_chip_id == AXP173_CHIP_ID)return AXP_NOT_SUPPORT; - if (mv < 700) { - AXP_DEBUG("DCDC3:Below settable voltage:700mV~3500mV"); - mv = 700; - } - if (mv > 3500) { - AXP_DEBUG("DCDC3:Above settable voltage:700mV~3500mV"); - mv = 3500; - } - uint8_t val = (mv - 700) / 25; - _writeByte(AXP202_DC3OUT_VOL, 1, &val); - return AXP_PASS; -} - -int AXP20X_Class::setLDO2Voltage(uint16_t mv) -{ - uint8_t rVal, wVal; - if (!_init) - return AXP_NOT_INIT; - if (mv < 1800) { - AXP_DEBUG("LDO2:Below settable voltage:1800mV~3300mV"); - mv = 1800; - } - if (mv > 3300) { - AXP_DEBUG("LDO2:Above settable voltage:1800mV~3300mV"); - mv = 3300; - } - wVal = (mv - 1800) / 100; - if (_chip_id == AXP202_CHIP_ID) { - _readByte(AXP202_LDO24OUT_VOL, 1, &rVal); - rVal &= 0x0F; - rVal |= (wVal << 4); - _writeByte(AXP202_LDO24OUT_VOL, 1, &rVal); - return AXP_PASS; - } else if (_chip_id == AXP192_CHIP_ID || _chip_id == AXP173_CHIP_ID) { - _readByte(AXP192_LDO23OUT_VOL, 1, &rVal); - rVal &= 0x0F; - rVal |= (wVal << 4); - _writeByte(AXP192_LDO23OUT_VOL, 1, &rVal); - return AXP_PASS; - } - return AXP_FAIL; -} - -uint16_t AXP20X_Class::getLDO2Voltage() -{ - uint8_t rVal; - if (_chip_id == AXP202_CHIP_ID) { - _readByte(AXP202_LDO24OUT_VOL, 1, &rVal); - rVal &= 0xF0; - rVal >>= 4; - return rVal * 100 + 1800; - } else if (_chip_id == AXP192_CHIP_ID || _chip_id == AXP173_CHIP_ID ) { - _readByte(AXP192_LDO23OUT_VOL, 1, &rVal); - AXP_DEBUG("get result:%x\n", rVal); - rVal &= 0xF0; - rVal >>= 4; - return rVal * 100 + 1800; - } - return 0; -} - -int AXP20X_Class::setLDO3Voltage(uint16_t mv) -{ - uint8_t rVal; - if (!_init) - return AXP_NOT_INIT; - if (_chip_id == AXP202_CHIP_ID && mv < 700) { - AXP_DEBUG("LDO3:Below settable voltage:700mV~3500mV"); - mv = 700; - } else if (_chip_id == AXP192_CHIP_ID && mv < 1800) { - AXP_DEBUG("LDO3:Below settable voltage:1800mV~3300mV"); - mv = 1800; - } - - if (_chip_id == AXP202_CHIP_ID && mv > 3500) { - AXP_DEBUG("LDO3:Above settable voltage:700mV~3500mV"); - mv = 3500; - } else if (_chip_id == AXP192_CHIP_ID && mv > 3300) { - AXP_DEBUG("LDO3:Above settable voltage:1800mV~3300mV"); - mv = 3300; - } - - if (_chip_id == AXP202_CHIP_ID) { - _readByte(AXP202_LDO3OUT_VOL, 1, &rVal); - rVal &= 0x80; - rVal |= ((mv - 700) / 25); - _writeByte(AXP202_LDO3OUT_VOL, 1, &rVal); - return AXP_PASS; - } else if (_chip_id == AXP192_CHIP_ID || _chip_id == AXP173_CHIP_ID) { - _readByte(AXP192_LDO23OUT_VOL, 1, &rVal); - rVal &= 0xF0; - rVal |= ((mv - 1800) / 100); - _writeByte(AXP192_LDO23OUT_VOL, 1, &rVal); - return AXP_PASS; - } - return AXP_FAIL; -} - -uint16_t AXP20X_Class::getLDO3Voltage() -{ - uint8_t rVal; - if (!_init) - return AXP_NOT_INIT; - - if (_chip_id == AXP202_CHIP_ID) { - _readByte(AXP202_LDO3OUT_VOL, 1, &rVal); - if (rVal & 0x80) { - //! According to the hardware N_VBUSEN Pin selection - return getVbusVoltage() * 1000; - } else { - return (rVal & 0x7F) * 25 + 700; - } - } else if (_chip_id == AXP192_CHIP_ID || _chip_id == AXP173_CHIP_ID) { - _readByte(AXP192_LDO23OUT_VOL, 1, &rVal); - rVal &= 0x0F; - return rVal * 100 + 1800; - } - return 0; -} - -//! Only axp173 support -int AXP20X_Class::setLDO4Voltage(uint16_t mv) -{ - if (!_init) - return AXP_NOT_INIT; - if (_chip_id != AXP173_CHIP_ID) - return AXP_FAIL; - - if (mv < 700) { - AXP_DEBUG("LDO4:Below settable voltage:700mV~3500mV"); - mv = 700; - } - if (mv > 3500) { - AXP_DEBUG("LDO4:Above settable voltage:700mV~3500mV"); - mv = 3500; - } - uint8_t val = (mv - 700) / 25; - _writeByte(AXP173_LDO4_VLOTAGE, 1, &val); - return AXP_PASS; -} - -uint16_t AXP20X_Class::getLDO4Voltage() -{ - const uint16_t ldo4_table[] = {1250, 1300, 1400, 1500, 1600, 1700, 1800, 1900, 2000, 2500, 2700, 2800, 3000, 3100, 3200, 3300}; - if (!_init) - return 0; - uint8_t val = 0; - switch (_chip_id) { - case AXP173_CHIP_ID: - _readByte(AXP173_LDO4_VLOTAGE, 1, &val); - return val * 25 + 700; - case AXP202_CHIP_ID: - _readByte(AXP202_LDO24OUT_VOL, 1, &val); - val &= 0xF; - return ldo4_table[val]; - break; - case AXP192_CHIP_ID: - default: - break; - } - return 0; -} - - -//! Only axp202 support -int AXP20X_Class::setLDO4Voltage(axp_ldo4_table_t param) -{ - if (!_init) - return AXP_NOT_INIT; - if (_chip_id == AXP202_CHIP_ID) { - if (param >= AXP202_LDO4_MAX) - return AXP_INVALID; - uint8_t val; - _readByte(AXP202_LDO24OUT_VOL, 1, &val); - val &= 0xF0; - val |= param; - _writeByte(AXP202_LDO24OUT_VOL, 1, &val); - return AXP_PASS; - } - return AXP_FAIL; -} - -//! Only AXP202 support -// 0 : LDO 1 : DCIN -int AXP20X_Class::setLDO3Mode(uint8_t mode) -{ - uint8_t val; - if (_chip_id != AXP202_CHIP_ID) - return AXP_FAIL; - _readByte(AXP202_LDO3OUT_VOL, 1, &val); - if (mode) { - val |= BIT_MASK(7); - } else { - val &= (~BIT_MASK(7)); - } - _writeByte(AXP202_LDO3OUT_VOL, 1, &val); - return AXP_PASS; -} - -int AXP20X_Class::setStartupTime(uint8_t param) -{ - uint8_t val; - if (!_init) - return AXP_NOT_INIT; - if (param > sizeof(startupParams) / sizeof(startupParams[0])) - return AXP_INVALID; - _readByte(AXP202_POK_SET, 1, &val); - val &= (~0b11000000); - val |= startupParams[param]; - _writeByte(AXP202_POK_SET, 1, &val); - return AXP_PASS; -} - -int AXP20X_Class::setlongPressTime(uint8_t param) -{ - uint8_t val; - if (!_init) - return AXP_NOT_INIT; - if (param > sizeof(longPressParams) / sizeof(longPressParams[0])) - return AXP_INVALID; - _readByte(AXP202_POK_SET, 1, &val); - val &= (~0b00110000); - val |= longPressParams[param]; - _writeByte(AXP202_POK_SET, 1, &val); - return AXP_PASS; -} - -int AXP20X_Class::setShutdownTime(uint8_t param) -{ - uint8_t val; - if (!_init) - return AXP_NOT_INIT; - if (param > sizeof(shutdownParams) / sizeof(shutdownParams[0])) - return AXP_INVALID; - _readByte(AXP202_POK_SET, 1, &val); - val &= (~0b00000011); - val |= shutdownParams[param]; - _writeByte(AXP202_POK_SET, 1, &val); - return AXP_PASS; -} - -int AXP20X_Class::setTimeOutShutdown(bool en) -{ - uint8_t val; - if (!_init) - return AXP_NOT_INIT; - _readByte(AXP202_POK_SET, 1, &val); - if (en) - val |= (1 << 3); - else - val &= (~(1 << 3)); - _writeByte(AXP202_POK_SET, 1, &val); - return AXP_PASS; -} - -int AXP20X_Class::shutdown() -{ - uint8_t val; - if (!_init) - return AXP_NOT_INIT; - _readByte(AXP202_OFF_CTL, 1, &val); - val |= (1 << 7); - _writeByte(AXP202_OFF_CTL, 1, &val); - return AXP_PASS; -} - -float AXP20X_Class::getSettingChargeCurrent() -{ - uint8_t val; - if (!_init) - return AXP_NOT_INIT; - _readByte(AXP202_CHARGE1, 1, &val); - val &= 0b00000111; - float cur = 300.0 + val * 100.0; - AXP_DEBUG("Setting Charge current : %.2f mA\n", cur); - return cur; -} - -bool AXP20X_Class::isChargeingEnable() -{ - uint8_t val; - if (!_init) - return false; - _readByte(AXP202_CHARGE1, 1, &val); - if (val & (1 << 7)) { - AXP_DEBUG("Charging enable is enable\n"); - val = true; - } else { - AXP_DEBUG("Charging enable is disable\n"); - val = false; - } - return val; -} - -int AXP20X_Class::enableChargeing(bool en) -{ - uint8_t val; - if (!_init) - return AXP_NOT_INIT; - _readByte(AXP202_CHARGE1, 1, &val); - val |= (1 << 7); - _writeByte(AXP202_CHARGE1, 1, &val); - return AXP_PASS; -} - -int AXP20X_Class::setChargingTargetVoltage(axp_chargeing_vol_t param) -{ - uint8_t val; - if (!_init) - return AXP_NOT_INIT; - if (param > sizeof(targetVolParams) / sizeof(targetVolParams[0])) - return AXP_INVALID; - _readByte(AXP202_CHARGE1, 1, &val); - val &= ~(0b01100000); - val |= targetVolParams[param]; - _writeByte(AXP202_CHARGE1, 1, &val); - return AXP_PASS; -} - -int AXP20X_Class::getBattPercentage() -{ - if (!_init) - return AXP_NOT_INIT; - if (_chip_id != AXP202_CHIP_ID) - return AXP_NOT_SUPPORT; - uint8_t val; - if (!isBatteryConnect()) - return 0; - _readByte(AXP202_BATT_PERCENTAGE, 1, &val); - if (!(val & BIT_MASK(7))) { - return val & (~BIT_MASK(7)); - } - return 0; -} - -int AXP20X_Class::setChgLEDMode(axp_chgled_mode_t mode) -{ - uint8_t val; - _readByte(AXP202_OFF_CTL, 1, &val); - val &= 0b11001111; - val |= BIT_MASK(3); - switch (mode) { - case AXP20X_LED_OFF: - _writeByte(AXP202_OFF_CTL, 1, &val); - break; - case AXP20X_LED_BLINK_1HZ: - val |= 0b00010000; - _writeByte(AXP202_OFF_CTL, 1, &val); - break; - case AXP20X_LED_BLINK_4HZ: - val |= 0b00100000; - _writeByte(AXP202_OFF_CTL, 1, &val); - break; - case AXP20X_LED_LOW_LEVEL: - val |= 0b00110000; - _writeByte(AXP202_OFF_CTL, 1, &val); - break; - default: - return AXP_FAIL; - } - return AXP_PASS; -} - -int AXP20X_Class::debugCharging() -{ - uint8_t val; - _readByte(AXP202_CHARGE1, 1, &val); - AXP_DEBUG("SRC REG:0x%x\n", val); - if (val & (1 << 7)) { - AXP_DEBUG("Charging enable is enable\n"); - } else { - AXP_DEBUG("Charging enable is disable\n"); - } - AXP_DEBUG("Charging target-voltage : 0x%x\n", ((val & 0b01100000) >> 5) & 0b11); - if (val & (1 << 4)) { - AXP_DEBUG("end when the charge current is lower than 15%% of the set value\n"); - } else { - AXP_DEBUG(" end when the charge current is lower than 10%% of the set value\n"); - } - val &= 0b00000111; - AXP_DEBUG("Charge current : %.2f mA\n", 300.0 + val * 100.0); - return AXP_PASS; -} - -int AXP20X_Class::debugStatus() -{ - if (!_init) - return AXP_NOT_INIT; - uint8_t val, val1, val2; - _readByte(AXP202_STATUS, 1, &val); - _readByte(AXP202_MODE_CHGSTATUS, 1, &val1); - _readByte(AXP202_IPS_SET, 1, &val2); - AXP_DEBUG("AXP202_STATUS: AXP202_MODE_CHGSTATUS AXP202_IPS_SET\n"); - AXP_DEBUG("0x%x\t\t\t 0x%x\t\t\t 0x%x\n", val, val1, val2); - return AXP_PASS; -} - -int AXP20X_Class::limitingOff() -{ - if (!_init) - return AXP_NOT_INIT; - uint8_t val; - _readByte(AXP202_IPS_SET, 1, &val); - if (_chip_id == AXP202_CHIP_ID) { - val |= 0x03; - } else { - val &= ~(1 << 1); - } - _writeByte(AXP202_IPS_SET, 1, &val); - return AXP_PASS; -} - -// Only AXP129 chip and AXP173 -int AXP20X_Class::setDCDC1Voltage(uint16_t mv) -{ - if (!_init) - return AXP_NOT_INIT; - if (_chip_id != AXP192_CHIP_ID && _chip_id != AXP173_CHIP_ID) - return AXP_FAIL; - if (mv < 700) { - AXP_DEBUG("DCDC1:Below settable voltage:700mV~3500mV"); - mv = 700; - } - if (mv > 3500) { - AXP_DEBUG("DCDC1:Above settable voltage:700mV~3500mV"); - mv = 3500; - } - uint8_t val = (mv - 700) / 25; - //! axp192 and axp173 dc1 control register same - _writeByte(AXP192_DC1_VLOTAGE, 1, &val); - return AXP_PASS; -} - -// Only AXP129 chip and AXP173 -uint16_t AXP20X_Class::getDCDC1Voltage() -{ - if (_chip_id != AXP192_CHIP_ID && _chip_id != AXP173_CHIP_ID) - return AXP_FAIL; - uint8_t val = 0; - //! axp192 and axp173 dc1 control register same - _readByte(AXP192_DC1_VLOTAGE, 1, &val); - return val * 25 + 700; -} - - -/*********************************************** - * !!! TIMER FUNCTION !!! - * *********************************************/ - -int AXP20X_Class::setTimer(uint8_t minutes) -{ - if (!_init) - return AXP_NOT_INIT; - if (_chip_id == AXP202_CHIP_ID) { - if (minutes > 63) { - return AXP_ARG_INVALID; - } - _writeByte(AXP202_TIMER_CTL, 1, &minutes); - return AXP_PASS; - } - return AXP_NOT_SUPPORT; -} - -int AXP20X_Class::offTimer() -{ - if (!_init) - return AXP_NOT_INIT; - if (_chip_id == AXP202_CHIP_ID) { - uint8_t minutes = 0x80; - _writeByte(AXP202_TIMER_CTL, 1, &minutes); - return AXP_PASS; - } - return AXP_NOT_SUPPORT; -} - -int AXP20X_Class::clearTimerStatus() -{ - if (!_init) - return AXP_NOT_INIT; - if (_chip_id == AXP202_CHIP_ID) { - uint8_t val; - _readByte(AXP202_TIMER_CTL, 1, &val); - val |= 0x80; - _writeByte(AXP202_TIMER_CTL, 1, &val); - return AXP_PASS; - } - return AXP_NOT_SUPPORT; -} - -/*********************************************** - * !!! GPIO FUNCTION !!! - * *********************************************/ - -int AXP20X_Class::_axp192_gpio_0_select( axp_gpio_mode_t mode) -{ - switch (mode) { - case AXP_IO_OUTPUT_LOW_MODE: - return 0b101; - case AXP_IO_INPUT_MODE: - return 0b001; - case AXP_IO_LDO_MODE: - return 0b010; - case AXP_IO_ADC_MODE: - return 0b100; - case AXP_IO_FLOATING_MODE: - return 0b111; - case AXP_IO_OPEN_DRAIN_OUTPUT_MODE: - return 0; - case AXP_IO_OUTPUT_HIGH_MODE: - case AXP_IO_PWM_OUTPUT_MODE: - default: - break; - } - return AXP_NOT_SUPPORT; -} - -int AXP20X_Class::_axp192_gpio_1_select( axp_gpio_mode_t mode) -{ - switch (mode) { - case AXP_IO_OUTPUT_LOW_MODE: - return 0b101; - case AXP_IO_INPUT_MODE: - return 0b001; - case AXP_IO_ADC_MODE: - return 0b100; - case AXP_IO_FLOATING_MODE: - return 0b111; - case AXP_IO_OPEN_DRAIN_OUTPUT_MODE: - return 0; - case AXP_IO_PWM_OUTPUT_MODE: - return 0b010; - case AXP_IO_OUTPUT_HIGH_MODE: - case AXP_IO_LDO_MODE: - default: - break; - } - return AXP_NOT_SUPPORT; -} - - -int AXP20X_Class::_axp192_gpio_3_select( axp_gpio_mode_t mode) -{ - switch (mode) { - case AXP_IO_EXTERN_CHARGING_CTRL_MODE: - return 0; - case AXP_IO_OPEN_DRAIN_OUTPUT_MODE: - return 1; - case AXP_IO_INPUT_MODE: - return 2; - default: - break; - } - return AXP_NOT_SUPPORT; -} - -int AXP20X_Class::_axp192_gpio_4_select( axp_gpio_mode_t mode) -{ - switch (mode) { - case AXP_IO_EXTERN_CHARGING_CTRL_MODE: - return 0; - case AXP_IO_OPEN_DRAIN_OUTPUT_MODE: - return 1; - case AXP_IO_INPUT_MODE: - return 2; - case AXP_IO_ADC_MODE: - return 3; - default: - break; - } - return AXP_NOT_SUPPORT; -} - - -int AXP20X_Class::_axp192_gpio_set(axp_gpio_t gpio, axp_gpio_mode_t mode) -{ - int rslt; - uint8_t val; - switch (gpio) { - case AXP_GPIO_0: { - rslt = _axp192_gpio_0_select(mode); - if (rslt < 0)return rslt; - _readByte(AXP192_GPIO0_CTL, 1, &val); - val &= 0xF8; - val |= (uint8_t)rslt; - _writeByte(AXP192_GPIO0_CTL, 1, &val); - return AXP_PASS; - } - case AXP_GPIO_1: { - rslt = _axp192_gpio_1_select(mode); - if (rslt < 0)return rslt; - _readByte(AXP192_GPIO1_CTL, 1, &val); - val &= 0xF8; - val |= (uint8_t)rslt; - _writeByte(AXP192_GPIO1_CTL, 1, &val); - return AXP_PASS; - } - case AXP_GPIO_2: { - rslt = _axp192_gpio_1_select(mode); - if (rslt < 0)return rslt; - _readByte(AXP192_GPIO2_CTL, 1, &val); - val &= 0xF8; - val |= (uint8_t)rslt; - _writeByte(AXP192_GPIO2_CTL, 1, &val); - return AXP_PASS; - } - case AXP_GPIO_3: { - rslt = _axp192_gpio_3_select(mode); - if (rslt < 0)return rslt; - _readByte(AXP192_GPIO34_CTL, 1, &val); - val &= 0xFC; - val |= (uint8_t)rslt; - _writeByte(AXP192_GPIO34_CTL, 1, &val); - return AXP_PASS; - } - case AXP_GPIO_4: { - rslt = _axp192_gpio_4_select(mode); - if (rslt < 0)return rslt; - _readByte(AXP192_GPIO34_CTL, 1, &val); - val &= 0xF3; - val |= (uint8_t)rslt; - _writeByte(AXP192_GPIO34_CTL, 1, &val); - return AXP_PASS; - } - default: - break; - } - return AXP_NOT_SUPPORT; -} - -int AXP20X_Class::_axp202_gpio_0_select( axp_gpio_mode_t mode) -{ - switch (mode) { - case AXP_IO_OUTPUT_LOW_MODE: - return 0; - case AXP_IO_OUTPUT_HIGH_MODE: - return 1; - case AXP_IO_INPUT_MODE: - return 2; - case AXP_IO_LDO_MODE: - return 3; - case AXP_IO_ADC_MODE: - return 4; - default: - break; - } - return AXP_NOT_SUPPORT; -} - -int AXP20X_Class::_axp202_gpio_1_select( axp_gpio_mode_t mode) -{ - switch (mode) { - case AXP_IO_OUTPUT_LOW_MODE: - return 0; - case AXP_IO_OUTPUT_HIGH_MODE: - return 1; - case AXP_IO_INPUT_MODE: - return 2; - case AXP_IO_ADC_MODE: - return 4; - default: - break; - } - return AXP_NOT_SUPPORT; -} - -int AXP20X_Class::_axp202_gpio_2_select( axp_gpio_mode_t mode) -{ - switch (mode) { - case AXP_IO_OUTPUT_LOW_MODE: - return 0; - case AXP_IO_INPUT_MODE: - return 2; - case AXP_IO_FLOATING_MODE: - return 1; - default: - break; - } - return AXP_NOT_SUPPORT; -} - - -int AXP20X_Class::_axp202_gpio_3_select(axp_gpio_mode_t mode) -{ - switch (mode) { - case AXP_IO_INPUT_MODE: - return 1; - case AXP_IO_OPEN_DRAIN_OUTPUT_MODE: - return 0; - default: - break; - } - return AXP_NOT_SUPPORT; -} - -int AXP20X_Class::_axp202_gpio_set(axp_gpio_t gpio, axp_gpio_mode_t mode) -{ - uint8_t val; - int rslt; - switch (gpio) { - case AXP_GPIO_0: { - rslt = _axp202_gpio_0_select(mode); - if (rslt < 0)return rslt; - _readByte(AXP202_GPIO0_CTL, 1, &val); - val &= 0b11111000; - val |= (uint8_t)rslt; - _writeByte(AXP202_GPIO0_CTL, 1, &val); - return AXP_PASS; - } - case AXP_GPIO_1: { - rslt = _axp202_gpio_1_select(mode); - if (rslt < 0)return rslt; - _readByte(AXP202_GPIO1_CTL, 1, &val); - val &= 0b11111000; - val |= (uint8_t)rslt; - _writeByte(AXP202_GPIO1_CTL, 1, &val); - return AXP_PASS; - } - case AXP_GPIO_2: { - rslt = _axp202_gpio_2_select(mode); - if (rslt < 0)return rslt; - _readByte(AXP202_GPIO2_CTL, 1, &val); - val &= 0b11111000; - val |= (uint8_t)rslt; - _writeByte(AXP202_GPIO2_CTL, 1, &val); - return AXP_PASS; - } - case AXP_GPIO_3: { - rslt = _axp202_gpio_3_select(mode); - if (rslt < 0)return rslt; - _readByte(AXP202_GPIO3_CTL, 1, &val); - val = rslt ? (val | BIT_MASK(2)) : (val & (~BIT_MASK(2))); - _writeByte(AXP202_GPIO3_CTL, 1, &val); - return AXP_PASS; - } - default: - break; - } - return AXP_NOT_SUPPORT; -} - - -int AXP20X_Class::setGPIOMode(axp_gpio_t gpio, axp_gpio_mode_t mode) -{ - if (!_init) - return AXP_NOT_INIT; - switch (_chip_id) { - case AXP202_CHIP_ID: - return _axp202_gpio_set(gpio, mode); - break; - case AXP192_CHIP_ID: - return _axp192_gpio_set(gpio, mode); - break; - default: - break; - } - return AXP_NOT_SUPPORT; -} - - -int AXP20X_Class::_axp_irq_mask(axp_gpio_irq_t irq) -{ - switch (irq) { - case AXP_IRQ_NONE: - return 0; - case AXP_IRQ_RISING: - return BIT_MASK(7); - case AXP_IRQ_FALLING: - return BIT_MASK(6); - case AXP_IRQ_DOUBLE_EDGE: - return 0b1100000; - default: - break; - } - return AXP_NOT_SUPPORT; -} - -int AXP20X_Class::_axp202_gpio_irq_set(axp_gpio_t gpio, axp_gpio_irq_t irq) -{ - uint8_t reg; - uint8_t val; - int mask; - mask = _axp_irq_mask(irq); - - if (mask < 0)return mask; - switch (gpio) { - case AXP_GPIO_0: - reg = AXP202_GPIO0_CTL; - break; - case AXP_GPIO_1: - reg = AXP202_GPIO1_CTL; - break; - case AXP_GPIO_2: - reg = AXP202_GPIO2_CTL; - break; - case AXP_GPIO_3: - reg = AXP202_GPIO3_CTL; - break; - default: - return AXP_NOT_SUPPORT; - } - _readByte(reg, 1, &val); - val = mask == 0 ? (val & 0b00111111) : (val | mask); - _writeByte(reg, 1, &val); - return AXP_PASS; -} - - -int AXP20X_Class::setGPIOIrq(axp_gpio_t gpio, axp_gpio_irq_t irq) -{ - if (!_init) - return AXP_NOT_INIT; - switch (_chip_id) { - case AXP202_CHIP_ID: - return _axp202_gpio_irq_set(gpio, irq); - case AXP192_CHIP_ID: - case AXP173_CHIP_ID: - return AXP_NOT_SUPPORT; - default: - break; - } - return AXP_NOT_SUPPORT; -} - -int AXP20X_Class::setLDO5Voltage(axp_ldo5_table_t vol) -{ - const uint8_t params[] = { - 0b11111000, //1.8V - 0b11111001, //2.5V - 0b11111010, //2.8V - 0b11111011, //3.0V - 0b11111100, //3.1V - 0b11111101, //3.3V - 0b11111110, //3.4V - 0b11111111, //3.5V - }; - if (!_init) - return AXP_NOT_INIT; - if (_chip_id != AXP202_CHIP_ID) - return AXP_NOT_SUPPORT; - if (vol > sizeof(params) / sizeof(params[0])) - return AXP_ARG_INVALID; - uint8_t val = 0; - _readByte(AXP202_GPIO0_VOL, 1, &val); - val &= 0b11111000; - val |= params[vol]; - _writeByte(AXP202_GPIO0_VOL, 1, &val); - return AXP_PASS; -} - - -int AXP20X_Class::_axp202_gpio_write(axp_gpio_t gpio, uint8_t val) -{ - uint8_t reg; - uint8_t wVal = 0; - switch (gpio) { - case AXP_GPIO_0: - reg = AXP202_GPIO0_CTL; - break; - case AXP_GPIO_1: - reg = AXP202_GPIO1_CTL; - break; - case AXP_GPIO_2: - reg = AXP202_GPIO2_CTL; - if (val) { - return AXP_NOT_SUPPORT; - } - break; - case AXP_GPIO_3: - if (val) { - return AXP_NOT_SUPPORT; - } - _readByte(AXP202_GPIO3_CTL, 1, &wVal); - wVal &= 0b11111101; - _writeByte(AXP202_GPIO3_CTL, 1, &wVal); - return AXP_PASS; - default: - return AXP_NOT_SUPPORT; - } - _readByte(reg, 1, &wVal); - wVal = val ? (wVal | 1) : (wVal & 0b11111000); - _writeByte(reg, 1, &wVal); - return AXP_PASS; -} - -int AXP20X_Class::_axp202_gpio_read(axp_gpio_t gpio) -{ - uint8_t val; - uint8_t reg = AXP202_GPIO012_SIGNAL; - uint8_t offset; - switch (gpio) { - case AXP_GPIO_0: - offset = 4; - break; - case AXP_GPIO_1: - offset = 5; - break; - case AXP_GPIO_2: - offset = 6; - break; - case AXP_GPIO_3: - reg = AXP202_GPIO3_CTL; - offset = 0; - break; - default: - return AXP_NOT_SUPPORT; - } - _readByte(reg, 1, &val); - return val & BIT_MASK(offset) ? 1 : 0; -} - -int AXP20X_Class::gpioWrite(axp_gpio_t gpio, uint8_t val) -{ - if (!_init) - return AXP_NOT_INIT; - switch (_chip_id) { - case AXP202_CHIP_ID: - return _axp202_gpio_write(gpio, val); - case AXP192_CHIP_ID: - case AXP173_CHIP_ID: - return AXP_NOT_SUPPORT; - default: - break; - } - return AXP_NOT_SUPPORT; -} - -int AXP20X_Class::gpioRead(axp_gpio_t gpio) -{ - if (!_init) - return AXP_NOT_INIT; - switch (_chip_id) { - case AXP202_CHIP_ID: - return _axp202_gpio_read(gpio); - case AXP192_CHIP_ID: - case AXP173_CHIP_ID: - return AXP_NOT_SUPPORT; - default: - break; - } - return AXP_NOT_SUPPORT; -} - - - -int AXP20X_Class::getChargeControlCur() -{ - int cur; - uint8_t val; - if (!_init) - return AXP_NOT_INIT; - switch (_chip_id) { - case AXP202_CHIP_ID: - _readByte(AXP202_CHARGE1, 1, &val); - val &= 0x0F; - cur = val * 100 + 300; - if (cur > 1800 || cur < 300)return 0; - return cur; - case AXP192_CHIP_ID: - case AXP173_CHIP_ID: - _readByte(AXP202_CHARGE1, 1, &val); - return val & 0x0F; - default: - break; - } - return AXP_NOT_SUPPORT; -} - -int AXP20X_Class::setChargeControlCur(uint16_t mA) -{ - uint8_t val; - if (!_init) - return AXP_NOT_INIT; - switch (_chip_id) { - case AXP202_CHIP_ID: - _readByte(AXP202_CHARGE1, 1, &val); - val &= 0b11110000; - mA -= 300; - val |= (mA / 100); - _writeByte(AXP202_CHARGE1, 1, &val); - return AXP_PASS; - case AXP192_CHIP_ID: - case AXP173_CHIP_ID: - _readByte(AXP202_CHARGE1, 1, &val); - val &= 0b11110000; - if(mA > AXP1XX_CHARGE_CUR_1320MA) - mA = AXP1XX_CHARGE_CUR_1320MA; - val |= mA; - _writeByte(AXP202_CHARGE1, 1, &val); - return AXP_PASS; - default: - break; - } - return AXP_NOT_SUPPORT; -} - +///////////////////////////////////////////////////////////////// +/* +MIT License + +Copyright (c) 2019 lewis he + +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. + +axp20x.cpp - Arduino library for X-Power AXP202 chip. +Created by Lewis he on April 1, 2019. +github:https://github.com/lewisxhe/AXP202X_Libraries +*/ +///////////////////////////////////////////////////////////////// + +#include "axp20x.h" +#include + +const uint8_t AXP20X_Class::startupParams[] = { + 0b00000000, + 0b01000000, + 0b10000000, + 0b11000000 +}; + +const uint8_t AXP20X_Class::longPressParams[] = { + 0b00000000, + 0b00010000, + 0b00100000, + 0b00110000 +}; + +const uint8_t AXP20X_Class::shutdownParams[] = { + 0b00000000, + 0b00000001, + 0b00000010, + 0b00000011 +}; + +const uint8_t AXP20X_Class::targetVolParams[] = { + 0b00000000, + 0b00100000, + 0b01000000, + 0b01100000 +}; + + + +// Power Output Control register +uint8_t AXP20X_Class::_outputReg; + +int AXP20X_Class::_axp_probe() +{ + uint8_t data; + if (_isAxp173) { + //!Axp173 does not have a chip ID, read the status register to see if it reads normally + _readByte(0x01, 1, &data); + if (data == 0 || data == 0xFF) { + return AXP_FAIL; + } + _chip_id = AXP173_CHIP_ID; + _readByte(AXP202_LDO234_DC23_CTL, 1, &_outputReg); + AXP_DEBUG("OUTPUT Register 0x%x\n", _outputReg); + _init = true; + return AXP_PASS; + } + _readByte(AXP202_IC_TYPE, 1, &_chip_id); + AXP_DEBUG("chip id detect 0x%x\n", _chip_id); + if (_chip_id == AXP202_CHIP_ID || _chip_id == AXP192_CHIP_ID) { + AXP_DEBUG("Detect CHIP :%s\n", _chip_id == AXP202_CHIP_ID ? "AXP202" : "AXP192"); + _readByte(AXP202_LDO234_DC23_CTL, 1, &_outputReg); + AXP_DEBUG("OUTPUT Register 0x%x\n", _outputReg); + _init = true; + return AXP_PASS; + } + return AXP_FAIL; +} + +int AXP20X_Class::begin(TwoWire &port, uint8_t addr, bool isAxp173) +{ + _i2cPort = &port; //Grab which port the user wants us to use + _address = addr; + _isAxp173 = isAxp173; + + return _axp_probe(); +} + +int AXP20X_Class::begin(axp_com_fptr_t read_cb, axp_com_fptr_t write_cb, uint8_t addr, bool isAxp173) +{ + if (read_cb == nullptr || write_cb == nullptr)return AXP_FAIL; + _read_cb = read_cb; + _write_cb = write_cb; + _address = addr; + _isAxp173 = isAxp173; + return _axp_probe(); +} + +//Only axp192 chip +bool AXP20X_Class::isDCDC1Enable() +{ + if (_chip_id == AXP192_CHIP_ID) + return IS_OPEN(_outputReg, AXP192_DCDC1); + else if (_chip_id == AXP173_CHIP_ID) + return IS_OPEN(_outputReg, AXP173_DCDC1); + return false; +} + +bool AXP20X_Class::isExtenEnable() +{ + if (_chip_id == AXP192_CHIP_ID) + return IS_OPEN(_outputReg, AXP192_EXTEN); + else if (_chip_id == AXP202_CHIP_ID) + return IS_OPEN(_outputReg, AXP202_EXTEN); + else if (_chip_id == AXP173_CHIP_ID) { + uint8_t data; + _readByte(AXP173_EXTEN_DC2_CTL, 1, &data); + return IS_OPEN(data, AXP173_CTL_EXTEN_BIT); + } + return false; +} + +bool AXP20X_Class::isLDO2Enable() +{ + if (_chip_id == AXP173_CHIP_ID) { + return IS_OPEN(_outputReg, AXP173_LDO2); + } + //axp192 same axp202 ldo2 bit + return IS_OPEN(_outputReg, AXP202_LDO2); +} + +bool AXP20X_Class::isLDO3Enable() +{ + if (_chip_id == AXP192_CHIP_ID) + return IS_OPEN(_outputReg, AXP192_LDO3); + else if (_chip_id == AXP202_CHIP_ID) + return IS_OPEN(_outputReg, AXP202_LDO3); + else if (_chip_id == AXP173_CHIP_ID) + return IS_OPEN(_outputReg, AXP173_LDO3); + return false; +} + +bool AXP20X_Class::isLDO4Enable() +{ + if (_chip_id == AXP202_CHIP_ID) + return IS_OPEN(_outputReg, AXP202_LDO4); + if (_chip_id == AXP173_CHIP_ID) + return IS_OPEN(_outputReg, AXP173_LDO4); + return false; +} + +bool AXP20X_Class::isDCDC2Enable() +{ + if (_chip_id == AXP173_CHIP_ID) { + uint8_t data; + _readByte(AXP173_EXTEN_DC2_CTL, 1, &data); + return IS_OPEN(data, AXP173_CTL_DC2_BIT); + } + //axp192 same axp202 dc2 bit + return IS_OPEN(_outputReg, AXP202_DCDC2); +} + +bool AXP20X_Class::isDCDC3Enable() +{ + if (_chip_id == AXP173_CHIP_ID) + return false; + //axp192 same axp202 dc3 bit + return IS_OPEN(_outputReg, AXP202_DCDC3); +} + +int AXP20X_Class::setPowerOutPut(uint8_t ch, bool en) +{ + uint8_t data; + uint8_t val = 0; + if (!_init) + return AXP_NOT_INIT; + + //! Axp173 cannot use the REG12H register to control + //! DC2 and EXTEN. It is necessary to control REG10H separately. + if (_chip_id == AXP173_CHIP_ID) { + _readByte(AXP173_EXTEN_DC2_CTL, 1, &data); + if (ch & AXP173_DCDC2) { + data = en ? data | BIT_MASK(AXP173_CTL_DC2_BIT) : data & (~BIT_MASK(AXP173_CTL_DC2_BIT)); + ch &= (~BIT_MASK(AXP173_DCDC2)); + _writeByte(AXP173_EXTEN_DC2_CTL, 1, &data); + } else if (ch & AXP173_EXTEN) { + data = en ? data | BIT_MASK(AXP173_CTL_EXTEN_BIT) : data & (~BIT_MASK(AXP173_CTL_EXTEN_BIT)); + ch &= (~BIT_MASK(AXP173_EXTEN)); + _writeByte(AXP173_EXTEN_DC2_CTL, 1, &data); + } + } + + _readByte(AXP202_LDO234_DC23_CTL, 1, &data); + if (en) { + data |= (1 << ch); + } else { + data &= (~(1 << ch)); + } + + if (_chip_id == AXP202_CHIP_ID) { + FORCED_OPEN_DCDC3(data); //! Must be forced open in T-Watch + } + + _writeByte(AXP202_LDO234_DC23_CTL, 1, &data); + delay(1); + _readByte(AXP202_LDO234_DC23_CTL, 1, &val); + if (data == val) { + _outputReg = val; + return AXP_PASS; + } + return AXP_FAIL; +} + +bool AXP20X_Class::isChargeing() +{ + uint8_t reg; + if (!_init) + return AXP_NOT_INIT; + _readByte(AXP202_MODE_CHGSTATUS, 1, ®); + return IS_OPEN(reg, 6); +} + +bool AXP20X_Class::isBatteryConnect() +{ + uint8_t reg; + if (!_init) + return AXP_NOT_INIT; + _readByte(AXP202_MODE_CHGSTATUS, 1, ®); + return IS_OPEN(reg, 5); +} + +float AXP20X_Class::getAcinVoltage() +{ + if (!_init) + return AXP_NOT_INIT; + return _getRegistResult(AXP202_ACIN_VOL_H8, AXP202_ACIN_VOL_L4) * AXP202_ACIN_VOLTAGE_STEP; +} + +float AXP20X_Class::getAcinCurrent() +{ + if (!_init) + return AXP_NOT_INIT; + return _getRegistResult(AXP202_ACIN_CUR_H8, AXP202_ACIN_CUR_L4) * AXP202_ACIN_CUR_STEP; +} + +float AXP20X_Class::getVbusVoltage() +{ + if (!_init) + return AXP_NOT_INIT; + return _getRegistResult(AXP202_VBUS_VOL_H8, AXP202_VBUS_VOL_L4) * AXP202_VBUS_VOLTAGE_STEP; +} + +float AXP20X_Class::getVbusCurrent() +{ + if (!_init) + return AXP_NOT_INIT; + return _getRegistResult(AXP202_VBUS_CUR_H8, AXP202_VBUS_CUR_L4) * AXP202_VBUS_CUR_STEP; +} + +float AXP20X_Class::getTemp() +{ + if (!_init) + return AXP_NOT_INIT; + return _getRegistResult(AXP202_INTERNAL_TEMP_H8, AXP202_INTERNAL_TEMP_L4) * AXP202_INTERNAL_TEMP_STEP; +} + +float AXP20X_Class::getTSTemp() +{ + if (!_init) + return AXP_NOT_INIT; + return _getRegistResult(AXP202_TS_IN_H8, AXP202_TS_IN_L4) * AXP202_TS_PIN_OUT_STEP; +} + +float AXP20X_Class::getGPIO0Voltage() +{ + if (!_init) + return AXP_NOT_INIT; + return _getRegistResult(AXP202_GPIO0_VOL_ADC_H8, AXP202_GPIO0_VOL_ADC_L4) * AXP202_GPIO0_STEP; +} + +float AXP20X_Class::getGPIO1Voltage() +{ + if (!_init) + return AXP_NOT_INIT; + return _getRegistResult(AXP202_GPIO1_VOL_ADC_H8, AXP202_GPIO1_VOL_ADC_L4) * AXP202_GPIO1_STEP; +} + +/* +Note: the battery power formula: +Pbat =2* register value * Voltage LSB * Current LSB / 1000. +(Voltage LSB is 1.1mV; Current LSB is 0.5mA, and unit of calculation result is mW.) +*/ +float AXP20X_Class::getBattInpower() +{ + float rslt; + uint8_t hv, mv, lv; + if (!_init) + return AXP_NOT_INIT; + _readByte(AXP202_BAT_POWERH8, 1, &hv); + _readByte(AXP202_BAT_POWERM8, 1, &mv); + _readByte(AXP202_BAT_POWERL8, 1, &lv); + rslt = (hv << 16) | (mv << 8) | lv; + rslt = 2 * rslt * 1.1 * 0.5 / 1000; + return rslt; +} + +float AXP20X_Class::getBattVoltage() +{ + if (!_init) + return AXP_NOT_INIT; + return _getRegistResult(AXP202_BAT_AVERVOL_H8, AXP202_BAT_AVERVOL_L4) * AXP202_BATT_VOLTAGE_STEP; +} + +float AXP20X_Class::getBattChargeCurrent() +{ + if (!_init) + return AXP_NOT_INIT; + switch (_chip_id) { + case AXP202_CHIP_ID: + return _getRegistResult(AXP202_BAT_AVERCHGCUR_H8, AXP202_BAT_AVERCHGCUR_L4) * AXP202_BATT_CHARGE_CUR_STEP; + case AXP192_CHIP_ID: + return _getRegistH8L5(AXP202_BAT_AVERCHGCUR_H8, AXP202_BAT_AVERCHGCUR_L5) * AXP202_BATT_CHARGE_CUR_STEP; + default: + return AXP_FAIL; + } +} + +float AXP20X_Class::getBattDischargeCurrent() +{ + if (!_init) + return AXP_NOT_INIT; + return _getRegistH8L5(AXP202_BAT_AVERDISCHGCUR_H8, AXP202_BAT_AVERDISCHGCUR_L5) * AXP202_BATT_DISCHARGE_CUR_STEP; +} + +float AXP20X_Class::getSysIPSOUTVoltage() +{ + if (!_init) + return AXP_NOT_INIT; + return _getRegistResult(AXP202_APS_AVERVOL_H8, AXP202_APS_AVERVOL_L4); +} + +/* +Coulomb calculation formula: +C= 65536 * current LSB *(charge coulomb counter value - discharge coulomb counter value) / +3600 / ADC sample rate. Refer to REG84H setting for ADC sample rate;the current LSB is +0.5mA;unit of the calculation result is mAh. ) +*/ +uint32_t AXP20X_Class::getBattChargeCoulomb() +{ + uint8_t buffer[4]; + if (!_init) + return AXP_NOT_INIT; + _readByte(0xB0, 4, buffer); + return (buffer[0] << 24) + (buffer[1] << 16) + (buffer[2] << 8) + buffer[3]; +} + +uint32_t AXP20X_Class::getBattDischargeCoulomb() +{ + uint8_t buffer[4]; + if (!_init) + return AXP_NOT_INIT; + _readByte(0xB4, 4, buffer); + return (buffer[0] << 24) + (buffer[1] << 16) + (buffer[2] << 8) + buffer[3]; +} + +float AXP20X_Class::getCoulombData() +{ + if (!_init) + return AXP_NOT_INIT; + uint32_t charge = getBattChargeCoulomb(), discharge = getBattDischargeCoulomb(); + uint8_t rate = getAdcSamplingRate(); + float result = 65536.0 * 0.5 * (charge - discharge) / 3600.0 / rate; + return result; +} + + +//------------------------------------------------------- +// New Coulomb functions by MrFlexi +//------------------------------------------------------- + +uint8_t AXP20X_Class::getCoulombRegister() +{ + uint8_t buffer; + if (!_init) + return AXP_NOT_INIT; + _readByte(AXP202_COULOMB_CTL, 1, &buffer); + return buffer; +} + + +int AXP20X_Class::setCoulombRegister(uint8_t val) +{ + if (!_init) + return AXP_NOT_INIT; + _writeByte(AXP202_COULOMB_CTL, 1, &val); + return AXP_PASS; +} + + +int AXP20X_Class::EnableCoulombcounter(void) +{ + + if (!_init) + return AXP_NOT_INIT; + uint8_t val = 0x80; + _writeByte(AXP202_COULOMB_CTL, 1, &val); + return AXP_PASS; +} + +int AXP20X_Class::DisableCoulombcounter(void) +{ + + if (!_init) + return AXP_NOT_INIT; + uint8_t val = 0x00; + _writeByte(AXP202_COULOMB_CTL, 1, &val); + return AXP_PASS; +} + +int AXP20X_Class::StopCoulombcounter(void) +{ + + if (!_init) + return AXP_NOT_INIT; + uint8_t val = 0xB8; + _writeByte(AXP202_COULOMB_CTL, 1, &val); + return AXP_PASS; +} + + +int AXP20X_Class::ClearCoulombcounter(void) +{ + + if (!_init) + return AXP_NOT_INIT; + uint8_t val = 0xA0; + _writeByte(AXP202_COULOMB_CTL, 1, &val); + return AXP_PASS; +} + +//------------------------------------------------------- +// END +//------------------------------------------------------- + + + +uint8_t AXP20X_Class::getAdcSamplingRate() +{ + //axp192 same axp202 aregister address 0x84 + if (!_init) + return AXP_NOT_INIT; + uint8_t val; + _readByte(AXP202_ADC_SPEED, 1, &val); + return 25 * (int)pow(2, (val & 0xC0) >> 6); +} + +int AXP20X_Class::setAdcSamplingRate(axp_adc_sampling_rate_t rate) +{ + //axp192 same axp202 aregister address 0x84 + if (!_init) + return AXP_NOT_INIT; + if (rate > AXP_ADC_SAMPLING_RATE_200HZ) + return AXP_FAIL; + uint8_t val; + _readByte(AXP202_ADC_SPEED, 1, &val); + uint8_t rw = rate; + val &= 0x3F; + val |= (rw << 6); + _writeByte(AXP202_ADC_SPEED, 1, &val); + return AXP_PASS; +} + +int AXP20X_Class::setTSfunction(axp_ts_pin_function_t func) +{ + //axp192 same axp202 aregister address 0x84 + if (!_init) + return AXP_NOT_INIT; + if (func > AXP_TS_PIN_FUNCTION_ADC) + return AXP_FAIL; + uint8_t val; + _readByte(AXP202_ADC_SPEED, 1, &val); + uint8_t rw = func; + val &= 0xFA; + val |= (rw << 2); + _writeByte(AXP202_ADC_SPEED, 1, &val); + return AXP_PASS; +} + +int AXP20X_Class::setTScurrent(axp_ts_pin_current_t current) +{ + //axp192 same axp202 aregister address 0x84 + if (!_init) + return AXP_NOT_INIT; + if (current > AXP_TS_PIN_CURRENT_80UA) + return AXP_FAIL; + uint8_t val; + _readByte(AXP202_ADC_SPEED, 1, &val); + uint8_t rw = current; + val &= 0xCF; + val |= (rw << 4); + _writeByte(AXP202_ADC_SPEED, 1, &val); + return AXP_PASS; +} + +int AXP20X_Class::setTSmode(axp_ts_pin_mode_t mode) +{ + //axp192 same axp202 aregister address 0x84 + if (!_init) + return AXP_NOT_INIT; + if (mode > AXP_TS_PIN_MODE_ENABLE) + return AXP_FAIL; + uint8_t val; + _readByte(AXP202_ADC_SPEED, 1, &val); + uint8_t rw = mode; + val &= 0xFC; + val |= rw; + _writeByte(AXP202_ADC_SPEED, 1, &val); + + // TS pin ADC function enable/disable + if (mode == AXP_TS_PIN_MODE_DISABLE) + adc1Enable(AXP202_TS_PIN_ADC1, false); + else + adc1Enable(AXP202_TS_PIN_ADC1, true); + return AXP_PASS; +} + +int AXP20X_Class::adc1Enable(uint16_t params, bool en) +{ + if (!_init) + return AXP_NOT_INIT; + uint8_t val; + _readByte(AXP202_ADC_EN1, 1, &val); + if (en) + val |= params; + else + val &= ~(params); + _writeByte(AXP202_ADC_EN1, 1, &val); + return AXP_PASS; +} + +int AXP20X_Class::adc2Enable(uint16_t params, bool en) +{ + if (!_init) + return AXP_NOT_INIT; + uint8_t val; + _readByte(AXP202_ADC_EN2, 1, &val); + if (en) + val |= params; + else + val &= ~(params); + _writeByte(AXP202_ADC_EN2, 1, &val); + return AXP_PASS; +} + +int AXP20X_Class::enableIRQ(uint64_t params, bool en) +{ + if (!_init) + return AXP_NOT_INIT; + uint8_t val, val1; + if (params & 0xFF) { + val1 = params & 0xFF; + _readByte(AXP202_INTEN1, 1, &val); + if (en) + val |= val1; + else + val &= ~(val1); + AXP_DEBUG("%s [0x%x]val:0x%x\n", en ? "enable" : "disable", AXP202_INTEN1, val); + _writeByte(AXP202_INTEN1, 1, &val); + } + if (params & 0xFF00) { + val1 = params >> 8; + _readByte(AXP202_INTEN2, 1, &val); + if (en) + val |= val1; + else + val &= ~(val1); + AXP_DEBUG("%s [0x%x]val:0x%x\n", en ? "enable" : "disable", AXP202_INTEN2, val); + _writeByte(AXP202_INTEN2, 1, &val); + } + + if (params & 0xFF0000) { + val1 = params >> 16; + _readByte(AXP202_INTEN3, 1, &val); + if (en) + val |= val1; + else + val &= ~(val1); + AXP_DEBUG("%s [0x%x]val:0x%x\n", en ? "enable" : "disable", AXP202_INTEN3, val); + _writeByte(AXP202_INTEN3, 1, &val); + } + + if (params & 0xFF000000) { + val1 = params >> 24; + _readByte(AXP202_INTEN4, 1, &val); + if (en) + val |= val1; + else + val &= ~(val1); + AXP_DEBUG("%s [0x%x]val:0x%x\n", en ? "enable" : "disable", AXP202_INTEN4, val); + _writeByte(AXP202_INTEN4, 1, &val); + } + + if (params & 0xFF00000000) { + val1 = params >> 32; + _readByte(AXP202_INTEN5, 1, &val); + if (en) + val |= val1; + else + val &= ~(val1); + AXP_DEBUG("%s [0x%x]val:0x%x\n", en ? "enable" : "disable", AXP202_INTEN5, val); + _writeByte(AXP202_INTEN5, 1, &val); + } + return AXP_PASS; +} + +int AXP20X_Class::readIRQ() +{ + if (!_init) + return AXP_NOT_INIT; + switch (_chip_id) { + case AXP192_CHIP_ID: + for (int i = 0; i < 4; ++i) { + _readByte(AXP192_INTSTS1 + i, 1, &_irq[i]); + } + _readByte(AXP192_INTSTS5, 1, &_irq[4]); + return AXP_PASS; + + case AXP202_CHIP_ID: + for (int i = 0; i < 5; ++i) { + _readByte(AXP202_INTSTS1 + i, 1, &_irq[i]); + } + return AXP_PASS; + default: + return AXP_FAIL; + } +} + +void AXP20X_Class::clearIRQ() +{ + uint8_t val = 0xFF; + switch (_chip_id) { + case AXP192_CHIP_ID: + for (int i = 0; i < 3; i++) { + _writeByte(AXP192_INTSTS1 + i, 1, &val); + } + _writeByte(AXP192_INTSTS5, 1, &val); + break; + case AXP202_CHIP_ID: + for (int i = 0; i < 5; i++) { + _writeByte(AXP202_INTSTS1 + i, 1, &val); + } + break; + default: + break; + } + memset(_irq, 0, sizeof(_irq)); +} + +bool AXP20X_Class::isAcinOverVoltageIRQ() +{ + return (bool)(_irq[0] & BIT_MASK(7)); +} + +bool AXP20X_Class::isAcinPlugInIRQ() +{ + return (bool)(_irq[0] & BIT_MASK(6)); +} + +bool AXP20X_Class::isAcinRemoveIRQ() +{ + return (bool)(_irq[0] & BIT_MASK(5)); +} + +bool AXP20X_Class::isVbusOverVoltageIRQ() +{ + return (bool)(_irq[0] & BIT_MASK(4)); +} + +bool AXP20X_Class::isVbusPlugInIRQ() +{ + return (bool)(_irq[0] & BIT_MASK(3)); +} + +bool AXP20X_Class::isVbusRemoveIRQ() +{ + return (bool)(_irq[0] & BIT_MASK(2)); +} + +bool AXP20X_Class::isVbusLowVHOLDIRQ() +{ + return (bool)(_irq[0] & BIT_MASK(1)); +} + +bool AXP20X_Class::isBattPlugInIRQ() +{ + return (bool)(_irq[1] & BIT_MASK(7)); +} +bool AXP20X_Class::isBattRemoveIRQ() +{ + return (bool)(_irq[1] & BIT_MASK(6)); +} +bool AXP20X_Class::isBattEnterActivateIRQ() +{ + return (bool)(_irq[1] & BIT_MASK(5)); +} +bool AXP20X_Class::isBattExitActivateIRQ() +{ + return (bool)(_irq[1] & BIT_MASK(4)); +} +bool AXP20X_Class::isChargingIRQ() +{ + return (bool)(_irq[1] & BIT_MASK(3)); +} +bool AXP20X_Class::isChargingDoneIRQ() +{ + return (bool)(_irq[1] & BIT_MASK(2)); +} +bool AXP20X_Class::isBattTempLowIRQ() +{ + return (bool)(_irq[1] & BIT_MASK(1)); +} +bool AXP20X_Class::isBattTempHighIRQ() +{ + return (bool)(_irq[1] & BIT_MASK(0)); +} + +bool AXP20X_Class::isPEKShortPressIRQ() +{ + return (bool)(_irq[2] & BIT_MASK(1)); +} + +bool AXP20X_Class::isPEKLongtPressIRQ() +{ + return (bool)(_irq[2] & BIT_MASK(0)); +} + +bool AXP20X_Class::isTimerTimeoutIRQ() +{ + return (bool)(_irq[4] & BIT_MASK(7)); +} + +bool AXP20X_Class::isVBUSPlug() +{ + if (!_init) + return AXP_NOT_INIT; + uint8_t reg; + _readByte(AXP202_STATUS, 1, ®); + return IS_OPEN(reg, 5); +} + +int AXP20X_Class::setDCDC2Voltage(uint16_t mv) +{ + if (!_init) + return AXP_NOT_INIT; + if (mv < 700) { + AXP_DEBUG("DCDC2:Below settable voltage:700mV~2275mV"); + mv = 700; + } + if (mv > 2275) { + AXP_DEBUG("DCDC2:Above settable voltage:700mV~2275mV"); + mv = 2275; + } + uint8_t val = (mv - 700) / 25; + //! axp173/192/202 same register + _writeByte(AXP202_DC2OUT_VOL, 1, &val); + return AXP_PASS; +} + +uint16_t AXP20X_Class::getDCDC2Voltage() +{ + uint8_t val = 0; + //! axp173/192/202 same register + _readByte(AXP202_DC2OUT_VOL, 1, &val); + return val * 25 + 700; +} + +uint16_t AXP20X_Class::getDCDC3Voltage() +{ + if (!_init) + return 0; + if (_chip_id == AXP173_CHIP_ID)return AXP_NOT_SUPPORT; + uint8_t val = 0; + _readByte(AXP202_DC3OUT_VOL, 1, &val); + return val * 25 + 700; +} + +int AXP20X_Class::setDCDC3Voltage(uint16_t mv) +{ + if (!_init) + return AXP_NOT_INIT; + if (_chip_id == AXP173_CHIP_ID)return AXP_NOT_SUPPORT; + if (mv < 700) { + AXP_DEBUG("DCDC3:Below settable voltage:700mV~3500mV"); + mv = 700; + } + if (mv > 3500) { + AXP_DEBUG("DCDC3:Above settable voltage:700mV~3500mV"); + mv = 3500; + } + uint8_t val = (mv - 700) / 25; + _writeByte(AXP202_DC3OUT_VOL, 1, &val); + return AXP_PASS; +} + +int AXP20X_Class::setLDO2Voltage(uint16_t mv) +{ + uint8_t rVal, wVal; + if (!_init) + return AXP_NOT_INIT; + if (mv < 1800) { + AXP_DEBUG("LDO2:Below settable voltage:1800mV~3300mV"); + mv = 1800; + } + if (mv > 3300) { + AXP_DEBUG("LDO2:Above settable voltage:1800mV~3300mV"); + mv = 3300; + } + wVal = (mv - 1800) / 100; + if (_chip_id == AXP202_CHIP_ID) { + _readByte(AXP202_LDO24OUT_VOL, 1, &rVal); + rVal &= 0x0F; + rVal |= (wVal << 4); + _writeByte(AXP202_LDO24OUT_VOL, 1, &rVal); + return AXP_PASS; + } else if (_chip_id == AXP192_CHIP_ID || _chip_id == AXP173_CHIP_ID) { + _readByte(AXP192_LDO23OUT_VOL, 1, &rVal); + rVal &= 0x0F; + rVal |= (wVal << 4); + _writeByte(AXP192_LDO23OUT_VOL, 1, &rVal); + return AXP_PASS; + } + return AXP_FAIL; +} + +uint16_t AXP20X_Class::getLDO2Voltage() +{ + uint8_t rVal; + if (_chip_id == AXP202_CHIP_ID) { + _readByte(AXP202_LDO24OUT_VOL, 1, &rVal); + rVal &= 0xF0; + rVal >>= 4; + return rVal * 100 + 1800; + } else if (_chip_id == AXP192_CHIP_ID || _chip_id == AXP173_CHIP_ID ) { + _readByte(AXP192_LDO23OUT_VOL, 1, &rVal); + AXP_DEBUG("get result:%x\n", rVal); + rVal &= 0xF0; + rVal >>= 4; + return rVal * 100 + 1800; + } + return 0; +} + +int AXP20X_Class::setLDO3Voltage(uint16_t mv) +{ + uint8_t rVal; + if (!_init) + return AXP_NOT_INIT; + if (_chip_id == AXP202_CHIP_ID && mv < 700) { + AXP_DEBUG("LDO3:Below settable voltage:700mV~3500mV"); + mv = 700; + } else if (_chip_id == AXP192_CHIP_ID && mv < 1800) { + AXP_DEBUG("LDO3:Below settable voltage:1800mV~3300mV"); + mv = 1800; + } + + if (_chip_id == AXP202_CHIP_ID && mv > 3500) { + AXP_DEBUG("LDO3:Above settable voltage:700mV~3500mV"); + mv = 3500; + } else if (_chip_id == AXP192_CHIP_ID && mv > 3300) { + AXP_DEBUG("LDO3:Above settable voltage:1800mV~3300mV"); + mv = 3300; + } + + if (_chip_id == AXP202_CHIP_ID) { + _readByte(AXP202_LDO3OUT_VOL, 1, &rVal); + rVal &= 0x80; + rVal |= ((mv - 700) / 25); + _writeByte(AXP202_LDO3OUT_VOL, 1, &rVal); + return AXP_PASS; + } else if (_chip_id == AXP192_CHIP_ID || _chip_id == AXP173_CHIP_ID) { + _readByte(AXP192_LDO23OUT_VOL, 1, &rVal); + rVal &= 0xF0; + rVal |= ((mv - 1800) / 100); + _writeByte(AXP192_LDO23OUT_VOL, 1, &rVal); + return AXP_PASS; + } + return AXP_FAIL; +} + +uint16_t AXP20X_Class::getLDO3Voltage() +{ + uint8_t rVal; + if (!_init) + return AXP_NOT_INIT; + + if (_chip_id == AXP202_CHIP_ID) { + _readByte(AXP202_LDO3OUT_VOL, 1, &rVal); + if (rVal & 0x80) { + //! According to the hardware N_VBUSEN Pin selection + return getVbusVoltage() * 1000; + } else { + return (rVal & 0x7F) * 25 + 700; + } + } else if (_chip_id == AXP192_CHIP_ID || _chip_id == AXP173_CHIP_ID) { + _readByte(AXP192_LDO23OUT_VOL, 1, &rVal); + rVal &= 0x0F; + return rVal * 100 + 1800; + } + return 0; +} + +//! Only axp173 support +int AXP20X_Class::setLDO4Voltage(uint16_t mv) +{ + if (!_init) + return AXP_NOT_INIT; + if (_chip_id != AXP173_CHIP_ID) + return AXP_FAIL; + + if (mv < 700) { + AXP_DEBUG("LDO4:Below settable voltage:700mV~3500mV"); + mv = 700; + } + if (mv > 3500) { + AXP_DEBUG("LDO4:Above settable voltage:700mV~3500mV"); + mv = 3500; + } + uint8_t val = (mv - 700) / 25; + _writeByte(AXP173_LDO4_VLOTAGE, 1, &val); + return AXP_PASS; +} + +uint16_t AXP20X_Class::getLDO4Voltage() +{ + const uint16_t ldo4_table[] = {1250, 1300, 1400, 1500, 1600, 1700, 1800, 1900, 2000, 2500, 2700, 2800, 3000, 3100, 3200, 3300}; + if (!_init) + return 0; + uint8_t val = 0; + switch (_chip_id) { + case AXP173_CHIP_ID: + _readByte(AXP173_LDO4_VLOTAGE, 1, &val); + return val * 25 + 700; + case AXP202_CHIP_ID: + _readByte(AXP202_LDO24OUT_VOL, 1, &val); + val &= 0xF; + return ldo4_table[val]; + break; + case AXP192_CHIP_ID: + default: + break; + } + return 0; +} + + +//! Only axp202 support +int AXP20X_Class::setLDO4Voltage(axp_ldo4_table_t param) +{ + if (!_init) + return AXP_NOT_INIT; + if (_chip_id == AXP202_CHIP_ID) { + if (param >= AXP202_LDO4_MAX) + return AXP_INVALID; + uint8_t val; + _readByte(AXP202_LDO24OUT_VOL, 1, &val); + val &= 0xF0; + val |= param; + _writeByte(AXP202_LDO24OUT_VOL, 1, &val); + return AXP_PASS; + } + return AXP_FAIL; +} + +//! Only AXP202 support +// 0 : LDO 1 : DCIN +int AXP20X_Class::setLDO3Mode(uint8_t mode) +{ + uint8_t val; + if (_chip_id != AXP202_CHIP_ID) + return AXP_FAIL; + _readByte(AXP202_LDO3OUT_VOL, 1, &val); + if (mode) { + val |= BIT_MASK(7); + } else { + val &= (~BIT_MASK(7)); + } + _writeByte(AXP202_LDO3OUT_VOL, 1, &val); + return AXP_PASS; +} + +int AXP20X_Class::setStartupTime(uint8_t param) +{ + uint8_t val; + if (!_init) + return AXP_NOT_INIT; + if (param > sizeof(startupParams) / sizeof(startupParams[0])) + return AXP_INVALID; + _readByte(AXP202_POK_SET, 1, &val); + val &= (~0b11000000); + val |= startupParams[param]; + _writeByte(AXP202_POK_SET, 1, &val); + return AXP_PASS; +} + +int AXP20X_Class::setlongPressTime(uint8_t param) +{ + uint8_t val; + if (!_init) + return AXP_NOT_INIT; + if (param > sizeof(longPressParams) / sizeof(longPressParams[0])) + return AXP_INVALID; + _readByte(AXP202_POK_SET, 1, &val); + val &= (~0b00110000); + val |= longPressParams[param]; + _writeByte(AXP202_POK_SET, 1, &val); + return AXP_PASS; +} + +int AXP20X_Class::setShutdownTime(uint8_t param) +{ + uint8_t val; + if (!_init) + return AXP_NOT_INIT; + if (param > sizeof(shutdownParams) / sizeof(shutdownParams[0])) + return AXP_INVALID; + _readByte(AXP202_POK_SET, 1, &val); + val &= (~0b00000011); + val |= shutdownParams[param]; + _writeByte(AXP202_POK_SET, 1, &val); + return AXP_PASS; +} + +int AXP20X_Class::setTimeOutShutdown(bool en) +{ + uint8_t val; + if (!_init) + return AXP_NOT_INIT; + _readByte(AXP202_POK_SET, 1, &val); + if (en) + val |= (1 << 3); + else + val &= (~(1 << 3)); + _writeByte(AXP202_POK_SET, 1, &val); + return AXP_PASS; +} + +int AXP20X_Class::shutdown() +{ + uint8_t val; + if (!_init) + return AXP_NOT_INIT; + _readByte(AXP202_OFF_CTL, 1, &val); + val |= (1 << 7); + _writeByte(AXP202_OFF_CTL, 1, &val); + return AXP_PASS; +} + +float AXP20X_Class::getSettingChargeCurrent() +{ + uint8_t val; + if (!_init) + return AXP_NOT_INIT; + _readByte(AXP202_CHARGE1, 1, &val); + val &= 0b00000111; + float cur = 300.0 + val * 100.0; + AXP_DEBUG("Setting Charge current : %.2f mA\n", cur); + return cur; +} + +bool AXP20X_Class::isChargeingEnable() +{ + uint8_t val; + if (!_init) + return false; + _readByte(AXP202_CHARGE1, 1, &val); + if (val & (1 << 7)) { + AXP_DEBUG("Charging enable is enable\n"); + val = true; + } else { + AXP_DEBUG("Charging enable is disable\n"); + val = false; + } + return val; +} + +int AXP20X_Class::enableChargeing(bool en) +{ + uint8_t val; + if (!_init) + return AXP_NOT_INIT; + _readByte(AXP202_CHARGE1, 1, &val); + val |= (1 << 7); + _writeByte(AXP202_CHARGE1, 1, &val); + return AXP_PASS; +} + +int AXP20X_Class::setChargingTargetVoltage(axp_chargeing_vol_t param) +{ + uint8_t val; + if (!_init) + return AXP_NOT_INIT; + if (param > sizeof(targetVolParams) / sizeof(targetVolParams[0])) + return AXP_INVALID; + _readByte(AXP202_CHARGE1, 1, &val); + val &= ~(0b01100000); + val |= targetVolParams[param]; + _writeByte(AXP202_CHARGE1, 1, &val); + return AXP_PASS; +} + +int AXP20X_Class::getBattPercentage() +{ + if (!_init) + return AXP_NOT_INIT; + if (_chip_id != AXP202_CHIP_ID) + return AXP_NOT_SUPPORT; + uint8_t val; + if (!isBatteryConnect()) + return 0; + _readByte(AXP202_BATT_PERCENTAGE, 1, &val); + if (!(val & BIT_MASK(7))) { + return val & (~BIT_MASK(7)); + } + return 0; +} + +int AXP20X_Class::setChgLEDMode(axp_chgled_mode_t mode) +{ + uint8_t val; + _readByte(AXP202_OFF_CTL, 1, &val); + val &= 0b11001111; + val |= BIT_MASK(3); + switch (mode) { + case AXP20X_LED_OFF: + _writeByte(AXP202_OFF_CTL, 1, &val); + break; + case AXP20X_LED_BLINK_1HZ: + val |= 0b00010000; + _writeByte(AXP202_OFF_CTL, 1, &val); + break; + case AXP20X_LED_BLINK_4HZ: + val |= 0b00100000; + _writeByte(AXP202_OFF_CTL, 1, &val); + break; + case AXP20X_LED_LOW_LEVEL: + val |= 0b00110000; + _writeByte(AXP202_OFF_CTL, 1, &val); + break; + default: + return AXP_FAIL; + } + return AXP_PASS; +} + +int AXP20X_Class::debugCharging() +{ + uint8_t val; + _readByte(AXP202_CHARGE1, 1, &val); + AXP_DEBUG("SRC REG:0x%x\n", val); + if (val & (1 << 7)) { + AXP_DEBUG("Charging enable is enable\n"); + } else { + AXP_DEBUG("Charging enable is disable\n"); + } + AXP_DEBUG("Charging target-voltage : 0x%x\n", ((val & 0b01100000) >> 5) & 0b11); + if (val & (1 << 4)) { + AXP_DEBUG("end when the charge current is lower than 15%% of the set value\n"); + } else { + AXP_DEBUG(" end when the charge current is lower than 10%% of the set value\n"); + } + val &= 0b00000111; + AXP_DEBUG("Charge current : %.2f mA\n", 300.0 + val * 100.0); + return AXP_PASS; +} + +int AXP20X_Class::debugStatus() +{ + if (!_init) + return AXP_NOT_INIT; + uint8_t val, val1, val2; + _readByte(AXP202_STATUS, 1, &val); + _readByte(AXP202_MODE_CHGSTATUS, 1, &val1); + _readByte(AXP202_IPS_SET, 1, &val2); + AXP_DEBUG("AXP202_STATUS: AXP202_MODE_CHGSTATUS AXP202_IPS_SET\n"); + AXP_DEBUG("0x%x\t\t\t 0x%x\t\t\t 0x%x\n", val, val1, val2); + return AXP_PASS; +} + +int AXP20X_Class::limitingOff() +{ + if (!_init) + return AXP_NOT_INIT; + uint8_t val; + _readByte(AXP202_IPS_SET, 1, &val); + if (_chip_id == AXP202_CHIP_ID) { + val |= 0x03; + } else { + val &= ~(1 << 1); + } + _writeByte(AXP202_IPS_SET, 1, &val); + return AXP_PASS; +} + +// Only AXP129 chip and AXP173 +int AXP20X_Class::setDCDC1Voltage(uint16_t mv) +{ + if (!_init) + return AXP_NOT_INIT; + if (_chip_id != AXP192_CHIP_ID && _chip_id != AXP173_CHIP_ID) + return AXP_FAIL; + if (mv < 700) { + AXP_DEBUG("DCDC1:Below settable voltage:700mV~3500mV"); + mv = 700; + } + if (mv > 3500) { + AXP_DEBUG("DCDC1:Above settable voltage:700mV~3500mV"); + mv = 3500; + } + uint8_t val = (mv - 700) / 25; + //! axp192 and axp173 dc1 control register same + _writeByte(AXP192_DC1_VLOTAGE, 1, &val); + return AXP_PASS; +} + +// Only AXP129 chip and AXP173 +uint16_t AXP20X_Class::getDCDC1Voltage() +{ + if (_chip_id != AXP192_CHIP_ID && _chip_id != AXP173_CHIP_ID) + return AXP_FAIL; + uint8_t val = 0; + //! axp192 and axp173 dc1 control register same + _readByte(AXP192_DC1_VLOTAGE, 1, &val); + return val * 25 + 700; +} + + +/*********************************************** + * !!! TIMER FUNCTION !!! + * *********************************************/ + +int AXP20X_Class::setTimer(uint8_t minutes) +{ + if (!_init) + return AXP_NOT_INIT; + if (_chip_id == AXP202_CHIP_ID) { + if (minutes > 63) { + return AXP_ARG_INVALID; + } + _writeByte(AXP202_TIMER_CTL, 1, &minutes); + return AXP_PASS; + } + return AXP_NOT_SUPPORT; +} + +int AXP20X_Class::offTimer() +{ + if (!_init) + return AXP_NOT_INIT; + if (_chip_id == AXP202_CHIP_ID) { + uint8_t minutes = 0x80; + _writeByte(AXP202_TIMER_CTL, 1, &minutes); + return AXP_PASS; + } + return AXP_NOT_SUPPORT; +} + +int AXP20X_Class::clearTimerStatus() +{ + if (!_init) + return AXP_NOT_INIT; + if (_chip_id == AXP202_CHIP_ID) { + uint8_t val; + _readByte(AXP202_TIMER_CTL, 1, &val); + val |= 0x80; + _writeByte(AXP202_TIMER_CTL, 1, &val); + return AXP_PASS; + } + return AXP_NOT_SUPPORT; +} + +/*********************************************** + * !!! GPIO FUNCTION !!! + * *********************************************/ + +int AXP20X_Class::_axp192_gpio_0_select( axp_gpio_mode_t mode) +{ + switch (mode) { + case AXP_IO_OUTPUT_LOW_MODE: + return 0b101; + case AXP_IO_INPUT_MODE: + return 0b001; + case AXP_IO_LDO_MODE: + return 0b010; + case AXP_IO_ADC_MODE: + return 0b100; + case AXP_IO_FLOATING_MODE: + return 0b111; + case AXP_IO_OPEN_DRAIN_OUTPUT_MODE: + return 0; + case AXP_IO_OUTPUT_HIGH_MODE: + case AXP_IO_PWM_OUTPUT_MODE: + default: + break; + } + return AXP_NOT_SUPPORT; +} + +int AXP20X_Class::_axp192_gpio_1_select( axp_gpio_mode_t mode) +{ + switch (mode) { + case AXP_IO_OUTPUT_LOW_MODE: + return 0b101; + case AXP_IO_INPUT_MODE: + return 0b001; + case AXP_IO_ADC_MODE: + return 0b100; + case AXP_IO_FLOATING_MODE: + return 0b111; + case AXP_IO_OPEN_DRAIN_OUTPUT_MODE: + return 0; + case AXP_IO_PWM_OUTPUT_MODE: + return 0b010; + case AXP_IO_OUTPUT_HIGH_MODE: + case AXP_IO_LDO_MODE: + default: + break; + } + return AXP_NOT_SUPPORT; +} + + +int AXP20X_Class::_axp192_gpio_3_select( axp_gpio_mode_t mode) +{ + switch (mode) { + case AXP_IO_EXTERN_CHARGING_CTRL_MODE: + return 0; + case AXP_IO_OPEN_DRAIN_OUTPUT_MODE: + return 1; + case AXP_IO_INPUT_MODE: + return 2; + default: + break; + } + return AXP_NOT_SUPPORT; +} + +int AXP20X_Class::_axp192_gpio_4_select( axp_gpio_mode_t mode) +{ + switch (mode) { + case AXP_IO_EXTERN_CHARGING_CTRL_MODE: + return 0; + case AXP_IO_OPEN_DRAIN_OUTPUT_MODE: + return 1; + case AXP_IO_INPUT_MODE: + return 2; + case AXP_IO_ADC_MODE: + return 3; + default: + break; + } + return AXP_NOT_SUPPORT; +} + + +int AXP20X_Class::_axp192_gpio_set(axp_gpio_t gpio, axp_gpio_mode_t mode) +{ + int rslt; + uint8_t val; + switch (gpio) { + case AXP_GPIO_0: { + rslt = _axp192_gpio_0_select(mode); + if (rslt < 0)return rslt; + _readByte(AXP192_GPIO0_CTL, 1, &val); + val &= 0xF8; + val |= (uint8_t)rslt; + _writeByte(AXP192_GPIO0_CTL, 1, &val); + return AXP_PASS; + } + case AXP_GPIO_1: { + rslt = _axp192_gpio_1_select(mode); + if (rslt < 0)return rslt; + _readByte(AXP192_GPIO1_CTL, 1, &val); + val &= 0xF8; + val |= (uint8_t)rslt; + _writeByte(AXP192_GPIO1_CTL, 1, &val); + return AXP_PASS; + } + case AXP_GPIO_2: { + rslt = _axp192_gpio_1_select(mode); + if (rslt < 0)return rslt; + _readByte(AXP192_GPIO2_CTL, 1, &val); + val &= 0xF8; + val |= (uint8_t)rslt; + _writeByte(AXP192_GPIO2_CTL, 1, &val); + return AXP_PASS; + } + case AXP_GPIO_3: { + rslt = _axp192_gpio_3_select(mode); + if (rslt < 0)return rslt; + _readByte(AXP192_GPIO34_CTL, 1, &val); + val &= 0xFC; + val |= (uint8_t)rslt; + _writeByte(AXP192_GPIO34_CTL, 1, &val); + return AXP_PASS; + } + case AXP_GPIO_4: { + rslt = _axp192_gpio_4_select(mode); + if (rslt < 0)return rslt; + _readByte(AXP192_GPIO34_CTL, 1, &val); + val &= 0xF3; + val |= (uint8_t)rslt; + _writeByte(AXP192_GPIO34_CTL, 1, &val); + return AXP_PASS; + } + default: + break; + } + return AXP_NOT_SUPPORT; +} + +int AXP20X_Class::_axp202_gpio_0_select( axp_gpio_mode_t mode) +{ + switch (mode) { + case AXP_IO_OUTPUT_LOW_MODE: + return 0; + case AXP_IO_OUTPUT_HIGH_MODE: + return 1; + case AXP_IO_INPUT_MODE: + return 2; + case AXP_IO_LDO_MODE: + return 3; + case AXP_IO_ADC_MODE: + return 4; + default: + break; + } + return AXP_NOT_SUPPORT; +} + +int AXP20X_Class::_axp202_gpio_1_select( axp_gpio_mode_t mode) +{ + switch (mode) { + case AXP_IO_OUTPUT_LOW_MODE: + return 0; + case AXP_IO_OUTPUT_HIGH_MODE: + return 1; + case AXP_IO_INPUT_MODE: + return 2; + case AXP_IO_ADC_MODE: + return 4; + default: + break; + } + return AXP_NOT_SUPPORT; +} + +int AXP20X_Class::_axp202_gpio_2_select( axp_gpio_mode_t mode) +{ + switch (mode) { + case AXP_IO_OUTPUT_LOW_MODE: + return 0; + case AXP_IO_INPUT_MODE: + return 2; + case AXP_IO_FLOATING_MODE: + return 1; + default: + break; + } + return AXP_NOT_SUPPORT; +} + + +int AXP20X_Class::_axp202_gpio_3_select(axp_gpio_mode_t mode) +{ + switch (mode) { + case AXP_IO_INPUT_MODE: + return 1; + case AXP_IO_OPEN_DRAIN_OUTPUT_MODE: + return 0; + default: + break; + } + return AXP_NOT_SUPPORT; +} + +int AXP20X_Class::_axp202_gpio_set(axp_gpio_t gpio, axp_gpio_mode_t mode) +{ + uint8_t val; + int rslt; + switch (gpio) { + case AXP_GPIO_0: { + rslt = _axp202_gpio_0_select(mode); + if (rslt < 0)return rslt; + _readByte(AXP202_GPIO0_CTL, 1, &val); + val &= 0b11111000; + val |= (uint8_t)rslt; + _writeByte(AXP202_GPIO0_CTL, 1, &val); + return AXP_PASS; + } + case AXP_GPIO_1: { + rslt = _axp202_gpio_1_select(mode); + if (rslt < 0)return rslt; + _readByte(AXP202_GPIO1_CTL, 1, &val); + val &= 0b11111000; + val |= (uint8_t)rslt; + _writeByte(AXP202_GPIO1_CTL, 1, &val); + return AXP_PASS; + } + case AXP_GPIO_2: { + rslt = _axp202_gpio_2_select(mode); + if (rslt < 0)return rslt; + _readByte(AXP202_GPIO2_CTL, 1, &val); + val &= 0b11111000; + val |= (uint8_t)rslt; + _writeByte(AXP202_GPIO2_CTL, 1, &val); + return AXP_PASS; + } + case AXP_GPIO_3: { + rslt = _axp202_gpio_3_select(mode); + if (rslt < 0)return rslt; + _readByte(AXP202_GPIO3_CTL, 1, &val); + val = rslt ? (val | BIT_MASK(2)) : (val & (~BIT_MASK(2))); + _writeByte(AXP202_GPIO3_CTL, 1, &val); + return AXP_PASS; + } + default: + break; + } + return AXP_NOT_SUPPORT; +} + + +int AXP20X_Class::setGPIOMode(axp_gpio_t gpio, axp_gpio_mode_t mode) +{ + if (!_init) + return AXP_NOT_INIT; + switch (_chip_id) { + case AXP202_CHIP_ID: + return _axp202_gpio_set(gpio, mode); + break; + case AXP192_CHIP_ID: + return _axp192_gpio_set(gpio, mode); + break; + default: + break; + } + return AXP_NOT_SUPPORT; +} + + +int AXP20X_Class::_axp_irq_mask(axp_gpio_irq_t irq) +{ + switch (irq) { + case AXP_IRQ_NONE: + return 0; + case AXP_IRQ_RISING: + return BIT_MASK(7); + case AXP_IRQ_FALLING: + return BIT_MASK(6); + case AXP_IRQ_DOUBLE_EDGE: + return 0b1100000; + default: + break; + } + return AXP_NOT_SUPPORT; +} + +int AXP20X_Class::_axp202_gpio_irq_set(axp_gpio_t gpio, axp_gpio_irq_t irq) +{ + uint8_t reg; + uint8_t val; + int mask; + mask = _axp_irq_mask(irq); + + if (mask < 0)return mask; + switch (gpio) { + case AXP_GPIO_0: + reg = AXP202_GPIO0_CTL; + break; + case AXP_GPIO_1: + reg = AXP202_GPIO1_CTL; + break; + case AXP_GPIO_2: + reg = AXP202_GPIO2_CTL; + break; + case AXP_GPIO_3: + reg = AXP202_GPIO3_CTL; + break; + default: + return AXP_NOT_SUPPORT; + } + _readByte(reg, 1, &val); + val = mask == 0 ? (val & 0b00111111) : (val | mask); + _writeByte(reg, 1, &val); + return AXP_PASS; +} + + +int AXP20X_Class::setGPIOIrq(axp_gpio_t gpio, axp_gpio_irq_t irq) +{ + if (!_init) + return AXP_NOT_INIT; + switch (_chip_id) { + case AXP202_CHIP_ID: + return _axp202_gpio_irq_set(gpio, irq); + case AXP192_CHIP_ID: + case AXP173_CHIP_ID: + return AXP_NOT_SUPPORT; + default: + break; + } + return AXP_NOT_SUPPORT; +} + +int AXP20X_Class::setLDO5Voltage(axp_ldo5_table_t vol) +{ + const uint8_t params[] = { + 0b11111000, //1.8V + 0b11111001, //2.5V + 0b11111010, //2.8V + 0b11111011, //3.0V + 0b11111100, //3.1V + 0b11111101, //3.3V + 0b11111110, //3.4V + 0b11111111, //3.5V + }; + if (!_init) + return AXP_NOT_INIT; + if (_chip_id != AXP202_CHIP_ID) + return AXP_NOT_SUPPORT; + if (vol > sizeof(params) / sizeof(params[0])) + return AXP_ARG_INVALID; + uint8_t val = 0; + _readByte(AXP202_GPIO0_VOL, 1, &val); + val &= 0b11111000; + val |= params[vol]; + _writeByte(AXP202_GPIO0_VOL, 1, &val); + return AXP_PASS; +} + + +int AXP20X_Class::_axp202_gpio_write(axp_gpio_t gpio, uint8_t val) +{ + uint8_t reg; + uint8_t wVal = 0; + switch (gpio) { + case AXP_GPIO_0: + reg = AXP202_GPIO0_CTL; + break; + case AXP_GPIO_1: + reg = AXP202_GPIO1_CTL; + break; + case AXP_GPIO_2: + reg = AXP202_GPIO2_CTL; + if (val) { + return AXP_NOT_SUPPORT; + } + break; + case AXP_GPIO_3: + if (val) { + return AXP_NOT_SUPPORT; + } + _readByte(AXP202_GPIO3_CTL, 1, &wVal); + wVal &= 0b11111101; + _writeByte(AXP202_GPIO3_CTL, 1, &wVal); + return AXP_PASS; + default: + return AXP_NOT_SUPPORT; + } + _readByte(reg, 1, &wVal); + wVal = val ? (wVal | 1) : (wVal & 0b11111000); + _writeByte(reg, 1, &wVal); + return AXP_PASS; +} + +int AXP20X_Class::_axp202_gpio_read(axp_gpio_t gpio) +{ + uint8_t val; + uint8_t reg = AXP202_GPIO012_SIGNAL; + uint8_t offset; + switch (gpio) { + case AXP_GPIO_0: + offset = 4; + break; + case AXP_GPIO_1: + offset = 5; + break; + case AXP_GPIO_2: + offset = 6; + break; + case AXP_GPIO_3: + reg = AXP202_GPIO3_CTL; + offset = 0; + break; + default: + return AXP_NOT_SUPPORT; + } + _readByte(reg, 1, &val); + return val & BIT_MASK(offset) ? 1 : 0; +} + +int AXP20X_Class::gpioWrite(axp_gpio_t gpio, uint8_t val) +{ + if (!_init) + return AXP_NOT_INIT; + switch (_chip_id) { + case AXP202_CHIP_ID: + return _axp202_gpio_write(gpio, val); + case AXP192_CHIP_ID: + case AXP173_CHIP_ID: + return AXP_NOT_SUPPORT; + default: + break; + } + return AXP_NOT_SUPPORT; +} + +int AXP20X_Class::gpioRead(axp_gpio_t gpio) +{ + if (!_init) + return AXP_NOT_INIT; + switch (_chip_id) { + case AXP202_CHIP_ID: + return _axp202_gpio_read(gpio); + case AXP192_CHIP_ID: + case AXP173_CHIP_ID: + return AXP_NOT_SUPPORT; + default: + break; + } + return AXP_NOT_SUPPORT; +} + + + +int AXP20X_Class::getChargeControlCur() +{ + int cur; + uint8_t val; + if (!_init) + return AXP_NOT_INIT; + switch (_chip_id) { + case AXP202_CHIP_ID: + _readByte(AXP202_CHARGE1, 1, &val); + val &= 0x0F; + cur = val * 100 + 300; + if (cur > 1800 || cur < 300)return 0; + return cur; + case AXP192_CHIP_ID: + case AXP173_CHIP_ID: + _readByte(AXP202_CHARGE1, 1, &val); + return val & 0x0F; + default: + break; + } + return AXP_NOT_SUPPORT; +} + +int AXP20X_Class::setChargeControlCur(uint16_t mA) +{ + uint8_t val; + if (!_init) + return AXP_NOT_INIT; + switch (_chip_id) { + case AXP202_CHIP_ID: + _readByte(AXP202_CHARGE1, 1, &val); + val &= 0b11110000; + mA -= 300; + val |= (mA / 100); + _writeByte(AXP202_CHARGE1, 1, &val); + return AXP_PASS; + case AXP192_CHIP_ID: + case AXP173_CHIP_ID: + _readByte(AXP202_CHARGE1, 1, &val); + val &= 0b11110000; + if(mA > AXP1XX_CHARGE_CUR_1320MA) + mA = AXP1XX_CHARGE_CUR_1320MA; + val |= mA; + _writeByte(AXP202_CHARGE1, 1, &val); + return AXP_PASS; + default: + break; + } + return AXP_NOT_SUPPORT; +} + diff --git a/lib/libesp32/TTGO_TWatch_Library/src/axp20x.h b/lib/libesp32_div/TTGO_TWatch_Library/src/axp20x.h old mode 100755 new mode 100644 similarity index 96% rename from lib/libesp32/TTGO_TWatch_Library/src/axp20x.h rename to lib/libesp32_div/TTGO_TWatch_Library/src/axp20x.h index f2ca85a77..b7f19ae7b --- a/lib/libesp32/TTGO_TWatch_Library/src/axp20x.h +++ b/lib/libesp32_div/TTGO_TWatch_Library/src/axp20x.h @@ -1,827 +1,827 @@ -///////////////////////////////////////////////////////////////// -/* -MIT License - -Copyright (c) 2019 lewis he - -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. - -axp20x.h - Arduino library for X-Power AXP202 chip. -Created by Lewis he on April 1, 2019. -github:https://github.com/lewisxhe/AXP202X_Libraries -*/ -///////////////////////////////////////////////////////////////// -#pragma once - -#include -#include - -// #define AXP_DEBUG_PORT Serial -#ifdef AXP_DEBUG_PORT -#define AXP_DEBUG(fmt, ...) AXP_DEBUG_PORT.printf_P((PGM_P)PSTR(fmt), ##__VA_ARGS__) -#else -#define AXP_DEBUG(...) -#endif - -#ifndef RISING -#define RISING 0x01 -#endif - -#ifndef FALLING -#define FALLING 0x02 -#endif - -#ifdef _BV -#undef _BV -#endif -#define _BV(b) (1ULL << (b)) - -//! Error Code -#define AXP_PASS (0) -#define AXP_FAIL (-1) -#define AXP_INVALID (-2) -#define AXP_NOT_INIT (-3) -#define AXP_NOT_SUPPORT (-4) -#define AXP_ARG_INVALID (-5) - -//! Chip Address -#define AXP202_SLAVE_ADDRESS (0x35) -#define AXP192_SLAVE_ADDRESS (0x34) -#define AXP173_SLAVE_ADDRESS (0x34) - -//! Chip ID -#define AXP202_CHIP_ID 0x41 -#define AXP192_CHIP_ID 0x03 -#define AXP173_CHIP_ID 0xAD //!Axp173 does not have a chip ID, given a custom ID - -//! Logic states -#define AXP202_ON 1 -#define AXP202_OFF 0 - -//! REG MAP -#define AXP202_STATUS (0x00) -#define AXP202_MODE_CHGSTATUS (0x01) -#define AXP202_OTG_STATUS (0x02) -#define AXP202_IC_TYPE (0x03) -#define AXP202_DATA_BUFFER1 (0x04) -#define AXP202_DATA_BUFFER2 (0x05) -#define AXP202_DATA_BUFFER3 (0x06) -#define AXP202_DATA_BUFFER4 (0x07) -#define AXP202_DATA_BUFFER5 (0x08) -#define AXP202_DATA_BUFFER6 (0x09) -#define AXP202_DATA_BUFFER7 (0x0A) -#define AXP202_DATA_BUFFER8 (0x0B) -#define AXP202_DATA_BUFFER9 (0x0C) -#define AXP202_DATA_BUFFERA (0x0D) -#define AXP202_DATA_BUFFERB (0x0E) -#define AXP202_DATA_BUFFERC (0x0F) -#define AXP202_LDO234_DC23_CTL (0x12) -#define AXP202_DC2OUT_VOL (0x23) -#define AXP202_LDO3_DC2_DVM (0x25) -#define AXP202_DC3OUT_VOL (0x27) -#define AXP202_LDO24OUT_VOL (0x28) -#define AXP202_LDO3OUT_VOL (0x29) -#define AXP202_IPS_SET (0x30) -#define AXP202_VOFF_SET (0x31) -#define AXP202_OFF_CTL (0x32) -#define AXP202_CHARGE1 (0x33) -#define AXP202_CHARGE2 (0x34) -#define AXP202_BACKUP_CHG (0x35) -#define AXP202_POK_SET (0x36) -#define AXP202_DCDC_FREQSET (0x37) -#define AXP202_VLTF_CHGSET (0x38) -#define AXP202_VHTF_CHGSET (0x39) -#define AXP202_APS_WARNING1 (0x3A) -#define AXP202_APS_WARNING2 (0x3B) -#define AXP202_TLTF_DISCHGSET (0x3C) -#define AXP202_THTF_DISCHGSET (0x3D) -#define AXP202_DCDC_MODESET (0x80) -#define AXP202_ADC_EN1 (0x82) -#define AXP202_ADC_EN2 (0x83) -#define AXP202_ADC_SPEED (0x84) -#define AXP202_ADC_INPUTRANGE (0x85) -#define AXP202_ADC_IRQ_RETFSET (0x86) -#define AXP202_ADC_IRQ_FETFSET (0x87) -#define AXP202_TIMER_CTL (0x8A) -#define AXP202_VBUS_DET_SRP (0x8B) -#define AXP202_HOTOVER_CTL (0x8F) -#define AXP202_GPIO0_CTL (0x90) -#define AXP202_GPIO0_VOL (0x91) -#define AXP202_GPIO1_CTL (0x92) -#define AXP202_GPIO2_CTL (0x93) -#define AXP202_GPIO012_SIGNAL (0x94) -#define AXP202_GPIO3_CTL (0x95) -#define AXP202_INTEN1 (0x40) -#define AXP202_INTEN2 (0x41) -#define AXP202_INTEN3 (0x42) -#define AXP202_INTEN4 (0x43) -#define AXP202_INTEN5 (0x44) -#define AXP202_INTSTS1 (0x48) -#define AXP202_INTSTS2 (0x49) -#define AXP202_INTSTS3 (0x4A) -#define AXP202_INTSTS4 (0x4B) -#define AXP202_INTSTS5 (0x4C) - -//Irq control register -#define AXP192_INTEN1 (0x40) -#define AXP192_INTEN2 (0x41) -#define AXP192_INTEN3 (0x42) -#define AXP192_INTEN4 (0x43) -#define AXP192_INTEN5 (0x4A) -//Irq status register -#define AXP192_INTSTS1 (0x44) -#define AXP192_INTSTS2 (0x45) -#define AXP192_INTSTS3 (0x46) -#define AXP192_INTSTS4 (0x47) -#define AXP192_INTSTS5 (0x4D) - -#define AXP192_DC1_VLOTAGE (0x26) -#define AXP192_LDO23OUT_VOL (0x28) -#define AXP192_GPIO0_CTL (0x90) -#define AXP192_GPIO0_VOL (0x91) -#define AXP192_GPIO1_CTL (0X92) -#define AXP192_GPIO2_CTL (0x93) -#define AXP192_GPIO012_SIGNAL (0x94) -#define AXP192_GPIO34_CTL (0x95) - - - -/* axp 192/202 adc data register */ -#define AXP202_BAT_AVERVOL_H8 (0x78) -#define AXP202_BAT_AVERVOL_L4 (0x79) -#define AXP202_BAT_AVERCHGCUR_H8 (0x7A) -#define AXP202_BAT_AVERCHGCUR_L4 (0x7B) -#define AXP202_BAT_AVERCHGCUR_L5 (0x7B) -#define AXP202_ACIN_VOL_H8 (0x56) -#define AXP202_ACIN_VOL_L4 (0x57) -#define AXP202_ACIN_CUR_H8 (0x58) -#define AXP202_ACIN_CUR_L4 (0x59) -#define AXP202_VBUS_VOL_H8 (0x5A) -#define AXP202_VBUS_VOL_L4 (0x5B) -#define AXP202_VBUS_CUR_H8 (0x5C) -#define AXP202_VBUS_CUR_L4 (0x5D) -#define AXP202_INTERNAL_TEMP_H8 (0x5E) -#define AXP202_INTERNAL_TEMP_L4 (0x5F) -#define AXP202_TS_IN_H8 (0x62) -#define AXP202_TS_IN_L4 (0x63) -#define AXP202_GPIO0_VOL_ADC_H8 (0x64) -#define AXP202_GPIO0_VOL_ADC_L4 (0x65) -#define AXP202_GPIO1_VOL_ADC_H8 (0x66) -#define AXP202_GPIO1_VOL_ADC_L4 (0x67) - -#define AXP202_BAT_AVERDISCHGCUR_H8 (0x7C) -#define AXP202_BAT_AVERDISCHGCUR_L5 (0x7D) -#define AXP202_APS_AVERVOL_H8 (0x7E) -#define AXP202_APS_AVERVOL_L4 (0x7F) -#define AXP202_INT_BAT_CHGCUR_H8 (0xA0) -#define AXP202_INT_BAT_CHGCUR_L4 (0xA1) -#define AXP202_EXT_BAT_CHGCUR_H8 (0xA2) -#define AXP202_EXT_BAT_CHGCUR_L4 (0xA3) -#define AXP202_INT_BAT_DISCHGCUR_H8 (0xA4) -#define AXP202_INT_BAT_DISCHGCUR_L4 (0xA5) -#define AXP202_EXT_BAT_DISCHGCUR_H8 (0xA6) -#define AXP202_EXT_BAT_DISCHGCUR_L4 (0xA7) -#define AXP202_BAT_CHGCOULOMB3 (0xB0) -#define AXP202_BAT_CHGCOULOMB2 (0xB1) -#define AXP202_BAT_CHGCOULOMB1 (0xB2) -#define AXP202_BAT_CHGCOULOMB0 (0xB3) -#define AXP202_BAT_DISCHGCOULOMB3 (0xB4) -#define AXP202_BAT_DISCHGCOULOMB2 (0xB5) -#define AXP202_BAT_DISCHGCOULOMB1 (0xB6) -#define AXP202_BAT_DISCHGCOULOMB0 (0xB7) -#define AXP202_COULOMB_CTL (0xB8) -#define AXP202_BAT_POWERH8 (0x70) -#define AXP202_BAT_POWERM8 (0x71) -#define AXP202_BAT_POWERL8 (0x72) - -#define AXP202_VREF_TEM_CTRL (0xF3) -#define AXP202_BATT_PERCENTAGE (0xB9) - -/* bit definitions for AXP events, irq event */ -/* AXP202 */ -#define AXP202_IRQ_USBLO (1) -#define AXP202_IRQ_USBRE (2) -#define AXP202_IRQ_USBIN (3) -#define AXP202_IRQ_USBOV (4) -#define AXP202_IRQ_ACRE (5) -#define AXP202_IRQ_ACIN (6) -#define AXP202_IRQ_ACOV (7) - -#define AXP202_IRQ_TEMLO (8) -#define AXP202_IRQ_TEMOV (9) -#define AXP202_IRQ_CHAOV (10) -#define AXP202_IRQ_CHAST (11) -#define AXP202_IRQ_BATATOU (12) -#define AXP202_IRQ_BATATIN (13) -#define AXP202_IRQ_BATRE (14) -#define AXP202_IRQ_BATIN (15) - -#define AXP202_IRQ_POKLO (16) -#define AXP202_IRQ_POKSH (17) -#define AXP202_IRQ_LDO3LO (18) -#define AXP202_IRQ_DCDC3LO (19) -#define AXP202_IRQ_DCDC2LO (20) -#define AXP202_IRQ_CHACURLO (22) -#define AXP202_IRQ_ICTEMOV (23) - -#define AXP202_IRQ_EXTLOWARN2 (24) -#define AXP202_IRQ_EXTLOWARN1 (25) -#define AXP202_IRQ_SESSION_END (26) -#define AXP202_IRQ_SESS_AB_VALID (27) -#define AXP202_IRQ_VBUS_UN_VALID (28) -#define AXP202_IRQ_VBUS_VALID (29) -#define AXP202_IRQ_PDOWN_BY_NOE (30) -#define AXP202_IRQ_PUP_BY_NOE (31) - -#define AXP202_IRQ_GPIO0TG (32) -#define AXP202_IRQ_GPIO1TG (33) -#define AXP202_IRQ_GPIO2TG (34) -#define AXP202_IRQ_GPIO3TG (35) -#define AXP202_IRQ_PEKFE (37) -#define AXP202_IRQ_PEKRE (38) -#define AXP202_IRQ_TIMER (39) - -//Signal Capture -#define AXP202_BATT_VOLTAGE_STEP (1.1F) -#define AXP202_BATT_DISCHARGE_CUR_STEP (0.5F) -#define AXP202_BATT_CHARGE_CUR_STEP (0.5F) -#define AXP202_ACIN_VOLTAGE_STEP (1.7F) -#define AXP202_ACIN_CUR_STEP (0.625F) -#define AXP202_VBUS_VOLTAGE_STEP (1.7F) -#define AXP202_VBUS_CUR_STEP (0.375F) -#define AXP202_INTERNAL_TEMP_STEP (0.1F) -#define AXP202_APS_VOLTAGE_STEP (1.4F) -#define AXP202_TS_PIN_OUT_STEP (0.8F) -#define AXP202_GPIO0_STEP (0.5F) -#define AXP202_GPIO1_STEP (0.5F) -// AXP192 only -#define AXP202_GPIO2_STEP (0.5F) -#define AXP202_GPIO3_STEP (0.5F) - -// AXP173 -#define AXP173_EXTEN_DC2_CTL (0x10) -#define AXP173_CTL_DC2_BIT (0) -#define AXP173_CTL_EXTEN_BIT (2) -#define AXP173_DC1_VLOTAGE (0x26) -#define AXP173_LDO4_VLOTAGE (0x27) - -#define FORCED_OPEN_DCDC3(x) (x |= (AXP202_ON << AXP202_DCDC3)) -#define BIT_MASK(x) (1 << x) -#define IS_OPEN(reg, channel) (bool)(reg & BIT_MASK(channel)) - -enum { - AXP202_EXTEN = 0, - AXP202_DCDC3 = 1, - AXP202_LDO2 = 2, - AXP202_LDO4 = 3, - AXP202_DCDC2 = 4, - AXP202_LDO3 = 6, - AXP202_OUTPUT_MAX, -}; - -enum { - AXP192_DCDC1 = 0, - AXP192_DCDC3 = 1, - AXP192_LDO2 = 2, - AXP192_LDO3 = 3, - AXP192_DCDC2 = 4, - AXP192_EXTEN = 6, - AXP192_OUTPUT_MAX, -}; - -enum { - AXP173_DCDC1 = 0, - AXP173_LDO4 = 1, - AXP173_LDO2 = 2, - AXP173_LDO3 = 3, - AXP173_DCDC2 = 4, - AXP173_EXTEN = 6, - AXP173_OUTPUT_MAX, -}; - -typedef enum { - AXP202_STARTUP_TIME_128MS, - AXP202_STARTUP_TIME_3S, - AXP202_STARTUP_TIME_1S, - AXP202_STARTUP_TIME_2S, -} axp202_startup_time_t; - -typedef enum { - AXP192_STARTUP_TIME_128MS, - AXP192_STARTUP_TIME_512MS, - AXP192_STARTUP_TIME_1S, - AXP192_STARTUP_TIME_2S, -} axp192_startup_time_t; - -typedef enum { - AXP_LONGPRESS_TIME_1S, - AXP_LONGPRESS_TIME_1S5, - AXP_LONGPRESS_TIME_2S, - AXP_LONGPRESS_TIME_2S5, -} axp_loonPress_time_t; - -typedef enum { - AXP_POWER_OFF_TIME_4S, - AXP_POWER_OFF_TIME_65, - AXP_POWER_OFF_TIME_8S, - AXP_POWER_OFF_TIME_16S, -} axp_poweroff_time_t; - -//REG 33H: Charging control 1 Charging target-voltage setting -typedef enum { - AXP202_TARGET_VOL_4_1V, - AXP202_TARGET_VOL_4_15V, - AXP202_TARGET_VOL_4_2V, - AXP202_TARGET_VOL_4_36V -} axp_chargeing_vol_t; - -//REG 82H: ADC Enable 1 register Parameter -typedef enum { - AXP202_BATT_VOL_ADC1 = 1 << 7, - AXP202_BATT_CUR_ADC1 = 1 << 6, - AXP202_ACIN_VOL_ADC1 = 1 << 5, - AXP202_ACIN_CUR_ADC1 = 1 << 4, - AXP202_VBUS_VOL_ADC1 = 1 << 3, - AXP202_VBUS_CUR_ADC1 = 1 << 2, - AXP202_APS_VOL_ADC1 = 1 << 1, - AXP202_TS_PIN_ADC1 = 1 << 0 -} axp_adc1_func_t; - -// REG 83H: ADC Enable 2 register Parameter -typedef enum { - AXP202_TEMP_MONITORING_ADC2 = 1 << 7, - AXP202_GPIO1_FUNC_ADC2 = 1 << 3, - AXP202_GPIO0_FUNC_ADC2 = 1 << 2 -} axp_adc2_func_t; - -typedef enum { - AXP202_LDO3_MODE_LDO, - AXP202_LDO3_MODE_DCIN -} axp202_ldo3_mode_t; - - - -typedef enum { - //! IRQ1 REG 40H - AXP202_VBUS_VHOLD_LOW_IRQ = _BV(1), //VBUS is available, but lower than V HOLD, IRQ enable - AXP202_VBUS_REMOVED_IRQ = _BV(2), //VBUS removed, IRQ enable - AXP202_VBUS_CONNECT_IRQ = _BV(3), //VBUS connected, IRQ enable - AXP202_VBUS_OVER_VOL_IRQ = _BV(4), //VBUS over-voltage, IRQ enable - AXP202_ACIN_REMOVED_IRQ = _BV(5), //ACIN removed, IRQ enable - AXP202_ACIN_CONNECT_IRQ = _BV(6), //ACIN connected, IRQ enable - AXP202_ACIN_OVER_VOL_IRQ = _BV(7), //ACIN over-voltage, IRQ enable - - //! IRQ2 REG 41H - AXP202_BATT_LOW_TEMP_IRQ = _BV(8), //Battery low-temperature, IRQ enable - AXP202_BATT_OVER_TEMP_IRQ = _BV(9), //Battery over-temperature, IRQ enable - AXP202_CHARGING_FINISHED_IRQ = _BV(10), //Charge finished, IRQ enable - AXP202_CHARGING_IRQ = _BV(11), //Be charging, IRQ enable - AXP202_BATT_EXIT_ACTIVATE_IRQ = _BV(12), //Exit battery activate mode, IRQ enable - AXP202_BATT_ACTIVATE_IRQ = _BV(13), //Battery activate mode, IRQ enable - AXP202_BATT_REMOVED_IRQ = _BV(14), //Battery removed, IRQ enable - AXP202_BATT_CONNECT_IRQ = _BV(15), //Battery connected, IRQ enable - - //! IRQ3 REG 42H - AXP202_PEK_LONGPRESS_IRQ = _BV(16), //PEK long press, IRQ enable - AXP202_PEK_SHORTPRESS_IRQ = _BV(17), //PEK short press, IRQ enable - AXP202_LDO3_LOW_VOL_IRQ = _BV(18), //LDO3output voltage is lower than the set value, IRQ enable - AXP202_DC3_LOW_VOL_IRQ = _BV(19), //DC-DC3output voltage is lower than the set value, IRQ enable - AXP202_DC2_LOW_VOL_IRQ = _BV(20), //DC-DC2 output voltage is lower than the set value, IRQ enable - //**Reserved and unchangeable BIT 5 - AXP202_CHARGE_LOW_CUR_IRQ = _BV(22), //Charge current is lower than the set current, IRQ enable - AXP202_CHIP_TEMP_HIGH_IRQ = _BV(23), //AXP202 internal over-temperature, IRQ enable - - //! IRQ4 REG 43H - AXP202_APS_LOW_VOL_LEVEL2_IRQ = _BV(24), //APS low-voltage, IRQ enable(LEVEL2) - APX202_APS_LOW_VOL_LEVEL1_IRQ = _BV(25), //APS low-voltage, IRQ enable(LEVEL1) - AXP202_VBUS_SESSION_END_IRQ = _BV(26), //VBUS Session End IRQ enable - AXP202_VBUS_SESSION_AB_IRQ = _BV(27), //VBUS Session A/B IRQ enable - AXP202_VBUS_INVALID_IRQ = _BV(28), //VBUS invalid, IRQ enable - AXP202_VBUS_VAILD_IRQ = _BV(29), //VBUS valid, IRQ enable - AXP202_NOE_OFF_IRQ = _BV(30), //N_OE shutdown, IRQ enable - AXP202_NOE_ON_IRQ = _BV(31), //N_OE startup, IRQ enable - - //! IRQ5 REG 44H - AXP202_GPIO0_EDGE_TRIGGER_IRQ = _BV(32), //GPIO0 input edge trigger, IRQ enable - AXP202_GPIO1_EDGE_TRIGGER_IRQ = _BV(33), //GPIO1input edge trigger or ADC input, IRQ enable - AXP202_GPIO2_EDGE_TRIGGER_IRQ = _BV(34), //GPIO2input edge trigger, IRQ enable - AXP202_GPIO3_EDGE_TRIGGER_IRQ = _BV(35), //GPIO3 input edge trigger, IRQ enable - //**Reserved and unchangeable BIT 4 - AXP202_PEK_FALLING_EDGE_IRQ = _BV(37), //PEK press falling edge, IRQ enable - AXP202_PEK_RISING_EDGE_IRQ = _BV(38), //PEK press rising edge, IRQ enable - AXP202_TIMER_TIMEOUT_IRQ = _BV(39), //Timer timeout, IRQ enable - - AXP202_ALL_IRQ = (0xFFFFFFFFFFULL) -} axp_irq_t; - -typedef enum { - AXP202_LDO4_1250MV, - AXP202_LDO4_1300MV, - AXP202_LDO4_1400MV, - AXP202_LDO4_1500MV, - AXP202_LDO4_1600MV, - AXP202_LDO4_1700MV, - AXP202_LDO4_1800MV, - AXP202_LDO4_1900MV, - AXP202_LDO4_2000MV, - AXP202_LDO4_2500MV, - AXP202_LDO4_2700MV, - AXP202_LDO4_2800MV, - AXP202_LDO4_3000MV, - AXP202_LDO4_3100MV, - AXP202_LDO4_3200MV, - AXP202_LDO4_3300MV, - AXP202_LDO4_MAX, -} axp_ldo4_table_t; - -typedef enum { - AXP202_LDO5_1800MV, - AXP202_LDO5_2500MV, - AXP202_LDO5_2800MV, - AXP202_LDO5_3000MV, - AXP202_LDO5_3100MV, - AXP202_LDO5_3300MV, - AXP202_LDO5_3400MV, - AXP202_LDO5_3500MV, -} axp_ldo5_table_t; - -typedef enum { - AXP20X_LED_OFF, - AXP20X_LED_BLINK_1HZ, - AXP20X_LED_BLINK_4HZ, - AXP20X_LED_LOW_LEVEL, -} axp_chgled_mode_t; - -typedef enum { - AXP_ADC_SAMPLING_RATE_25HZ = 0, - AXP_ADC_SAMPLING_RATE_50HZ = 1, - AXP_ADC_SAMPLING_RATE_100HZ = 2, - AXP_ADC_SAMPLING_RATE_200HZ = 3, -} axp_adc_sampling_rate_t; - -typedef enum { - AXP_TS_PIN_CURRENT_20UA = 0, - AXP_TS_PIN_CURRENT_40UA = 1, - AXP_TS_PIN_CURRENT_60UA = 2, - AXP_TS_PIN_CURRENT_80UA = 3, -} axp_ts_pin_current_t; - -typedef enum { - AXP_TS_PIN_FUNCTION_BATT = 0, - AXP_TS_PIN_FUNCTION_ADC = 1, -} axp_ts_pin_function_t; - -typedef enum { - AXP_TS_PIN_MODE_DISABLE = 0, - AXP_TS_PIN_MODE_CHARGING = 1, - AXP_TS_PIN_MODE_SAMPLING = 2, - AXP_TS_PIN_MODE_ENABLE = 3, -} axp_ts_pin_mode_t; - -//! Only AXP192 and AXP202 have gpio function -typedef enum { - AXP_GPIO_0, - AXP_GPIO_1, - AXP_GPIO_2, - AXP_GPIO_3, - AXP_GPIO_4, -} axp_gpio_t; - -typedef enum { - AXP_IO_OUTPUT_LOW_MODE, - AXP_IO_OUTPUT_HIGH_MODE, - AXP_IO_INPUT_MODE, - AXP_IO_LDO_MODE, - AXP_IO_ADC_MODE, - AXP_IO_FLOATING_MODE, - AXP_IO_OPEN_DRAIN_OUTPUT_MODE, - AXP_IO_PWM_OUTPUT_MODE, - AXP_IO_EXTERN_CHARGING_CTRL_MODE, -} axp_gpio_mode_t; - -typedef enum { - AXP_IRQ_NONE, - AXP_IRQ_RISING, - AXP_IRQ_FALLING, - AXP_IRQ_DOUBLE_EDGE, -} axp_gpio_irq_t; - - -typedef enum { - AXP192_GPIO_1V8, - AXP192_GPIO_1V9, - AXP192_GPIO_2V0, - AXP192_GPIO_2V1, - AXP192_GPIO_2V2, - AXP192_GPIO_2V3, - AXP192_GPIO_2V4, - AXP192_GPIO_2V5, - AXP192_GPIO_2V6, - AXP192_GPIO_2V7, - AXP192_GPIO_2V8, - AXP192_GPIO_2V9, - AXP192_GPIO_3V0, - AXP192_GPIO_3V1, - AXP192_GPIO_3V2, - AXP192_GPIO_3V3, -} axp192_gpio_voltage_t; - -typedef enum { - AXP1XX_CHARGE_CUR_100MA, - AXP1XX_CHARGE_CUR_190MA, - AXP1XX_CHARGE_CUR_280MA, - AXP1XX_CHARGE_CUR_360MA, - AXP1XX_CHARGE_CUR_450MA, - AXP1XX_CHARGE_CUR_550MA, - AXP1XX_CHARGE_CUR_630MA, - AXP1XX_CHARGE_CUR_700MA, - AXP1XX_CHARGE_CUR_780MA, - AXP1XX_CHARGE_CUR_880MA, - AXP1XX_CHARGE_CUR_960MA, - AXP1XX_CHARGE_CUR_1000MA, - AXP1XX_CHARGE_CUR_1080MA, - AXP1XX_CHARGE_CUR_1160MA, - AXP1XX_CHARGE_CUR_1240MA, - AXP1XX_CHARGE_CUR_1320MA, -} axp1xx_charge_current_t; - -typedef uint8_t (*axp_com_fptr_t)(uint8_t dev_addr, uint8_t reg_addr, uint8_t *data, uint8_t len); - - -class AXP20X_Class -{ -public: - int begin(TwoWire &port = Wire, uint8_t addr = AXP202_SLAVE_ADDRESS, bool isAxp173 = false); - int begin(axp_com_fptr_t read_cb, axp_com_fptr_t write_cb, uint8_t addr = AXP202_SLAVE_ADDRESS, bool isAxp173 = false); - - // Power Output Control - int setPowerOutPut(uint8_t ch, bool en); - - bool isBatteryConnect(); - bool isChargeing(); - bool isLDO2Enable(); - bool isLDO3Enable(); - bool isLDO4Enable(); - bool isDCDC3Enable(); - bool isDCDC2Enable(); - bool isChargeingEnable(); - bool isVBUSPlug(); - bool isExtenEnable(); - - //Only axp192 chip - bool isDCDC1Enable(); - - - //IRQ Status - bool isAcinOverVoltageIRQ(); - bool isAcinPlugInIRQ(); - bool isAcinRemoveIRQ(); - bool isVbusOverVoltageIRQ(); - bool isVbusPlugInIRQ(); - bool isVbusRemoveIRQ(); - bool isVbusLowVHOLDIRQ(); - - bool isBattPlugInIRQ(); - bool isBattRemoveIRQ(); - bool isBattEnterActivateIRQ(); - bool isBattExitActivateIRQ(); - bool isChargingIRQ(); - bool isChargingDoneIRQ(); - bool isBattTempLowIRQ(); - bool isBattTempHighIRQ(); - - bool isPEKShortPressIRQ(); - bool isPEKLongtPressIRQ(); - bool isTimerTimeoutIRQ(); - - //! Group4 ADC data - float getAcinVoltage(); - float getAcinCurrent(); - float getVbusVoltage(); - float getVbusCurrent(); - float getTemp(); - float getTSTemp(); - float getGPIO0Voltage(); - float getGPIO1Voltage(); - float getBattInpower(); - float getBattVoltage(); - float getBattChargeCurrent(); - float getBattDischargeCurrent(); - float getSysIPSOUTVoltage(); - uint32_t getBattChargeCoulomb(); - uint32_t getBattDischargeCoulomb(); - float getSettingChargeCurrent(); - - int setChargingTargetVoltage(axp_chargeing_vol_t param); - int enableChargeing(bool en); - - int adc1Enable(uint16_t params, bool en); - int adc2Enable(uint16_t params, bool en); - - int setTScurrent(axp_ts_pin_current_t current); - int setTSfunction(axp_ts_pin_function_t func); - int setTSmode(axp_ts_pin_mode_t mode); - - - int setTimer(uint8_t minutes); - int offTimer(); - int clearTimerStatus(); - /** - * param: axp202_startup_time_t or axp192_startup_time_t - */ - int setStartupTime(uint8_t param); - - /** - * param: axp_loonPress_time_t - */ - int setlongPressTime(uint8_t param); - - /** - * @param param: axp_poweroff_time_t - */ - int setShutdownTime(uint8_t param); - - int setTimeOutShutdown(bool en); - - int shutdown(); - - /** - * params: axp_irq_t - */ - int enableIRQ(uint64_t params, bool en); - int readIRQ(); - void clearIRQ(); - - int setDCDC1Voltage(uint16_t mv); //! Only AXP192 support and AXP173 - // return mv - uint16_t getDCDC1Voltage(); //! Only AXP192 support and AXP173 - - // ----------------- - - /* - !! Chip resource table - | CHIP | AXP173 | AXP192 | AXP202 | - | -------- | ---------------- | ---------------- | ---------------- | - | DC1 | 0v7~3v5 /1200mA | 0v7~3v5 /1200mA | X | - | DC2 | 0v7~2v275/1600mA | 0v7~2v275/1600mA | 0v7~2v275/1600mA | - | DC3 | X | 0v7~3v5 /700mA | 0v7~3v5 /1200mA | - | LDO1 | 3v3 /30mA | 3v3 /30mA | 3v3 /30mA | - | LDO2 | 1v8~3v3 /200mA | 1v8~3v3 /200mA | 1v8~3v3 /200mA | - | LDO3 | 1v8~3v3 /200mA | 1v8~3v3 /200mA | 0v7~3v3 /200mA | - | LDO4 | 0v7~3v5 /500mA | X | 1v8~3v3 /200mA | - | LDO5/IO0 | X | 1v8~3v3 /50mA | 1v8~3v3 /50mA | - */ - int setDCDC2Voltage(uint16_t mv); - uint16_t getDCDC2Voltage(); - - int setDCDC3Voltage(uint16_t mv); - uint16_t getDCDC3Voltage(); - - int setLDO2Voltage(uint16_t mv); - uint16_t getLDO2Voltage(); - - int setLDO3Voltage(uint16_t mv); - uint16_t getLDO3Voltage(); - - - int setLDO4Voltage(axp_ldo4_table_t param); //! Only axp202 support - int setLDO4Voltage(uint16_t mv); //! Only axp173 support - - // return mv - uint16_t getLDO4Voltage(); //! Only axp173/axp202 support - - - /** - * @param mode: axp_chgled_mode_t - */ - int setChgLEDMode(axp_chgled_mode_t mode); - - /** - * @param mode: axp202_ldo3_mode_t - */ - int setLDO3Mode(uint8_t mode); //! Only AXP202 support - - int getBattPercentage(); - - int debugCharging(); - int debugStatus(); - int limitingOff(); - - int setAdcSamplingRate(axp_adc_sampling_rate_t rate); - uint8_t getAdcSamplingRate(); - float getCoulombData(); - uint8_t getCoulombRegister(); - int setCoulombRegister(uint8_t val); - int EnableCoulombcounter(void); - int DisableCoulombcounter(void); - int StopCoulombcounter(void); - int ClearCoulombcounter(void); - - - int setGPIOMode(axp_gpio_t gpio, axp_gpio_mode_t mode); - int setGPIOIrq(axp_gpio_t gpio, axp_gpio_irq_t irq); - int setLDO5Voltage(axp_ldo5_table_t vol); - - int gpioWrite(axp_gpio_t gpio, uint8_t vol); - int gpioRead(axp_gpio_t gpio); - - // When the chip is axp192 / 173, the allowed values are 0 ~ 15, corresponding to the axp1xx_charge_current_t enumeration - // When the chip is axp202 allows maximum charging current of 1800mA, minimum 300mA - int getChargeControlCur(); - int setChargeControlCur(uint16_t mA); - -private: - uint16_t _getRegistH8L5(uint8_t regh8, uint8_t regl5) - { - uint8_t hv, lv; - _readByte(regh8, 1, &hv); - _readByte(regl5, 1, &lv); - return (hv << 5) | (lv & 0x1F); - } - - uint16_t _getRegistResult(uint8_t regh8, uint8_t regl4) - { - uint8_t hv, lv; - _readByte(regh8, 1, &hv); - _readByte(regl4, 1, &lv); - return (hv << 4) | (lv & 0x0F); - } - - int _readByte(uint8_t reg, uint8_t nbytes, uint8_t *data) - { - if (_read_cb != nullptr) { - return _read_cb(_address, reg, data, nbytes); - } - if (nbytes == 0 || !data) - return -1; - _i2cPort->beginTransmission(_address); - _i2cPort->write(reg); - _i2cPort->endTransmission(); - _i2cPort->requestFrom(_address, nbytes); - uint8_t index = 0; - while (_i2cPort->available()) - data[index++] = _i2cPort->read(); - return 0; - } - - int _writeByte(uint8_t reg, uint8_t nbytes, uint8_t *data) - { - if (_write_cb != nullptr) { - return _write_cb(_address, reg, data, nbytes); - } - if (nbytes == 0 || !data) - return -1; - _i2cPort->beginTransmission(_address); - _i2cPort->write(reg); - for (uint8_t i = 0; i < nbytes; i++) { - _i2cPort->write(data[i]); - } - _i2cPort->endTransmission(); - return 0; - } - - int _setGpioInterrupt(uint8_t *val, int mode, bool en); - int _axp_probe(); - int _axp_irq_mask(axp_gpio_irq_t irq); - - int _axp192_gpio_set(axp_gpio_t gpio, axp_gpio_mode_t mode); - int _axp192_gpio_0_select( axp_gpio_mode_t mode); - int _axp192_gpio_1_select( axp_gpio_mode_t mode); - int _axp192_gpio_3_select( axp_gpio_mode_t mode); - int _axp192_gpio_4_select( axp_gpio_mode_t mode); - - int _axp202_gpio_set(axp_gpio_t gpio, axp_gpio_mode_t mode); - int _axp202_gpio_0_select( axp_gpio_mode_t mode); - int _axp202_gpio_1_select( axp_gpio_mode_t mode); - int _axp202_gpio_2_select( axp_gpio_mode_t mode); - int _axp202_gpio_3_select( axp_gpio_mode_t mode); - int _axp202_gpio_irq_set(axp_gpio_t gpio, axp_gpio_irq_t irq); - int _axp202_gpio_write(axp_gpio_t gpio, uint8_t val); - int _axp202_gpio_read(axp_gpio_t gpio); - - - static const uint8_t startupParams[], longPressParams[], shutdownParams[], targetVolParams[]; - static uint8_t _outputReg; - uint8_t _address, _irq[5], _chip_id, _gpio[4]; - bool _init = false; - axp_com_fptr_t _read_cb = nullptr; - axp_com_fptr_t _write_cb = nullptr; - TwoWire *_i2cPort; - bool _isAxp173; -}; +///////////////////////////////////////////////////////////////// +/* +MIT License + +Copyright (c) 2019 lewis he + +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. + +axp20x.h - Arduino library for X-Power AXP202 chip. +Created by Lewis he on April 1, 2019. +github:https://github.com/lewisxhe/AXP202X_Libraries +*/ +///////////////////////////////////////////////////////////////// +#pragma once + +#include +#include + +// #define AXP_DEBUG_PORT Serial +#ifdef AXP_DEBUG_PORT +#define AXP_DEBUG(fmt, ...) AXP_DEBUG_PORT.printf_P((PGM_P)PSTR(fmt), ##__VA_ARGS__) +#else +#define AXP_DEBUG(...) +#endif + +#ifndef RISING +#define RISING 0x01 +#endif + +#ifndef FALLING +#define FALLING 0x02 +#endif + +#ifdef _BV +#undef _BV +#endif +#define _BV(b) (1ULL << (b)) + +//! Error Code +#define AXP_PASS (0) +#define AXP_FAIL (-1) +#define AXP_INVALID (-2) +#define AXP_NOT_INIT (-3) +#define AXP_NOT_SUPPORT (-4) +#define AXP_ARG_INVALID (-5) + +//! Chip Address +#define AXP202_SLAVE_ADDRESS (0x35) +#define AXP192_SLAVE_ADDRESS (0x34) +#define AXP173_SLAVE_ADDRESS (0x34) + +//! Chip ID +#define AXP202_CHIP_ID 0x41 +#define AXP192_CHIP_ID 0x03 +#define AXP173_CHIP_ID 0xAD //!Axp173 does not have a chip ID, given a custom ID + +//! Logic states +#define AXP202_ON 1 +#define AXP202_OFF 0 + +//! REG MAP +#define AXP202_STATUS (0x00) +#define AXP202_MODE_CHGSTATUS (0x01) +#define AXP202_OTG_STATUS (0x02) +#define AXP202_IC_TYPE (0x03) +#define AXP202_DATA_BUFFER1 (0x04) +#define AXP202_DATA_BUFFER2 (0x05) +#define AXP202_DATA_BUFFER3 (0x06) +#define AXP202_DATA_BUFFER4 (0x07) +#define AXP202_DATA_BUFFER5 (0x08) +#define AXP202_DATA_BUFFER6 (0x09) +#define AXP202_DATA_BUFFER7 (0x0A) +#define AXP202_DATA_BUFFER8 (0x0B) +#define AXP202_DATA_BUFFER9 (0x0C) +#define AXP202_DATA_BUFFERA (0x0D) +#define AXP202_DATA_BUFFERB (0x0E) +#define AXP202_DATA_BUFFERC (0x0F) +#define AXP202_LDO234_DC23_CTL (0x12) +#define AXP202_DC2OUT_VOL (0x23) +#define AXP202_LDO3_DC2_DVM (0x25) +#define AXP202_DC3OUT_VOL (0x27) +#define AXP202_LDO24OUT_VOL (0x28) +#define AXP202_LDO3OUT_VOL (0x29) +#define AXP202_IPS_SET (0x30) +#define AXP202_VOFF_SET (0x31) +#define AXP202_OFF_CTL (0x32) +#define AXP202_CHARGE1 (0x33) +#define AXP202_CHARGE2 (0x34) +#define AXP202_BACKUP_CHG (0x35) +#define AXP202_POK_SET (0x36) +#define AXP202_DCDC_FREQSET (0x37) +#define AXP202_VLTF_CHGSET (0x38) +#define AXP202_VHTF_CHGSET (0x39) +#define AXP202_APS_WARNING1 (0x3A) +#define AXP202_APS_WARNING2 (0x3B) +#define AXP202_TLTF_DISCHGSET (0x3C) +#define AXP202_THTF_DISCHGSET (0x3D) +#define AXP202_DCDC_MODESET (0x80) +#define AXP202_ADC_EN1 (0x82) +#define AXP202_ADC_EN2 (0x83) +#define AXP202_ADC_SPEED (0x84) +#define AXP202_ADC_INPUTRANGE (0x85) +#define AXP202_ADC_IRQ_RETFSET (0x86) +#define AXP202_ADC_IRQ_FETFSET (0x87) +#define AXP202_TIMER_CTL (0x8A) +#define AXP202_VBUS_DET_SRP (0x8B) +#define AXP202_HOTOVER_CTL (0x8F) +#define AXP202_GPIO0_CTL (0x90) +#define AXP202_GPIO0_VOL (0x91) +#define AXP202_GPIO1_CTL (0x92) +#define AXP202_GPIO2_CTL (0x93) +#define AXP202_GPIO012_SIGNAL (0x94) +#define AXP202_GPIO3_CTL (0x95) +#define AXP202_INTEN1 (0x40) +#define AXP202_INTEN2 (0x41) +#define AXP202_INTEN3 (0x42) +#define AXP202_INTEN4 (0x43) +#define AXP202_INTEN5 (0x44) +#define AXP202_INTSTS1 (0x48) +#define AXP202_INTSTS2 (0x49) +#define AXP202_INTSTS3 (0x4A) +#define AXP202_INTSTS4 (0x4B) +#define AXP202_INTSTS5 (0x4C) + +//Irq control register +#define AXP192_INTEN1 (0x40) +#define AXP192_INTEN2 (0x41) +#define AXP192_INTEN3 (0x42) +#define AXP192_INTEN4 (0x43) +#define AXP192_INTEN5 (0x4A) +//Irq status register +#define AXP192_INTSTS1 (0x44) +#define AXP192_INTSTS2 (0x45) +#define AXP192_INTSTS3 (0x46) +#define AXP192_INTSTS4 (0x47) +#define AXP192_INTSTS5 (0x4D) + +#define AXP192_DC1_VLOTAGE (0x26) +#define AXP192_LDO23OUT_VOL (0x28) +#define AXP192_GPIO0_CTL (0x90) +#define AXP192_GPIO0_VOL (0x91) +#define AXP192_GPIO1_CTL (0X92) +#define AXP192_GPIO2_CTL (0x93) +#define AXP192_GPIO012_SIGNAL (0x94) +#define AXP192_GPIO34_CTL (0x95) + + + +/* axp 192/202 adc data register */ +#define AXP202_BAT_AVERVOL_H8 (0x78) +#define AXP202_BAT_AVERVOL_L4 (0x79) +#define AXP202_BAT_AVERCHGCUR_H8 (0x7A) +#define AXP202_BAT_AVERCHGCUR_L4 (0x7B) +#define AXP202_BAT_AVERCHGCUR_L5 (0x7B) +#define AXP202_ACIN_VOL_H8 (0x56) +#define AXP202_ACIN_VOL_L4 (0x57) +#define AXP202_ACIN_CUR_H8 (0x58) +#define AXP202_ACIN_CUR_L4 (0x59) +#define AXP202_VBUS_VOL_H8 (0x5A) +#define AXP202_VBUS_VOL_L4 (0x5B) +#define AXP202_VBUS_CUR_H8 (0x5C) +#define AXP202_VBUS_CUR_L4 (0x5D) +#define AXP202_INTERNAL_TEMP_H8 (0x5E) +#define AXP202_INTERNAL_TEMP_L4 (0x5F) +#define AXP202_TS_IN_H8 (0x62) +#define AXP202_TS_IN_L4 (0x63) +#define AXP202_GPIO0_VOL_ADC_H8 (0x64) +#define AXP202_GPIO0_VOL_ADC_L4 (0x65) +#define AXP202_GPIO1_VOL_ADC_H8 (0x66) +#define AXP202_GPIO1_VOL_ADC_L4 (0x67) + +#define AXP202_BAT_AVERDISCHGCUR_H8 (0x7C) +#define AXP202_BAT_AVERDISCHGCUR_L5 (0x7D) +#define AXP202_APS_AVERVOL_H8 (0x7E) +#define AXP202_APS_AVERVOL_L4 (0x7F) +#define AXP202_INT_BAT_CHGCUR_H8 (0xA0) +#define AXP202_INT_BAT_CHGCUR_L4 (0xA1) +#define AXP202_EXT_BAT_CHGCUR_H8 (0xA2) +#define AXP202_EXT_BAT_CHGCUR_L4 (0xA3) +#define AXP202_INT_BAT_DISCHGCUR_H8 (0xA4) +#define AXP202_INT_BAT_DISCHGCUR_L4 (0xA5) +#define AXP202_EXT_BAT_DISCHGCUR_H8 (0xA6) +#define AXP202_EXT_BAT_DISCHGCUR_L4 (0xA7) +#define AXP202_BAT_CHGCOULOMB3 (0xB0) +#define AXP202_BAT_CHGCOULOMB2 (0xB1) +#define AXP202_BAT_CHGCOULOMB1 (0xB2) +#define AXP202_BAT_CHGCOULOMB0 (0xB3) +#define AXP202_BAT_DISCHGCOULOMB3 (0xB4) +#define AXP202_BAT_DISCHGCOULOMB2 (0xB5) +#define AXP202_BAT_DISCHGCOULOMB1 (0xB6) +#define AXP202_BAT_DISCHGCOULOMB0 (0xB7) +#define AXP202_COULOMB_CTL (0xB8) +#define AXP202_BAT_POWERH8 (0x70) +#define AXP202_BAT_POWERM8 (0x71) +#define AXP202_BAT_POWERL8 (0x72) + +#define AXP202_VREF_TEM_CTRL (0xF3) +#define AXP202_BATT_PERCENTAGE (0xB9) + +/* bit definitions for AXP events, irq event */ +/* AXP202 */ +#define AXP202_IRQ_USBLO (1) +#define AXP202_IRQ_USBRE (2) +#define AXP202_IRQ_USBIN (3) +#define AXP202_IRQ_USBOV (4) +#define AXP202_IRQ_ACRE (5) +#define AXP202_IRQ_ACIN (6) +#define AXP202_IRQ_ACOV (7) + +#define AXP202_IRQ_TEMLO (8) +#define AXP202_IRQ_TEMOV (9) +#define AXP202_IRQ_CHAOV (10) +#define AXP202_IRQ_CHAST (11) +#define AXP202_IRQ_BATATOU (12) +#define AXP202_IRQ_BATATIN (13) +#define AXP202_IRQ_BATRE (14) +#define AXP202_IRQ_BATIN (15) + +#define AXP202_IRQ_POKLO (16) +#define AXP202_IRQ_POKSH (17) +#define AXP202_IRQ_LDO3LO (18) +#define AXP202_IRQ_DCDC3LO (19) +#define AXP202_IRQ_DCDC2LO (20) +#define AXP202_IRQ_CHACURLO (22) +#define AXP202_IRQ_ICTEMOV (23) + +#define AXP202_IRQ_EXTLOWARN2 (24) +#define AXP202_IRQ_EXTLOWARN1 (25) +#define AXP202_IRQ_SESSION_END (26) +#define AXP202_IRQ_SESS_AB_VALID (27) +#define AXP202_IRQ_VBUS_UN_VALID (28) +#define AXP202_IRQ_VBUS_VALID (29) +#define AXP202_IRQ_PDOWN_BY_NOE (30) +#define AXP202_IRQ_PUP_BY_NOE (31) + +#define AXP202_IRQ_GPIO0TG (32) +#define AXP202_IRQ_GPIO1TG (33) +#define AXP202_IRQ_GPIO2TG (34) +#define AXP202_IRQ_GPIO3TG (35) +#define AXP202_IRQ_PEKFE (37) +#define AXP202_IRQ_PEKRE (38) +#define AXP202_IRQ_TIMER (39) + +//Signal Capture +#define AXP202_BATT_VOLTAGE_STEP (1.1F) +#define AXP202_BATT_DISCHARGE_CUR_STEP (0.5F) +#define AXP202_BATT_CHARGE_CUR_STEP (0.5F) +#define AXP202_ACIN_VOLTAGE_STEP (1.7F) +#define AXP202_ACIN_CUR_STEP (0.625F) +#define AXP202_VBUS_VOLTAGE_STEP (1.7F) +#define AXP202_VBUS_CUR_STEP (0.375F) +#define AXP202_INTERNAL_TEMP_STEP (0.1F) +#define AXP202_APS_VOLTAGE_STEP (1.4F) +#define AXP202_TS_PIN_OUT_STEP (0.8F) +#define AXP202_GPIO0_STEP (0.5F) +#define AXP202_GPIO1_STEP (0.5F) +// AXP192 only +#define AXP202_GPIO2_STEP (0.5F) +#define AXP202_GPIO3_STEP (0.5F) + +// AXP173 +#define AXP173_EXTEN_DC2_CTL (0x10) +#define AXP173_CTL_DC2_BIT (0) +#define AXP173_CTL_EXTEN_BIT (2) +#define AXP173_DC1_VLOTAGE (0x26) +#define AXP173_LDO4_VLOTAGE (0x27) + +#define FORCED_OPEN_DCDC3(x) (x |= (AXP202_ON << AXP202_DCDC3)) +#define BIT_MASK(x) (1 << x) +#define IS_OPEN(reg, channel) (bool)(reg & BIT_MASK(channel)) + +enum { + AXP202_EXTEN = 0, + AXP202_DCDC3 = 1, + AXP202_LDO2 = 2, + AXP202_LDO4 = 3, + AXP202_DCDC2 = 4, + AXP202_LDO3 = 6, + AXP202_OUTPUT_MAX, +}; + +enum { + AXP192_DCDC1 = 0, + AXP192_DCDC3 = 1, + AXP192_LDO2 = 2, + AXP192_LDO3 = 3, + AXP192_DCDC2 = 4, + AXP192_EXTEN = 6, + AXP192_OUTPUT_MAX, +}; + +enum { + AXP173_DCDC1 = 0, + AXP173_LDO4 = 1, + AXP173_LDO2 = 2, + AXP173_LDO3 = 3, + AXP173_DCDC2 = 4, + AXP173_EXTEN = 6, + AXP173_OUTPUT_MAX, +}; + +typedef enum { + AXP202_STARTUP_TIME_128MS, + AXP202_STARTUP_TIME_3S, + AXP202_STARTUP_TIME_1S, + AXP202_STARTUP_TIME_2S, +} axp202_startup_time_t; + +typedef enum { + AXP192_STARTUP_TIME_128MS, + AXP192_STARTUP_TIME_512MS, + AXP192_STARTUP_TIME_1S, + AXP192_STARTUP_TIME_2S, +} axp192_startup_time_t; + +typedef enum { + AXP_LONGPRESS_TIME_1S, + AXP_LONGPRESS_TIME_1S5, + AXP_LONGPRESS_TIME_2S, + AXP_LONGPRESS_TIME_2S5, +} axp_loonPress_time_t; + +typedef enum { + AXP_POWER_OFF_TIME_4S, + AXP_POWER_OFF_TIME_65, + AXP_POWER_OFF_TIME_8S, + AXP_POWER_OFF_TIME_16S, +} axp_poweroff_time_t; + +//REG 33H: Charging control 1 Charging target-voltage setting +typedef enum { + AXP202_TARGET_VOL_4_1V, + AXP202_TARGET_VOL_4_15V, + AXP202_TARGET_VOL_4_2V, + AXP202_TARGET_VOL_4_36V +} axp_chargeing_vol_t; + +//REG 82H: ADC Enable 1 register Parameter +typedef enum { + AXP202_BATT_VOL_ADC1 = 1 << 7, + AXP202_BATT_CUR_ADC1 = 1 << 6, + AXP202_ACIN_VOL_ADC1 = 1 << 5, + AXP202_ACIN_CUR_ADC1 = 1 << 4, + AXP202_VBUS_VOL_ADC1 = 1 << 3, + AXP202_VBUS_CUR_ADC1 = 1 << 2, + AXP202_APS_VOL_ADC1 = 1 << 1, + AXP202_TS_PIN_ADC1 = 1 << 0 +} axp_adc1_func_t; + +// REG 83H: ADC Enable 2 register Parameter +typedef enum { + AXP202_TEMP_MONITORING_ADC2 = 1 << 7, + AXP202_GPIO1_FUNC_ADC2 = 1 << 3, + AXP202_GPIO0_FUNC_ADC2 = 1 << 2 +} axp_adc2_func_t; + +typedef enum { + AXP202_LDO3_MODE_LDO, + AXP202_LDO3_MODE_DCIN +} axp202_ldo3_mode_t; + + + +typedef enum { + //! IRQ1 REG 40H + AXP202_VBUS_VHOLD_LOW_IRQ = _BV(1), //VBUS is available, but lower than V HOLD, IRQ enable + AXP202_VBUS_REMOVED_IRQ = _BV(2), //VBUS removed, IRQ enable + AXP202_VBUS_CONNECT_IRQ = _BV(3), //VBUS connected, IRQ enable + AXP202_VBUS_OVER_VOL_IRQ = _BV(4), //VBUS over-voltage, IRQ enable + AXP202_ACIN_REMOVED_IRQ = _BV(5), //ACIN removed, IRQ enable + AXP202_ACIN_CONNECT_IRQ = _BV(6), //ACIN connected, IRQ enable + AXP202_ACIN_OVER_VOL_IRQ = _BV(7), //ACIN over-voltage, IRQ enable + + //! IRQ2 REG 41H + AXP202_BATT_LOW_TEMP_IRQ = _BV(8), //Battery low-temperature, IRQ enable + AXP202_BATT_OVER_TEMP_IRQ = _BV(9), //Battery over-temperature, IRQ enable + AXP202_CHARGING_FINISHED_IRQ = _BV(10), //Charge finished, IRQ enable + AXP202_CHARGING_IRQ = _BV(11), //Be charging, IRQ enable + AXP202_BATT_EXIT_ACTIVATE_IRQ = _BV(12), //Exit battery activate mode, IRQ enable + AXP202_BATT_ACTIVATE_IRQ = _BV(13), //Battery activate mode, IRQ enable + AXP202_BATT_REMOVED_IRQ = _BV(14), //Battery removed, IRQ enable + AXP202_BATT_CONNECT_IRQ = _BV(15), //Battery connected, IRQ enable + + //! IRQ3 REG 42H + AXP202_PEK_LONGPRESS_IRQ = _BV(16), //PEK long press, IRQ enable + AXP202_PEK_SHORTPRESS_IRQ = _BV(17), //PEK short press, IRQ enable + AXP202_LDO3_LOW_VOL_IRQ = _BV(18), //LDO3output voltage is lower than the set value, IRQ enable + AXP202_DC3_LOW_VOL_IRQ = _BV(19), //DC-DC3output voltage is lower than the set value, IRQ enable + AXP202_DC2_LOW_VOL_IRQ = _BV(20), //DC-DC2 output voltage is lower than the set value, IRQ enable + //**Reserved and unchangeable BIT 5 + AXP202_CHARGE_LOW_CUR_IRQ = _BV(22), //Charge current is lower than the set current, IRQ enable + AXP202_CHIP_TEMP_HIGH_IRQ = _BV(23), //AXP202 internal over-temperature, IRQ enable + + //! IRQ4 REG 43H + AXP202_APS_LOW_VOL_LEVEL2_IRQ = _BV(24), //APS low-voltage, IRQ enable(LEVEL2) + APX202_APS_LOW_VOL_LEVEL1_IRQ = _BV(25), //APS low-voltage, IRQ enable(LEVEL1) + AXP202_VBUS_SESSION_END_IRQ = _BV(26), //VBUS Session End IRQ enable + AXP202_VBUS_SESSION_AB_IRQ = _BV(27), //VBUS Session A/B IRQ enable + AXP202_VBUS_INVALID_IRQ = _BV(28), //VBUS invalid, IRQ enable + AXP202_VBUS_VAILD_IRQ = _BV(29), //VBUS valid, IRQ enable + AXP202_NOE_OFF_IRQ = _BV(30), //N_OE shutdown, IRQ enable + AXP202_NOE_ON_IRQ = _BV(31), //N_OE startup, IRQ enable + + //! IRQ5 REG 44H + AXP202_GPIO0_EDGE_TRIGGER_IRQ = _BV(32), //GPIO0 input edge trigger, IRQ enable + AXP202_GPIO1_EDGE_TRIGGER_IRQ = _BV(33), //GPIO1input edge trigger or ADC input, IRQ enable + AXP202_GPIO2_EDGE_TRIGGER_IRQ = _BV(34), //GPIO2input edge trigger, IRQ enable + AXP202_GPIO3_EDGE_TRIGGER_IRQ = _BV(35), //GPIO3 input edge trigger, IRQ enable + //**Reserved and unchangeable BIT 4 + AXP202_PEK_FALLING_EDGE_IRQ = _BV(37), //PEK press falling edge, IRQ enable + AXP202_PEK_RISING_EDGE_IRQ = _BV(38), //PEK press rising edge, IRQ enable + AXP202_TIMER_TIMEOUT_IRQ = _BV(39), //Timer timeout, IRQ enable + + AXP202_ALL_IRQ = (0xFFFFFFFFFFULL) +} axp_irq_t; + +typedef enum { + AXP202_LDO4_1250MV, + AXP202_LDO4_1300MV, + AXP202_LDO4_1400MV, + AXP202_LDO4_1500MV, + AXP202_LDO4_1600MV, + AXP202_LDO4_1700MV, + AXP202_LDO4_1800MV, + AXP202_LDO4_1900MV, + AXP202_LDO4_2000MV, + AXP202_LDO4_2500MV, + AXP202_LDO4_2700MV, + AXP202_LDO4_2800MV, + AXP202_LDO4_3000MV, + AXP202_LDO4_3100MV, + AXP202_LDO4_3200MV, + AXP202_LDO4_3300MV, + AXP202_LDO4_MAX, +} axp_ldo4_table_t; + +typedef enum { + AXP202_LDO5_1800MV, + AXP202_LDO5_2500MV, + AXP202_LDO5_2800MV, + AXP202_LDO5_3000MV, + AXP202_LDO5_3100MV, + AXP202_LDO5_3300MV, + AXP202_LDO5_3400MV, + AXP202_LDO5_3500MV, +} axp_ldo5_table_t; + +typedef enum { + AXP20X_LED_OFF, + AXP20X_LED_BLINK_1HZ, + AXP20X_LED_BLINK_4HZ, + AXP20X_LED_LOW_LEVEL, +} axp_chgled_mode_t; + +typedef enum { + AXP_ADC_SAMPLING_RATE_25HZ = 0, + AXP_ADC_SAMPLING_RATE_50HZ = 1, + AXP_ADC_SAMPLING_RATE_100HZ = 2, + AXP_ADC_SAMPLING_RATE_200HZ = 3, +} axp_adc_sampling_rate_t; + +typedef enum { + AXP_TS_PIN_CURRENT_20UA = 0, + AXP_TS_PIN_CURRENT_40UA = 1, + AXP_TS_PIN_CURRENT_60UA = 2, + AXP_TS_PIN_CURRENT_80UA = 3, +} axp_ts_pin_current_t; + +typedef enum { + AXP_TS_PIN_FUNCTION_BATT = 0, + AXP_TS_PIN_FUNCTION_ADC = 1, +} axp_ts_pin_function_t; + +typedef enum { + AXP_TS_PIN_MODE_DISABLE = 0, + AXP_TS_PIN_MODE_CHARGING = 1, + AXP_TS_PIN_MODE_SAMPLING = 2, + AXP_TS_PIN_MODE_ENABLE = 3, +} axp_ts_pin_mode_t; + +//! Only AXP192 and AXP202 have gpio function +typedef enum { + AXP_GPIO_0, + AXP_GPIO_1, + AXP_GPIO_2, + AXP_GPIO_3, + AXP_GPIO_4, +} axp_gpio_t; + +typedef enum { + AXP_IO_OUTPUT_LOW_MODE, + AXP_IO_OUTPUT_HIGH_MODE, + AXP_IO_INPUT_MODE, + AXP_IO_LDO_MODE, + AXP_IO_ADC_MODE, + AXP_IO_FLOATING_MODE, + AXP_IO_OPEN_DRAIN_OUTPUT_MODE, + AXP_IO_PWM_OUTPUT_MODE, + AXP_IO_EXTERN_CHARGING_CTRL_MODE, +} axp_gpio_mode_t; + +typedef enum { + AXP_IRQ_NONE, + AXP_IRQ_RISING, + AXP_IRQ_FALLING, + AXP_IRQ_DOUBLE_EDGE, +} axp_gpio_irq_t; + + +typedef enum { + AXP192_GPIO_1V8, + AXP192_GPIO_1V9, + AXP192_GPIO_2V0, + AXP192_GPIO_2V1, + AXP192_GPIO_2V2, + AXP192_GPIO_2V3, + AXP192_GPIO_2V4, + AXP192_GPIO_2V5, + AXP192_GPIO_2V6, + AXP192_GPIO_2V7, + AXP192_GPIO_2V8, + AXP192_GPIO_2V9, + AXP192_GPIO_3V0, + AXP192_GPIO_3V1, + AXP192_GPIO_3V2, + AXP192_GPIO_3V3, +} axp192_gpio_voltage_t; + +typedef enum { + AXP1XX_CHARGE_CUR_100MA, + AXP1XX_CHARGE_CUR_190MA, + AXP1XX_CHARGE_CUR_280MA, + AXP1XX_CHARGE_CUR_360MA, + AXP1XX_CHARGE_CUR_450MA, + AXP1XX_CHARGE_CUR_550MA, + AXP1XX_CHARGE_CUR_630MA, + AXP1XX_CHARGE_CUR_700MA, + AXP1XX_CHARGE_CUR_780MA, + AXP1XX_CHARGE_CUR_880MA, + AXP1XX_CHARGE_CUR_960MA, + AXP1XX_CHARGE_CUR_1000MA, + AXP1XX_CHARGE_CUR_1080MA, + AXP1XX_CHARGE_CUR_1160MA, + AXP1XX_CHARGE_CUR_1240MA, + AXP1XX_CHARGE_CUR_1320MA, +} axp1xx_charge_current_t; + +typedef uint8_t (*axp_com_fptr_t)(uint8_t dev_addr, uint8_t reg_addr, uint8_t *data, uint8_t len); + + +class AXP20X_Class +{ +public: + int begin(TwoWire &port = Wire, uint8_t addr = AXP202_SLAVE_ADDRESS, bool isAxp173 = false); + int begin(axp_com_fptr_t read_cb, axp_com_fptr_t write_cb, uint8_t addr = AXP202_SLAVE_ADDRESS, bool isAxp173 = false); + + // Power Output Control + int setPowerOutPut(uint8_t ch, bool en); + + bool isBatteryConnect(); + bool isChargeing(); + bool isLDO2Enable(); + bool isLDO3Enable(); + bool isLDO4Enable(); + bool isDCDC3Enable(); + bool isDCDC2Enable(); + bool isChargeingEnable(); + bool isVBUSPlug(); + bool isExtenEnable(); + + //Only axp192 chip + bool isDCDC1Enable(); + + + //IRQ Status + bool isAcinOverVoltageIRQ(); + bool isAcinPlugInIRQ(); + bool isAcinRemoveIRQ(); + bool isVbusOverVoltageIRQ(); + bool isVbusPlugInIRQ(); + bool isVbusRemoveIRQ(); + bool isVbusLowVHOLDIRQ(); + + bool isBattPlugInIRQ(); + bool isBattRemoveIRQ(); + bool isBattEnterActivateIRQ(); + bool isBattExitActivateIRQ(); + bool isChargingIRQ(); + bool isChargingDoneIRQ(); + bool isBattTempLowIRQ(); + bool isBattTempHighIRQ(); + + bool isPEKShortPressIRQ(); + bool isPEKLongtPressIRQ(); + bool isTimerTimeoutIRQ(); + + //! Group4 ADC data + float getAcinVoltage(); + float getAcinCurrent(); + float getVbusVoltage(); + float getVbusCurrent(); + float getTemp(); + float getTSTemp(); + float getGPIO0Voltage(); + float getGPIO1Voltage(); + float getBattInpower(); + float getBattVoltage(); + float getBattChargeCurrent(); + float getBattDischargeCurrent(); + float getSysIPSOUTVoltage(); + uint32_t getBattChargeCoulomb(); + uint32_t getBattDischargeCoulomb(); + float getSettingChargeCurrent(); + + int setChargingTargetVoltage(axp_chargeing_vol_t param); + int enableChargeing(bool en); + + int adc1Enable(uint16_t params, bool en); + int adc2Enable(uint16_t params, bool en); + + int setTScurrent(axp_ts_pin_current_t current); + int setTSfunction(axp_ts_pin_function_t func); + int setTSmode(axp_ts_pin_mode_t mode); + + + int setTimer(uint8_t minutes); + int offTimer(); + int clearTimerStatus(); + /** + * param: axp202_startup_time_t or axp192_startup_time_t + */ + int setStartupTime(uint8_t param); + + /** + * param: axp_loonPress_time_t + */ + int setlongPressTime(uint8_t param); + + /** + * @param param: axp_poweroff_time_t + */ + int setShutdownTime(uint8_t param); + + int setTimeOutShutdown(bool en); + + int shutdown(); + + /** + * params: axp_irq_t + */ + int enableIRQ(uint64_t params, bool en); + int readIRQ(); + void clearIRQ(); + + int setDCDC1Voltage(uint16_t mv); //! Only AXP192 support and AXP173 + // return mv + uint16_t getDCDC1Voltage(); //! Only AXP192 support and AXP173 + + // ----------------- + + /* + !! Chip resource table + | CHIP | AXP173 | AXP192 | AXP202 | + | -------- | ---------------- | ---------------- | ---------------- | + | DC1 | 0v7~3v5 /1200mA | 0v7~3v5 /1200mA | X | + | DC2 | 0v7~2v275/1600mA | 0v7~2v275/1600mA | 0v7~2v275/1600mA | + | DC3 | X | 0v7~3v5 /700mA | 0v7~3v5 /1200mA | + | LDO1 | 3v3 /30mA | 3v3 /30mA | 3v3 /30mA | + | LDO2 | 1v8~3v3 /200mA | 1v8~3v3 /200mA | 1v8~3v3 /200mA | + | LDO3 | 1v8~3v3 /200mA | 1v8~3v3 /200mA | 0v7~3v3 /200mA | + | LDO4 | 0v7~3v5 /500mA | X | 1v8~3v3 /200mA | + | LDO5/IO0 | X | 1v8~3v3 /50mA | 1v8~3v3 /50mA | + */ + int setDCDC2Voltage(uint16_t mv); + uint16_t getDCDC2Voltage(); + + int setDCDC3Voltage(uint16_t mv); + uint16_t getDCDC3Voltage(); + + int setLDO2Voltage(uint16_t mv); + uint16_t getLDO2Voltage(); + + int setLDO3Voltage(uint16_t mv); + uint16_t getLDO3Voltage(); + + + int setLDO4Voltage(axp_ldo4_table_t param); //! Only axp202 support + int setLDO4Voltage(uint16_t mv); //! Only axp173 support + + // return mv + uint16_t getLDO4Voltage(); //! Only axp173/axp202 support + + + /** + * @param mode: axp_chgled_mode_t + */ + int setChgLEDMode(axp_chgled_mode_t mode); + + /** + * @param mode: axp202_ldo3_mode_t + */ + int setLDO3Mode(uint8_t mode); //! Only AXP202 support + + int getBattPercentage(); + + int debugCharging(); + int debugStatus(); + int limitingOff(); + + int setAdcSamplingRate(axp_adc_sampling_rate_t rate); + uint8_t getAdcSamplingRate(); + float getCoulombData(); + uint8_t getCoulombRegister(); + int setCoulombRegister(uint8_t val); + int EnableCoulombcounter(void); + int DisableCoulombcounter(void); + int StopCoulombcounter(void); + int ClearCoulombcounter(void); + + + int setGPIOMode(axp_gpio_t gpio, axp_gpio_mode_t mode); + int setGPIOIrq(axp_gpio_t gpio, axp_gpio_irq_t irq); + int setLDO5Voltage(axp_ldo5_table_t vol); + + int gpioWrite(axp_gpio_t gpio, uint8_t vol); + int gpioRead(axp_gpio_t gpio); + + // When the chip is axp192 / 173, the allowed values are 0 ~ 15, corresponding to the axp1xx_charge_current_t enumeration + // When the chip is axp202 allows maximum charging current of 1800mA, minimum 300mA + int getChargeControlCur(); + int setChargeControlCur(uint16_t mA); + +private: + uint16_t _getRegistH8L5(uint8_t regh8, uint8_t regl5) + { + uint8_t hv, lv; + _readByte(regh8, 1, &hv); + _readByte(regl5, 1, &lv); + return (hv << 5) | (lv & 0x1F); + } + + uint16_t _getRegistResult(uint8_t regh8, uint8_t regl4) + { + uint8_t hv, lv; + _readByte(regh8, 1, &hv); + _readByte(regl4, 1, &lv); + return (hv << 4) | (lv & 0x0F); + } + + int _readByte(uint8_t reg, uint8_t nbytes, uint8_t *data) + { + if (_read_cb != nullptr) { + return _read_cb(_address, reg, data, nbytes); + } + if (nbytes == 0 || !data) + return -1; + _i2cPort->beginTransmission(_address); + _i2cPort->write(reg); + _i2cPort->endTransmission(); + _i2cPort->requestFrom(_address, nbytes); + uint8_t index = 0; + while (_i2cPort->available()) + data[index++] = _i2cPort->read(); + return 0; + } + + int _writeByte(uint8_t reg, uint8_t nbytes, uint8_t *data) + { + if (_write_cb != nullptr) { + return _write_cb(_address, reg, data, nbytes); + } + if (nbytes == 0 || !data) + return -1; + _i2cPort->beginTransmission(_address); + _i2cPort->write(reg); + for (uint8_t i = 0; i < nbytes; i++) { + _i2cPort->write(data[i]); + } + _i2cPort->endTransmission(); + return 0; + } + + int _setGpioInterrupt(uint8_t *val, int mode, bool en); + int _axp_probe(); + int _axp_irq_mask(axp_gpio_irq_t irq); + + int _axp192_gpio_set(axp_gpio_t gpio, axp_gpio_mode_t mode); + int _axp192_gpio_0_select( axp_gpio_mode_t mode); + int _axp192_gpio_1_select( axp_gpio_mode_t mode); + int _axp192_gpio_3_select( axp_gpio_mode_t mode); + int _axp192_gpio_4_select( axp_gpio_mode_t mode); + + int _axp202_gpio_set(axp_gpio_t gpio, axp_gpio_mode_t mode); + int _axp202_gpio_0_select( axp_gpio_mode_t mode); + int _axp202_gpio_1_select( axp_gpio_mode_t mode); + int _axp202_gpio_2_select( axp_gpio_mode_t mode); + int _axp202_gpio_3_select( axp_gpio_mode_t mode); + int _axp202_gpio_irq_set(axp_gpio_t gpio, axp_gpio_irq_t irq); + int _axp202_gpio_write(axp_gpio_t gpio, uint8_t val); + int _axp202_gpio_read(axp_gpio_t gpio); + + + static const uint8_t startupParams[], longPressParams[], shutdownParams[], targetVolParams[]; + static uint8_t _outputReg; + uint8_t _address, _irq[5], _chip_id, _gpio[4]; + bool _init = false; + axp_com_fptr_t _read_cb = nullptr; + axp_com_fptr_t _write_cb = nullptr; + TwoWire *_i2cPort; + bool _isAxp173; +}; diff --git a/lib/libesp32/TTGO_TWatch_Library/src/bma.cpp b/lib/libesp32_div/TTGO_TWatch_Library/src/bma.cpp old mode 100755 new mode 100644 similarity index 95% rename from lib/libesp32/TTGO_TWatch_Library/src/bma.cpp rename to lib/libesp32_div/TTGO_TWatch_Library/src/bma.cpp index 76d1c52f0..3d843a549 --- a/lib/libesp32/TTGO_TWatch_Library/src/bma.cpp +++ b/lib/libesp32_div/TTGO_TWatch_Library/src/bma.cpp @@ -1,279 +1,279 @@ -#include "bma.h" -#include - -I2CBus *BMA::_bus = nullptr; - -BMA::BMA(I2CBus &bus) -{ - _bus = &bus; -} - -BMA::~BMA() -{ - -} - -uint16_t BMA::read(uint8_t addr, uint8_t reg, uint8_t *data, uint16_t len) -{ - return _bus->readBytes(addr, reg, data, len); -} - -uint16_t BMA::write(uint8_t addr, uint8_t reg, uint8_t *data, uint16_t len) -{ - return _bus->writeBytes(addr, reg, data, len); -} - -bool BMA::begin() -{ - _dev.dev_addr = BMA4_I2C_ADDR_SECONDARY; - _dev.interface = BMA4_I2C_INTERFACE; - _dev.bus_read = read; - _dev.bus_write = write; - _dev.delay = delay; - _dev.read_write_len = 8; - _dev.resolution = 12; - _dev.feature_len = BMA423_FEATURE_SIZE; - - reset(); - - delay(20); - - if (bma423_init(&_dev) != BMA4_OK) { - //Serial.println("bma4 init fail"); - return false; - } - - config(); - - return true; -} - -void BMA::reset() -{ - uint8_t reg = 0xB6; - _bus->writeBytes(BMA4_I2C_ADDR_SECONDARY, 0x7E, ®, 1); -} - -uint16_t BMA::config() -{ - return bma423_write_config_file(&_dev); -} - -bool BMA::getAccel(Accel &acc) -{ - memset(&acc, 0, sizeof(acc)); - if (bma4_read_accel_xyz(&acc, &_dev) != BMA4_OK) { - return false; - } - return true; -} - -uint8_t BMA::direction() -{ - Accel acc; - if (bma4_read_accel_xyz(&acc, &_dev) != BMA4_OK) { - return 0; - } - uint16_t absX = abs(acc.x); - uint16_t absY = abs(acc.y); - uint16_t absZ = abs(acc.z); - - if ((absZ > absX) && (absZ > absY)) { - if (acc.z > 0) { - return DIRECTION_DISP_DOWN; - } else { - return DIRECTION_DISP_UP; - } - } else if ((absY > absX) && (absY > absZ)) { - if (acc.y > 0) { - return DIRECTION_BOTTOM_EDGE; - } else { - return DIRECTION_TOP_EDGE; - } - } else { - if (acc.x < 0) { - return DIRECTION_RIGHT_EDGE; - } else { - return DIRECTION_LEFT_EDGE; - } - } -} - -float BMA::temperature() -{ - int32_t data = 0; - bma4_get_temperature(&data, BMA4_DEG, &_dev); - float res = (float)data / (float)BMA4_SCALE_TEMP; - /* 0x80 - temp read from the register and 23 is the ambient temp added. - * If the temp read from register is 0x80, it means no valid - * information is available */ - if (((data - 23) / BMA4_SCALE_TEMP) == 0x80) { - res = 0; - } - return res; -} - - -void BMA::enableAccel() -{ - if (bma4_set_accel_enable(BMA4_ENABLE, &_dev)) { - return; - } - Acfg cfg; - cfg.odr = BMA4_OUTPUT_DATA_RATE_100HZ; - cfg.range = BMA4_ACCEL_RANGE_2G; - cfg.bandwidth = BMA4_ACCEL_NORMAL_AVG4; - cfg.perf_mode = BMA4_CONTINUOUS_MODE; - - if (bma4_set_accel_config(&cfg, &_dev)) { - Serial.println("[bma4] set accel config fail"); - return; - } -} - -void BMA::disalbeIrq() -{ - bma423_map_interrupt(BMA4_INTR1_MAP, BMA423_STEP_CNTR_INT /* |BMA423_WAKEUP_INT*/, BMA4_DISABLE, &_dev); -} - -void BMA::enableIrq() -{ - bma423_map_interrupt(BMA4_INTR1_MAP, BMA423_STEP_CNTR_INT /* |BMA423_WAKEUP_INT*/, BMA4_ENABLE, &_dev); -} - -//attachInterrupt bma423 int1 -void BMA::attachInterrupt() -{ - uint16_t rslt = BMA4_OK; - enableAccel(); - // rslt |= bma423_reset_step_counter(&_dev); - rslt |= bma423_step_detector_enable(BMA4_ENABLE, &_dev); - rslt |= bma423_feature_enable(BMA423_STEP_CNTR, BMA4_ENABLE, &_dev); - rslt |= bma423_feature_enable(BMA423_WAKEUP, BMA4_ENABLE, &_dev); - rslt |= bma423_feature_enable(BMA423_TILT, BMA4_ENABLE, &_dev); - rslt |= bma423_step_counter_set_watermark(100, &_dev); - - // rslt |= bma423_map_interrupt(BMA4_INTR1_MAP, BMA423_STEP_CNTR_INT | BMA423_WAKEUP_INT, BMA4_ENABLE, &_dev); - - rslt |= bma423_map_interrupt(BMA4_INTR1_MAP, BMA423_STEP_CNTR_INT, BMA4_ENABLE, &_dev); - rslt |= bma423_map_interrupt(BMA4_INTR1_MAP, BMA423_TILT_INT, BMA4_ENABLE, &_dev); - - bma423_anymotion_enable_axis(BMA423_ALL_AXIS_DIS, &_dev); - - struct bma4_int_pin_config config ; - - config.edge_ctrl = BMA4_LEVEL_TRIGGER; - config.lvl = BMA4_ACTIVE_HIGH; - config.od = BMA4_PUSH_PULL; - config.output_en = BMA4_OUTPUT_ENABLE; - config.input_en = BMA4_INPUT_DISABLE; - rslt |= bma4_set_int_pin_config(&config, BMA4_INTR1_MAP, &_dev); - - // Serial.printf("[bma4] attachInterrupt %s\n", rslt != 0 ? "fail" : "pass"); - - - struct bma423_axes_remap remap_data; - - remap_data.x_axis = 0; - remap_data.x_axis_sign = 1; - remap_data.y_axis = 1; - remap_data.y_axis_sign = 1; - remap_data.z_axis = 2; - remap_data.z_axis_sign = 0; - - bma423_set_remap_axes(&remap_data, &_dev); - -} - -bool BMA::set_remap_axes(struct bma423_axes_remap *remap_data) -{ - return bma423_set_remap_axes(remap_data, &_dev); -} - -bool BMA::readInterrupt() -{ - return bma423_read_int_status(&_irqStatus, &_dev) == BMA4_OK; -} - -uint8_t BMA::getIrqStatus() -{ - return _irqStatus; -} - -uint32_t BMA::getCounter() -{ - uint32_t stepCount; - if (bma423_step_counter_output(&stepCount, &_dev) == BMA4_OK) { - return stepCount; - } - return 0; -} - -bool BMA::isStepCounter() -{ - return (bool)(BMA423_STEP_CNTR_INT & _irqStatus); -} - -bool BMA::isDoubleClick() -{ - return (bool)(BMA423_WAKEUP_INT & _irqStatus); -} - - -bool BMA::isTilt() -{ - return (bool)(BMA423_TILT_INT & _irqStatus); -} - - -bool BMA::isActivity() -{ - return (bool)(BMA423_ACTIVITY_INT & _irqStatus); -} - -bool BMA::isAnyNoMotion() -{ - return (bool)(BMA423_ANY_NO_MOTION_INT & _irqStatus); -} - - -const char *BMA::getActivity() -{ - uint8_t activity; - bma423_activity_output(&activity, &_dev); - if (activity & BMA423_USER_STATIONARY) { - return "BMA423_USER_STATIONARY"; - } else if (activity & BMA423_USER_WALKING) { - return "BMA423_USER_WALKING"; - } else if (activity & BMA423_USER_RUNNING) { - return "BMA423_USER_RUNNING"; - } else if (activity & BMA423_STATE_INVALID) { - return "BMA423_STATE_INVALID"; - } - return "None"; -} - -bool BMA::enableStepCountInterrupt(bool en) -{ - return (BMA4_OK == bma423_map_interrupt(BMA4_INTR1_MAP, BMA423_STEP_CNTR_INT, en, &_dev)); -} - -bool BMA::enableTiltInterrupt(bool en) -{ - return (BMA4_OK == bma423_map_interrupt(BMA4_INTR1_MAP, BMA423_TILT_INT, en, &_dev)); -} - -bool BMA::enableWakeupInterrupt(bool en) -{ - return (BMA4_OK == bma423_map_interrupt(BMA4_INTR1_MAP, BMA423_WAKEUP_INT, en, &_dev)); -} - -bool BMA::enableAnyNoMotionInterrupt(bool en) -{ - return (BMA4_OK == bma423_map_interrupt(BMA4_INTR1_MAP, BMA423_ANY_NO_MOTION_INT, en, &_dev)); -} - -bool BMA::enableActivityInterrupt(bool en) -{ - return (BMA4_OK == bma423_map_interrupt(BMA4_INTR1_MAP, BMA423_ACTIVITY_INT, en, &_dev)); -} +#include "bma.h" +#include + +I2CBus *BMA::_bus = nullptr; + +BMA::BMA(I2CBus &bus) +{ + _bus = &bus; +} + +BMA::~BMA() +{ + +} + +uint16_t BMA::read(uint8_t addr, uint8_t reg, uint8_t *data, uint16_t len) +{ + return _bus->readBytes(addr, reg, data, len); +} + +uint16_t BMA::write(uint8_t addr, uint8_t reg, uint8_t *data, uint16_t len) +{ + return _bus->writeBytes(addr, reg, data, len); +} + +bool BMA::begin() +{ + _dev.dev_addr = BMA4_I2C_ADDR_SECONDARY; + _dev.interface = BMA4_I2C_INTERFACE; + _dev.bus_read = read; + _dev.bus_write = write; + _dev.delay = delay; + _dev.read_write_len = 8; + _dev.resolution = 12; + _dev.feature_len = BMA423_FEATURE_SIZE; + + reset(); + + delay(20); + + if (bma423_init(&_dev) != BMA4_OK) { + //Serial.println("bma4 init fail"); + return false; + } + + config(); + + return true; +} + +void BMA::reset() +{ + uint8_t reg = 0xB6; + _bus->writeBytes(BMA4_I2C_ADDR_SECONDARY, 0x7E, ®, 1); +} + +uint16_t BMA::config() +{ + return bma423_write_config_file(&_dev); +} + +bool BMA::getAccel(Accel &acc) +{ + memset(&acc, 0, sizeof(acc)); + if (bma4_read_accel_xyz(&acc, &_dev) != BMA4_OK) { + return false; + } + return true; +} + +uint8_t BMA::direction() +{ + Accel acc; + if (bma4_read_accel_xyz(&acc, &_dev) != BMA4_OK) { + return 0; + } + uint16_t absX = abs(acc.x); + uint16_t absY = abs(acc.y); + uint16_t absZ = abs(acc.z); + + if ((absZ > absX) && (absZ > absY)) { + if (acc.z > 0) { + return DIRECTION_DISP_DOWN; + } else { + return DIRECTION_DISP_UP; + } + } else if ((absY > absX) && (absY > absZ)) { + if (acc.y > 0) { + return DIRECTION_BOTTOM_EDGE; + } else { + return DIRECTION_TOP_EDGE; + } + } else { + if (acc.x < 0) { + return DIRECTION_RIGHT_EDGE; + } else { + return DIRECTION_LEFT_EDGE; + } + } +} + +float BMA::temperature() +{ + int32_t data = 0; + bma4_get_temperature(&data, BMA4_DEG, &_dev); + float res = (float)data / (float)BMA4_SCALE_TEMP; + /* 0x80 - temp read from the register and 23 is the ambient temp added. + * If the temp read from register is 0x80, it means no valid + * information is available */ + if (((data - 23) / BMA4_SCALE_TEMP) == 0x80) { + res = 0; + } + return res; +} + + +void BMA::enableAccel() +{ + if (bma4_set_accel_enable(BMA4_ENABLE, &_dev)) { + return; + } + Acfg cfg; + cfg.odr = BMA4_OUTPUT_DATA_RATE_100HZ; + cfg.range = BMA4_ACCEL_RANGE_2G; + cfg.bandwidth = BMA4_ACCEL_NORMAL_AVG4; + cfg.perf_mode = BMA4_CONTINUOUS_MODE; + + if (bma4_set_accel_config(&cfg, &_dev)) { + Serial.println("[bma4] set accel config fail"); + return; + } +} + +void BMA::disalbeIrq() +{ + bma423_map_interrupt(BMA4_INTR1_MAP, BMA423_STEP_CNTR_INT /* |BMA423_WAKEUP_INT*/, BMA4_DISABLE, &_dev); +} + +void BMA::enableIrq() +{ + bma423_map_interrupt(BMA4_INTR1_MAP, BMA423_STEP_CNTR_INT /* |BMA423_WAKEUP_INT*/, BMA4_ENABLE, &_dev); +} + +//attachInterrupt bma423 int1 +void BMA::attachInterrupt() +{ + uint16_t rslt = BMA4_OK; + enableAccel(); + // rslt |= bma423_reset_step_counter(&_dev); + rslt |= bma423_step_detector_enable(BMA4_ENABLE, &_dev); + rslt |= bma423_feature_enable(BMA423_STEP_CNTR, BMA4_ENABLE, &_dev); + rslt |= bma423_feature_enable(BMA423_WAKEUP, BMA4_ENABLE, &_dev); + rslt |= bma423_feature_enable(BMA423_TILT, BMA4_ENABLE, &_dev); + rslt |= bma423_step_counter_set_watermark(100, &_dev); + + // rslt |= bma423_map_interrupt(BMA4_INTR1_MAP, BMA423_STEP_CNTR_INT | BMA423_WAKEUP_INT, BMA4_ENABLE, &_dev); + + rslt |= bma423_map_interrupt(BMA4_INTR1_MAP, BMA423_STEP_CNTR_INT, BMA4_ENABLE, &_dev); + rslt |= bma423_map_interrupt(BMA4_INTR1_MAP, BMA423_TILT_INT, BMA4_ENABLE, &_dev); + + bma423_anymotion_enable_axis(BMA423_ALL_AXIS_DIS, &_dev); + + struct bma4_int_pin_config config ; + + config.edge_ctrl = BMA4_LEVEL_TRIGGER; + config.lvl = BMA4_ACTIVE_HIGH; + config.od = BMA4_PUSH_PULL; + config.output_en = BMA4_OUTPUT_ENABLE; + config.input_en = BMA4_INPUT_DISABLE; + rslt |= bma4_set_int_pin_config(&config, BMA4_INTR1_MAP, &_dev); + + // Serial.printf("[bma4] attachInterrupt %s\n", rslt != 0 ? "fail" : "pass"); + + + struct bma423_axes_remap remap_data; + + remap_data.x_axis = 0; + remap_data.x_axis_sign = 1; + remap_data.y_axis = 1; + remap_data.y_axis_sign = 1; + remap_data.z_axis = 2; + remap_data.z_axis_sign = 0; + + bma423_set_remap_axes(&remap_data, &_dev); + +} + +bool BMA::set_remap_axes(struct bma423_axes_remap *remap_data) +{ + return bma423_set_remap_axes(remap_data, &_dev); +} + +bool BMA::readInterrupt() +{ + return bma423_read_int_status(&_irqStatus, &_dev) == BMA4_OK; +} + +uint8_t BMA::getIrqStatus() +{ + return _irqStatus; +} + +uint32_t BMA::getCounter() +{ + uint32_t stepCount; + if (bma423_step_counter_output(&stepCount, &_dev) == BMA4_OK) { + return stepCount; + } + return 0; +} + +bool BMA::isStepCounter() +{ + return (bool)(BMA423_STEP_CNTR_INT & _irqStatus); +} + +bool BMA::isDoubleClick() +{ + return (bool)(BMA423_WAKEUP_INT & _irqStatus); +} + + +bool BMA::isTilt() +{ + return (bool)(BMA423_TILT_INT & _irqStatus); +} + + +bool BMA::isActivity() +{ + return (bool)(BMA423_ACTIVITY_INT & _irqStatus); +} + +bool BMA::isAnyNoMotion() +{ + return (bool)(BMA423_ANY_NO_MOTION_INT & _irqStatus); +} + + +const char *BMA::getActivity() +{ + uint8_t activity; + bma423_activity_output(&activity, &_dev); + if (activity & BMA423_USER_STATIONARY) { + return "BMA423_USER_STATIONARY"; + } else if (activity & BMA423_USER_WALKING) { + return "BMA423_USER_WALKING"; + } else if (activity & BMA423_USER_RUNNING) { + return "BMA423_USER_RUNNING"; + } else if (activity & BMA423_STATE_INVALID) { + return "BMA423_STATE_INVALID"; + } + return "None"; +} + +bool BMA::enableStepCountInterrupt(bool en) +{ + return (BMA4_OK == bma423_map_interrupt(BMA4_INTR1_MAP, BMA423_STEP_CNTR_INT, en, &_dev)); +} + +bool BMA::enableTiltInterrupt(bool en) +{ + return (BMA4_OK == bma423_map_interrupt(BMA4_INTR1_MAP, BMA423_TILT_INT, en, &_dev)); +} + +bool BMA::enableWakeupInterrupt(bool en) +{ + return (BMA4_OK == bma423_map_interrupt(BMA4_INTR1_MAP, BMA423_WAKEUP_INT, en, &_dev)); +} + +bool BMA::enableAnyNoMotionInterrupt(bool en) +{ + return (BMA4_OK == bma423_map_interrupt(BMA4_INTR1_MAP, BMA423_ANY_NO_MOTION_INT, en, &_dev)); +} + +bool BMA::enableActivityInterrupt(bool en) +{ + return (BMA4_OK == bma423_map_interrupt(BMA4_INTR1_MAP, BMA423_ACTIVITY_INT, en, &_dev)); +} diff --git a/lib/libesp32/TTGO_TWatch_Library/src/bma.h b/lib/libesp32_div/TTGO_TWatch_Library/src/bma.h old mode 100755 new mode 100644 similarity index 96% rename from lib/libesp32/TTGO_TWatch_Library/src/bma.h rename to lib/libesp32_div/TTGO_TWatch_Library/src/bma.h index 31a13ec6c..f3104305b --- a/lib/libesp32/TTGO_TWatch_Library/src/bma.h +++ b/lib/libesp32_div/TTGO_TWatch_Library/src/bma.h @@ -1,64 +1,64 @@ - -#pragma once - -#include "bma423.h" -#include "i2c_bus.h" - - -enum { - DIRECTION_TOP_EDGE = 0, - DIRECTION_BOTTOM_EDGE = 1, - DIRECTION_LEFT_EDGE = 2, - DIRECTION_RIGHT_EDGE = 3, - DIRECTION_DISP_UP = 4, - DIRECTION_DISP_DOWN = 5 -} ; -typedef struct bma4_dev Bma; -typedef struct bma4_accel Accel; -typedef struct bma4_accel_config Acfg; - -class BMA -{ -public: - BMA(I2CBus &bus); - ~BMA(); - bool begin(); - void reset(); - uint8_t direction(); - float temperature(); - void enableAccel(); - - void disalbeIrq(); - void enableIrq(); - void attachInterrupt(); - uint32_t getCounter(); - bool isStepCounter(); - bool isDoubleClick(); - bool readInterrupt(); - bool isTilt(); - bool isActivity(); - bool isAnyNoMotion(); - bool getAccel(Accel &acc); - uint8_t getIrqStatus(); - const char * getActivity(); - + +#pragma once + +#include "bma423.h" +#include "i2c_bus.h" + + +enum { + DIRECTION_TOP_EDGE = 0, + DIRECTION_BOTTOM_EDGE = 1, + DIRECTION_LEFT_EDGE = 2, + DIRECTION_RIGHT_EDGE = 3, + DIRECTION_DISP_UP = 4, + DIRECTION_DISP_DOWN = 5 +} ; +typedef struct bma4_dev Bma; +typedef struct bma4_accel Accel; +typedef struct bma4_accel_config Acfg; + +class BMA +{ +public: + BMA(I2CBus &bus); + ~BMA(); + bool begin(); + void reset(); + uint8_t direction(); + float temperature(); + void enableAccel(); + + void disalbeIrq(); + void enableIrq(); + void attachInterrupt(); + uint32_t getCounter(); + bool isStepCounter(); + bool isDoubleClick(); + bool readInterrupt(); + bool isTilt(); + bool isActivity(); + bool isAnyNoMotion(); + bool getAccel(Accel &acc); + uint8_t getIrqStatus(); + const char * getActivity(); + bool set_remap_axes(struct bma423_axes_remap *remap_data); - bool enableStepCountInterrupt(bool en = true); - bool enableTiltInterrupt(bool en = true); - bool enableWakeupInterrupt(bool en = true); - bool enableAnyNoMotionInterrupt(bool en = true); - bool enableActivityInterrupt(bool en = true); - -private: - static uint16_t read(uint8_t dev_addr, uint8_t reg_addr, uint8_t *read_data, uint16_t len); - static uint16_t write(uint8_t dev_addr, uint8_t reg_addr, uint8_t *read_data, uint16_t len); - - uint16_t config(); - Bma _dev; - static bma4_com_fptr_t _read; - static bma4_com_fptr_t _write; - static I2CBus *_bus; - bool _irqRead = false; - uint16_t _irqStatus; - + bool enableStepCountInterrupt(bool en = true); + bool enableTiltInterrupt(bool en = true); + bool enableWakeupInterrupt(bool en = true); + bool enableAnyNoMotionInterrupt(bool en = true); + bool enableActivityInterrupt(bool en = true); + +private: + static uint16_t read(uint8_t dev_addr, uint8_t reg_addr, uint8_t *read_data, uint16_t len); + static uint16_t write(uint8_t dev_addr, uint8_t reg_addr, uint8_t *read_data, uint16_t len); + + uint16_t config(); + Bma _dev; + static bma4_com_fptr_t _read; + static bma4_com_fptr_t _write; + static I2CBus *_bus; + bool _irqRead = false; + uint16_t _irqStatus; + }; diff --git a/lib/libesp32/TTGO_TWatch_Library/src/bma4.c b/lib/libesp32_div/TTGO_TWatch_Library/src/bma4.c old mode 100755 new mode 100644 similarity index 96% rename from lib/libesp32/TTGO_TWatch_Library/src/bma4.c rename to lib/libesp32_div/TTGO_TWatch_Library/src/bma4.c index 01a59a2fd..221b20831 --- a/lib/libesp32/TTGO_TWatch_Library/src/bma4.c +++ b/lib/libesp32_div/TTGO_TWatch_Library/src/bma4.c @@ -1,4204 +1,4204 @@ -/* -**************************************************************************** -* Copyright (C) 2015 - 2016 Bosch Sensortec GmbH -* -* File :bma4.c -* -* Date: 12 Oct 2017 -* -* Revision: 2.1.9 $ -* -* Usage: Sensor Driver for BMA4 family of sensors -* -**************************************************************************** -* Disclaimer -* -* Common: -* Bosch Sensortec products are developed for the consumer goods industry. -* They may only be used within the parameters of the respective valid -* product data sheet. Bosch Sensortec products are provided with the -* express understanding that there is no warranty of fitness for a -* particular purpose.They are not fit for use in life-sustaining, -* safety or security sensitive systems or any system or device -* that may lead to bodily harm or property damage if the system -* or device malfunctions. In addition,Bosch Sensortec products are -* not fit for use in products which interact with motor vehicle systems. -* The resale and or use of products are at the purchasers own risk and -* his own responsibility. The examination of fitness for the intended use -* is the sole responsibility of the Purchaser. -* -* The purchaser shall indemnify Bosch Sensortec from all third party -* claims, including any claims for incidental, or consequential damages, -* arising from any product use not covered by the parameters of -* the respective valid product data sheet or not approved by -* Bosch Sensortec and reimburse Bosch Sensortec for all costs in -* connection with such claims. -* -* The purchaser must monitor the market for the purchased products, -* particularly with regard to product safety and inform Bosch Sensortec -* without delay of all security relevant incidents. -* -* Engineering Samples are marked with an asterisk (*) or (e). -* Samples may vary from the valid technical specifications of the product -* series. They are therefore not intended or fit for resale to third -* parties or for use in end products. Their sole purpose is internal -* client testing. The testing of an engineering sample may in no way -* replace the testing of a product series. Bosch Sensortec assumes -* no liability for the use of engineering samples. -* By accepting the engineering samples, the Purchaser agrees to indemnify -* Bosch Sensortec from all claims arising from the use of engineering -* samples. -* -* Special: -* This software module (hereinafter called "Software") and any information -* on application-sheets (hereinafter called "Information") is provided -* free of charge for the sole purpose to support your application work. -* The Software and Information is subject to the following -* terms and conditions: -* -* The Software is specifically designed for the exclusive use for -* Bosch Sensortec products by personnel who have special experience -* and training. Do not use this Software if you do not have the -* proper experience or training. -* -* This Software package is provided `` as is `` and without any expressed -* or implied warranties,including without limitation, the implied warranties -* of merchantability and fitness for a particular purpose. -* -* Bosch Sensortec and their representatives and agents deny any liability -* for the functional impairment -* of this Software in terms of fitness, performance and safety. -* Bosch Sensortec and their representatives and agents shall not be liable -* for any direct or indirect damages or injury, except as -* otherwise stipulated in mandatory applicable law. -* -* The Information provided is believed to be accurate and reliable. -* Bosch Sensortec assumes no responsibility for the consequences of use -* of such Information nor for any infringement of patents or -* other rights of third parties which may result from its use. -* No license is granted by implication or otherwise under any patent or -* patent rights of Bosch. Specifications mentioned in the Information are -* subject to change without notice. -**************************************************************************/ -/*! \file bma4.c - \brief Sensor Driver for BMA4 family of sensors */ -/***************************************************************************/ -/**\name Header files -****************************************************************************/ -#include "bma4.h" - -/***************************************************************************/ -/**\name Static Data Buffer -****************************************************************************/ -/* Local array to store the values read from the register - * using read_regs API */ -static uint8_t temp_buff[BMA4_MAX_BUFFER_SIZE] = {0}; - -/***************************************************************************/ -/**\name Local structures -****************************************************************************/ -/*! - * @brief Accel difference value of axis. - */ -struct data_with_sign { - /*! Difference value */ - int16_t val; - /*! Indicates negative value if set */ - uint8_t is_negative; -}; - -/*! - * @brief Accel data deviation from ideal value - */ -struct offset_delta { - /*! Accel x axis */ - struct data_with_sign x; - /*! Accel y axis */ - struct data_with_sign y; - /*! Accel z axis */ - struct data_with_sign z; -}; - -/*! - * @brief Accel offset xyz structure - */ -struct accel_offset { - /*! Accel offset X data */ - uint8_t x; - /*! Accel offset Y data */ - uint8_t y; - /*! Accel offset Z data */ - uint8_t z; -}; - -/*! - * @brief Accel self test diff xyz data structure - */ -struct selftest_delta_limit { - /*! Accel X data */ - int32_t x; - /*! Accel Y data */ - int32_t y; - /*! Accel Z data */ - int32_t z; -}; - -/*! - * @brief Structure to store temp data values - */ -struct accel_temp { - /*! Accel X temp data */ - int32_t x; - /*! Accel Y temp data */ - int32_t y; - /*! Accel Z temp data */ - int32_t z; -}; - -/***************************************************************************/ -/*! Static Function Declarations -****************************************************************************/ - -/*! - * @brief This API validates the bandwidth and perfmode - * value set by the user. - * - * param bandwidth[in] : bandwidth value set by the user. - * param perf_mode[in] : perf_mode value set by the user. - */ -static uint16_t validate_bandwidth_perfmode(uint8_t bandwidth, uint8_t perf_mode); - -/*! - * @brief @brief This API validates the ODR value set by the user. - * - * param bandwidth[in] : odr for accelerometer - */ -static uint16_t validate_odr(uint8_t odr); - -/*! - * @brief This API is used to reset the FIFO related configurations - * in the fifo_frame structure. - * - * @param dev[in,out] : Structure instance of bma4_dev - * - */ -static void reset_fifo_data_structure(const struct bma4_dev *dev); - -/*! - * @brief This API computes the number of bytes of accel FIFO data - * which is to be parsed in header-less mode - * - * @param[out] start_idx : The start index for parsing data - * @param[out] len : Number of bytes to be parsed - * @param[in] acc_count : Number of accelerometer frames to be read - * @param[in] dev : Structure instance of bma4_dev. - * - */ -static void get_accel_len_to_parse(uint16_t *start_idx, uint16_t *len, const uint16_t *acc_count, - const struct bma4_dev *dev); - -/*! - * @brief This API checks the fifo read data as empty frame, if it - * is empty frame then moves the index to last byte. - * - * @param[in,out] data_index : The index of the current data to - * be parsed from fifo data - * @param[in] dev : Structure instance of bma4_dev. - */ -static void check_empty_fifo(uint16_t *data_index, const struct bma4_dev *dev); - -/*! - * @brief This API is used to parse the accelerometer data from the - * FIFO data in header mode. - * - * @param[in,out] accel_data : Structure instance of bma4_accel where - * the accelerometer data in FIFO is stored. - * @param[in,out] accel_length : Number of accelerometer frames - * (x,y,z axes data) - * @param[in,out] dev : Structure instance of bma4_dev. - * - */ -static void extract_accel_header_mode(struct bma4_accel *accel_data, uint16_t *accel_length, - const struct bma4_dev *dev); - -/*! - * @brief This API is used to parse the accelerometer data from the - * FIFO data in both header mode and header-less mode. - * It update the idx value which is used to store the index of - * the current data byte which is parsed. - * - * @param[in,out] acc : Structure instance of bma4_accel. - * @param[in,out] idx : Index value of number of bytes parsed - * @param[in,out] acc_idx : Index value of accelerometer data - * (x,y,z axes) frame to be parsed - * @param[in] frm : It consists of either fifo_data_enable - * parameter (Accel and/or mag data enabled in FIFO) - * in header-less mode or frame header data - * in header mode - * @param[in] dev : Structure instance of bma4_dev. - * - */ -static void unpack_acc_frm(struct bma4_accel *acc, uint16_t *idx, uint16_t *acc_idx, uint8_t frm, - const struct bma4_dev *dev); - -/*! - * @brief This API is used to parse the accelerometer data from the - * FIFO data and store it in the instance of the structure bma4_accel. - * - * @param[out] accel_data : Structure instance of bma4_accel where - * the parsed accel data bytes are stored. - * @param[in] data_start_index : Index value of the accel data bytes - * which is to be parsed from the fifo data. - * @param[in] dev : Structure instance of bma4_dev. - * - */ -static void unpack_accel_data(struct bma4_accel *accel_data, uint16_t data_start_index, const struct bma4_dev *dev); -/*! - * @brief This API computes the number of bytes of Mag FIFO data which is - * to be parsed in header-less mode - * - * @param[out] start_idx : The start index for parsing data - * @param[out] len : Number of bytes to be parsed - * @param[in] mag_count : Number of magnetometer frames to be read - * @param[in] dev : Structure instance of bma4_dev. - * - */ -static void get_mag_len_to_parse(uint16_t *start_idx, uint16_t *len, const uint16_t *mag_count, - const struct bma4_dev *dev); -/*! - * @brief This API is used to parse the magnetometer data from the - * FIFO data in header mode. - * - * @param[in,out] data : Structure instance of bma4_mag_xyzr where - * the magnetometer data in FIFO is extracted - * and stored. - * @param[in,out] len : Number of magnetometer frames - * (x,y,z,r data) - * @param[in,out] dev : Structure instance of bma4_dev. - * - * @return Result of API execution status - * @retval 0 -> Success - * @retval Any non zero value -> Fail - * - */ -static uint16_t extract_mag_header_mode(struct bma4_mag *data, uint16_t *len, const struct bma4_dev *dev); - -/*! - * @brief This API is used to parse the magnetometer data from the - * FIFO data in both header mode and header-less mode and update the - * idx value which is used to store the index of the current - * data byte which is parsed. - * - * @param data : Structure instance of bma4_mag_xyzr. - * @param idx : Index value of number of bytes parsed - * @param mag_idx : Index value magnetometer data frame (x,y,z,r) - * to be parsed - * @param frm : It consists of either the fifo_data_enable parameter - * (Accel and/or mag data enabled in FIFO) in - * header-less mode and frame header data in header mode - * @param dev : Structure instance of bma4_dev. - * - * @return Result of API execution status - * @retval 0 -> Success - * @retval Any non zero value -> Fail - * - */ -static uint16_t unpack_mag_frm(struct bma4_mag *data, uint16_t *idx, uint16_t *mag_idx, uint8_t frm, - const struct bma4_dev *dev); - -/*! - * @brief This API is used to parse the auxiliary magnetometer data from - * the FIFO data and store it in the instance of the structure mag_data. - * - * @param mag_data : Structure instance of bma4_mag_xyzr where the - * parsed magnetometer data bytes are stored. - * @param start_idx : Index value of the magnetometer data bytes - * which is to be parsed from the FIFO data - * @param dev : Structure instance of bma4_dev. - * - * @return Result of API execution status - * @retval 0 -> Success - * @retval Any non zero value -> Fail - * - */ -static uint16_t unpack_mag_data(struct bma4_mag *mag_data, uint16_t start_idx, const struct bma4_dev *dev); - -/*! - * @brief This API is used to parse and store the sensor time from the - * FIFO data in the structure instance dev. - * - * @param[in,out] data_index : Index of the FIFO data which - * has the sensor time. - * @param[in,out] dev : Structure instance of bma4_dev. - * - */ -static void unpack_sensortime_frame(uint16_t *data_index, const struct bma4_dev *dev); - -/*! - * @brief This API is used to parse and store the skipped_frame_count from - * the FIFO data in the structure instance dev. - * - * @param[in,out] data_index : Index of the FIFO data which - * has the skipped frame count. - * @param[in,out] dev : Structure instance of bma4_dev. - * - */ -static void unpack_skipped_frame(uint16_t *data_index, const struct bma4_dev *dev); - -/*! - * @brief This API is used to parse and store the dropped_frame_count from - * the FIFO data in the structure instance dev. - * - * @param[in,out] data_index : Index of the FIFO data which - * has the dropped frame data. - * @param[in,out] dev : Structure instance of bma4_dev. - * - */ -static void unpack_dropped_frame(uint16_t *data_index, const struct bma4_dev *dev); - -/*! - * @brief This API is used to move the data index ahead of the - * current_frame_length parameter when unnecessary FIFO data appears while - * extracting the user specified data. - * - * @param[in,out] data_index : Index of the FIFO data which - * is to be moved ahead of the - * current_frame_length - * @param[in] current_frame_length : Number of bytes in a particular frame - * @param[in] dev : Structure instance of bma4_dev. - * - */ -static void move_next_frame(uint16_t *data_index, uint8_t current_frame_length, const struct bma4_dev *dev); - -/*! -* @brief This API writes the config stream data in memory using burst mode -* -* @param[in] stream_data : Pointer to store data of 32 bytes -* @param[in] index : Represents value in multiple of 32 bytes -* @param[in] dev : Structure instance of bma4_dev. -* -* @return Result of API execution status -* @retval 0 -> Success -* @retval Any non zero value -> Fail -*/ -static uint16_t stream_transfer_write(const uint8_t *stream_data, uint16_t index, struct bma4_dev *dev); - -/*! - * @brief This API enables or disables the Accel Self test feature in the - * sensor. - * - * @param[in] accel_selftest_enable : Variable used to enable or disable - * the Accel self test feature - * Value | Description - * --------|--------------- - * 0x00 | BMA4_DISABLE - * 0x01 | BMA4_ENABLE - * - * @param[in] dev : Structure instance of bma4_dev - * - * @return Result of API execution status - * @retval 0 -> Success - * @retval Any non zero value -> Fail - * - */ -static uint16_t set_accel_selftest_enable(uint8_t accel_selftest_axis, struct bma4_dev *dev); - -/*! - * @brief This API selects the sign of Accel self-test excitation - * - * @param[in] accel_selftest_sign: Variable used to select the Accel - * self test sign - * Value | Description - * --------|-------------------------- - * 0x00 | BMA4_DISABLE (negative) - * 0x01 | BMA4_ENABLE (positive) - * - * @param[in] dev : Structure instance of bma4_dev - * - * @return Result of API execution status - * @retval 0 -> Success - * @retval Any non zero value -> Fail - * - */ -static uint16_t set_accel_selftest_sign(uint8_t accel_selftest_sign, struct bma4_dev *dev); - -/*! - * @brief This API sets the Accel self test amplitude in the sensor. - * - * @param[in] accel_selftest_amp : Variable used to specify the Accel self - * test amplitude - * Value | Description - * --------|------------------------------------ - * 0x00 | BMA4_SELFTEST_AMP_LOW - * 0x01 | BMA4_SELFTEST_AMP_HIGH - * - * @param[in] dev : structure instance of bma4_dev - * - * @return Result of API execution status - * @retval 0 -> Success - * @retval Any non zero value -> Fail - * - */ -static uint16_t set_accel_selftest_amp(uint8_t accel_selftest_amp, struct bma4_dev *dev); - -/*! - * @brief This function enables and configures the Accel which is needed - * for Self test operation. - * - * @param[in] dev : Structure instance of bma4_dev - * - * @return results of self test - * @retval 0 -> Success - * @retval Any non zero value -> Fail - * - */ -static uint16_t set_accel_selftest_config(struct bma4_dev *dev); - -/*! - * @brief This API validates the Accel g value provided as input by the - * user for Accel offset compensation. - * - * @param[in] gvalue : Pointer variable used to specify the g value - * set by the user for Accel offset compensation. - * - * @note The g-values to be passed to the parameter should be - * multiples of 1000000. - * - * @return results of the status of user input validation - * @retval 0 -> Success - * @retval Any non zero value -> Fail - * - */ -static uint16_t validate_user_input(const int32_t *gvalue); -/*! - * @brief This API converts the range value into corresponding integer - * value. - * - * @param[in] range_in : input range value. - * @param[out] range_out : pointer to store the integer value of range. - * - * @return results of the status of user input validation - * @retval 0 -> Success - * @retval Any non zero value -> Fail - * - */ -static void map_range(uint8_t range_in, uint8_t *range_out); - -/*! - * @brief This API normalise the data with offset. - * - * @param[out] compensated_data : pointer to store the compensated data. - * @param[in] offset_data : pointer of offset. - * - * @return results of the status of user input validation - * @retval 0 -> Success - * @retval Any non zero value -> Fail - * - */ -static void normalise_offset(const struct offset_delta *compensated_data, struct accel_offset *offset_data); - -/*! - * @brief This API normalise the data with offset. - * - * @param[in] res : resolution of the sensor. - * @param[in] range : G-range of the accel. - * @param[in] delta : pointer of offset_delta. - * @param[out] data : pointer to store accel_offset data. - * - * @return results of the status of user input validation - * @retval 0 -> Success - * @retval Any non zero value -> Fail - * - */ -static void scale_offset(uint8_t res, uint8_t range, const struct offset_delta *delta, struct accel_offset *data); - -/*! - * @brief This API compensate the accel data against gravity. - * - * @param[in] lsb_per_g : lsb value pre 1g. - * @param[in] g_val : G reference value of all axis. - * @param[in] data : pointer of accel_offset data. - * @param[out] comp_data : pointer to store compensated data. - * - * @note The g-values to be passed to the parameter should be - * multiples of 1000000. - * - * @return results of the status of user input validation - * @retval 0 -> Success - * @retval Any non zero value -> Fail - * - */ -static void comp_for_grvty(uint16_t lsb_per_g, const int32_t g_val[3], const struct bma4_accel *data, - struct offset_delta *comp_data); -/*! - * @brief This function validates the Accel Self test data and decides the - * result of Self test operation. - * - * @param[in] accel_data_diff : Pointer to structure variable which holds - * the Accel data difference of Self test operation - * @param[in] dev : Structure instance of bma4_dev - * - * @return results of self test operation - * @retval 0 -> Success - * @retval Any non zero value -> Fail - * - */ -static uint16_t validate_selftest(const struct selftest_delta_limit *accel_data_diff, - const struct bma4_dev *dev); - -/*! - * @brief This function configure the Accel for FOC. - * - * @param[in] acc_conf : accel config structure instance - * @param[in] acc_en : enables the accel - * @param[in] pwr_mode : set the power mode - * @param[in] dev : Structure instance of bma4_dev - * - * @return results of self test operation - * @retval 0 -> Success - * @retval Any non zero value -> Fail - * - */ -static uint16_t foc_config(struct bma4_accel_config *acc_conf, uint8_t *acc_en, uint8_t *pwr_mode, - struct bma4_dev *dev); - -/*! - * @brief This API converts lsb value of axes to mg for self-test - * - * @param[in] accel_data_diff : Pointer variable used to pass accel difference - * values in g - * @param[out] accel_data_diff_mg : Pointer variable used to store accel - * difference values in mg - * @param[out] dev : Structure instance of bma4_dev - * - * @return None * - */ -static void convert_lsb_g(const struct selftest_delta_limit *accel_data_diff, - struct selftest_delta_limit *accel_data_diff_mg, - const struct bma4_dev *dev); - -/*! - * @brief This API sets the feature config. data start address in the sensor. - * - * @param[in] dev : Structure instance of bma4_dev. - * - * @return Result of API execution status - * @retval 0 -> Success - * @retval Any non zero value -> Fail - */ -static uint16_t set_feature_config_start_addr(struct bma4_dev *dev); - -/*! - * @brief This API increments the feature config. data address according to the user - * provided read/write length in the dev structure. - * - * @param[in] dev : Structure instance of bma4_dev. - * - * @return Result of API execution status - * @retval 0 -> Success - * @retval Any non zero value -> Fail - */ -static uint16_t increment_feature_config_addr(const struct bma4_dev *dev); - -/*! - * @brief This API reads the 8-bit data from the given register - * in the sensor. - */ -static uint16_t read_regs(uint8_t addr, uint8_t *data, uint8_t len, const struct bma4_dev *dev); - -/*! - * @brief This API writes the 8-bit data to the given register - * in the sensor. - */ -static uint16_t write_regs(uint8_t addr, uint8_t *data, uint8_t len, const struct bma4_dev *dev); - -/*! - * @brief This API sets the feature config. data start address in the sensor. - */ -static uint16_t get_feature_config_start_addr(struct bma4_dev *dev); - -/*! - * @brief This API is used to calculate the power of given - * base value. - * - * @param[in] base : value of base - * @param[in] resolution : resolution of the sensor - * - * @return : return the value of base^resolution - */ - -static int32_t power(int16_t base, uint8_t resolution); - -/*! - * @brief This API performs roundoff on given value - * - * @param[in] value : Value which is need to be rounded off - * - * @return : None - */ -static int8_t roundoff(int32_t value); - -/*! - * @brief This API finds the bit position of 3.9mg according to given range - * and resolution. - * - * @param[in] range : range of the accel. - * @param[in] res : resolution of the accel. - * - * @return : bit position of 3.9mg - */ -static int8_t get_bit_pos_3_9mg(uint8_t range, uint8_t res); - -/*! - * @brief This API finds the the null error of the device pointer structure - * - * @param[in] dev : Structure instance of bma4_dev. - * - * @return Null error - */ -static uint16_t bma4_null_pointer_check(const struct bma4_dev *dev); - -/*! - * @brief This internal API brings up the secondary interface to access - * auxiliary sensor - * - * @param[in] dev : Structure instance of bma4_dev. - * - * @return Result of API execution status - * - * @retval 0 if success, else fail - */ -static uint16_t bma4_set_aux_interface_config(struct bma4_dev *dev); - -/*! - * @brief This internal API reads the data from the auxiliary sensor - * depending on burst length configured - * - * @param[in] dev : Structure instance of bma4_dev. - * @param[out] aux_data : Pointer variable to store data read - * @param[in] aux_reg_addr : Variable to pass address from where - * data is to be read - * - * @return Result of API execution status - * - * @retval 0 if success, else fail - */ -static uint16_t bma4_extract_aux_data(uint8_t aux_reg_addr, uint8_t *aux_data, uint16_t len, struct bma4_dev *dev); - -/*! - * @brief This internal API maps the actual burst read length with user length set. - * - * @param[in] dev : Structure instance of bma4_dev. - * @param[out] len : Pointer variable to store mapped length - * - * @return Result of API execution status - * - * @retval 0 if success, else fail - */ -static uint16_t bma4_map_read_len(uint8_t *len, const struct bma4_dev *dev); - -/***************************************************************************/ -/**\name Extern Declarations -****************************************************************************/ - -/***************************************************************************/ -/**\name Globals -****************************************************************************/ - - -/***************************************************************************/ -/**\name Function definitions -****************************************************************************/ -/*! - * @brief This API is the entry point. - * Call this API before using all other APIs. - * This API reads the chip-id of the sensor which is the first step to - * verify the sensor and also it configures the read mechanism of SPI and - * I2C interface. - */ -uint16_t bma4_init(struct bma4_dev *dev) -{ - uint16_t rslt = 0; - uint8_t data = 0; - /* Check the bma4 structure as NULL */ - if ((dev == NULL) || (dev->bus_read == NULL) || (dev->bus_write == NULL)) { - rslt |= BMA4_E_NULL_PTR; - } else { - if (dev->interface == BMA4_SPI_INTERFACE) - dev->dummy_byte = 1; - else - dev->dummy_byte = 0; - - rslt |= bma4_read_regs(BMA4_CHIP_ID_ADDR, &data, 1, dev); - - if (rslt == BMA4_OK) { - /* Assign Chip Id */ - dev->chip_id = data; - } - } - - return rslt; -} - -/*! - * @brief This API is used to write the binary configuration in the sensor - */ -uint16_t bma4_write_config_file(struct bma4_dev *dev) -{ - uint16_t rslt; - /* Config loading disable*/ - uint8_t config_load = 0; - uint16_t index = 0; - uint8_t config_stream_status = 0; - - /* Disable advanced power save */ - rslt = bma4_set_advance_power_save(BMA4_DISABLE, dev); - /* Wait for sensor time synchronization. Refer the data-sheet for - more information*/ - dev->delay(1); - - if (rslt == BMA4_OK) { - /* Disable config loading*/ - rslt |= bma4_write_regs(BMA4_INIT_CTRL_ADDR, &config_load, 1, dev); - /* Write the config stream */ - for (index = 0; index < BMA4_CONFIG_STREAM_SIZE; index += dev->read_write_len) - rslt |= stream_transfer_write((dev->config_file_ptr + index), index, dev); - - /* Enable config loading and FIFO mode */ - config_load = 0x01; - rslt |= bma4_write_regs(BMA4_INIT_CTRL_ADDR, &config_load, 1, dev); - /* Wait till ASIC is initialized. Refer the data-sheet for - more information*/ - dev->delay(150); - /* Read the status of config stream operation */ - rslt |= bma4_read_regs(BMA4_INTERNAL_STAT, &config_stream_status, 1, dev); - - if (config_stream_status != BMA4_ASIC_INITIALIZED) { - rslt |= BMA4_E_CONFIG_STREAM_ERROR; - } else { - /* Enable advanced power save */ - rslt |= bma4_set_advance_power_save(BMA4_ENABLE, dev); - rslt |= get_feature_config_start_addr(dev); - } - } - return rslt; -} - -/*! - * @brief This API checks whether the write operation requested is for feature - * config or register write and accordingly writes the data in the sensor. - */ -uint16_t bma4_write_regs(uint8_t addr, uint8_t *data, uint8_t len, struct bma4_dev *dev) -{ - uint8_t i; - uint8_t loop_count; - uint8_t overflow; - uint8_t index; - uint16_t rslt = BMA4_OK; - uint8_t adv_pwr_save = 0; - - /* Check the dev structure as NULL*/ - if (dev == NULL) { - rslt |= BMA4_E_NULL_PTR; - } else { - if (addr == BMA4_FEATURE_CONFIG_ADDR) { - /* Disable APS if enabled before writing the feature config register */ - rslt = bma4_get_advance_power_save(&adv_pwr_save, dev); - if (adv_pwr_save == BMA4_ENABLE) { - rslt |= bma4_set_advance_power_save(BMA4_DISABLE, dev); - /* Wait for sensor time synchronization. Refer the data-sheet for - more information*/ - dev->delay(1); - } - - if (((len % 2) == 0) && (len <= dev->feature_len) && (rslt == BMA4_OK)) { - if (dev->read_write_len < len) { - /* Calculate the no of writes to be performed according - to the read/write length */ - loop_count = len / dev->read_write_len; - overflow = len % dev->read_write_len; - index = 0; - rslt = set_feature_config_start_addr(dev); - for (i = 0; i < loop_count; i++) { - rslt |= write_regs(BMA4_FEATURE_CONFIG_ADDR, data + index, - dev->read_write_len, dev); - rslt |= increment_feature_config_addr(dev); - index = index + dev->read_write_len; - } - if (overflow) - rslt |= write_regs(BMA4_FEATURE_CONFIG_ADDR, data + index, - overflow, dev); - rslt |= set_feature_config_start_addr(dev); - } else { - rslt = write_regs(BMA4_FEATURE_CONFIG_ADDR, data, len, dev); - } - } else { - rslt = BMA4_E_RD_WR_LENGTH_INVALID; - } - - if (rslt == BMA4_OK) { - /* Enable APS once write feature config register is done */ - rslt = bma4_get_advance_power_save(&adv_pwr_save, dev); - if (adv_pwr_save == BMA4_DISABLE) { - rslt |= bma4_set_advance_power_save(BMA4_ENABLE, dev); - /* Wait for sensor time synchronization. Refer the data-sheet for - more information*/ - dev->delay(1); - } - } - - } else { - rslt = write_regs(addr, data, len, dev); - } - } - - return rslt; -} - -/*! - * @brief This API writes the 8-bit data to the given register - * in the sensor. - */ -static uint16_t write_regs(uint8_t addr, uint8_t *data, uint8_t len, const struct bma4_dev *dev) -{ - uint16_t rslt = 0; - - /* Check the bma4 structure as NULL */ - if (dev == NULL) { - rslt |= BMA4_E_NULL_PTR; - } else { - if (dev->interface == BMA4_SPI_INTERFACE) - addr = addr & BMA4_SPI_WR_MASK; - /* write data in the register*/ - rslt |= dev->bus_write(dev->dev_addr, addr, data, len); - } - return rslt; -} - -/*! - * @brief This API sets the feature config. data start address in the sensor. - */ -static uint16_t get_feature_config_start_addr(struct bma4_dev *dev) -{ - uint16_t rslt; - uint8_t asic_lsb; - uint8_t asic_msb; - - rslt = read_regs(BMA4_RESERVED_REG_5B_ADDR, &asic_lsb, 1, dev); - rslt |= read_regs(BMA4_RESERVED_REG_5C_ADDR, &asic_msb, 1, dev); - - /* Store asic info in dev structure */ - dev->asic_data.asic_lsb = asic_lsb & 0x0F; - dev->asic_data.asic_msb = asic_msb; - - return rslt; -} - -/*! - * @brief This API sets the feature config. data start address in the sensor. - */ -static uint16_t set_feature_config_start_addr(struct bma4_dev *dev) -{ - uint16_t rslt; - - rslt = write_regs(BMA4_RESERVED_REG_5B_ADDR, &dev->asic_data.asic_lsb, 1, dev); - rslt |= write_regs(BMA4_RESERVED_REG_5C_ADDR, &dev->asic_data.asic_msb, 1, dev); - - return rslt; -} - -/*! - * @brief This API increments the feature config. data address according to the user - * provided read/write length in the dev structure. - */ -static uint16_t increment_feature_config_addr(const struct bma4_dev *dev) -{ - uint16_t rslt; - uint16_t asic_addr; - uint8_t asic_lsb; - uint8_t asic_msb; - - /* Read the asic address from the sensor */ - rslt = read_regs(BMA4_RESERVED_REG_5B_ADDR, &asic_lsb, 1, dev); - rslt |= read_regs(BMA4_RESERVED_REG_5C_ADDR, &asic_msb, 1, dev); - /* Get the asic address */ - asic_addr = (asic_msb << 4) | (asic_lsb & 0x0F); - /* Sum the asic address with read/write length after converting from - byte to word */ - asic_addr = asic_addr + (dev->read_write_len / 2); - /* Split the asic address */ - asic_lsb = asic_addr & 0x0F; - asic_msb = (uint8_t)(asic_addr >> 4); - /* Write the asic address in the sensor */ - rslt |= write_regs(BMA4_RESERVED_REG_5B_ADDR, &asic_lsb, 1, dev); - rslt |= write_regs(BMA4_RESERVED_REG_5C_ADDR, &asic_msb, 1, dev); - - return rslt; -} - -/*! - * @brief This API checks whether the read operation requested is for feature - * or register read and accordingly reads the data from the sensor. - */ -uint16_t bma4_read_regs(uint8_t addr, uint8_t *data, uint8_t len, struct bma4_dev *dev) -{ - uint8_t i; - uint8_t loop_count; - uint8_t overflow; - uint8_t index; - uint16_t rslt = BMA4_OK; - uint8_t adv_pwr_save = 0; - - /* Check the dev structure as NULL*/ - if (dev == NULL) { - rslt |= BMA4_E_NULL_PTR; - } else { - if (addr == BMA4_FEATURE_CONFIG_ADDR) { - /* Disable APS if enabled before reading the feature config register */ - rslt = bma4_get_advance_power_save(&adv_pwr_save, dev); - if (adv_pwr_save == BMA4_ENABLE) { - rslt |= bma4_set_advance_power_save(BMA4_DISABLE, dev); - /* Wait for sensor time synchronization. Refer the data-sheet for - more information*/ - dev->delay(1); - } - - if (((len % 2) == 0) && (len <= dev->feature_len) && (rslt == BMA4_OK)) { - if (dev->read_write_len < len) { - /* Calculate the no of writes to be performed according - to the read/write length */ - loop_count = len / dev->read_write_len; - overflow = len % dev->read_write_len; - index = 0; - rslt = set_feature_config_start_addr(dev); - for (i = 0; i < loop_count; i++) { - rslt |= read_regs(BMA4_FEATURE_CONFIG_ADDR, data + index, - dev->read_write_len, dev); - rslt |= increment_feature_config_addr(dev); - index = index + dev->read_write_len; - } - if (overflow) - rslt |= read_regs(BMA4_FEATURE_CONFIG_ADDR, data + index, - overflow, dev); - rslt |= set_feature_config_start_addr(dev); - } else { - rslt = read_regs(BMA4_FEATURE_CONFIG_ADDR, data, len, dev); - } - } else { - rslt = BMA4_E_RD_WR_LENGTH_INVALID; - } - if (rslt == BMA4_OK) { - /* Enable APS once read feature config register is done */ - rslt = bma4_get_advance_power_save(&adv_pwr_save, dev); - if (adv_pwr_save == BMA4_DISABLE) { - rslt |= bma4_set_advance_power_save(BMA4_ENABLE, dev); - /* Wait for sensor time synchronization. Refer the data-sheet for - more information*/ - dev->delay(1); - } - } - } else { - rslt = read_regs(addr, data, len, dev); - } - } - - return rslt; -} - -/*! - * @brief This API reads the 8-bit data from the given register - * in the sensor. - */ -static uint16_t read_regs(uint8_t addr, uint8_t *data, uint8_t len, const struct bma4_dev *dev) -{ - /* variable used to return the status of communication result*/ - uint16_t rslt = 0; - uint16_t temp_len = len + dev->dummy_byte; - uint16_t i; - - if (dev->interface == BMA4_SPI_INTERFACE) { - /* SPI mask added */ - addr = addr | BMA4_SPI_RD_MASK; - } - - if (temp_len > BMA4_MAX_BUFFER_SIZE) { - /* Buffer size is not sufficient */ - rslt |= BMA4_E_OUT_OF_RANGE; - } - - if (rslt == BMA4_OK) { - /* Read the data from the register */ - rslt |= dev->bus_read(dev->dev_addr, addr, temp_buff, temp_len); - - for (i = 0; i < len; i++) { - /* Parsing and storing the valid data */ - data[i] = temp_buff[i + dev->dummy_byte]; - } - } - - return rslt; -} - -/*! - * @brief This API reads the error status from the sensor. - */ -uint16_t bma4_get_error_status(struct bma4_err_reg *err_reg, struct bma4_dev *dev) -{ - uint16_t rslt = 0; - uint8_t data = 0; - - /* Check the bma4 structure as NULL */ - if (dev == NULL) { - rslt |= BMA4_E_NULL_PTR; - } else { - /* Read the error codes*/ - rslt |= bma4_read_regs(BMA4_ERROR_ADDR, &data, 1, dev); - - if (rslt == BMA4_OK) { - /* Fatal error*/ - err_reg->fatal_err = BMA4_GET_BITS_POS_0(data, BMA4_FATAL_ERR); - /* Cmd error*/ - err_reg->cmd_err = BMA4_GET_BITSLICE(data, BMA4_CMD_ERR); - /* User error*/ - err_reg->err_code = BMA4_GET_BITSLICE(data, BMA4_ERR_CODE); - /* FIFO error*/ - err_reg->fifo_err = BMA4_GET_BITSLICE(data, BMA4_FIFO_ERR); - /* Mag data ready error*/ - err_reg->aux_err = BMA4_GET_BITSLICE(data, BMA4_AUX_ERR); - } - } - - return rslt; -} - -/*! - * @brief This API reads the sensor status from the sensor. - */ -uint16_t bma4_get_status(uint8_t *status, struct bma4_dev *dev) -{ - uint16_t rslt = 0; - uint8_t data = 0; - - /* Check the bma4 structure as NULL */ - if (dev == NULL) { - rslt |= BMA4_E_NULL_PTR; - } else { - /* Read the error codes*/ - rslt |= bma4_read_regs(BMA4_STATUS_ADDR, &data, 1, dev); - - if (rslt == BMA4_OK) - *status = data; - } - - return rslt; -} - -/*! - * @brief This API reads the Accel data for x,y and z axis from the sensor. - * The data units is in LSB format. - */ -uint16_t bma4_read_accel_xyz(struct bma4_accel *accel, struct bma4_dev *dev) -{ - uint16_t rslt = 0; - uint16_t lsb = 0; - uint16_t msb = 0; - uint8_t data[BMA4_ACCEL_DATA_LENGTH] = {0}; - - /* Check the bma4 structure as NULL */ - if (dev == NULL) { - rslt |= BMA4_E_NULL_PTR; - } else { - rslt |= bma4_read_regs(BMA4_DATA_8_ADDR, data, BMA4_ACCEL_DATA_LENGTH, dev); - - if (rslt == BMA4_OK) { - msb = data[1]; - lsb = data[0]; - /* Accel data x axis */ - accel->x = (int16_t)((msb << 8) | lsb); - - msb = data[3]; - lsb = data[2]; - /* Accel data y axis */ - accel->y = (int16_t)((msb << 8) | lsb); - - msb = data[5]; - lsb = data[4]; - /* Accel data z axis */ - accel->z = (int16_t)((msb << 8) | lsb); - - if (dev->resolution == BMA4_12_BIT_RESOLUTION) { - accel->x = (accel->x / 0x10); - accel->y = (accel->y / 0x10); - accel->z = (accel->z / 0x10); - } else if (dev->resolution == BMA4_14_BIT_RESOLUTION) { - accel->x = (accel->x / 0x04); - accel->y = (accel->y / 0x04); - accel->z = (accel->z / 0x04); - } - } - } - - return rslt; -} - -/*! - * @brief This API reads the sensor time of Sensor time gets updated - * with every update of data register or FIFO. - */ -uint16_t bma4_get_sensor_time(uint32_t *sensor_time, struct bma4_dev *dev) -{ - uint16_t rslt = 0; - uint8_t data[BMA4_SENSOR_TIME_LENGTH] = {0}; - uint8_t msb = 0; - uint8_t xlsb = 0; - uint8_t lsb = 0; - - /* Check the bma4 structure as NULL */ - if (dev == NULL) { - rslt |= BMA4_E_NULL_PTR; - } else { - rslt |= bma4_read_regs(BMA4_SENSORTIME_0_ADDR, data, BMA4_SENSOR_TIME_LENGTH, dev); - - if (rslt == BMA4_OK) { - msb = data[BMA4_SENSOR_TIME_MSB_BYTE]; - xlsb = data[BMA4_SENSOR_TIME_XLSB_BYTE]; - lsb = data[BMA4_SENSOR_TIME_LSB_BYTE]; - *sensor_time = (uint32_t)((msb << 16) | (xlsb << 8) | lsb); - } - } - - return rslt; -} - -/*! - * @brief This API reads the chip temperature of sensor. - * - * @note Using a scaling factor of 1000, to obtain integer values, which - * at the user end, are used to get accurate temperature value . - * BMA4_FAHREN_SCALED = 1.8 * 1000, BMA4_KELVIN_SCALED = 273.15 * 1000 - */ -uint16_t bma4_get_temperature(int32_t *temp, uint8_t temp_unit, struct bma4_dev *dev) -{ - uint16_t rslt = 0; - uint8_t data[BMA4_TEMP_DATA_SIZE] = {0}; - int32_t temp_raw_scaled = 0; - - /* Check for Null pointer error */ - if (dev == NULL) { - rslt |= BMA4_E_NULL_PTR; - } else { - /* Read temperature value from the register */ - rslt |= bma4_read_regs(BMA4_TEMPERATURE_ADDR, data, BMA4_TEMP_DATA_SIZE, dev); - - if (rslt == BMA4_OK) - temp_raw_scaled = (int32_t)data[BMA4_TEMP_BYTE] * BMA4_SCALE_TEMP; - - /* '0' value read from the register corresponds to 23 degree C */ - (*temp) = temp_raw_scaled + (BMA4_OFFSET_TEMP * BMA4_SCALE_TEMP); - - switch (temp_unit) { - case BMA4_DEG: - break; - - case BMA4_FAHREN: - /* Temperature in degree Fahrenheit */ - (*temp) = (((*temp) / BMA4_SCALE_TEMP) * BMA4_FAHREN_SCALED) + (32 * BMA4_SCALE_TEMP); - break; - - case BMA4_KELVIN: - /* Temperature in degree Kelvin */ - (*temp) = (*temp) + BMA4_KELVIN_SCALED; - break; - - default: - break; - } - } - - return rslt; -} - -/*! - * @brief This API reads the Output data rate, Bandwidth, perf_mode - * and Range of accel. - */ -uint16_t bma4_get_accel_config(struct bma4_accel_config *accel, struct bma4_dev *dev) -{ - uint16_t rslt = 0; - uint8_t data[2] = {0}; - - /* Check the bma4 structure as NULL */ - if (dev == NULL) { - rslt |= BMA4_E_NULL_PTR; - } else { - rslt |= bma4_read_regs(BMA4_ACCEL_CONFIG_ADDR, data, BMA4_ACCEL_CONFIG_LENGTH, dev); - - if (rslt == BMA4_OK) { - /* To get the ODR */ - accel->odr = BMA4_GET_BITS_POS_0(data[0], BMA4_ACCEL_ODR); - /* To get the bandwidth */ - accel->bandwidth = BMA4_GET_BITSLICE(data[0], BMA4_ACCEL_BW); - /* To get the under sampling mode */ - accel->perf_mode = BMA4_GET_BITSLICE(data[0], BMA4_ACCEL_PERFMODE); - /* Read the Accel range */ - accel->range = BMA4_GET_BITS_POS_0(data[1], BMA4_ACCEL_RANGE); - } - } - - return rslt; -} - -/*! - * @brief This API sets the output_data_rate, bandwidth, perf_mode - * and range of Accel. - */ -uint16_t bma4_set_accel_config(const struct bma4_accel_config *accel, struct bma4_dev *dev) -{ - uint16_t rslt = 0; - uint8_t accel_config_data[2] = {0, 0}; - - /* Check the bma4 structure as NULL */ - if (dev == NULL) { - rslt |= BMA4_E_NULL_PTR; - } else { - /* check whether the bandwidth and perfmode - settings are valid */ - rslt = validate_bandwidth_perfmode(accel->bandwidth, accel->perf_mode); - - if (rslt == BMA4_OK) { - /* check ODR is valid */ - rslt |= validate_odr(accel->odr); - - if (rslt == BMA4_OK) { - accel_config_data[0] = accel->odr & BMA4_ACCEL_ODR_MSK; - accel_config_data[0] |= (uint8_t)(accel->bandwidth << BMA4_ACCEL_BW_POS); - accel_config_data[0] |= (uint8_t)(accel->perf_mode << BMA4_ACCEL_PERFMODE_POS); - accel_config_data[1] = accel->range & BMA4_ACCEL_RANGE_MSK; - - /* Burst write is not possible in - suspend mode hence individual write is - used with delay of 1 ms */ - rslt |= bma4_write_regs(BMA4_ACCEL_CONFIG_ADDR, &accel_config_data[0], 1, dev); - dev->delay(BMA4_GEN_READ_WRITE_DELAY); - rslt |= bma4_write_regs((BMA4_ACCEL_CONFIG_ADDR + 1), &accel_config_data[1], - 1, dev); - } - } - } - - return rslt; -} - -/*! - * @brief This API validates the bandwidth and perf_mode - * value set by the user. - */ -static uint16_t validate_bandwidth_perfmode(uint8_t bandwidth, uint8_t perf_mode) -{ - uint16_t rslt = BMA4_OK; - - if (perf_mode == BMA4_CONTINUOUS_MODE) { - if (bandwidth > BMA4_ACCEL_NORMAL_AVG4) { - /* Invalid bandwidth error for continuous mode */ - rslt = BMA4_E_OUT_OF_RANGE; - } - } else if (perf_mode == BMA4_CIC_AVG_MODE) { - if (bandwidth > BMA4_ACCEL_RES_AVG128) { - /* Invalid bandwidth error for CIC avg. mode */ - rslt = BMA4_E_OUT_OF_RANGE; - } - } else { - rslt = BMA4_E_OUT_OF_RANGE; - } - - return rslt; -} - -/*! - * @brief This API validates the ODR value set by the user. - */ -static uint16_t validate_odr(uint8_t odr) -{ - uint16_t rslt = BMA4_OK; - - if ((odr < BMA4_OUTPUT_DATA_RATE_0_78HZ) || (odr > BMA4_OUTPUT_DATA_RATE_1600HZ)) { - /* If odr is not valid return error */ - rslt = BMA4_E_OUT_OF_RANGE; - } - - return rslt; -} - -/*! - * @brief This API sets the advance power save mode in the sensor. - */ -uint16_t bma4_set_advance_power_save(uint8_t adv_pwr_save, struct bma4_dev *dev) -{ - uint16_t rslt = BMA4_OK; - uint8_t data = 0; - - /* Check the bma4 structure as NULL */ - if (dev == NULL) { - rslt |= BMA4_E_NULL_PTR; - } else { - rslt |= bma4_read_regs(BMA4_POWER_CONF_ADDR, &data, 1, dev); - if (rslt == BMA4_OK) { - data = BMA4_SET_BITS_POS_0(data, BMA4_ADVANCE_POWER_SAVE, adv_pwr_save); - rslt |= bma4_write_regs(BMA4_POWER_CONF_ADDR, &data, 1, dev); - } - } - - return rslt; -} - -/*! - * @brief This API reads the status of advance power save mode - * from the sensor. - */ -uint16_t bma4_get_advance_power_save(uint8_t *adv_pwr_save, struct bma4_dev *dev) -{ - uint16_t rslt = BMA4_OK; - uint8_t data = 0; - - /* Check the bma4 structure as NULL */ - if (dev == NULL) { - rslt |= BMA4_E_NULL_PTR; - } else { - rslt |= bma4_read_regs(BMA4_POWER_CONF_ADDR, &data, 1, dev); - - if (rslt == BMA4_OK) - *adv_pwr_save = BMA4_GET_BITS_POS_0(data, BMA4_ADVANCE_POWER_SAVE); - } - - return rslt; -} - -/*! - * @brief This API sets the FIFO self wake up functionality in the sensor. - */ -uint16_t bma4_set_fifo_self_wakeup(uint8_t fifo_self_wakeup, struct bma4_dev *dev) -{ - uint16_t rslt = 0; - uint8_t data = 0; - - /* Check the bma4 structure as NULL */ - if (dev == NULL) { - rslt |= BMA4_E_NULL_PTR; - } else { - rslt |= bma4_read_regs(BMA4_POWER_CONF_ADDR, &data, 1, dev); - - if (rslt == BMA4_OK) { - data = BMA4_SET_BITSLICE(data, BMA4_FIFO_SELF_WAKE_UP, fifo_self_wakeup); - rslt |= bma4_write_regs(BMA4_POWER_CONF_ADDR, &data, 1, dev); - } - } - - return rslt; -} - -/*! - * @brief This API gets the status of FIFO self wake up functionality from - * the sensor. - */ -uint16_t bma4_get_fifo_self_wakeup(uint8_t *fifo_self_wake_up, struct bma4_dev *dev) -{ - uint16_t rslt = 0; - uint8_t data = 0; - - /* Check the bma4 structure as NULL */ - if (dev == NULL) { - rslt |= BMA4_E_NULL_PTR; - } else { - rslt |= bma4_read_regs(BMA4_POWER_CONF_ADDR, &data, 1, dev); - - if (rslt == BMA4_OK) - *fifo_self_wake_up = BMA4_GET_BITSLICE(data, BMA4_FIFO_SELF_WAKE_UP); - } - - return rslt; -} - -/*! - * @brief This API enables or disables the Accel in the sensor. - */ -uint16_t bma4_set_accel_enable(uint8_t accel_en, struct bma4_dev *dev) -{ - uint16_t rslt = 0; - uint8_t data = 0; - - /* Check the bma4 structure as NULL */ - if (dev == NULL) { - rslt |= BMA4_E_NULL_PTR; - } else { - rslt |= bma4_read_regs(BMA4_POWER_CTRL_ADDR, &data, 1, dev); - - if (rslt == BMA4_OK) { - data = BMA4_SET_BITSLICE(data, BMA4_ACCEL_ENABLE, accel_en); - rslt |= bma4_write_regs(BMA4_POWER_CTRL_ADDR, &data, 1, dev); - } - } - - return rslt; -} - -/*! - * @brief This API checks whether Accel is enabled or not in the sensor. - */ -uint16_t bma4_get_accel_enable(uint8_t *accel_en, struct bma4_dev *dev) -{ - uint16_t rslt = 0; - uint8_t data = 0; - - /* Check the bma4 structure as NULL */ - if (dev == NULL) { - rslt |= BMA4_E_NULL_PTR; - } else { - rslt |= bma4_read_regs(BMA4_POWER_CTRL_ADDR, &data, 1, dev); - - if (rslt == BMA4_OK) - *accel_en = BMA4_GET_BITSLICE(data, BMA4_ACCEL_ENABLE); - } - - return rslt; -} - -/*! - * @brief This API is used to enable or disable auxiliary Mag - * in the sensor. - */ -uint16_t bma4_set_mag_enable(uint8_t mag_en, struct bma4_dev *dev) -{ - uint16_t rslt = 0; - uint8_t data = 0; - - /* Check the bma4 structure as NULL */ - if (dev == NULL) { - rslt |= BMA4_E_NULL_PTR; - } else { - rslt |= bma4_read_regs(BMA4_POWER_CTRL_ADDR, &data, 1, dev); - - if (rslt == BMA4_OK) { - data = BMA4_SET_BITS_POS_0(data, BMA4_MAG_ENABLE, mag_en); - rslt |= bma4_write_regs(BMA4_POWER_CTRL_ADDR, &data, 1, dev); - } - } - - return rslt; -} - -/*! - * @brief This API is used to check whether the auxiliary Mag is enabled - * or not in the sensor. - */ -uint16_t bma4_get_mag_enable(uint8_t *mag_en, struct bma4_dev *dev) -{ - uint16_t rslt = 0; - uint8_t data = 0; - - /* Check the bma4 structure as NULL */ - if (dev == NULL) { - rslt |= BMA4_E_NULL_PTR; - } else { - rslt |= bma4_read_regs(BMA4_POWER_CTRL_ADDR, &data, 1, dev); - - if (rslt == BMA4_OK) - *mag_en = BMA4_GET_BITS_POS_0(data, BMA4_MAG_ENABLE); - } - - return rslt; -} - -/*! - * @brief This API reads the SPI interface mode which is set for primary - * interface. - */ -uint16_t bma4_get_spi_interface(uint8_t *spi, struct bma4_dev *dev) -{ - uint16_t rslt = 0; - uint8_t data = 0; - - /* Check the bma4 structure as NULL */ - if (dev == NULL) { - rslt |= BMA4_E_NULL_PTR; - } else { - /* Read SPI mode */ - rslt |= bma4_read_regs(BMA4_IF_CONFIG_ADDR, &data, 1, dev); - - if (rslt == BMA4_OK) - *spi = BMA4_GET_BITS_POS_0(data, BMA4_CONFIG_SPI3); - } - - return rslt; -} - -/*! - * @brief This API configures the SPI interface Mode for primary interface - */ -uint16_t bma4_set_spi_interface(uint8_t spi, struct bma4_dev *dev) -{ - uint16_t rslt = 0; - uint8_t data = 0; - - /* Check the bma4 structure as NULL */ - if (dev == NULL) { - rslt |= BMA4_E_NULL_PTR; - } else { - if (spi <= BMA4_MAX_VALUE_SPI3) { - /* Write SPI mode */ - rslt |= bma4_read_regs(BMA4_IF_CONFIG_ADDR, &data, 1, dev); - - if (rslt == BMA4_OK) { - data = BMA4_SET_BITS_POS_0(data, BMA4_CONFIG_SPI3, spi); - rslt |= bma4_write_regs(BMA4_IF_CONFIG_ADDR, &data, 1, dev); - } - } else { - rslt |= BMA4_E_OUT_OF_RANGE; - } - } - - return rslt; -} - -/*! -* @brief This API writes the available sensor specific commands -* to the sensor. -*/ -uint16_t bma4_set_command_register(uint8_t command_reg, struct bma4_dev *dev) -{ - uint16_t rslt = 0; - - /* Check the bma4 structure as NULL */ - if (dev == NULL) { - rslt |= BMA4_E_NULL_PTR; - } else { - /* Write command register */ - rslt |= bma4_write_regs(BMA4_CMD_ADDR, &command_reg, 1, dev); - } - - return rslt; -} - -/*! - * @brief This API sets the I2C device address of auxiliary sensor - */ -uint16_t bma4_set_i2c_device_addr(struct bma4_dev *dev) -{ - uint16_t rslt = 0; - uint8_t data = 0, dev_id = 0; - - /* Check the bma4 structure as NULL */ - if (dev == NULL) { - rslt |= BMA4_E_NULL_PTR; - } else { - /* Write the auxiliary I2C device address */ - rslt |= bma4_read_regs(BMA4_AUX_DEV_ID_ADDR, &data, 1, dev); - - if (rslt == BMA4_OK) { - dev_id = BMA4_SET_BITSLICE(data, BMA4_I2C_DEVICE_ADDR, dev->aux_config.aux_dev_addr); - rslt |= bma4_write_regs(BMA4_AUX_DEV_ID_ADDR, &dev_id, 1, dev); - } - } - - return rslt; -} - -/*! - * @brief This API sets the register access on MAG_IF[2], MAG_IF[3], - * MAG_IF[4] in the sensor. This implies that the DATA registers are - * not updated with Mag values automatically. - */ -uint16_t bma4_set_mag_manual_enable(uint8_t mag_manual, struct bma4_dev *dev) -{ - uint16_t rslt = 0; - uint8_t data = 0; - /* Check the bma4 structure as NULL */ - if (dev == NULL) { - rslt |= BMA4_E_NULL_PTR; - } else { - /* Write the Mag manual*/ - rslt |= bma4_read_regs(BMA4_AUX_IF_CONF_ADDR, &data, 1, dev); - dev->delay(BMA4_GEN_READ_WRITE_DELAY); - - if (rslt == BMA4_OK) { - /* Set the bit of Mag manual enable */ - data = BMA4_SET_BITSLICE(data, BMA4_MAG_MANUAL_ENABLE, mag_manual); - rslt |= bma4_write_regs(BMA4_AUX_IF_CONF_ADDR, &data, 1, dev); - - if (rslt == BMA4_OK) - dev->aux_config.manual_enable = (uint8_t)mag_manual; - } else { - /*dev->mag_manual_enable = 0;*/ - dev->aux_config.manual_enable = 0; - } - } - - return rslt; -} - -/*! - * @brief This API checks whether the Mag access is done manually or - * automatically in the sensor. - * If the Mag access is done through manual mode then Mag data registers - * in sensor are not updated automatically. - */ -uint16_t bma4_get_mag_manual_enable(uint8_t *mag_manual, struct bma4_dev *dev) -{ - uint16_t rslt = 0; - uint8_t data = 0; - - /* Check the bma4 structure as NULL */ - if (dev == NULL) { - rslt |= BMA4_E_NULL_PTR; - } else { - /* Read Mag manual */ - rslt |= bma4_read_regs(BMA4_AUX_IF_CONF_ADDR, &data, 1, dev); - - if (rslt == BMA4_OK) - *mag_manual = BMA4_GET_BITSLICE(data, BMA4_MAG_MANUAL_ENABLE); - } - - return rslt; -} - -/*! - * @brief This API sets the I2C interface configuration(if) mode - * for auxiliary Mag. - */ -uint16_t bma4_set_aux_if_mode(uint8_t if_mode, struct bma4_dev *dev) -{ - uint16_t rslt = 0; - uint8_t data = 0; - - /* Check the bma4 structure as NULL */ - if (dev == NULL) { - rslt |= BMA4_E_NULL_PTR; - } else { - rslt |= bma4_read_regs(BMA4_IF_CONFIG_ADDR, &data, 1, dev); - - if (rslt == BMA4_OK) { - data = BMA4_SET_BITSLICE(data, BMA4_IF_CONFIG_IF_MODE, if_mode); - rslt |= bma4_write_regs(BMA4_IF_CONFIG_ADDR, &data, 1, dev); - } - } - - return rslt; -} - -/*! - * @brief This API gets the address of the register of Aux Mag sensor - * where the data to be read. - */ -uint16_t bma4_get_mag_read_addr(uint8_t *mag_read_addr, struct bma4_dev *dev) -{ - uint16_t rslt = 0; - uint8_t data = 0; - - /* Check the bma4 structure as NULL */ - if (dev == NULL) { - rslt |= BMA4_E_NULL_PTR; - } else { - rslt |= bma4_read_regs(BMA4_AUX_RD_ADDR, &data, 1, dev); - - if (rslt == BMA4_OK) - *mag_read_addr = BMA4_GET_BITS_POS_0(data, BMA4_READ_ADDR); - } - - return rslt; -} - -/*! - * @brief This API sets the address of the register of Aux Mag sensor - * where the data to be read. - */ -uint16_t bma4_set_mag_read_addr(uint8_t mag_read_addr, struct bma4_dev *dev) -{ - uint16_t rslt = 0; - - /* Check the bma4 structure as NULL */ - if (dev == NULL) { - rslt |= BMA4_E_NULL_PTR; - } else { - /* Write the Mag read address*/ - rslt |= bma4_write_regs(BMA4_AUX_RD_ADDR, &mag_read_addr, 1, dev); - } - - return rslt; -} - -/*! - * @brief This API gets the Aux Mag write address from the sensor. - * Mag write address is where the Mag data will be written. - */ -uint16_t bma4_get_mag_write_addr(uint8_t *mag_write_addr, struct bma4_dev *dev) -{ - uint16_t rslt = 0; - uint8_t data = 0; - - /* Check the bma4 structure as NULL */ - if (dev == NULL) { - rslt |= BMA4_E_NULL_PTR; - } else { - rslt |= bma4_read_regs(BMA4_AUX_WR_ADDR, &data, 1, dev); - - if (rslt == BMA4_OK) - *mag_write_addr = BMA4_GET_BITS_POS_0(data, BMA4_WRITE_ADDR); - } - - return rslt; -} - -/*! - * @brief This API sets the Aux Mag write address in the sensor. - * Mag write address is where the Mag data will be written. - */ -uint16_t bma4_set_mag_write_addr(uint8_t mag_write_addr, struct bma4_dev *dev) -{ - uint16_t rslt = 0; - - /* Check the bma4 structure as NULL */ - if (dev == NULL) - rslt |= BMA4_E_NULL_PTR; - else - rslt |= bma4_write_regs(BMA4_AUX_WR_ADDR, &mag_write_addr, 1, dev); - - return rslt; -} - -/*! - * @brief This API reads the data from the sensor which is written to the - * Mag. - */ -uint16_t bma4_get_mag_write_data(uint8_t *mag_write_data, struct bma4_dev *dev) -{ - uint16_t rslt = 0; - uint8_t data = 0; - - /* Check the bma4 structure as NULL */ - if (dev == NULL) { - rslt |= BMA4_E_NULL_PTR; - } else { - rslt |= bma4_read_regs(BMA4_AUX_WR_DATA_ADDR, &data, 1, dev); - - if (rslt == BMA4_OK) - *mag_write_data = BMA4_GET_BITS_POS_0(data, BMA4_WRITE_DATA); - } - - return rslt; -} - -/*! - * @brief This API sets the data in the sensor which in turn will - * be written to Mag. - */ -uint16_t bma4_set_mag_write_data(uint8_t mag_write_data, struct bma4_dev *dev) -{ - uint16_t rslt = 0; - - /* Check the bma4 structure as NULL */ - if (dev == NULL) - rslt |= BMA4_E_NULL_PTR; - else - rslt |= bma4_write_regs(BMA4_AUX_WR_DATA_ADDR, &mag_write_data, 1, dev); - - return rslt; -} - -/*! - * @brief This API reads the x,y,z and r axis data from the auxiliary - * Mag BMM150/AKM9916 sensor. - */ -uint16_t bma4_read_mag_xyzr(struct bma4_mag_xyzr *mag, struct bma4_dev *dev) -{ - uint16_t rslt = 0; - uint16_t msb = 0; - uint16_t lsb = 0; - uint8_t data[BMA4_MAG_XYZR_DATA_LENGTH] = {0}; - - /* Check the bma4 structure as NULL */ - if (dev == NULL) { - rslt |= BMA4_E_NULL_PTR; - } else { - rslt |= bma4_read_regs(BMA4_DATA_0_ADDR, data, BMA4_MAG_XYZR_DATA_LENGTH, dev); - - if (rslt == BMA4_OK) { - /* Data X */ - /* X-axis LSB value shifting */ - lsb = BMA4_GET_BITSLICE(data[BMA4_MAG_X_LSB_BYTE], BMA4_DATA_MAG_X_LSB); - msb = data[BMA4_MAG_X_MSB_BYTE]; - mag->x = (int16_t)((msb << 8) | lsb); - mag->x = (mag->x / 0x08); - - /* Data Y */ - /* Y-axis LSB value shifting */ - lsb = BMA4_GET_BITSLICE(data[BMA4_MAG_Y_LSB_BYTE], BMA4_DATA_MAG_Y_LSB); - msb = data[BMA4_MAG_Y_MSB_BYTE]; - mag->y = (int16_t)((msb << 8) | lsb); - mag->y = (mag->y / 0x08); - - /* Data Z */ - /* Z-axis LSB value shifting */ - lsb = BMA4_GET_BITSLICE(data[BMA4_MAG_Z_LSB_BYTE], BMA4_DATA_MAG_Z_LSB); - msb = data[BMA4_MAG_Z_MSB_BYTE]; - mag->z = (int16_t)((msb << 8) | lsb); - mag->z = (mag->z / 0x02); - - /* RHall */ - /* R-axis LSB value shifting */ - lsb = BMA4_GET_BITSLICE(data[BMA4_MAG_R_LSB_BYTE], BMA4_DATA_MAG_R_LSB); - msb = data[BMA4_MAG_R_MSB_BYTE]; - mag->r = (int16_t)((msb << 8) | lsb); - mag->r = (mag->r / 0x04); - } - } - - return rslt; -} - -/*! - * @brief This API sets the burst data length (1,2,6,8 byte) of auxiliary - * Mag sensor. - */ -uint16_t bma4_set_mag_burst(uint8_t mag_burst, struct bma4_dev *dev) -{ - uint16_t rslt = 0; - uint8_t data = 0; - - /* Check the bma4 structure as NULL */ - if (dev == NULL) { - rslt |= BMA4_E_NULL_PTR; - } else { - /* Write auxiliary burst mode length*/ - rslt |= bma4_read_regs(BMA4_AUX_IF_CONF_ADDR, &data, 1, dev); - - if (rslt == BMA4_OK) { - data = BMA4_SET_BITS_POS_0(data, BMA4_MAG_BURST, mag_burst); - rslt |= bma4_write_regs(BMA4_AUX_IF_CONF_ADDR, &data, 1, dev); - } - } - - return rslt; -} - -/*! - * @brief This API reads the burst data length of Mag set in the sensor. - */ -uint16_t bma4_get_mag_burst(uint8_t *mag_burst, struct bma4_dev *dev) -{ - uint16_t rslt = 0; - uint8_t data = 0; - - /* Check the bma4 structure as NULL */ - if (dev == NULL) { - rslt |= BMA4_E_NULL_PTR; - } else { - /* Write Mag burst mode length*/ - rslt |= bma4_read_regs(BMA4_AUX_IF_CONF_ADDR, &data, 1, dev); - - if (rslt == BMA4_OK) - *mag_burst = BMA4_GET_BITS_POS_0(data, BMA4_MAG_BURST); - } - - return rslt; -} - -/*! - * @brief This API reads the FIFO data of Accel and/or Mag sensor - */ -uint16_t bma4_read_fifo_data(struct bma4_dev *dev) -{ - uint16_t rslt = 0; - uint8_t data = 0; - uint8_t addr = BMA4_FIFO_DATA_ADDR; - /* check the bma4 structure as NULL*/ - if (dev == NULL || dev->fifo == NULL || dev->fifo->data == NULL) { - rslt |= BMA4_E_NULL_PTR; - } else { - reset_fifo_data_structure(dev); - /* read FIFO data*/ - if (dev->interface == BMA4_SPI_INTERFACE) - addr = addr | BMA4_SPI_RD_MASK; - - rslt |= dev->bus_read(dev->dev_addr, addr, dev->fifo->data, dev->fifo->length); - /* read fifo frame content configuration*/ - rslt |= bma4_read_regs(BMA4_FIFO_CONFIG_1_ADDR, &data, 1, dev); - /* filter fifo header enabled status */ - dev->fifo->fifo_header_enable = data & BMA4_FIFO_HEADER; - /* filter accel/mag data enabled status */ - dev->fifo->fifo_data_enable = data & BMA4_FIFO_M_A_ENABLE; - } - - return rslt; -} - -/*! - * @brief This API parses and extracts the accelerometer frames from - * FIFO data read by the "bma4_read_fifo_data" API and stores it in the - * "accel_data" structure instance. - */ -uint16_t bma4_extract_accel(struct bma4_accel *accel_data, uint16_t *accel_length, const struct bma4_dev *dev) -{ - uint16_t rslt = 0; - uint16_t data_index = 0; - uint16_t accel_index = 0; - uint16_t data_read_length = 0; - - if (dev == NULL || dev->fifo == NULL || dev->fifo->data == NULL) { - rslt |= BMA4_E_NULL_PTR; - } else { - /* Parsing the FIFO data in header-less mode */ - if (dev->fifo->fifo_header_enable == 0) { - get_accel_len_to_parse(&data_index, &data_read_length, accel_length, dev); - - for (; data_index < data_read_length;) { - unpack_acc_frm(accel_data, &data_index, &accel_index, dev->fifo->fifo_data_enable, dev); - /*Check for the availability of next - two bytes of FIFO data */ - check_empty_fifo(&data_index, dev); - } - /* update number of accel data read*/ - *accel_length = accel_index; - /*update the accel byte index*/ - dev->fifo->accel_byte_start_idx = data_index; - } else { - /* Parsing the FIFO data in header mode */ - extract_accel_header_mode(accel_data, accel_length, dev); - } - } - - return rslt; -} - -/*! - * @brief This API parses and extracts the magnetometer frames from - * FIFO data read by the "bma4_read_fifo_data" API and stores it in the - * "mag_data" structure instance parameter of this API - */ -uint16_t bma4_extract_mag(struct bma4_mag *mag_data, uint16_t *mag_length, const struct bma4_dev *dev) -{ - uint16_t rslt = 0; - uint16_t data_index = 0; - uint16_t mag_index = 0; - uint16_t data_read_length = 0; - - if (dev == NULL || dev->fifo == NULL || dev->fifo->data == NULL) { - rslt |= BMA4_E_NULL_PTR; - } else { - /* Parsing the FIFO data in header-less mode */ - if (dev->fifo->fifo_header_enable == 0) { - get_mag_len_to_parse(&data_index, &data_read_length, mag_length, dev); - for (; data_index < data_read_length;) { - rslt |= unpack_mag_frm(mag_data, &data_index, &mag_index, - dev->fifo->fifo_data_enable, dev); - /*Check for the availability of next - two bytes of FIFO data */ - check_empty_fifo(&data_index, dev); - } - /* update number of Aux. sensor data read*/ - *mag_length = mag_index; - /*update the Aux. sensor frame index*/ - dev->fifo->mag_byte_start_idx = data_index; - } else { - /* Parsing the FIFO data in header mode */ - rslt |= extract_mag_header_mode(mag_data, mag_length, dev); - } - } - - return rslt; -} - -/*! - * @brief This API reads the FIFO water mark level which is set - * in the sensor. - */ -uint16_t bma4_get_fifo_wm(uint16_t *fifo_wm, struct bma4_dev *dev) -{ - uint16_t rslt = 0; - uint8_t data[2] = {0, 0}; - - /* Check the bma4 structure as NULL*/ - if (dev == NULL) { - rslt |= BMA4_E_NULL_PTR; - } else { - /* Read the FIFO water mark level*/ - rslt |= bma4_read_regs(BMA4_FIFO_WTM_0_ADDR, data, BMA4_FIFO_WM_LENGTH, dev); - - if (BMA4_OK == rslt) - *fifo_wm = (data[1] << 8) | (data[0]); - } - - return rslt; -} - -/*! - * @brief This API sets the FIFO watermark level in the sensor. - */ -uint16_t bma4_set_fifo_wm(uint16_t fifo_wm, struct bma4_dev *dev) -{ - uint16_t rslt = 0; - uint8_t data[2] = {0, 0}; - - /* Check the bma4 structure as NULL*/ - if (dev == NULL) { - rslt |= BMA4_E_NULL_PTR; - } else { - - data[0] = BMA4_GET_LSB(fifo_wm); - data[1] = BMA4_GET_MSB(fifo_wm); - /* consecutive write is not possible in suspend mode hence - separate write is used with delay of 1 ms*/ - /* Write the fifo watermark level*/ - rslt |= bma4_write_regs(BMA4_FIFO_WTM_0_ADDR, &data[0], 1, dev); - dev->delay(BMA4_GEN_READ_WRITE_DELAY); - rslt |= bma4_write_regs((BMA4_FIFO_WTM_0_ADDR + 1), &data[1], 1, dev); - } - - return rslt; -} - -/*! - * @brief This API checks whether the Accel FIFO data is set for filtered - * or unfiltered mode. - */ -uint16_t bma4_get_accel_fifo_filter_data(uint8_t *accel_fifo_filter, struct bma4_dev *dev) -{ - uint16_t rslt = 0; - uint8_t data = 0; - - /* Check the bma4 structure as NULL */ - if (dev == NULL) { - rslt |= BMA4_E_NULL_PTR; - } else { - /* Read the Accel FIFO filter data */ - rslt |= bma4_read_regs(BMA4_FIFO_DOWN_ADDR, &data, 1, dev); - - if (rslt == BMA4_OK) - *accel_fifo_filter = BMA4_GET_BITSLICE(data, BMA4_FIFO_FILTER_ACCEL); - } - - return rslt; -} - -/*! - * @brief This API sets the condition of Accel FIFO data either to - * filtered or unfiltered mode. - */ -uint16_t bma4_set_accel_fifo_filter_data(uint8_t accel_fifo_filter, struct bma4_dev *dev) -{ - uint16_t rslt = 0; - uint8_t data = 0; - - /* Check the bma4 structure as NULL */ - if (dev == NULL) { - rslt |= BMA4_E_NULL_PTR; - } else { - if (accel_fifo_filter <= BMA4_MAX_VALUE_FIFO_FILTER) { - rslt |= bma4_read_regs(BMA4_FIFO_DOWN_ADDR, &data, 1, dev); - - if (rslt == BMA4_OK) { - /* Write Accel FIFO filter data */ - data = BMA4_SET_BITSLICE(data, BMA4_FIFO_FILTER_ACCEL, accel_fifo_filter); - rslt |= bma4_write_regs(BMA4_FIFO_DOWN_ADDR, &data, 1, dev); - } - } else { - rslt |= BMA4_E_OUT_OF_RANGE; - } - } - return rslt; -} - -/*! - * @brief This API reads the down sampling rates which is configured - * for Accel FIFO data. - */ -uint16_t bma4_get_fifo_down_accel(uint8_t *fifo_down, struct bma4_dev *dev) -{ - uint16_t rslt = 0; - uint8_t data = 0; - - - /* Check the bma4 structure as NULL */ - if (dev == NULL) { - rslt |= BMA4_E_NULL_PTR; - } else { - /* Read the Accel FIFO down data */ - rslt |= bma4_read_regs(BMA4_FIFO_DOWN_ADDR, &data, 1, dev); - - if (rslt == BMA4_OK) - *fifo_down = BMA4_GET_BITSLICE(data, BMA4_FIFO_DOWN_ACCEL); - } - - return rslt; -} - -/*! - * @brief This API sets the down-sampling rates for Accel FIFO. - */ -uint16_t bma4_set_fifo_down_accel(uint8_t fifo_down, struct bma4_dev *dev) -{ - uint16_t rslt = 0; - uint8_t data = 0; - - /* Check the bma4 structure as NULL */ - if (dev == NULL) { - rslt |= BMA4_E_NULL_PTR; - } else { - /* Write the Accel FIFO down data */ - rslt |= bma4_read_regs(BMA4_FIFO_DOWN_ADDR, &data, 1, dev); - - if (rslt == BMA4_OK) { - data = BMA4_SET_BITSLICE(data, BMA4_FIFO_DOWN_ACCEL, fifo_down); - rslt |= bma4_write_regs(BMA4_FIFO_DOWN_ADDR, &data, 1, dev); - } - } - return rslt; -} - -/*! - * @brief This API reads the length of FIFO data available in the sensor - * in the units of bytes. - */ -uint16_t bma4_get_fifo_length(uint16_t *fifo_length, struct bma4_dev *dev) -{ - uint16_t rslt = 0; - uint8_t index = 0; - uint8_t data[BMA4_FIFO_DATA_LENGTH] = {0, 0}; - - /* Check the bma4 structure as NULL */ - if (dev == NULL) { - rslt |= BMA4_E_NULL_PTR; - } else { - /* Read FIFO length*/ - rslt |= bma4_read_regs(BMA4_FIFO_LENGTH_0_ADDR, data, BMA4_FIFO_DATA_LENGTH, dev); - - if (rslt == BMA4_OK) { - index = BMA4_FIFO_LENGTH_MSB_BYTE; - data[index] = BMA4_GET_BITS_POS_0(data[index], BMA4_FIFO_BYTE_COUNTER_MSB); - *fifo_length = ((data[index] << 8) | data[index - 1]); - } - } - - return rslt; -} - -/*! - * @brief This API aligns and compensates the Mag data of BMM150/AKM9916 - * sensor. - */ -uint16_t bma4_second_if_mag_compensate_xyz(struct bma4_mag_fifo_data mag_fifo_data, - uint8_t mag_second_if, struct bma4_mag *compensated_mag_data) -{ - uint16_t rslt = 0; -#ifdef BMM150 - int16_t mag_x = 0; - int16_t mag_y = 0; - int16_t mag_z = 0; - uint16_t mag_r = 0; -#endif - - switch (mag_second_if) { -#ifdef BMM150 - case BMA4_SEC_IF_BMM150: - /* X data*/ - mag_x = (int16_t)((mag_fifo_data.mag_x_msb << 8) | (mag_fifo_data.mag_x_lsb)); - mag_x = (int16_t) (mag_x / 0x08); - - /* Y data*/ - mag_y = (int16_t)((mag_fifo_data.mag_y_msb << 8) | (mag_fifo_data.mag_y_lsb)); - mag_y = (int16_t) (mag_y / 0x08); - - /* Z data*/ - mag_z = (int16_t)((mag_fifo_data.mag_z_msb << 8) | (mag_fifo_data.mag_z_lsb)); - mag_z = (int16_t) (mag_z / 0x02); - - /* R data*/ - mag_r = (uint16_t)((mag_fifo_data.mag_r_y2_msb << 8) | (mag_fifo_data.mag_r_y2_lsb)); - mag_r = (uint16_t) (mag_r >> 2); - - /* Compensated Mag x data */ - compensated_mag_data->x = bma4_bmm150_mag_compensate_X(mag_x, mag_r); - - /* Compensated Mag y data */ - compensated_mag_data->y = bma4_bmm150_mag_compensate_Y(mag_y, mag_r); - - /* Compensated Mag z data */ - compensated_mag_data->z = bma4_bmm150_mag_compensate_Z(mag_z, mag_r); - break; -#endif - -#ifdef AKM9916 - - case BMA4_SEC_IF_AKM09916: - /* Compensated X data */ - compensated_mag_data->x = (int16_t)((mag_fifo_data.mag_x_msb << 8) | (mag_fifo_data.mag_x_lsb)); - /* Compensated Y data*/ - compensated_mag_data->y = (int16_t)((mag_fifo_data.mag_y_msb << 8) | (mag_fifo_data.mag_y_lsb)); - /* Compensated Z data*/ - compensated_mag_data->z = (int16_t)((mag_fifo_data.mag_z_msb << 8) | (mag_fifo_data.mag_z_lsb)); - break; - -#endif - default: - rslt |= BMA4_E_OUT_OF_RANGE; - break; - } - return rslt; -} - -/*! - * @brief This API reads Mag. x,y and z axis data from either BMM150 or - * AKM9916 sensor - */ -uint16_t bma4_read_mag_xyz(struct bma4_mag *mag, uint8_t sensor_select, struct bma4_dev *dev) -{ - uint16_t rslt = 0; - -#if defined(AKM9916) || defined(BMM150) - uint8_t index; - uint16_t msb = 0; - uint16_t lsb = 0; - uint8_t data[BMA4_MAG_XYZ_DATA_LENGTH] = {0}; -#endif - - /* Check the bma4 structure as NULL */ - if (dev == NULL) { - rslt |= BMA4_E_NULL_PTR; - } else { - switch (sensor_select) { - -#if defined(BMM150) - - case BMA4_SEC_IF_BMM150: - rslt |= bma4_read_regs(BMA4_DATA_0_ADDR, data, BMA4_MAG_XYZ_DATA_LENGTH, dev); - - if (rslt == BMA4_OK) { - index = BMA4_MAG_X_LSB_BYTE; - /*X-axis LSB value shifting*/ - data[index] = BMA4_GET_BITSLICE(data[index], BMA4_DATA_MAG_X_LSB); - /* Data X */ - msb = data[index + 1]; - lsb = data[index]; - mag->x = (int16_t)((msb << 8) | lsb); - mag->x = (mag->x / 0x08); - - /* Data Y */ - /*Y-axis LSB value shifting*/ - data[index + 2] = BMA4_GET_BITSLICE(data[index + 2], BMA4_DATA_MAG_Y_LSB); - msb = data[index + 3]; - lsb = data[index + 2]; - mag->y = (int16_t)((msb << 8) | lsb); - mag->y = (mag->y / 0x08); - - /* Data Z */ - /*Z-axis LSB value shifting*/ - data[index + 4] = BMA4_GET_BITSLICE(data[index + 4], BMA4_DATA_MAG_Z_LSB); - msb = data[index + 5]; - lsb = data[index + 4]; - mag->z = (int16_t)((msb << 8) | lsb); - mag->z = (mag->z / 0x02); - } - break; -#endif - -#if defined(AKM9916) - case BMA4_SEC_IF_AKM09916: - - if (AKM9916_SENSOR == dev->aux_sensor) { - rslt |= bma4_read_regs(BMA4_DATA_0_ADDR, data, BMA4_MAG_XYZ_DATA_LENGTH, dev); - - if (rslt == BMA4_OK) { - index = BMA4_MAG_X_LSB_BYTE; - /* Data X */ - msb = data[index + 1]; - lsb = data[index]; - mag->x = (int16_t)((msb << 8) | lsb); - - /* Data Y */ - msb = data[index + 3]; - lsb = data[index + 2]; - mag->y = (int32_t)((msb << 8) | lsb); - - /* Data Z */ - msb = data[index + 5]; - lsb = data[index + 4]; - mag->z = (int16_t)((msb << 8) | lsb); - } - } - break; -#endif - - default: - rslt |= BMA4_E_OUT_OF_RANGE; - break; - } - } - - return rslt; -} - -/*! - * @brief This API reads the auxiliary I2C interface configuration which - * is set in the sensor. - */ -uint16_t bma4_get_if_mode(uint8_t *if_mode, struct bma4_dev *dev) -{ - uint16_t rslt = 0; - uint8_t data = 0; - - /* Check the bma4 structure as NULL */ - if (dev == NULL) { - rslt |= BMA4_E_NULL_PTR; - } else { - /* Read auxiliary interface configuration */ - rslt |= bma4_read_regs(BMA4_IF_CONFIG_ADDR, &data, 1, dev); - - if (rslt == BMA4_OK) - *if_mode = BMA4_GET_BITSLICE(data, BMA4_IF_CONFIG_IF_MODE); - } - - return rslt; -} - -/*! - * @brief This API sets the auxiliary interface configuration in the - * sensor. - */ -uint16_t bma4_set_if_mode(uint8_t if_mode, struct bma4_dev *dev) -{ - uint16_t rslt = 0; - uint8_t data = 0; - - /* Check the bma4 structure as NULL */ - if (dev == NULL) { - rslt |= BMA4_E_NULL_PTR; - } else { - if (if_mode <= BMA4_MAX_IF_MODE) { - /* Write the interface configuration mode */ - rslt |= bma4_read_regs(BMA4_IF_CONFIG_ADDR, &data, 1, dev); - if (rslt == BMA4_OK) { - data = BMA4_SET_BITSLICE(data, BMA4_IF_CONFIG_IF_MODE, if_mode); - rslt |= bma4_write_regs(BMA4_IF_CONFIG_ADDR, &data, 1, dev); - } - } else { - rslt |= BMA4_E_OUT_OF_RANGE; - } - } - - return rslt; -} - -/*! - * @brief This API reads the data ready status of Accel from the sensor. - */ -uint16_t bma4_get_accel_data_rdy(uint8_t *data_rdy, struct bma4_dev *dev) -{ - uint16_t rslt = 0; - uint8_t data = 0; - - /* Check the bma4 structure as NULL */ - if (dev == NULL) { - rslt |= BMA4_E_NULL_PTR; - } else { - /*Reads the status of Accel data ready*/ - rslt |= bma4_read_regs(BMA4_STATUS_ADDR, &data, 1, dev); - - if (rslt == BMA4_OK) - *data_rdy = BMA4_GET_BITSLICE(data, BMA4_STAT_DATA_RDY_ACCEL); - } - - return rslt; -} - -/*! - * @brief This API reads the data ready status of Mag from the sensor. - * The status get reset when Mag data register is read. - */ -uint16_t bma4_get_mag_data_rdy(uint8_t *data_rdy, struct bma4_dev *dev) -{ - uint16_t rslt = 0; - uint8_t data = 0; - - /* Check the bma4 structure as NULL */ - if (dev == NULL) { - rslt |= BMA4_E_NULL_PTR; - } else { - /*Reads the status of Accel data ready*/ - rslt |= bma4_read_regs(BMA4_STATUS_ADDR, &data, 1, dev); - - if (rslt == BMA4_OK) - *data_rdy = BMA4_GET_BITSLICE(data, BMA4_STAT_DATA_RDY_MAG); - } - - return rslt; -} - -/*! - * @brief This API reads the ASIC status from the sensor. - * The status information is mentioned in the below table. - */ -uint16_t bma4_get_asic_status(struct bma4_asic_status *asic_status, struct bma4_dev *dev) -{ - uint16_t rslt = 0; - uint8_t data = 0; - - /* Check the bma4 structure as NULL */ - if (dev == NULL) { - rslt |= BMA4_E_NULL_PTR; - } else { - /* Read the Mag I2C device address*/ - rslt |= bma4_read_regs(BMA4_INTERNAL_ERROR, &data, 1, dev); - - if (rslt == BMA4_OK) { - asic_status->sleep = (data & 0x01); - asic_status->irq_ovrn = ((data & 0x02) >> 0x01); - asic_status->wc_event = ((data & 0x04) >> 0x02); - asic_status->stream_transfer_active = ((data & 0x08) >> 0x03); - } - } - - return rslt; -} - -/*! - * @brief This API enables the offset compensation for filtered and - * unfiltered Accel data. - */ -uint16_t bma4_set_offset_comp(uint8_t offset_en, struct bma4_dev *dev) -{ - uint16_t rslt = 0; - uint8_t data = 0; - - /* Check the bma4 structure as NULL */ - if (dev == NULL) { - rslt |= BMA4_E_NULL_PTR; - } else { - rslt |= bma4_read_regs(BMA4_NV_CONFIG_ADDR, &data, 1, dev); - - if (rslt == BMA4_OK) { - /* Write Accel FIFO filter data */ - data = BMA4_SET_BITSLICE(data, BMA4_NV_ACCEL_OFFSET, offset_en); - rslt |= bma4_write_regs(BMA4_NV_CONFIG_ADDR, &data, 1, dev); - } - } - - return rslt; -} - -/*! - * @brief This API gets the status of Accel offset compensation - */ -uint16_t bma4_get_offset_comp(uint8_t *offset_en, struct bma4_dev *dev) -{ - uint16_t rslt = 0; - uint8_t data = 0; - - /* Check the bma4 structure as NULL */ - if (dev == NULL) { - rslt |= BMA4_E_NULL_PTR; - } else { - rslt |= bma4_read_regs(BMA4_NV_CONFIG_ADDR, &data, 1, dev); - - if (rslt == BMA4_OK) { - /* Write Accel FIFO filter data */ - *offset_en = BMA4_GET_BITSLICE(data, BMA4_NV_ACCEL_OFFSET); - } - } - - return rslt; -} - -/*! - * @brief This API performs Fast Offset Compensation for Accel. - * - * @note The g-values to be passed to the parameter should be - * multiples of 1000000. - */ -uint16_t bma4_perform_accel_foc(const int32_t accel_g_value[3], struct bma4_dev *dev) -{ - uint16_t rslt = 0; - struct bma4_accel accel_value[10] = { {0} }; - struct accel_offset offset = {0}; - struct offset_delta delta = { {0} }; - struct bma4_accel_config acc_conf = {0}; - uint8_t accel_en = 0; - uint8_t adv_pwr_save = 0; - uint8_t range = 0; - uint16_t lsb_per_g = 0; - struct accel_temp temp = {0}; - struct bma4_accel avg = {0}; - struct bma4_accel accel_data = {0}; - uint8_t i = 0; - - /* used to validate user input */ - rslt |= validate_user_input(accel_g_value); - - if (BMA4_OK == rslt) { - /* Configure accel config, accel enable and - advance power save for FOC */ - rslt |= foc_config(&acc_conf, &accel_en, &adv_pwr_save, dev); - - /*TO DO: Check for data ready status before - reading accel values*/ - - if (BMA4_OK == rslt) { - /* Giving a delay of 20ms before reading accel data - since odr is configured as 50Hz */ - for (i = 0; i < 10; i++) { - dev->delay(20); - rslt |= bma4_read_accel_xyz(&accel_value[i], dev); - temp.x = temp.x + (int32_t)accel_value[i].x; - temp.y = temp.y + (int32_t)accel_value[i].y; - temp.z = temp.z + (int32_t)accel_value[i].z; - } - - /* Take average of x, y and z data for lesser noise */ - avg.x = (int16_t)(temp.x / 10); - avg.y = (int16_t)(temp.y / 10); - avg.z = (int16_t)(temp.z / 10); - - /* Copy average value in another structure */ - accel_data = avg; - - if (BMA4_OK == rslt) { - /* Get the exact range value */ - map_range(acc_conf.range, &range); - /* Get LSB per bit given the range and resolution */ - lsb_per_g = (uint16_t)(power(2, dev->resolution) / (2 * range)); - /* Compensate accel data against gravity */ - comp_for_grvty(lsb_per_g, accel_g_value, &accel_data, &delta); - /* scale according to offset register resolution*/ - scale_offset(dev->resolution, range, &delta, &offset); - /* normalise the data with offset*/ - normalise_offset(&delta, &offset); - - /* offset values are written in the offset register */ - rslt |= bma4_write_regs(BMA4_OFFSET_0_ADDR, (uint8_t *)&offset.x, 1, dev); - rslt |= bma4_write_regs(BMA4_OFFSET_1_ADDR, (uint8_t *)&offset.y, 1, dev); - rslt |= bma4_write_regs(BMA4_OFFSET_2_ADDR, (uint8_t *)&offset.z, 1, dev); - - /* Enable offset compensation */ - rslt |= bma4_set_offset_comp(BMA4_ENABLE, dev); - - /* Set accel config, accel enable and advance power save */ - rslt |= bma4_set_accel_config(&acc_conf, dev); - rslt |= bma4_set_accel_enable(accel_en, dev); - rslt |= bma4_set_advance_power_save(adv_pwr_save, dev); - } else { - rslt |= BMA4_E_FOC_FAIL; - } - } - } - return rslt; -} - -/*! - * @brief This API checks whether the self test functionality of the sensor - * is working or not. - * The following parameter of struct bma4_dev, should have the valid value before - * performing the Self test, - * 1. Variant and 2. Resolution - */ -uint16_t bma4_perform_accel_selftest(uint8_t *result, struct bma4_dev *dev) -{ - uint16_t rslt = 0; - struct bma4_accel positive = {0}; - struct bma4_accel negative = {0}; - /*! Structure for difference of accel values in g*/ - struct selftest_delta_limit accel_data_diff = {0}; - /*! Structure for difference of accel values in mg*/ - struct selftest_delta_limit accel_data_diff_mg = {0}; - - *result = BMA4_SELFTEST_FAIL; - - if (dev == NULL) { - rslt |= BMA4_E_NULL_PTR; - } else { - - rslt = set_accel_selftest_config(dev); - dev->delay(20); - rslt |= bma4_selftest_config(BMA4_ENABLE, dev); - - if (rslt == BMA4_OK) { - dev->delay(100); - rslt = bma4_read_accel_xyz(&positive, dev); - rslt |= bma4_selftest_config(BMA4_DISABLE, dev); - - if (rslt == BMA4_OK) { - dev->delay(100); - rslt = bma4_read_accel_xyz(&negative, dev); - - accel_data_diff.x = ABS(positive.x) + ABS(negative.x); - accel_data_diff.y = ABS(positive.y) + ABS(negative.y); - accel_data_diff.z = ABS(positive.z) + ABS(negative.z); - - /*! Converting LSB of the differences of accel values to mg*/ - convert_lsb_g(&accel_data_diff, &accel_data_diff_mg, dev); - /*! Validating self test for accel values in mg*/ - rslt |= validate_selftest(&accel_data_diff_mg, dev); - - if (rslt == BMA4_OK) - *result = BMA4_SELFTEST_PASS; - - /* Triggers a soft reset */ - rslt |= bma4_set_command_register(0xB6, dev); - dev->delay(200); - } - } - } - - return rslt; -} - -/*! - * @brief This API performs the steps needed for Self test operation - * before reading the Accel Self test data. - */ -uint16_t bma4_selftest_config(uint8_t sign, struct bma4_dev *dev) -{ - uint16_t rslt = 0; - - rslt |= set_accel_selftest_enable(BMA4_ENABLE, dev); - rslt |= set_accel_selftest_sign(sign, dev); - - /* Set self test amplitude based on variant */ - switch (dev->variant) { - case BMA42X_VARIANT: - /* Set self test amplitude to high for BMA42x */ - rslt |= set_accel_selftest_amp(BMA4_ENABLE, dev); - break; - - case BMA45X_VARIANT: - /* Set self test amplitude to low for BMA45x */ - rslt |= set_accel_selftest_amp(BMA4_DISABLE, dev); - break; - - default: - rslt = BMA4_E_INVALID_SENSOR; - break; - } - - return rslt; -} - -/*! - * @brief API sets the interrupt to either interrupt1 or - * interrupt2 pin in the sensor. - */ -uint16_t bma4_map_interrupt(uint8_t int_line, uint16_t int_map, uint8_t enable, struct bma4_dev *dev) -{ - uint16_t rslt = 0; - uint8_t data[3] = {0, 0, 0}; - uint8_t index[2] = {BMA4_INT_MAP_1_ADDR, BMA4_INT_MAP_2_ADDR}; - - /* Check the bma4 structure as NULL */ - if (dev == NULL) { - rslt |= BMA4_E_NULL_PTR; - } else { - - rslt |= bma4_read_regs(BMA4_INT_MAP_1_ADDR, data, 3, dev); - - if (enable == TRUE) { - /* Feature interrupt mapping */ - data[int_line] |= (uint8_t)(int_map & (0x00FF)); - /* Hardware interrupt mapping */ - if (int_line == BMA4_INTR2_MAP) - data[2] |= (uint8_t)((int_map & (0xFF00)) >> 4); - else - data[2] |= (uint8_t)((int_map & (0xFF00)) >> 8); - - rslt |= bma4_write_regs(index[int_line], &data[int_line], 1, dev); - rslt |= bma4_write_regs(BMA4_INT_MAP_DATA_ADDR, &data[2], 1, dev); - - } else { - /* Feature interrupt un-mapping */ - data[int_line] &= (~(uint8_t)(int_map & (0x00FF))); - /* Hardware interrupt un-mapping */ - if (int_line == BMA4_INTR2_MAP) - data[2] &= (~(uint8_t)((int_map & (0xFF00)) >> 4)); - else - data[2] &= (~(uint8_t)((int_map & (0xFF00)) >> 8)); - - rslt |= bma4_write_regs(index[int_line], &data[int_line], 1, dev); - rslt |= bma4_write_regs(BMA4_INT_MAP_DATA_ADDR, &data[2], 1, dev); - - } - } - - return rslt; -} - -/*! - * @brief This API sets the interrupt mode in the sensor. - */ -uint16_t bma4_set_interrupt_mode(uint8_t mode, struct bma4_dev *dev) -{ - uint16_t rslt = 0; - - /* Check the bma4 structure as NULL */ - if (dev == NULL) { - rslt |= BMA4_E_NULL_PTR; - } else { - - if (mode == BMA4_NON_LATCH_MODE || mode == BMA4_LATCH_MODE) - rslt |= bma4_write_regs(BMA4_INTR_LATCH_ADDR, &mode, 1, dev); - else - rslt |= BMA4_E_OUT_OF_RANGE; - } - - return rslt; -} - -/*! - * @brief This API gets the interrupt mode which is set in the sensor. - */ -uint16_t bma4_get_interrupt_mode(uint8_t *mode, struct bma4_dev *dev) -{ - uint16_t rslt = 0; - uint8_t data = 0; - - /* Check the bma4 structure as NULL */ - if (dev == NULL) { - rslt |= BMA4_E_NULL_PTR; - } else { - rslt |= bma4_read_regs(BMA4_INTR_LATCH_ADDR, &data, 1, dev); - *mode = data; - } - - return rslt; - -} - -/*! - * @brief This API sets the auxiliary Mag(BMM150 or AKM9916) output data - * rate and offset. - */ -uint16_t bma4_set_aux_mag_config(const struct bma4_aux_mag_config *aux_mag, struct bma4_dev *dev) -{ - uint16_t rslt = 0; - uint8_t data = 0; - - /* Check the bma4 structure as NULL */ - if (dev == NULL) { - rslt |= BMA4_E_NULL_PTR; - } else { - if ((aux_mag->odr >= BMA4_OUTPUT_DATA_RATE_0_78HZ) && - (aux_mag->odr <= BMA4_OUTPUT_DATA_RATE_1600HZ) - && ((aux_mag->offset & BMA4_MAG_CONFIG_OFFSET_MSK) == 0x00)) { - data = (uint8_t)(aux_mag->odr | - ((aux_mag->offset << - BMA4_MAG_CONFIG_OFFSET_POS))); - rslt |= bma4_write_regs(BMA4_AUX_CONFIG_ADDR, &data, 1, dev); - } else { - rslt |= BMA4_E_OUT_OF_RANGE; - } - } - - return rslt; -} - -/*! - * @brief This API reads the auxiliary Mag(BMM150 or AKM9916) output data - * rate and offset. - */ -uint16_t bma4_get_aux_mag_config(struct bma4_aux_mag_config *aux_mag, struct bma4_dev *dev) -{ - uint16_t rslt = 0; - uint8_t data = 0; - - /* Check the bma4 structure as NULL */ - if (dev == NULL) { - rslt |= BMA4_E_NULL_PTR; - } else { - rslt |= bma4_read_regs(BMA4_AUX_CONFIG_ADDR, &data, 1, dev); - - if (rslt == BMA4_OK) { - aux_mag->odr = (data & 0x0F); - aux_mag->offset = (data & BMA4_MAG_CONFIG_OFFSET_MSK) >> 4; - } - } - - return rslt; -} - -/*! @brief This API sets the FIFO configuration in the sensor. - */ -uint16_t bma4_set_fifo_config(uint8_t config, uint8_t enable, struct bma4_dev *dev) -{ - uint16_t rslt = 0; - uint8_t data[2] = {0, 0}; - uint8_t fifo_config_0 = config & BMA4_FIFO_CONFIG_0_MASK; - - /* Check the bma4 structure as NULL */ - if (dev == NULL) { - rslt |= BMA4_E_NULL_PTR; - } else { - rslt |= bma4_read_regs(BMA4_FIFO_CONFIG_0_ADDR, data, BMA4_FIFO_CONFIG_LENGTH, dev); - - if (rslt == BMA4_OK) { - - if (fifo_config_0 > 0) { - - if (enable == TRUE) - data[0] = data[0] | fifo_config_0; - else - data[0] = data[0] & (~fifo_config_0); - } - - if (enable == TRUE) - data[1] = data[1] | (config & BMA4_FIFO_CONFIG_1_MASK); - else - data[1] = data[1] & (~(config & BMA4_FIFO_CONFIG_1_MASK)); - - /* Burst write is not possible in suspend mode hence - separate write is used with delay of 1 ms*/ - rslt |= bma4_write_regs(BMA4_FIFO_CONFIG_0_ADDR, &data[0], 1, dev); - dev->delay(BMA4_GEN_READ_WRITE_DELAY); - rslt |= bma4_write_regs((BMA4_FIFO_CONFIG_0_ADDR + 1), &data[1], 1, dev); - } - } - - return rslt; -} - -/*! @brief This API reads the FIFO configuration from the sensor. - */ -uint16_t bma4_get_fifo_config(uint8_t *fifo_config, struct bma4_dev *dev) -{ - uint16_t rslt = 0; - uint8_t data[2] = {0, 0}; - - /* Check the bma4 structure as NULL */ - if (dev == NULL) { - rslt |= BMA4_E_NULL_PTR; - } else { - rslt |= bma4_read_regs(BMA4_FIFO_CONFIG_0_ADDR, data, BMA4_FIFO_CONFIG_LENGTH, dev); - - if (rslt == BMA4_OK) - *fifo_config = ((uint8_t)((data[0] & BMA4_FIFO_CONFIG_0_MASK) | (data[1]))); - - } - - return rslt; -} - -/*! @brief This function sets the electrical behaviour of interrupt pin1 or - * pin2 in the sensor. - */ -uint16_t bma4_set_int_pin_config(const struct bma4_int_pin_config *int_pin_config, uint8_t int_line, - struct bma4_dev *dev) -{ - uint16_t rslt = 0; - uint8_t interrupt_address_array[2] = {BMA4_INT1_IO_CTRL_ADDR, BMA4_INT2_IO_CTRL_ADDR}; - uint8_t data = 0; - - /* Check the bma4 structure as NULL */ - if (dev == NULL) { - rslt |= BMA4_E_NULL_PTR; - } else { - if (int_line <= 1) { - data = ((uint8_t)((int_pin_config->edge_ctrl & BMA4_INT_EDGE_CTRL_MASK) | - ((int_pin_config->lvl << 1) & BMA4_INT_LEVEL_MASK) | - ((int_pin_config->od << 2) & BMA4_INT_OPEN_DRAIN_MASK) | - ((int_pin_config->output_en << 3) & BMA4_INT_OUTPUT_EN_MASK) | - ((int_pin_config->input_en << 4) & BMA4_INT_INPUT_EN_MASK))); - - rslt |= bma4_write_regs(interrupt_address_array[int_line], &data, 1, dev); - } else { - rslt |= BMA4_E_INT_LINE_INVALID; - } - } - - return rslt; -} - -/*! @brief This API reads the electrical behavior of interrupt pin1 or pin2 - * from the sensor. - */ -uint16_t bma4_get_int_pin_config(struct bma4_int_pin_config *int_pin_config, uint8_t int_line, struct bma4_dev *dev) -{ - uint16_t rslt = 0; - uint8_t interrupt_address_array[2] = {BMA4_INT1_IO_CTRL_ADDR, BMA4_INT2_IO_CTRL_ADDR}; - uint8_t data = 0; - - if (dev == NULL) { - rslt |= BMA4_E_NULL_PTR; - } else { - if (int_line <= 1) { - rslt |= bma4_read_regs(interrupt_address_array[int_line], &data, 1, dev); - /* Assign interrupt configurations to the - structure members*/ - if (rslt == BMA4_OK) { - int_pin_config->edge_ctrl = data & BMA4_INT_EDGE_CTRL_MASK; - int_pin_config->lvl = ((data & BMA4_INT_LEVEL_MASK) >> BMA4_INT_LEVEL_POS); - int_pin_config->od = ((data & BMA4_INT_OPEN_DRAIN_MASK) >> BMA4_INT_OPEN_DRAIN_POS); - int_pin_config->output_en = ((data & BMA4_INT_OUTPUT_EN_MASK) - >> BMA4_INT_OUTPUT_EN_POS); - int_pin_config->input_en = ((data & BMA4_INT_INPUT_EN_MASK) >> BMA4_INT_INPUT_EN_POS); - } - } else { - rslt |= BMA4_E_INT_LINE_INVALID; - } - } - - return rslt; -} - -/*! - * @brief This API reads the Feature and Hardware interrupt status from the sensor. - */ -uint16_t bma4_read_int_status(uint16_t *int_status, struct bma4_dev *dev) -{ - uint16_t rslt = 0; - uint8_t data[2] = {0}; - - /* Check the bma4 structure as NULL */ - if (dev == NULL) { - rslt |= BMA4_E_NULL_PTR; - } else { - rslt |= bma4_read_regs(BMA4_INT_STAT_0_ADDR, data, 2, dev); - - if (rslt == BMA4_OK) { - *int_status = data[0]; - *((uint8_t *)int_status + 1) = data[1]; - } - } - - return rslt; -} - -/*! - * @brief This API reads the Feature interrupt status from the sensor. - */ -uint16_t bma4_read_int_status_0(uint8_t *int_status_0, struct bma4_dev *dev) -{ - uint16_t rslt = BMA4_OK; - - /* Check the bma4 structure as NULL */ - if (dev == NULL) { - /* Null pointer check */ - rslt = BMA4_E_NULL_PTR; - } else { - rslt = bma4_read_regs(BMA4_INT_STAT_0_ADDR, int_status_0, 1, dev); - } - - return rslt; -} - -/*! - * @brief This API reads the Hardware interrupt status from the sensor. - */ -uint16_t bma4_read_int_status_1(uint8_t *int_status_1, struct bma4_dev *dev) -{ - uint16_t rslt = BMA4_OK; - - /* Check the bma4 structure as NULL */ - if (dev == NULL) { - /* Null pointer check */ - rslt = BMA4_E_NULL_PTR; - } else { - rslt = bma4_read_regs(BMA4_INT_STAT_1_ADDR, int_status_1, 1, dev); - } - - return rslt; -} - -/*! - * @brief This API initializes the auxiliary interface to access - * auxiliary sensor - */ -uint16_t bma4_aux_interface_init(struct bma4_dev *dev) -{ - /* Variable to return error codes */ - uint16_t rslt = BMA4_OK; - - /* Check for Null pointer error */ - rslt |= bma4_null_pointer_check(dev); - if (rslt == BMA4_OK) { - /* Set the auxiliary sensor configuration */ - rslt = bma4_set_aux_interface_config(dev); - if (rslt != BMA4_OK) - rslt = BMA4_E_AUX_CONFIG_FAIL; - } - - return rslt; -} - -/*! - * @brief This API reads the data from the auxiliary sensor -*/ -uint16_t bma4_aux_read(uint8_t aux_reg_addr, uint8_t *aux_data, uint16_t len, struct bma4_dev *dev) -{ - /* Variable to return error codes */ - uint16_t rslt = BMA4_OK; - - /* Check for Null pointer error */ - rslt |= bma4_null_pointer_check(dev); - if (rslt == BMA4_OK) { - /* Read the data from the data register in terms of - user defined length */ - rslt = bma4_extract_aux_data(aux_reg_addr, aux_data, len, dev); - } - - return rslt; -} - -/*! - * @brief This API writes the data into the auxiliary sensor -*/ -uint16_t bma4_aux_write(uint8_t aux_reg_addr, uint8_t *aux_data, uint16_t len, struct bma4_dev *dev) -{ - - uint16_t rslt = BMA4_OK; - - /* Check for Null pointer error */ - rslt |= bma4_null_pointer_check(dev); - if (rslt == BMA4_OK) { - /* Write data in terms of user defined length */ - if (len > 0) { - while (len--) { - /* First set data to write */ - rslt = bma4_write_regs(BMA4_AUX_WR_DATA_ADDR, aux_data, 1, dev); - dev->delay(BMA4_AUX_COM_DELAY); - if (rslt == BMA4_OK) { - /* Then set address to write */ - rslt = bma4_write_regs(BMA4_AUX_WR_ADDR, &aux_reg_addr, 1, dev); - dev->delay(BMA4_AUX_COM_DELAY); - - /* Increment data array and register address until - * user-defined length is greater than 0 */ - if ((rslt == BMA4_OK) && (len > 0)) { - aux_data++; - aux_reg_addr++; - } - } else { - rslt = BMA4_E_FAIL; - } - } - } else { - rslt = BMA4_E_RD_WR_LENGTH_INVALID; - } - } - - return rslt; -} - -/*****************************************************************************/ -/* Static function definition */ -/*! - * @brief This API converts lsb value of axes to mg for self-test * - */ -static void convert_lsb_g(const struct selftest_delta_limit *accel_data_diff, - struct selftest_delta_limit *accel_data_diff_mg, - const struct bma4_dev *dev) -{ - uint32_t lsb_per_g; - /*! Range considered for self-test is 8g */ - uint8_t range = 8; - - /*! lsb_per_g for the respective resolution and 8g range*/ - lsb_per_g = (uint32_t)(power(2, dev->resolution) / (2 * range)); - /*! accel x value in mg */ - accel_data_diff_mg->x = (accel_data_diff->x / (int32_t)lsb_per_g) * 1000; - /*! accel y value in mg */ - accel_data_diff_mg->y = (accel_data_diff->y / (int32_t)lsb_per_g) * 1000; - /*! accel z value in mg */ - accel_data_diff_mg->z = (accel_data_diff->z / (int32_t)lsb_per_g) * 1000; -} - -/*! - * @brief This API writes the config stream data in memory using burst mode - * @note index value should be even number. - */ -static uint16_t stream_transfer_write(const uint8_t *stream_data, uint16_t index, struct bma4_dev *dev) -{ - uint16_t rslt = 0; - uint8_t asic_msb = (uint8_t)((index / 2) >> 4); - uint8_t asic_lsb = ((index / 2) & 0x0F); - - rslt |= bma4_write_regs(BMA4_RESERVED_REG_5B_ADDR, &asic_lsb, 1, dev); - - if (rslt == BMA4_OK) { - rslt |= bma4_write_regs(BMA4_RESERVED_REG_5C_ADDR, &asic_msb, 1, dev); - - if (rslt == BMA4_OK) - rslt |= write_regs(BMA4_FEATURE_CONFIG_ADDR, (uint8_t *)stream_data, dev->read_write_len, dev); - } - - return rslt; -} - -/*! - * @brief This API enables or disables the Accel Self test feature in the - * sensor. - */ -static uint16_t set_accel_selftest_enable(uint8_t accel_selftest_enable, struct bma4_dev *dev) -{ - uint16_t rslt = 0; - uint8_t data = 0; - /* Check the bma4 structure as NULL */ - if (dev == NULL) { - rslt |= BMA4_E_NULL_PTR; - } else { - /* Read the self test register */ - rslt |= bma4_read_regs(BMA4_ACC_SELF_TEST_ADDR, &data, 1, dev); - - if (rslt == BMA4_OK) { - data = BMA4_SET_BITS_POS_0(data, BMA4_ACCEL_SELFTEST_ENABLE, accel_selftest_enable); - rslt |= bma4_write_regs(BMA4_ACC_SELF_TEST_ADDR, &data, 1, dev); - } - } - - return rslt; -} - -/*! - * @brief This API selects the sign of Accel self-test excitation. - */ -static uint16_t set_accel_selftest_sign(uint8_t accel_selftest_sign, struct bma4_dev *dev) -{ - uint16_t rslt = 0; - uint8_t data = 0; - /* Check the bma4 structure as NULL */ - if (dev == NULL) { - rslt |= BMA4_E_NULL_PTR; - } else { - - if (accel_selftest_sign <= BMA4_MAX_VALUE_SELFTEST_SIGN) { - /* Read the Accel self test sign*/ - rslt |= bma4_read_regs(BMA4_ACC_SELF_TEST_ADDR, &data, 1, dev); - - if (rslt == BMA4_OK) { - data = BMA4_SET_BITSLICE(data, BMA4_ACCEL_SELFTEST_SIGN, accel_selftest_sign); - rslt |= bma4_write_regs(BMA4_ACC_SELF_TEST_ADDR, &data, 1, dev); - } - } else { - rslt = BMA4_E_OUT_OF_RANGE; - } - } - - return rslt; -} - -/*! - * @brief This API sets the Accel self test amplitude in the sensor. - */ -static uint16_t set_accel_selftest_amp(uint8_t accel_selftest_amp, struct bma4_dev *dev) -{ - uint16_t rslt = 0; - uint8_t data = 0; - /* Check the bma4 structure as NULL */ - if (dev == NULL) { - rslt |= BMA4_E_NULL_PTR; - } else { - - if (accel_selftest_amp <= BMA4_MAX_VALUE_SELFTEST_AMP) { - /* Write self test amplitude*/ - rslt |= bma4_read_regs(BMA4_ACC_SELF_TEST_ADDR, &data, 1, dev); - - if (rslt == BMA4_OK) { - data = BMA4_SET_BITSLICE(data, BMA4_SELFTEST_AMP, accel_selftest_amp); - - rslt |= bma4_write_regs(BMA4_ACC_SELF_TEST_ADDR, &data, 1, dev); - } - } else { - rslt |= BMA4_E_OUT_OF_RANGE; - } - } - - return rslt; -} - -/*! - * @brief This function enables and configures the Accel which is needed - * for Self test operation. - */ -static uint16_t set_accel_selftest_config(struct bma4_dev *dev) -{ - uint16_t rslt = 0; - struct bma4_accel_config accel = {0}; - - accel.odr = BMA4_OUTPUT_DATA_RATE_1600HZ; - accel.bandwidth = BMA4_ACCEL_NORMAL_AVG4; - accel.perf_mode = BMA4_ENABLE; - accel.range = BMA4_ACCEL_RANGE_8G; - - rslt |= bma4_set_accel_enable(BMA4_ENABLE, dev); - dev->delay(1); - rslt |= bma4_set_accel_config(&accel, dev); - - return rslt; -} - -/*! - * @brief This API validates the Accel g value provided as input by the - * user for Accel offset compensation. - * - * @note The g-values to be passed to the parameter should be - * multiples of 1000000. - */ -static uint16_t validate_user_input(const int32_t *gvalue) - -{ - uint8_t index = 0; - int32_t min_gval = (int32_t)(-1.0 * BMA4XY_MULTIPLIER); - int32_t max_gval = (int32_t)(1.0 * BMA4XY_MULTIPLIER); - - while (index < 3) { - if (gvalue[index] >= min_gval && gvalue[index] <= max_gval) - index++; - else - return BMA4_E_OUT_OF_RANGE; - } - - return BMA4_OK; -} - -/*! - * @brief This API normalise the data with offset - */ -static void normalise_offset(const struct offset_delta *compensated_data, struct accel_offset *offset_data) -{ - /* for handling negative offset */ - /* employing twos's Complement method*/ - if (compensated_data->x.is_negative == TRUE) { - offset_data->x = ~offset_data->x; - offset_data->x += 1; - } - - if (compensated_data->y.is_negative == TRUE) { - offset_data->y = ~offset_data->y; - offset_data->y += 1; - } - - if (compensated_data->z.is_negative == TRUE) { - offset_data->z = ~offset_data->z; - offset_data->z += 1; - } - - offset_data->x = (uint8_t)((offset_data->x) * (-1)); - offset_data->y = (uint8_t)((offset_data->y) * (-1)); - offset_data->z = (uint8_t)((offset_data->z) * (-1)); -} - -/*! - * @brief This API normalize the data with offset. - */ -static void scale_offset(uint8_t res, uint8_t range, const struct offset_delta *delta, struct accel_offset *data) -{ - int8_t bit_pos_3_9mg, bit_pos_3_9mg_nextbit; - uint8_t round_off = 0; - - /* Find the bit position of 3.9mg */ - bit_pos_3_9mg = get_bit_pos_3_9mg(range, res); - - /* Data register resolution less than or equal to 3.9 mg */ - if (bit_pos_3_9mg > 0) { - /* Round off, consider if the next bit is high */ - bit_pos_3_9mg_nextbit = bit_pos_3_9mg - 1; - round_off = (uint8_t)(1 * power(2, ((uint8_t) bit_pos_3_9mg_nextbit))); - /* scale according to offset register resolution*/ - data->x = (uint8_t)((delta->x.val + round_off) / power(2, ((uint8_t)bit_pos_3_9mg))); - data->y = (uint8_t)((delta->y.val + round_off) / power(2, ((uint8_t)bit_pos_3_9mg))); - data->z = (uint8_t)((delta->z.val + round_off) / power(2, ((uint8_t)bit_pos_3_9mg))); - } else if (bit_pos_3_9mg < 0) { - bit_pos_3_9mg = (int8_t)(bit_pos_3_9mg * -1); - data->x = (uint8_t)(delta->x.val * power(2, ((uint8_t)bit_pos_3_9mg))); - data->y = (uint8_t)(delta->y.val * power(2, ((uint8_t)bit_pos_3_9mg))); - data->z = (uint8_t)(delta->z.val * power(2, ((uint8_t)bit_pos_3_9mg))); - } else { - /* Scale according to offset register resolution */ - data->x = (uint8_t)(delta->x.val); - data->y = (uint8_t)(delta->y.val); - data->z = (uint8_t)(delta->z.val); - } -} - -/*! - * @brief This API compensate the accel data against gravity. - * - * @note The g-values to be passed to the parameter should be - * multiples of 1000000. - */ -static void comp_for_grvty(uint16_t lsb_per_g, const int32_t g_val[3], const struct bma4_accel *data, - struct offset_delta *comp_data) -{ - int64_t accel_value_lsb[3] = {0}; - uint8_t index; - - for (index = 0; index < 3; index++) { - /* convert g to lsb */ - accel_value_lsb[index] = ((int64_t)(lsb_per_g) * (int64_t)(g_val[index])); - } - - /* Dividing the accel value in LSB by 1000000 to get - compensated data back in g-value */ - comp_data->x.val = (int16_t)(data->x - (int16_t)((accel_value_lsb[BMA4_X_AXIS] / (int64_t)BMA4XY_MULTIPLIER))); - comp_data->y.val = (int16_t)(data->y - (int16_t)((accel_value_lsb[BMA4_Y_AXIS] / (int64_t)BMA4XY_MULTIPLIER))); - comp_data->z.val = (int16_t)(data->z - (int16_t)((accel_value_lsb[BMA4_Z_AXIS] / (int64_t)BMA4XY_MULTIPLIER))); - - if (comp_data->x.val < 0) { - comp_data->x.val = ABS(comp_data->x.val); - comp_data->x.is_negative = 1; - } - - if (comp_data->y.val < 0) { - comp_data->y.val = ABS(comp_data->y.val); - comp_data->y.is_negative = 1; - } - - if (comp_data->z.val < 0) { - comp_data->z.val = ABS(comp_data->z.val); - comp_data->z.is_negative = 1; - } -} - -/*! - * @brief This API converts the range value into corresponding - * integer value. - */ -static void map_range(uint8_t range_in, uint8_t *range_out) -{ - switch (range_in) { - case BMA4_ACCEL_RANGE_2G: - *range_out = 2; - break; - case BMA4_ACCEL_RANGE_4G: - *range_out = 4; - break; - case BMA4_ACCEL_RANGE_8G: - *range_out = 8; - break; - case BMA4_ACCEL_RANGE_16G: - *range_out = 16; - break; - default: - break; - } -} - -/*! - * @brief This API is used to reset the FIFO related configurations - * in the fifo_frame structure. - * - */ -static void reset_fifo_data_structure(const struct bma4_dev *dev) -{ - /*Prepare for next FIFO read by resetting FIFO's - internal data structures*/ - dev->fifo->accel_byte_start_idx = 0; - dev->fifo->mag_byte_start_idx = 0; - dev->fifo->sc_frame_byte_start_idx = 0; - dev->fifo->sensor_time = 0; - dev->fifo->skipped_frame_count = 0; - dev->fifo->accel_dropped_frame_count = 0; - dev->fifo->mag_dropped_frame_count = 0; -} - -/*! - * @brief This API computes the number of bytes of accel FIFO data - * which is to be parsed in header-less mode - */ -static void get_accel_len_to_parse(uint16_t *start_idx, uint16_t *len, const uint16_t *acc_count, - const struct bma4_dev *dev) -{ - uint8_t dummy_byte_spi = 0; - - /*Check if this is the first iteration of data unpacking - if yes, then consider dummy byte on SPI*/ - if (dev->fifo->accel_byte_start_idx == 0) - dummy_byte_spi = dev->dummy_byte; - - /*Data start index*/ - *start_idx = dev->fifo->accel_byte_start_idx + dummy_byte_spi; - - if (dev->fifo->fifo_data_enable == BMA4_FIFO_A_ENABLE) { - /*Len has the number of bytes to loop for */ - *len = (uint16_t)(((*acc_count) * BMA4_FIFO_A_LENGTH) + dummy_byte_spi); - } else if (dev->fifo->fifo_data_enable == BMA4_FIFO_M_A_ENABLE) { - /*Len has the number of bytes to loop for */ - *len = (uint16_t)(((*acc_count) * BMA4_FIFO_MA_LENGTH) + dummy_byte_spi); - } else { - /*Only aux. sensor or no sensor is enabled in FIFO, - so there will be no accel data. - Update the data index as complete*/ - *start_idx = dev->fifo->length; - } - if ((*len) > dev->fifo->length) { - /*Handling the case where more data is requested - than available*/ - *len = dev->fifo->length; - } -} - -/*! - * @brief This API checks the fifo read data as empty frame, if it - * is empty frame then moves the index to last byte. - */ -static void check_empty_fifo(uint16_t *data_index, const struct bma4_dev *dev) -{ - if ((*data_index + 2) < dev->fifo->length) { - /* Check if FIFO is empty */ - if ((dev->fifo->data[*data_index] == FIFO_MSB_CONFIG_CHECK) - && (dev->fifo->data[*data_index + 1] == FIFO_LSB_CONFIG_CHECK)) { - /*Update the data index as complete*/ - *data_index = dev->fifo->length; - } - } -} - -/*! - * @brief This API is used to parse the accelerometer data from the - * FIFO data in header mode. - * - */ -static void extract_accel_header_mode(struct bma4_accel *accel_data, uint16_t *accel_length, const struct bma4_dev *dev) -{ - uint8_t frame_header = 0; - uint16_t data_index; - uint16_t accel_index = 0; - uint16_t frame_to_read = *accel_length; - /*Check if this is the first iteration of data unpacking - if yes, then consider dummy byte on SPI*/ - if (dev->fifo->accel_byte_start_idx == 0) - dev->fifo->accel_byte_start_idx = dev->dummy_byte; - - for (data_index = dev->fifo->accel_byte_start_idx; data_index < dev->fifo->length;) { - /*Header byte is stored in the variable frame_header*/ - frame_header = dev->fifo->data[data_index]; - /*Get the frame details from header*/ - frame_header = frame_header & BMA4_FIFO_TAG_INTR_MASK; - /*Index is moved to next byte where the data is starting*/ - data_index++; - - switch (frame_header) { - /* Accel frame */ - case FIFO_HEAD_A: - case FIFO_HEAD_M_A: - unpack_acc_frm(accel_data, &data_index, &accel_index, frame_header, dev); - break; - /* Aux. sensor frame */ - case FIFO_HEAD_M: - move_next_frame(&data_index, BMA4_FIFO_M_LENGTH, dev); - break; - /* Sensor time frame */ - case FIFO_HEAD_SENSOR_TIME: - unpack_sensortime_frame(&data_index, dev); - break; - /* Skip frame */ - case FIFO_HEAD_SKIP_FRAME: - unpack_skipped_frame(&data_index, dev); - break; - /* Input config frame */ - case FIFO_HEAD_INPUT_CONFIG: - move_next_frame(&data_index, 1, dev); - break; - /* Sample drop frame */ - case FIFO_HEAD_SAMPLE_DROP: - unpack_dropped_frame(&data_index, dev); - break; - /* Over read FIFO data */ - case FIFO_HEAD_OVER_READ_MSB: - /* Update the data index as complete*/ - data_index = dev->fifo->length; - break; - default: - break; - } - if (frame_to_read == accel_index) { - /*Number of frames to read completed*/ - break; - } - } - - /*Update number of accel data read*/ - *accel_length = accel_index; - /*Update the accel frame index*/ - dev->fifo->accel_byte_start_idx = data_index; -} - -/*! - * @brief This API is used to parse the accelerometer data from the - * FIFO data in both header mode and header-less mode. - * It update the idx value which is used to store the index of - * the current data byte which is parsed. - */ -static void unpack_acc_frm(struct bma4_accel *acc, uint16_t *idx, uint16_t *acc_idx, uint8_t frm, - const struct bma4_dev *dev) -{ - switch (frm) { - case FIFO_HEAD_A: - case BMA4_FIFO_A_ENABLE: - /*Partial read, then skip the data*/ - if ((*idx + BMA4_FIFO_A_LENGTH) > dev->fifo->length) { - /*Update the data index as complete*/ - *idx = dev->fifo->length; - break; - } - /*Unpack the data array into the structure instance "acc" */ - unpack_accel_data(&acc[*acc_idx], *idx, dev); - /*Move the data index*/ - *idx = *idx + BMA4_FIFO_A_LENGTH; - (*acc_idx)++; - break; - case FIFO_HEAD_M_A: - case BMA4_FIFO_M_A_ENABLE: - /*Partial read, then skip the data*/ - if ((*idx + BMA4_FIFO_MA_LENGTH) > dev->fifo->length) { - /*Update the data index as complete*/ - *idx = dev->fifo->length; - break; - } - /*Unpack the data array into structure instance "acc"*/ - unpack_accel_data(&acc[*acc_idx], *idx + BMA4_MA_FIFO_A_X_LSB, dev); - /*Move the data index*/ - *idx = *idx + BMA4_FIFO_MA_LENGTH; - (*acc_idx)++; - break; - /* Aux. sensor frame */ - case FIFO_HEAD_M: - case BMA4_FIFO_M_ENABLE: - (*idx) = (*idx) + BMA4_FIFO_M_LENGTH; - break; - default: - break; - } -} - -/*! - * @brief This API is used to parse the accelerometer data from the - * FIFO data and store it in the instance of the structure bma4_accel. - */ -static void unpack_accel_data(struct bma4_accel *accel_data, uint16_t data_start_index, const struct bma4_dev *dev) -{ - uint16_t data_lsb; - uint16_t data_msb; - - /* Accel raw x data */ - data_lsb = dev->fifo->data[data_start_index++]; - data_msb = dev->fifo->data[data_start_index++]; - accel_data->x = (int16_t)((data_msb << 8) | data_lsb); - - /* Accel raw y data */ - data_lsb = dev->fifo->data[data_start_index++]; - data_msb = dev->fifo->data[data_start_index++]; - accel_data->y = (int16_t)((data_msb << 8) | data_lsb); - - /* Accel raw z data */ - data_lsb = dev->fifo->data[data_start_index++]; - data_msb = dev->fifo->data[data_start_index++]; - accel_data->z = (int16_t)((data_msb << 8) | data_lsb); - - if (dev->resolution == BMA4_12_BIT_RESOLUTION) { - accel_data->x = (accel_data->x / 0x10); - accel_data->y = (accel_data->y / 0x10); - accel_data->z = (accel_data->z / 0x10); - } else if (dev->resolution == BMA4_14_BIT_RESOLUTION) { - accel_data->x = (accel_data->x / 0x04); - accel_data->y = (accel_data->y / 0x04); - accel_data->z = (accel_data->z / 0x04); - } -} - -/*! - * @brief This API computes the number of bytes of Mag FIFO data which is - * to be parsed in header-less mode - * - */ -static void get_mag_len_to_parse(uint16_t *start_idx, uint16_t *len, const uint16_t *mag_count, - const struct bma4_dev *dev) -{ - uint8_t dummy_byte_spi = 0; - - /*Check if this is the first iteration of data unpacking - if yes, then consider dummy byte on SPI*/ - if (dev->fifo->mag_byte_start_idx == 0) - dummy_byte_spi = dev->dummy_byte; - - /*Data start index*/ - *start_idx = dev->fifo->mag_byte_start_idx + dummy_byte_spi; - - if (dev->fifo->fifo_data_enable == BMA4_FIFO_M_ENABLE) { - /*Len has the number of bytes to loop for */ - *len = (uint16_t)(((*mag_count) * BMA4_FIFO_M_LENGTH) + dummy_byte_spi); - } else if (dev->fifo->fifo_data_enable == BMA4_FIFO_M_A_ENABLE) { - /*Len has the number of bytes to loop for */ - *len = (uint16_t)(((*mag_count) * BMA4_FIFO_MA_LENGTH) + dummy_byte_spi); - } else { - /*Only accel sensor or no sensor is enabled in FIFO, - so there will be no mag data. - Update the data index as complete*/ - *start_idx = dev->fifo->length; - } - - /*Handling the case where more data is requested than available*/ - if ((*len) > dev->fifo->length) { - /*Len is equal to the FIFO length*/ - *len = dev->fifo->length; - } -} - -/*! - * @brief This API is used to parse the magnetometer data from the - * FIFO data in header mode. - * - */ -static uint16_t extract_mag_header_mode(struct bma4_mag *data, uint16_t *len, const struct bma4_dev *dev) -{ - uint16_t rslt = 0; - uint8_t frame_header = 0; - uint16_t data_index; - uint16_t mag_index = 0; - uint16_t frame_to_read = *len; - - /*Check if this is the first iteration of data unpacking - if yes, then consider dummy byte on SPI*/ - if (dev->fifo->mag_byte_start_idx == 0) - dev->fifo->mag_byte_start_idx = dev->dummy_byte; - - for (data_index = dev->fifo->mag_byte_start_idx; data_index < dev->fifo->length;) { - /*Header byte is stored in the variable frame_header*/ - frame_header = dev->fifo->data[data_index]; - /*Get the frame details from header*/ - frame_header = frame_header & BMA4_FIFO_TAG_INTR_MASK; - /*Index is moved to next byte where the data is starting*/ - data_index++; - - switch (frame_header) { - /* Aux. sensor frame */ - case FIFO_HEAD_M: - case FIFO_HEAD_M_A: - rslt |= unpack_mag_frm(data, &data_index, &mag_index, frame_header, dev); - break; - /* Aux. sensor frame */ - case FIFO_HEAD_A: - move_next_frame(&data_index, BMA4_FIFO_A_LENGTH, dev); - break; - /* Sensor time frame */ - case FIFO_HEAD_SENSOR_TIME: - unpack_sensortime_frame(&data_index, dev); - break; - /* Skip frame */ - case FIFO_HEAD_SKIP_FRAME: - unpack_skipped_frame(&data_index, dev); - break; - /* Input config frame */ - case FIFO_HEAD_INPUT_CONFIG: - move_next_frame(&data_index, 1, dev); - break; - /* Sample drop frame */ - case FIFO_HEAD_SAMPLE_DROP: - unpack_dropped_frame(&data_index, dev); - break; - case FIFO_HEAD_OVER_READ_MSB: - /*Update the data index as complete*/ - data_index = dev->fifo->length; - break; - default: - break; - } - if (frame_to_read == mag_index) { - /*Number of frames to read completed*/ - break; - } - } - /*update number of Aux. sensor data read*/ - *len = mag_index; - /*update the Aux. sensor frame index*/ - dev->fifo->mag_byte_start_idx = data_index; - return rslt; -} - -/*! - * @brief This API is used to parse the magnetometer data from the - * FIFO data in both header mode and header-less mode and update the - * data_index value which is used to store the index of the current - * data byte which is parsed. - * - */ -static uint16_t unpack_mag_frm(struct bma4_mag *data, uint16_t *idx, uint16_t *mag_idx, uint8_t frm, - const struct bma4_dev *dev) -{ - uint16_t rslt = 0; - - switch (frm) { - case FIFO_HEAD_M: - case BMA4_FIFO_M_ENABLE: - /*partial read, then skip the data*/ - if ((*idx + BMA4_FIFO_M_LENGTH) > dev->fifo->length) { - /*update the data index as complete*/ - *idx = dev->fifo->length; - break; - } - - /*unpack the data array into Aux. sensor data structure*/ - rslt |= unpack_mag_data(&data[*mag_idx], *idx, dev); - /*move the data index*/ - *idx = *idx + BMA4_FIFO_M_LENGTH; - (*mag_idx)++; - break; - case FIFO_HEAD_M_A: - case BMA4_FIFO_M_A_ENABLE: - /*partial read, then skip the data*/ - if ((*idx + BMA4_FIFO_MA_LENGTH) > dev->fifo->length) { - /*update the data index as complete*/ - *idx = dev->fifo->length; - break; - } - - /*unpack the data array into Aux. sensor data structure*/ - rslt |= unpack_mag_data(&data[*mag_idx], *idx, dev); - /*move the data index to next frame*/ - *idx = *idx + BMA4_FIFO_MA_LENGTH; - (*mag_idx)++; - break; - /* aux. sensor frame */ - case FIFO_HEAD_A: - case BMA4_FIFO_A_ENABLE: - (*idx) = (*idx) + BMA4_FIFO_A_LENGTH; - break; - default: - break; - } - - return rslt; -} - -/*! - * @brief This API is used to parse the auxiliary magnetometer data from - * the FIFO data and store it in the instance of the structure mag_data. - * - */ -static uint16_t unpack_mag_data(struct bma4_mag *mag_data, uint16_t start_idx, const struct bma4_dev *dev) -{ - uint16_t rslt = 0; - struct bma4_mag_fifo_data mag_fifo_data; - - /* Aux. mag sensor raw x data */ - mag_fifo_data.mag_x_lsb = dev->fifo->data[start_idx++]; - mag_fifo_data.mag_x_msb = dev->fifo->data[start_idx++]; - - /* Aux. mag sensor raw y data */ - mag_fifo_data.mag_y_lsb = dev->fifo->data[start_idx++]; - mag_fifo_data.mag_y_msb = dev->fifo->data[start_idx++]; - - /* Aux. mag sensor raw z data */ - mag_fifo_data.mag_z_lsb = dev->fifo->data[start_idx++]; - mag_fifo_data.mag_z_msb = dev->fifo->data[start_idx++]; - - /* Aux. mag sensor raw r data */ - mag_fifo_data.mag_r_y2_lsb = dev->fifo->data[start_idx++]; - mag_fifo_data.mag_r_y2_msb = dev->fifo->data[start_idx++]; - - /*Compensated FIFO data output*/ - rslt |= bma4_second_if_mag_compensate_xyz(mag_fifo_data, dev->aux_sensor, mag_data); - - return rslt; -} - -/*! - * @brief This API is used to parse and store the sensor time from the - * FIFO data in the structure instance dev. - * - */ -static void unpack_sensortime_frame(uint16_t *data_index, const struct bma4_dev *dev) -{ - uint32_t sensor_time_byte3 = 0; - uint16_t sensor_time_byte2 = 0; - uint8_t sensor_time_byte1 = 0; - - /*Partial read, then move the data index to last data*/ - if ((*data_index + BMA4_SENSOR_TIME_LENGTH) > dev->fifo->length) { - /*Update the data index as complete*/ - *data_index = dev->fifo->length; - } else { - sensor_time_byte3 = dev->fifo->data[(*data_index) + BMA4_SENSOR_TIME_MSB_BYTE] << 16; - sensor_time_byte2 = dev->fifo->data[(*data_index) + BMA4_SENSOR_TIME_XLSB_BYTE] << 8; - sensor_time_byte1 = dev->fifo->data[(*data_index)]; - /* Sensor time */ - dev->fifo->sensor_time = (uint32_t)(sensor_time_byte3 | sensor_time_byte2 | sensor_time_byte1); - *data_index = (*data_index) + BMA4_SENSOR_TIME_LENGTH; - } -} - -/*! - * @brief This API is used to parse and store the skipped_frame_count from - * the FIFO data in the structure instance dev. - */ -static void unpack_skipped_frame(uint16_t *data_index, const struct bma4_dev *dev) -{ - /*Partial read, then move the data index to last data*/ - if (*data_index >= dev->fifo->length) { - /*Update the data index as complete*/ - *data_index = dev->fifo->length; - } else { - dev->fifo->skipped_frame_count = dev->fifo->data[*data_index]; - /*Move the data index*/ - *data_index = (*data_index) + 1; - } -} - -/*! - * @brief This API is used to parse and store the dropped_frame_count from - * the FIFO data in the structure instance dev. - */ -static void unpack_dropped_frame(uint16_t *data_index, const struct bma4_dev *dev) -{ - uint8_t dropped_frame = 0; - /*Partial read, then move the data index to last data*/ - if (*data_index >= dev->fifo->length) { - /*Update the data index as complete*/ - *data_index = dev->fifo->length; - } else { - /*Extract accel and mag dropped frame count*/ - dropped_frame = dev->fifo->data[*data_index] & ACCEL_AUX_FIFO_DROP; - /*Move the data index and update the dropped frame count*/ - switch (dropped_frame) { - case ACCEL_FIFO_DROP: - *data_index = (*data_index) + BMA4_FIFO_A_LENGTH; - dev->fifo->accel_dropped_frame_count = dev->fifo->accel_dropped_frame_count + 1; - break; - case AUX_FIFO_DROP: - *data_index = (*data_index) + BMA4_FIFO_M_LENGTH; - dev->fifo->mag_dropped_frame_count = dev->fifo->mag_dropped_frame_count + 1; - break; - case ACCEL_AUX_FIFO_DROP: - *data_index = (*data_index) + BMA4_FIFO_MA_LENGTH; - dev->fifo->accel_dropped_frame_count = dev->fifo->accel_dropped_frame_count + 1; - dev->fifo->mag_dropped_frame_count = dev->fifo->mag_dropped_frame_count + 1; - break; - default: - break; - } - } -} - -/*! - * @brief This API is used to move the data index ahead of the - * current_frame_length parameter when unnecessary FIFO data appears while - * extracting the user specified data. - */ -static void move_next_frame(uint16_t *data_index, uint8_t current_frame_length, const struct bma4_dev *dev) -{ - /*Partial read, then move the data index to last data*/ - if ((*data_index + current_frame_length) > dev->fifo->length) { - /*Update the data index as complete*/ - *data_index = dev->fifo->length; - } else { - /*Move the data index to next frame*/ - *data_index = *data_index + current_frame_length; - } -} - -/*! - * @brief This function validates the Accel Self test data and decides the - * result of Self test operation. - */ -static uint16_t validate_selftest(const struct selftest_delta_limit *accel_data_diff, - const struct bma4_dev *dev) -{ - uint16_t rslt = 0; - - /* Set self test amplitude based on variant */ - switch (dev->variant) { - case BMA42X_VARIANT: - /* Validating accel data by comparing with minimum value of the axes in mg */ - /* For BMA42x - > x axis limit 400mg, y axis limit 800mg and z axis limit 400mg */ - if ((accel_data_diff->x > BMA42X_ST_ACC_X_AXIS_SIGNAL_DIFF) && - (accel_data_diff->y > BMA42X_ST_ACC_Y_AXIS_SIGNAL_DIFF) && - (accel_data_diff->z > BMA42X_ST_ACC_Z_AXIS_SIGNAL_DIFF)) { - rslt = BMA4_OK; - } else { - rslt = BMA4_E_SELF_TEST_FAIL; - } - break; - - case BMA45X_VARIANT: - /* Validating accel data by comparing with minimum value of the axes in mg */ - /* For BMA45x - > x axis limit 1800mg, y axis limit 1800mg and z axis limit 1800mg */ - if ((accel_data_diff->x > BMA45X_ST_ACC_X_AXIS_SIGNAL_DIFF) && - (accel_data_diff->y > BMA45X_ST_ACC_Y_AXIS_SIGNAL_DIFF) && - (accel_data_diff->z > BMA45X_ST_ACC_Z_AXIS_SIGNAL_DIFF)) { - rslt = BMA4_OK; - } else { - rslt = BMA4_E_SELF_TEST_FAIL; - } - break; - - default: - rslt = BMA4_E_INVALID_SENSOR; - break; - } - - return rslt; -} - -/*! - * @brief This function configure the Accel for FOC. - */ -static uint16_t foc_config(struct bma4_accel_config *acc_conf, uint8_t *acc_en, uint8_t *pwr_mode, struct bma4_dev *dev) -{ - uint16_t rslt = 0; - uint8_t accel_cnf = BMA4_ACCEL_CONFIG_FOC; - - /* for saving Accel configuration, - Accel enable status, advance power save*/ - rslt |= bma4_get_accel_config(acc_conf, dev); - rslt |= bma4_get_accel_enable(acc_en, dev); - rslt |= bma4_get_advance_power_save(pwr_mode, dev); - - /* Disabling offset compensation that is in place*/ - rslt |= bma4_set_offset_comp(BMA4_DISABLE, dev); - - if (rslt == BMA4_OK) { - /* Set Accel config to 50Hz, continuous filter mode, - no under sampling */ - rslt |= bma4_write_regs(BMA4_ACCEL_CONFIG_ADDR, &accel_cnf, 1, dev); - - if (rslt == BMA4_OK) { - /* Switch Accel to normal mode and - advance power save to zero*/ - rslt |= bma4_set_accel_enable(BMA4_ENABLE, dev); - rslt |= bma4_set_advance_power_save(BMA4_DISABLE, dev); - } - } - - return rslt; -} - -/*! - * @brief This API is used to calculate the power of 2 - */ -static int32_t power(int16_t base, uint8_t resolution) -{ - uint8_t i = 1; - /* Initialize variable to store the power of 2 value */ - int32_t value = 1; - - for (; i <= resolution; i++) - value = (int32_t)(value * base); - - return value; -} - -/*! - * @brief This API performs the roundoff on given value - */ -static int8_t roundoff(int32_t value) -{ - /* Variable to return the round off value */ - int8_t ret = 0; - - /* Since the value passed is scaled in multiples of 100, - the return value is divided by 100 to get the round off value */ - if (value < 0) - ret = (int8_t)(((value) - 50) / 100); - else - ret = (int8_t)(((value) + 50) / 100); - - - return ret; -} - -/*! - * @brief This API finds the bit position of 3.9mg according to given range - * and resolution. - */ -static int8_t get_bit_pos_3_9mg(uint8_t range, uint8_t res) -{ - /* Variable to store the bit position of 3.9mg */ - int8_t bit_pos_3_9mg = 0; - /* Variable to store the value to be rounded off */ - int32_t value = 0; - /* Variable to store the LSB per bit in micros */ - int32_t ug_per_bit; - /* Variable to store the rounded off value */ - int8_t round_off_int; - /* Variable to store the bit count */ - uint8_t bit_count = 0; - /* Variable to store the signed range value */ - int32_t range_value; - - /* Scaling range with a multiplier to get integer value of ug_per_bit */ - range_value = (int32_t)(2 * range * BMA4XY_MULTIPLIER); - - /* Get the G-per bit resolution*/ - ug_per_bit = (int32_t)(range_value / power(2, res)); - - /* Compare for -ve & +ve bit position w.r.t 3900micro-g or as reference - * Note: Value scaled in 100s to get accurate integer value */ - if (ug_per_bit > 3900) - value = (int32_t)(ug_per_bit * 100 / 3900); - else - value = (int32_t)(3900 * 100 / ug_per_bit); - - /* Round off the value */ - round_off_int = (int8_t)(roundoff(value)); - - /* Find the bit position of 3.9mg*/ - while (round_off_int != 1) { - round_off_int = (round_off_int / 0x02); - bit_count++; - } - - /* Check for +ve and -ve bit position of 3.9 mg */ - if (ug_per_bit > 3900) - bit_pos_3_9mg = (int8_t)(bit_count * (-1)); - else - bit_pos_3_9mg = (int8_t)bit_count; - - return bit_pos_3_9mg; -} -/*! - * @brief This internal API brings up the secondary interface to access - * auxiliary sensor * - */ -static uint16_t bma4_set_aux_interface_config(struct bma4_dev *dev) -{ - /* Variable to return error codes */ - uint16_t rslt = BMA4_OK; - - /* Check for null pointer error */ - rslt |= bma4_null_pointer_check(dev); - - if (rslt == BMA4_OK) { - /* Enable the auxiliary sensor */ - rslt |= bma4_set_mag_enable(0x01, dev); - dev->delay(BMA4_AUX_COM_DELAY); - - /* Disable advance power save */ - rslt |= bma4_set_advance_power_save(0x00, dev); - dev->delay(BMA4_AUX_COM_DELAY); - - /* Set the I2C device address of auxiliary device */ - rslt |= bma4_set_i2c_device_addr(dev); - dev->delay(BMA4_AUX_COM_DELAY); - - /* Set auxiliary interface to manual mode */ - rslt |= bma4_set_mag_manual_enable(dev->aux_config.manual_enable, dev); - dev->delay(BMA4_AUX_COM_DELAY); - - /* Set the number of bytes for burst read */ - rslt |= bma4_set_mag_burst(dev->aux_config.burst_read_length, dev); - dev->delay(BMA4_AUX_COM_DELAY); - - /* Switch on the the auxiliary interface mode */ - rslt |= bma4_set_if_mode(dev->aux_config.if_mode, dev); - dev->delay(BMA4_AUX_COM_DELAY); - - } - - return rslt; -} - -/*! -* @brief This internal API reads the data from the auxiliary sensor -* depending on burst length configured -*/ -static uint16_t bma4_extract_aux_data(uint8_t aux_reg_addr, uint8_t *aux_data, uint16_t len, struct bma4_dev *dev) -{ - /* Variable to return error codes */ - uint16_t rslt = BMA4_OK; - /* Pointer variable to read data from the register */ - uint8_t data[15] = {0}; - /* Variable to define length counts */ - uint8_t len_count = 0; - /* Variable to define burst read length */ - uint8_t burst_len = 0; - /* Variable to define read length */ - uint8_t read_length = 0; - /* Variable to define the number of burst reads */ - uint8_t burst_count; - /* Variable to define address of the data register*/ - uint8_t aux_read_addr = BMA4_DATA_0_ADDR; - - /* Extract burst read length in a variable */ - rslt |= bma4_map_read_len(&burst_len, dev); - - for (burst_count = 0; burst_count < len; burst_count += burst_len) { - /* Set the address whose data is to be read */ - rslt |= bma4_set_mag_read_addr(aux_reg_addr, dev); - dev->delay(BMA4_AUX_COM_DELAY); - - if (rslt == BMA4_OK) { - /* If user defined length is valid */ - if (len > 0) { - /* Read the data from the data register */ - rslt |= bma4_read_regs(aux_read_addr, data, (uint8_t)burst_len, dev); - dev->delay(BMA4_AUX_COM_DELAY); - - if (rslt == BMA4_OK) { - /* If defined user length or remaining length after a burst - read is less than burst length */ - if ((len - burst_count) < burst_len) { - /* Read length is equal to burst_length or - remaining length*/ - read_length = (uint8_t)(len - burst_count); - } else { - /* Read length is equal to burst_length */ - read_length = burst_len; - } - - /* Copy the read data in terms of given read length */ - for (len_count = 0; len_count < read_length; len_count++) - aux_data[burst_count + len_count] = data[len_count]; - - /* Increment the register address by burst read length */ - aux_reg_addr += burst_len; - } else { - rslt = BMA4_E_RD_WR_LENGTH_INVALID; - } - } else { - rslt = BMA4_E_FAIL; - } - } else { - rslt = BMA4_E_FAIL; - } - } - - return rslt; -} - -/*! - * @brief This internal API maps the actual burst read length with user - length set. - */ -static uint16_t bma4_map_read_len(uint8_t *len, const struct bma4_dev *dev) -{ - /* Variable to return error codes */ - uint16_t rslt = BMA4_OK; - - switch (dev->aux_config.burst_read_length) { - - case BMA4_AUX_READ_LEN_0: - *len = 1; - break; - case BMA4_AUX_READ_LEN_1: - *len = 2; - break; - case BMA4_AUX_READ_LEN_2: - *len = 6; - break; - case BMA4_AUX_READ_LEN_3: - *len = 8; - break; - default: - rslt = BMA4_E_OUT_OF_RANGE; - break; - } - - return rslt; -} - -/*! -* @brief This internal API checks null pointer error -*/ -static uint16_t bma4_null_pointer_check(const struct bma4_dev *dev) -{ - uint16_t rslt = BMA4_OK; - - if ((dev == NULL) || (dev->bus_read == NULL) || (dev->bus_write == NULL)) - rslt |= BMA4_E_NULL_PTR; - else - rslt = BMA4_OK; - - return rslt; -} +/* +**************************************************************************** +* Copyright (C) 2015 - 2016 Bosch Sensortec GmbH +* +* File :bma4.c +* +* Date: 12 Oct 2017 +* +* Revision: 2.1.9 $ +* +* Usage: Sensor Driver for BMA4 family of sensors +* +**************************************************************************** +* Disclaimer +* +* Common: +* Bosch Sensortec products are developed for the consumer goods industry. +* They may only be used within the parameters of the respective valid +* product data sheet. Bosch Sensortec products are provided with the +* express understanding that there is no warranty of fitness for a +* particular purpose.They are not fit for use in life-sustaining, +* safety or security sensitive systems or any system or device +* that may lead to bodily harm or property damage if the system +* or device malfunctions. In addition,Bosch Sensortec products are +* not fit for use in products which interact with motor vehicle systems. +* The resale and or use of products are at the purchasers own risk and +* his own responsibility. The examination of fitness for the intended use +* is the sole responsibility of the Purchaser. +* +* The purchaser shall indemnify Bosch Sensortec from all third party +* claims, including any claims for incidental, or consequential damages, +* arising from any product use not covered by the parameters of +* the respective valid product data sheet or not approved by +* Bosch Sensortec and reimburse Bosch Sensortec for all costs in +* connection with such claims. +* +* The purchaser must monitor the market for the purchased products, +* particularly with regard to product safety and inform Bosch Sensortec +* without delay of all security relevant incidents. +* +* Engineering Samples are marked with an asterisk (*) or (e). +* Samples may vary from the valid technical specifications of the product +* series. They are therefore not intended or fit for resale to third +* parties or for use in end products. Their sole purpose is internal +* client testing. The testing of an engineering sample may in no way +* replace the testing of a product series. Bosch Sensortec assumes +* no liability for the use of engineering samples. +* By accepting the engineering samples, the Purchaser agrees to indemnify +* Bosch Sensortec from all claims arising from the use of engineering +* samples. +* +* Special: +* This software module (hereinafter called "Software") and any information +* on application-sheets (hereinafter called "Information") is provided +* free of charge for the sole purpose to support your application work. +* The Software and Information is subject to the following +* terms and conditions: +* +* The Software is specifically designed for the exclusive use for +* Bosch Sensortec products by personnel who have special experience +* and training. Do not use this Software if you do not have the +* proper experience or training. +* +* This Software package is provided `` as is `` and without any expressed +* or implied warranties,including without limitation, the implied warranties +* of merchantability and fitness for a particular purpose. +* +* Bosch Sensortec and their representatives and agents deny any liability +* for the functional impairment +* of this Software in terms of fitness, performance and safety. +* Bosch Sensortec and their representatives and agents shall not be liable +* for any direct or indirect damages or injury, except as +* otherwise stipulated in mandatory applicable law. +* +* The Information provided is believed to be accurate and reliable. +* Bosch Sensortec assumes no responsibility for the consequences of use +* of such Information nor for any infringement of patents or +* other rights of third parties which may result from its use. +* No license is granted by implication or otherwise under any patent or +* patent rights of Bosch. Specifications mentioned in the Information are +* subject to change without notice. +**************************************************************************/ +/*! \file bma4.c + \brief Sensor Driver for BMA4 family of sensors */ +/***************************************************************************/ +/**\name Header files +****************************************************************************/ +#include "bma4.h" + +/***************************************************************************/ +/**\name Static Data Buffer +****************************************************************************/ +/* Local array to store the values read from the register + * using read_regs API */ +static uint8_t temp_buff[BMA4_MAX_BUFFER_SIZE] = {0}; + +/***************************************************************************/ +/**\name Local structures +****************************************************************************/ +/*! + * @brief Accel difference value of axis. + */ +struct data_with_sign { + /*! Difference value */ + int16_t val; + /*! Indicates negative value if set */ + uint8_t is_negative; +}; + +/*! + * @brief Accel data deviation from ideal value + */ +struct offset_delta { + /*! Accel x axis */ + struct data_with_sign x; + /*! Accel y axis */ + struct data_with_sign y; + /*! Accel z axis */ + struct data_with_sign z; +}; + +/*! + * @brief Accel offset xyz structure + */ +struct accel_offset { + /*! Accel offset X data */ + uint8_t x; + /*! Accel offset Y data */ + uint8_t y; + /*! Accel offset Z data */ + uint8_t z; +}; + +/*! + * @brief Accel self test diff xyz data structure + */ +struct selftest_delta_limit { + /*! Accel X data */ + int32_t x; + /*! Accel Y data */ + int32_t y; + /*! Accel Z data */ + int32_t z; +}; + +/*! + * @brief Structure to store temp data values + */ +struct accel_temp { + /*! Accel X temp data */ + int32_t x; + /*! Accel Y temp data */ + int32_t y; + /*! Accel Z temp data */ + int32_t z; +}; + +/***************************************************************************/ +/*! Static Function Declarations +****************************************************************************/ + +/*! + * @brief This API validates the bandwidth and perfmode + * value set by the user. + * + * param bandwidth[in] : bandwidth value set by the user. + * param perf_mode[in] : perf_mode value set by the user. + */ +static uint16_t validate_bandwidth_perfmode(uint8_t bandwidth, uint8_t perf_mode); + +/*! + * @brief @brief This API validates the ODR value set by the user. + * + * param bandwidth[in] : odr for accelerometer + */ +static uint16_t validate_odr(uint8_t odr); + +/*! + * @brief This API is used to reset the FIFO related configurations + * in the fifo_frame structure. + * + * @param dev[in,out] : Structure instance of bma4_dev + * + */ +static void reset_fifo_data_structure(const struct bma4_dev *dev); + +/*! + * @brief This API computes the number of bytes of accel FIFO data + * which is to be parsed in header-less mode + * + * @param[out] start_idx : The start index for parsing data + * @param[out] len : Number of bytes to be parsed + * @param[in] acc_count : Number of accelerometer frames to be read + * @param[in] dev : Structure instance of bma4_dev. + * + */ +static void get_accel_len_to_parse(uint16_t *start_idx, uint16_t *len, const uint16_t *acc_count, + const struct bma4_dev *dev); + +/*! + * @brief This API checks the fifo read data as empty frame, if it + * is empty frame then moves the index to last byte. + * + * @param[in,out] data_index : The index of the current data to + * be parsed from fifo data + * @param[in] dev : Structure instance of bma4_dev. + */ +static void check_empty_fifo(uint16_t *data_index, const struct bma4_dev *dev); + +/*! + * @brief This API is used to parse the accelerometer data from the + * FIFO data in header mode. + * + * @param[in,out] accel_data : Structure instance of bma4_accel where + * the accelerometer data in FIFO is stored. + * @param[in,out] accel_length : Number of accelerometer frames + * (x,y,z axes data) + * @param[in,out] dev : Structure instance of bma4_dev. + * + */ +static void extract_accel_header_mode(struct bma4_accel *accel_data, uint16_t *accel_length, + const struct bma4_dev *dev); + +/*! + * @brief This API is used to parse the accelerometer data from the + * FIFO data in both header mode and header-less mode. + * It update the idx value which is used to store the index of + * the current data byte which is parsed. + * + * @param[in,out] acc : Structure instance of bma4_accel. + * @param[in,out] idx : Index value of number of bytes parsed + * @param[in,out] acc_idx : Index value of accelerometer data + * (x,y,z axes) frame to be parsed + * @param[in] frm : It consists of either fifo_data_enable + * parameter (Accel and/or mag data enabled in FIFO) + * in header-less mode or frame header data + * in header mode + * @param[in] dev : Structure instance of bma4_dev. + * + */ +static void unpack_acc_frm(struct bma4_accel *acc, uint16_t *idx, uint16_t *acc_idx, uint8_t frm, + const struct bma4_dev *dev); + +/*! + * @brief This API is used to parse the accelerometer data from the + * FIFO data and store it in the instance of the structure bma4_accel. + * + * @param[out] accel_data : Structure instance of bma4_accel where + * the parsed accel data bytes are stored. + * @param[in] data_start_index : Index value of the accel data bytes + * which is to be parsed from the fifo data. + * @param[in] dev : Structure instance of bma4_dev. + * + */ +static void unpack_accel_data(struct bma4_accel *accel_data, uint16_t data_start_index, const struct bma4_dev *dev); +/*! + * @brief This API computes the number of bytes of Mag FIFO data which is + * to be parsed in header-less mode + * + * @param[out] start_idx : The start index for parsing data + * @param[out] len : Number of bytes to be parsed + * @param[in] mag_count : Number of magnetometer frames to be read + * @param[in] dev : Structure instance of bma4_dev. + * + */ +static void get_mag_len_to_parse(uint16_t *start_idx, uint16_t *len, const uint16_t *mag_count, + const struct bma4_dev *dev); +/*! + * @brief This API is used to parse the magnetometer data from the + * FIFO data in header mode. + * + * @param[in,out] data : Structure instance of bma4_mag_xyzr where + * the magnetometer data in FIFO is extracted + * and stored. + * @param[in,out] len : Number of magnetometer frames + * (x,y,z,r data) + * @param[in,out] dev : Structure instance of bma4_dev. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + * + */ +static uint16_t extract_mag_header_mode(struct bma4_mag *data, uint16_t *len, const struct bma4_dev *dev); + +/*! + * @brief This API is used to parse the magnetometer data from the + * FIFO data in both header mode and header-less mode and update the + * idx value which is used to store the index of the current + * data byte which is parsed. + * + * @param data : Structure instance of bma4_mag_xyzr. + * @param idx : Index value of number of bytes parsed + * @param mag_idx : Index value magnetometer data frame (x,y,z,r) + * to be parsed + * @param frm : It consists of either the fifo_data_enable parameter + * (Accel and/or mag data enabled in FIFO) in + * header-less mode and frame header data in header mode + * @param dev : Structure instance of bma4_dev. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + * + */ +static uint16_t unpack_mag_frm(struct bma4_mag *data, uint16_t *idx, uint16_t *mag_idx, uint8_t frm, + const struct bma4_dev *dev); + +/*! + * @brief This API is used to parse the auxiliary magnetometer data from + * the FIFO data and store it in the instance of the structure mag_data. + * + * @param mag_data : Structure instance of bma4_mag_xyzr where the + * parsed magnetometer data bytes are stored. + * @param start_idx : Index value of the magnetometer data bytes + * which is to be parsed from the FIFO data + * @param dev : Structure instance of bma4_dev. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + * + */ +static uint16_t unpack_mag_data(struct bma4_mag *mag_data, uint16_t start_idx, const struct bma4_dev *dev); + +/*! + * @brief This API is used to parse and store the sensor time from the + * FIFO data in the structure instance dev. + * + * @param[in,out] data_index : Index of the FIFO data which + * has the sensor time. + * @param[in,out] dev : Structure instance of bma4_dev. + * + */ +static void unpack_sensortime_frame(uint16_t *data_index, const struct bma4_dev *dev); + +/*! + * @brief This API is used to parse and store the skipped_frame_count from + * the FIFO data in the structure instance dev. + * + * @param[in,out] data_index : Index of the FIFO data which + * has the skipped frame count. + * @param[in,out] dev : Structure instance of bma4_dev. + * + */ +static void unpack_skipped_frame(uint16_t *data_index, const struct bma4_dev *dev); + +/*! + * @brief This API is used to parse and store the dropped_frame_count from + * the FIFO data in the structure instance dev. + * + * @param[in,out] data_index : Index of the FIFO data which + * has the dropped frame data. + * @param[in,out] dev : Structure instance of bma4_dev. + * + */ +static void unpack_dropped_frame(uint16_t *data_index, const struct bma4_dev *dev); + +/*! + * @brief This API is used to move the data index ahead of the + * current_frame_length parameter when unnecessary FIFO data appears while + * extracting the user specified data. + * + * @param[in,out] data_index : Index of the FIFO data which + * is to be moved ahead of the + * current_frame_length + * @param[in] current_frame_length : Number of bytes in a particular frame + * @param[in] dev : Structure instance of bma4_dev. + * + */ +static void move_next_frame(uint16_t *data_index, uint8_t current_frame_length, const struct bma4_dev *dev); + +/*! +* @brief This API writes the config stream data in memory using burst mode +* +* @param[in] stream_data : Pointer to store data of 32 bytes +* @param[in] index : Represents value in multiple of 32 bytes +* @param[in] dev : Structure instance of bma4_dev. +* +* @return Result of API execution status +* @retval 0 -> Success +* @retval Any non zero value -> Fail +*/ +static uint16_t stream_transfer_write(const uint8_t *stream_data, uint16_t index, struct bma4_dev *dev); + +/*! + * @brief This API enables or disables the Accel Self test feature in the + * sensor. + * + * @param[in] accel_selftest_enable : Variable used to enable or disable + * the Accel self test feature + * Value | Description + * --------|--------------- + * 0x00 | BMA4_DISABLE + * 0x01 | BMA4_ENABLE + * + * @param[in] dev : Structure instance of bma4_dev + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + * + */ +static uint16_t set_accel_selftest_enable(uint8_t accel_selftest_axis, struct bma4_dev *dev); + +/*! + * @brief This API selects the sign of Accel self-test excitation + * + * @param[in] accel_selftest_sign: Variable used to select the Accel + * self test sign + * Value | Description + * --------|-------------------------- + * 0x00 | BMA4_DISABLE (negative) + * 0x01 | BMA4_ENABLE (positive) + * + * @param[in] dev : Structure instance of bma4_dev + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + * + */ +static uint16_t set_accel_selftest_sign(uint8_t accel_selftest_sign, struct bma4_dev *dev); + +/*! + * @brief This API sets the Accel self test amplitude in the sensor. + * + * @param[in] accel_selftest_amp : Variable used to specify the Accel self + * test amplitude + * Value | Description + * --------|------------------------------------ + * 0x00 | BMA4_SELFTEST_AMP_LOW + * 0x01 | BMA4_SELFTEST_AMP_HIGH + * + * @param[in] dev : structure instance of bma4_dev + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + * + */ +static uint16_t set_accel_selftest_amp(uint8_t accel_selftest_amp, struct bma4_dev *dev); + +/*! + * @brief This function enables and configures the Accel which is needed + * for Self test operation. + * + * @param[in] dev : Structure instance of bma4_dev + * + * @return results of self test + * @retval 0 -> Success + * @retval Any non zero value -> Fail + * + */ +static uint16_t set_accel_selftest_config(struct bma4_dev *dev); + +/*! + * @brief This API validates the Accel g value provided as input by the + * user for Accel offset compensation. + * + * @param[in] gvalue : Pointer variable used to specify the g value + * set by the user for Accel offset compensation. + * + * @note The g-values to be passed to the parameter should be + * multiples of 1000000. + * + * @return results of the status of user input validation + * @retval 0 -> Success + * @retval Any non zero value -> Fail + * + */ +static uint16_t validate_user_input(const int32_t *gvalue); +/*! + * @brief This API converts the range value into corresponding integer + * value. + * + * @param[in] range_in : input range value. + * @param[out] range_out : pointer to store the integer value of range. + * + * @return results of the status of user input validation + * @retval 0 -> Success + * @retval Any non zero value -> Fail + * + */ +static void map_range(uint8_t range_in, uint8_t *range_out); + +/*! + * @brief This API normalise the data with offset. + * + * @param[out] compensated_data : pointer to store the compensated data. + * @param[in] offset_data : pointer of offset. + * + * @return results of the status of user input validation + * @retval 0 -> Success + * @retval Any non zero value -> Fail + * + */ +static void normalise_offset(const struct offset_delta *compensated_data, struct accel_offset *offset_data); + +/*! + * @brief This API normalise the data with offset. + * + * @param[in] res : resolution of the sensor. + * @param[in] range : G-range of the accel. + * @param[in] delta : pointer of offset_delta. + * @param[out] data : pointer to store accel_offset data. + * + * @return results of the status of user input validation + * @retval 0 -> Success + * @retval Any non zero value -> Fail + * + */ +static void scale_offset(uint8_t res, uint8_t range, const struct offset_delta *delta, struct accel_offset *data); + +/*! + * @brief This API compensate the accel data against gravity. + * + * @param[in] lsb_per_g : lsb value pre 1g. + * @param[in] g_val : G reference value of all axis. + * @param[in] data : pointer of accel_offset data. + * @param[out] comp_data : pointer to store compensated data. + * + * @note The g-values to be passed to the parameter should be + * multiples of 1000000. + * + * @return results of the status of user input validation + * @retval 0 -> Success + * @retval Any non zero value -> Fail + * + */ +static void comp_for_grvty(uint16_t lsb_per_g, const int32_t g_val[3], const struct bma4_accel *data, + struct offset_delta *comp_data); +/*! + * @brief This function validates the Accel Self test data and decides the + * result of Self test operation. + * + * @param[in] accel_data_diff : Pointer to structure variable which holds + * the Accel data difference of Self test operation + * @param[in] dev : Structure instance of bma4_dev + * + * @return results of self test operation + * @retval 0 -> Success + * @retval Any non zero value -> Fail + * + */ +static uint16_t validate_selftest(const struct selftest_delta_limit *accel_data_diff, + const struct bma4_dev *dev); + +/*! + * @brief This function configure the Accel for FOC. + * + * @param[in] acc_conf : accel config structure instance + * @param[in] acc_en : enables the accel + * @param[in] pwr_mode : set the power mode + * @param[in] dev : Structure instance of bma4_dev + * + * @return results of self test operation + * @retval 0 -> Success + * @retval Any non zero value -> Fail + * + */ +static uint16_t foc_config(struct bma4_accel_config *acc_conf, uint8_t *acc_en, uint8_t *pwr_mode, + struct bma4_dev *dev); + +/*! + * @brief This API converts lsb value of axes to mg for self-test + * + * @param[in] accel_data_diff : Pointer variable used to pass accel difference + * values in g + * @param[out] accel_data_diff_mg : Pointer variable used to store accel + * difference values in mg + * @param[out] dev : Structure instance of bma4_dev + * + * @return None * + */ +static void convert_lsb_g(const struct selftest_delta_limit *accel_data_diff, + struct selftest_delta_limit *accel_data_diff_mg, + const struct bma4_dev *dev); + +/*! + * @brief This API sets the feature config. data start address in the sensor. + * + * @param[in] dev : Structure instance of bma4_dev. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + */ +static uint16_t set_feature_config_start_addr(struct bma4_dev *dev); + +/*! + * @brief This API increments the feature config. data address according to the user + * provided read/write length in the dev structure. + * + * @param[in] dev : Structure instance of bma4_dev. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + */ +static uint16_t increment_feature_config_addr(const struct bma4_dev *dev); + +/*! + * @brief This API reads the 8-bit data from the given register + * in the sensor. + */ +static uint16_t read_regs(uint8_t addr, uint8_t *data, uint8_t len, const struct bma4_dev *dev); + +/*! + * @brief This API writes the 8-bit data to the given register + * in the sensor. + */ +static uint16_t write_regs(uint8_t addr, uint8_t *data, uint8_t len, const struct bma4_dev *dev); + +/*! + * @brief This API sets the feature config. data start address in the sensor. + */ +static uint16_t get_feature_config_start_addr(struct bma4_dev *dev); + +/*! + * @brief This API is used to calculate the power of given + * base value. + * + * @param[in] base : value of base + * @param[in] resolution : resolution of the sensor + * + * @return : return the value of base^resolution + */ + +static int32_t power(int16_t base, uint8_t resolution); + +/*! + * @brief This API performs roundoff on given value + * + * @param[in] value : Value which is need to be rounded off + * + * @return : None + */ +static int8_t roundoff(int32_t value); + +/*! + * @brief This API finds the bit position of 3.9mg according to given range + * and resolution. + * + * @param[in] range : range of the accel. + * @param[in] res : resolution of the accel. + * + * @return : bit position of 3.9mg + */ +static int8_t get_bit_pos_3_9mg(uint8_t range, uint8_t res); + +/*! + * @brief This API finds the the null error of the device pointer structure + * + * @param[in] dev : Structure instance of bma4_dev. + * + * @return Null error + */ +static uint16_t bma4_null_pointer_check(const struct bma4_dev *dev); + +/*! + * @brief This internal API brings up the secondary interface to access + * auxiliary sensor + * + * @param[in] dev : Structure instance of bma4_dev. + * + * @return Result of API execution status + * + * @retval 0 if success, else fail + */ +static uint16_t bma4_set_aux_interface_config(struct bma4_dev *dev); + +/*! + * @brief This internal API reads the data from the auxiliary sensor + * depending on burst length configured + * + * @param[in] dev : Structure instance of bma4_dev. + * @param[out] aux_data : Pointer variable to store data read + * @param[in] aux_reg_addr : Variable to pass address from where + * data is to be read + * + * @return Result of API execution status + * + * @retval 0 if success, else fail + */ +static uint16_t bma4_extract_aux_data(uint8_t aux_reg_addr, uint8_t *aux_data, uint16_t len, struct bma4_dev *dev); + +/*! + * @brief This internal API maps the actual burst read length with user length set. + * + * @param[in] dev : Structure instance of bma4_dev. + * @param[out] len : Pointer variable to store mapped length + * + * @return Result of API execution status + * + * @retval 0 if success, else fail + */ +static uint16_t bma4_map_read_len(uint8_t *len, const struct bma4_dev *dev); + +/***************************************************************************/ +/**\name Extern Declarations +****************************************************************************/ + +/***************************************************************************/ +/**\name Globals +****************************************************************************/ + + +/***************************************************************************/ +/**\name Function definitions +****************************************************************************/ +/*! + * @brief This API is the entry point. + * Call this API before using all other APIs. + * This API reads the chip-id of the sensor which is the first step to + * verify the sensor and also it configures the read mechanism of SPI and + * I2C interface. + */ +uint16_t bma4_init(struct bma4_dev *dev) +{ + uint16_t rslt = 0; + uint8_t data = 0; + /* Check the bma4 structure as NULL */ + if ((dev == NULL) || (dev->bus_read == NULL) || (dev->bus_write == NULL)) { + rslt |= BMA4_E_NULL_PTR; + } else { + if (dev->interface == BMA4_SPI_INTERFACE) + dev->dummy_byte = 1; + else + dev->dummy_byte = 0; + + rslt |= bma4_read_regs(BMA4_CHIP_ID_ADDR, &data, 1, dev); + + if (rslt == BMA4_OK) { + /* Assign Chip Id */ + dev->chip_id = data; + } + } + + return rslt; +} + +/*! + * @brief This API is used to write the binary configuration in the sensor + */ +uint16_t bma4_write_config_file(struct bma4_dev *dev) +{ + uint16_t rslt; + /* Config loading disable*/ + uint8_t config_load = 0; + uint16_t index = 0; + uint8_t config_stream_status = 0; + + /* Disable advanced power save */ + rslt = bma4_set_advance_power_save(BMA4_DISABLE, dev); + /* Wait for sensor time synchronization. Refer the data-sheet for + more information*/ + dev->delay(1); + + if (rslt == BMA4_OK) { + /* Disable config loading*/ + rslt |= bma4_write_regs(BMA4_INIT_CTRL_ADDR, &config_load, 1, dev); + /* Write the config stream */ + for (index = 0; index < BMA4_CONFIG_STREAM_SIZE; index += dev->read_write_len) + rslt |= stream_transfer_write((dev->config_file_ptr + index), index, dev); + + /* Enable config loading and FIFO mode */ + config_load = 0x01; + rslt |= bma4_write_regs(BMA4_INIT_CTRL_ADDR, &config_load, 1, dev); + /* Wait till ASIC is initialized. Refer the data-sheet for + more information*/ + dev->delay(150); + /* Read the status of config stream operation */ + rslt |= bma4_read_regs(BMA4_INTERNAL_STAT, &config_stream_status, 1, dev); + + if (config_stream_status != BMA4_ASIC_INITIALIZED) { + rslt |= BMA4_E_CONFIG_STREAM_ERROR; + } else { + /* Enable advanced power save */ + rslt |= bma4_set_advance_power_save(BMA4_ENABLE, dev); + rslt |= get_feature_config_start_addr(dev); + } + } + return rslt; +} + +/*! + * @brief This API checks whether the write operation requested is for feature + * config or register write and accordingly writes the data in the sensor. + */ +uint16_t bma4_write_regs(uint8_t addr, uint8_t *data, uint8_t len, struct bma4_dev *dev) +{ + uint8_t i; + uint8_t loop_count; + uint8_t overflow; + uint8_t index; + uint16_t rslt = BMA4_OK; + uint8_t adv_pwr_save = 0; + + /* Check the dev structure as NULL*/ + if (dev == NULL) { + rslt |= BMA4_E_NULL_PTR; + } else { + if (addr == BMA4_FEATURE_CONFIG_ADDR) { + /* Disable APS if enabled before writing the feature config register */ + rslt = bma4_get_advance_power_save(&adv_pwr_save, dev); + if (adv_pwr_save == BMA4_ENABLE) { + rslt |= bma4_set_advance_power_save(BMA4_DISABLE, dev); + /* Wait for sensor time synchronization. Refer the data-sheet for + more information*/ + dev->delay(1); + } + + if (((len % 2) == 0) && (len <= dev->feature_len) && (rslt == BMA4_OK)) { + if (dev->read_write_len < len) { + /* Calculate the no of writes to be performed according + to the read/write length */ + loop_count = len / dev->read_write_len; + overflow = len % dev->read_write_len; + index = 0; + rslt = set_feature_config_start_addr(dev); + for (i = 0; i < loop_count; i++) { + rslt |= write_regs(BMA4_FEATURE_CONFIG_ADDR, data + index, + dev->read_write_len, dev); + rslt |= increment_feature_config_addr(dev); + index = index + dev->read_write_len; + } + if (overflow) + rslt |= write_regs(BMA4_FEATURE_CONFIG_ADDR, data + index, + overflow, dev); + rslt |= set_feature_config_start_addr(dev); + } else { + rslt = write_regs(BMA4_FEATURE_CONFIG_ADDR, data, len, dev); + } + } else { + rslt = BMA4_E_RD_WR_LENGTH_INVALID; + } + + if (rslt == BMA4_OK) { + /* Enable APS once write feature config register is done */ + rslt = bma4_get_advance_power_save(&adv_pwr_save, dev); + if (adv_pwr_save == BMA4_DISABLE) { + rslt |= bma4_set_advance_power_save(BMA4_ENABLE, dev); + /* Wait for sensor time synchronization. Refer the data-sheet for + more information*/ + dev->delay(1); + } + } + + } else { + rslt = write_regs(addr, data, len, dev); + } + } + + return rslt; +} + +/*! + * @brief This API writes the 8-bit data to the given register + * in the sensor. + */ +static uint16_t write_regs(uint8_t addr, uint8_t *data, uint8_t len, const struct bma4_dev *dev) +{ + uint16_t rslt = 0; + + /* Check the bma4 structure as NULL */ + if (dev == NULL) { + rslt |= BMA4_E_NULL_PTR; + } else { + if (dev->interface == BMA4_SPI_INTERFACE) + addr = addr & BMA4_SPI_WR_MASK; + /* write data in the register*/ + rslt |= dev->bus_write(dev->dev_addr, addr, data, len); + } + return rslt; +} + +/*! + * @brief This API sets the feature config. data start address in the sensor. + */ +static uint16_t get_feature_config_start_addr(struct bma4_dev *dev) +{ + uint16_t rslt; + uint8_t asic_lsb; + uint8_t asic_msb; + + rslt = read_regs(BMA4_RESERVED_REG_5B_ADDR, &asic_lsb, 1, dev); + rslt |= read_regs(BMA4_RESERVED_REG_5C_ADDR, &asic_msb, 1, dev); + + /* Store asic info in dev structure */ + dev->asic_data.asic_lsb = asic_lsb & 0x0F; + dev->asic_data.asic_msb = asic_msb; + + return rslt; +} + +/*! + * @brief This API sets the feature config. data start address in the sensor. + */ +static uint16_t set_feature_config_start_addr(struct bma4_dev *dev) +{ + uint16_t rslt; + + rslt = write_regs(BMA4_RESERVED_REG_5B_ADDR, &dev->asic_data.asic_lsb, 1, dev); + rslt |= write_regs(BMA4_RESERVED_REG_5C_ADDR, &dev->asic_data.asic_msb, 1, dev); + + return rslt; +} + +/*! + * @brief This API increments the feature config. data address according to the user + * provided read/write length in the dev structure. + */ +static uint16_t increment_feature_config_addr(const struct bma4_dev *dev) +{ + uint16_t rslt; + uint16_t asic_addr; + uint8_t asic_lsb; + uint8_t asic_msb; + + /* Read the asic address from the sensor */ + rslt = read_regs(BMA4_RESERVED_REG_5B_ADDR, &asic_lsb, 1, dev); + rslt |= read_regs(BMA4_RESERVED_REG_5C_ADDR, &asic_msb, 1, dev); + /* Get the asic address */ + asic_addr = (asic_msb << 4) | (asic_lsb & 0x0F); + /* Sum the asic address with read/write length after converting from + byte to word */ + asic_addr = asic_addr + (dev->read_write_len / 2); + /* Split the asic address */ + asic_lsb = asic_addr & 0x0F; + asic_msb = (uint8_t)(asic_addr >> 4); + /* Write the asic address in the sensor */ + rslt |= write_regs(BMA4_RESERVED_REG_5B_ADDR, &asic_lsb, 1, dev); + rslt |= write_regs(BMA4_RESERVED_REG_5C_ADDR, &asic_msb, 1, dev); + + return rslt; +} + +/*! + * @brief This API checks whether the read operation requested is for feature + * or register read and accordingly reads the data from the sensor. + */ +uint16_t bma4_read_regs(uint8_t addr, uint8_t *data, uint8_t len, struct bma4_dev *dev) +{ + uint8_t i; + uint8_t loop_count; + uint8_t overflow; + uint8_t index; + uint16_t rslt = BMA4_OK; + uint8_t adv_pwr_save = 0; + + /* Check the dev structure as NULL*/ + if (dev == NULL) { + rslt |= BMA4_E_NULL_PTR; + } else { + if (addr == BMA4_FEATURE_CONFIG_ADDR) { + /* Disable APS if enabled before reading the feature config register */ + rslt = bma4_get_advance_power_save(&adv_pwr_save, dev); + if (adv_pwr_save == BMA4_ENABLE) { + rslt |= bma4_set_advance_power_save(BMA4_DISABLE, dev); + /* Wait for sensor time synchronization. Refer the data-sheet for + more information*/ + dev->delay(1); + } + + if (((len % 2) == 0) && (len <= dev->feature_len) && (rslt == BMA4_OK)) { + if (dev->read_write_len < len) { + /* Calculate the no of writes to be performed according + to the read/write length */ + loop_count = len / dev->read_write_len; + overflow = len % dev->read_write_len; + index = 0; + rslt = set_feature_config_start_addr(dev); + for (i = 0; i < loop_count; i++) { + rslt |= read_regs(BMA4_FEATURE_CONFIG_ADDR, data + index, + dev->read_write_len, dev); + rslt |= increment_feature_config_addr(dev); + index = index + dev->read_write_len; + } + if (overflow) + rslt |= read_regs(BMA4_FEATURE_CONFIG_ADDR, data + index, + overflow, dev); + rslt |= set_feature_config_start_addr(dev); + } else { + rslt = read_regs(BMA4_FEATURE_CONFIG_ADDR, data, len, dev); + } + } else { + rslt = BMA4_E_RD_WR_LENGTH_INVALID; + } + if (rslt == BMA4_OK) { + /* Enable APS once read feature config register is done */ + rslt = bma4_get_advance_power_save(&adv_pwr_save, dev); + if (adv_pwr_save == BMA4_DISABLE) { + rslt |= bma4_set_advance_power_save(BMA4_ENABLE, dev); + /* Wait for sensor time synchronization. Refer the data-sheet for + more information*/ + dev->delay(1); + } + } + } else { + rslt = read_regs(addr, data, len, dev); + } + } + + return rslt; +} + +/*! + * @brief This API reads the 8-bit data from the given register + * in the sensor. + */ +static uint16_t read_regs(uint8_t addr, uint8_t *data, uint8_t len, const struct bma4_dev *dev) +{ + /* variable used to return the status of communication result*/ + uint16_t rslt = 0; + uint16_t temp_len = len + dev->dummy_byte; + uint16_t i; + + if (dev->interface == BMA4_SPI_INTERFACE) { + /* SPI mask added */ + addr = addr | BMA4_SPI_RD_MASK; + } + + if (temp_len > BMA4_MAX_BUFFER_SIZE) { + /* Buffer size is not sufficient */ + rslt |= BMA4_E_OUT_OF_RANGE; + } + + if (rslt == BMA4_OK) { + /* Read the data from the register */ + rslt |= dev->bus_read(dev->dev_addr, addr, temp_buff, temp_len); + + for (i = 0; i < len; i++) { + /* Parsing and storing the valid data */ + data[i] = temp_buff[i + dev->dummy_byte]; + } + } + + return rslt; +} + +/*! + * @brief This API reads the error status from the sensor. + */ +uint16_t bma4_get_error_status(struct bma4_err_reg *err_reg, struct bma4_dev *dev) +{ + uint16_t rslt = 0; + uint8_t data = 0; + + /* Check the bma4 structure as NULL */ + if (dev == NULL) { + rslt |= BMA4_E_NULL_PTR; + } else { + /* Read the error codes*/ + rslt |= bma4_read_regs(BMA4_ERROR_ADDR, &data, 1, dev); + + if (rslt == BMA4_OK) { + /* Fatal error*/ + err_reg->fatal_err = BMA4_GET_BITS_POS_0(data, BMA4_FATAL_ERR); + /* Cmd error*/ + err_reg->cmd_err = BMA4_GET_BITSLICE(data, BMA4_CMD_ERR); + /* User error*/ + err_reg->err_code = BMA4_GET_BITSLICE(data, BMA4_ERR_CODE); + /* FIFO error*/ + err_reg->fifo_err = BMA4_GET_BITSLICE(data, BMA4_FIFO_ERR); + /* Mag data ready error*/ + err_reg->aux_err = BMA4_GET_BITSLICE(data, BMA4_AUX_ERR); + } + } + + return rslt; +} + +/*! + * @brief This API reads the sensor status from the sensor. + */ +uint16_t bma4_get_status(uint8_t *status, struct bma4_dev *dev) +{ + uint16_t rslt = 0; + uint8_t data = 0; + + /* Check the bma4 structure as NULL */ + if (dev == NULL) { + rslt |= BMA4_E_NULL_PTR; + } else { + /* Read the error codes*/ + rslt |= bma4_read_regs(BMA4_STATUS_ADDR, &data, 1, dev); + + if (rslt == BMA4_OK) + *status = data; + } + + return rslt; +} + +/*! + * @brief This API reads the Accel data for x,y and z axis from the sensor. + * The data units is in LSB format. + */ +uint16_t bma4_read_accel_xyz(struct bma4_accel *accel, struct bma4_dev *dev) +{ + uint16_t rslt = 0; + uint16_t lsb = 0; + uint16_t msb = 0; + uint8_t data[BMA4_ACCEL_DATA_LENGTH] = {0}; + + /* Check the bma4 structure as NULL */ + if (dev == NULL) { + rslt |= BMA4_E_NULL_PTR; + } else { + rslt |= bma4_read_regs(BMA4_DATA_8_ADDR, data, BMA4_ACCEL_DATA_LENGTH, dev); + + if (rslt == BMA4_OK) { + msb = data[1]; + lsb = data[0]; + /* Accel data x axis */ + accel->x = (int16_t)((msb << 8) | lsb); + + msb = data[3]; + lsb = data[2]; + /* Accel data y axis */ + accel->y = (int16_t)((msb << 8) | lsb); + + msb = data[5]; + lsb = data[4]; + /* Accel data z axis */ + accel->z = (int16_t)((msb << 8) | lsb); + + if (dev->resolution == BMA4_12_BIT_RESOLUTION) { + accel->x = (accel->x / 0x10); + accel->y = (accel->y / 0x10); + accel->z = (accel->z / 0x10); + } else if (dev->resolution == BMA4_14_BIT_RESOLUTION) { + accel->x = (accel->x / 0x04); + accel->y = (accel->y / 0x04); + accel->z = (accel->z / 0x04); + } + } + } + + return rslt; +} + +/*! + * @brief This API reads the sensor time of Sensor time gets updated + * with every update of data register or FIFO. + */ +uint16_t bma4_get_sensor_time(uint32_t *sensor_time, struct bma4_dev *dev) +{ + uint16_t rslt = 0; + uint8_t data[BMA4_SENSOR_TIME_LENGTH] = {0}; + uint8_t msb = 0; + uint8_t xlsb = 0; + uint8_t lsb = 0; + + /* Check the bma4 structure as NULL */ + if (dev == NULL) { + rslt |= BMA4_E_NULL_PTR; + } else { + rslt |= bma4_read_regs(BMA4_SENSORTIME_0_ADDR, data, BMA4_SENSOR_TIME_LENGTH, dev); + + if (rslt == BMA4_OK) { + msb = data[BMA4_SENSOR_TIME_MSB_BYTE]; + xlsb = data[BMA4_SENSOR_TIME_XLSB_BYTE]; + lsb = data[BMA4_SENSOR_TIME_LSB_BYTE]; + *sensor_time = (uint32_t)((msb << 16) | (xlsb << 8) | lsb); + } + } + + return rslt; +} + +/*! + * @brief This API reads the chip temperature of sensor. + * + * @note Using a scaling factor of 1000, to obtain integer values, which + * at the user end, are used to get accurate temperature value . + * BMA4_FAHREN_SCALED = 1.8 * 1000, BMA4_KELVIN_SCALED = 273.15 * 1000 + */ +uint16_t bma4_get_temperature(int32_t *temp, uint8_t temp_unit, struct bma4_dev *dev) +{ + uint16_t rslt = 0; + uint8_t data[BMA4_TEMP_DATA_SIZE] = {0}; + int32_t temp_raw_scaled = 0; + + /* Check for Null pointer error */ + if (dev == NULL) { + rslt |= BMA4_E_NULL_PTR; + } else { + /* Read temperature value from the register */ + rslt |= bma4_read_regs(BMA4_TEMPERATURE_ADDR, data, BMA4_TEMP_DATA_SIZE, dev); + + if (rslt == BMA4_OK) + temp_raw_scaled = (int32_t)data[BMA4_TEMP_BYTE] * BMA4_SCALE_TEMP; + + /* '0' value read from the register corresponds to 23 degree C */ + (*temp) = temp_raw_scaled + (BMA4_OFFSET_TEMP * BMA4_SCALE_TEMP); + + switch (temp_unit) { + case BMA4_DEG: + break; + + case BMA4_FAHREN: + /* Temperature in degree Fahrenheit */ + (*temp) = (((*temp) / BMA4_SCALE_TEMP) * BMA4_FAHREN_SCALED) + (32 * BMA4_SCALE_TEMP); + break; + + case BMA4_KELVIN: + /* Temperature in degree Kelvin */ + (*temp) = (*temp) + BMA4_KELVIN_SCALED; + break; + + default: + break; + } + } + + return rslt; +} + +/*! + * @brief This API reads the Output data rate, Bandwidth, perf_mode + * and Range of accel. + */ +uint16_t bma4_get_accel_config(struct bma4_accel_config *accel, struct bma4_dev *dev) +{ + uint16_t rslt = 0; + uint8_t data[2] = {0}; + + /* Check the bma4 structure as NULL */ + if (dev == NULL) { + rslt |= BMA4_E_NULL_PTR; + } else { + rslt |= bma4_read_regs(BMA4_ACCEL_CONFIG_ADDR, data, BMA4_ACCEL_CONFIG_LENGTH, dev); + + if (rslt == BMA4_OK) { + /* To get the ODR */ + accel->odr = BMA4_GET_BITS_POS_0(data[0], BMA4_ACCEL_ODR); + /* To get the bandwidth */ + accel->bandwidth = BMA4_GET_BITSLICE(data[0], BMA4_ACCEL_BW); + /* To get the under sampling mode */ + accel->perf_mode = BMA4_GET_BITSLICE(data[0], BMA4_ACCEL_PERFMODE); + /* Read the Accel range */ + accel->range = BMA4_GET_BITS_POS_0(data[1], BMA4_ACCEL_RANGE); + } + } + + return rslt; +} + +/*! + * @brief This API sets the output_data_rate, bandwidth, perf_mode + * and range of Accel. + */ +uint16_t bma4_set_accel_config(const struct bma4_accel_config *accel, struct bma4_dev *dev) +{ + uint16_t rslt = 0; + uint8_t accel_config_data[2] = {0, 0}; + + /* Check the bma4 structure as NULL */ + if (dev == NULL) { + rslt |= BMA4_E_NULL_PTR; + } else { + /* check whether the bandwidth and perfmode + settings are valid */ + rslt = validate_bandwidth_perfmode(accel->bandwidth, accel->perf_mode); + + if (rslt == BMA4_OK) { + /* check ODR is valid */ + rslt |= validate_odr(accel->odr); + + if (rslt == BMA4_OK) { + accel_config_data[0] = accel->odr & BMA4_ACCEL_ODR_MSK; + accel_config_data[0] |= (uint8_t)(accel->bandwidth << BMA4_ACCEL_BW_POS); + accel_config_data[0] |= (uint8_t)(accel->perf_mode << BMA4_ACCEL_PERFMODE_POS); + accel_config_data[1] = accel->range & BMA4_ACCEL_RANGE_MSK; + + /* Burst write is not possible in + suspend mode hence individual write is + used with delay of 1 ms */ + rslt |= bma4_write_regs(BMA4_ACCEL_CONFIG_ADDR, &accel_config_data[0], 1, dev); + dev->delay(BMA4_GEN_READ_WRITE_DELAY); + rslt |= bma4_write_regs((BMA4_ACCEL_CONFIG_ADDR + 1), &accel_config_data[1], + 1, dev); + } + } + } + + return rslt; +} + +/*! + * @brief This API validates the bandwidth and perf_mode + * value set by the user. + */ +static uint16_t validate_bandwidth_perfmode(uint8_t bandwidth, uint8_t perf_mode) +{ + uint16_t rslt = BMA4_OK; + + if (perf_mode == BMA4_CONTINUOUS_MODE) { + if (bandwidth > BMA4_ACCEL_NORMAL_AVG4) { + /* Invalid bandwidth error for continuous mode */ + rslt = BMA4_E_OUT_OF_RANGE; + } + } else if (perf_mode == BMA4_CIC_AVG_MODE) { + if (bandwidth > BMA4_ACCEL_RES_AVG128) { + /* Invalid bandwidth error for CIC avg. mode */ + rslt = BMA4_E_OUT_OF_RANGE; + } + } else { + rslt = BMA4_E_OUT_OF_RANGE; + } + + return rslt; +} + +/*! + * @brief This API validates the ODR value set by the user. + */ +static uint16_t validate_odr(uint8_t odr) +{ + uint16_t rslt = BMA4_OK; + + if ((odr < BMA4_OUTPUT_DATA_RATE_0_78HZ) || (odr > BMA4_OUTPUT_DATA_RATE_1600HZ)) { + /* If odr is not valid return error */ + rslt = BMA4_E_OUT_OF_RANGE; + } + + return rslt; +} + +/*! + * @brief This API sets the advance power save mode in the sensor. + */ +uint16_t bma4_set_advance_power_save(uint8_t adv_pwr_save, struct bma4_dev *dev) +{ + uint16_t rslt = BMA4_OK; + uint8_t data = 0; + + /* Check the bma4 structure as NULL */ + if (dev == NULL) { + rslt |= BMA4_E_NULL_PTR; + } else { + rslt |= bma4_read_regs(BMA4_POWER_CONF_ADDR, &data, 1, dev); + if (rslt == BMA4_OK) { + data = BMA4_SET_BITS_POS_0(data, BMA4_ADVANCE_POWER_SAVE, adv_pwr_save); + rslt |= bma4_write_regs(BMA4_POWER_CONF_ADDR, &data, 1, dev); + } + } + + return rslt; +} + +/*! + * @brief This API reads the status of advance power save mode + * from the sensor. + */ +uint16_t bma4_get_advance_power_save(uint8_t *adv_pwr_save, struct bma4_dev *dev) +{ + uint16_t rslt = BMA4_OK; + uint8_t data = 0; + + /* Check the bma4 structure as NULL */ + if (dev == NULL) { + rslt |= BMA4_E_NULL_PTR; + } else { + rslt |= bma4_read_regs(BMA4_POWER_CONF_ADDR, &data, 1, dev); + + if (rslt == BMA4_OK) + *adv_pwr_save = BMA4_GET_BITS_POS_0(data, BMA4_ADVANCE_POWER_SAVE); + } + + return rslt; +} + +/*! + * @brief This API sets the FIFO self wake up functionality in the sensor. + */ +uint16_t bma4_set_fifo_self_wakeup(uint8_t fifo_self_wakeup, struct bma4_dev *dev) +{ + uint16_t rslt = 0; + uint8_t data = 0; + + /* Check the bma4 structure as NULL */ + if (dev == NULL) { + rslt |= BMA4_E_NULL_PTR; + } else { + rslt |= bma4_read_regs(BMA4_POWER_CONF_ADDR, &data, 1, dev); + + if (rslt == BMA4_OK) { + data = BMA4_SET_BITSLICE(data, BMA4_FIFO_SELF_WAKE_UP, fifo_self_wakeup); + rslt |= bma4_write_regs(BMA4_POWER_CONF_ADDR, &data, 1, dev); + } + } + + return rslt; +} + +/*! + * @brief This API gets the status of FIFO self wake up functionality from + * the sensor. + */ +uint16_t bma4_get_fifo_self_wakeup(uint8_t *fifo_self_wake_up, struct bma4_dev *dev) +{ + uint16_t rslt = 0; + uint8_t data = 0; + + /* Check the bma4 structure as NULL */ + if (dev == NULL) { + rslt |= BMA4_E_NULL_PTR; + } else { + rslt |= bma4_read_regs(BMA4_POWER_CONF_ADDR, &data, 1, dev); + + if (rslt == BMA4_OK) + *fifo_self_wake_up = BMA4_GET_BITSLICE(data, BMA4_FIFO_SELF_WAKE_UP); + } + + return rslt; +} + +/*! + * @brief This API enables or disables the Accel in the sensor. + */ +uint16_t bma4_set_accel_enable(uint8_t accel_en, struct bma4_dev *dev) +{ + uint16_t rslt = 0; + uint8_t data = 0; + + /* Check the bma4 structure as NULL */ + if (dev == NULL) { + rslt |= BMA4_E_NULL_PTR; + } else { + rslt |= bma4_read_regs(BMA4_POWER_CTRL_ADDR, &data, 1, dev); + + if (rslt == BMA4_OK) { + data = BMA4_SET_BITSLICE(data, BMA4_ACCEL_ENABLE, accel_en); + rslt |= bma4_write_regs(BMA4_POWER_CTRL_ADDR, &data, 1, dev); + } + } + + return rslt; +} + +/*! + * @brief This API checks whether Accel is enabled or not in the sensor. + */ +uint16_t bma4_get_accel_enable(uint8_t *accel_en, struct bma4_dev *dev) +{ + uint16_t rslt = 0; + uint8_t data = 0; + + /* Check the bma4 structure as NULL */ + if (dev == NULL) { + rslt |= BMA4_E_NULL_PTR; + } else { + rslt |= bma4_read_regs(BMA4_POWER_CTRL_ADDR, &data, 1, dev); + + if (rslt == BMA4_OK) + *accel_en = BMA4_GET_BITSLICE(data, BMA4_ACCEL_ENABLE); + } + + return rslt; +} + +/*! + * @brief This API is used to enable or disable auxiliary Mag + * in the sensor. + */ +uint16_t bma4_set_mag_enable(uint8_t mag_en, struct bma4_dev *dev) +{ + uint16_t rslt = 0; + uint8_t data = 0; + + /* Check the bma4 structure as NULL */ + if (dev == NULL) { + rslt |= BMA4_E_NULL_PTR; + } else { + rslt |= bma4_read_regs(BMA4_POWER_CTRL_ADDR, &data, 1, dev); + + if (rslt == BMA4_OK) { + data = BMA4_SET_BITS_POS_0(data, BMA4_MAG_ENABLE, mag_en); + rslt |= bma4_write_regs(BMA4_POWER_CTRL_ADDR, &data, 1, dev); + } + } + + return rslt; +} + +/*! + * @brief This API is used to check whether the auxiliary Mag is enabled + * or not in the sensor. + */ +uint16_t bma4_get_mag_enable(uint8_t *mag_en, struct bma4_dev *dev) +{ + uint16_t rslt = 0; + uint8_t data = 0; + + /* Check the bma4 structure as NULL */ + if (dev == NULL) { + rslt |= BMA4_E_NULL_PTR; + } else { + rslt |= bma4_read_regs(BMA4_POWER_CTRL_ADDR, &data, 1, dev); + + if (rslt == BMA4_OK) + *mag_en = BMA4_GET_BITS_POS_0(data, BMA4_MAG_ENABLE); + } + + return rslt; +} + +/*! + * @brief This API reads the SPI interface mode which is set for primary + * interface. + */ +uint16_t bma4_get_spi_interface(uint8_t *spi, struct bma4_dev *dev) +{ + uint16_t rslt = 0; + uint8_t data = 0; + + /* Check the bma4 structure as NULL */ + if (dev == NULL) { + rslt |= BMA4_E_NULL_PTR; + } else { + /* Read SPI mode */ + rslt |= bma4_read_regs(BMA4_IF_CONFIG_ADDR, &data, 1, dev); + + if (rslt == BMA4_OK) + *spi = BMA4_GET_BITS_POS_0(data, BMA4_CONFIG_SPI3); + } + + return rslt; +} + +/*! + * @brief This API configures the SPI interface Mode for primary interface + */ +uint16_t bma4_set_spi_interface(uint8_t spi, struct bma4_dev *dev) +{ + uint16_t rslt = 0; + uint8_t data = 0; + + /* Check the bma4 structure as NULL */ + if (dev == NULL) { + rslt |= BMA4_E_NULL_PTR; + } else { + if (spi <= BMA4_MAX_VALUE_SPI3) { + /* Write SPI mode */ + rslt |= bma4_read_regs(BMA4_IF_CONFIG_ADDR, &data, 1, dev); + + if (rslt == BMA4_OK) { + data = BMA4_SET_BITS_POS_0(data, BMA4_CONFIG_SPI3, spi); + rslt |= bma4_write_regs(BMA4_IF_CONFIG_ADDR, &data, 1, dev); + } + } else { + rslt |= BMA4_E_OUT_OF_RANGE; + } + } + + return rslt; +} + +/*! +* @brief This API writes the available sensor specific commands +* to the sensor. +*/ +uint16_t bma4_set_command_register(uint8_t command_reg, struct bma4_dev *dev) +{ + uint16_t rslt = 0; + + /* Check the bma4 structure as NULL */ + if (dev == NULL) { + rslt |= BMA4_E_NULL_PTR; + } else { + /* Write command register */ + rslt |= bma4_write_regs(BMA4_CMD_ADDR, &command_reg, 1, dev); + } + + return rslt; +} + +/*! + * @brief This API sets the I2C device address of auxiliary sensor + */ +uint16_t bma4_set_i2c_device_addr(struct bma4_dev *dev) +{ + uint16_t rslt = 0; + uint8_t data = 0, dev_id = 0; + + /* Check the bma4 structure as NULL */ + if (dev == NULL) { + rslt |= BMA4_E_NULL_PTR; + } else { + /* Write the auxiliary I2C device address */ + rslt |= bma4_read_regs(BMA4_AUX_DEV_ID_ADDR, &data, 1, dev); + + if (rslt == BMA4_OK) { + dev_id = BMA4_SET_BITSLICE(data, BMA4_I2C_DEVICE_ADDR, dev->aux_config.aux_dev_addr); + rslt |= bma4_write_regs(BMA4_AUX_DEV_ID_ADDR, &dev_id, 1, dev); + } + } + + return rslt; +} + +/*! + * @brief This API sets the register access on MAG_IF[2], MAG_IF[3], + * MAG_IF[4] in the sensor. This implies that the DATA registers are + * not updated with Mag values automatically. + */ +uint16_t bma4_set_mag_manual_enable(uint8_t mag_manual, struct bma4_dev *dev) +{ + uint16_t rslt = 0; + uint8_t data = 0; + /* Check the bma4 structure as NULL */ + if (dev == NULL) { + rslt |= BMA4_E_NULL_PTR; + } else { + /* Write the Mag manual*/ + rslt |= bma4_read_regs(BMA4_AUX_IF_CONF_ADDR, &data, 1, dev); + dev->delay(BMA4_GEN_READ_WRITE_DELAY); + + if (rslt == BMA4_OK) { + /* Set the bit of Mag manual enable */ + data = BMA4_SET_BITSLICE(data, BMA4_MAG_MANUAL_ENABLE, mag_manual); + rslt |= bma4_write_regs(BMA4_AUX_IF_CONF_ADDR, &data, 1, dev); + + if (rslt == BMA4_OK) + dev->aux_config.manual_enable = (uint8_t)mag_manual; + } else { + /*dev->mag_manual_enable = 0;*/ + dev->aux_config.manual_enable = 0; + } + } + + return rslt; +} + +/*! + * @brief This API checks whether the Mag access is done manually or + * automatically in the sensor. + * If the Mag access is done through manual mode then Mag data registers + * in sensor are not updated automatically. + */ +uint16_t bma4_get_mag_manual_enable(uint8_t *mag_manual, struct bma4_dev *dev) +{ + uint16_t rslt = 0; + uint8_t data = 0; + + /* Check the bma4 structure as NULL */ + if (dev == NULL) { + rslt |= BMA4_E_NULL_PTR; + } else { + /* Read Mag manual */ + rslt |= bma4_read_regs(BMA4_AUX_IF_CONF_ADDR, &data, 1, dev); + + if (rslt == BMA4_OK) + *mag_manual = BMA4_GET_BITSLICE(data, BMA4_MAG_MANUAL_ENABLE); + } + + return rslt; +} + +/*! + * @brief This API sets the I2C interface configuration(if) mode + * for auxiliary Mag. + */ +uint16_t bma4_set_aux_if_mode(uint8_t if_mode, struct bma4_dev *dev) +{ + uint16_t rslt = 0; + uint8_t data = 0; + + /* Check the bma4 structure as NULL */ + if (dev == NULL) { + rslt |= BMA4_E_NULL_PTR; + } else { + rslt |= bma4_read_regs(BMA4_IF_CONFIG_ADDR, &data, 1, dev); + + if (rslt == BMA4_OK) { + data = BMA4_SET_BITSLICE(data, BMA4_IF_CONFIG_IF_MODE, if_mode); + rslt |= bma4_write_regs(BMA4_IF_CONFIG_ADDR, &data, 1, dev); + } + } + + return rslt; +} + +/*! + * @brief This API gets the address of the register of Aux Mag sensor + * where the data to be read. + */ +uint16_t bma4_get_mag_read_addr(uint8_t *mag_read_addr, struct bma4_dev *dev) +{ + uint16_t rslt = 0; + uint8_t data = 0; + + /* Check the bma4 structure as NULL */ + if (dev == NULL) { + rslt |= BMA4_E_NULL_PTR; + } else { + rslt |= bma4_read_regs(BMA4_AUX_RD_ADDR, &data, 1, dev); + + if (rslt == BMA4_OK) + *mag_read_addr = BMA4_GET_BITS_POS_0(data, BMA4_READ_ADDR); + } + + return rslt; +} + +/*! + * @brief This API sets the address of the register of Aux Mag sensor + * where the data to be read. + */ +uint16_t bma4_set_mag_read_addr(uint8_t mag_read_addr, struct bma4_dev *dev) +{ + uint16_t rslt = 0; + + /* Check the bma4 structure as NULL */ + if (dev == NULL) { + rslt |= BMA4_E_NULL_PTR; + } else { + /* Write the Mag read address*/ + rslt |= bma4_write_regs(BMA4_AUX_RD_ADDR, &mag_read_addr, 1, dev); + } + + return rslt; +} + +/*! + * @brief This API gets the Aux Mag write address from the sensor. + * Mag write address is where the Mag data will be written. + */ +uint16_t bma4_get_mag_write_addr(uint8_t *mag_write_addr, struct bma4_dev *dev) +{ + uint16_t rslt = 0; + uint8_t data = 0; + + /* Check the bma4 structure as NULL */ + if (dev == NULL) { + rslt |= BMA4_E_NULL_PTR; + } else { + rslt |= bma4_read_regs(BMA4_AUX_WR_ADDR, &data, 1, dev); + + if (rslt == BMA4_OK) + *mag_write_addr = BMA4_GET_BITS_POS_0(data, BMA4_WRITE_ADDR); + } + + return rslt; +} + +/*! + * @brief This API sets the Aux Mag write address in the sensor. + * Mag write address is where the Mag data will be written. + */ +uint16_t bma4_set_mag_write_addr(uint8_t mag_write_addr, struct bma4_dev *dev) +{ + uint16_t rslt = 0; + + /* Check the bma4 structure as NULL */ + if (dev == NULL) + rslt |= BMA4_E_NULL_PTR; + else + rslt |= bma4_write_regs(BMA4_AUX_WR_ADDR, &mag_write_addr, 1, dev); + + return rslt; +} + +/*! + * @brief This API reads the data from the sensor which is written to the + * Mag. + */ +uint16_t bma4_get_mag_write_data(uint8_t *mag_write_data, struct bma4_dev *dev) +{ + uint16_t rslt = 0; + uint8_t data = 0; + + /* Check the bma4 structure as NULL */ + if (dev == NULL) { + rslt |= BMA4_E_NULL_PTR; + } else { + rslt |= bma4_read_regs(BMA4_AUX_WR_DATA_ADDR, &data, 1, dev); + + if (rslt == BMA4_OK) + *mag_write_data = BMA4_GET_BITS_POS_0(data, BMA4_WRITE_DATA); + } + + return rslt; +} + +/*! + * @brief This API sets the data in the sensor which in turn will + * be written to Mag. + */ +uint16_t bma4_set_mag_write_data(uint8_t mag_write_data, struct bma4_dev *dev) +{ + uint16_t rslt = 0; + + /* Check the bma4 structure as NULL */ + if (dev == NULL) + rslt |= BMA4_E_NULL_PTR; + else + rslt |= bma4_write_regs(BMA4_AUX_WR_DATA_ADDR, &mag_write_data, 1, dev); + + return rslt; +} + +/*! + * @brief This API reads the x,y,z and r axis data from the auxiliary + * Mag BMM150/AKM9916 sensor. + */ +uint16_t bma4_read_mag_xyzr(struct bma4_mag_xyzr *mag, struct bma4_dev *dev) +{ + uint16_t rslt = 0; + uint16_t msb = 0; + uint16_t lsb = 0; + uint8_t data[BMA4_MAG_XYZR_DATA_LENGTH] = {0}; + + /* Check the bma4 structure as NULL */ + if (dev == NULL) { + rslt |= BMA4_E_NULL_PTR; + } else { + rslt |= bma4_read_regs(BMA4_DATA_0_ADDR, data, BMA4_MAG_XYZR_DATA_LENGTH, dev); + + if (rslt == BMA4_OK) { + /* Data X */ + /* X-axis LSB value shifting */ + lsb = BMA4_GET_BITSLICE(data[BMA4_MAG_X_LSB_BYTE], BMA4_DATA_MAG_X_LSB); + msb = data[BMA4_MAG_X_MSB_BYTE]; + mag->x = (int16_t)((msb << 8) | lsb); + mag->x = (mag->x / 0x08); + + /* Data Y */ + /* Y-axis LSB value shifting */ + lsb = BMA4_GET_BITSLICE(data[BMA4_MAG_Y_LSB_BYTE], BMA4_DATA_MAG_Y_LSB); + msb = data[BMA4_MAG_Y_MSB_BYTE]; + mag->y = (int16_t)((msb << 8) | lsb); + mag->y = (mag->y / 0x08); + + /* Data Z */ + /* Z-axis LSB value shifting */ + lsb = BMA4_GET_BITSLICE(data[BMA4_MAG_Z_LSB_BYTE], BMA4_DATA_MAG_Z_LSB); + msb = data[BMA4_MAG_Z_MSB_BYTE]; + mag->z = (int16_t)((msb << 8) | lsb); + mag->z = (mag->z / 0x02); + + /* RHall */ + /* R-axis LSB value shifting */ + lsb = BMA4_GET_BITSLICE(data[BMA4_MAG_R_LSB_BYTE], BMA4_DATA_MAG_R_LSB); + msb = data[BMA4_MAG_R_MSB_BYTE]; + mag->r = (int16_t)((msb << 8) | lsb); + mag->r = (mag->r / 0x04); + } + } + + return rslt; +} + +/*! + * @brief This API sets the burst data length (1,2,6,8 byte) of auxiliary + * Mag sensor. + */ +uint16_t bma4_set_mag_burst(uint8_t mag_burst, struct bma4_dev *dev) +{ + uint16_t rslt = 0; + uint8_t data = 0; + + /* Check the bma4 structure as NULL */ + if (dev == NULL) { + rslt |= BMA4_E_NULL_PTR; + } else { + /* Write auxiliary burst mode length*/ + rslt |= bma4_read_regs(BMA4_AUX_IF_CONF_ADDR, &data, 1, dev); + + if (rslt == BMA4_OK) { + data = BMA4_SET_BITS_POS_0(data, BMA4_MAG_BURST, mag_burst); + rslt |= bma4_write_regs(BMA4_AUX_IF_CONF_ADDR, &data, 1, dev); + } + } + + return rslt; +} + +/*! + * @brief This API reads the burst data length of Mag set in the sensor. + */ +uint16_t bma4_get_mag_burst(uint8_t *mag_burst, struct bma4_dev *dev) +{ + uint16_t rslt = 0; + uint8_t data = 0; + + /* Check the bma4 structure as NULL */ + if (dev == NULL) { + rslt |= BMA4_E_NULL_PTR; + } else { + /* Write Mag burst mode length*/ + rslt |= bma4_read_regs(BMA4_AUX_IF_CONF_ADDR, &data, 1, dev); + + if (rslt == BMA4_OK) + *mag_burst = BMA4_GET_BITS_POS_0(data, BMA4_MAG_BURST); + } + + return rslt; +} + +/*! + * @brief This API reads the FIFO data of Accel and/or Mag sensor + */ +uint16_t bma4_read_fifo_data(struct bma4_dev *dev) +{ + uint16_t rslt = 0; + uint8_t data = 0; + uint8_t addr = BMA4_FIFO_DATA_ADDR; + /* check the bma4 structure as NULL*/ + if (dev == NULL || dev->fifo == NULL || dev->fifo->data == NULL) { + rslt |= BMA4_E_NULL_PTR; + } else { + reset_fifo_data_structure(dev); + /* read FIFO data*/ + if (dev->interface == BMA4_SPI_INTERFACE) + addr = addr | BMA4_SPI_RD_MASK; + + rslt |= dev->bus_read(dev->dev_addr, addr, dev->fifo->data, dev->fifo->length); + /* read fifo frame content configuration*/ + rslt |= bma4_read_regs(BMA4_FIFO_CONFIG_1_ADDR, &data, 1, dev); + /* filter fifo header enabled status */ + dev->fifo->fifo_header_enable = data & BMA4_FIFO_HEADER; + /* filter accel/mag data enabled status */ + dev->fifo->fifo_data_enable = data & BMA4_FIFO_M_A_ENABLE; + } + + return rslt; +} + +/*! + * @brief This API parses and extracts the accelerometer frames from + * FIFO data read by the "bma4_read_fifo_data" API and stores it in the + * "accel_data" structure instance. + */ +uint16_t bma4_extract_accel(struct bma4_accel *accel_data, uint16_t *accel_length, const struct bma4_dev *dev) +{ + uint16_t rslt = 0; + uint16_t data_index = 0; + uint16_t accel_index = 0; + uint16_t data_read_length = 0; + + if (dev == NULL || dev->fifo == NULL || dev->fifo->data == NULL) { + rslt |= BMA4_E_NULL_PTR; + } else { + /* Parsing the FIFO data in header-less mode */ + if (dev->fifo->fifo_header_enable == 0) { + get_accel_len_to_parse(&data_index, &data_read_length, accel_length, dev); + + for (; data_index < data_read_length;) { + unpack_acc_frm(accel_data, &data_index, &accel_index, dev->fifo->fifo_data_enable, dev); + /*Check for the availability of next + two bytes of FIFO data */ + check_empty_fifo(&data_index, dev); + } + /* update number of accel data read*/ + *accel_length = accel_index; + /*update the accel byte index*/ + dev->fifo->accel_byte_start_idx = data_index; + } else { + /* Parsing the FIFO data in header mode */ + extract_accel_header_mode(accel_data, accel_length, dev); + } + } + + return rslt; +} + +/*! + * @brief This API parses and extracts the magnetometer frames from + * FIFO data read by the "bma4_read_fifo_data" API and stores it in the + * "mag_data" structure instance parameter of this API + */ +uint16_t bma4_extract_mag(struct bma4_mag *mag_data, uint16_t *mag_length, const struct bma4_dev *dev) +{ + uint16_t rslt = 0; + uint16_t data_index = 0; + uint16_t mag_index = 0; + uint16_t data_read_length = 0; + + if (dev == NULL || dev->fifo == NULL || dev->fifo->data == NULL) { + rslt |= BMA4_E_NULL_PTR; + } else { + /* Parsing the FIFO data in header-less mode */ + if (dev->fifo->fifo_header_enable == 0) { + get_mag_len_to_parse(&data_index, &data_read_length, mag_length, dev); + for (; data_index < data_read_length;) { + rslt |= unpack_mag_frm(mag_data, &data_index, &mag_index, + dev->fifo->fifo_data_enable, dev); + /*Check for the availability of next + two bytes of FIFO data */ + check_empty_fifo(&data_index, dev); + } + /* update number of Aux. sensor data read*/ + *mag_length = mag_index; + /*update the Aux. sensor frame index*/ + dev->fifo->mag_byte_start_idx = data_index; + } else { + /* Parsing the FIFO data in header mode */ + rslt |= extract_mag_header_mode(mag_data, mag_length, dev); + } + } + + return rslt; +} + +/*! + * @brief This API reads the FIFO water mark level which is set + * in the sensor. + */ +uint16_t bma4_get_fifo_wm(uint16_t *fifo_wm, struct bma4_dev *dev) +{ + uint16_t rslt = 0; + uint8_t data[2] = {0, 0}; + + /* Check the bma4 structure as NULL*/ + if (dev == NULL) { + rslt |= BMA4_E_NULL_PTR; + } else { + /* Read the FIFO water mark level*/ + rslt |= bma4_read_regs(BMA4_FIFO_WTM_0_ADDR, data, BMA4_FIFO_WM_LENGTH, dev); + + if (BMA4_OK == rslt) + *fifo_wm = (data[1] << 8) | (data[0]); + } + + return rslt; +} + +/*! + * @brief This API sets the FIFO watermark level in the sensor. + */ +uint16_t bma4_set_fifo_wm(uint16_t fifo_wm, struct bma4_dev *dev) +{ + uint16_t rslt = 0; + uint8_t data[2] = {0, 0}; + + /* Check the bma4 structure as NULL*/ + if (dev == NULL) { + rslt |= BMA4_E_NULL_PTR; + } else { + + data[0] = BMA4_GET_LSB(fifo_wm); + data[1] = BMA4_GET_MSB(fifo_wm); + /* consecutive write is not possible in suspend mode hence + separate write is used with delay of 1 ms*/ + /* Write the fifo watermark level*/ + rslt |= bma4_write_regs(BMA4_FIFO_WTM_0_ADDR, &data[0], 1, dev); + dev->delay(BMA4_GEN_READ_WRITE_DELAY); + rslt |= bma4_write_regs((BMA4_FIFO_WTM_0_ADDR + 1), &data[1], 1, dev); + } + + return rslt; +} + +/*! + * @brief This API checks whether the Accel FIFO data is set for filtered + * or unfiltered mode. + */ +uint16_t bma4_get_accel_fifo_filter_data(uint8_t *accel_fifo_filter, struct bma4_dev *dev) +{ + uint16_t rslt = 0; + uint8_t data = 0; + + /* Check the bma4 structure as NULL */ + if (dev == NULL) { + rslt |= BMA4_E_NULL_PTR; + } else { + /* Read the Accel FIFO filter data */ + rslt |= bma4_read_regs(BMA4_FIFO_DOWN_ADDR, &data, 1, dev); + + if (rslt == BMA4_OK) + *accel_fifo_filter = BMA4_GET_BITSLICE(data, BMA4_FIFO_FILTER_ACCEL); + } + + return rslt; +} + +/*! + * @brief This API sets the condition of Accel FIFO data either to + * filtered or unfiltered mode. + */ +uint16_t bma4_set_accel_fifo_filter_data(uint8_t accel_fifo_filter, struct bma4_dev *dev) +{ + uint16_t rslt = 0; + uint8_t data = 0; + + /* Check the bma4 structure as NULL */ + if (dev == NULL) { + rslt |= BMA4_E_NULL_PTR; + } else { + if (accel_fifo_filter <= BMA4_MAX_VALUE_FIFO_FILTER) { + rslt |= bma4_read_regs(BMA4_FIFO_DOWN_ADDR, &data, 1, dev); + + if (rslt == BMA4_OK) { + /* Write Accel FIFO filter data */ + data = BMA4_SET_BITSLICE(data, BMA4_FIFO_FILTER_ACCEL, accel_fifo_filter); + rslt |= bma4_write_regs(BMA4_FIFO_DOWN_ADDR, &data, 1, dev); + } + } else { + rslt |= BMA4_E_OUT_OF_RANGE; + } + } + return rslt; +} + +/*! + * @brief This API reads the down sampling rates which is configured + * for Accel FIFO data. + */ +uint16_t bma4_get_fifo_down_accel(uint8_t *fifo_down, struct bma4_dev *dev) +{ + uint16_t rslt = 0; + uint8_t data = 0; + + + /* Check the bma4 structure as NULL */ + if (dev == NULL) { + rslt |= BMA4_E_NULL_PTR; + } else { + /* Read the Accel FIFO down data */ + rslt |= bma4_read_regs(BMA4_FIFO_DOWN_ADDR, &data, 1, dev); + + if (rslt == BMA4_OK) + *fifo_down = BMA4_GET_BITSLICE(data, BMA4_FIFO_DOWN_ACCEL); + } + + return rslt; +} + +/*! + * @brief This API sets the down-sampling rates for Accel FIFO. + */ +uint16_t bma4_set_fifo_down_accel(uint8_t fifo_down, struct bma4_dev *dev) +{ + uint16_t rslt = 0; + uint8_t data = 0; + + /* Check the bma4 structure as NULL */ + if (dev == NULL) { + rslt |= BMA4_E_NULL_PTR; + } else { + /* Write the Accel FIFO down data */ + rslt |= bma4_read_regs(BMA4_FIFO_DOWN_ADDR, &data, 1, dev); + + if (rslt == BMA4_OK) { + data = BMA4_SET_BITSLICE(data, BMA4_FIFO_DOWN_ACCEL, fifo_down); + rslt |= bma4_write_regs(BMA4_FIFO_DOWN_ADDR, &data, 1, dev); + } + } + return rslt; +} + +/*! + * @brief This API reads the length of FIFO data available in the sensor + * in the units of bytes. + */ +uint16_t bma4_get_fifo_length(uint16_t *fifo_length, struct bma4_dev *dev) +{ + uint16_t rslt = 0; + uint8_t index = 0; + uint8_t data[BMA4_FIFO_DATA_LENGTH] = {0, 0}; + + /* Check the bma4 structure as NULL */ + if (dev == NULL) { + rslt |= BMA4_E_NULL_PTR; + } else { + /* Read FIFO length*/ + rslt |= bma4_read_regs(BMA4_FIFO_LENGTH_0_ADDR, data, BMA4_FIFO_DATA_LENGTH, dev); + + if (rslt == BMA4_OK) { + index = BMA4_FIFO_LENGTH_MSB_BYTE; + data[index] = BMA4_GET_BITS_POS_0(data[index], BMA4_FIFO_BYTE_COUNTER_MSB); + *fifo_length = ((data[index] << 8) | data[index - 1]); + } + } + + return rslt; +} + +/*! + * @brief This API aligns and compensates the Mag data of BMM150/AKM9916 + * sensor. + */ +uint16_t bma4_second_if_mag_compensate_xyz(struct bma4_mag_fifo_data mag_fifo_data, + uint8_t mag_second_if, struct bma4_mag *compensated_mag_data) +{ + uint16_t rslt = 0; +#ifdef BMM150 + int16_t mag_x = 0; + int16_t mag_y = 0; + int16_t mag_z = 0; + uint16_t mag_r = 0; +#endif + + switch (mag_second_if) { +#ifdef BMM150 + case BMA4_SEC_IF_BMM150: + /* X data*/ + mag_x = (int16_t)((mag_fifo_data.mag_x_msb << 8) | (mag_fifo_data.mag_x_lsb)); + mag_x = (int16_t) (mag_x / 0x08); + + /* Y data*/ + mag_y = (int16_t)((mag_fifo_data.mag_y_msb << 8) | (mag_fifo_data.mag_y_lsb)); + mag_y = (int16_t) (mag_y / 0x08); + + /* Z data*/ + mag_z = (int16_t)((mag_fifo_data.mag_z_msb << 8) | (mag_fifo_data.mag_z_lsb)); + mag_z = (int16_t) (mag_z / 0x02); + + /* R data*/ + mag_r = (uint16_t)((mag_fifo_data.mag_r_y2_msb << 8) | (mag_fifo_data.mag_r_y2_lsb)); + mag_r = (uint16_t) (mag_r >> 2); + + /* Compensated Mag x data */ + compensated_mag_data->x = bma4_bmm150_mag_compensate_X(mag_x, mag_r); + + /* Compensated Mag y data */ + compensated_mag_data->y = bma4_bmm150_mag_compensate_Y(mag_y, mag_r); + + /* Compensated Mag z data */ + compensated_mag_data->z = bma4_bmm150_mag_compensate_Z(mag_z, mag_r); + break; +#endif + +#ifdef AKM9916 + + case BMA4_SEC_IF_AKM09916: + /* Compensated X data */ + compensated_mag_data->x = (int16_t)((mag_fifo_data.mag_x_msb << 8) | (mag_fifo_data.mag_x_lsb)); + /* Compensated Y data*/ + compensated_mag_data->y = (int16_t)((mag_fifo_data.mag_y_msb << 8) | (mag_fifo_data.mag_y_lsb)); + /* Compensated Z data*/ + compensated_mag_data->z = (int16_t)((mag_fifo_data.mag_z_msb << 8) | (mag_fifo_data.mag_z_lsb)); + break; + +#endif + default: + rslt |= BMA4_E_OUT_OF_RANGE; + break; + } + return rslt; +} + +/*! + * @brief This API reads Mag. x,y and z axis data from either BMM150 or + * AKM9916 sensor + */ +uint16_t bma4_read_mag_xyz(struct bma4_mag *mag, uint8_t sensor_select, struct bma4_dev *dev) +{ + uint16_t rslt = 0; + +#if defined(AKM9916) || defined(BMM150) + uint8_t index; + uint16_t msb = 0; + uint16_t lsb = 0; + uint8_t data[BMA4_MAG_XYZ_DATA_LENGTH] = {0}; +#endif + + /* Check the bma4 structure as NULL */ + if (dev == NULL) { + rslt |= BMA4_E_NULL_PTR; + } else { + switch (sensor_select) { + +#if defined(BMM150) + + case BMA4_SEC_IF_BMM150: + rslt |= bma4_read_regs(BMA4_DATA_0_ADDR, data, BMA4_MAG_XYZ_DATA_LENGTH, dev); + + if (rslt == BMA4_OK) { + index = BMA4_MAG_X_LSB_BYTE; + /*X-axis LSB value shifting*/ + data[index] = BMA4_GET_BITSLICE(data[index], BMA4_DATA_MAG_X_LSB); + /* Data X */ + msb = data[index + 1]; + lsb = data[index]; + mag->x = (int16_t)((msb << 8) | lsb); + mag->x = (mag->x / 0x08); + + /* Data Y */ + /*Y-axis LSB value shifting*/ + data[index + 2] = BMA4_GET_BITSLICE(data[index + 2], BMA4_DATA_MAG_Y_LSB); + msb = data[index + 3]; + lsb = data[index + 2]; + mag->y = (int16_t)((msb << 8) | lsb); + mag->y = (mag->y / 0x08); + + /* Data Z */ + /*Z-axis LSB value shifting*/ + data[index + 4] = BMA4_GET_BITSLICE(data[index + 4], BMA4_DATA_MAG_Z_LSB); + msb = data[index + 5]; + lsb = data[index + 4]; + mag->z = (int16_t)((msb << 8) | lsb); + mag->z = (mag->z / 0x02); + } + break; +#endif + +#if defined(AKM9916) + case BMA4_SEC_IF_AKM09916: + + if (AKM9916_SENSOR == dev->aux_sensor) { + rslt |= bma4_read_regs(BMA4_DATA_0_ADDR, data, BMA4_MAG_XYZ_DATA_LENGTH, dev); + + if (rslt == BMA4_OK) { + index = BMA4_MAG_X_LSB_BYTE; + /* Data X */ + msb = data[index + 1]; + lsb = data[index]; + mag->x = (int16_t)((msb << 8) | lsb); + + /* Data Y */ + msb = data[index + 3]; + lsb = data[index + 2]; + mag->y = (int32_t)((msb << 8) | lsb); + + /* Data Z */ + msb = data[index + 5]; + lsb = data[index + 4]; + mag->z = (int16_t)((msb << 8) | lsb); + } + } + break; +#endif + + default: + rslt |= BMA4_E_OUT_OF_RANGE; + break; + } + } + + return rslt; +} + +/*! + * @brief This API reads the auxiliary I2C interface configuration which + * is set in the sensor. + */ +uint16_t bma4_get_if_mode(uint8_t *if_mode, struct bma4_dev *dev) +{ + uint16_t rslt = 0; + uint8_t data = 0; + + /* Check the bma4 structure as NULL */ + if (dev == NULL) { + rslt |= BMA4_E_NULL_PTR; + } else { + /* Read auxiliary interface configuration */ + rslt |= bma4_read_regs(BMA4_IF_CONFIG_ADDR, &data, 1, dev); + + if (rslt == BMA4_OK) + *if_mode = BMA4_GET_BITSLICE(data, BMA4_IF_CONFIG_IF_MODE); + } + + return rslt; +} + +/*! + * @brief This API sets the auxiliary interface configuration in the + * sensor. + */ +uint16_t bma4_set_if_mode(uint8_t if_mode, struct bma4_dev *dev) +{ + uint16_t rslt = 0; + uint8_t data = 0; + + /* Check the bma4 structure as NULL */ + if (dev == NULL) { + rslt |= BMA4_E_NULL_PTR; + } else { + if (if_mode <= BMA4_MAX_IF_MODE) { + /* Write the interface configuration mode */ + rslt |= bma4_read_regs(BMA4_IF_CONFIG_ADDR, &data, 1, dev); + if (rslt == BMA4_OK) { + data = BMA4_SET_BITSLICE(data, BMA4_IF_CONFIG_IF_MODE, if_mode); + rslt |= bma4_write_regs(BMA4_IF_CONFIG_ADDR, &data, 1, dev); + } + } else { + rslt |= BMA4_E_OUT_OF_RANGE; + } + } + + return rslt; +} + +/*! + * @brief This API reads the data ready status of Accel from the sensor. + */ +uint16_t bma4_get_accel_data_rdy(uint8_t *data_rdy, struct bma4_dev *dev) +{ + uint16_t rslt = 0; + uint8_t data = 0; + + /* Check the bma4 structure as NULL */ + if (dev == NULL) { + rslt |= BMA4_E_NULL_PTR; + } else { + /*Reads the status of Accel data ready*/ + rslt |= bma4_read_regs(BMA4_STATUS_ADDR, &data, 1, dev); + + if (rslt == BMA4_OK) + *data_rdy = BMA4_GET_BITSLICE(data, BMA4_STAT_DATA_RDY_ACCEL); + } + + return rslt; +} + +/*! + * @brief This API reads the data ready status of Mag from the sensor. + * The status get reset when Mag data register is read. + */ +uint16_t bma4_get_mag_data_rdy(uint8_t *data_rdy, struct bma4_dev *dev) +{ + uint16_t rslt = 0; + uint8_t data = 0; + + /* Check the bma4 structure as NULL */ + if (dev == NULL) { + rslt |= BMA4_E_NULL_PTR; + } else { + /*Reads the status of Accel data ready*/ + rslt |= bma4_read_regs(BMA4_STATUS_ADDR, &data, 1, dev); + + if (rslt == BMA4_OK) + *data_rdy = BMA4_GET_BITSLICE(data, BMA4_STAT_DATA_RDY_MAG); + } + + return rslt; +} + +/*! + * @brief This API reads the ASIC status from the sensor. + * The status information is mentioned in the below table. + */ +uint16_t bma4_get_asic_status(struct bma4_asic_status *asic_status, struct bma4_dev *dev) +{ + uint16_t rslt = 0; + uint8_t data = 0; + + /* Check the bma4 structure as NULL */ + if (dev == NULL) { + rslt |= BMA4_E_NULL_PTR; + } else { + /* Read the Mag I2C device address*/ + rslt |= bma4_read_regs(BMA4_INTERNAL_ERROR, &data, 1, dev); + + if (rslt == BMA4_OK) { + asic_status->sleep = (data & 0x01); + asic_status->irq_ovrn = ((data & 0x02) >> 0x01); + asic_status->wc_event = ((data & 0x04) >> 0x02); + asic_status->stream_transfer_active = ((data & 0x08) >> 0x03); + } + } + + return rslt; +} + +/*! + * @brief This API enables the offset compensation for filtered and + * unfiltered Accel data. + */ +uint16_t bma4_set_offset_comp(uint8_t offset_en, struct bma4_dev *dev) +{ + uint16_t rslt = 0; + uint8_t data = 0; + + /* Check the bma4 structure as NULL */ + if (dev == NULL) { + rslt |= BMA4_E_NULL_PTR; + } else { + rslt |= bma4_read_regs(BMA4_NV_CONFIG_ADDR, &data, 1, dev); + + if (rslt == BMA4_OK) { + /* Write Accel FIFO filter data */ + data = BMA4_SET_BITSLICE(data, BMA4_NV_ACCEL_OFFSET, offset_en); + rslt |= bma4_write_regs(BMA4_NV_CONFIG_ADDR, &data, 1, dev); + } + } + + return rslt; +} + +/*! + * @brief This API gets the status of Accel offset compensation + */ +uint16_t bma4_get_offset_comp(uint8_t *offset_en, struct bma4_dev *dev) +{ + uint16_t rslt = 0; + uint8_t data = 0; + + /* Check the bma4 structure as NULL */ + if (dev == NULL) { + rslt |= BMA4_E_NULL_PTR; + } else { + rslt |= bma4_read_regs(BMA4_NV_CONFIG_ADDR, &data, 1, dev); + + if (rslt == BMA4_OK) { + /* Write Accel FIFO filter data */ + *offset_en = BMA4_GET_BITSLICE(data, BMA4_NV_ACCEL_OFFSET); + } + } + + return rslt; +} + +/*! + * @brief This API performs Fast Offset Compensation for Accel. + * + * @note The g-values to be passed to the parameter should be + * multiples of 1000000. + */ +uint16_t bma4_perform_accel_foc(const int32_t accel_g_value[3], struct bma4_dev *dev) +{ + uint16_t rslt = 0; + struct bma4_accel accel_value[10] = { {0} }; + struct accel_offset offset = {0}; + struct offset_delta delta = { {0} }; + struct bma4_accel_config acc_conf = {0}; + uint8_t accel_en = 0; + uint8_t adv_pwr_save = 0; + uint8_t range = 0; + uint16_t lsb_per_g = 0; + struct accel_temp temp = {0}; + struct bma4_accel avg = {0}; + struct bma4_accel accel_data = {0}; + uint8_t i = 0; + + /* used to validate user input */ + rslt |= validate_user_input(accel_g_value); + + if (BMA4_OK == rslt) { + /* Configure accel config, accel enable and + advance power save for FOC */ + rslt |= foc_config(&acc_conf, &accel_en, &adv_pwr_save, dev); + + /*TO DO: Check for data ready status before + reading accel values*/ + + if (BMA4_OK == rslt) { + /* Giving a delay of 20ms before reading accel data + since odr is configured as 50Hz */ + for (i = 0; i < 10; i++) { + dev->delay(20); + rslt |= bma4_read_accel_xyz(&accel_value[i], dev); + temp.x = temp.x + (int32_t)accel_value[i].x; + temp.y = temp.y + (int32_t)accel_value[i].y; + temp.z = temp.z + (int32_t)accel_value[i].z; + } + + /* Take average of x, y and z data for lesser noise */ + avg.x = (int16_t)(temp.x / 10); + avg.y = (int16_t)(temp.y / 10); + avg.z = (int16_t)(temp.z / 10); + + /* Copy average value in another structure */ + accel_data = avg; + + if (BMA4_OK == rslt) { + /* Get the exact range value */ + map_range(acc_conf.range, &range); + /* Get LSB per bit given the range and resolution */ + lsb_per_g = (uint16_t)(power(2, dev->resolution) / (2 * range)); + /* Compensate accel data against gravity */ + comp_for_grvty(lsb_per_g, accel_g_value, &accel_data, &delta); + /* scale according to offset register resolution*/ + scale_offset(dev->resolution, range, &delta, &offset); + /* normalise the data with offset*/ + normalise_offset(&delta, &offset); + + /* offset values are written in the offset register */ + rslt |= bma4_write_regs(BMA4_OFFSET_0_ADDR, (uint8_t *)&offset.x, 1, dev); + rslt |= bma4_write_regs(BMA4_OFFSET_1_ADDR, (uint8_t *)&offset.y, 1, dev); + rslt |= bma4_write_regs(BMA4_OFFSET_2_ADDR, (uint8_t *)&offset.z, 1, dev); + + /* Enable offset compensation */ + rslt |= bma4_set_offset_comp(BMA4_ENABLE, dev); + + /* Set accel config, accel enable and advance power save */ + rslt |= bma4_set_accel_config(&acc_conf, dev); + rslt |= bma4_set_accel_enable(accel_en, dev); + rslt |= bma4_set_advance_power_save(adv_pwr_save, dev); + } else { + rslt |= BMA4_E_FOC_FAIL; + } + } + } + return rslt; +} + +/*! + * @brief This API checks whether the self test functionality of the sensor + * is working or not. + * The following parameter of struct bma4_dev, should have the valid value before + * performing the Self test, + * 1. Variant and 2. Resolution + */ +uint16_t bma4_perform_accel_selftest(uint8_t *result, struct bma4_dev *dev) +{ + uint16_t rslt = 0; + struct bma4_accel positive = {0}; + struct bma4_accel negative = {0}; + /*! Structure for difference of accel values in g*/ + struct selftest_delta_limit accel_data_diff = {0}; + /*! Structure for difference of accel values in mg*/ + struct selftest_delta_limit accel_data_diff_mg = {0}; + + *result = BMA4_SELFTEST_FAIL; + + if (dev == NULL) { + rslt |= BMA4_E_NULL_PTR; + } else { + + rslt = set_accel_selftest_config(dev); + dev->delay(20); + rslt |= bma4_selftest_config(BMA4_ENABLE, dev); + + if (rslt == BMA4_OK) { + dev->delay(100); + rslt = bma4_read_accel_xyz(&positive, dev); + rslt |= bma4_selftest_config(BMA4_DISABLE, dev); + + if (rslt == BMA4_OK) { + dev->delay(100); + rslt = bma4_read_accel_xyz(&negative, dev); + + accel_data_diff.x = ABS(positive.x) + ABS(negative.x); + accel_data_diff.y = ABS(positive.y) + ABS(negative.y); + accel_data_diff.z = ABS(positive.z) + ABS(negative.z); + + /*! Converting LSB of the differences of accel values to mg*/ + convert_lsb_g(&accel_data_diff, &accel_data_diff_mg, dev); + /*! Validating self test for accel values in mg*/ + rslt |= validate_selftest(&accel_data_diff_mg, dev); + + if (rslt == BMA4_OK) + *result = BMA4_SELFTEST_PASS; + + /* Triggers a soft reset */ + rslt |= bma4_set_command_register(0xB6, dev); + dev->delay(200); + } + } + } + + return rslt; +} + +/*! + * @brief This API performs the steps needed for Self test operation + * before reading the Accel Self test data. + */ +uint16_t bma4_selftest_config(uint8_t sign, struct bma4_dev *dev) +{ + uint16_t rslt = 0; + + rslt |= set_accel_selftest_enable(BMA4_ENABLE, dev); + rslt |= set_accel_selftest_sign(sign, dev); + + /* Set self test amplitude based on variant */ + switch (dev->variant) { + case BMA42X_VARIANT: + /* Set self test amplitude to high for BMA42x */ + rslt |= set_accel_selftest_amp(BMA4_ENABLE, dev); + break; + + case BMA45X_VARIANT: + /* Set self test amplitude to low for BMA45x */ + rslt |= set_accel_selftest_amp(BMA4_DISABLE, dev); + break; + + default: + rslt = BMA4_E_INVALID_SENSOR; + break; + } + + return rslt; +} + +/*! + * @brief API sets the interrupt to either interrupt1 or + * interrupt2 pin in the sensor. + */ +uint16_t bma4_map_interrupt(uint8_t int_line, uint16_t int_map, uint8_t enable, struct bma4_dev *dev) +{ + uint16_t rslt = 0; + uint8_t data[3] = {0, 0, 0}; + uint8_t index[2] = {BMA4_INT_MAP_1_ADDR, BMA4_INT_MAP_2_ADDR}; + + /* Check the bma4 structure as NULL */ + if (dev == NULL) { + rslt |= BMA4_E_NULL_PTR; + } else { + + rslt |= bma4_read_regs(BMA4_INT_MAP_1_ADDR, data, 3, dev); + + if (enable == TRUE) { + /* Feature interrupt mapping */ + data[int_line] |= (uint8_t)(int_map & (0x00FF)); + /* Hardware interrupt mapping */ + if (int_line == BMA4_INTR2_MAP) + data[2] |= (uint8_t)((int_map & (0xFF00)) >> 4); + else + data[2] |= (uint8_t)((int_map & (0xFF00)) >> 8); + + rslt |= bma4_write_regs(index[int_line], &data[int_line], 1, dev); + rslt |= bma4_write_regs(BMA4_INT_MAP_DATA_ADDR, &data[2], 1, dev); + + } else { + /* Feature interrupt un-mapping */ + data[int_line] &= (~(uint8_t)(int_map & (0x00FF))); + /* Hardware interrupt un-mapping */ + if (int_line == BMA4_INTR2_MAP) + data[2] &= (~(uint8_t)((int_map & (0xFF00)) >> 4)); + else + data[2] &= (~(uint8_t)((int_map & (0xFF00)) >> 8)); + + rslt |= bma4_write_regs(index[int_line], &data[int_line], 1, dev); + rslt |= bma4_write_regs(BMA4_INT_MAP_DATA_ADDR, &data[2], 1, dev); + + } + } + + return rslt; +} + +/*! + * @brief This API sets the interrupt mode in the sensor. + */ +uint16_t bma4_set_interrupt_mode(uint8_t mode, struct bma4_dev *dev) +{ + uint16_t rslt = 0; + + /* Check the bma4 structure as NULL */ + if (dev == NULL) { + rslt |= BMA4_E_NULL_PTR; + } else { + + if (mode == BMA4_NON_LATCH_MODE || mode == BMA4_LATCH_MODE) + rslt |= bma4_write_regs(BMA4_INTR_LATCH_ADDR, &mode, 1, dev); + else + rslt |= BMA4_E_OUT_OF_RANGE; + } + + return rslt; +} + +/*! + * @brief This API gets the interrupt mode which is set in the sensor. + */ +uint16_t bma4_get_interrupt_mode(uint8_t *mode, struct bma4_dev *dev) +{ + uint16_t rslt = 0; + uint8_t data = 0; + + /* Check the bma4 structure as NULL */ + if (dev == NULL) { + rslt |= BMA4_E_NULL_PTR; + } else { + rslt |= bma4_read_regs(BMA4_INTR_LATCH_ADDR, &data, 1, dev); + *mode = data; + } + + return rslt; + +} + +/*! + * @brief This API sets the auxiliary Mag(BMM150 or AKM9916) output data + * rate and offset. + */ +uint16_t bma4_set_aux_mag_config(const struct bma4_aux_mag_config *aux_mag, struct bma4_dev *dev) +{ + uint16_t rslt = 0; + uint8_t data = 0; + + /* Check the bma4 structure as NULL */ + if (dev == NULL) { + rslt |= BMA4_E_NULL_PTR; + } else { + if ((aux_mag->odr >= BMA4_OUTPUT_DATA_RATE_0_78HZ) && + (aux_mag->odr <= BMA4_OUTPUT_DATA_RATE_1600HZ) + && ((aux_mag->offset & BMA4_MAG_CONFIG_OFFSET_MSK) == 0x00)) { + data = (uint8_t)(aux_mag->odr | + ((aux_mag->offset << + BMA4_MAG_CONFIG_OFFSET_POS))); + rslt |= bma4_write_regs(BMA4_AUX_CONFIG_ADDR, &data, 1, dev); + } else { + rslt |= BMA4_E_OUT_OF_RANGE; + } + } + + return rslt; +} + +/*! + * @brief This API reads the auxiliary Mag(BMM150 or AKM9916) output data + * rate and offset. + */ +uint16_t bma4_get_aux_mag_config(struct bma4_aux_mag_config *aux_mag, struct bma4_dev *dev) +{ + uint16_t rslt = 0; + uint8_t data = 0; + + /* Check the bma4 structure as NULL */ + if (dev == NULL) { + rslt |= BMA4_E_NULL_PTR; + } else { + rslt |= bma4_read_regs(BMA4_AUX_CONFIG_ADDR, &data, 1, dev); + + if (rslt == BMA4_OK) { + aux_mag->odr = (data & 0x0F); + aux_mag->offset = (data & BMA4_MAG_CONFIG_OFFSET_MSK) >> 4; + } + } + + return rslt; +} + +/*! @brief This API sets the FIFO configuration in the sensor. + */ +uint16_t bma4_set_fifo_config(uint8_t config, uint8_t enable, struct bma4_dev *dev) +{ + uint16_t rslt = 0; + uint8_t data[2] = {0, 0}; + uint8_t fifo_config_0 = config & BMA4_FIFO_CONFIG_0_MASK; + + /* Check the bma4 structure as NULL */ + if (dev == NULL) { + rslt |= BMA4_E_NULL_PTR; + } else { + rslt |= bma4_read_regs(BMA4_FIFO_CONFIG_0_ADDR, data, BMA4_FIFO_CONFIG_LENGTH, dev); + + if (rslt == BMA4_OK) { + + if (fifo_config_0 > 0) { + + if (enable == TRUE) + data[0] = data[0] | fifo_config_0; + else + data[0] = data[0] & (~fifo_config_0); + } + + if (enable == TRUE) + data[1] = data[1] | (config & BMA4_FIFO_CONFIG_1_MASK); + else + data[1] = data[1] & (~(config & BMA4_FIFO_CONFIG_1_MASK)); + + /* Burst write is not possible in suspend mode hence + separate write is used with delay of 1 ms*/ + rslt |= bma4_write_regs(BMA4_FIFO_CONFIG_0_ADDR, &data[0], 1, dev); + dev->delay(BMA4_GEN_READ_WRITE_DELAY); + rslt |= bma4_write_regs((BMA4_FIFO_CONFIG_0_ADDR + 1), &data[1], 1, dev); + } + } + + return rslt; +} + +/*! @brief This API reads the FIFO configuration from the sensor. + */ +uint16_t bma4_get_fifo_config(uint8_t *fifo_config, struct bma4_dev *dev) +{ + uint16_t rslt = 0; + uint8_t data[2] = {0, 0}; + + /* Check the bma4 structure as NULL */ + if (dev == NULL) { + rslt |= BMA4_E_NULL_PTR; + } else { + rslt |= bma4_read_regs(BMA4_FIFO_CONFIG_0_ADDR, data, BMA4_FIFO_CONFIG_LENGTH, dev); + + if (rslt == BMA4_OK) + *fifo_config = ((uint8_t)((data[0] & BMA4_FIFO_CONFIG_0_MASK) | (data[1]))); + + } + + return rslt; +} + +/*! @brief This function sets the electrical behaviour of interrupt pin1 or + * pin2 in the sensor. + */ +uint16_t bma4_set_int_pin_config(const struct bma4_int_pin_config *int_pin_config, uint8_t int_line, + struct bma4_dev *dev) +{ + uint16_t rslt = 0; + uint8_t interrupt_address_array[2] = {BMA4_INT1_IO_CTRL_ADDR, BMA4_INT2_IO_CTRL_ADDR}; + uint8_t data = 0; + + /* Check the bma4 structure as NULL */ + if (dev == NULL) { + rslt |= BMA4_E_NULL_PTR; + } else { + if (int_line <= 1) { + data = ((uint8_t)((int_pin_config->edge_ctrl & BMA4_INT_EDGE_CTRL_MASK) | + ((int_pin_config->lvl << 1) & BMA4_INT_LEVEL_MASK) | + ((int_pin_config->od << 2) & BMA4_INT_OPEN_DRAIN_MASK) | + ((int_pin_config->output_en << 3) & BMA4_INT_OUTPUT_EN_MASK) | + ((int_pin_config->input_en << 4) & BMA4_INT_INPUT_EN_MASK))); + + rslt |= bma4_write_regs(interrupt_address_array[int_line], &data, 1, dev); + } else { + rslt |= BMA4_E_INT_LINE_INVALID; + } + } + + return rslt; +} + +/*! @brief This API reads the electrical behavior of interrupt pin1 or pin2 + * from the sensor. + */ +uint16_t bma4_get_int_pin_config(struct bma4_int_pin_config *int_pin_config, uint8_t int_line, struct bma4_dev *dev) +{ + uint16_t rslt = 0; + uint8_t interrupt_address_array[2] = {BMA4_INT1_IO_CTRL_ADDR, BMA4_INT2_IO_CTRL_ADDR}; + uint8_t data = 0; + + if (dev == NULL) { + rslt |= BMA4_E_NULL_PTR; + } else { + if (int_line <= 1) { + rslt |= bma4_read_regs(interrupt_address_array[int_line], &data, 1, dev); + /* Assign interrupt configurations to the + structure members*/ + if (rslt == BMA4_OK) { + int_pin_config->edge_ctrl = data & BMA4_INT_EDGE_CTRL_MASK; + int_pin_config->lvl = ((data & BMA4_INT_LEVEL_MASK) >> BMA4_INT_LEVEL_POS); + int_pin_config->od = ((data & BMA4_INT_OPEN_DRAIN_MASK) >> BMA4_INT_OPEN_DRAIN_POS); + int_pin_config->output_en = ((data & BMA4_INT_OUTPUT_EN_MASK) + >> BMA4_INT_OUTPUT_EN_POS); + int_pin_config->input_en = ((data & BMA4_INT_INPUT_EN_MASK) >> BMA4_INT_INPUT_EN_POS); + } + } else { + rslt |= BMA4_E_INT_LINE_INVALID; + } + } + + return rslt; +} + +/*! + * @brief This API reads the Feature and Hardware interrupt status from the sensor. + */ +uint16_t bma4_read_int_status(uint16_t *int_status, struct bma4_dev *dev) +{ + uint16_t rslt = 0; + uint8_t data[2] = {0}; + + /* Check the bma4 structure as NULL */ + if (dev == NULL) { + rslt |= BMA4_E_NULL_PTR; + } else { + rslt |= bma4_read_regs(BMA4_INT_STAT_0_ADDR, data, 2, dev); + + if (rslt == BMA4_OK) { + *int_status = data[0]; + *((uint8_t *)int_status + 1) = data[1]; + } + } + + return rslt; +} + +/*! + * @brief This API reads the Feature interrupt status from the sensor. + */ +uint16_t bma4_read_int_status_0(uint8_t *int_status_0, struct bma4_dev *dev) +{ + uint16_t rslt = BMA4_OK; + + /* Check the bma4 structure as NULL */ + if (dev == NULL) { + /* Null pointer check */ + rslt = BMA4_E_NULL_PTR; + } else { + rslt = bma4_read_regs(BMA4_INT_STAT_0_ADDR, int_status_0, 1, dev); + } + + return rslt; +} + +/*! + * @brief This API reads the Hardware interrupt status from the sensor. + */ +uint16_t bma4_read_int_status_1(uint8_t *int_status_1, struct bma4_dev *dev) +{ + uint16_t rslt = BMA4_OK; + + /* Check the bma4 structure as NULL */ + if (dev == NULL) { + /* Null pointer check */ + rslt = BMA4_E_NULL_PTR; + } else { + rslt = bma4_read_regs(BMA4_INT_STAT_1_ADDR, int_status_1, 1, dev); + } + + return rslt; +} + +/*! + * @brief This API initializes the auxiliary interface to access + * auxiliary sensor + */ +uint16_t bma4_aux_interface_init(struct bma4_dev *dev) +{ + /* Variable to return error codes */ + uint16_t rslt = BMA4_OK; + + /* Check for Null pointer error */ + rslt |= bma4_null_pointer_check(dev); + if (rslt == BMA4_OK) { + /* Set the auxiliary sensor configuration */ + rslt = bma4_set_aux_interface_config(dev); + if (rslt != BMA4_OK) + rslt = BMA4_E_AUX_CONFIG_FAIL; + } + + return rslt; +} + +/*! + * @brief This API reads the data from the auxiliary sensor +*/ +uint16_t bma4_aux_read(uint8_t aux_reg_addr, uint8_t *aux_data, uint16_t len, struct bma4_dev *dev) +{ + /* Variable to return error codes */ + uint16_t rslt = BMA4_OK; + + /* Check for Null pointer error */ + rslt |= bma4_null_pointer_check(dev); + if (rslt == BMA4_OK) { + /* Read the data from the data register in terms of + user defined length */ + rslt = bma4_extract_aux_data(aux_reg_addr, aux_data, len, dev); + } + + return rslt; +} + +/*! + * @brief This API writes the data into the auxiliary sensor +*/ +uint16_t bma4_aux_write(uint8_t aux_reg_addr, uint8_t *aux_data, uint16_t len, struct bma4_dev *dev) +{ + + uint16_t rslt = BMA4_OK; + + /* Check for Null pointer error */ + rslt |= bma4_null_pointer_check(dev); + if (rslt == BMA4_OK) { + /* Write data in terms of user defined length */ + if (len > 0) { + while (len--) { + /* First set data to write */ + rslt = bma4_write_regs(BMA4_AUX_WR_DATA_ADDR, aux_data, 1, dev); + dev->delay(BMA4_AUX_COM_DELAY); + if (rslt == BMA4_OK) { + /* Then set address to write */ + rslt = bma4_write_regs(BMA4_AUX_WR_ADDR, &aux_reg_addr, 1, dev); + dev->delay(BMA4_AUX_COM_DELAY); + + /* Increment data array and register address until + * user-defined length is greater than 0 */ + if ((rslt == BMA4_OK) && (len > 0)) { + aux_data++; + aux_reg_addr++; + } + } else { + rslt = BMA4_E_FAIL; + } + } + } else { + rslt = BMA4_E_RD_WR_LENGTH_INVALID; + } + } + + return rslt; +} + +/*****************************************************************************/ +/* Static function definition */ +/*! + * @brief This API converts lsb value of axes to mg for self-test * + */ +static void convert_lsb_g(const struct selftest_delta_limit *accel_data_diff, + struct selftest_delta_limit *accel_data_diff_mg, + const struct bma4_dev *dev) +{ + uint32_t lsb_per_g; + /*! Range considered for self-test is 8g */ + uint8_t range = 8; + + /*! lsb_per_g for the respective resolution and 8g range*/ + lsb_per_g = (uint32_t)(power(2, dev->resolution) / (2 * range)); + /*! accel x value in mg */ + accel_data_diff_mg->x = (accel_data_diff->x / (int32_t)lsb_per_g) * 1000; + /*! accel y value in mg */ + accel_data_diff_mg->y = (accel_data_diff->y / (int32_t)lsb_per_g) * 1000; + /*! accel z value in mg */ + accel_data_diff_mg->z = (accel_data_diff->z / (int32_t)lsb_per_g) * 1000; +} + +/*! + * @brief This API writes the config stream data in memory using burst mode + * @note index value should be even number. + */ +static uint16_t stream_transfer_write(const uint8_t *stream_data, uint16_t index, struct bma4_dev *dev) +{ + uint16_t rslt = 0; + uint8_t asic_msb = (uint8_t)((index / 2) >> 4); + uint8_t asic_lsb = ((index / 2) & 0x0F); + + rslt |= bma4_write_regs(BMA4_RESERVED_REG_5B_ADDR, &asic_lsb, 1, dev); + + if (rslt == BMA4_OK) { + rslt |= bma4_write_regs(BMA4_RESERVED_REG_5C_ADDR, &asic_msb, 1, dev); + + if (rslt == BMA4_OK) + rslt |= write_regs(BMA4_FEATURE_CONFIG_ADDR, (uint8_t *)stream_data, dev->read_write_len, dev); + } + + return rslt; +} + +/*! + * @brief This API enables or disables the Accel Self test feature in the + * sensor. + */ +static uint16_t set_accel_selftest_enable(uint8_t accel_selftest_enable, struct bma4_dev *dev) +{ + uint16_t rslt = 0; + uint8_t data = 0; + /* Check the bma4 structure as NULL */ + if (dev == NULL) { + rslt |= BMA4_E_NULL_PTR; + } else { + /* Read the self test register */ + rslt |= bma4_read_regs(BMA4_ACC_SELF_TEST_ADDR, &data, 1, dev); + + if (rslt == BMA4_OK) { + data = BMA4_SET_BITS_POS_0(data, BMA4_ACCEL_SELFTEST_ENABLE, accel_selftest_enable); + rslt |= bma4_write_regs(BMA4_ACC_SELF_TEST_ADDR, &data, 1, dev); + } + } + + return rslt; +} + +/*! + * @brief This API selects the sign of Accel self-test excitation. + */ +static uint16_t set_accel_selftest_sign(uint8_t accel_selftest_sign, struct bma4_dev *dev) +{ + uint16_t rslt = 0; + uint8_t data = 0; + /* Check the bma4 structure as NULL */ + if (dev == NULL) { + rslt |= BMA4_E_NULL_PTR; + } else { + + if (accel_selftest_sign <= BMA4_MAX_VALUE_SELFTEST_SIGN) { + /* Read the Accel self test sign*/ + rslt |= bma4_read_regs(BMA4_ACC_SELF_TEST_ADDR, &data, 1, dev); + + if (rslt == BMA4_OK) { + data = BMA4_SET_BITSLICE(data, BMA4_ACCEL_SELFTEST_SIGN, accel_selftest_sign); + rslt |= bma4_write_regs(BMA4_ACC_SELF_TEST_ADDR, &data, 1, dev); + } + } else { + rslt = BMA4_E_OUT_OF_RANGE; + } + } + + return rslt; +} + +/*! + * @brief This API sets the Accel self test amplitude in the sensor. + */ +static uint16_t set_accel_selftest_amp(uint8_t accel_selftest_amp, struct bma4_dev *dev) +{ + uint16_t rslt = 0; + uint8_t data = 0; + /* Check the bma4 structure as NULL */ + if (dev == NULL) { + rslt |= BMA4_E_NULL_PTR; + } else { + + if (accel_selftest_amp <= BMA4_MAX_VALUE_SELFTEST_AMP) { + /* Write self test amplitude*/ + rslt |= bma4_read_regs(BMA4_ACC_SELF_TEST_ADDR, &data, 1, dev); + + if (rslt == BMA4_OK) { + data = BMA4_SET_BITSLICE(data, BMA4_SELFTEST_AMP, accel_selftest_amp); + + rslt |= bma4_write_regs(BMA4_ACC_SELF_TEST_ADDR, &data, 1, dev); + } + } else { + rslt |= BMA4_E_OUT_OF_RANGE; + } + } + + return rslt; +} + +/*! + * @brief This function enables and configures the Accel which is needed + * for Self test operation. + */ +static uint16_t set_accel_selftest_config(struct bma4_dev *dev) +{ + uint16_t rslt = 0; + struct bma4_accel_config accel = {0}; + + accel.odr = BMA4_OUTPUT_DATA_RATE_1600HZ; + accel.bandwidth = BMA4_ACCEL_NORMAL_AVG4; + accel.perf_mode = BMA4_ENABLE; + accel.range = BMA4_ACCEL_RANGE_8G; + + rslt |= bma4_set_accel_enable(BMA4_ENABLE, dev); + dev->delay(1); + rslt |= bma4_set_accel_config(&accel, dev); + + return rslt; +} + +/*! + * @brief This API validates the Accel g value provided as input by the + * user for Accel offset compensation. + * + * @note The g-values to be passed to the parameter should be + * multiples of 1000000. + */ +static uint16_t validate_user_input(const int32_t *gvalue) + +{ + uint8_t index = 0; + int32_t min_gval = (int32_t)(-1.0 * BMA4XY_MULTIPLIER); + int32_t max_gval = (int32_t)(1.0 * BMA4XY_MULTIPLIER); + + while (index < 3) { + if (gvalue[index] >= min_gval && gvalue[index] <= max_gval) + index++; + else + return BMA4_E_OUT_OF_RANGE; + } + + return BMA4_OK; +} + +/*! + * @brief This API normalise the data with offset + */ +static void normalise_offset(const struct offset_delta *compensated_data, struct accel_offset *offset_data) +{ + /* for handling negative offset */ + /* employing twos's Complement method*/ + if (compensated_data->x.is_negative == TRUE) { + offset_data->x = ~offset_data->x; + offset_data->x += 1; + } + + if (compensated_data->y.is_negative == TRUE) { + offset_data->y = ~offset_data->y; + offset_data->y += 1; + } + + if (compensated_data->z.is_negative == TRUE) { + offset_data->z = ~offset_data->z; + offset_data->z += 1; + } + + offset_data->x = (uint8_t)((offset_data->x) * (-1)); + offset_data->y = (uint8_t)((offset_data->y) * (-1)); + offset_data->z = (uint8_t)((offset_data->z) * (-1)); +} + +/*! + * @brief This API normalize the data with offset. + */ +static void scale_offset(uint8_t res, uint8_t range, const struct offset_delta *delta, struct accel_offset *data) +{ + int8_t bit_pos_3_9mg, bit_pos_3_9mg_nextbit; + uint8_t round_off = 0; + + /* Find the bit position of 3.9mg */ + bit_pos_3_9mg = get_bit_pos_3_9mg(range, res); + + /* Data register resolution less than or equal to 3.9 mg */ + if (bit_pos_3_9mg > 0) { + /* Round off, consider if the next bit is high */ + bit_pos_3_9mg_nextbit = bit_pos_3_9mg - 1; + round_off = (uint8_t)(1 * power(2, ((uint8_t) bit_pos_3_9mg_nextbit))); + /* scale according to offset register resolution*/ + data->x = (uint8_t)((delta->x.val + round_off) / power(2, ((uint8_t)bit_pos_3_9mg))); + data->y = (uint8_t)((delta->y.val + round_off) / power(2, ((uint8_t)bit_pos_3_9mg))); + data->z = (uint8_t)((delta->z.val + round_off) / power(2, ((uint8_t)bit_pos_3_9mg))); + } else if (bit_pos_3_9mg < 0) { + bit_pos_3_9mg = (int8_t)(bit_pos_3_9mg * -1); + data->x = (uint8_t)(delta->x.val * power(2, ((uint8_t)bit_pos_3_9mg))); + data->y = (uint8_t)(delta->y.val * power(2, ((uint8_t)bit_pos_3_9mg))); + data->z = (uint8_t)(delta->z.val * power(2, ((uint8_t)bit_pos_3_9mg))); + } else { + /* Scale according to offset register resolution */ + data->x = (uint8_t)(delta->x.val); + data->y = (uint8_t)(delta->y.val); + data->z = (uint8_t)(delta->z.val); + } +} + +/*! + * @brief This API compensate the accel data against gravity. + * + * @note The g-values to be passed to the parameter should be + * multiples of 1000000. + */ +static void comp_for_grvty(uint16_t lsb_per_g, const int32_t g_val[3], const struct bma4_accel *data, + struct offset_delta *comp_data) +{ + int64_t accel_value_lsb[3] = {0}; + uint8_t index; + + for (index = 0; index < 3; index++) { + /* convert g to lsb */ + accel_value_lsb[index] = ((int64_t)(lsb_per_g) * (int64_t)(g_val[index])); + } + + /* Dividing the accel value in LSB by 1000000 to get + compensated data back in g-value */ + comp_data->x.val = (int16_t)(data->x - (int16_t)((accel_value_lsb[BMA4_X_AXIS] / (int64_t)BMA4XY_MULTIPLIER))); + comp_data->y.val = (int16_t)(data->y - (int16_t)((accel_value_lsb[BMA4_Y_AXIS] / (int64_t)BMA4XY_MULTIPLIER))); + comp_data->z.val = (int16_t)(data->z - (int16_t)((accel_value_lsb[BMA4_Z_AXIS] / (int64_t)BMA4XY_MULTIPLIER))); + + if (comp_data->x.val < 0) { + comp_data->x.val = ABS(comp_data->x.val); + comp_data->x.is_negative = 1; + } + + if (comp_data->y.val < 0) { + comp_data->y.val = ABS(comp_data->y.val); + comp_data->y.is_negative = 1; + } + + if (comp_data->z.val < 0) { + comp_data->z.val = ABS(comp_data->z.val); + comp_data->z.is_negative = 1; + } +} + +/*! + * @brief This API converts the range value into corresponding + * integer value. + */ +static void map_range(uint8_t range_in, uint8_t *range_out) +{ + switch (range_in) { + case BMA4_ACCEL_RANGE_2G: + *range_out = 2; + break; + case BMA4_ACCEL_RANGE_4G: + *range_out = 4; + break; + case BMA4_ACCEL_RANGE_8G: + *range_out = 8; + break; + case BMA4_ACCEL_RANGE_16G: + *range_out = 16; + break; + default: + break; + } +} + +/*! + * @brief This API is used to reset the FIFO related configurations + * in the fifo_frame structure. + * + */ +static void reset_fifo_data_structure(const struct bma4_dev *dev) +{ + /*Prepare for next FIFO read by resetting FIFO's + internal data structures*/ + dev->fifo->accel_byte_start_idx = 0; + dev->fifo->mag_byte_start_idx = 0; + dev->fifo->sc_frame_byte_start_idx = 0; + dev->fifo->sensor_time = 0; + dev->fifo->skipped_frame_count = 0; + dev->fifo->accel_dropped_frame_count = 0; + dev->fifo->mag_dropped_frame_count = 0; +} + +/*! + * @brief This API computes the number of bytes of accel FIFO data + * which is to be parsed in header-less mode + */ +static void get_accel_len_to_parse(uint16_t *start_idx, uint16_t *len, const uint16_t *acc_count, + const struct bma4_dev *dev) +{ + uint8_t dummy_byte_spi = 0; + + /*Check if this is the first iteration of data unpacking + if yes, then consider dummy byte on SPI*/ + if (dev->fifo->accel_byte_start_idx == 0) + dummy_byte_spi = dev->dummy_byte; + + /*Data start index*/ + *start_idx = dev->fifo->accel_byte_start_idx + dummy_byte_spi; + + if (dev->fifo->fifo_data_enable == BMA4_FIFO_A_ENABLE) { + /*Len has the number of bytes to loop for */ + *len = (uint16_t)(((*acc_count) * BMA4_FIFO_A_LENGTH) + dummy_byte_spi); + } else if (dev->fifo->fifo_data_enable == BMA4_FIFO_M_A_ENABLE) { + /*Len has the number of bytes to loop for */ + *len = (uint16_t)(((*acc_count) * BMA4_FIFO_MA_LENGTH) + dummy_byte_spi); + } else { + /*Only aux. sensor or no sensor is enabled in FIFO, + so there will be no accel data. + Update the data index as complete*/ + *start_idx = dev->fifo->length; + } + if ((*len) > dev->fifo->length) { + /*Handling the case where more data is requested + than available*/ + *len = dev->fifo->length; + } +} + +/*! + * @brief This API checks the fifo read data as empty frame, if it + * is empty frame then moves the index to last byte. + */ +static void check_empty_fifo(uint16_t *data_index, const struct bma4_dev *dev) +{ + if ((*data_index + 2) < dev->fifo->length) { + /* Check if FIFO is empty */ + if ((dev->fifo->data[*data_index] == FIFO_MSB_CONFIG_CHECK) + && (dev->fifo->data[*data_index + 1] == FIFO_LSB_CONFIG_CHECK)) { + /*Update the data index as complete*/ + *data_index = dev->fifo->length; + } + } +} + +/*! + * @brief This API is used to parse the accelerometer data from the + * FIFO data in header mode. + * + */ +static void extract_accel_header_mode(struct bma4_accel *accel_data, uint16_t *accel_length, const struct bma4_dev *dev) +{ + uint8_t frame_header = 0; + uint16_t data_index; + uint16_t accel_index = 0; + uint16_t frame_to_read = *accel_length; + /*Check if this is the first iteration of data unpacking + if yes, then consider dummy byte on SPI*/ + if (dev->fifo->accel_byte_start_idx == 0) + dev->fifo->accel_byte_start_idx = dev->dummy_byte; + + for (data_index = dev->fifo->accel_byte_start_idx; data_index < dev->fifo->length;) { + /*Header byte is stored in the variable frame_header*/ + frame_header = dev->fifo->data[data_index]; + /*Get the frame details from header*/ + frame_header = frame_header & BMA4_FIFO_TAG_INTR_MASK; + /*Index is moved to next byte where the data is starting*/ + data_index++; + + switch (frame_header) { + /* Accel frame */ + case FIFO_HEAD_A: + case FIFO_HEAD_M_A: + unpack_acc_frm(accel_data, &data_index, &accel_index, frame_header, dev); + break; + /* Aux. sensor frame */ + case FIFO_HEAD_M: + move_next_frame(&data_index, BMA4_FIFO_M_LENGTH, dev); + break; + /* Sensor time frame */ + case FIFO_HEAD_SENSOR_TIME: + unpack_sensortime_frame(&data_index, dev); + break; + /* Skip frame */ + case FIFO_HEAD_SKIP_FRAME: + unpack_skipped_frame(&data_index, dev); + break; + /* Input config frame */ + case FIFO_HEAD_INPUT_CONFIG: + move_next_frame(&data_index, 1, dev); + break; + /* Sample drop frame */ + case FIFO_HEAD_SAMPLE_DROP: + unpack_dropped_frame(&data_index, dev); + break; + /* Over read FIFO data */ + case FIFO_HEAD_OVER_READ_MSB: + /* Update the data index as complete*/ + data_index = dev->fifo->length; + break; + default: + break; + } + if (frame_to_read == accel_index) { + /*Number of frames to read completed*/ + break; + } + } + + /*Update number of accel data read*/ + *accel_length = accel_index; + /*Update the accel frame index*/ + dev->fifo->accel_byte_start_idx = data_index; +} + +/*! + * @brief This API is used to parse the accelerometer data from the + * FIFO data in both header mode and header-less mode. + * It update the idx value which is used to store the index of + * the current data byte which is parsed. + */ +static void unpack_acc_frm(struct bma4_accel *acc, uint16_t *idx, uint16_t *acc_idx, uint8_t frm, + const struct bma4_dev *dev) +{ + switch (frm) { + case FIFO_HEAD_A: + case BMA4_FIFO_A_ENABLE: + /*Partial read, then skip the data*/ + if ((*idx + BMA4_FIFO_A_LENGTH) > dev->fifo->length) { + /*Update the data index as complete*/ + *idx = dev->fifo->length; + break; + } + /*Unpack the data array into the structure instance "acc" */ + unpack_accel_data(&acc[*acc_idx], *idx, dev); + /*Move the data index*/ + *idx = *idx + BMA4_FIFO_A_LENGTH; + (*acc_idx)++; + break; + case FIFO_HEAD_M_A: + case BMA4_FIFO_M_A_ENABLE: + /*Partial read, then skip the data*/ + if ((*idx + BMA4_FIFO_MA_LENGTH) > dev->fifo->length) { + /*Update the data index as complete*/ + *idx = dev->fifo->length; + break; + } + /*Unpack the data array into structure instance "acc"*/ + unpack_accel_data(&acc[*acc_idx], *idx + BMA4_MA_FIFO_A_X_LSB, dev); + /*Move the data index*/ + *idx = *idx + BMA4_FIFO_MA_LENGTH; + (*acc_idx)++; + break; + /* Aux. sensor frame */ + case FIFO_HEAD_M: + case BMA4_FIFO_M_ENABLE: + (*idx) = (*idx) + BMA4_FIFO_M_LENGTH; + break; + default: + break; + } +} + +/*! + * @brief This API is used to parse the accelerometer data from the + * FIFO data and store it in the instance of the structure bma4_accel. + */ +static void unpack_accel_data(struct bma4_accel *accel_data, uint16_t data_start_index, const struct bma4_dev *dev) +{ + uint16_t data_lsb; + uint16_t data_msb; + + /* Accel raw x data */ + data_lsb = dev->fifo->data[data_start_index++]; + data_msb = dev->fifo->data[data_start_index++]; + accel_data->x = (int16_t)((data_msb << 8) | data_lsb); + + /* Accel raw y data */ + data_lsb = dev->fifo->data[data_start_index++]; + data_msb = dev->fifo->data[data_start_index++]; + accel_data->y = (int16_t)((data_msb << 8) | data_lsb); + + /* Accel raw z data */ + data_lsb = dev->fifo->data[data_start_index++]; + data_msb = dev->fifo->data[data_start_index++]; + accel_data->z = (int16_t)((data_msb << 8) | data_lsb); + + if (dev->resolution == BMA4_12_BIT_RESOLUTION) { + accel_data->x = (accel_data->x / 0x10); + accel_data->y = (accel_data->y / 0x10); + accel_data->z = (accel_data->z / 0x10); + } else if (dev->resolution == BMA4_14_BIT_RESOLUTION) { + accel_data->x = (accel_data->x / 0x04); + accel_data->y = (accel_data->y / 0x04); + accel_data->z = (accel_data->z / 0x04); + } +} + +/*! + * @brief This API computes the number of bytes of Mag FIFO data which is + * to be parsed in header-less mode + * + */ +static void get_mag_len_to_parse(uint16_t *start_idx, uint16_t *len, const uint16_t *mag_count, + const struct bma4_dev *dev) +{ + uint8_t dummy_byte_spi = 0; + + /*Check if this is the first iteration of data unpacking + if yes, then consider dummy byte on SPI*/ + if (dev->fifo->mag_byte_start_idx == 0) + dummy_byte_spi = dev->dummy_byte; + + /*Data start index*/ + *start_idx = dev->fifo->mag_byte_start_idx + dummy_byte_spi; + + if (dev->fifo->fifo_data_enable == BMA4_FIFO_M_ENABLE) { + /*Len has the number of bytes to loop for */ + *len = (uint16_t)(((*mag_count) * BMA4_FIFO_M_LENGTH) + dummy_byte_spi); + } else if (dev->fifo->fifo_data_enable == BMA4_FIFO_M_A_ENABLE) { + /*Len has the number of bytes to loop for */ + *len = (uint16_t)(((*mag_count) * BMA4_FIFO_MA_LENGTH) + dummy_byte_spi); + } else { + /*Only accel sensor or no sensor is enabled in FIFO, + so there will be no mag data. + Update the data index as complete*/ + *start_idx = dev->fifo->length; + } + + /*Handling the case where more data is requested than available*/ + if ((*len) > dev->fifo->length) { + /*Len is equal to the FIFO length*/ + *len = dev->fifo->length; + } +} + +/*! + * @brief This API is used to parse the magnetometer data from the + * FIFO data in header mode. + * + */ +static uint16_t extract_mag_header_mode(struct bma4_mag *data, uint16_t *len, const struct bma4_dev *dev) +{ + uint16_t rslt = 0; + uint8_t frame_header = 0; + uint16_t data_index; + uint16_t mag_index = 0; + uint16_t frame_to_read = *len; + + /*Check if this is the first iteration of data unpacking + if yes, then consider dummy byte on SPI*/ + if (dev->fifo->mag_byte_start_idx == 0) + dev->fifo->mag_byte_start_idx = dev->dummy_byte; + + for (data_index = dev->fifo->mag_byte_start_idx; data_index < dev->fifo->length;) { + /*Header byte is stored in the variable frame_header*/ + frame_header = dev->fifo->data[data_index]; + /*Get the frame details from header*/ + frame_header = frame_header & BMA4_FIFO_TAG_INTR_MASK; + /*Index is moved to next byte where the data is starting*/ + data_index++; + + switch (frame_header) { + /* Aux. sensor frame */ + case FIFO_HEAD_M: + case FIFO_HEAD_M_A: + rslt |= unpack_mag_frm(data, &data_index, &mag_index, frame_header, dev); + break; + /* Aux. sensor frame */ + case FIFO_HEAD_A: + move_next_frame(&data_index, BMA4_FIFO_A_LENGTH, dev); + break; + /* Sensor time frame */ + case FIFO_HEAD_SENSOR_TIME: + unpack_sensortime_frame(&data_index, dev); + break; + /* Skip frame */ + case FIFO_HEAD_SKIP_FRAME: + unpack_skipped_frame(&data_index, dev); + break; + /* Input config frame */ + case FIFO_HEAD_INPUT_CONFIG: + move_next_frame(&data_index, 1, dev); + break; + /* Sample drop frame */ + case FIFO_HEAD_SAMPLE_DROP: + unpack_dropped_frame(&data_index, dev); + break; + case FIFO_HEAD_OVER_READ_MSB: + /*Update the data index as complete*/ + data_index = dev->fifo->length; + break; + default: + break; + } + if (frame_to_read == mag_index) { + /*Number of frames to read completed*/ + break; + } + } + /*update number of Aux. sensor data read*/ + *len = mag_index; + /*update the Aux. sensor frame index*/ + dev->fifo->mag_byte_start_idx = data_index; + return rslt; +} + +/*! + * @brief This API is used to parse the magnetometer data from the + * FIFO data in both header mode and header-less mode and update the + * data_index value which is used to store the index of the current + * data byte which is parsed. + * + */ +static uint16_t unpack_mag_frm(struct bma4_mag *data, uint16_t *idx, uint16_t *mag_idx, uint8_t frm, + const struct bma4_dev *dev) +{ + uint16_t rslt = 0; + + switch (frm) { + case FIFO_HEAD_M: + case BMA4_FIFO_M_ENABLE: + /*partial read, then skip the data*/ + if ((*idx + BMA4_FIFO_M_LENGTH) > dev->fifo->length) { + /*update the data index as complete*/ + *idx = dev->fifo->length; + break; + } + + /*unpack the data array into Aux. sensor data structure*/ + rslt |= unpack_mag_data(&data[*mag_idx], *idx, dev); + /*move the data index*/ + *idx = *idx + BMA4_FIFO_M_LENGTH; + (*mag_idx)++; + break; + case FIFO_HEAD_M_A: + case BMA4_FIFO_M_A_ENABLE: + /*partial read, then skip the data*/ + if ((*idx + BMA4_FIFO_MA_LENGTH) > dev->fifo->length) { + /*update the data index as complete*/ + *idx = dev->fifo->length; + break; + } + + /*unpack the data array into Aux. sensor data structure*/ + rslt |= unpack_mag_data(&data[*mag_idx], *idx, dev); + /*move the data index to next frame*/ + *idx = *idx + BMA4_FIFO_MA_LENGTH; + (*mag_idx)++; + break; + /* aux. sensor frame */ + case FIFO_HEAD_A: + case BMA4_FIFO_A_ENABLE: + (*idx) = (*idx) + BMA4_FIFO_A_LENGTH; + break; + default: + break; + } + + return rslt; +} + +/*! + * @brief This API is used to parse the auxiliary magnetometer data from + * the FIFO data and store it in the instance of the structure mag_data. + * + */ +static uint16_t unpack_mag_data(struct bma4_mag *mag_data, uint16_t start_idx, const struct bma4_dev *dev) +{ + uint16_t rslt = 0; + struct bma4_mag_fifo_data mag_fifo_data; + + /* Aux. mag sensor raw x data */ + mag_fifo_data.mag_x_lsb = dev->fifo->data[start_idx++]; + mag_fifo_data.mag_x_msb = dev->fifo->data[start_idx++]; + + /* Aux. mag sensor raw y data */ + mag_fifo_data.mag_y_lsb = dev->fifo->data[start_idx++]; + mag_fifo_data.mag_y_msb = dev->fifo->data[start_idx++]; + + /* Aux. mag sensor raw z data */ + mag_fifo_data.mag_z_lsb = dev->fifo->data[start_idx++]; + mag_fifo_data.mag_z_msb = dev->fifo->data[start_idx++]; + + /* Aux. mag sensor raw r data */ + mag_fifo_data.mag_r_y2_lsb = dev->fifo->data[start_idx++]; + mag_fifo_data.mag_r_y2_msb = dev->fifo->data[start_idx++]; + + /*Compensated FIFO data output*/ + rslt |= bma4_second_if_mag_compensate_xyz(mag_fifo_data, dev->aux_sensor, mag_data); + + return rslt; +} + +/*! + * @brief This API is used to parse and store the sensor time from the + * FIFO data in the structure instance dev. + * + */ +static void unpack_sensortime_frame(uint16_t *data_index, const struct bma4_dev *dev) +{ + uint32_t sensor_time_byte3 = 0; + uint16_t sensor_time_byte2 = 0; + uint8_t sensor_time_byte1 = 0; + + /*Partial read, then move the data index to last data*/ + if ((*data_index + BMA4_SENSOR_TIME_LENGTH) > dev->fifo->length) { + /*Update the data index as complete*/ + *data_index = dev->fifo->length; + } else { + sensor_time_byte3 = dev->fifo->data[(*data_index) + BMA4_SENSOR_TIME_MSB_BYTE] << 16; + sensor_time_byte2 = dev->fifo->data[(*data_index) + BMA4_SENSOR_TIME_XLSB_BYTE] << 8; + sensor_time_byte1 = dev->fifo->data[(*data_index)]; + /* Sensor time */ + dev->fifo->sensor_time = (uint32_t)(sensor_time_byte3 | sensor_time_byte2 | sensor_time_byte1); + *data_index = (*data_index) + BMA4_SENSOR_TIME_LENGTH; + } +} + +/*! + * @brief This API is used to parse and store the skipped_frame_count from + * the FIFO data in the structure instance dev. + */ +static void unpack_skipped_frame(uint16_t *data_index, const struct bma4_dev *dev) +{ + /*Partial read, then move the data index to last data*/ + if (*data_index >= dev->fifo->length) { + /*Update the data index as complete*/ + *data_index = dev->fifo->length; + } else { + dev->fifo->skipped_frame_count = dev->fifo->data[*data_index]; + /*Move the data index*/ + *data_index = (*data_index) + 1; + } +} + +/*! + * @brief This API is used to parse and store the dropped_frame_count from + * the FIFO data in the structure instance dev. + */ +static void unpack_dropped_frame(uint16_t *data_index, const struct bma4_dev *dev) +{ + uint8_t dropped_frame = 0; + /*Partial read, then move the data index to last data*/ + if (*data_index >= dev->fifo->length) { + /*Update the data index as complete*/ + *data_index = dev->fifo->length; + } else { + /*Extract accel and mag dropped frame count*/ + dropped_frame = dev->fifo->data[*data_index] & ACCEL_AUX_FIFO_DROP; + /*Move the data index and update the dropped frame count*/ + switch (dropped_frame) { + case ACCEL_FIFO_DROP: + *data_index = (*data_index) + BMA4_FIFO_A_LENGTH; + dev->fifo->accel_dropped_frame_count = dev->fifo->accel_dropped_frame_count + 1; + break; + case AUX_FIFO_DROP: + *data_index = (*data_index) + BMA4_FIFO_M_LENGTH; + dev->fifo->mag_dropped_frame_count = dev->fifo->mag_dropped_frame_count + 1; + break; + case ACCEL_AUX_FIFO_DROP: + *data_index = (*data_index) + BMA4_FIFO_MA_LENGTH; + dev->fifo->accel_dropped_frame_count = dev->fifo->accel_dropped_frame_count + 1; + dev->fifo->mag_dropped_frame_count = dev->fifo->mag_dropped_frame_count + 1; + break; + default: + break; + } + } +} + +/*! + * @brief This API is used to move the data index ahead of the + * current_frame_length parameter when unnecessary FIFO data appears while + * extracting the user specified data. + */ +static void move_next_frame(uint16_t *data_index, uint8_t current_frame_length, const struct bma4_dev *dev) +{ + /*Partial read, then move the data index to last data*/ + if ((*data_index + current_frame_length) > dev->fifo->length) { + /*Update the data index as complete*/ + *data_index = dev->fifo->length; + } else { + /*Move the data index to next frame*/ + *data_index = *data_index + current_frame_length; + } +} + +/*! + * @brief This function validates the Accel Self test data and decides the + * result of Self test operation. + */ +static uint16_t validate_selftest(const struct selftest_delta_limit *accel_data_diff, + const struct bma4_dev *dev) +{ + uint16_t rslt = 0; + + /* Set self test amplitude based on variant */ + switch (dev->variant) { + case BMA42X_VARIANT: + /* Validating accel data by comparing with minimum value of the axes in mg */ + /* For BMA42x - > x axis limit 400mg, y axis limit 800mg and z axis limit 400mg */ + if ((accel_data_diff->x > BMA42X_ST_ACC_X_AXIS_SIGNAL_DIFF) && + (accel_data_diff->y > BMA42X_ST_ACC_Y_AXIS_SIGNAL_DIFF) && + (accel_data_diff->z > BMA42X_ST_ACC_Z_AXIS_SIGNAL_DIFF)) { + rslt = BMA4_OK; + } else { + rslt = BMA4_E_SELF_TEST_FAIL; + } + break; + + case BMA45X_VARIANT: + /* Validating accel data by comparing with minimum value of the axes in mg */ + /* For BMA45x - > x axis limit 1800mg, y axis limit 1800mg and z axis limit 1800mg */ + if ((accel_data_diff->x > BMA45X_ST_ACC_X_AXIS_SIGNAL_DIFF) && + (accel_data_diff->y > BMA45X_ST_ACC_Y_AXIS_SIGNAL_DIFF) && + (accel_data_diff->z > BMA45X_ST_ACC_Z_AXIS_SIGNAL_DIFF)) { + rslt = BMA4_OK; + } else { + rslt = BMA4_E_SELF_TEST_FAIL; + } + break; + + default: + rslt = BMA4_E_INVALID_SENSOR; + break; + } + + return rslt; +} + +/*! + * @brief This function configure the Accel for FOC. + */ +static uint16_t foc_config(struct bma4_accel_config *acc_conf, uint8_t *acc_en, uint8_t *pwr_mode, struct bma4_dev *dev) +{ + uint16_t rslt = 0; + uint8_t accel_cnf = BMA4_ACCEL_CONFIG_FOC; + + /* for saving Accel configuration, + Accel enable status, advance power save*/ + rslt |= bma4_get_accel_config(acc_conf, dev); + rslt |= bma4_get_accel_enable(acc_en, dev); + rslt |= bma4_get_advance_power_save(pwr_mode, dev); + + /* Disabling offset compensation that is in place*/ + rslt |= bma4_set_offset_comp(BMA4_DISABLE, dev); + + if (rslt == BMA4_OK) { + /* Set Accel config to 50Hz, continuous filter mode, + no under sampling */ + rslt |= bma4_write_regs(BMA4_ACCEL_CONFIG_ADDR, &accel_cnf, 1, dev); + + if (rslt == BMA4_OK) { + /* Switch Accel to normal mode and + advance power save to zero*/ + rslt |= bma4_set_accel_enable(BMA4_ENABLE, dev); + rslt |= bma4_set_advance_power_save(BMA4_DISABLE, dev); + } + } + + return rslt; +} + +/*! + * @brief This API is used to calculate the power of 2 + */ +static int32_t power(int16_t base, uint8_t resolution) +{ + uint8_t i = 1; + /* Initialize variable to store the power of 2 value */ + int32_t value = 1; + + for (; i <= resolution; i++) + value = (int32_t)(value * base); + + return value; +} + +/*! + * @brief This API performs the roundoff on given value + */ +static int8_t roundoff(int32_t value) +{ + /* Variable to return the round off value */ + int8_t ret = 0; + + /* Since the value passed is scaled in multiples of 100, + the return value is divided by 100 to get the round off value */ + if (value < 0) + ret = (int8_t)(((value) - 50) / 100); + else + ret = (int8_t)(((value) + 50) / 100); + + + return ret; +} + +/*! + * @brief This API finds the bit position of 3.9mg according to given range + * and resolution. + */ +static int8_t get_bit_pos_3_9mg(uint8_t range, uint8_t res) +{ + /* Variable to store the bit position of 3.9mg */ + int8_t bit_pos_3_9mg = 0; + /* Variable to store the value to be rounded off */ + int32_t value = 0; + /* Variable to store the LSB per bit in micros */ + int32_t ug_per_bit; + /* Variable to store the rounded off value */ + int8_t round_off_int; + /* Variable to store the bit count */ + uint8_t bit_count = 0; + /* Variable to store the signed range value */ + int32_t range_value; + + /* Scaling range with a multiplier to get integer value of ug_per_bit */ + range_value = (int32_t)(2 * range * BMA4XY_MULTIPLIER); + + /* Get the G-per bit resolution*/ + ug_per_bit = (int32_t)(range_value / power(2, res)); + + /* Compare for -ve & +ve bit position w.r.t 3900micro-g or as reference + * Note: Value scaled in 100s to get accurate integer value */ + if (ug_per_bit > 3900) + value = (int32_t)(ug_per_bit * 100 / 3900); + else + value = (int32_t)(3900 * 100 / ug_per_bit); + + /* Round off the value */ + round_off_int = (int8_t)(roundoff(value)); + + /* Find the bit position of 3.9mg*/ + while (round_off_int != 1) { + round_off_int = (round_off_int / 0x02); + bit_count++; + } + + /* Check for +ve and -ve bit position of 3.9 mg */ + if (ug_per_bit > 3900) + bit_pos_3_9mg = (int8_t)(bit_count * (-1)); + else + bit_pos_3_9mg = (int8_t)bit_count; + + return bit_pos_3_9mg; +} +/*! + * @brief This internal API brings up the secondary interface to access + * auxiliary sensor * + */ +static uint16_t bma4_set_aux_interface_config(struct bma4_dev *dev) +{ + /* Variable to return error codes */ + uint16_t rslt = BMA4_OK; + + /* Check for null pointer error */ + rslt |= bma4_null_pointer_check(dev); + + if (rslt == BMA4_OK) { + /* Enable the auxiliary sensor */ + rslt |= bma4_set_mag_enable(0x01, dev); + dev->delay(BMA4_AUX_COM_DELAY); + + /* Disable advance power save */ + rslt |= bma4_set_advance_power_save(0x00, dev); + dev->delay(BMA4_AUX_COM_DELAY); + + /* Set the I2C device address of auxiliary device */ + rslt |= bma4_set_i2c_device_addr(dev); + dev->delay(BMA4_AUX_COM_DELAY); + + /* Set auxiliary interface to manual mode */ + rslt |= bma4_set_mag_manual_enable(dev->aux_config.manual_enable, dev); + dev->delay(BMA4_AUX_COM_DELAY); + + /* Set the number of bytes for burst read */ + rslt |= bma4_set_mag_burst(dev->aux_config.burst_read_length, dev); + dev->delay(BMA4_AUX_COM_DELAY); + + /* Switch on the the auxiliary interface mode */ + rslt |= bma4_set_if_mode(dev->aux_config.if_mode, dev); + dev->delay(BMA4_AUX_COM_DELAY); + + } + + return rslt; +} + +/*! +* @brief This internal API reads the data from the auxiliary sensor +* depending on burst length configured +*/ +static uint16_t bma4_extract_aux_data(uint8_t aux_reg_addr, uint8_t *aux_data, uint16_t len, struct bma4_dev *dev) +{ + /* Variable to return error codes */ + uint16_t rslt = BMA4_OK; + /* Pointer variable to read data from the register */ + uint8_t data[15] = {0}; + /* Variable to define length counts */ + uint8_t len_count = 0; + /* Variable to define burst read length */ + uint8_t burst_len = 0; + /* Variable to define read length */ + uint8_t read_length = 0; + /* Variable to define the number of burst reads */ + uint8_t burst_count; + /* Variable to define address of the data register*/ + uint8_t aux_read_addr = BMA4_DATA_0_ADDR; + + /* Extract burst read length in a variable */ + rslt |= bma4_map_read_len(&burst_len, dev); + + for (burst_count = 0; burst_count < len; burst_count += burst_len) { + /* Set the address whose data is to be read */ + rslt |= bma4_set_mag_read_addr(aux_reg_addr, dev); + dev->delay(BMA4_AUX_COM_DELAY); + + if (rslt == BMA4_OK) { + /* If user defined length is valid */ + if (len > 0) { + /* Read the data from the data register */ + rslt |= bma4_read_regs(aux_read_addr, data, (uint8_t)burst_len, dev); + dev->delay(BMA4_AUX_COM_DELAY); + + if (rslt == BMA4_OK) { + /* If defined user length or remaining length after a burst + read is less than burst length */ + if ((len - burst_count) < burst_len) { + /* Read length is equal to burst_length or + remaining length*/ + read_length = (uint8_t)(len - burst_count); + } else { + /* Read length is equal to burst_length */ + read_length = burst_len; + } + + /* Copy the read data in terms of given read length */ + for (len_count = 0; len_count < read_length; len_count++) + aux_data[burst_count + len_count] = data[len_count]; + + /* Increment the register address by burst read length */ + aux_reg_addr += burst_len; + } else { + rslt = BMA4_E_RD_WR_LENGTH_INVALID; + } + } else { + rslt = BMA4_E_FAIL; + } + } else { + rslt = BMA4_E_FAIL; + } + } + + return rslt; +} + +/*! + * @brief This internal API maps the actual burst read length with user + length set. + */ +static uint16_t bma4_map_read_len(uint8_t *len, const struct bma4_dev *dev) +{ + /* Variable to return error codes */ + uint16_t rslt = BMA4_OK; + + switch (dev->aux_config.burst_read_length) { + + case BMA4_AUX_READ_LEN_0: + *len = 1; + break; + case BMA4_AUX_READ_LEN_1: + *len = 2; + break; + case BMA4_AUX_READ_LEN_2: + *len = 6; + break; + case BMA4_AUX_READ_LEN_3: + *len = 8; + break; + default: + rslt = BMA4_E_OUT_OF_RANGE; + break; + } + + return rslt; +} + +/*! +* @brief This internal API checks null pointer error +*/ +static uint16_t bma4_null_pointer_check(const struct bma4_dev *dev) +{ + uint16_t rslt = BMA4_OK; + + if ((dev == NULL) || (dev->bus_read == NULL) || (dev->bus_write == NULL)) + rslt |= BMA4_E_NULL_PTR; + else + rslt = BMA4_OK; + + return rslt; +} diff --git a/lib/libesp32/TTGO_TWatch_Library/src/bma4.h b/lib/libesp32_div/TTGO_TWatch_Library/src/bma4.h old mode 100755 new mode 100644 similarity index 97% rename from lib/libesp32/TTGO_TWatch_Library/src/bma4.h rename to lib/libesp32_div/TTGO_TWatch_Library/src/bma4.h index eba44b26c..b99d9e111 --- a/lib/libesp32/TTGO_TWatch_Library/src/bma4.h +++ b/lib/libesp32_div/TTGO_TWatch_Library/src/bma4.h @@ -1,1574 +1,1574 @@ -/* -* -**************************************************************************** -* Copyright (C) 2015 - 2016 Bosch Sensortec GmbH -* -* File : bma4.h -* -* Date: 12 Oct 2017 -* -* Revision: 2.1.9 $ -* -* Usage: Sensor Driver for BMA4 family of sensors -* -**************************************************************************** -* -* Disclaimer -* -* Common: -* Bosch Sensortec products are developed for the consumer goods industry. -* They may only be used within the parameters of the respective valid -* product data sheet. Bosch Sensortec products are provided with the -* express understanding that there is no warranty of fitness for a -* particular purpose.They are not fit for use in life-sustaining, -* safety or security sensitive systems or any system or device -* that may lead to bodily harm or property damage if the system -* or device malfunctions. In addition,Bosch Sensortec products are -* not fit for use in products which interact with motor vehicle systems. -* The resale and or use of products are at the purchasers own risk and -* his own responsibility. The examination of fitness for the intended use -* is the sole responsibility of the Purchaser. -* -* The purchaser shall indemnify Bosch Sensortec from all third party -* claims, including any claims for incidental, or consequential damages, -* arising from any product use not covered by the parameters of -* the respective valid product data sheet or not approved by -* Bosch Sensortec and reimburse Bosch Sensortec for all costs in -* connection with such claims. -* -* The purchaser must monitor the market for the purchased products, -* particularly with regard to product safety and inform Bosch Sensortec -* without delay of all security relevant incidents. -* -* Engineering Samples are marked with an asterisk (*) or (e). -* Samples may vary from the valid technical specifications of the product -* series. They are therefore not intended or fit for resale to third -* parties or for use in end products. Their sole purpose is internal -* client testing. The testing of an engineering sample may in no way -* replace the testing of a product series. Bosch Sensortec assumes -* no liability for the use of engineering samples. -* By accepting the engineering samples, the Purchaser agrees to indemnify -* Bosch Sensortec from all claims arising from the use of engineering -* samples. -* -* Special: -* This software module (hereinafter called "Software") and any information -* on application-sheets (hereinafter called "Information") is provided -* free of charge for the sole purpose to support your application work. -* The Software and Information is subject to the following -* terms and conditions: -* -* The Software is specifically designed for the exclusive use for -* Bosch Sensortec products by personnel who have special experience -* and training. Do not use this Software if you do not have the -* proper experience or training. -* -* This Software package is provided `` as is `` and without any expressed -* or implied warranties,including without limitation, the implied warranties -* of merchantability and fitness for a particular purpose. -* -* Bosch Sensortec and their representatives and agents deny any liability -* for the functional impairment -* of this Software in terms of fitness, performance and safety. -* Bosch Sensortec and their representatives and agents shall not be liable -* for any direct or indirect damages or injury, except as -* otherwise stipulated in mandatory applicable law. -* -* The Information provided is believed to be accurate and reliable. -* Bosch Sensortec assumes no responsibility for the consequences of use -* of such Information nor for any infringement of patents or -* other rights of third parties which may result from its use. -* No license is granted by implication or otherwise under any patent or -* patent rights of Bosch. Specifications mentioned in the Information are -* subject to change without notice. -**************************************************************************/ -/*! \file bma4.h - \brief Sensor Driver for BMA4 family of sensors */ -#ifndef BMA4_H__ -#define BMA4_H__ - -/*********************************************************************/ -/* header files */ - -#include "bma4_defs.h" -#ifdef AKM9916 -#include "aux_akm9916.h" -#endif - -#ifdef BMM150 -#include "aux_bmm150.h" -#endif -/*********************************************************************/ -/* (extern) variable declarations */ - -/*********************************************************************/ -/* function prototype declarations */ -/*! - * @brief This API is the entry point. - * Call this API before using all other APIs. - * This API reads the chip-id of the sensor which is the first step to - * verify the sensor and also it configures the read mechanism of SPI and - * I2C interface. - * - * @param[in,out] dev : Structure instance of bma4_dev - * - * @return Result of API execution status - * @retval 0 -> Success - * @retval Any non zero value -> Fail - * - * @note - * While changing the parameter of the bma4 - * consider the following point: - * Changing the reference value of the parameter - * will changes the local copy or local reference - * make sure your changes will not - * affect the reference value of the parameter - * (Better case don't change the reference value of the parameter) - */ -uint16_t bma4_init(struct bma4_dev *dev); - -/*! - * @brief This API is used to write the binary configuration in the sensor - * - * @param[in] dev : Structure instance of bma4_dev. - * - * @return Result of API execution status - * @retval 0 -> Success - * @retval Any non zero value -> Fail - * - */ -uint16_t bma4_write_config_file(struct bma4_dev *dev); - -/*! - * @brief This API checks whether the write operation requested is for - * feature config or register write and accordingly writes the data in the - * sensor. - * - * @note user has to disable the advance power save mode in the sensor when - * using this API in burst write mode. - * bma4_set_advance_power_save(BMA4_DISABLE, dev); - * - * @param[in] addr : Register address. - * @param[in] data : Write data buffer - * @param[in] len : No of bytes to write - * @param[in] dev : Structure instance of bma4_dev. - * - * @return Result of API execution status - * @retval 0 -> Success - * @retval Any non zero value -> Fail - */ -uint16_t bma4_write_regs(uint8_t addr, uint8_t *data, uint8_t len, struct bma4_dev *dev); - -/*! - * @brief This API checks whether the read operation requested is for - * feature or register read and accordingly reads the data from the sensor. - * - * @param[in] addr : Register address. - * @param[in] data : Read data buffer. - * @param[in] len : No of bytes to read. - * @param[in] dev : Structure instance of bma4_dev - * - * @return Result of API execution status - * @retval 0 -> Success - * @retval Any non zero value -> Fail - */ -uint16_t bma4_read_regs(uint8_t addr, uint8_t *data, uint8_t len, struct bma4_dev *dev); - -/*! - * @brief This API reads the error status from the sensor. - * - * Below table mention the types of error which can occur in the sensor - *@verbatim - ************************************************************************* - * Error | Description - *************************|*********************************************** - * | Fatal Error, chip is not in operational - * fatal | state (Boot-, power-system). - * | This flag will be reset only by - * | power-on-reset or soft reset. - *************************|*********************************************** - * cmd | Command execution failed. - *************************|*********************************************** - * | Value Name Description - * error_code | 000 no_error no error - * | 001 acc_err error in - * | ACC_CONF - *************************|*********************************************** - * | Error in FIFO detected: Input data was - * fifo | discarded in stream mode. This flag - * | will be reset when read. - *************************|*********************************************** - * mag | Error in I2C-Master detected. - * | This flag will be reset when read. - ************************************************************************* - *@endverbatim - * - * @param[in,out] err_reg : Pointer to structure variable which stores the - * error status read from the sensor. - * @param[in] dev : Structure instance of bma4_dev. - * - * @return Result of API execution status - * @retval 0 -> Success - * @retval Any non zero value -> Fail - */ -uint16_t bma4_get_error_status(struct bma4_err_reg *err_reg, struct bma4_dev *dev); - -/*! - * @brief This API reads the sensor status from the dev sensor. - * - * Below table lists the sensor status flags - * Status | Description - * ----------------------------|---------------------------------------- - * BMA4_MAG_MAN_OP_ONGOING | Manual Mag. interface operation ongoing - * BMA4_CMD_RDY | Command decoder is ready. - * BMA4_MAG_DATA_RDY | Data ready for Mag. - * BMA4_ACC_DATA_RDY | Data ready for Accel. - * - * @param[in] status : Variable used to store the sensor status flags - * which is read from the sensor. - * @param[in] dev : Structure instance of bma4_dev. - * - * @return Result of API execution status - * @retval 0 -> Success - * @retval Any non zero value -> Fail - * - */ -uint16_t bma4_get_status(uint8_t *status, struct bma4_dev *dev); - -/*! - * @brief This API reads the Accel data for x,y and z axis from the sensor. - * The data units is in LSB format. - * - * @param[in] accel : Variable used to store the Accel data which is read - * from the sensor. - * @param[in] dev : Structure instance of bma4_dev. - * - * @note For setting the Accel configuration use the below function - * bma4_set_accel_config - * - * @return Result of API execution status - * @retval 0 -> Success - * @retval Any non zero value -> Fail - * - */ -uint16_t bma4_read_accel_xyz(struct bma4_accel *accel, struct bma4_dev *dev); - -/*! - * @brief This API reads the sensor time of Sensor time gets updated - * with every update of data register or FIFO. - * - * @param[in] sensor_time : Pointer variable which stores sensor time - * @param[in] dev : Structure instance of bma4_dev. - * - * @return Result of API execution status - * @retval 0 -> Success - * @retval Any non zero value -> Fail - * - */ -uint16_t bma4_get_sensor_time(uint32_t *sensor_time, struct bma4_dev *dev); - -/*! - * @brief This API reads the chip temperature of sensor. - * @note If Accel and Mag are disabled, the temperature value will be set - * to invalid. - * - * @param[out] temp : Pointer variable which stores the temperature value. - * @param[in] temp_unit : indicates the unit of temperature - * temp_unit | description - * ------------|------------------- - * BMA4_DEG | degrees Celsius - * BMA4_FAHREN | degrees fahrenheit - * BMA4_KELVIN | degrees kelvin - * - * @param[in] dev : Structure instance of bma4_dev. - * - * @note Using a scaling factor of 1000, to obtain integer values, which - * at the user end, are used to get accurate temperature value. - * BMA4_SCALE_FARHAN = 1.8 * 1000, BMA4_SCALE_KELVIN = 273.15 * 1000 - * - * @return Result of API execution status - * @retval 0 -> Success - * @retval Any non zero value -> Fail - * - */ -uint16_t bma4_get_temperature(int32_t *temp, uint8_t temp_unit, struct bma4_dev *dev); - -/*! - * @brief This API reads the Output data rate, Bandwidth, perf_mode - * and Range of accel. - * - * @param[in,out] accel : Address of user passed structure which is used - * to store the Accel configurations read from the sensor. - * - * @note Enums and corresponding values for structure parameters like - * Odr, Bandwidth and Range are mentioned in the below tables. - * - * Value | Odr - * -----------|------------------------------------ - * 1 | BMA4_OUTPUT_DATA_RATE_0_78HZ - * 2 | BMA4_OUTPUT_DATA_RATE_1_56HZ - * 3 | BMA4_OUTPUT_DATA_RATE_3_12HZ - * 4 | BMA4_OUTPUT_DATA_RATE_6_25HZ - * 5 | BMA4_OUTPUT_DATA_RATE_12_5HZ - * 6 | BMA4_OUTPUT_DATA_RATE_25HZ - * 7 | BMA4_OUTPUT_DATA_RATE_50HZ - * 8 | BMA4_OUTPUT_DATA_RATE_100HZ - * 9 | BMA4_OUTPUT_DATA_RATE_200HZ - * 10 | BMA4_OUTPUT_DATA_RATE_400HZ - * 11 | BMA4_OUTPUT_DATA_RATE_800HZ - * 12 | BMA4_OUTPUT_DATA_RATE_1600HZ - * - * Value | accel_bw - * ------|-------------------------- - * 0 | BMA4_ACCEL_OSR4_AVG1 - * 1 | BMA4_ACCEL_OSR2_AVG2 - * 2 | BMA4_ACCEL_NORMAL_AVG4 - * 3 | BMA4_ACCEL_CIC_AVG8 - * 4 | BMA4_ACCEL_RES_AVG16 - * 5 | BMA4_ACCEL_RES_AVG32 - * 6 | BMA4_ACCEL_RES_AVG64 - * 7 | BMA4_ACCEL_RES_AVG128 - * - * Value | g_range - * --------|--------------------- - * 0x00 | BMA4_ACCEL_RANGE_2G - * 0x01 | BMA4_ACCEL_RANGE_4G - * 0x02 | BMA4_ACCEL_RANGE_8G - * 0x03 | BMA4_ACCEL_RANGE_16G - * - * @param[in] dev : Structure instance of bma4_dev - * @return Result of API execution status - * @retval 0 -> Success - * @retval Any non zero value -> Fail - * - */ -uint16_t bma4_get_accel_config(struct bma4_accel_config *accel, struct bma4_dev *dev); - -/*! - * @brief This API sets the output_data_rate, bandwidth, perf_mode - * and range of Accel. - * - * @param[in] accel : Pointer to structure variable which specifies the - * Accel configurations. - * - * @note Enums and corresponding values for structure parameters like - * Odr, Bandwidth and Range are mentioned in the below tables. - * Value | ODR - * --------|----------------------------------------- - * 1 | BMA4_OUTPUT_DATA_RATE_0_78HZ - * 2 | BMA4_OUTPUT_DATA_RATE_1_56HZ - * 3 | BMA4_OUTPUT_DATA_RATE_3_12HZ - * 4 | BMA4_OUTPUT_DATA_RATE_6_25HZ - * 5 | BMA4_OUTPUT_DATA_RATE_12_5HZ - * 6 | BMA4_OUTPUT_DATA_RATE_25HZ - * 7 | BMA4_OUTPUT_DATA_RATE_50HZ - * 8 | BMA4_OUTPUT_DATA_RATE_100HZ - * 9 | BMA4_OUTPUT_DATA_RATE_200HZ - * 10 | BMA4_OUTPUT_DATA_RATE_400HZ - * 11 | BMA4_OUTPUT_DATA_RATE_800HZ - * 12 | BMA4_OUTPUT_DATA_RATE_1600HZ - * - * Value | accel_bw - * ------|-------------------------- - * 0 | BMA4_ACCEL_OSR4_AVG1 - * 1 | BMA4_ACCEL_OSR2_AVG2 - * 2 | BMA4_ACCEL_NORMAL_AVG4 - * 3 | BMA4_ACCEL_CIC_AVG8 - * 4 | BMA4_ACCEL_RES_AVG16 - * 5 | BMA4_ACCEL_RES_AVG32 - * 6 | BMA4_ACCEL_RES_AVG64 - * 7 | BMA4_ACCEL_RES_AVG128 - * - * Value | g_range - * --------|--------------------- - * 0x00 | BMA4_ACCEL_RANGE_2G - * 0x01 | BMA4_ACCEL_RANGE_4G - * 0x02 | BMA4_ACCEL_RANGE_8G - * 0x03 | BMA4_ACCEL_RANGE_16G - * - * @param[in] dev : Structure instance of bma4_dev - * - * @return Result of API execution status - * @retval 0 -> Success - * @retval Any non zero value -> Fail - * - */ -uint16_t bma4_set_accel_config(const struct bma4_accel_config *accel, struct bma4_dev *dev); - -/*! - * @brief This API sets the advance power save mode in the sensor. - * - * @note If advanced power save is enabled and the Accel and/or - * magnetometer operate in duty cycling mode, the length of the unlatched - * DRDY interrupt pulse is longer than 1/3.2 kHz (312.5 us). - * - * @param[in] adv_pwr_save : The value of advance power save mode - * @param[in] dev : Structure instance of bma4_dev. - * - * @return Result of API execution status - * @retval 0 -> Success - * @retval Any non zero value -> Fail - * - */ -uint16_t bma4_set_advance_power_save(uint8_t adv_pwr_save, - struct bma4_dev *dev); - -/*! - * @brief This API reads the status of advance power save mode - * from the sensor. - * - * @note If the advanced power save is enabled and the Accel and/or - * magnetometer operate in duty cycling mode, the length of the unlatched - * DRDY interrupt pulse is longer than 1/3.2 kHz (312.5 us). - * - * @param[out] adv_pwr_save : The value of advance power save mode - * @param[in] dev : Structure instance of bma4_dev. - * - * @return Result of API execution status - * @retval 0 -> Success - * @retval Any non zero value -> Fail - * - */ -uint16_t bma4_get_advance_power_save(uint8_t *adv_pwr_save, struct bma4_dev *dev); - -/*! - * @brief This API sets the FIFO self wake up functionality in the sensor. - * - * @note Functionality related to FIFO self wake up depends upon the - * advance power save mode. for more info. refer data sheet. - * - * @param[in] fifo_self_wakeup : Variable used to enable or disable - * FIFO self wake up functionality. - * @param[in] dev : Structure instance of bma4_dev. - * - * @return Result of API execution status - * @retval 0 -> Success - * @retval Any non zero value -> Fail - * - */ -uint16_t bma4_set_fifo_self_wakeup(uint8_t fifo_self_wakeup, struct bma4_dev *dev); - -/*! - * @brief This API gets the status of FIFO self wake up functionality from - * the sensor. - * - * @note Functionality related to FIFO self wake up depends upon the - * advance power save mode. for more info. refer data sheet. - * - * @param[out] fifo_self_wake_up : Pointer variable used to store the - * fifo self wake up status. - * @param[in] dev : Structure instance of bma4_dev. - * - * @return Result of API execution status - * @retval 0 -> Success - * @retval Any non zero value -> Fail - * - */ -uint16_t bma4_get_fifo_self_wakeup(uint8_t *fifo_self_wake_up, struct bma4_dev *dev); - -/*! - * @brief This API enables or disables the Accel in the sensor. - * - * @note Before reading Accel data, user should call this API. - * - * @param[in] accel_en : Variable used to enable or disable the Accel. - * @param[in] dev : Structure instance of bma4_dev. - * - * @return Result of API execution status - * @retval 0 -> Success - * @retval Any non zero value -> Fail - * - */ -uint16_t bma4_set_accel_enable(uint8_t accel_en, struct bma4_dev *dev); - -/*! - * @brief This API checks whether Accel is enabled or not in the sensor. - * - * @param[out] accel_en : Pointer variable used to store the Accel enable - * status - * @param[in] dev : Structure instance of bma4_dev. - * - * @return Result of API execution status - * @retval 0 -> Success - * @retval Any non zero value -> Fail - * - */ -uint16_t bma4_get_accel_enable(uint8_t *accel_en, struct bma4_dev *dev); - -/*! - * @brief This API is used to enable or disable auxiliary Mag - * in the sensor. - * - * @note Before reading Mag data, user should call this API. - * - * @param[in] mag_en : Variable used to enable or disable the Mag. - * @param[in] dev : Structure instance of bma4_dev. - * - * @return Result of API execution status - * @retval 0 -> Success - * @retval Any non zero value -> Fail - * - */ -uint16_t bma4_set_mag_enable(uint8_t mag_en, struct bma4_dev *dev); - -/*! - * @brief This API is used to check whether the auxiliary Mag is enabled - * or not in the sensor. - * - * @param[out] mag_en : Pointer variable used to store the enable status of - * Mag in the sensor. - * @param[in] dev : Structure instance of bma4_dev. - * - * @return Result of API execution status - * @retval 0 -> Success - * @retval Any non zero value -> Fail - * - */ -uint16_t bma4_get_mag_enable(uint8_t *mag_en, struct bma4_dev *dev); - -/*! - * @brief This API reads the SPI interface mode which is set for primary - * interface. - * - * @param[out] spi : Pointer variable which stores the SPI mode selection - * Value | Description - * --------|------------------ - * 0 | SPI 4-wire mode - * 1 | SPI 3-wire mode - * @param[in] dev : Structure instance of bma4_dev. - * - * @return Result of API execution status - * @retval 0 -> Success - * @retval Any non zero value -> Fail - * - */ -uint16_t bma4_get_spi_interface(uint8_t *spi, struct bma4_dev *dev); - -/*! - * @brief This API configures the SPI interface Mode for primary interface - * - * @param[in] spi : The value of SPI mode selection - * Value | Description - * --------|------------------ - * 0 | SPI 4-wire mode - * 1 | SPI 3-wire mode - * - * @param[in] dev : Structure instance of bma4_dev. - * - * @return Result of API execution status - * @retval 0 -> Success - * @retval Any non zero value -> Fail - * - */ -uint16_t bma4_set_spi_interface(uint8_t spi, struct bma4_dev *dev); - - /*! - * @brief This API writes the available sensor specific commands - * to the sensor. - * - * @param[in] command_reg : The command to write to the command register. - *@verbatim - * value | Description - * --------|------------------------------------------------------ - * 0xB6 | Triggers a soft reset - * 0xB0 | Clears all data in the FIFO, does not change - * | FIFO_CONFIG and FIFO_DOWNS registers - * 0xF0 | Reset acceleration data path - *@endverbatim - * @param[in] dev : Structure instance of bma4_dev. - * - * @note Register will always read as 0x00 - * - * @return Result of API execution status - * @retval 0 -> Success - * @retval Any non zero value -> Fail - * - */ -uint16_t bma4_set_command_register(uint8_t command_reg, struct bma4_dev *dev); - -/*! - * @brief This API sets the I2C device address of auxiliary sensor - * - * @param[in] dev : Structure instance of bma4_dev. - * - * @return Result of API execution status - * @retval 0 -> Success - * @retval Any non zero value -> Fail - * - */ -uint16_t bma4_set_i2c_device_addr(struct bma4_dev *dev); - -/*! - * @brief This API sets the register access on MAG_IF[2], MAG_IF[3], - * MAG_IF[4] in the sensor. This implies that the DATA registers are - * not updated with Mag values automatically. - * - * @param[in] mag_manual : Variable used to specify the Mag manual - * enable status. - * value | mag manual - * ---------|-------------------- - * 0x01 | BMA4_ENABLE - * 0x00 | BMA4_DISABLE - * - * @param[out] dev : Structure instance of bma4_dev. - * - * @return Result of API execution status - * @retval 0 -> Success - * @retval Any non zero value -> Fail - * - */ -uint16_t bma4_set_mag_manual_enable(uint8_t mag_manual, struct bma4_dev *dev); - -/*! - * @brief This API checks whether the Mag access is done manually or - * automatically in the sensor. - * If the Mag access is done through manual mode then Mag data registers - * in sensor are not updated automatically. - * - * @param[out] mag_manual : Mag manual enable value - * value | mag_manual - * --------|------------------- - * 0x01 | BMA4_ENABLE - * 0x00 | BMA4_DISABLE - * @param[in] dev : Structure instance of bma4_dev - * - * @return Result of API execution status - * @retval 0 -> Success - * @retval Any non zero value -> Fail - * - */ -uint16_t bma4_get_mag_manual_enable(uint8_t *mag_manual, struct bma4_dev *dev); - -/*! - * @brief This API sets the I2C interface configuration(if) mode - * for auxiliary Mag. - * - * @param[in] if_mode : The value of interface configuration mode - * Value | Description - * ------------|------------------------------------------- - * 0 | p_auto_s_off Auxiliary interface:off - * 1 | p_auto_s_mag Auxiliary interface:on - * @param[in] dev : Structure instance of bma4_dev. - * - * @return Result of API execution status - * @retval 0 -> Success - * @retval Any non zero value -> Fail - * - */ -uint16_t bma4_set_aux_if_mode(uint8_t if_mode, struct bma4_dev *dev); - -/*! - * @brief This API gets the address of the register of Aux Mag sensor - * where the data to be read. - * - * @param[out] mag_read_addr : Pointer variable used to store the - * mag read address. - * @param[in] dev : Structure instance of bma4_dev. - * - * @return Result of API execution status - * @retval 0 -> Success - * @retval Any non zero value -> Fail - * - */ -uint16_t bma4_get_mag_read_addr(uint8_t *mag_read_addr, struct bma4_dev *dev); - -/*! - * @brief This API sets the address of the register of Aux Mag sensor - * where the data to be read. - * - * @param[in] mag_read_addr: Value of Mag. read address in order to read - * the data from the auxiliary Mag. - * @param[in] dev : Structure instance of bma4_dev. - * - * @return Result of API execution status - * @retval 0 -> Success - * @retval Any non zero value -> Fail - * - */ -uint16_t bma4_set_mag_read_addr(uint8_t mag_read_addr, struct bma4_dev *dev); - -/*! - * @brief This API gets the Aux Mag write address from the sensor. - * Mag write address is where the Mag data will be written. - * - * @param[out] mag_write_addr: Pointer used to store the Mag write address - * which is read from the sensor. - * @param[in] dev : Structure instance of bma4_dev - * - * @return Result of API execution status - * @retval 0 -> Success - * @retval Any non zero value -> Fail - * - */ -uint16_t bma4_get_mag_write_addr(uint8_t *mag_write_addr, struct bma4_dev *dev); - -/*! - * @brief This API sets the Aux Mag write address in the sensor. - * Mag write address is where the Mag data will be written. - * - * @param[in] mag_write_addr: Write address of Mag where the data will - * be written. - * @param[out] dev : Structure instance of bma4_dev - * - * @return Result of API execution status - * @retval 0 -> Success - * @retval Any non zero value -> Fail - * - */ -uint16_t bma4_set_mag_write_addr(uint8_t mag_write_addr, struct bma4_dev *dev); - -/*! - * @brief This API reads the data from the sensor which is written to the - * Mag. - * - * @param[out] mag_write_data: Pointer variable which stores the - * data which is written in Mag through sensor. - * @param[in] dev : Structure instance of bma4_dev - * - * @return Result of API execution status - * @retval 0 -> Success - * @retval Any non zero value -> Fail - * - */ -uint16_t bma4_get_mag_write_data(uint8_t *mag_write_data, struct bma4_dev *dev); - -/*! - * @brief This API sets the data in the sensor which in turn will - * be written to Mag. - * - * @param[in] mag_write_data: variable which specify the data which is to - * be written in Mag. - * @param[out] dev : Structure instance of bma4_dev - * - * @return Result of API execution status - * @retval 0 -> Success - * @retval Any non zero value -> Fail - * - */ -uint16_t bma4_set_mag_write_data(uint8_t mag_write_data, struct bma4_dev *dev); - -/*! - * @brief This API reads the x,y,z and r axis data from the auxiliary - * Mag BMM150/AKM9916 sensor. - * - * @param[out] mag : Pointer variable to store the auxiliary Mag x,y,z - * and r axis data read from the sensor. - * @param[in] dev : Structure instance of bma4_dev - * - * @return Result of API execution status - * @retval 0 -> Success - * @retval Any non zero value -> Fail - * - */ -uint16_t bma4_read_mag_xyzr(struct bma4_mag_xyzr *mag, struct bma4_dev *dev); - -/*! - * @brief This API sets the burst data length (1,2,6,8 byte) of auxiliary - * Mag sensor. - * - * @param[in] mag_burst : Variable used to specify the Mag burst read length - * @param[in] dev : Structure instance of bma4_dev - * - * @return Result of API execution status - * @retval 0 -> Success - * @retval Any non zero value -> Fail - * - */ -uint16_t bma4_set_mag_burst(uint8_t mag_burst, struct bma4_dev *dev); - -/*! - * @brief This API reads the burst data length of Mag set in the sensor. - * - * @param[out] mag_burst : Pointer variable used to store the burst length - * @param[in] dev : Structure instance of bma4_dev - * - * @return Result of API execution status - * @retval 0 -> Success - * @retval Any non zero value -> Fail - * - */ -uint16_t bma4_get_mag_burst(uint8_t *mag_burst, struct bma4_dev *dev); - -/*! - * @brief This API reads the FIFO data of Accel and/or Mag sensor - * - * @param dev : Structure instance of bma4_dev - * - * @return Result of API execution status - * @retval 0 -> Success - * @retval Any non zero value -> Fail - * - */ -uint16_t bma4_read_fifo_data(struct bma4_dev *dev); - -/*! - * @brief This API reads the FIFO water mark level which is set - * in the sensor. - * - * @note The FIFO watermark is issued when the FIFO fill level is - * equal or above the watermark level. - * - * @param[out] fifo_wm : Pointer variable to store FIFO water mark level - * @param[in] dev : Structure instance of bma4_dev - * - * @return Result of API execution status - * @retval 0 -> Success - * @retval Any non zero value -> Fail - * - */ -uint16_t bma4_get_fifo_wm(uint16_t *fifo_wm, struct bma4_dev *dev); - -/*! - * @brief This API sets the FIFO watermark level in the sensor. - * - * @note The FIFO watermark is issued when the FIFO fill level is - * equal or above the watermark level. - * - * @param[in] fifo_wm : Variable used to set the FIFO water mark level - * @param[out] dev : Structure instance of bma4_dev - * - * @return Result of API execution status - * @retval 0 -> Success - * @retval Any non zero value -> Fail - * - */ -uint16_t bma4_set_fifo_wm(uint16_t fifo_wm, struct bma4_dev *dev); - -/*! - * @brief This API checks whether the Accel FIFO data is set for filtered - * or unfiltered mode. - * - * @param[out] accel_fifo_filter : Variable used to check whether the Accel - * data is filtered or unfiltered. - * Value | accel_fifo_filter - * ---------|------------------------- - * 0x00 | Unfiltered data - * 0x01 | Filtered data - * @param[in] dev : structure instance of bma4_dev - * - * @return Result of API execution status - * @retval 0 -> Success - * @retval Any non zero value -> Fail - * - */ -uint16_t bma4_get_accel_fifo_filter_data(uint8_t *accel_fifo_filter, struct bma4_dev *dev); - -/*! - * @brief This API sets the condition of Accel FIFO data either to - * filtered or unfiltered mode. - * - * @param[in] accel_fifo_filter : Variable used to set the filtered or - * unfiltered condition of Accel FIFO data. - * value | accel_fifo_filter_data - * -----------|------------------------- - * 0x00 | Unfiltered data - * 0x01 | Filtered data - * @param[out] dev : Structure instance of bma4_dev - * - * @return Result of API execution status - * @retval 0 -> Success - * @retval Any non zero value -> Fail - * - */ -uint16_t bma4_set_accel_fifo_filter_data(uint8_t accel_fifo_filter, struct bma4_dev *dev); - -/*! - * @brief This API reads the down sampling rates which is configured - * for Accel FIFO data. - * - * @param[out] fifo_down : Variable used to specify the Accel FIFO - * down-sampling rates - * @param[in] dev : Structure instance of bma4_dev - * - * @return Result of API execution status - * @retval 0 -> Success - * @retval Any non zero value -> Fail - * - */ -uint16_t bma4_get_fifo_down_accel(uint8_t *fifo_down, struct bma4_dev *dev); - -/*! - * @brief This API sets the down-sampling rates for Accel FIFO. - * - * @param[in] fifo_down : Variable used to specify the Accel FIFO - * down-sampling rates. - * @param[in] dev : structure instance of bma4_dev - * - * @return Result of API execution status - * @retval 0 -> Success - * @retval Any non zero value -> Fail - * - */ -uint16_t bma4_set_fifo_down_accel(uint8_t fifo_down, struct bma4_dev *dev); - -/*! - * @brief This API reads the length of FIFO data available in the sensor - * in the units of bytes. - * - * @note This byte counter is updated each time a complete frame was read - * or written - * - * @param[in] fifo_length : Pointer variable used to store the value of - * fifo byte counter - * @param[in] dev : Structure instance of bma4_dev - * - * @return Result of API execution status - * @retval 0 -> Success - * @retval Any non zero value -> Fail - * - */ -uint16_t bma4_get_fifo_length(uint16_t *fifo_length, struct bma4_dev *dev); - -/*! - * @brief This API aligns and compensates the Mag data of BMM150/AKM9916 - * sensor. - * - * @param[in] mag_fifo_data: Structure object which stores the Mag x,yand z - * axis FIFO data which is to be aligned and/or compensated. - * @param[in] mag_second_if: Variable used to select the Mag sensor. - * Value | mag_second_if - * --------|---------------------- - * 1 | BMA4_SEC_IF_BMM150 - * 2 | BMA4_SEC_IF_AKM09916 - * - * @param[out] compensated_mag_data: Pointer variable used to store the - * compensated Mag xyz axis data - * - * @return Result of API execution status - * @retval 0 -> Success - * @retval Any non zero value -> Fail - * - */ -uint16_t bma4_second_if_mag_compensate_xyz(struct bma4_mag_fifo_data mag_fifo_data, - uint8_t mag_second_if, - struct bma4_mag *compensated_mag_data); - -/*! - * @brief This API reads Mag. x,y and z axis data from either BMM150 or - * AKM9916 sensor - * - * @param[out] mag : Structure pointer used to store the Mag x,y, and z axis - * data read from the sensor. - * - * @param[in] sensor_select : Variable used to select the Mag sensor - * Value | Sensor - * ---------|---------------------- - * 0 | BMA4_SEC_IF_NULL - * 1 | BMA4_SEC_IF_BMM150 - * 2 | BMA4_SEC_IF_AKM09916 - * @param[in] dev : Structure instance of bma4_dev - * - * @return Result of API execution status - * @retval 0 -> Success - * @retval Any non zero value -> Fail - * - */ -uint16_t bma4_read_mag_xyz(struct bma4_mag *mag, uint8_t sensor_select, struct bma4_dev *dev); - -/*! - * @brief This API reads the auxiliary I2C interface configuration which - * is set in the sensor. - * - * @param[out] if_mode : Pointer variable used to store the auxiliary - * interface configuration. - * Value | Description - * ----- |---------------------------------- - * 0x00 | auxiliary interface:off - * 0x01 | auxiliary interface:on - * @param[in] dev : Structure instance of bma4_dev - * - * @return Result of API execution status - * @retval 0 -> Success - * @retval Any non zero value -> Fail - * - */ -uint16_t bma4_get_if_mode(uint8_t *if_mode, struct bma4_dev *dev); - -/*! - * @brief This API sets the auxiliary interface configuration in the sensor. - * - * @param[in] if_mode : Variable used to select the auxiliary interface - * configuration. - * Value | Description - * ----- |-------------------------- - * 0x00 | auxiliary interface:off - * 0x01 | auxiliary interface:on - * - * @param[in] dev : Structure instance of bma4_dev - * - * @return Result of API execution status - * @retval 0 -> Success - * @retval Any non zero value -> Fail - * - */ -uint16_t bma4_set_if_mode(uint8_t if_mode, struct bma4_dev *dev); - -/*! - * @brief This API reads the data ready status of Accel from the sensor. - * @note The status get reset when Accel data register is read. - * - * @param[out] data_rdy : Pointer variable to store the data ready status - * @param[in] dev : structure instance of bma4_dev - * - * @return Result of API execution status - * @retval 0 -> Success - * @retval Any non zero value -> Fail - * - */ -uint16_t bma4_get_accel_data_rdy(uint8_t *data_rdy, struct bma4_dev *dev); - -/*! - * @brief This API reads the data ready status of Mag from the sensor. - * The status get reset when Mag data register is read. - * - * @param[out] data_rdy : Pointer variable to store the data ready status - * @param[in] dev : Structure instance of bma4_dev - * - * @return Result of API execution status - * @retval 0 -> Success - * @retval Any non zero value -> Fail - * - */ -uint16_t bma4_get_mag_data_rdy(uint8_t *data_rdy, struct bma4_dev *dev); - -/*! - * @brief This API reads the ASIC status from the sensor. - * The status information is mentioned in the below table. - * - *@verbatim - ******************************************************************************* - * Status | Description - **************************|**************************************************** - * sleep | ASIC is in sleep/halt state. - * irq_ovrn | Dedicated interrupt is set again before previous - * | interrupt was acknowledged. - * wc_event | Watchcell event detected (ASIC stopped). - * stream_transfer_active | stream transfer has started. - ******************************************************************************* - *@endverbatim - * - * @param[out] asic_status : Structure pointer used to store the ASIC - * status read from the sensor. - * @param[in] dev : Structure instance of bma4_dev - * - * @return Result of API execution status - * @retval 0 -> Success - * @retval Any non zero value -> Fail - * - */ -uint16_t bma4_get_asic_status(struct bma4_asic_status *asic_status, struct bma4_dev *dev); - -/*! - * @brief This API enables the offset compensation for filtered and - * unfiltered Accel data. - * - * @param[in] offset_en : Variable used to enable or disable offset - * compensation - * offset_en | Description - * ------------|---------------------- - * 0 | BMA4_DISABLE - * 1 | BMA4_ENABLE - * - * @param[in] dev : Structure instance of bma4_dev - * - * @return Result of API execution status - * @retval 0 -> Success - * @retval Any non zero value -> Fail - * - */ -uint16_t bma4_set_offset_comp(uint8_t offset_en, struct bma4_dev *dev); - -/*! - * @brief This API gets the status of Accel offset compensation - * - * @param[out] offset_en : Pointer variable used to store the Accel offset - * enable or disable status. - * offset_en | Description - * ----------|-------------- - * 0 | BMA4_DISABLE - * 1 | BMA4_ENABLE - * - * @param[in] dev : Structure instance of bma4_dev - * - * @return Result of API execution status - * @retval 0 -> Success - * @retval Any non zero value -> Fail - * - */ -uint16_t bma4_get_offset_comp(uint8_t *offset_en, struct bma4_dev *dev); - -/*! - * @brief This API parses and extracts the accelerometer frames from - * FIFO data read by the "bma4_read_fifo_data" API and stores it in the - * "accel_data" structure instance. - * - * @note The bma4_extract_accel API should be called only after reading - * the FIFO data by calling the bma4_read_fifo_data() API - * - * @param[in,out] accel_data : Structure instance of bma4_accel where - * the accelerometer data in FIFO is stored. - * @param[in,out] accel_length : Number of accelerometer frames - * (x,y,z axes data) - * @param[in,out] dev : Structure instance of bma4_dev. - * - * @note accel_length has the number of accelerometer frames - * (1 accel frame = 6 bytes) which the user needs to extract and store is - * provided as input parameter by the user and the Number of valid - * accelerometer frames extracted and stored is updated in - * "accel_length" at the end of execution of this API. - * - * @return Result of API execution status - * @retval 0 -> Success - * @retval Any non zero value -> Fail - * - */ -uint16_t bma4_extract_accel(struct bma4_accel *accel_data, uint16_t *accel_length, const struct bma4_dev *dev); - -/*! - * @brief This API parses and extracts the magnetometer frames from - * FIFO data read by the "bma4_read_fifo_data" API and stores it in the - * "mag_data" structure instance parameter of this API - * - * @note The bma4_extract_mag API should be called only after reading - * the FIFO data by calling the bma4_read_fifo_data() API - * - * @param[in,out] mag_data : Structure instance of bma4_mag_xyzr where - * the magnetometer data in FIFO is stored. - * @param[in,out] mag_length : Number of magnetometer frames (x,y,z,r data) - * @param[in,out] dev : Structure instance of bma4_dev. - * - * @note mag_length has the number of magnetometer frames(x,y,z,r data) - * (1 mag frame = 8 bytes) which the user needs to extract and store,It is - * provided as input parameter by the user and the number of valid - * magnetometer frames extracted and stored is updated in - * "mag_length" at the end of execution of this API. - * - * @return Result of API execution status - * @retval 0 -> Success - * @retval Any non zero value -> Fail - * - */ -uint16_t bma4_extract_mag(struct bma4_mag *mag_data, uint16_t *mag_length, const struct bma4_dev *dev); - -/*! - * @brief This API performs Fast Offset Compensation for Accel. - * @param[in] accel_g_value : Array which stores the Accel g units - * for x,y and z axis. - * accel_g_value | Description - * --------------------------|--------------------------------------- - * accel_g_value[0] | x axis g units - * accel_g_value[1] | y axis g units - * accel_g_value[2] | z axis g units - * - * @param[in] dev : structure instance of dev - * - * @note The g-values to be passed to the parameter should be - * multiples of 1000000. - * - * @return Result of API execution status - * @retval 0 -> Success - * @retval Any non zero value -> Fail - * - */ -uint16_t bma4_perform_accel_foc(const int32_t accel_g_value[3], struct bma4_dev *dev); -/*! - * @brief This API checks whether the self test functionality of the sensor - * is working or not - * - * @param[in] result : Pointer variable used to store the result of self test - * operation - * result | Description - * ---------|-------------------- - * 0x00 | BMA4_SELFTEST_PASS - * 0x01 | BMA4_SELFTEST_FAIL - * @param[in] dev : Structure instance of bma4_dev - * - * @return results of self test - * @retval 0 -> Success - * @retval Any non zero value -> Fail - * - */ -uint16_t bma4_perform_accel_selftest(uint8_t *result, struct bma4_dev *dev); - -/*! - * @brief This API performs the steps needed for Self test operation - * before reading the Accel Self test data. - * - * @param[in] sign: Variable used to specify the self test sign - * @param[in] dev : Structure instance of bma4_dev - * - * @return results of self test - * @retval 0 -> Success - * @retval Any non zero value -> Fail - * - */ -uint16_t bma4_selftest_config(uint8_t sign, struct bma4_dev *dev); - -/*! - * @brief API sets the interrupt to either interrupt1 or - * interrupt2 pin in the sensor. - * - * @param[in] int_line: Variable used to select interrupt pin1 or pin2 - * int_line | interrupt selection - * ---------|------------------- - * 0 | BMA4_INTR1_MAP - * 1 | BMA4_INTR2_MAP - * - * @param[in] int_map: Variable used to select a particular interrupt - * in the sensor - * - * @param[in] enable : Variable used to enable or disable the interrupt - * Value | Behaviour - * ---------|------------------- - * 0x01 | BMA4_ENABLE - * 0x00 | BMA4_DISABLE - * - * @param[in] dev : Structure instance of bma4_dev - * - * @return Result of API execution status - * @retval 0 -> Success - * @retval Any non zero value -> Fail - * - */ -uint16_t bma4_map_interrupt(uint8_t int_line, uint16_t int_map, uint8_t enable, struct bma4_dev *dev); - -/*! - * @brief This API sets the interrupt mode in the sensor. - * - * @param[in] mode: Variable used to specify the interrupt mode which - * is to be set in the sensor. - * Mode | Value - * ----------------------- |--------- - * BMA4_NON_LATCH_MODE | 0 - * BMA4_LATCH_MODE | 1 - * - * @param[in] dev : Structure instance of bma4_dev - * - * @return status of bus communication function - * @retval 0 -> Success - * @retval Any non zero value -> Fail - * - */ -uint16_t bma4_set_interrupt_mode(uint8_t mode, struct bma4_dev *dev); - -/*! - * @brief This API gets the interrupt mode which is set in the sensor. - * - * @param[out] mode: Pointer variable used to store the interrupt mode set in - * in the sensor. - * Mode | Value - * ---------------------|--------------- - * BMA4_NON_LATCH_MODE | 0 - * BMA4_LATCH_MODE | 1 - * - * @param[in] dev : Structure instance of bma4_dev - * - * @return status of bus communication function - * @retval 0 -> Success - * @retval Any non zero value -> Fail - * - */ -uint16_t bma4_get_interrupt_mode(uint8_t *mode, struct bma4_dev *dev); - -/*! - * @brief This API sets the auxiliary Mag(BMM150 or AKM9916) output data - * rate and offset. - * - * @param[in] aux_mag : Pointer to structure variable used to specify - * the auxiliary Mag configuration. - *@verbatim - *------------------------------------------------------------------------------ - * Odr | Value - *----------------------------------------|--------------------------------- - * BMA4_OUTPUT_DATA_RATE_0_78HZ | 0x01 - * BMA4_OUTPUT_DATA_RATE_1_56HZ | 0x02 - * BMA4_OUTPUT_DATA_RATE_3_12HZ | 0x03 - * BMA4_OUTPUT_DATA_RATE_6_25HZ | 0x04 - * BMA4_OUTPUT_DATA_RATE_12_5HZ | 0x05 - * BMA4_OUTPUT_DATA_RATE_25HZ | 0x06 - * BMA4_OUTPUT_DATA_RATE_50HZ | 0x07 - * BMA4_OUTPUT_DATA_RATE_100HZ | 0x08 - * BMA4_OUTPUT_DATA_RATE_200HZ | 0x09 - * BMA4_OUTPUT_DATA_RATE_400HZ | 0x0A - * BMA4_OUTPUT_DATA_RATE_800HZ | 0x0B - * BMA4_OUTPUT_DATA_RATE_1600HZ | 0x0C - *------------------------------------------------------------------------------ - * Offset | Value - *--------------------------------------------|--------------------------------- - * BMA4_MAG_OFFSET_MAX | 0x00 - *--------------------------------------------|--------------------------------- - @endverbatim - * @param[in] dev : Structure instance of bma4_dev - * - * @return status of bus communication function - * @retval 0 -> Success - * @retval Any non zero value -> Fail - * - */ -uint16_t bma4_set_aux_mag_config(const struct bma4_aux_mag_config *aux_mag, struct bma4_dev *dev); - -/*! - * @brief This API reads the auxiliary Mag(BMM150 or AKM9916) output data - * rate and offset. - * @note : Valid output data rates are mentioned in the below table - * - * @param[out] aux_mag : Pointer to structure variable used to store the - * auxiliary Mag configuration read from the sensor - *@verbatim - *------------------------------------------------------------------------ - * Odr | Value - *----------------------------------------|------------------------------- - * BMA4_OUTPUT_DATA_RATE_0_78HZ | 0x01 - * BMA4_OUTPUT_DATA_RATE_1_56HZ | 0x02 - * BMA4_OUTPUT_DATA_RATE_3_12HZ | 0x03 - * BMA4_OUTPUT_DATA_RATE_6_25HZ | 0x04 - * BMA4_OUTPUT_DATA_RATE_12_5HZ | 0x05 - * BMA4_OUTPUT_DATA_RATE_25HZ | 0x06 - * BMA4_OUTPUT_DATA_RATE_50HZ | 0x07 - * BMA4_OUTPUT_DATA_RATE_100HZ | 0x08 - * BMA4_OUTPUT_DATA_RATE_200HZ | 0x09 - * BMA4_OUTPUT_DATA_RATE_400HZ | 0x0A - * BMA4_OUTPUT_DATA_RATE_800HZ | 0x0B - * BMA4_OUTPUT_DATA_RATE_1600HZ | 0x0C - *------------------------------------------------------------------------- - * Offset | Value - *----------------------------------------|-------------------------------- - * BMA4_MAG_OFFSET_MAX | 0x00 - *------------------------------------------------------------------------- - @endverbatim - * @param[in] dev : Structure instance of bma4_dev - * - * @return status of bus communication function - * @retval 0 -> Success - * @retval Any non zero value -> Fail - * - */ -uint16_t bma4_get_aux_mag_config(struct bma4_aux_mag_config *aux_mag, struct bma4_dev *dev); - -/*! @brief This API sets the FIFO configuration in the sensor. - * - * @param[in] config : Enum variable used to specify the FIFO - * configurations which are to be enabled or disabled in the sensor. - * - * @note : User can set either one or more or all FIFO configurations - * by ORing the below mentioned enums. - * config | Value - * ------------------------|--------------------------- - * BMA4_FIFO_STOP_ON_FULL | 0x01 - * BMA4_FIFO_TIME | 0x02 - * BMA4_FIFO_TAG_INTR2 | 0x04 - * BMA4_FIFO_TAG_INTR1 | 0x08 - * BMA4_FIFO_HEADER | 0x10 - * BMA4_FIFO_MAG | 0x20 - * BMA4_FIFO_ACCEL | 0x40 - * BMA4_FIFO_ALL | 0x7F - * - * @param[in] enable : Parameter used to enable or disable the above - * FIFO configuration - * @param[in] dev : Structure instance of bma4_dev. - * - * @return status of bus communication result - * @retval 0 -> Success - * @retval Any non zero value -> Fail - * - */ -uint16_t bma4_set_fifo_config(uint8_t config, uint8_t enable, struct bma4_dev *dev); - -/*! @brief This API reads the FIFO configuration from the sensor. - * - * @param[in] fifo_config : Enum variable used to get the below fifo - * configuration from the sensor. - * - * @note After calling this function user should do the AND operation with - * the enum value populated by this function to know which FIFO - * configuration is enabled. - * fifo_config | Value - * -------------------------|-------------------------- - * BMA4_FIFO_STOP_ON_FULL | 0x01 - * BMA4_FIFO_TIME | 0x02 - * BMA4_FIFO_TAG_INTR2 | 0x04 - * BMA4_FIFO_TAG_INTR1 | 0x08 - * BMA4_FIFO_HEADER | 0x10 - * BMA4_FIFO_MAG | 0x20 - * BMA4_FIFO_ACCEL | 0x40 - * BMA4_FIFO_ALL | 0x7F - * - * - * @param[in] dev : Structure instance of bma4_dev - * - * @return status of bus communication function - * @retval 0 -> Success - * @retval Any non zero value -> Fail - * - */ -uint16_t bma4_get_fifo_config(uint8_t *fifo_config, struct bma4_dev *dev); - -/*! @brief This function sets the electrical behaviour of interrupt pin1 or - * pin2 in the sensor. - * - * @param[in] int_pin_config : Pointer to structure variable which specifies - * the configuration data of either interrupt pin1 or 2. - *@verbatim - * ************************************************************************ - * Structure field members | Macros - * ********************************|*************************************** - * edge_ctrl | BMA4_LEVEL_TRIGGER(0) - * | BMA4_EDGE_TRIGGER(1) - * ********************************|*************************************** - * lvl | BMA4_ACTIVE_LOW(0) - * | BMA4_ACTIVE_HIGH(1) - * ********************************|*************************************** - * od | BMA4_PUSH_PULL(0) - * | BMA4_OPEN_DRAIN(1) - * ********************************|*************************************** - * output_en | BMA4_OUTPUT_DISABLE(0) - * | BMA4_OUTPUT_ENABLE(1) - * ********************************|*************************************** - * input_en | BMA4_INPUT_DISABLE(0) - * | BMA4_INPUT_ENABLE(1) - * ************************************************************************ - *@endverbatim - * @param[in] int_line : Variable used to select the interrupt pin1 or - * pin2 for interrupt configuration. - * int_line | Value - * ----------------|---------------------- - * BMA4_INTR1_MAP | 0 - * BMA4_INTR2_MAP | 1 - * - * @param[in] dev : Structure instance of bma4_dev - * - * @return status of bus communication function - * @retval 0 -> Success - * @retval Any non zero value -> Fail - */ -uint16_t bma4_set_int_pin_config(const struct bma4_int_pin_config *int_pin_config, uint8_t int_line, - struct bma4_dev *dev); - -/*! @brief This API reads the electrical behavior of interrupt pin1 or pin2 - * from the sensor. - * - * @param[out] int_pin_config : Pointer to structure variable which stores the - * configuration data of either interrupt pin1 or pin2 read from the sensor - *@verbatim - * ************************************************************************ - * Structure field members | Macros - * ************************|*********************************************** - * edge_ctrl | BMA4_LEVEL_TRIGGER(0) - * | BMA4_EDGE_TRIGGER(1) - * ************************|*********************************************** - * lvl | BMA4_ACTIVE_LOW(0) - * | BMA4_ACTIVE_HIGH(1) - * ************************|*********************************************** - * od | BMA4_PUSH_PULL(0) - * | BMA4_OPEN_DRAIN(1) - * ************************|*********************************************** - * output_en | BMA4_OUTPUT_DISABLE(0) - * | BMA4_OUTPUT_ENABLE(1) - * ************************|*********************************************** - * input_en | BMA4_INPUT_DISABLE(0) - * | BMA4_INPUT_ENABLE(1) - * ************************************************************************ - *@endverbatim - * @param[in] int_line : Variable used to select the interrupt pin1 or - * pin2 for interrupt configuration. - * int_line | Value - * -------------------|--------------- - * BMA4_INTR1_MAP | 0 - * BMA4_INTR2_MAP | 1 - * - * @param[in] dev : Structure instance of bma4_dev - * - * @return status of bus communication function - * @retval 0 -> Success - * @retval Any non zero value -> Fail - * - */ -uint16_t bma4_get_int_pin_config(struct bma4_int_pin_config *int_pin_config, uint8_t int_line, struct bma4_dev *dev); - -/*! - * @brief This API reads the Feature and Hardware interrupt status from the sensor. - * - * @param[out] int_status : Variable used to get the interrupt status. - * @param[in] dev : Structure instance of bma4_dev. - * - * @return Result of API execution status - * @retval 0 -> Success - * @retval Any non zero value -> Fail - * - */ -uint16_t bma4_read_int_status(uint16_t *int_status, struct bma4_dev *dev); - -/*! - * @brief This API reads the Feature interrupt status from the sensor. - * - * @param[out] int_status_0 : Variable used to get the interrupt status. - * @param[in] dev : Structure instance of bma4_dev. - * - * @return Result of API execution status - * @retval 0 -> Success - * @retval Any non zero value -> Fail - * - */ -uint16_t bma4_read_int_status_0(uint8_t *int_status_0, struct bma4_dev *dev); - -/*! - * @brief This API reads the Hardware interrupt status from the sensor. - * - * @param[out] int_status_1 : Variable used to get the interrupt status. - * @param[in] dev : Structure instance of bma4_dev. - * - * @return Result of API execution status - * @retval 0 -> Success - * @retval Any non zero value -> Fail - * - */ -uint16_t bma4_read_int_status_1(uint8_t *int_status_1, struct bma4_dev *dev); - -/*! - * @brief This API initializes the auxiliary interface to access - * auxiliary sensor - * - * @param[in] dev : Structure instance of bma4_dev. - * - * @return Result of API execution status - * @retval 0 -> Success - * @retval Any non zero value -> Fail - * - */ -uint16_t bma4_aux_interface_init(struct bma4_dev *dev); - -/*! - * @brief This API reads the data from the auxiliary sensor - * - * @param[in] dev : Structure instance of bma4_dev. - * @param[in] len : User specified data length - * @param[out] aux_data : Pointer variable to store data read - * @param[in] aux_reg_addr : Variable to pass address from where - * data is to be read - * - * @return Result of API execution status - * @retval 0 -> Success - * @retval Any non zero value -> Fail - * - */ -uint16_t bma4_aux_read(uint8_t aux_reg_addr, uint8_t *aux_data, uint16_t len, struct bma4_dev *dev); - -/*! - * @brief This API writes the data into the auxiliary sensor - * - * @param[in] dev : Structure instance of bma4_dev. - * @param[in] len : User specified data length - * @param[out] aux_data : Pointer variable to store data read - * @param[in] aux_reg_addr : Variable to pass address from where - * data is to be written - * - * @return Result of API execution status - * @retval 0 -> Success - * @retval Any non zero value -> Fail - * - */ -uint16_t bma4_aux_write(uint8_t aux_reg_addr, uint8_t *aux_data, uint16_t len, struct bma4_dev *dev); - - -#endif -/* End of __BMA4_H__ */ +/* +* +**************************************************************************** +* Copyright (C) 2015 - 2016 Bosch Sensortec GmbH +* +* File : bma4.h +* +* Date: 12 Oct 2017 +* +* Revision: 2.1.9 $ +* +* Usage: Sensor Driver for BMA4 family of sensors +* +**************************************************************************** +* +* Disclaimer +* +* Common: +* Bosch Sensortec products are developed for the consumer goods industry. +* They may only be used within the parameters of the respective valid +* product data sheet. Bosch Sensortec products are provided with the +* express understanding that there is no warranty of fitness for a +* particular purpose.They are not fit for use in life-sustaining, +* safety or security sensitive systems or any system or device +* that may lead to bodily harm or property damage if the system +* or device malfunctions. In addition,Bosch Sensortec products are +* not fit for use in products which interact with motor vehicle systems. +* The resale and or use of products are at the purchasers own risk and +* his own responsibility. The examination of fitness for the intended use +* is the sole responsibility of the Purchaser. +* +* The purchaser shall indemnify Bosch Sensortec from all third party +* claims, including any claims for incidental, or consequential damages, +* arising from any product use not covered by the parameters of +* the respective valid product data sheet or not approved by +* Bosch Sensortec and reimburse Bosch Sensortec for all costs in +* connection with such claims. +* +* The purchaser must monitor the market for the purchased products, +* particularly with regard to product safety and inform Bosch Sensortec +* without delay of all security relevant incidents. +* +* Engineering Samples are marked with an asterisk (*) or (e). +* Samples may vary from the valid technical specifications of the product +* series. They are therefore not intended or fit for resale to third +* parties or for use in end products. Their sole purpose is internal +* client testing. The testing of an engineering sample may in no way +* replace the testing of a product series. Bosch Sensortec assumes +* no liability for the use of engineering samples. +* By accepting the engineering samples, the Purchaser agrees to indemnify +* Bosch Sensortec from all claims arising from the use of engineering +* samples. +* +* Special: +* This software module (hereinafter called "Software") and any information +* on application-sheets (hereinafter called "Information") is provided +* free of charge for the sole purpose to support your application work. +* The Software and Information is subject to the following +* terms and conditions: +* +* The Software is specifically designed for the exclusive use for +* Bosch Sensortec products by personnel who have special experience +* and training. Do not use this Software if you do not have the +* proper experience or training. +* +* This Software package is provided `` as is `` and without any expressed +* or implied warranties,including without limitation, the implied warranties +* of merchantability and fitness for a particular purpose. +* +* Bosch Sensortec and their representatives and agents deny any liability +* for the functional impairment +* of this Software in terms of fitness, performance and safety. +* Bosch Sensortec and their representatives and agents shall not be liable +* for any direct or indirect damages or injury, except as +* otherwise stipulated in mandatory applicable law. +* +* The Information provided is believed to be accurate and reliable. +* Bosch Sensortec assumes no responsibility for the consequences of use +* of such Information nor for any infringement of patents or +* other rights of third parties which may result from its use. +* No license is granted by implication or otherwise under any patent or +* patent rights of Bosch. Specifications mentioned in the Information are +* subject to change without notice. +**************************************************************************/ +/*! \file bma4.h + \brief Sensor Driver for BMA4 family of sensors */ +#ifndef BMA4_H__ +#define BMA4_H__ + +/*********************************************************************/ +/* header files */ + +#include "bma4_defs.h" +#ifdef AKM9916 +#include "aux_akm9916.h" +#endif + +#ifdef BMM150 +#include "aux_bmm150.h" +#endif +/*********************************************************************/ +/* (extern) variable declarations */ + +/*********************************************************************/ +/* function prototype declarations */ +/*! + * @brief This API is the entry point. + * Call this API before using all other APIs. + * This API reads the chip-id of the sensor which is the first step to + * verify the sensor and also it configures the read mechanism of SPI and + * I2C interface. + * + * @param[in,out] dev : Structure instance of bma4_dev + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + * + * @note + * While changing the parameter of the bma4 + * consider the following point: + * Changing the reference value of the parameter + * will changes the local copy or local reference + * make sure your changes will not + * affect the reference value of the parameter + * (Better case don't change the reference value of the parameter) + */ +uint16_t bma4_init(struct bma4_dev *dev); + +/*! + * @brief This API is used to write the binary configuration in the sensor + * + * @param[in] dev : Structure instance of bma4_dev. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + * + */ +uint16_t bma4_write_config_file(struct bma4_dev *dev); + +/*! + * @brief This API checks whether the write operation requested is for + * feature config or register write and accordingly writes the data in the + * sensor. + * + * @note user has to disable the advance power save mode in the sensor when + * using this API in burst write mode. + * bma4_set_advance_power_save(BMA4_DISABLE, dev); + * + * @param[in] addr : Register address. + * @param[in] data : Write data buffer + * @param[in] len : No of bytes to write + * @param[in] dev : Structure instance of bma4_dev. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + */ +uint16_t bma4_write_regs(uint8_t addr, uint8_t *data, uint8_t len, struct bma4_dev *dev); + +/*! + * @brief This API checks whether the read operation requested is for + * feature or register read and accordingly reads the data from the sensor. + * + * @param[in] addr : Register address. + * @param[in] data : Read data buffer. + * @param[in] len : No of bytes to read. + * @param[in] dev : Structure instance of bma4_dev + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + */ +uint16_t bma4_read_regs(uint8_t addr, uint8_t *data, uint8_t len, struct bma4_dev *dev); + +/*! + * @brief This API reads the error status from the sensor. + * + * Below table mention the types of error which can occur in the sensor + *@verbatim + ************************************************************************* + * Error | Description + *************************|*********************************************** + * | Fatal Error, chip is not in operational + * fatal | state (Boot-, power-system). + * | This flag will be reset only by + * | power-on-reset or soft reset. + *************************|*********************************************** + * cmd | Command execution failed. + *************************|*********************************************** + * | Value Name Description + * error_code | 000 no_error no error + * | 001 acc_err error in + * | ACC_CONF + *************************|*********************************************** + * | Error in FIFO detected: Input data was + * fifo | discarded in stream mode. This flag + * | will be reset when read. + *************************|*********************************************** + * mag | Error in I2C-Master detected. + * | This flag will be reset when read. + ************************************************************************* + *@endverbatim + * + * @param[in,out] err_reg : Pointer to structure variable which stores the + * error status read from the sensor. + * @param[in] dev : Structure instance of bma4_dev. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + */ +uint16_t bma4_get_error_status(struct bma4_err_reg *err_reg, struct bma4_dev *dev); + +/*! + * @brief This API reads the sensor status from the dev sensor. + * + * Below table lists the sensor status flags + * Status | Description + * ----------------------------|---------------------------------------- + * BMA4_MAG_MAN_OP_ONGOING | Manual Mag. interface operation ongoing + * BMA4_CMD_RDY | Command decoder is ready. + * BMA4_MAG_DATA_RDY | Data ready for Mag. + * BMA4_ACC_DATA_RDY | Data ready for Accel. + * + * @param[in] status : Variable used to store the sensor status flags + * which is read from the sensor. + * @param[in] dev : Structure instance of bma4_dev. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + * + */ +uint16_t bma4_get_status(uint8_t *status, struct bma4_dev *dev); + +/*! + * @brief This API reads the Accel data for x,y and z axis from the sensor. + * The data units is in LSB format. + * + * @param[in] accel : Variable used to store the Accel data which is read + * from the sensor. + * @param[in] dev : Structure instance of bma4_dev. + * + * @note For setting the Accel configuration use the below function + * bma4_set_accel_config + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + * + */ +uint16_t bma4_read_accel_xyz(struct bma4_accel *accel, struct bma4_dev *dev); + +/*! + * @brief This API reads the sensor time of Sensor time gets updated + * with every update of data register or FIFO. + * + * @param[in] sensor_time : Pointer variable which stores sensor time + * @param[in] dev : Structure instance of bma4_dev. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + * + */ +uint16_t bma4_get_sensor_time(uint32_t *sensor_time, struct bma4_dev *dev); + +/*! + * @brief This API reads the chip temperature of sensor. + * @note If Accel and Mag are disabled, the temperature value will be set + * to invalid. + * + * @param[out] temp : Pointer variable which stores the temperature value. + * @param[in] temp_unit : indicates the unit of temperature + * temp_unit | description + * ------------|------------------- + * BMA4_DEG | degrees Celsius + * BMA4_FAHREN | degrees fahrenheit + * BMA4_KELVIN | degrees kelvin + * + * @param[in] dev : Structure instance of bma4_dev. + * + * @note Using a scaling factor of 1000, to obtain integer values, which + * at the user end, are used to get accurate temperature value. + * BMA4_SCALE_FARHAN = 1.8 * 1000, BMA4_SCALE_KELVIN = 273.15 * 1000 + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + * + */ +uint16_t bma4_get_temperature(int32_t *temp, uint8_t temp_unit, struct bma4_dev *dev); + +/*! + * @brief This API reads the Output data rate, Bandwidth, perf_mode + * and Range of accel. + * + * @param[in,out] accel : Address of user passed structure which is used + * to store the Accel configurations read from the sensor. + * + * @note Enums and corresponding values for structure parameters like + * Odr, Bandwidth and Range are mentioned in the below tables. + * + * Value | Odr + * -----------|------------------------------------ + * 1 | BMA4_OUTPUT_DATA_RATE_0_78HZ + * 2 | BMA4_OUTPUT_DATA_RATE_1_56HZ + * 3 | BMA4_OUTPUT_DATA_RATE_3_12HZ + * 4 | BMA4_OUTPUT_DATA_RATE_6_25HZ + * 5 | BMA4_OUTPUT_DATA_RATE_12_5HZ + * 6 | BMA4_OUTPUT_DATA_RATE_25HZ + * 7 | BMA4_OUTPUT_DATA_RATE_50HZ + * 8 | BMA4_OUTPUT_DATA_RATE_100HZ + * 9 | BMA4_OUTPUT_DATA_RATE_200HZ + * 10 | BMA4_OUTPUT_DATA_RATE_400HZ + * 11 | BMA4_OUTPUT_DATA_RATE_800HZ + * 12 | BMA4_OUTPUT_DATA_RATE_1600HZ + * + * Value | accel_bw + * ------|-------------------------- + * 0 | BMA4_ACCEL_OSR4_AVG1 + * 1 | BMA4_ACCEL_OSR2_AVG2 + * 2 | BMA4_ACCEL_NORMAL_AVG4 + * 3 | BMA4_ACCEL_CIC_AVG8 + * 4 | BMA4_ACCEL_RES_AVG16 + * 5 | BMA4_ACCEL_RES_AVG32 + * 6 | BMA4_ACCEL_RES_AVG64 + * 7 | BMA4_ACCEL_RES_AVG128 + * + * Value | g_range + * --------|--------------------- + * 0x00 | BMA4_ACCEL_RANGE_2G + * 0x01 | BMA4_ACCEL_RANGE_4G + * 0x02 | BMA4_ACCEL_RANGE_8G + * 0x03 | BMA4_ACCEL_RANGE_16G + * + * @param[in] dev : Structure instance of bma4_dev + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + * + */ +uint16_t bma4_get_accel_config(struct bma4_accel_config *accel, struct bma4_dev *dev); + +/*! + * @brief This API sets the output_data_rate, bandwidth, perf_mode + * and range of Accel. + * + * @param[in] accel : Pointer to structure variable which specifies the + * Accel configurations. + * + * @note Enums and corresponding values for structure parameters like + * Odr, Bandwidth and Range are mentioned in the below tables. + * Value | ODR + * --------|----------------------------------------- + * 1 | BMA4_OUTPUT_DATA_RATE_0_78HZ + * 2 | BMA4_OUTPUT_DATA_RATE_1_56HZ + * 3 | BMA4_OUTPUT_DATA_RATE_3_12HZ + * 4 | BMA4_OUTPUT_DATA_RATE_6_25HZ + * 5 | BMA4_OUTPUT_DATA_RATE_12_5HZ + * 6 | BMA4_OUTPUT_DATA_RATE_25HZ + * 7 | BMA4_OUTPUT_DATA_RATE_50HZ + * 8 | BMA4_OUTPUT_DATA_RATE_100HZ + * 9 | BMA4_OUTPUT_DATA_RATE_200HZ + * 10 | BMA4_OUTPUT_DATA_RATE_400HZ + * 11 | BMA4_OUTPUT_DATA_RATE_800HZ + * 12 | BMA4_OUTPUT_DATA_RATE_1600HZ + * + * Value | accel_bw + * ------|-------------------------- + * 0 | BMA4_ACCEL_OSR4_AVG1 + * 1 | BMA4_ACCEL_OSR2_AVG2 + * 2 | BMA4_ACCEL_NORMAL_AVG4 + * 3 | BMA4_ACCEL_CIC_AVG8 + * 4 | BMA4_ACCEL_RES_AVG16 + * 5 | BMA4_ACCEL_RES_AVG32 + * 6 | BMA4_ACCEL_RES_AVG64 + * 7 | BMA4_ACCEL_RES_AVG128 + * + * Value | g_range + * --------|--------------------- + * 0x00 | BMA4_ACCEL_RANGE_2G + * 0x01 | BMA4_ACCEL_RANGE_4G + * 0x02 | BMA4_ACCEL_RANGE_8G + * 0x03 | BMA4_ACCEL_RANGE_16G + * + * @param[in] dev : Structure instance of bma4_dev + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + * + */ +uint16_t bma4_set_accel_config(const struct bma4_accel_config *accel, struct bma4_dev *dev); + +/*! + * @brief This API sets the advance power save mode in the sensor. + * + * @note If advanced power save is enabled and the Accel and/or + * magnetometer operate in duty cycling mode, the length of the unlatched + * DRDY interrupt pulse is longer than 1/3.2 kHz (312.5 us). + * + * @param[in] adv_pwr_save : The value of advance power save mode + * @param[in] dev : Structure instance of bma4_dev. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + * + */ +uint16_t bma4_set_advance_power_save(uint8_t adv_pwr_save, + struct bma4_dev *dev); + +/*! + * @brief This API reads the status of advance power save mode + * from the sensor. + * + * @note If the advanced power save is enabled and the Accel and/or + * magnetometer operate in duty cycling mode, the length of the unlatched + * DRDY interrupt pulse is longer than 1/3.2 kHz (312.5 us). + * + * @param[out] adv_pwr_save : The value of advance power save mode + * @param[in] dev : Structure instance of bma4_dev. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + * + */ +uint16_t bma4_get_advance_power_save(uint8_t *adv_pwr_save, struct bma4_dev *dev); + +/*! + * @brief This API sets the FIFO self wake up functionality in the sensor. + * + * @note Functionality related to FIFO self wake up depends upon the + * advance power save mode. for more info. refer data sheet. + * + * @param[in] fifo_self_wakeup : Variable used to enable or disable + * FIFO self wake up functionality. + * @param[in] dev : Structure instance of bma4_dev. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + * + */ +uint16_t bma4_set_fifo_self_wakeup(uint8_t fifo_self_wakeup, struct bma4_dev *dev); + +/*! + * @brief This API gets the status of FIFO self wake up functionality from + * the sensor. + * + * @note Functionality related to FIFO self wake up depends upon the + * advance power save mode. for more info. refer data sheet. + * + * @param[out] fifo_self_wake_up : Pointer variable used to store the + * fifo self wake up status. + * @param[in] dev : Structure instance of bma4_dev. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + * + */ +uint16_t bma4_get_fifo_self_wakeup(uint8_t *fifo_self_wake_up, struct bma4_dev *dev); + +/*! + * @brief This API enables or disables the Accel in the sensor. + * + * @note Before reading Accel data, user should call this API. + * + * @param[in] accel_en : Variable used to enable or disable the Accel. + * @param[in] dev : Structure instance of bma4_dev. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + * + */ +uint16_t bma4_set_accel_enable(uint8_t accel_en, struct bma4_dev *dev); + +/*! + * @brief This API checks whether Accel is enabled or not in the sensor. + * + * @param[out] accel_en : Pointer variable used to store the Accel enable + * status + * @param[in] dev : Structure instance of bma4_dev. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + * + */ +uint16_t bma4_get_accel_enable(uint8_t *accel_en, struct bma4_dev *dev); + +/*! + * @brief This API is used to enable or disable auxiliary Mag + * in the sensor. + * + * @note Before reading Mag data, user should call this API. + * + * @param[in] mag_en : Variable used to enable or disable the Mag. + * @param[in] dev : Structure instance of bma4_dev. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + * + */ +uint16_t bma4_set_mag_enable(uint8_t mag_en, struct bma4_dev *dev); + +/*! + * @brief This API is used to check whether the auxiliary Mag is enabled + * or not in the sensor. + * + * @param[out] mag_en : Pointer variable used to store the enable status of + * Mag in the sensor. + * @param[in] dev : Structure instance of bma4_dev. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + * + */ +uint16_t bma4_get_mag_enable(uint8_t *mag_en, struct bma4_dev *dev); + +/*! + * @brief This API reads the SPI interface mode which is set for primary + * interface. + * + * @param[out] spi : Pointer variable which stores the SPI mode selection + * Value | Description + * --------|------------------ + * 0 | SPI 4-wire mode + * 1 | SPI 3-wire mode + * @param[in] dev : Structure instance of bma4_dev. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + * + */ +uint16_t bma4_get_spi_interface(uint8_t *spi, struct bma4_dev *dev); + +/*! + * @brief This API configures the SPI interface Mode for primary interface + * + * @param[in] spi : The value of SPI mode selection + * Value | Description + * --------|------------------ + * 0 | SPI 4-wire mode + * 1 | SPI 3-wire mode + * + * @param[in] dev : Structure instance of bma4_dev. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + * + */ +uint16_t bma4_set_spi_interface(uint8_t spi, struct bma4_dev *dev); + + /*! + * @brief This API writes the available sensor specific commands + * to the sensor. + * + * @param[in] command_reg : The command to write to the command register. + *@verbatim + * value | Description + * --------|------------------------------------------------------ + * 0xB6 | Triggers a soft reset + * 0xB0 | Clears all data in the FIFO, does not change + * | FIFO_CONFIG and FIFO_DOWNS registers + * 0xF0 | Reset acceleration data path + *@endverbatim + * @param[in] dev : Structure instance of bma4_dev. + * + * @note Register will always read as 0x00 + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + * + */ +uint16_t bma4_set_command_register(uint8_t command_reg, struct bma4_dev *dev); + +/*! + * @brief This API sets the I2C device address of auxiliary sensor + * + * @param[in] dev : Structure instance of bma4_dev. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + * + */ +uint16_t bma4_set_i2c_device_addr(struct bma4_dev *dev); + +/*! + * @brief This API sets the register access on MAG_IF[2], MAG_IF[3], + * MAG_IF[4] in the sensor. This implies that the DATA registers are + * not updated with Mag values automatically. + * + * @param[in] mag_manual : Variable used to specify the Mag manual + * enable status. + * value | mag manual + * ---------|-------------------- + * 0x01 | BMA4_ENABLE + * 0x00 | BMA4_DISABLE + * + * @param[out] dev : Structure instance of bma4_dev. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + * + */ +uint16_t bma4_set_mag_manual_enable(uint8_t mag_manual, struct bma4_dev *dev); + +/*! + * @brief This API checks whether the Mag access is done manually or + * automatically in the sensor. + * If the Mag access is done through manual mode then Mag data registers + * in sensor are not updated automatically. + * + * @param[out] mag_manual : Mag manual enable value + * value | mag_manual + * --------|------------------- + * 0x01 | BMA4_ENABLE + * 0x00 | BMA4_DISABLE + * @param[in] dev : Structure instance of bma4_dev + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + * + */ +uint16_t bma4_get_mag_manual_enable(uint8_t *mag_manual, struct bma4_dev *dev); + +/*! + * @brief This API sets the I2C interface configuration(if) mode + * for auxiliary Mag. + * + * @param[in] if_mode : The value of interface configuration mode + * Value | Description + * ------------|------------------------------------------- + * 0 | p_auto_s_off Auxiliary interface:off + * 1 | p_auto_s_mag Auxiliary interface:on + * @param[in] dev : Structure instance of bma4_dev. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + * + */ +uint16_t bma4_set_aux_if_mode(uint8_t if_mode, struct bma4_dev *dev); + +/*! + * @brief This API gets the address of the register of Aux Mag sensor + * where the data to be read. + * + * @param[out] mag_read_addr : Pointer variable used to store the + * mag read address. + * @param[in] dev : Structure instance of bma4_dev. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + * + */ +uint16_t bma4_get_mag_read_addr(uint8_t *mag_read_addr, struct bma4_dev *dev); + +/*! + * @brief This API sets the address of the register of Aux Mag sensor + * where the data to be read. + * + * @param[in] mag_read_addr: Value of Mag. read address in order to read + * the data from the auxiliary Mag. + * @param[in] dev : Structure instance of bma4_dev. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + * + */ +uint16_t bma4_set_mag_read_addr(uint8_t mag_read_addr, struct bma4_dev *dev); + +/*! + * @brief This API gets the Aux Mag write address from the sensor. + * Mag write address is where the Mag data will be written. + * + * @param[out] mag_write_addr: Pointer used to store the Mag write address + * which is read from the sensor. + * @param[in] dev : Structure instance of bma4_dev + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + * + */ +uint16_t bma4_get_mag_write_addr(uint8_t *mag_write_addr, struct bma4_dev *dev); + +/*! + * @brief This API sets the Aux Mag write address in the sensor. + * Mag write address is where the Mag data will be written. + * + * @param[in] mag_write_addr: Write address of Mag where the data will + * be written. + * @param[out] dev : Structure instance of bma4_dev + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + * + */ +uint16_t bma4_set_mag_write_addr(uint8_t mag_write_addr, struct bma4_dev *dev); + +/*! + * @brief This API reads the data from the sensor which is written to the + * Mag. + * + * @param[out] mag_write_data: Pointer variable which stores the + * data which is written in Mag through sensor. + * @param[in] dev : Structure instance of bma4_dev + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + * + */ +uint16_t bma4_get_mag_write_data(uint8_t *mag_write_data, struct bma4_dev *dev); + +/*! + * @brief This API sets the data in the sensor which in turn will + * be written to Mag. + * + * @param[in] mag_write_data: variable which specify the data which is to + * be written in Mag. + * @param[out] dev : Structure instance of bma4_dev + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + * + */ +uint16_t bma4_set_mag_write_data(uint8_t mag_write_data, struct bma4_dev *dev); + +/*! + * @brief This API reads the x,y,z and r axis data from the auxiliary + * Mag BMM150/AKM9916 sensor. + * + * @param[out] mag : Pointer variable to store the auxiliary Mag x,y,z + * and r axis data read from the sensor. + * @param[in] dev : Structure instance of bma4_dev + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + * + */ +uint16_t bma4_read_mag_xyzr(struct bma4_mag_xyzr *mag, struct bma4_dev *dev); + +/*! + * @brief This API sets the burst data length (1,2,6,8 byte) of auxiliary + * Mag sensor. + * + * @param[in] mag_burst : Variable used to specify the Mag burst read length + * @param[in] dev : Structure instance of bma4_dev + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + * + */ +uint16_t bma4_set_mag_burst(uint8_t mag_burst, struct bma4_dev *dev); + +/*! + * @brief This API reads the burst data length of Mag set in the sensor. + * + * @param[out] mag_burst : Pointer variable used to store the burst length + * @param[in] dev : Structure instance of bma4_dev + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + * + */ +uint16_t bma4_get_mag_burst(uint8_t *mag_burst, struct bma4_dev *dev); + +/*! + * @brief This API reads the FIFO data of Accel and/or Mag sensor + * + * @param dev : Structure instance of bma4_dev + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + * + */ +uint16_t bma4_read_fifo_data(struct bma4_dev *dev); + +/*! + * @brief This API reads the FIFO water mark level which is set + * in the sensor. + * + * @note The FIFO watermark is issued when the FIFO fill level is + * equal or above the watermark level. + * + * @param[out] fifo_wm : Pointer variable to store FIFO water mark level + * @param[in] dev : Structure instance of bma4_dev + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + * + */ +uint16_t bma4_get_fifo_wm(uint16_t *fifo_wm, struct bma4_dev *dev); + +/*! + * @brief This API sets the FIFO watermark level in the sensor. + * + * @note The FIFO watermark is issued when the FIFO fill level is + * equal or above the watermark level. + * + * @param[in] fifo_wm : Variable used to set the FIFO water mark level + * @param[out] dev : Structure instance of bma4_dev + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + * + */ +uint16_t bma4_set_fifo_wm(uint16_t fifo_wm, struct bma4_dev *dev); + +/*! + * @brief This API checks whether the Accel FIFO data is set for filtered + * or unfiltered mode. + * + * @param[out] accel_fifo_filter : Variable used to check whether the Accel + * data is filtered or unfiltered. + * Value | accel_fifo_filter + * ---------|------------------------- + * 0x00 | Unfiltered data + * 0x01 | Filtered data + * @param[in] dev : structure instance of bma4_dev + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + * + */ +uint16_t bma4_get_accel_fifo_filter_data(uint8_t *accel_fifo_filter, struct bma4_dev *dev); + +/*! + * @brief This API sets the condition of Accel FIFO data either to + * filtered or unfiltered mode. + * + * @param[in] accel_fifo_filter : Variable used to set the filtered or + * unfiltered condition of Accel FIFO data. + * value | accel_fifo_filter_data + * -----------|------------------------- + * 0x00 | Unfiltered data + * 0x01 | Filtered data + * @param[out] dev : Structure instance of bma4_dev + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + * + */ +uint16_t bma4_set_accel_fifo_filter_data(uint8_t accel_fifo_filter, struct bma4_dev *dev); + +/*! + * @brief This API reads the down sampling rates which is configured + * for Accel FIFO data. + * + * @param[out] fifo_down : Variable used to specify the Accel FIFO + * down-sampling rates + * @param[in] dev : Structure instance of bma4_dev + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + * + */ +uint16_t bma4_get_fifo_down_accel(uint8_t *fifo_down, struct bma4_dev *dev); + +/*! + * @brief This API sets the down-sampling rates for Accel FIFO. + * + * @param[in] fifo_down : Variable used to specify the Accel FIFO + * down-sampling rates. + * @param[in] dev : structure instance of bma4_dev + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + * + */ +uint16_t bma4_set_fifo_down_accel(uint8_t fifo_down, struct bma4_dev *dev); + +/*! + * @brief This API reads the length of FIFO data available in the sensor + * in the units of bytes. + * + * @note This byte counter is updated each time a complete frame was read + * or written + * + * @param[in] fifo_length : Pointer variable used to store the value of + * fifo byte counter + * @param[in] dev : Structure instance of bma4_dev + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + * + */ +uint16_t bma4_get_fifo_length(uint16_t *fifo_length, struct bma4_dev *dev); + +/*! + * @brief This API aligns and compensates the Mag data of BMM150/AKM9916 + * sensor. + * + * @param[in] mag_fifo_data: Structure object which stores the Mag x,yand z + * axis FIFO data which is to be aligned and/or compensated. + * @param[in] mag_second_if: Variable used to select the Mag sensor. + * Value | mag_second_if + * --------|---------------------- + * 1 | BMA4_SEC_IF_BMM150 + * 2 | BMA4_SEC_IF_AKM09916 + * + * @param[out] compensated_mag_data: Pointer variable used to store the + * compensated Mag xyz axis data + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + * + */ +uint16_t bma4_second_if_mag_compensate_xyz(struct bma4_mag_fifo_data mag_fifo_data, + uint8_t mag_second_if, + struct bma4_mag *compensated_mag_data); + +/*! + * @brief This API reads Mag. x,y and z axis data from either BMM150 or + * AKM9916 sensor + * + * @param[out] mag : Structure pointer used to store the Mag x,y, and z axis + * data read from the sensor. + * + * @param[in] sensor_select : Variable used to select the Mag sensor + * Value | Sensor + * ---------|---------------------- + * 0 | BMA4_SEC_IF_NULL + * 1 | BMA4_SEC_IF_BMM150 + * 2 | BMA4_SEC_IF_AKM09916 + * @param[in] dev : Structure instance of bma4_dev + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + * + */ +uint16_t bma4_read_mag_xyz(struct bma4_mag *mag, uint8_t sensor_select, struct bma4_dev *dev); + +/*! + * @brief This API reads the auxiliary I2C interface configuration which + * is set in the sensor. + * + * @param[out] if_mode : Pointer variable used to store the auxiliary + * interface configuration. + * Value | Description + * ----- |---------------------------------- + * 0x00 | auxiliary interface:off + * 0x01 | auxiliary interface:on + * @param[in] dev : Structure instance of bma4_dev + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + * + */ +uint16_t bma4_get_if_mode(uint8_t *if_mode, struct bma4_dev *dev); + +/*! + * @brief This API sets the auxiliary interface configuration in the sensor. + * + * @param[in] if_mode : Variable used to select the auxiliary interface + * configuration. + * Value | Description + * ----- |-------------------------- + * 0x00 | auxiliary interface:off + * 0x01 | auxiliary interface:on + * + * @param[in] dev : Structure instance of bma4_dev + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + * + */ +uint16_t bma4_set_if_mode(uint8_t if_mode, struct bma4_dev *dev); + +/*! + * @brief This API reads the data ready status of Accel from the sensor. + * @note The status get reset when Accel data register is read. + * + * @param[out] data_rdy : Pointer variable to store the data ready status + * @param[in] dev : structure instance of bma4_dev + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + * + */ +uint16_t bma4_get_accel_data_rdy(uint8_t *data_rdy, struct bma4_dev *dev); + +/*! + * @brief This API reads the data ready status of Mag from the sensor. + * The status get reset when Mag data register is read. + * + * @param[out] data_rdy : Pointer variable to store the data ready status + * @param[in] dev : Structure instance of bma4_dev + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + * + */ +uint16_t bma4_get_mag_data_rdy(uint8_t *data_rdy, struct bma4_dev *dev); + +/*! + * @brief This API reads the ASIC status from the sensor. + * The status information is mentioned in the below table. + * + *@verbatim + ******************************************************************************* + * Status | Description + **************************|**************************************************** + * sleep | ASIC is in sleep/halt state. + * irq_ovrn | Dedicated interrupt is set again before previous + * | interrupt was acknowledged. + * wc_event | Watchcell event detected (ASIC stopped). + * stream_transfer_active | stream transfer has started. + ******************************************************************************* + *@endverbatim + * + * @param[out] asic_status : Structure pointer used to store the ASIC + * status read from the sensor. + * @param[in] dev : Structure instance of bma4_dev + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + * + */ +uint16_t bma4_get_asic_status(struct bma4_asic_status *asic_status, struct bma4_dev *dev); + +/*! + * @brief This API enables the offset compensation for filtered and + * unfiltered Accel data. + * + * @param[in] offset_en : Variable used to enable or disable offset + * compensation + * offset_en | Description + * ------------|---------------------- + * 0 | BMA4_DISABLE + * 1 | BMA4_ENABLE + * + * @param[in] dev : Structure instance of bma4_dev + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + * + */ +uint16_t bma4_set_offset_comp(uint8_t offset_en, struct bma4_dev *dev); + +/*! + * @brief This API gets the status of Accel offset compensation + * + * @param[out] offset_en : Pointer variable used to store the Accel offset + * enable or disable status. + * offset_en | Description + * ----------|-------------- + * 0 | BMA4_DISABLE + * 1 | BMA4_ENABLE + * + * @param[in] dev : Structure instance of bma4_dev + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + * + */ +uint16_t bma4_get_offset_comp(uint8_t *offset_en, struct bma4_dev *dev); + +/*! + * @brief This API parses and extracts the accelerometer frames from + * FIFO data read by the "bma4_read_fifo_data" API and stores it in the + * "accel_data" structure instance. + * + * @note The bma4_extract_accel API should be called only after reading + * the FIFO data by calling the bma4_read_fifo_data() API + * + * @param[in,out] accel_data : Structure instance of bma4_accel where + * the accelerometer data in FIFO is stored. + * @param[in,out] accel_length : Number of accelerometer frames + * (x,y,z axes data) + * @param[in,out] dev : Structure instance of bma4_dev. + * + * @note accel_length has the number of accelerometer frames + * (1 accel frame = 6 bytes) which the user needs to extract and store is + * provided as input parameter by the user and the Number of valid + * accelerometer frames extracted and stored is updated in + * "accel_length" at the end of execution of this API. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + * + */ +uint16_t bma4_extract_accel(struct bma4_accel *accel_data, uint16_t *accel_length, const struct bma4_dev *dev); + +/*! + * @brief This API parses and extracts the magnetometer frames from + * FIFO data read by the "bma4_read_fifo_data" API and stores it in the + * "mag_data" structure instance parameter of this API + * + * @note The bma4_extract_mag API should be called only after reading + * the FIFO data by calling the bma4_read_fifo_data() API + * + * @param[in,out] mag_data : Structure instance of bma4_mag_xyzr where + * the magnetometer data in FIFO is stored. + * @param[in,out] mag_length : Number of magnetometer frames (x,y,z,r data) + * @param[in,out] dev : Structure instance of bma4_dev. + * + * @note mag_length has the number of magnetometer frames(x,y,z,r data) + * (1 mag frame = 8 bytes) which the user needs to extract and store,It is + * provided as input parameter by the user and the number of valid + * magnetometer frames extracted and stored is updated in + * "mag_length" at the end of execution of this API. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + * + */ +uint16_t bma4_extract_mag(struct bma4_mag *mag_data, uint16_t *mag_length, const struct bma4_dev *dev); + +/*! + * @brief This API performs Fast Offset Compensation for Accel. + * @param[in] accel_g_value : Array which stores the Accel g units + * for x,y and z axis. + * accel_g_value | Description + * --------------------------|--------------------------------------- + * accel_g_value[0] | x axis g units + * accel_g_value[1] | y axis g units + * accel_g_value[2] | z axis g units + * + * @param[in] dev : structure instance of dev + * + * @note The g-values to be passed to the parameter should be + * multiples of 1000000. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + * + */ +uint16_t bma4_perform_accel_foc(const int32_t accel_g_value[3], struct bma4_dev *dev); +/*! + * @brief This API checks whether the self test functionality of the sensor + * is working or not + * + * @param[in] result : Pointer variable used to store the result of self test + * operation + * result | Description + * ---------|-------------------- + * 0x00 | BMA4_SELFTEST_PASS + * 0x01 | BMA4_SELFTEST_FAIL + * @param[in] dev : Structure instance of bma4_dev + * + * @return results of self test + * @retval 0 -> Success + * @retval Any non zero value -> Fail + * + */ +uint16_t bma4_perform_accel_selftest(uint8_t *result, struct bma4_dev *dev); + +/*! + * @brief This API performs the steps needed for Self test operation + * before reading the Accel Self test data. + * + * @param[in] sign: Variable used to specify the self test sign + * @param[in] dev : Structure instance of bma4_dev + * + * @return results of self test + * @retval 0 -> Success + * @retval Any non zero value -> Fail + * + */ +uint16_t bma4_selftest_config(uint8_t sign, struct bma4_dev *dev); + +/*! + * @brief API sets the interrupt to either interrupt1 or + * interrupt2 pin in the sensor. + * + * @param[in] int_line: Variable used to select interrupt pin1 or pin2 + * int_line | interrupt selection + * ---------|------------------- + * 0 | BMA4_INTR1_MAP + * 1 | BMA4_INTR2_MAP + * + * @param[in] int_map: Variable used to select a particular interrupt + * in the sensor + * + * @param[in] enable : Variable used to enable or disable the interrupt + * Value | Behaviour + * ---------|------------------- + * 0x01 | BMA4_ENABLE + * 0x00 | BMA4_DISABLE + * + * @param[in] dev : Structure instance of bma4_dev + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + * + */ +uint16_t bma4_map_interrupt(uint8_t int_line, uint16_t int_map, uint8_t enable, struct bma4_dev *dev); + +/*! + * @brief This API sets the interrupt mode in the sensor. + * + * @param[in] mode: Variable used to specify the interrupt mode which + * is to be set in the sensor. + * Mode | Value + * ----------------------- |--------- + * BMA4_NON_LATCH_MODE | 0 + * BMA4_LATCH_MODE | 1 + * + * @param[in] dev : Structure instance of bma4_dev + * + * @return status of bus communication function + * @retval 0 -> Success + * @retval Any non zero value -> Fail + * + */ +uint16_t bma4_set_interrupt_mode(uint8_t mode, struct bma4_dev *dev); + +/*! + * @brief This API gets the interrupt mode which is set in the sensor. + * + * @param[out] mode: Pointer variable used to store the interrupt mode set in + * in the sensor. + * Mode | Value + * ---------------------|--------------- + * BMA4_NON_LATCH_MODE | 0 + * BMA4_LATCH_MODE | 1 + * + * @param[in] dev : Structure instance of bma4_dev + * + * @return status of bus communication function + * @retval 0 -> Success + * @retval Any non zero value -> Fail + * + */ +uint16_t bma4_get_interrupt_mode(uint8_t *mode, struct bma4_dev *dev); + +/*! + * @brief This API sets the auxiliary Mag(BMM150 or AKM9916) output data + * rate and offset. + * + * @param[in] aux_mag : Pointer to structure variable used to specify + * the auxiliary Mag configuration. + *@verbatim + *------------------------------------------------------------------------------ + * Odr | Value + *----------------------------------------|--------------------------------- + * BMA4_OUTPUT_DATA_RATE_0_78HZ | 0x01 + * BMA4_OUTPUT_DATA_RATE_1_56HZ | 0x02 + * BMA4_OUTPUT_DATA_RATE_3_12HZ | 0x03 + * BMA4_OUTPUT_DATA_RATE_6_25HZ | 0x04 + * BMA4_OUTPUT_DATA_RATE_12_5HZ | 0x05 + * BMA4_OUTPUT_DATA_RATE_25HZ | 0x06 + * BMA4_OUTPUT_DATA_RATE_50HZ | 0x07 + * BMA4_OUTPUT_DATA_RATE_100HZ | 0x08 + * BMA4_OUTPUT_DATA_RATE_200HZ | 0x09 + * BMA4_OUTPUT_DATA_RATE_400HZ | 0x0A + * BMA4_OUTPUT_DATA_RATE_800HZ | 0x0B + * BMA4_OUTPUT_DATA_RATE_1600HZ | 0x0C + *------------------------------------------------------------------------------ + * Offset | Value + *--------------------------------------------|--------------------------------- + * BMA4_MAG_OFFSET_MAX | 0x00 + *--------------------------------------------|--------------------------------- + @endverbatim + * @param[in] dev : Structure instance of bma4_dev + * + * @return status of bus communication function + * @retval 0 -> Success + * @retval Any non zero value -> Fail + * + */ +uint16_t bma4_set_aux_mag_config(const struct bma4_aux_mag_config *aux_mag, struct bma4_dev *dev); + +/*! + * @brief This API reads the auxiliary Mag(BMM150 or AKM9916) output data + * rate and offset. + * @note : Valid output data rates are mentioned in the below table + * + * @param[out] aux_mag : Pointer to structure variable used to store the + * auxiliary Mag configuration read from the sensor + *@verbatim + *------------------------------------------------------------------------ + * Odr | Value + *----------------------------------------|------------------------------- + * BMA4_OUTPUT_DATA_RATE_0_78HZ | 0x01 + * BMA4_OUTPUT_DATA_RATE_1_56HZ | 0x02 + * BMA4_OUTPUT_DATA_RATE_3_12HZ | 0x03 + * BMA4_OUTPUT_DATA_RATE_6_25HZ | 0x04 + * BMA4_OUTPUT_DATA_RATE_12_5HZ | 0x05 + * BMA4_OUTPUT_DATA_RATE_25HZ | 0x06 + * BMA4_OUTPUT_DATA_RATE_50HZ | 0x07 + * BMA4_OUTPUT_DATA_RATE_100HZ | 0x08 + * BMA4_OUTPUT_DATA_RATE_200HZ | 0x09 + * BMA4_OUTPUT_DATA_RATE_400HZ | 0x0A + * BMA4_OUTPUT_DATA_RATE_800HZ | 0x0B + * BMA4_OUTPUT_DATA_RATE_1600HZ | 0x0C + *------------------------------------------------------------------------- + * Offset | Value + *----------------------------------------|-------------------------------- + * BMA4_MAG_OFFSET_MAX | 0x00 + *------------------------------------------------------------------------- + @endverbatim + * @param[in] dev : Structure instance of bma4_dev + * + * @return status of bus communication function + * @retval 0 -> Success + * @retval Any non zero value -> Fail + * + */ +uint16_t bma4_get_aux_mag_config(struct bma4_aux_mag_config *aux_mag, struct bma4_dev *dev); + +/*! @brief This API sets the FIFO configuration in the sensor. + * + * @param[in] config : Enum variable used to specify the FIFO + * configurations which are to be enabled or disabled in the sensor. + * + * @note : User can set either one or more or all FIFO configurations + * by ORing the below mentioned enums. + * config | Value + * ------------------------|--------------------------- + * BMA4_FIFO_STOP_ON_FULL | 0x01 + * BMA4_FIFO_TIME | 0x02 + * BMA4_FIFO_TAG_INTR2 | 0x04 + * BMA4_FIFO_TAG_INTR1 | 0x08 + * BMA4_FIFO_HEADER | 0x10 + * BMA4_FIFO_MAG | 0x20 + * BMA4_FIFO_ACCEL | 0x40 + * BMA4_FIFO_ALL | 0x7F + * + * @param[in] enable : Parameter used to enable or disable the above + * FIFO configuration + * @param[in] dev : Structure instance of bma4_dev. + * + * @return status of bus communication result + * @retval 0 -> Success + * @retval Any non zero value -> Fail + * + */ +uint16_t bma4_set_fifo_config(uint8_t config, uint8_t enable, struct bma4_dev *dev); + +/*! @brief This API reads the FIFO configuration from the sensor. + * + * @param[in] fifo_config : Enum variable used to get the below fifo + * configuration from the sensor. + * + * @note After calling this function user should do the AND operation with + * the enum value populated by this function to know which FIFO + * configuration is enabled. + * fifo_config | Value + * -------------------------|-------------------------- + * BMA4_FIFO_STOP_ON_FULL | 0x01 + * BMA4_FIFO_TIME | 0x02 + * BMA4_FIFO_TAG_INTR2 | 0x04 + * BMA4_FIFO_TAG_INTR1 | 0x08 + * BMA4_FIFO_HEADER | 0x10 + * BMA4_FIFO_MAG | 0x20 + * BMA4_FIFO_ACCEL | 0x40 + * BMA4_FIFO_ALL | 0x7F + * + * + * @param[in] dev : Structure instance of bma4_dev + * + * @return status of bus communication function + * @retval 0 -> Success + * @retval Any non zero value -> Fail + * + */ +uint16_t bma4_get_fifo_config(uint8_t *fifo_config, struct bma4_dev *dev); + +/*! @brief This function sets the electrical behaviour of interrupt pin1 or + * pin2 in the sensor. + * + * @param[in] int_pin_config : Pointer to structure variable which specifies + * the configuration data of either interrupt pin1 or 2. + *@verbatim + * ************************************************************************ + * Structure field members | Macros + * ********************************|*************************************** + * edge_ctrl | BMA4_LEVEL_TRIGGER(0) + * | BMA4_EDGE_TRIGGER(1) + * ********************************|*************************************** + * lvl | BMA4_ACTIVE_LOW(0) + * | BMA4_ACTIVE_HIGH(1) + * ********************************|*************************************** + * od | BMA4_PUSH_PULL(0) + * | BMA4_OPEN_DRAIN(1) + * ********************************|*************************************** + * output_en | BMA4_OUTPUT_DISABLE(0) + * | BMA4_OUTPUT_ENABLE(1) + * ********************************|*************************************** + * input_en | BMA4_INPUT_DISABLE(0) + * | BMA4_INPUT_ENABLE(1) + * ************************************************************************ + *@endverbatim + * @param[in] int_line : Variable used to select the interrupt pin1 or + * pin2 for interrupt configuration. + * int_line | Value + * ----------------|---------------------- + * BMA4_INTR1_MAP | 0 + * BMA4_INTR2_MAP | 1 + * + * @param[in] dev : Structure instance of bma4_dev + * + * @return status of bus communication function + * @retval 0 -> Success + * @retval Any non zero value -> Fail + */ +uint16_t bma4_set_int_pin_config(const struct bma4_int_pin_config *int_pin_config, uint8_t int_line, + struct bma4_dev *dev); + +/*! @brief This API reads the electrical behavior of interrupt pin1 or pin2 + * from the sensor. + * + * @param[out] int_pin_config : Pointer to structure variable which stores the + * configuration data of either interrupt pin1 or pin2 read from the sensor + *@verbatim + * ************************************************************************ + * Structure field members | Macros + * ************************|*********************************************** + * edge_ctrl | BMA4_LEVEL_TRIGGER(0) + * | BMA4_EDGE_TRIGGER(1) + * ************************|*********************************************** + * lvl | BMA4_ACTIVE_LOW(0) + * | BMA4_ACTIVE_HIGH(1) + * ************************|*********************************************** + * od | BMA4_PUSH_PULL(0) + * | BMA4_OPEN_DRAIN(1) + * ************************|*********************************************** + * output_en | BMA4_OUTPUT_DISABLE(0) + * | BMA4_OUTPUT_ENABLE(1) + * ************************|*********************************************** + * input_en | BMA4_INPUT_DISABLE(0) + * | BMA4_INPUT_ENABLE(1) + * ************************************************************************ + *@endverbatim + * @param[in] int_line : Variable used to select the interrupt pin1 or + * pin2 for interrupt configuration. + * int_line | Value + * -------------------|--------------- + * BMA4_INTR1_MAP | 0 + * BMA4_INTR2_MAP | 1 + * + * @param[in] dev : Structure instance of bma4_dev + * + * @return status of bus communication function + * @retval 0 -> Success + * @retval Any non zero value -> Fail + * + */ +uint16_t bma4_get_int_pin_config(struct bma4_int_pin_config *int_pin_config, uint8_t int_line, struct bma4_dev *dev); + +/*! + * @brief This API reads the Feature and Hardware interrupt status from the sensor. + * + * @param[out] int_status : Variable used to get the interrupt status. + * @param[in] dev : Structure instance of bma4_dev. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + * + */ +uint16_t bma4_read_int_status(uint16_t *int_status, struct bma4_dev *dev); + +/*! + * @brief This API reads the Feature interrupt status from the sensor. + * + * @param[out] int_status_0 : Variable used to get the interrupt status. + * @param[in] dev : Structure instance of bma4_dev. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + * + */ +uint16_t bma4_read_int_status_0(uint8_t *int_status_0, struct bma4_dev *dev); + +/*! + * @brief This API reads the Hardware interrupt status from the sensor. + * + * @param[out] int_status_1 : Variable used to get the interrupt status. + * @param[in] dev : Structure instance of bma4_dev. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + * + */ +uint16_t bma4_read_int_status_1(uint8_t *int_status_1, struct bma4_dev *dev); + +/*! + * @brief This API initializes the auxiliary interface to access + * auxiliary sensor + * + * @param[in] dev : Structure instance of bma4_dev. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + * + */ +uint16_t bma4_aux_interface_init(struct bma4_dev *dev); + +/*! + * @brief This API reads the data from the auxiliary sensor + * + * @param[in] dev : Structure instance of bma4_dev. + * @param[in] len : User specified data length + * @param[out] aux_data : Pointer variable to store data read + * @param[in] aux_reg_addr : Variable to pass address from where + * data is to be read + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + * + */ +uint16_t bma4_aux_read(uint8_t aux_reg_addr, uint8_t *aux_data, uint16_t len, struct bma4_dev *dev); + +/*! + * @brief This API writes the data into the auxiliary sensor + * + * @param[in] dev : Structure instance of bma4_dev. + * @param[in] len : User specified data length + * @param[out] aux_data : Pointer variable to store data read + * @param[in] aux_reg_addr : Variable to pass address from where + * data is to be written + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + * + */ +uint16_t bma4_aux_write(uint8_t aux_reg_addr, uint8_t *aux_data, uint16_t len, struct bma4_dev *dev); + + +#endif +/* End of __BMA4_H__ */ diff --git a/lib/libesp32/TTGO_TWatch_Library/src/bma423.c b/lib/libesp32_div/TTGO_TWatch_Library/src/bma423.c old mode 100755 new mode 100644 similarity index 97% rename from lib/libesp32/TTGO_TWatch_Library/src/bma423.c rename to lib/libesp32_div/TTGO_TWatch_Library/src/bma423.c index 3d5d9c63c..2f8024085 --- a/lib/libesp32/TTGO_TWatch_Library/src/bma423.c +++ b/lib/libesp32_div/TTGO_TWatch_Library/src/bma423.c @@ -1,1695 +1,1695 @@ -/**\mainpage -* -**************************************************************************** -* Copyright (C) 2017 - 2018 Bosch Sensortec GmbH -* -* File : bma423.c -* -* Date: 12 Oct 2017 -* -* Revision : 1.1.4 $ -* -* Usage: Sensor Driver for BMA423 sensor -* -**************************************************************************** -* -* \section Disclaimer -* -* Common: -* Bosch Sensortec products are developed for the consumer goods industry. -* They may only be used within the parameters of the respective valid -* product data sheet. Bosch Sensortec products are provided with the -* express understanding that there is no warranty of fitness for a -* particular purpose.They are not fit for use in life-sustaining, -* safety or security sensitive systems or any system or device -* that may lead to bodily harm or property damage if the system -* or device malfunctions. In addition,Bosch Sensortec products are -* not fit for use in products which interact with motor vehicle systems. -* The resale and or use of products are at the purchasers own risk and -* his own responsibility. The examination of fitness for the intended use -* is the sole responsibility of the Purchaser. -* -* The purchaser shall indemnify Bosch Sensortec from all third party -* claims, including any claims for incidental, or consequential damages, -* arising from any product use not covered by the parameters of -* the respective valid product data sheet or not approved by -* Bosch Sensortec and reimburse Bosch Sensortec for all costs in -* connection with such claims. -* -* The purchaser must monitor the market for the purchased products, -* particularly with regard to product safety and inform Bosch Sensortec -* without delay of all security relevant incidents. -* -* Engineering Samples are marked with an asterisk (*) or (e). -* Samples may vary from the valid technical specifications of the product -* series. They are therefore not intended or fit for resale to third -* parties or for use in end products. Their sole purpose is internal -* client testing. The testing of an engineering sample may in no way -* replace the testing of a product series. Bosch Sensortec assumes -* no liability for the use of engineering samples. -* By accepting the engineering samples, the Purchaser agrees to indemnify -* Bosch Sensortec from all claims arising from the use of engineering -* samples. -* -* Special: -* This software module (hereinafter called "Software") and any information -* on application-sheets (hereinafter called "Information") is provided -* free of charge for the sole purpose to support your application work. -* The Software and Information is subject to the following -* terms and conditions: -* -* The Software is specifically designed for the exclusive use for -* Bosch Sensortec products by personnel who have special experience -* and training. Do not use this Software if you do not have the -* proper experience or training. -* -* This Software package is provided `` as is `` and without any expressed -* or implied warranties,including without limitation, the implied warranties -* of merchantability and fitness for a particular purpose. -* -* Bosch Sensortec and their representatives and agents deny any liability -* for the functional impairment -* of this Software in terms of fitness, performance and safety. -* Bosch Sensortec and their representatives and agents shall not be liable -* for any direct or indirect damages or injury, except as -* otherwise stipulated in mandatory applicable law. -* -* The Information provided is believed to be accurate and reliable. -* Bosch Sensortec assumes no responsibility for the consequences of use -* of such Information nor for any infringement of patents or -* other rights of third parties which may result from its use. -* No license is granted by implication or otherwise under any patent or -* patent rights of Bosch. Specifications mentioned in the Information are -* subject to change without notice. -**************************************************************************/ -/*! \file bma423.c - \brief Sensor Driver for BMA423 sensor */ - -#include "bma423.h" - -/**\name Feature configuration file */ -const uint8_t bma423_config_file[] = { - 0x80, 0x2e, 0xfc, 0x00, 0x80, 0x2e, 0xfe, 0x00, 0xc8, 0x2e, 0x00, 0x2e, - 0x80, 0x2e, 0xfa, 0x00, 0x80, 0x2e, 0x23, 0xb1, 0x80, 0x2e, 0xfd, 0x00, - 0x80, 0x2e, 0xfb, 0x00, 0x80, 0x2e, 0x5a, 0xb1, 0x50, 0x39, 0x21, 0x2e, - 0xb0, 0xf0, 0x10, 0x30, 0x21, 0x2e, 0x16, 0xf0, 0x80, 0x2e, 0xfc, 0x01, - 0x5d, 0x50, 0x45, 0x52, 0x01, 0x42, 0x3b, 0x80, 0x41, 0x30, 0x01, 0x42, - 0x3c, 0x80, 0x00, 0x2e, 0x01, 0x40, 0x01, 0x42, 0x21, 0x2e, 0xff, 0xaf, - 0xb8, 0x2e, 0xb6, 0xd6, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0xfd, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x00, 0x24, 0x01, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, 0x2e, - 0x99, 0x01, 0x20, 0x26, 0x98, 0x2e, 0xf6, 0x00, 0x98, 0x2e, 0xe9, 0x01, - 0x10, 0x30, 0x21, 0x2e, 0x59, 0xf0, 0x98, 0x2e, 0xd8, 0x00, 0x00, 0x2e, - 0x00, 0x2e, 0xd0, 0x2e, 0x98, 0x2e, 0xdd, 0x00, 0x01, 0x2e, 0x56, 0x00, - 0x00, 0xb2, 0x11, 0x2f, 0x00, 0x30, 0x21, 0x2e, 0x56, 0x00, 0x41, 0x50, - 0x98, 0x2e, 0xcc, 0xb0, 0x41, 0x50, 0x98, 0x2e, 0x8f, 0xb4, 0x01, 0x2e, - 0x03, 0xf0, 0x0d, 0xbc, 0x0f, 0xb8, 0x00, 0x90, 0x02, 0x2f, 0x45, 0x50, - 0x21, 0x2e, 0xbc, 0xf0, 0x01, 0x2e, 0x55, 0x00, 0x00, 0xb2, 0x1a, 0x2f, - 0x00, 0x30, 0x21, 0x2e, 0x55, 0x00, 0x43, 0x50, 0x98, 0x2e, 0xcc, 0xb0, - 0x43, 0x50, 0x98, 0x2e, 0xdc, 0xb1, 0x43, 0x50, 0x98, 0x2e, 0x92, 0xb5, - 0x43, 0x50, 0x98, 0x2e, 0x00, 0xb0, 0x01, 0x2e, 0x1c, 0x01, 0x0f, 0xbc, - 0x0f, 0xb8, 0x00, 0x90, 0x45, 0x50, 0x02, 0x2f, 0x21, 0x2e, 0xbc, 0xf0, - 0x02, 0x2d, 0x21, 0x2e, 0xba, 0xf0, 0x98, 0x2e, 0xd8, 0x00, 0xc3, 0x2d, - 0x01, 0x2e, 0x55, 0xf0, 0xc0, 0x2e, 0x21, 0x2e, 0x55, 0xf0, 0x03, 0x2e, - 0x00, 0xf0, 0x45, 0x54, 0x01, 0x2e, 0x59, 0xf0, 0x4a, 0x0e, 0x02, 0x2f, - 0xf1, 0x33, 0x0d, 0x2c, 0x01, 0x08, 0xf2, 0x30, 0x4a, 0x08, 0x79, 0x84, - 0x82, 0xa2, 0x04, 0x2f, 0x02, 0x34, 0x82, 0x0a, 0x47, 0xa2, 0x03, 0x2c, - 0x10, 0x22, 0x45, 0x52, 0x01, 0x0a, 0xc0, 0x2e, 0x21, 0x2e, 0x59, 0xf0, - 0x00, 0x31, 0xc0, 0x2e, 0x21, 0x2e, 0xba, 0xf0, 0xc8, 0x2e, 0xc8, 0x2e, - 0xc8, 0x2e, 0xc8, 0x2e, 0xc8, 0x2e, 0x44, 0x47, 0xaa, 0x00, 0x05, 0x00, - 0x2d, 0x01, 0xd4, 0x7b, 0x3b, 0x01, 0xdb, 0x7a, 0x04, 0x00, 0x3f, 0x7b, - 0xcd, 0x6c, 0xc3, 0x04, 0x85, 0x09, 0xc3, 0x04, 0xec, 0xe6, 0x0c, 0x46, - 0x01, 0x00, 0x27, 0x00, 0x19, 0x00, 0x96, 0x00, 0xa0, 0x00, 0x01, 0x00, - 0x0c, 0x00, 0xf0, 0x3c, 0x00, 0x01, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, - 0x0e, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x43, 0x28, 0x88, 0x00, - 0x52, 0x00, 0x4f, 0x00, 0x80, 0x00, 0x5b, 0x00, 0x00, 0x40, 0xaf, 0x00, - 0xff, 0x00, 0xff, 0xb7, 0x00, 0x02, 0x00, 0xb0, 0x05, 0x80, 0xb1, 0xf0, - 0xc0, 0x00, 0x00, 0x01, 0x5e, 0xf0, 0x39, 0xf0, 0x89, 0xf0, 0x00, 0x20, - 0xff, 0x7f, 0x7d, 0x00, 0x5e, 0x00, 0x62, 0x00, 0x7c, 0x00, 0xff, 0xfb, - 0x52, 0xf0, 0x56, 0xf0, 0x33, 0x09, 0x33, 0x07, 0x00, 0x08, 0x90, 0x01, - 0x00, 0xf8, 0x67, 0x00, 0x4c, 0x04, 0xa0, 0x00, 0xe8, 0x03, 0x81, 0x00, - 0x82, 0x00, 0x6a, 0x00, 0x6d, 0x00, 0x6c, 0x00, 0xeb, 0x07, 0xae, 0x07, - 0x72, 0x00, 0x6f, 0x00, 0xa1, 0x01, 0x1e, 0x05, 0x47, 0xfd, 0x73, 0x00, - 0x77, 0x00, 0x79, 0x00, 0x76, 0x00, 0xcc, 0x00, 0x30, 0x50, 0x50, 0x40, - 0x00, 0x18, 0x50, 0x40, 0x56, 0x25, 0x47, 0x25, 0x00, 0x18, 0x2e, 0x00, - 0x41, 0x40, 0xa7, 0x02, 0x09, 0x18, 0xc6, 0x00, 0xfb, 0x7f, 0x00, 0x30, - 0x49, 0x52, 0x05, 0x30, 0x05, 0x2c, 0x17, 0x03, 0x1e, 0xbd, 0xd2, 0xba, - 0x92, 0xb8, 0x6a, 0x0b, 0x61, 0x0e, 0xf9, 0x2f, 0x61, 0x1a, 0x01, 0x2f, - 0x5d, 0x0e, 0xf5, 0x2f, 0xd4, 0x7f, 0x02, 0x30, 0x1f, 0x2c, 0xe3, 0x7f, - 0x85, 0x01, 0xd1, 0x03, 0x7c, 0x0e, 0x03, 0x2f, 0x7c, 0x1a, 0x0f, 0x2f, - 0x73, 0x0f, 0x0d, 0x2f, 0xe3, 0x6f, 0xde, 0x04, 0x5f, 0xba, 0x11, 0xbf, - 0xb4, 0x0b, 0xd4, 0x6f, 0x27, 0x07, 0xb3, 0x25, 0xd1, 0xbf, 0xeb, 0x7f, - 0x07, 0x00, 0xb4, 0x25, 0x96, 0x02, 0xdb, 0x7f, 0x2f, 0xbf, 0x9e, 0xbf, - 0x01, 0xb8, 0xd2, 0xba, 0x21, 0xb9, 0x92, 0xb8, 0x06, 0x0a, 0x6f, 0x0b, - 0x40, 0x90, 0xdf, 0x2f, 0x40, 0x91, 0xdd, 0x2f, 0xfb, 0x6f, 0xd0, 0x5f, - 0xb8, 0x2e, 0x57, 0x50, 0x41, 0x30, 0x02, 0x40, 0x51, 0x0a, 0x01, 0x42, - 0x18, 0x82, 0x4b, 0x50, 0x60, 0x42, 0x70, 0x3c, 0x4d, 0x54, 0x42, 0x42, - 0x69, 0x82, 0x82, 0x32, 0x43, 0x40, 0x18, 0x08, 0x02, 0x0a, 0x40, 0x42, - 0x42, 0x80, 0x02, 0x3f, 0x01, 0x40, 0x10, 0x50, 0x4a, 0x08, 0xfb, 0x7f, - 0x11, 0x42, 0x0b, 0x31, 0x0b, 0x42, 0x3e, 0x80, 0x01, 0x32, 0x01, 0x42, - 0x00, 0x2e, 0x01, 0x2e, 0x40, 0xf0, 0x13, 0x90, 0x20, 0x2f, 0x03, 0x30, - 0x51, 0x50, 0x4f, 0x54, 0xf4, 0x34, 0x06, 0x30, 0x55, 0x52, 0x55, 0x32, - 0x1d, 0x1a, 0xe3, 0x22, 0x18, 0x1a, 0x53, 0x58, 0xe3, 0x22, 0x04, 0x30, - 0xd5, 0x40, 0xb5, 0x0d, 0xe1, 0xbe, 0x6f, 0xbb, 0x80, 0x91, 0xa9, 0x0d, - 0x01, 0x89, 0xb5, 0x23, 0x10, 0xa1, 0xf7, 0x2f, 0xda, 0x0e, 0xf4, 0x34, - 0xeb, 0x2f, 0x01, 0x2e, 0x25, 0x00, 0x70, 0x1a, 0x00, 0x30, 0x21, 0x30, - 0x02, 0x2c, 0x08, 0x22, 0x30, 0x30, 0x00, 0xb2, 0x06, 0x2f, 0x21, 0x2e, - 0x59, 0xf0, 0x98, 0x2e, 0xd8, 0x00, 0x00, 0x2e, 0x00, 0x2e, 0xd0, 0x2e, - 0xfb, 0x6f, 0xf0, 0x5f, 0xb8, 0x2e, 0x01, 0x2e, 0xb1, 0xf0, 0x59, 0x52, - 0x01, 0x0a, 0x21, 0x2e, 0xb1, 0xf0, 0x01, 0x2e, 0x1c, 0x01, 0x0f, 0xbc, - 0x0f, 0xb8, 0x00, 0x90, 0x45, 0x50, 0x02, 0x2f, 0xc0, 0x2e, 0x21, 0x2e, - 0xbc, 0xf0, 0xc0, 0x2e, 0x21, 0x2e, 0xba, 0xf0, 0x1a, 0x24, 0x26, 0x00, - 0x80, 0x2e, 0x8f, 0x00, 0x03, 0x2e, 0x01, 0x01, 0x05, 0x2e, 0x01, 0x01, - 0x92, 0xbd, 0x20, 0x50, 0x03, 0x2e, 0x01, 0x01, 0xbf, 0xba, 0x21, 0xbd, - 0x2f, 0xbb, 0x1f, 0xba, 0x40, 0x91, 0xf0, 0x7f, 0x04, 0x2f, 0x80, 0x91, - 0x02, 0x2f, 0x00, 0xb3, 0x90, 0x2e, 0xc7, 0xb0, 0x03, 0x2e, 0x7b, 0x00, - 0x01, 0x80, 0x40, 0x90, 0x14, 0x2f, 0x41, 0x84, 0xf1, 0x6f, 0x25, 0x2e, - 0x7b, 0x00, 0x41, 0x40, 0x23, 0x2e, 0x5a, 0x00, 0x47, 0x52, 0x12, 0x40, - 0x52, 0x42, 0x02, 0x30, 0x00, 0x40, 0x40, 0x42, 0xe0, 0x5f, 0x25, 0x2e, - 0x57, 0x00, 0x25, 0x2e, 0x58, 0x00, 0x25, 0x2e, 0x5d, 0x00, 0xb8, 0x2e, - 0x07, 0x2e, 0x00, 0x01, 0x03, 0x2e, 0x01, 0x01, 0x05, 0x2e, 0x00, 0x01, - 0x24, 0xbd, 0x0f, 0x2e, 0x59, 0x00, 0xb5, 0xbd, 0x93, 0xbc, 0x2f, 0xb9, - 0xb5, 0xb9, 0x93, 0xb8, 0x3a, 0x1a, 0x06, 0x2f, 0x07, 0x30, 0x25, 0x2e, - 0x59, 0x00, 0x2f, 0x2e, 0x57, 0x00, 0x2f, 0x2e, 0x58, 0x00, 0x40, 0xb3, - 0x05, 0x30, 0x07, 0x30, 0x0a, 0x2f, 0xf7, 0x6f, 0xe6, 0x7f, 0x00, 0x2e, - 0xc6, 0x41, 0x0f, 0x2e, 0x5a, 0x00, 0xb7, 0x05, 0x80, 0xa9, 0xee, 0x05, - 0xf7, 0x23, 0xe6, 0x6f, 0x80, 0xb3, 0x06, 0x30, 0x09, 0x2f, 0xe7, 0x7f, - 0x00, 0x2e, 0x06, 0x40, 0x0f, 0x2e, 0x5b, 0x00, 0xb7, 0x05, 0x80, 0xa9, - 0xee, 0x05, 0xb7, 0x23, 0xe7, 0x6f, 0x00, 0xb3, 0x04, 0x30, 0x0b, 0x2f, - 0xf4, 0x6f, 0x02, 0x89, 0xe7, 0x7f, 0x00, 0x2e, 0x04, 0x41, 0x0f, 0x2e, - 0x5c, 0x00, 0x27, 0x05, 0x00, 0xa9, 0xec, 0x05, 0x27, 0x23, 0xe7, 0x6f, - 0x7b, 0x0f, 0x17, 0x30, 0x0b, 0x2f, 0x73, 0x0f, 0x05, 0x30, 0x17, 0x30, - 0x07, 0x2f, 0x63, 0x0f, 0x15, 0x30, 0x17, 0x30, 0x00, 0x2f, 0x07, 0x30, - 0xe3, 0x0e, 0x00, 0x2f, 0x05, 0x30, 0x80, 0x90, 0x05, 0x2e, 0x57, 0x00, - 0x13, 0x30, 0x13, 0x29, 0xf2, 0x6f, 0x47, 0x5c, 0x17, 0x2f, 0xc0, 0x91, - 0x05, 0x30, 0x0b, 0x2f, 0x07, 0x2e, 0x58, 0x00, 0xc1, 0x86, 0x2b, 0x2e, - 0x57, 0x00, 0x59, 0x0e, 0x27, 0x2e, 0x58, 0x00, 0x24, 0x2f, 0x2b, 0x2e, - 0x5d, 0x00, 0x22, 0x2d, 0x61, 0x0e, 0x29, 0x2e, 0x57, 0x00, 0x2b, 0x2e, - 0x58, 0x00, 0x1b, 0x2f, 0x27, 0x2e, 0x5d, 0x00, 0x19, 0x2d, 0x40, 0x91, - 0x05, 0x2f, 0x01, 0x30, 0x23, 0x2e, 0x57, 0x00, 0x23, 0x2e, 0x5d, 0x00, - 0x06, 0x2d, 0x29, 0x2e, 0x57, 0x00, 0x61, 0x0e, 0x01, 0x2f, 0x27, 0x2e, - 0x5d, 0x00, 0x81, 0x40, 0x23, 0x2e, 0x5a, 0x00, 0x30, 0x25, 0x47, 0x52, - 0xd4, 0x40, 0x54, 0x42, 0x00, 0x2e, 0xc3, 0x40, 0x43, 0x42, 0x00, 0x2e, - 0x03, 0x2e, 0x5d, 0x00, 0x40, 0xb2, 0x0d, 0x2f, 0x81, 0x40, 0x23, 0x2e, - 0x5a, 0x00, 0x11, 0x40, 0x91, 0x43, 0x01, 0x34, 0x00, 0x40, 0x80, 0x43, - 0x23, 0x2e, 0x5e, 0xf0, 0x03, 0x2d, 0x00, 0x30, 0x21, 0x2e, 0x7b, 0x00, - 0xe0, 0x5f, 0xb8, 0x2e, 0x50, 0x50, 0xf0, 0x7f, 0x1a, 0x25, 0x13, 0x40, - 0x7b, 0x84, 0xe0, 0x7f, 0x83, 0x42, 0x35, 0x30, 0x11, 0x40, 0x04, 0x40, - 0xc1, 0x7f, 0xd4, 0x7f, 0x86, 0x31, 0x07, 0x2e, 0x59, 0xf0, 0x03, 0x2e, - 0x1f, 0x01, 0x0d, 0x09, 0x02, 0xab, 0x05, 0x30, 0x8e, 0x09, 0x2c, 0x23, - 0xe3, 0xba, 0x42, 0xab, 0x16, 0x30, 0x75, 0x23, 0x59, 0x5c, 0x8e, 0x09, - 0x66, 0xbb, 0x82, 0xab, 0x27, 0x30, 0xbe, 0x23, 0x3e, 0x80, 0x25, 0x1a, - 0x06, 0x2f, 0x2e, 0x1a, 0x04, 0x2f, 0x26, 0x1a, 0x02, 0x2f, 0xf7, 0x3d, - 0x03, 0x2c, 0xdf, 0x08, 0x07, 0x32, 0xdf, 0x0a, 0x14, 0x01, 0x55, 0x01, - 0x04, 0x41, 0x14, 0x42, 0x16, 0x01, 0x42, 0x41, 0x45, 0x30, 0x4d, 0x09, - 0x04, 0x41, 0x12, 0x42, 0x04, 0x42, 0x40, 0xb3, 0x04, 0x2f, 0xf0, 0x6f, - 0x02, 0x30, 0x04, 0x40, 0x94, 0x04, 0x02, 0x42, 0x00, 0x32, 0x08, 0x08, - 0x00, 0xb2, 0x00, 0x30, 0x05, 0x2f, 0xe2, 0x6f, 0x00, 0x2e, 0x84, 0x40, - 0x04, 0x05, 0x84, 0x42, 0x00, 0x2e, 0x5b, 0x54, 0x4a, 0x08, 0x40, 0xb2, - 0xf1, 0x6f, 0x04, 0x2f, 0x42, 0x82, 0x00, 0x2e, 0x42, 0x40, 0x02, 0x04, - 0x40, 0x42, 0xb0, 0x5f, 0x27, 0x2e, 0x59, 0xf0, 0xb8, 0x2e, 0x50, 0x50, - 0xf7, 0x7f, 0x00, 0x2e, 0x0f, 0x2e, 0xb8, 0xf0, 0xf8, 0xbf, 0xff, 0xbb, - 0xc0, 0xb3, 0x2a, 0x2f, 0x0f, 0x2e, 0x01, 0xf0, 0xfe, 0xbf, 0xe6, 0x7f, - 0x7e, 0xbb, 0xd5, 0x7f, 0x37, 0x30, 0x5f, 0x5a, 0xbe, 0x05, 0x67, 0x41, - 0xc4, 0x7f, 0x78, 0xbe, 0x47, 0x41, 0x27, 0x0b, 0xb3, 0x7f, 0xe6, 0x11, - 0x41, 0x56, 0x43, 0x89, 0xd7, 0x42, 0x00, 0x2e, 0x27, 0x41, 0x05, 0x41, - 0xf8, 0xbf, 0x7d, 0x0b, 0x6e, 0x11, 0x03, 0x8f, 0xd5, 0x42, 0x14, 0x30, - 0xe5, 0x41, 0xc7, 0x41, 0xd8, 0xbe, 0x6f, 0x0b, 0x6e, 0x11, 0xc5, 0x42, - 0x29, 0x2e, 0x56, 0x00, 0x45, 0x56, 0x27, 0x2e, 0xb8, 0xf0, 0xe6, 0x6f, - 0xd5, 0x6f, 0xc4, 0x6f, 0xb3, 0x6f, 0xf7, 0x6f, 0xb0, 0x5f, 0xc8, 0x2e, - 0x50, 0x50, 0xe5, 0x7f, 0xd7, 0x7f, 0xf6, 0x7f, 0x36, 0x30, 0x0b, 0x2e, - 0x01, 0xf0, 0xde, 0xbe, 0xde, 0xbb, 0x61, 0x5a, 0xb7, 0x05, 0x67, 0x41, - 0xc4, 0x7f, 0x78, 0xbe, 0x47, 0x41, 0x27, 0x0b, 0xb3, 0x7f, 0xe6, 0x11, - 0x43, 0x56, 0x43, 0x89, 0xd7, 0x42, 0x00, 0x2e, 0x27, 0x41, 0x05, 0x41, - 0xf8, 0xbf, 0x7d, 0x0b, 0x6e, 0x11, 0x03, 0x8f, 0xd5, 0x42, 0x14, 0x30, - 0xe5, 0x41, 0xc7, 0x41, 0xd8, 0xbe, 0x6f, 0x0b, 0x6e, 0x11, 0xc5, 0x42, - 0x29, 0x2e, 0x55, 0x00, 0x03, 0x31, 0x27, 0x2e, 0xb8, 0xf0, 0xf6, 0x6f, - 0xe5, 0x6f, 0xd7, 0x6f, 0xc4, 0x6f, 0xb3, 0x6f, 0xb0, 0x5f, 0xc8, 0x2e, - 0x40, 0x50, 0xf6, 0x7f, 0x1a, 0x18, 0x63, 0x56, 0x33, 0x00, 0x06, 0x30, - 0xfe, 0x03, 0x0e, 0xb8, 0xf2, 0xbf, 0x07, 0x0a, 0x2a, 0x18, 0x63, 0x5a, - 0xb5, 0x01, 0x03, 0x30, 0xfb, 0x03, 0x6e, 0xbb, 0xf2, 0xbf, 0xe1, 0x7f, - 0xf7, 0x0b, 0x56, 0x40, 0x36, 0x25, 0x46, 0x40, 0x06, 0x28, 0xc7, 0x7f, - 0x22, 0x18, 0xd1, 0x7f, 0xb5, 0x00, 0x01, 0x30, 0x39, 0x03, 0x2e, 0xb9, - 0x42, 0xbe, 0x14, 0x0b, 0xf2, 0x6f, 0x10, 0x18, 0xb5, 0x00, 0xb9, 0x03, - 0x2e, 0xb9, 0x62, 0xbf, 0x96, 0x0a, 0xb6, 0x6f, 0x30, 0x18, 0x75, 0x01, - 0xb9, 0x03, 0x5c, 0x28, 0xe2, 0xbf, 0xde, 0xb9, 0xd6, 0x6f, 0xdf, 0x0a, - 0x8a, 0x28, 0xc4, 0x6f, 0x82, 0x43, 0x23, 0x29, 0xe5, 0x6f, 0xc0, 0x2e, - 0x44, 0x43, 0xc0, 0x5f, 0x40, 0x50, 0xd0, 0x7f, 0x4a, 0x17, 0x00, 0x40, - 0x01, 0x18, 0x46, 0x25, 0x07, 0x25, 0x65, 0x56, 0xd9, 0x04, 0x53, 0x18, - 0xeb, 0x18, 0x05, 0x30, 0x49, 0x16, 0x69, 0x06, 0xca, 0x18, 0xa6, 0x00, - 0xc7, 0x02, 0x65, 0x58, 0xcb, 0x7f, 0x98, 0x2e, 0x7f, 0xb6, 0xcb, 0x6f, - 0xd2, 0x6f, 0xc0, 0x2e, 0x80, 0x42, 0xc0, 0x5f, 0x09, 0x2e, 0x1b, 0x01, - 0x05, 0x2e, 0x1b, 0x01, 0xa3, 0xbc, 0x44, 0xbe, 0x90, 0x50, 0x4f, 0xb9, - 0x07, 0x2e, 0x1b, 0x01, 0x4a, 0x25, 0x9f, 0xb8, 0x39, 0x8f, 0xb2, 0xbd, - 0xf2, 0x7f, 0xbf, 0xb9, 0xeb, 0x7f, 0x8a, 0x0a, 0x37, 0x89, 0x0b, 0x30, - 0x93, 0x0a, 0x8b, 0x7f, 0xcb, 0x43, 0x0b, 0x43, 0x80, 0xb2, 0xd3, 0x7f, - 0xc1, 0x7f, 0x90, 0x2e, 0x87, 0xb2, 0x20, 0x25, 0x01, 0x2e, 0x64, 0x00, - 0x01, 0x90, 0x0e, 0x2f, 0x67, 0x52, 0x01, 0x2e, 0x61, 0x00, 0xb4, 0x7f, - 0xa2, 0x7f, 0x98, 0x2e, 0x8d, 0xb2, 0x00, 0x30, 0x21, 0x2e, 0x64, 0x00, - 0xc1, 0x6f, 0xd3, 0x6f, 0xa2, 0x6f, 0xb4, 0x6f, 0x0b, 0x30, 0x01, 0x2e, - 0x1b, 0x01, 0x06, 0xbc, 0x06, 0xbb, 0x57, 0x25, 0x01, 0x2e, 0x1b, 0x01, - 0x94, 0xb1, 0x05, 0xbc, 0xb6, 0x7f, 0x0f, 0xbb, 0x6b, 0x50, 0x80, 0xb3, - 0x0f, 0x2f, 0x0d, 0x2e, 0x1b, 0x01, 0x6f, 0x5e, 0xb7, 0x09, 0x2d, 0x2e, - 0x1b, 0x01, 0x71, 0x5c, 0x69, 0x5e, 0x9b, 0x43, 0x9b, 0x43, 0xdb, 0x43, - 0x9b, 0x43, 0x1b, 0x42, 0xcb, 0x43, 0x0b, 0x42, 0x8b, 0x43, 0x40, 0xb2, - 0x05, 0x2f, 0x69, 0x50, 0x00, 0x2e, 0x16, 0x40, 0x0b, 0x40, 0x76, 0x7f, - 0x8b, 0x7f, 0xcb, 0x0a, 0x01, 0x2e, 0x61, 0x00, 0x67, 0x52, 0x6d, 0x5c, - 0x98, 0x2e, 0xd3, 0xb2, 0x90, 0x6f, 0x00, 0xb2, 0x0b, 0x2f, 0xf0, 0x6f, - 0x00, 0xb2, 0x08, 0x2f, 0x69, 0x58, 0x6b, 0x50, 0x12, 0x41, 0x12, 0x42, - 0x21, 0x30, 0x04, 0x41, 0x04, 0x42, 0x23, 0x2e, 0x5e, 0xf0, 0xc0, 0x6f, - 0x00, 0xb2, 0x26, 0x2f, 0x74, 0x6f, 0x80, 0x6f, 0x71, 0x54, 0x88, 0xbd, - 0xc8, 0xb8, 0x4b, 0x0a, 0x94, 0x42, 0x91, 0x42, 0x90, 0x42, 0x88, 0xba, - 0x69, 0x52, 0xf3, 0x6f, 0x54, 0x42, 0x85, 0x42, 0xc0, 0x90, 0x40, 0x42, - 0x15, 0x2f, 0x6b, 0x52, 0x00, 0x2e, 0x52, 0x40, 0x41, 0x40, 0xa2, 0x04, - 0x41, 0x06, 0x40, 0xaa, 0x04, 0x2f, 0x40, 0x90, 0x0b, 0x2f, 0xb1, 0x6f, - 0x4a, 0x0f, 0x08, 0x2f, 0xb2, 0x6f, 0x80, 0xb2, 0x05, 0x2f, 0x6b, 0x54, - 0x21, 0x30, 0x94, 0x42, 0x80, 0x42, 0x23, 0x2e, 0x5e, 0xf0, 0xd0, 0x6f, - 0x00, 0xb2, 0x13, 0x2f, 0x01, 0x2e, 0x60, 0x00, 0x09, 0x2e, 0x7c, 0x00, - 0x04, 0x1a, 0x0d, 0x2f, 0x73, 0x50, 0x29, 0x2e, 0x60, 0x00, 0x24, 0x42, - 0x44, 0x30, 0x02, 0x40, 0x02, 0x42, 0x09, 0x80, 0x00, 0x2e, 0x04, 0x42, - 0x03, 0x2d, 0x10, 0x30, 0x21, 0x2e, 0x64, 0x00, 0xeb, 0x6f, 0x70, 0x5f, - 0xb8, 0x2e, 0x09, 0x86, 0x49, 0x54, 0xe4, 0x40, 0xc3, 0x80, 0x94, 0x04, - 0xc3, 0x40, 0x13, 0x05, 0x05, 0x40, 0x25, 0x05, 0x8a, 0x17, 0x73, 0x30, - 0x73, 0x09, 0x8c, 0x17, 0xf3, 0x08, 0xe3, 0x00, 0x4c, 0x82, 0x95, 0x00, - 0xb3, 0xb5, 0x23, 0xb5, 0x53, 0x42, 0x52, 0x42, 0x53, 0x42, 0x42, 0x42, - 0x71, 0x82, 0x75, 0x54, 0x52, 0x42, 0x10, 0x50, 0x77, 0x54, 0x52, 0x42, - 0xfb, 0x7f, 0x22, 0x30, 0x79, 0x56, 0x43, 0x42, 0x44, 0x82, 0x0b, 0x30, - 0x52, 0x42, 0x5b, 0x42, 0x7c, 0x84, 0x4b, 0x42, 0x35, 0x82, 0x8c, 0x80, - 0x8b, 0x42, 0x0b, 0x42, 0x39, 0x80, 0x04, 0x30, 0x0b, 0x42, 0x37, 0x80, - 0x15, 0x30, 0x60, 0x25, 0x98, 0x2e, 0xc6, 0xb2, 0x8b, 0x83, 0xfb, 0x6f, - 0x65, 0x42, 0xc0, 0x2e, 0x44, 0x42, 0xf0, 0x5f, 0x05, 0x80, 0x02, 0x30, - 0x51, 0x82, 0x02, 0x42, 0x13, 0x30, 0x41, 0x40, 0x4b, 0x08, 0x7b, 0x54, - 0x3e, 0x80, 0x51, 0x14, 0xc0, 0x2e, 0x01, 0x42, 0x00, 0x2e, 0x40, 0x51, - 0xd1, 0x7f, 0x12, 0x25, 0x02, 0x30, 0x42, 0x43, 0x32, 0x30, 0x82, 0x43, - 0xc6, 0x7f, 0xe5, 0x7f, 0xb4, 0x7f, 0xa3, 0x7f, 0x90, 0x7f, 0x8b, 0x7f, - 0x98, 0x2e, 0x54, 0x01, 0xc0, 0x7e, 0x00, 0xac, 0x01, 0x2f, 0x65, 0x50, - 0xc0, 0x7e, 0x00, 0x2e, 0x90, 0x6f, 0x09, 0x8a, 0xd1, 0x6f, 0x75, 0x7f, - 0x4c, 0x82, 0x63, 0x41, 0x65, 0x7f, 0x11, 0x7f, 0x00, 0x2e, 0x64, 0x41, - 0x44, 0x85, 0x52, 0x7f, 0x45, 0x7f, 0x00, 0x2e, 0xa6, 0x40, 0x80, 0x40, - 0x32, 0x7f, 0x82, 0x8e, 0xc2, 0x6e, 0x45, 0x41, 0xf0, 0x7f, 0x27, 0x7f, - 0x02, 0x7f, 0x98, 0x2e, 0x8a, 0xb1, 0x23, 0x6f, 0xd1, 0x6f, 0xc2, 0x40, - 0xf9, 0x86, 0x23, 0x7f, 0x80, 0xb2, 0xe0, 0x7e, 0x0f, 0x2f, 0x32, 0x6f, - 0x64, 0x6f, 0x82, 0x40, 0xf2, 0x7f, 0x4e, 0x82, 0x42, 0x6f, 0x50, 0x6f, - 0x73, 0x6f, 0x85, 0x40, 0xc3, 0x40, 0x04, 0x41, 0x06, 0x40, 0xe2, 0x6e, - 0x98, 0x2e, 0x8a, 0xb1, 0xe0, 0x7e, 0xf3, 0x31, 0x10, 0x6f, 0x36, 0x80, - 0xe1, 0x6e, 0x02, 0x40, 0x71, 0x7f, 0x51, 0x04, 0x02, 0x30, 0x40, 0xa8, - 0x91, 0x04, 0x4a, 0x22, 0x89, 0x16, 0x93, 0x08, 0x4a, 0x00, 0x95, 0xb4, - 0x09, 0x18, 0x8e, 0x16, 0x13, 0x30, 0x93, 0x08, 0x21, 0x6f, 0x60, 0x7f, - 0x4d, 0x86, 0x02, 0x80, 0xb2, 0x00, 0x41, 0x40, 0x21, 0xb5, 0x50, 0x7f, - 0x43, 0x7f, 0x98, 0x2e, 0xc2, 0xb1, 0x40, 0x6f, 0x62, 0x6f, 0x55, 0x6f, - 0x13, 0x40, 0x84, 0x40, 0x01, 0x40, 0x45, 0x41, 0x42, 0xbe, 0x1d, 0x18, - 0x4c, 0x04, 0x31, 0x0f, 0x04, 0x8a, 0xc0, 0x6f, 0x11, 0x30, 0x02, 0x2f, - 0x00, 0x2e, 0x03, 0x2c, 0x01, 0x42, 0x23, 0x30, 0x03, 0x42, 0x00, 0x2e, - 0xd6, 0x6f, 0x44, 0x41, 0x8a, 0x87, 0x76, 0x8b, 0x00, 0xb3, 0x53, 0x7f, - 0x15, 0x2f, 0x04, 0x6f, 0x7d, 0x5e, 0x8b, 0x8d, 0xe7, 0x01, 0xc0, 0xa5, - 0x84, 0x41, 0x01, 0x2f, 0x00, 0xa1, 0x03, 0x2f, 0xc0, 0xad, 0x08, 0x2f, - 0x00, 0xa5, 0x06, 0x2f, 0xc6, 0x40, 0x81, 0x8d, 0x07, 0x30, 0x3c, 0x05, - 0xd6, 0x42, 0x04, 0x2c, 0xc4, 0x42, 0x02, 0x2c, 0x07, 0x30, 0x07, 0x30, - 0x86, 0x86, 0x94, 0x6f, 0xd7, 0x7e, 0x0e, 0x8d, 0x00, 0x40, 0x74, 0x89, - 0xc7, 0x40, 0x02, 0xb2, 0xf9, 0x29, 0x45, 0x41, 0x86, 0x41, 0xbe, 0x80, - 0x21, 0x41, 0x75, 0x23, 0x82, 0x40, 0xc7, 0x42, 0x45, 0x7f, 0x34, 0x7f, - 0x20, 0x7f, 0x98, 0x2e, 0xc2, 0xb1, 0x31, 0x6f, 0x60, 0x6f, 0x24, 0x6f, - 0x22, 0x40, 0x05, 0x41, 0x43, 0x40, 0x13, 0x01, 0x43, 0x86, 0xac, 0x0f, - 0xd1, 0x6f, 0x30, 0x7f, 0x00, 0x2f, 0x44, 0x42, 0x48, 0x8a, 0x41, 0x88, - 0xe1, 0x40, 0x13, 0x7f, 0x04, 0x7f, 0xf5, 0x7e, 0x98, 0x2e, 0xc2, 0xb1, - 0x11, 0x6f, 0x60, 0x6f, 0x34, 0x6f, 0x42, 0x40, 0x03, 0x40, 0x9a, 0x04, - 0x04, 0x41, 0x43, 0x82, 0xa2, 0x0e, 0x03, 0x6f, 0x00, 0x2f, 0xc2, 0x42, - 0x00, 0x2e, 0x41, 0x40, 0x72, 0x6f, 0x98, 0x2e, 0xc2, 0xb1, 0x25, 0x6f, - 0x72, 0x6f, 0x53, 0x41, 0x93, 0x0e, 0xd1, 0x6f, 0x46, 0x80, 0x1b, 0x30, - 0x03, 0x30, 0x0c, 0x2f, 0x04, 0x40, 0x00, 0x91, 0x42, 0x42, 0x08, 0x2f, - 0xf6, 0x6e, 0x44, 0x6f, 0x86, 0x41, 0xb4, 0x0e, 0x03, 0x2f, 0x02, 0x88, - 0xdb, 0x7e, 0x03, 0x43, 0x0b, 0x42, 0x46, 0x8d, 0x44, 0x41, 0x47, 0x80, - 0x05, 0x6f, 0x94, 0x0f, 0x76, 0x7f, 0x60, 0x7f, 0x02, 0x2f, 0x45, 0x89, - 0x42, 0x43, 0x03, 0x43, 0x49, 0x88, 0xa5, 0x6f, 0x40, 0x91, 0xa4, 0x7f, - 0x15, 0x30, 0xe2, 0x6f, 0xd3, 0x6e, 0x03, 0x2f, 0x04, 0x30, 0x83, 0x42, - 0x80, 0x2e, 0x77, 0xb4, 0x04, 0x40, 0x25, 0x29, 0x04, 0x42, 0x83, 0x42, - 0x45, 0x82, 0x94, 0x6f, 0x04, 0x85, 0xc0, 0xb2, 0x90, 0x2e, 0x63, 0xb4, - 0x15, 0x87, 0x3c, 0x8c, 0xc4, 0x40, 0x46, 0x7f, 0xc2, 0x86, 0x07, 0x40, - 0x86, 0x41, 0xf4, 0xbf, 0x00, 0xb3, 0x0c, 0x2f, 0x90, 0x6f, 0x16, 0x80, - 0x46, 0x25, 0x00, 0x40, 0x57, 0x25, 0x04, 0x18, 0xae, 0x0e, 0x10, 0x30, - 0x06, 0x30, 0x75, 0x25, 0x46, 0x23, 0x60, 0x6f, 0x64, 0x25, 0xc4, 0x40, - 0xfa, 0x86, 0x00, 0xb3, 0x33, 0x7f, 0x09, 0x2f, 0x93, 0x6f, 0xd8, 0x88, - 0x53, 0x6f, 0x04, 0x41, 0xc3, 0x40, 0xdc, 0x0e, 0x13, 0x30, 0x04, 0x30, - 0xdc, 0x22, 0xb3, 0x25, 0x40, 0xb3, 0x02, 0x2f, 0x3b, 0x25, 0xc0, 0x90, - 0x05, 0x2f, 0x91, 0x6f, 0xd0, 0x6f, 0x98, 0x2e, 0xc6, 0xb2, 0x4d, 0x2c, - 0x04, 0x30, 0x8d, 0x88, 0x43, 0x40, 0x82, 0x40, 0x54, 0x7f, 0xda, 0x0f, - 0x04, 0x30, 0x08, 0x2f, 0xc1, 0x80, 0x40, 0x42, 0xc2, 0x0f, 0x02, 0x2f, - 0x00, 0x30, 0xc0, 0x7e, 0x1b, 0x2d, 0xc0, 0x7e, 0x19, 0x2d, 0xe1, 0xbc, - 0x92, 0x6f, 0x4f, 0x04, 0x90, 0x84, 0x40, 0xa8, 0x21, 0x05, 0x83, 0x40, - 0x4c, 0x22, 0x4b, 0x0e, 0xb6, 0x84, 0x21, 0x30, 0x02, 0x2f, 0x11, 0x30, - 0x04, 0x2c, 0xc1, 0x7e, 0xe3, 0x6f, 0xc1, 0x7e, 0xc1, 0x42, 0x00, 0x2e, - 0x00, 0x40, 0x81, 0x40, 0x04, 0xbd, 0x40, 0x6f, 0x98, 0x2e, 0xc2, 0xb1, - 0x50, 0x6f, 0x11, 0x30, 0x02, 0x40, 0x51, 0x08, 0xc3, 0x6e, 0x03, 0x80, - 0x99, 0x15, 0x0b, 0x40, 0xb1, 0x6f, 0xd0, 0x6f, 0xb6, 0x7f, 0x5b, 0x7f, - 0x04, 0x30, 0x4d, 0x54, 0x03, 0x30, 0x11, 0x2c, 0x10, 0x80, 0x55, 0x6f, - 0x06, 0x40, 0x75, 0x01, 0x58, 0xbb, 0x6a, 0x09, 0x05, 0x42, 0xc1, 0x86, - 0x47, 0x40, 0x51, 0x25, 0xbe, 0x01, 0x56, 0x43, 0x00, 0x2e, 0x46, 0x41, - 0xf4, 0x03, 0xb6, 0x6f, 0x47, 0x43, 0x5e, 0x0e, 0xed, 0x2f, 0x31, 0x6f, - 0x60, 0x6f, 0x42, 0x40, 0x15, 0x30, 0x02, 0x82, 0x95, 0x08, 0x04, 0x42, - 0x52, 0x42, 0x02, 0x2c, 0x44, 0x42, 0x04, 0x30, 0x3e, 0x8e, 0x91, 0x6f, - 0x4f, 0x8c, 0x02, 0x40, 0x83, 0x41, 0xb5, 0x8d, 0x93, 0x0e, 0xd0, 0x6f, - 0x01, 0x2f, 0x98, 0x2e, 0xc6, 0xb2, 0x00, 0x2e, 0xc0, 0x41, 0x81, 0x41, - 0xc1, 0x0f, 0xc0, 0x6f, 0x01, 0x2f, 0x04, 0x42, 0x00, 0x2e, 0x70, 0x6f, - 0x3c, 0x82, 0x00, 0x40, 0x41, 0x40, 0x89, 0x16, 0x95, 0x08, 0x4a, 0x00, - 0x04, 0xbc, 0x91, 0xb4, 0x01, 0x0e, 0xe0, 0x6f, 0x07, 0x2f, 0xa1, 0x6f, - 0x00, 0x2e, 0x41, 0x40, 0x40, 0xb2, 0x02, 0x2f, 0xa1, 0x6f, 0x05, 0x42, - 0x44, 0x42, 0x00, 0x2e, 0x8b, 0x6f, 0xc0, 0x5e, 0xb8, 0x2e, 0x03, 0x2e, - 0x1c, 0x01, 0x9c, 0xbc, 0x1d, 0xb9, 0x02, 0x82, 0x25, 0x2e, 0x8e, 0x00, - 0x83, 0x56, 0x13, 0x18, 0x01, 0x2e, 0x66, 0x00, 0x43, 0x40, 0xd8, 0x04, - 0x05, 0x2e, 0x65, 0x00, 0x40, 0x50, 0x27, 0x2e, 0x65, 0x00, 0xfb, 0x7f, - 0xda, 0x05, 0x8b, 0x50, 0x4b, 0x40, 0x02, 0x40, 0x81, 0x82, 0x01, 0x42, - 0x03, 0x80, 0x81, 0x52, 0xb1, 0x00, 0x03, 0x40, 0x3b, 0x82, 0x85, 0x58, - 0x14, 0x01, 0xc0, 0xb2, 0x37, 0x2e, 0x66, 0x00, 0xd1, 0x7f, 0xe2, 0x7f, - 0x04, 0x2f, 0x05, 0x2e, 0x6b, 0x00, 0x81, 0x84, 0x25, 0x2e, 0x6b, 0x00, - 0x62, 0x40, 0x3a, 0x0f, 0x45, 0x40, 0xc1, 0x7f, 0x21, 0x30, 0x12, 0x30, - 0x42, 0x2f, 0x0d, 0x2e, 0x69, 0x00, 0x3e, 0x0e, 0x33, 0x2f, 0x05, 0x2e, - 0x6a, 0x00, 0x01, 0x35, 0x91, 0x0e, 0x01, 0x30, 0x03, 0x2f, 0x09, 0x2e, - 0x6e, 0x00, 0x00, 0xb3, 0x24, 0x2f, 0xc0, 0x35, 0x90, 0x0e, 0x39, 0x2f, - 0x8f, 0x50, 0x02, 0x30, 0x01, 0x40, 0x7f, 0x82, 0x43, 0xa2, 0x02, 0x2f, - 0x00, 0x2e, 0x0c, 0x2c, 0x01, 0x30, 0xc0, 0xb2, 0x11, 0x30, 0x02, 0x2f, - 0x25, 0x2e, 0x6d, 0x00, 0x03, 0x2d, 0x23, 0x2e, 0x6d, 0x00, 0x21, 0x30, - 0x25, 0x2e, 0x6b, 0x00, 0x42, 0xb2, 0x04, 0x2f, 0x41, 0xb2, 0x02, 0x2f, - 0x25, 0x2e, 0x6d, 0x00, 0x31, 0x30, 0x3e, 0x80, 0x04, 0x86, 0x25, 0x2e, - 0x6c, 0x00, 0x02, 0x42, 0xc2, 0x42, 0x18, 0x2d, 0x02, 0x35, 0x01, 0x42, - 0x25, 0x2e, 0x6a, 0x00, 0x13, 0x2d, 0x2c, 0x04, 0x38, 0x1e, 0x21, 0x2e, - 0x69, 0x00, 0x7f, 0x50, 0x11, 0x30, 0x22, 0x30, 0x98, 0x2e, 0x66, 0xb5, - 0x09, 0x2c, 0x01, 0x30, 0x2c, 0x00, 0x38, 0x1c, 0x21, 0x2e, 0x68, 0x00, - 0x7f, 0x50, 0x98, 0x2e, 0x66, 0xb5, 0x01, 0x30, 0xc0, 0x6f, 0xd4, 0xb1, - 0xf5, 0xbd, 0x6b, 0xba, 0x91, 0x5a, 0x02, 0x40, 0x15, 0x18, 0xf5, 0xbe, - 0xeb, 0xbb, 0xe3, 0x0a, 0x3d, 0x0b, 0xd2, 0x6f, 0xe3, 0x00, 0x84, 0x40, - 0x63, 0x05, 0x93, 0x58, 0x2c, 0x18, 0xf5, 0xbe, 0x03, 0x42, 0xeb, 0xbb, - 0xfd, 0x0b, 0xe0, 0x6f, 0x58, 0x01, 0xdf, 0x01, 0x7d, 0x1f, 0x95, 0x42, - 0x18, 0x04, 0x85, 0x40, 0x5d, 0x05, 0x2c, 0x18, 0x75, 0xbe, 0xeb, 0xba, - 0x2c, 0x0b, 0xdc, 0x04, 0x18, 0x1c, 0x80, 0x42, 0x84, 0x80, 0x02, 0x30, - 0x00, 0x40, 0x00, 0xb2, 0x0c, 0x2f, 0x01, 0x2e, 0x6b, 0x00, 0x03, 0x35, - 0x83, 0x0e, 0x07, 0x2f, 0x8d, 0x50, 0x3e, 0x80, 0x25, 0x2e, 0x6d, 0x00, - 0x02, 0x42, 0x03, 0x80, 0x00, 0x2e, 0x02, 0x42, 0x40, 0xb2, 0x04, 0x2f, - 0x8b, 0x50, 0x04, 0x80, 0x25, 0x2e, 0x6a, 0x00, 0x02, 0x42, 0x42, 0xb2, - 0x89, 0x56, 0x9a, 0x22, 0x41, 0xb2, 0x01, 0x2e, 0x1c, 0x01, 0x87, 0x52, - 0x0b, 0xbc, 0x8a, 0x22, 0x0f, 0xb8, 0x00, 0x90, 0x01, 0x32, 0x06, 0x2f, - 0x10, 0x30, 0x90, 0x08, 0x80, 0xb2, 0x08, 0x2f, 0x23, 0x2e, 0x5e, 0xf0, - 0x06, 0x2d, 0x20, 0x30, 0x90, 0x08, 0x80, 0xb2, 0x01, 0x2f, 0x23, 0x2e, - 0x5e, 0xf0, 0xfb, 0x6f, 0xc0, 0x5f, 0xb8, 0x2e, 0x07, 0x86, 0xfc, 0x88, - 0xc6, 0x40, 0x05, 0x41, 0x31, 0x1a, 0x12, 0x2f, 0x80, 0x91, 0x22, 0x2f, - 0x01, 0x35, 0x29, 0x0f, 0x0a, 0x2f, 0x06, 0x80, 0x00, 0x2e, 0x00, 0x40, - 0x00, 0xb2, 0x01, 0x2f, 0x44, 0xa9, 0x03, 0x2f, 0x00, 0x30, 0xc0, 0x42, - 0x00, 0x43, 0xb8, 0x2e, 0xc2, 0x42, 0x01, 0x43, 0xb8, 0x2e, 0x01, 0x35, - 0xa9, 0x0e, 0x0e, 0x2f, 0x03, 0x3b, 0xeb, 0x00, 0xcc, 0xa8, 0x0a, 0x2f, - 0x05, 0x86, 0xc2, 0x80, 0xc3, 0x40, 0x02, 0x42, 0x3c, 0x84, 0xc1, 0x80, - 0x81, 0x42, 0x82, 0x84, 0xc0, 0x2e, 0x80, 0x42, 0x00, 0x2e, 0xb8, 0x2e, - 0x03, 0x2e, 0x1d, 0x01, 0x9f, 0xbc, 0x9f, 0xb8, 0x90, 0x50, 0x40, 0xb2, - 0x90, 0x2e, 0x71, 0xb6, 0x12, 0x40, 0x03, 0x30, 0x11, 0x40, 0x80, 0xa8, - 0x5a, 0x05, 0x9f, 0x58, 0x55, 0x23, 0x00, 0x40, 0x75, 0x7f, 0x40, 0xa8, - 0x16, 0x41, 0xd9, 0x05, 0xcf, 0x23, 0x56, 0x05, 0x40, 0xa9, 0x9d, 0x05, - 0x87, 0x7f, 0x6e, 0x23, 0x17, 0x41, 0xa5, 0x7f, 0x3e, 0x8b, 0x04, 0x41, - 0x52, 0x43, 0x00, 0xa8, 0x98, 0x05, 0xf2, 0x7f, 0x86, 0x22, 0xcf, 0x05, - 0xc0, 0xa9, 0x9f, 0x05, 0xbe, 0x23, 0x04, 0x05, 0x92, 0x7f, 0x00, 0xa9, - 0xdc, 0x05, 0x51, 0x43, 0xb6, 0x7f, 0x27, 0x23, 0xa7, 0x54, 0xe1, 0x7f, - 0x02, 0x18, 0x7d, 0x83, 0x40, 0x43, 0xeb, 0xba, 0x75, 0xbd, 0xaa, 0x0a, - 0x0b, 0x2e, 0x71, 0x00, 0x77, 0x5c, 0x2e, 0x18, 0xf5, 0xbe, 0x6b, 0xbb, - 0x75, 0x0b, 0xaa, 0x00, 0xc4, 0x7f, 0x25, 0x2e, 0x71, 0x00, 0xb2, 0x6f, - 0xa5, 0x6f, 0xaa, 0x00, 0x54, 0x01, 0x84, 0x6f, 0x72, 0x6f, 0x94, 0x05, - 0x80, 0xa9, 0xde, 0x05, 0xb7, 0x23, 0x99, 0x5e, 0x77, 0x0e, 0x41, 0x40, - 0x97, 0x5c, 0xb1, 0x01, 0xd5, 0x7f, 0x00, 0x2e, 0x85, 0x41, 0x0e, 0x2f, - 0x00, 0xa0, 0x0c, 0x2f, 0x14, 0x0f, 0x04, 0x2f, 0xe0, 0x6f, 0x00, 0xac, - 0x10, 0x30, 0x08, 0x2c, 0x18, 0x22, 0xf0, 0x6f, 0x00, 0xac, 0x30, 0x30, - 0x24, 0x30, 0x02, 0x2c, 0x20, 0x22, 0x40, 0x30, 0x0d, 0x2e, 0x71, 0x00, - 0x80, 0xa1, 0x1e, 0x23, 0x79, 0x5e, 0x37, 0x0f, 0xbc, 0x23, 0x00, 0x90, - 0x14, 0x30, 0x10, 0x30, 0x18, 0x2f, 0x9d, 0x50, 0x30, 0x00, 0x9b, 0x56, - 0x43, 0x0e, 0x02, 0x2f, 0x10, 0x30, 0x0a, 0x2c, 0x03, 0x30, 0x99, 0x50, - 0x10, 0x0e, 0x13, 0x30, 0x00, 0x2f, 0x03, 0x30, 0x90, 0x0f, 0x10, 0x30, - 0x00, 0x2f, 0x00, 0x30, 0x00, 0x90, 0x10, 0x30, 0x00, 0x2f, 0x00, 0x30, - 0xc0, 0x90, 0x13, 0x30, 0x00, 0x2f, 0x03, 0x30, 0x40, 0xb2, 0x87, 0x5c, - 0x22, 0x2f, 0x41, 0x90, 0x4a, 0x2f, 0xa5, 0x50, 0x00, 0x2e, 0x01, 0x40, - 0x41, 0x82, 0x01, 0x42, 0x02, 0x80, 0x4a, 0xa8, 0x01, 0x40, 0x06, 0x2f, - 0xd0, 0x6f, 0x85, 0x0e, 0x3e, 0x2f, 0x41, 0x80, 0x21, 0x2e, 0x78, 0x00, - 0x3b, 0x2d, 0x95, 0x50, 0xfb, 0x7f, 0x4a, 0xa8, 0x06, 0x2f, 0x98, 0x2e, - 0x73, 0xb6, 0xc0, 0x90, 0xfb, 0x6f, 0x32, 0x2f, 0x00, 0x2e, 0x30, 0x2d, - 0x98, 0x2e, 0x73, 0xb6, 0x29, 0x2e, 0x7a, 0x00, 0x2b, 0x2c, 0xfb, 0x6f, - 0xa1, 0x52, 0xd2, 0x6f, 0x95, 0x0e, 0x41, 0x40, 0x05, 0x2f, 0x00, 0x90, - 0x17, 0x2f, 0x05, 0x2e, 0x7a, 0x00, 0x80, 0x90, 0x13, 0x2f, 0x7f, 0x82, - 0x40, 0xac, 0x23, 0x2e, 0x77, 0x00, 0x01, 0x30, 0x18, 0x2f, 0xa1, 0x54, - 0x82, 0x84, 0x23, 0x2e, 0x77, 0x00, 0x82, 0x40, 0x80, 0xb2, 0x11, 0x2f, - 0x00, 0x90, 0x23, 0x2e, 0x79, 0x00, 0x0d, 0x2f, 0x29, 0x2e, 0x72, 0x00, - 0x0b, 0x2d, 0x41, 0x80, 0x21, 0x2e, 0x77, 0x00, 0x0f, 0xa4, 0x05, 0x2f, - 0xa3, 0x50, 0x3e, 0x80, 0xf1, 0x30, 0x29, 0x2e, 0x79, 0x00, 0x01, 0x42, - 0x06, 0x30, 0x34, 0x08, 0x00, 0xb2, 0x02, 0x2f, 0x80, 0x30, 0x21, 0x2e, - 0x5e, 0xf0, 0x70, 0x5f, 0xb8, 0x2e, 0x04, 0x84, 0x01, 0x30, 0x81, 0x42, - 0x82, 0x84, 0x01, 0x42, 0xa1, 0x42, 0x81, 0x42, 0x82, 0x84, 0x00, 0x2e, - 0x91, 0x42, 0x81, 0x42, 0xb8, 0x2e, 0x30, 0x50, 0xf3, 0x7f, 0xc0, 0xac, - 0xe4, 0x7f, 0xd5, 0x7f, 0x03, 0x2f, 0x00, 0x30, 0x82, 0x04, 0xf3, 0x6f, - 0xc3, 0x06, 0x40, 0xad, 0x05, 0x2f, 0xe0, 0x6f, 0x05, 0x30, 0x28, 0x04, - 0xd1, 0x6f, 0x69, 0x07, 0xe0, 0x7f, 0x40, 0xa1, 0x01, 0x30, 0x20, 0x2f, - 0x13, 0x25, 0x02, 0x25, 0x04, 0x32, 0x06, 0x30, 0x02, 0x30, 0x03, 0x30, - 0xaf, 0xbb, 0xb1, 0xbd, 0xdf, 0x0a, 0x9f, 0xbb, 0x21, 0xbd, 0x97, 0x0a, - 0x8f, 0xbb, 0x91, 0xbc, 0x01, 0xbc, 0x4f, 0x0a, 0x6b, 0x0e, 0x04, 0x2f, - 0x6b, 0x1a, 0x07, 0x2f, 0xe7, 0x6f, 0x7a, 0x0f, 0x04, 0x2f, 0xe7, 0x6f, - 0x97, 0x04, 0x17, 0x30, 0x07, 0x0a, 0xdd, 0x06, 0x81, 0x8d, 0x34, 0x0e, - 0xe6, 0x2f, 0x00, 0x2e, 0x0d, 0x2d, 0x6b, 0x0e, 0x00, 0x30, 0x05, 0x2f, - 0x6b, 0x1a, 0x07, 0x2f, 0xe0, 0x6f, 0x42, 0x0f, 0x00, 0x30, 0x03, 0x2f, - 0xe0, 0x6f, 0x90, 0x04, 0xdd, 0x06, 0x10, 0x30, 0xf5, 0x6f, 0xc3, 0x7f, - 0xb2, 0x7f, 0x40, 0xad, 0x06, 0x2f, 0x03, 0x30, 0xb2, 0x6f, 0x9a, 0x04, - 0xc4, 0x6f, 0xdc, 0x06, 0xb2, 0x7f, 0xc3, 0x7f, 0x00, 0x2e, 0xd2, 0x6f, - 0xaa, 0x0c, 0x80, 0xac, 0x02, 0x30, 0x01, 0x2f, 0x10, 0x04, 0x51, 0x06, - 0xd0, 0x5f, 0xb8, 0x2e, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00 -}; - -/***************************************************************************/ -/*! Static Function Declarations -****************************************************************************/ -/*! - * @brief This API update the length for read and write. - * - * @param[in] len : Length for read and write - * @param[in] feature : Variable to specify the features - * which are to be set in the sensor. - * @param[in] enable : Variable which specifies whether to enable or - * disable the features in the bma455 sensor. - * enable | Macros - * ----------------|------------------- - * 0x01 | BMA4_EN - * 0x00 | BMA4_DIS - * @param[in] dev : Structure instance of bma4_dev. - * - * @return none - */ -static void update_len(uint8_t *len, uint8_t feature, uint8_t enable); - -/*! - * @brief This API enables the features of sensor. - * - * @param[in] feature : Variable to specify the features - * which are to be set in the sensor. - * @param[in] len : length to read and write - * @param[in] feature_config : Array address which stores the feature - * configuration data - * @param[in] dev : Structure instance of bma4_dev. - * - * @return Result of API execution status - * @retval 0 -> Success - * @retval Any positive value mentioned in ERROR CODES -> Fail - */ -static uint16_t feature_enable(uint8_t feature, uint8_t len, uint8_t *feature_config, struct bma4_dev *dev); - -/*! - * @brief This API disables the features of sensor. - * - * @param[in] feature : Variable to specify the features - * which are to be unset in the sensor. - * @param[in] len : length to read and write - * @param[in] feature_config : Array address which stores the feature - * configuration data - * @param[in] dev : Structure instance of bma4_dev. - * - * @return Result of API execution status - * @retval 0 -> Success - * @retval Any positive value mentioned in ERROR CODES -> Fail - */ -static uint16_t feature_disable(uint8_t feature, uint8_t len, uint8_t *feature_config, struct bma4_dev *dev); - -/*! - * @brief This API update the settings of step counter into write array. - * - * @param[in] setting : Pointer to structure variable which stores the - * settings parameter1 to parameter25. - * @param[in] index : value for array traversing. - * @param[out] feature_config : Pointer to store the settings - * - * @return none - */ -static void update_stepcounter_parameter(const struct bma423_stepcounter_settings *setting, - uint8_t index, uint8_t *feature_config); -/*! - * @brief This API copy the settings of step counter into the - * structure of bma423_stepcounter_settings, which is read from sensor. - * - * @param[out] setting : Pointer to structure variable which stores the - * settings parameter1 to parameter25 read from sensor. - * @param[in] data_p : Pointer of array which stores the parameters. - * - * @return none - */ -static void extract_stepcounter_parameter(struct bma423_stepcounter_settings *setting, const uint16_t *data_p); - -/***************************************************************************/ -/**\name Function definitions -****************************************************************************/ - -/*! - * @brief This API is the entry point. - * Call this API before using all other APIs. - * This API reads the chip-id of the sensor and sets the resolution. - */ -#include -uint16_t bma423_init(struct bma4_dev *dev) -{ - uint16_t rslt; - - rslt = bma4_init(dev); - - if (rslt == BMA4_OK) { - if (dev->chip_id == BMA423_CHIP_ID) { - /* Resolution of BMA423 sensor is 12 bit */ - dev->resolution = 12; - dev->feature_len = BMA423_FEATURE_SIZE; - dev->variant = BMA42X_VARIANT; - } else { - rslt |= BMA4_E_INVALID_SENSOR; - } - } - - return rslt; -} - -/*! - * @brief This API is used to upload the config file to enable - * the features of the sensor. - */ -uint16_t bma423_write_config_file(struct bma4_dev *dev) -{ - uint16_t rslt = BMA4_OK; - - if (dev != NULL) { - if (dev->chip_id == BMA423_CHIP_ID) { - /* Config. stream read/write length boundary check */ - if ((dev->read_write_len >= BMA423_RD_WR_MIN_LEN) && - (dev->read_write_len <= BMA423_FEATURE_SIZE)) { - /* Even or odd check */ - if ((dev->read_write_len % 2) != 0) - dev->read_write_len = dev->read_write_len - 1; - /*Assign stream data */ - dev->config_file_ptr = bma423_config_file; - rslt = bma4_write_config_file(dev); - } else { - rslt = BMA4_E_RD_WR_LENGTH_INVALID; - } - } else { - rslt = BMA4_E_INVALID_SENSOR; - } - } else { - rslt = BMA4_E_NULL_PTR; - } - return rslt; -} - -/*! - * @brief This API is used to get the configuration id of the sensor. - */ -uint16_t bma423_get_config_id(uint16_t *config_id, struct bma4_dev *dev) -{ - uint8_t feature_config[BMA423_FEATURE_SIZE] = {0}; - uint8_t index = BMA423_CONFIG_ID_OFFSET; - uint16_t rslt = BMA4_OK; - uint16_t config_id_lsb = 0; - uint16_t config_id_msb = 0; - - if (dev != NULL) { - if (dev->chip_id == BMA423_CHIP_ID) { - rslt = bma4_read_regs(BMA4_FEATURE_CONFIG_ADDR, feature_config, BMA423_FEATURE_SIZE, dev); - if (rslt == BMA4_OK) { - config_id_lsb = (uint16_t)feature_config[index]; - config_id_msb = ((uint16_t)feature_config[index + 1]) << 8; - *config_id = config_id_lsb | config_id_msb; - } - } else { - rslt = BMA4_E_INVALID_SENSOR; - } - } else { - rslt = BMA4_E_NULL_PTR; - } - - return rslt; -} - -/*! - * @brief This API sets/unsets the user provided interrupt to either - * interrupt pin1 or pin2 in the sensor. - */ -uint16_t bma423_map_interrupt(uint8_t int_line, uint16_t int_map, uint8_t enable, struct bma4_dev *dev) -{ - uint16_t rslt = BMA4_OK; - - if (dev != NULL) { - if (dev->chip_id == BMA423_CHIP_ID) { - if (int_line <= 1) { - /* Map/Unmap the interrupt */ - rslt = bma4_map_interrupt(int_line, int_map, enable, dev); - } else { - rslt = BMA4_E_INT_LINE_INVALID; - } - } else { - rslt = BMA4_E_INVALID_SENSOR; - } - } else { - rslt = BMA4_E_NULL_PTR; - } - - return rslt; -} - -/*! - * @brief This API reads the bma423 interrupt status from the sensor. - */ -uint16_t bma423_read_int_status(uint16_t *int_status, struct bma4_dev *dev) -{ - uint16_t rslt = BMA4_OK; - - if (dev != NULL) { - if (dev->chip_id == BMA423_CHIP_ID) { - /* Read the interrupt status */ - rslt = bma4_read_int_status(int_status, dev); - } else { - rslt = BMA4_E_INVALID_SENSOR; - } - } else { - rslt = BMA4_E_NULL_PTR; - } - - return rslt; -} - -/*! - * @brief This API enables/disables the features of the sensor. - */ -uint16_t bma423_feature_enable(uint8_t feature, uint8_t enable, struct bma4_dev *dev) -{ - uint8_t feature_config[BMA423_FEATURE_SIZE] = {0}; - uint16_t rslt = BMA4_OK; - uint8_t len; - - if (dev != NULL) { - if (dev->chip_id == BMA423_CHIP_ID) { - /* Update the length for read and write */ - update_len(&len, feature, enable); - rslt = bma4_read_regs(BMA4_FEATURE_CONFIG_ADDR, feature_config, len, dev); - if (rslt == BMA4_OK) { - if (enable == TRUE) { - /* Enables the feature */ - rslt |= feature_enable(feature, len, feature_config, dev); - } else { - /* Disables the feature */ - rslt |= feature_disable(feature, len, feature_config, dev); - } - } - } else { - rslt = BMA4_E_INVALID_SENSOR; - } - } else { - rslt = BMA4_E_NULL_PTR; - } - - return rslt; -} - -/*! - * @brief This API performs x, y and z axis remapping in the sensor. - */ -uint16_t bma423_set_remap_axes(const struct bma423_axes_remap *remap_data, struct bma4_dev *dev) -{ - uint8_t feature_config[BMA423_FEATURE_SIZE] = {0}; - uint8_t index = BMA423_AXES_REMAP_OFFSET; - uint16_t rslt = BMA4_OK; - uint8_t x_axis = 0; - uint8_t x_axis_sign = 0; - uint8_t y_axis = 0; - uint8_t y_axis_sign = 0; - uint8_t z_axis = 0; - - if (dev != NULL) { - if (dev->chip_id == BMA423_CHIP_ID) { - rslt = bma4_read_regs(BMA4_FEATURE_CONFIG_ADDR, feature_config, BMA423_FEATURE_SIZE, dev); - if (rslt == BMA4_OK) { - x_axis = remap_data->x_axis & BMA423_X_AXIS_MASK; - x_axis_sign = (remap_data->x_axis_sign << 2) & BMA423_X_AXIS_SIGN_MASK; - y_axis = (remap_data->y_axis << 3) & BMA423_Y_AXIS_MASK; - y_axis_sign = (remap_data->y_axis_sign << 5) & BMA423_Y_AXIS_SIGN_MASK; - z_axis = (remap_data->z_axis << 6) & BMA423_Z_AXIS_MASK; - feature_config[index] = x_axis | x_axis_sign | y_axis | y_axis_sign | z_axis; - feature_config[index + 1] = remap_data->z_axis_sign & BMA423_Z_AXIS_SIGN_MASK; - rslt |= bma4_write_regs(BMA4_FEATURE_CONFIG_ADDR, feature_config, - BMA423_FEATURE_SIZE, dev); - } - } else { - rslt = BMA4_E_INVALID_SENSOR; - } - } else { - rslt = BMA4_E_NULL_PTR; - } - - return rslt; -} - -/*! - * @brief This API reads the x, y and z axis remap data from the sensor. - */ -uint16_t bma423_get_remap_axes(struct bma423_axes_remap *remap_data, struct bma4_dev *dev) -{ - uint8_t feature_config[BMA423_FEATURE_SIZE] = {0}; - uint8_t index = BMA423_AXES_REMAP_OFFSET; - uint16_t rslt = BMA4_OK; - - if (dev != NULL) { - if (dev->chip_id == BMA423_CHIP_ID) { - rslt = bma4_read_regs(BMA4_FEATURE_CONFIG_ADDR, feature_config, BMA423_FEATURE_SIZE, dev); - if (rslt == BMA4_OK) { - remap_data->x_axis = feature_config[index] & BMA423_X_AXIS_MASK; - remap_data->x_axis_sign = (feature_config[index] & BMA423_X_AXIS_SIGN_MASK) >> 2; - remap_data->y_axis = (feature_config[index] & BMA423_Y_AXIS_MASK) >> 3; - remap_data->y_axis_sign = (feature_config[index] & BMA423_Y_AXIS_SIGN_MASK) >> 5; - remap_data->z_axis = (feature_config[index] & BMA423_Z_AXIS_MASK) >> 6; - remap_data->z_axis_sign = (feature_config[index + 1] & BMA423_Z_AXIS_SIGN_MASK); - } - } else { - rslt = BMA4_E_INVALID_SENSOR; - } - } else { - rslt = BMA4_E_NULL_PTR; - } - - return rslt; -} - -/*! - * @brief This API enables the any motion feature according to the axis - * set by the user in the sensor. - */ -uint16_t bma423_anymotion_enable_axis(uint8_t axis, struct bma4_dev *dev) -{ - uint8_t feature_config[BMA423_ANYMOTION_EN_LEN + 2] = {0}; - /* Anymotion axis enable bit pos. is 3 byte ahead of the - anymotion base address(0x00) */ - uint8_t index = 3; - uint16_t rslt = BMA4_OK; - - if (dev != NULL) { - if (dev->chip_id == BMA423_CHIP_ID) { - rslt = bma4_read_regs(BMA4_FEATURE_CONFIG_ADDR, feature_config, - BMA423_ANYMOTION_EN_LEN + 2, dev); - if (rslt == BMA4_OK) { - feature_config[index] = BMA4_SET_BITSLICE(feature_config[index], - BMA423_ANY_NO_MOTION_AXIS_EN, axis); - rslt |= bma4_write_regs(BMA4_FEATURE_CONFIG_ADDR, feature_config, - BMA423_ANYMOTION_EN_LEN + 2, dev); - } - } else { - rslt = BMA4_E_INVALID_SENSOR; - } - } else { - rslt = BMA4_E_NULL_PTR; - } - - return rslt; -} - -/*! @brief This API sets the configuration of Any motion feature in - * the sensor. - */ -uint16_t bma423_set_any_motion_config(const struct bma423_anymotion_config *any_motion, struct bma4_dev *dev) -{ - uint8_t feature_config[BMA423_ANYMOTION_EN_LEN + 2] = {0}; - uint8_t index = BMA423_ANY_NO_MOTION_OFFSET; - uint16_t duration_lsb = 0; - uint16_t duration_msb = 0; - uint16_t duration = 0; - uint16_t rslt = BMA4_OK; - - if (dev != NULL) { - if (dev->chip_id == BMA423_CHIP_ID) { - rslt = bma4_read_regs(BMA4_FEATURE_CONFIG_ADDR, feature_config, - BMA423_ANYMOTION_EN_LEN + 2, dev); - if (rslt == BMA4_OK) { - /* Assign threshold value in feature config array */ - feature_config[index++] = BMA4_GET_LSB(any_motion->threshold); - feature_config[index] = BMA4_GET_MSB(any_motion->threshold); - /* Assign no motion selection value in feature config array*/ - feature_config[index++] |= (uint8_t) - (any_motion->nomotion_sel << BMA423_ANY_NO_MOTION_SEL_POS); - - /* Extract duration */ - duration_lsb = feature_config[index]; - duration_msb = feature_config[index + 1] << 8; - duration = duration_lsb | duration_msb; - duration = BMA4_SET_BITS_POS_0(duration, - BMA423_ANY_NO_MOTION_DUR, any_motion->duration); - /* Assign duration value in feature config array*/ - feature_config[index++] = BMA4_GET_LSB(duration); - feature_config[index] = BMA4_GET_MSB(duration); - - /* Write any motion settings to the sensor*/ - rslt |= bma4_write_regs(BMA4_FEATURE_CONFIG_ADDR, feature_config, - BMA423_ANYMOTION_EN_LEN + 2, dev); - } - } else { - rslt = BMA4_E_INVALID_SENSOR; - } - } else { - rslt = BMA4_E_NULL_PTR; - } - - return rslt; -} - -/*! @brief This API gets the configuration of any motion feature from - * the sensor. - */ -uint16_t bma423_get_any_motion_config(struct bma423_anymotion_config *any_motion, struct bma4_dev *dev) -{ - uint8_t feature_config[BMA423_ANYMOTION_EN_LEN + 2] = {0}; - uint8_t anymotion = 0; - uint16_t rslt = BMA4_OK; - uint16_t *data_p = (uint16_t *)feature_config; - - if (dev != NULL) { - if (dev->chip_id == BMA423_CHIP_ID) { - rslt = bma4_read_regs(BMA4_FEATURE_CONFIG_ADDR, feature_config, - BMA423_ANYMOTION_EN_LEN + 2, dev); - if (rslt == BMA4_OK) { - /* Extract threshold value */ - any_motion->threshold = (*data_p) & BMA423_ANY_NO_MOTION_THRES_MSK; - /* Extract threshold & nomotion selection - * data */ - anymotion = ((uint8_t)(*(data_p++) >> 8)) & BMA423_ANY_NO_MOTION_SEL_MSK; - /* Extract no motion field */ - any_motion->nomotion_sel = anymotion >> - BMA423_ANY_NO_MOTION_SEL_POS; - /* Extract duration value */ - any_motion->duration = (*(data_p)) & BMA423_ANY_NO_MOTION_DUR_MSK; - } - } else { - rslt = BMA4_E_INVALID_SENSOR; - } - } else { - rslt = BMA4_E_NULL_PTR; - } - - return rslt; -} - -/*! - * @brief This API enables or disables the step detector feature in the - * sensor. - */ -uint16_t bma423_step_detector_enable(uint8_t enable, struct bma4_dev *dev) -{ - uint8_t feature_config[BMA423_FEATURE_SIZE] = {0}; - uint16_t rslt = BMA4_OK; - /* Step detector enable bit pos. is 1 byte ahead of the base address */ - uint8_t index = BMA423_STEP_CNTR_OFFSET + 1; - - if (dev != NULL) { - if (dev->chip_id == BMA423_CHIP_ID) { - rslt = bma4_read_regs(BMA4_FEATURE_CONFIG_ADDR, feature_config, - BMA423_FEATURE_SIZE, dev); - if (rslt == BMA4_OK) { - feature_config[index] = BMA4_SET_BITSLICE(feature_config[index], - BMA423_STEP_DETECTOR_EN, enable); - rslt |= bma4_write_regs(BMA4_FEATURE_CONFIG_ADDR, feature_config, - BMA423_FEATURE_SIZE, dev); - } - } else { - rslt = BMA4_E_INVALID_SENSOR; - } - } else { - rslt = BMA4_E_NULL_PTR; - } - - return rslt; -} - -/*! - * @brief This API sets the watermark level for step counter - * interrupt in the sensor. - */ -uint16_t bma423_step_counter_set_watermark(uint16_t step_counter_wm, struct bma4_dev *dev) -{ - uint8_t feature_config[BMA423_FEATURE_SIZE] = {0}; - uint8_t index = BMA423_STEP_CNTR_OFFSET; - uint16_t wm_lsb = 0; - uint16_t wm_msb = 0; - uint16_t rslt = BMA4_OK; - uint16_t data = 0; - - if (dev != NULL) { - if (dev->chip_id == BMA423_CHIP_ID) { - rslt = bma4_read_regs(BMA4_FEATURE_CONFIG_ADDR, feature_config, - BMA423_FEATURE_SIZE, dev); - if (rslt == BMA4_OK) { - wm_lsb = feature_config[index]; - wm_msb = feature_config[index + 1] << 8; - data = wm_lsb | wm_msb; - /* Sets only watermark bits in the complete - 16 bits of data */ - data = BMA4_SET_BITS_POS_0(data, BMA423_STEP_CNTR_WM, step_counter_wm); - /* Splits 16 bits of data to individual - 8 bits data */ - feature_config[index] = BMA4_GET_LSB(data); - feature_config[index + 1] = BMA4_GET_MSB(data); - /* Writes stepcounter watermark settings - in the sensor */ - rslt |= bma4_write_regs(BMA4_FEATURE_CONFIG_ADDR, feature_config, - BMA423_FEATURE_SIZE, dev); - } - } else { - rslt = BMA4_E_INVALID_SENSOR; - } - } else { - rslt = BMA4_E_NULL_PTR; - } - - return rslt; -} - -/*! - * @brief This API gets the water mark level set for step counter interrupt - * in the sensor - */ -uint16_t bma423_step_counter_get_watermark(uint16_t *step_counter_wm, struct bma4_dev *dev) -{ - uint8_t feature_config[BMA423_FEATURE_SIZE] = {0}; - uint8_t index = BMA423_STEP_CNTR_OFFSET; - uint16_t wm_lsb = 0; - uint16_t wm_msb = 0; - uint16_t rslt = BMA4_OK; - uint16_t data = 0; - - if (dev != NULL) { - if (dev->chip_id == BMA423_CHIP_ID) { - rslt = bma4_read_regs(BMA4_FEATURE_CONFIG_ADDR, feature_config, - BMA423_FEATURE_SIZE, dev); - if (rslt == BMA4_OK) { - wm_lsb = feature_config[index]; - wm_msb = feature_config[index + 1] << 8; - data = wm_lsb | wm_msb; - *step_counter_wm = BMA4_GET_BITS_POS_0(data, BMA423_STEP_CNTR_WM); - } - } else { - rslt = BMA4_E_INVALID_SENSOR; - } - } else { - rslt = BMA4_E_NULL_PTR; - } - - return rslt; -} - -/*! - * @brief This API resets the counted steps of step counter. - */ -uint16_t bma423_reset_step_counter(struct bma4_dev *dev) -{ - uint8_t feature_config[BMA423_FEATURE_SIZE] = {0}; - /* Reset bit is 1 byte ahead of base address */ - uint8_t index = BMA423_STEP_CNTR_OFFSET + 1; - uint16_t rslt = BMA4_OK; - - if (dev != NULL) { - if (dev->chip_id == BMA423_CHIP_ID) { - rslt = bma4_read_regs(BMA4_FEATURE_CONFIG_ADDR, feature_config, - BMA423_FEATURE_SIZE, dev); - - if (rslt == BMA4_OK) { - feature_config[index] = BMA4_SET_BITSLICE(feature_config[index], - BMA423_STEP_CNTR_RST, 1); - rslt |= bma4_write_regs(BMA4_FEATURE_CONFIG_ADDR, feature_config, - BMA423_FEATURE_SIZE, dev); - } - } else { - rslt = BMA4_E_INVALID_SENSOR; - } - } else { - rslt = BMA4_E_NULL_PTR; - } - return rslt; -} - -/*! - * @brief This API gets the number of counted steps of the step counter - * feature from the sensor. - */ -uint16_t bma423_step_counter_output(uint32_t *step_count, struct bma4_dev *dev) -{ - uint8_t data[BMA423_STEP_CNTR_DATA_SIZE] = {0}; - uint16_t rslt = BMA4_OK; - uint32_t step_count_0 = 0; - uint32_t step_count_1 = 0; - uint32_t step_count_2 = 0; - uint32_t step_count_3 = 0; - - if (dev != NULL) { - if (dev->chip_id == BMA423_CHIP_ID) { - /* Reads the step counter output data from the - gpio register */ - rslt = bma4_read_regs(BMA4_STEP_CNT_OUT_0_ADDR, data, - BMA423_STEP_CNTR_DATA_SIZE, dev); - - if (rslt == BMA4_OK) { - step_count_0 = (uint32_t)data[0]; - step_count_1 = (uint32_t)data[1] << 8; - step_count_2 = (uint32_t)data[2] << 16; - step_count_3 = (uint32_t)data[3] << 24; - *step_count = step_count_0 | step_count_1 | step_count_2 | step_count_3; - } - } else { - rslt = BMA4_E_INVALID_SENSOR; - } - } else { - rslt = BMA4_E_NULL_PTR; - } - - return rslt; -} - -/*! - * @brief This API gets the output for activity feature. - */ -uint16_t bma423_activity_output(uint8_t *activity, struct bma4_dev *dev) -{ - uint8_t data = 0; - uint16_t rslt = BMA4_OK; - - if (dev != NULL) { - if (dev->chip_id == BMA423_CHIP_ID) { - /* Reads the activity output from the gpio register */ - rslt = bma4_read_regs(BMA4_ACTIVITY_OUT_ADDR, &data, 1, dev); - if (rslt == BMA4_OK) - *activity = data; - } else { - rslt = BMA4_E_INVALID_SENSOR; - } - } else { - rslt = BMA4_E_NULL_PTR; - } - - return rslt; -} - -/*! - * @brief This API select the platform configuration wrist(Default) or phone. - */ -uint16_t bma423_select_platform(uint8_t platform, struct bma4_dev *dev) -{ - uint16_t rslt = BMA4_OK; - struct bma423_stepcounter_settings sc_settings = {0}; - - if (dev != NULL) { - if (dev->chip_id == BMA423_CHIP_ID) { - switch (platform) { - case BMA423_PHONE_CONFIG: - sc_settings.param1 = BMA423_PHONE_SC_PARAM_1; - sc_settings.param2 = BMA423_PHONE_SC_PARAM_2; - sc_settings.param3 = BMA423_PHONE_SC_PARAM_3; - sc_settings.param4 = BMA423_PHONE_SC_PARAM_4; - sc_settings.param5 = BMA423_PHONE_SC_PARAM_5; - sc_settings.param6 = BMA423_PHONE_SC_PARAM_6; - sc_settings.param7 = BMA423_PHONE_SC_PARAM_7; - sc_settings.param8 = BMA423_PHONE_SC_PARAM_8; - sc_settings.param9 = BMA423_PHONE_SC_PARAM_9; - sc_settings.param10 = BMA423_PHONE_SC_PARAM_10; - sc_settings.param11 = BMA423_PHONE_SC_PARAM_11; - sc_settings.param12 = BMA423_PHONE_SC_PARAM_12; - sc_settings.param13 = BMA423_PHONE_SC_PARAM_13; - sc_settings.param14 = BMA423_PHONE_SC_PARAM_14; - sc_settings.param15 = BMA423_PHONE_SC_PARAM_15; - sc_settings.param16 = BMA423_PHONE_SC_PARAM_16; - sc_settings.param17 = BMA423_PHONE_SC_PARAM_17; - sc_settings.param18 = BMA423_PHONE_SC_PARAM_18; - sc_settings.param19 = BMA423_PHONE_SC_PARAM_19; - sc_settings.param20 = BMA423_PHONE_SC_PARAM_20; - sc_settings.param21 = BMA423_PHONE_SC_PARAM_21; - sc_settings.param22 = BMA423_PHONE_SC_PARAM_22; - sc_settings.param23 = BMA423_PHONE_SC_PARAM_23; - sc_settings.param24 = BMA423_PHONE_SC_PARAM_24; - sc_settings.param25 = BMA423_PHONE_SC_PARAM_25; - break; - - case BMA423_WRIST_CONFIG: - sc_settings.param1 = BMA423_WRIST_SC_PARAM_1; - sc_settings.param2 = BMA423_WRIST_SC_PARAM_2; - sc_settings.param3 = BMA423_WRIST_SC_PARAM_3; - sc_settings.param4 = BMA423_WRIST_SC_PARAM_4; - sc_settings.param5 = BMA423_WRIST_SC_PARAM_5; - sc_settings.param6 = BMA423_WRIST_SC_PARAM_6; - sc_settings.param7 = BMA423_WRIST_SC_PARAM_7; - sc_settings.param8 = BMA423_WRIST_SC_PARAM_8; - sc_settings.param9 = BMA423_WRIST_SC_PARAM_9; - sc_settings.param10 = BMA423_WRIST_SC_PARAM_10; - sc_settings.param11 = BMA423_WRIST_SC_PARAM_11; - sc_settings.param12 = BMA423_WRIST_SC_PARAM_12; - sc_settings.param13 = BMA423_WRIST_SC_PARAM_13; - sc_settings.param14 = BMA423_WRIST_SC_PARAM_14; - sc_settings.param15 = BMA423_WRIST_SC_PARAM_15; - sc_settings.param16 = BMA423_WRIST_SC_PARAM_16; - sc_settings.param17 = BMA423_WRIST_SC_PARAM_17; - sc_settings.param18 = BMA423_WRIST_SC_PARAM_18; - sc_settings.param19 = BMA423_WRIST_SC_PARAM_19; - sc_settings.param20 = BMA423_WRIST_SC_PARAM_20; - sc_settings.param21 = BMA423_WRIST_SC_PARAM_21; - sc_settings.param22 = BMA423_WRIST_SC_PARAM_22; - sc_settings.param23 = BMA423_WRIST_SC_PARAM_23; - sc_settings.param24 = BMA423_WRIST_SC_PARAM_24; - sc_settings.param25 = BMA423_WRIST_SC_PARAM_25; - break; - - default: - rslt = BMA4_E_OUT_OF_RANGE; - break; - } - } else { - rslt = BMA4_E_INVALID_SENSOR; - } - } else { - rslt = BMA4_E_NULL_PTR; - } - - if (rslt == BMA4_OK) { - /* Set the step counter parameter */ - rslt = bma423_stepcounter_set_parameter(&sc_settings, dev); - } - - return rslt; -} - -/*! - * @brief This API gets the parameter1 to parameter7 settings of the - * step counter feature. - */ -uint16_t bma423_stepcounter_get_parameter(struct bma423_stepcounter_settings *setting, struct bma4_dev *dev) -{ - uint8_t feature_config[BMA423_FEATURE_SIZE] = {0}; - uint16_t *data_p = (uint16_t *)feature_config; - uint16_t rslt = BMA4_OK; - - if (dev != NULL) { - if (dev->chip_id == BMA423_CHIP_ID) { - rslt = bma4_read_regs(BMA4_FEATURE_CONFIG_ADDR, feature_config, BMA423_FEATURE_SIZE, dev); - - if (rslt == BMA4_OK) { - /* To convert 8bit to 16 bit address */ - data_p = data_p + BMA423_STEP_CNTR_PARAM_OFFSET/2; - extract_stepcounter_parameter(setting, data_p); - } - } else { - rslt = BMA4_E_INVALID_SENSOR; - } - } else { - rslt = BMA4_E_NULL_PTR; - } - - return rslt; -} - -/*! - * @brief This API sets the parameter1 to parameter7 settings of the - * step counter feature in the sensor. - */ -uint16_t bma423_stepcounter_set_parameter(const struct bma423_stepcounter_settings *setting, struct bma4_dev *dev) -{ - uint8_t feature_config[BMA423_FEATURE_SIZE] = {0}; - uint8_t index = BMA423_STEP_CNTR_PARAM_OFFSET; - uint16_t rslt = BMA4_OK; - - if (dev != NULL) { - if (dev->chip_id == BMA423_CHIP_ID) { - rslt = bma4_read_regs(BMA4_FEATURE_CONFIG_ADDR, feature_config, BMA423_FEATURE_SIZE, dev); - if (rslt == BMA4_OK) { - update_stepcounter_parameter(setting, index, feature_config); - /* Writes stepcounter parameter settings - in the sensor */ - rslt = bma4_write_regs(BMA4_FEATURE_CONFIG_ADDR, feature_config, - BMA423_FEATURE_SIZE, dev); - } - } else { - rslt = BMA4_E_INVALID_SENSOR; - } - } else { - rslt = BMA4_E_NULL_PTR; - } - - return rslt; -} - -/*! - * @brief This API sets the sensitivity of wake up feature in the sensor - */ -uint16_t bma423_wakeup_set_sensitivity(uint8_t sensitivity, struct bma4_dev *dev) -{ - uint8_t feature_config[BMA423_FEATURE_SIZE] = {0}; - uint8_t index = BMA423_WAKEUP_OFFSET; - uint16_t rslt = BMA4_OK; - - if (dev != NULL) { - if (dev->chip_id == BMA423_CHIP_ID) { - rslt = bma4_read_regs(BMA4_FEATURE_CONFIG_ADDR, feature_config, BMA423_FEATURE_SIZE, dev); - if (rslt == BMA4_OK) { - feature_config[index] = BMA4_SET_BITSLICE(feature_config[index], - BMA423_WAKEUP_SENS, sensitivity); - /* Writes sensitivity settings in the sensor */ - rslt |= bma4_write_regs(BMA4_FEATURE_CONFIG_ADDR, feature_config, - BMA423_FEATURE_SIZE, dev); - } - } else { - rslt = BMA4_E_INVALID_SENSOR; - } - } else { - rslt = BMA4_E_NULL_PTR; - } - - return rslt; -} - -/*! - * @brief This API gets the sensitivity of wake up feature in the sensor - */ -uint16_t bma423_wakeup_get_sensitivity(uint8_t *sensitivity, struct bma4_dev *dev) -{ - uint8_t feature_config[BMA423_FEATURE_SIZE] = {0}; - uint8_t index = BMA423_WAKEUP_OFFSET; - uint16_t rslt = BMA4_OK; - - if (dev != NULL) { - if (dev->chip_id == BMA423_CHIP_ID) { - rslt = bma4_read_regs(BMA4_FEATURE_CONFIG_ADDR, feature_config, BMA423_FEATURE_SIZE, dev); - if (rslt == BMA4_OK) { - /* Extracts sensitivity data */ - *sensitivity = BMA4_GET_BITSLICE(feature_config[index], BMA423_WAKEUP_SENS); - } - } else { - rslt = BMA4_E_INVALID_SENSOR; - } - } else { - rslt = BMA4_E_NULL_PTR; - } - - return rslt; -} - -/*! - * @brief This API is used to select single/double tap - * feature in the sensor - */ -uint16_t bma423_tap_selection(const uint8_t tap_select, struct bma4_dev *dev) -{ - uint16_t rslt = BMA4_OK; - uint8_t feature_config[BMA423_FEATURE_SIZE] = {0,}; - uint8_t index = BMA423_WAKEUP_OFFSET; - - if (dev != NULL) { - if (dev->chip_id == BMA423_CHIP_ID) { - rslt = bma4_read_regs(BMA4_FEATURE_CONFIG_ADDR, feature_config, BMA423_FEATURE_SIZE, dev); - if (rslt == BMA4_OK) { - feature_config[index] = BMA4_SET_BITSLICE(feature_config[index], - BMA423_TAP_SEL, tap_select); - rslt = bma4_write_regs(BMA4_FEATURE_CONFIG_ADDR, feature_config, - BMA423_FEATURE_SIZE, dev); - } - } else { - rslt = BMA4_E_INVALID_SENSOR; - } - } else { - rslt = BMA4_E_NULL_PTR; - } - - return rslt; -} -/*! - * @brief This API update the length for read and write. - */ -static void update_len(uint8_t *len, uint8_t feature, uint8_t enable) -{ - uint8_t length = BMA423_FEATURE_SIZE; - - if ((feature == BMA423_ANY_MOTION) || (feature == BMA423_NO_MOTION)) { - /* Change the feature length to 2 for reading and writing of 2 bytes for - any/no-motion enable */ - length = BMA423_ANYMOTION_EN_LEN; - - /* Read and write 4 byte to disable the any/no motion completely along with - all axis */ - if (enable == BMA4_DISABLE) { - /*Change the feature length to 4 for reading and writing - of 4 bytes for any/no-motion enable */ - length = length + 2; - } - } - - *len = length; -} - -/*! - * @brief This API enables the features of the sensor. - */ -static uint16_t feature_enable(uint8_t feature, uint8_t len, uint8_t *feature_config, struct bma4_dev *dev) -{ - uint8_t index = 0; - uint16_t rslt; - - /* Enable step counter */ - if ((feature & BMA423_STEP_CNTR) > 0) { - /* Step counter enable bit pos. is 1 byte ahead of the - base address */ - index = BMA423_STEP_CNTR_OFFSET + 1; - feature_config[index] = feature_config[index] | BMA423_STEP_CNTR_EN_MSK; - } - - /* Enable activity */ - if ((feature & BMA423_ACTIVITY) > 0) { - /* Activity enable bit pos. is 1 byte ahead of the - base address */ - index = BMA423_STEP_CNTR_OFFSET + 1; - feature_config[index] = feature_config[index] | BMA423_ACTIVITY_EN_MSK; - } - /* Enable tilt */ - if ((feature & BMA423_TILT) > 0) { - /* Tilt enable bit pos. is the base address(0x3A) of tilt */ - index = BMA423_TILT_OFFSET; - feature_config[index] = feature_config[index] | BMA423_TILT_EN_MSK; - } - - /* Enable wakeup */ - if ((feature & BMA423_WAKEUP) > 0) { - /* Wakeup enable bit pos. is the base address(0x38) of wakeup */ - index = BMA423_WAKEUP_OFFSET; - feature_config[index] = feature_config[index] | BMA423_WAKEUP_EN_MSK; - } - - /* Enable anymotion/nomotion */ - if ((feature & BMA423_ANY_MOTION) > 0 || (feature & BMA423_NO_MOTION) > 0) { - /* Any/Nomotion enable bit pos. is 1 bytes ahead of the - any/nomotion base address(0x00) */ - index = 1; - - if ((feature & BMA423_ANY_MOTION) > 0) { - /* Enable anymotion */ - feature_config[index] = feature_config[index] & (~BMA423_ANY_NO_MOTION_SEL_MSK); - } else { - /* Enable nomotion */ - feature_config[index] = feature_config[index] | BMA423_ANY_NO_MOTION_SEL_MSK; - } - } - - /* Write the feature enable settings in the sensor */ - rslt = bma4_write_regs(BMA4_FEATURE_CONFIG_ADDR, feature_config, len, dev); - - return rslt; -} - -/*! - * @brief This API disables the features of the sensor. - */ -static uint16_t feature_disable(uint8_t feature, uint8_t len, uint8_t *feature_config, struct bma4_dev *dev) -{ - uint8_t index = 0; - uint16_t rslt; - - /* Disable step counter */ - if ((feature & BMA423_STEP_CNTR) > 0) { - /* Step counter enable bit pos. is 1 byte ahead of the - base address */ - index = BMA423_STEP_CNTR_OFFSET + 1; - feature_config[index] = feature_config[index] & (~BMA423_STEP_CNTR_EN_MSK); - } - - /* Disable activity */ - if ((feature & BMA423_ACTIVITY) > 0) { - /* Activity enable bit pos. is 1 byte ahead of the - base address */ - index = BMA423_STEP_CNTR_OFFSET + 1; - feature_config[index] = feature_config[index] & (~BMA423_ACTIVITY_EN_MSK); - } - /* Disable tilt */ - if ((feature & BMA423_TILT) > 0) { - /* Tilt enable bit pos. is the base address(0x3A) of tilt */ - index = BMA423_TILT_OFFSET; - feature_config[index] = feature_config[index] & (~BMA423_TILT_EN_MSK); - } - - /* Disable wakeup */ - if ((feature & BMA423_WAKEUP) > 0) { - /* Tilt enable bit pos. is the base address(0x38) of wakeup */ - index = BMA423_WAKEUP_OFFSET; - feature_config[index] = feature_config[index] & (~BMA423_WAKEUP_EN_MSK); - } - - /* Disable anymotion/nomotion */ - if ((feature & BMA423_ANY_MOTION) > 0 || (feature & BMA423_NO_MOTION) > 0) { - /* Any/Nomotion enable bit pos. is 1 bytes ahead of the - any/nomotion base address(0x00) */ - index = 1; - - if ((feature & BMA423_ANY_MOTION) > 0) { - /* Disable anymotion */ - feature_config[index] = feature_config[index] | BMA423_ANY_NO_MOTION_SEL_MSK; - } else { - /* Disable nomotion */ - feature_config[index] = feature_config[index] & (~BMA423_ANY_NO_MOTION_SEL_MSK); - } - /* Any/Nomotion axis enable bit pos. is 3 byte ahead of the - any/nomotion base address(0x00) */ - index = 3; - feature_config[index] = feature_config[index] & (~BMA423_ANY_NO_MOTION_AXIS_EN_MSK); - } - /* Write the configured settings in the sensor */ - rslt = bma4_write_regs(BMA4_FEATURE_CONFIG_ADDR, feature_config, len, dev); - - return rslt; -} - -/*! - * @brief This API update the settings of step counter. - */ -static void update_stepcounter_parameter(const struct bma423_stepcounter_settings *setting, - uint8_t index, uint8_t *feature_config) -{ - feature_config[index++] = BMA4_GET_LSB(setting->param1); - feature_config[index++] = BMA4_GET_MSB(setting->param1); - feature_config[index++] = BMA4_GET_LSB(setting->param2); - feature_config[index++] = BMA4_GET_MSB(setting->param2); - feature_config[index++] = BMA4_GET_LSB(setting->param3); - feature_config[index++] = BMA4_GET_MSB(setting->param3); - feature_config[index++] = BMA4_GET_LSB(setting->param4); - feature_config[index++] = BMA4_GET_MSB(setting->param4); - feature_config[index++] = BMA4_GET_LSB(setting->param5); - feature_config[index++] = BMA4_GET_MSB(setting->param5); - feature_config[index++] = BMA4_GET_LSB(setting->param6); - feature_config[index++] = BMA4_GET_MSB(setting->param6); - feature_config[index++] = BMA4_GET_LSB(setting->param7); - feature_config[index++] = BMA4_GET_MSB(setting->param7); - feature_config[index++] = BMA4_GET_LSB(setting->param8); - feature_config[index++] = BMA4_GET_MSB(setting->param8); - feature_config[index++] = BMA4_GET_LSB(setting->param9); - feature_config[index++] = BMA4_GET_MSB(setting->param9); - feature_config[index++] = BMA4_GET_LSB(setting->param10); - feature_config[index++] = BMA4_GET_MSB(setting->param10); - feature_config[index++] = BMA4_GET_LSB(setting->param11); - feature_config[index++] = BMA4_GET_MSB(setting->param11); - feature_config[index++] = BMA4_GET_LSB(setting->param12); - feature_config[index++] = BMA4_GET_MSB(setting->param12); - feature_config[index++] = BMA4_GET_LSB(setting->param13); - feature_config[index++] = BMA4_GET_MSB(setting->param13); - feature_config[index++] = BMA4_GET_LSB(setting->param14); - feature_config[index++] = BMA4_GET_MSB(setting->param14); - feature_config[index++] = BMA4_GET_LSB(setting->param15); - feature_config[index++] = BMA4_GET_MSB(setting->param15); - feature_config[index++] = BMA4_GET_LSB(setting->param16); - feature_config[index++] = BMA4_GET_MSB(setting->param16); - feature_config[index++] = BMA4_GET_LSB(setting->param17); - feature_config[index++] = BMA4_GET_MSB(setting->param17); - feature_config[index++] = BMA4_GET_LSB(setting->param18); - feature_config[index++] = BMA4_GET_MSB(setting->param18); - feature_config[index++] = BMA4_GET_LSB(setting->param19); - feature_config[index++] = BMA4_GET_MSB(setting->param19); - feature_config[index++] = BMA4_GET_LSB(setting->param20); - feature_config[index++] = BMA4_GET_MSB(setting->param20); - feature_config[index++] = BMA4_GET_LSB(setting->param21); - feature_config[index++] = BMA4_GET_MSB(setting->param21); - feature_config[index++] = BMA4_GET_LSB(setting->param22); - feature_config[index++] = BMA4_GET_MSB(setting->param22); - feature_config[index++] = BMA4_GET_LSB(setting->param23); - feature_config[index++] = BMA4_GET_MSB(setting->param23); - feature_config[index++] = BMA4_GET_LSB(setting->param24); - feature_config[index++] = BMA4_GET_MSB(setting->param24); - feature_config[index++] = BMA4_GET_LSB(setting->param25); - feature_config[index] = BMA4_GET_MSB(setting->param25); -} - -/*! - * @brief This API copy the settings of step counter into the - * structure of bma423_stepcounter_settings, which is read from sensor. - */ -static void extract_stepcounter_parameter(struct bma423_stepcounter_settings *setting, const uint16_t *data_p) -{ - setting->param1 = *(data_p++); - setting->param2 = *(data_p++); - setting->param3 = *(data_p++); - setting->param4 = *(data_p++); - setting->param5 = *(data_p++); - setting->param6 = *(data_p++); - setting->param7 = *(data_p++); - setting->param8 = *(data_p++); - setting->param9 = *(data_p++); - setting->param10 = *(data_p++); - setting->param11 = *(data_p++); - setting->param12 = *(data_p++); - setting->param13 = *(data_p++); - setting->param14 = *(data_p++); - setting->param15 = *(data_p++); - setting->param16 = *(data_p++); - setting->param17 = *(data_p++); - setting->param18 = *(data_p++); - setting->param19 = *(data_p++); - setting->param20 = *(data_p++); - setting->param21 = *(data_p++); - setting->param22 = *(data_p++); - setting->param23 = *(data_p++); - setting->param24 = *(data_p++); - setting->param25 = *data_p; -} +/**\mainpage +* +**************************************************************************** +* Copyright (C) 2017 - 2018 Bosch Sensortec GmbH +* +* File : bma423.c +* +* Date: 12 Oct 2017 +* +* Revision : 1.1.4 $ +* +* Usage: Sensor Driver for BMA423 sensor +* +**************************************************************************** +* +* \section Disclaimer +* +* Common: +* Bosch Sensortec products are developed for the consumer goods industry. +* They may only be used within the parameters of the respective valid +* product data sheet. Bosch Sensortec products are provided with the +* express understanding that there is no warranty of fitness for a +* particular purpose.They are not fit for use in life-sustaining, +* safety or security sensitive systems or any system or device +* that may lead to bodily harm or property damage if the system +* or device malfunctions. In addition,Bosch Sensortec products are +* not fit for use in products which interact with motor vehicle systems. +* The resale and or use of products are at the purchasers own risk and +* his own responsibility. The examination of fitness for the intended use +* is the sole responsibility of the Purchaser. +* +* The purchaser shall indemnify Bosch Sensortec from all third party +* claims, including any claims for incidental, or consequential damages, +* arising from any product use not covered by the parameters of +* the respective valid product data sheet or not approved by +* Bosch Sensortec and reimburse Bosch Sensortec for all costs in +* connection with such claims. +* +* The purchaser must monitor the market for the purchased products, +* particularly with regard to product safety and inform Bosch Sensortec +* without delay of all security relevant incidents. +* +* Engineering Samples are marked with an asterisk (*) or (e). +* Samples may vary from the valid technical specifications of the product +* series. They are therefore not intended or fit for resale to third +* parties or for use in end products. Their sole purpose is internal +* client testing. The testing of an engineering sample may in no way +* replace the testing of a product series. Bosch Sensortec assumes +* no liability for the use of engineering samples. +* By accepting the engineering samples, the Purchaser agrees to indemnify +* Bosch Sensortec from all claims arising from the use of engineering +* samples. +* +* Special: +* This software module (hereinafter called "Software") and any information +* on application-sheets (hereinafter called "Information") is provided +* free of charge for the sole purpose to support your application work. +* The Software and Information is subject to the following +* terms and conditions: +* +* The Software is specifically designed for the exclusive use for +* Bosch Sensortec products by personnel who have special experience +* and training. Do not use this Software if you do not have the +* proper experience or training. +* +* This Software package is provided `` as is `` and without any expressed +* or implied warranties,including without limitation, the implied warranties +* of merchantability and fitness for a particular purpose. +* +* Bosch Sensortec and their representatives and agents deny any liability +* for the functional impairment +* of this Software in terms of fitness, performance and safety. +* Bosch Sensortec and their representatives and agents shall not be liable +* for any direct or indirect damages or injury, except as +* otherwise stipulated in mandatory applicable law. +* +* The Information provided is believed to be accurate and reliable. +* Bosch Sensortec assumes no responsibility for the consequences of use +* of such Information nor for any infringement of patents or +* other rights of third parties which may result from its use. +* No license is granted by implication or otherwise under any patent or +* patent rights of Bosch. Specifications mentioned in the Information are +* subject to change without notice. +**************************************************************************/ +/*! \file bma423.c + \brief Sensor Driver for BMA423 sensor */ + +#include "bma423.h" + +/**\name Feature configuration file */ +const uint8_t bma423_config_file[] = { + 0x80, 0x2e, 0xfc, 0x00, 0x80, 0x2e, 0xfe, 0x00, 0xc8, 0x2e, 0x00, 0x2e, + 0x80, 0x2e, 0xfa, 0x00, 0x80, 0x2e, 0x23, 0xb1, 0x80, 0x2e, 0xfd, 0x00, + 0x80, 0x2e, 0xfb, 0x00, 0x80, 0x2e, 0x5a, 0xb1, 0x50, 0x39, 0x21, 0x2e, + 0xb0, 0xf0, 0x10, 0x30, 0x21, 0x2e, 0x16, 0xf0, 0x80, 0x2e, 0xfc, 0x01, + 0x5d, 0x50, 0x45, 0x52, 0x01, 0x42, 0x3b, 0x80, 0x41, 0x30, 0x01, 0x42, + 0x3c, 0x80, 0x00, 0x2e, 0x01, 0x40, 0x01, 0x42, 0x21, 0x2e, 0xff, 0xaf, + 0xb8, 0x2e, 0xb6, 0xd6, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0xfd, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x00, 0x24, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, 0x2e, + 0x99, 0x01, 0x20, 0x26, 0x98, 0x2e, 0xf6, 0x00, 0x98, 0x2e, 0xe9, 0x01, + 0x10, 0x30, 0x21, 0x2e, 0x59, 0xf0, 0x98, 0x2e, 0xd8, 0x00, 0x00, 0x2e, + 0x00, 0x2e, 0xd0, 0x2e, 0x98, 0x2e, 0xdd, 0x00, 0x01, 0x2e, 0x56, 0x00, + 0x00, 0xb2, 0x11, 0x2f, 0x00, 0x30, 0x21, 0x2e, 0x56, 0x00, 0x41, 0x50, + 0x98, 0x2e, 0xcc, 0xb0, 0x41, 0x50, 0x98, 0x2e, 0x8f, 0xb4, 0x01, 0x2e, + 0x03, 0xf0, 0x0d, 0xbc, 0x0f, 0xb8, 0x00, 0x90, 0x02, 0x2f, 0x45, 0x50, + 0x21, 0x2e, 0xbc, 0xf0, 0x01, 0x2e, 0x55, 0x00, 0x00, 0xb2, 0x1a, 0x2f, + 0x00, 0x30, 0x21, 0x2e, 0x55, 0x00, 0x43, 0x50, 0x98, 0x2e, 0xcc, 0xb0, + 0x43, 0x50, 0x98, 0x2e, 0xdc, 0xb1, 0x43, 0x50, 0x98, 0x2e, 0x92, 0xb5, + 0x43, 0x50, 0x98, 0x2e, 0x00, 0xb0, 0x01, 0x2e, 0x1c, 0x01, 0x0f, 0xbc, + 0x0f, 0xb8, 0x00, 0x90, 0x45, 0x50, 0x02, 0x2f, 0x21, 0x2e, 0xbc, 0xf0, + 0x02, 0x2d, 0x21, 0x2e, 0xba, 0xf0, 0x98, 0x2e, 0xd8, 0x00, 0xc3, 0x2d, + 0x01, 0x2e, 0x55, 0xf0, 0xc0, 0x2e, 0x21, 0x2e, 0x55, 0xf0, 0x03, 0x2e, + 0x00, 0xf0, 0x45, 0x54, 0x01, 0x2e, 0x59, 0xf0, 0x4a, 0x0e, 0x02, 0x2f, + 0xf1, 0x33, 0x0d, 0x2c, 0x01, 0x08, 0xf2, 0x30, 0x4a, 0x08, 0x79, 0x84, + 0x82, 0xa2, 0x04, 0x2f, 0x02, 0x34, 0x82, 0x0a, 0x47, 0xa2, 0x03, 0x2c, + 0x10, 0x22, 0x45, 0x52, 0x01, 0x0a, 0xc0, 0x2e, 0x21, 0x2e, 0x59, 0xf0, + 0x00, 0x31, 0xc0, 0x2e, 0x21, 0x2e, 0xba, 0xf0, 0xc8, 0x2e, 0xc8, 0x2e, + 0xc8, 0x2e, 0xc8, 0x2e, 0xc8, 0x2e, 0x44, 0x47, 0xaa, 0x00, 0x05, 0x00, + 0x2d, 0x01, 0xd4, 0x7b, 0x3b, 0x01, 0xdb, 0x7a, 0x04, 0x00, 0x3f, 0x7b, + 0xcd, 0x6c, 0xc3, 0x04, 0x85, 0x09, 0xc3, 0x04, 0xec, 0xe6, 0x0c, 0x46, + 0x01, 0x00, 0x27, 0x00, 0x19, 0x00, 0x96, 0x00, 0xa0, 0x00, 0x01, 0x00, + 0x0c, 0x00, 0xf0, 0x3c, 0x00, 0x01, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, + 0x0e, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x43, 0x28, 0x88, 0x00, + 0x52, 0x00, 0x4f, 0x00, 0x80, 0x00, 0x5b, 0x00, 0x00, 0x40, 0xaf, 0x00, + 0xff, 0x00, 0xff, 0xb7, 0x00, 0x02, 0x00, 0xb0, 0x05, 0x80, 0xb1, 0xf0, + 0xc0, 0x00, 0x00, 0x01, 0x5e, 0xf0, 0x39, 0xf0, 0x89, 0xf0, 0x00, 0x20, + 0xff, 0x7f, 0x7d, 0x00, 0x5e, 0x00, 0x62, 0x00, 0x7c, 0x00, 0xff, 0xfb, + 0x52, 0xf0, 0x56, 0xf0, 0x33, 0x09, 0x33, 0x07, 0x00, 0x08, 0x90, 0x01, + 0x00, 0xf8, 0x67, 0x00, 0x4c, 0x04, 0xa0, 0x00, 0xe8, 0x03, 0x81, 0x00, + 0x82, 0x00, 0x6a, 0x00, 0x6d, 0x00, 0x6c, 0x00, 0xeb, 0x07, 0xae, 0x07, + 0x72, 0x00, 0x6f, 0x00, 0xa1, 0x01, 0x1e, 0x05, 0x47, 0xfd, 0x73, 0x00, + 0x77, 0x00, 0x79, 0x00, 0x76, 0x00, 0xcc, 0x00, 0x30, 0x50, 0x50, 0x40, + 0x00, 0x18, 0x50, 0x40, 0x56, 0x25, 0x47, 0x25, 0x00, 0x18, 0x2e, 0x00, + 0x41, 0x40, 0xa7, 0x02, 0x09, 0x18, 0xc6, 0x00, 0xfb, 0x7f, 0x00, 0x30, + 0x49, 0x52, 0x05, 0x30, 0x05, 0x2c, 0x17, 0x03, 0x1e, 0xbd, 0xd2, 0xba, + 0x92, 0xb8, 0x6a, 0x0b, 0x61, 0x0e, 0xf9, 0x2f, 0x61, 0x1a, 0x01, 0x2f, + 0x5d, 0x0e, 0xf5, 0x2f, 0xd4, 0x7f, 0x02, 0x30, 0x1f, 0x2c, 0xe3, 0x7f, + 0x85, 0x01, 0xd1, 0x03, 0x7c, 0x0e, 0x03, 0x2f, 0x7c, 0x1a, 0x0f, 0x2f, + 0x73, 0x0f, 0x0d, 0x2f, 0xe3, 0x6f, 0xde, 0x04, 0x5f, 0xba, 0x11, 0xbf, + 0xb4, 0x0b, 0xd4, 0x6f, 0x27, 0x07, 0xb3, 0x25, 0xd1, 0xbf, 0xeb, 0x7f, + 0x07, 0x00, 0xb4, 0x25, 0x96, 0x02, 0xdb, 0x7f, 0x2f, 0xbf, 0x9e, 0xbf, + 0x01, 0xb8, 0xd2, 0xba, 0x21, 0xb9, 0x92, 0xb8, 0x06, 0x0a, 0x6f, 0x0b, + 0x40, 0x90, 0xdf, 0x2f, 0x40, 0x91, 0xdd, 0x2f, 0xfb, 0x6f, 0xd0, 0x5f, + 0xb8, 0x2e, 0x57, 0x50, 0x41, 0x30, 0x02, 0x40, 0x51, 0x0a, 0x01, 0x42, + 0x18, 0x82, 0x4b, 0x50, 0x60, 0x42, 0x70, 0x3c, 0x4d, 0x54, 0x42, 0x42, + 0x69, 0x82, 0x82, 0x32, 0x43, 0x40, 0x18, 0x08, 0x02, 0x0a, 0x40, 0x42, + 0x42, 0x80, 0x02, 0x3f, 0x01, 0x40, 0x10, 0x50, 0x4a, 0x08, 0xfb, 0x7f, + 0x11, 0x42, 0x0b, 0x31, 0x0b, 0x42, 0x3e, 0x80, 0x01, 0x32, 0x01, 0x42, + 0x00, 0x2e, 0x01, 0x2e, 0x40, 0xf0, 0x13, 0x90, 0x20, 0x2f, 0x03, 0x30, + 0x51, 0x50, 0x4f, 0x54, 0xf4, 0x34, 0x06, 0x30, 0x55, 0x52, 0x55, 0x32, + 0x1d, 0x1a, 0xe3, 0x22, 0x18, 0x1a, 0x53, 0x58, 0xe3, 0x22, 0x04, 0x30, + 0xd5, 0x40, 0xb5, 0x0d, 0xe1, 0xbe, 0x6f, 0xbb, 0x80, 0x91, 0xa9, 0x0d, + 0x01, 0x89, 0xb5, 0x23, 0x10, 0xa1, 0xf7, 0x2f, 0xda, 0x0e, 0xf4, 0x34, + 0xeb, 0x2f, 0x01, 0x2e, 0x25, 0x00, 0x70, 0x1a, 0x00, 0x30, 0x21, 0x30, + 0x02, 0x2c, 0x08, 0x22, 0x30, 0x30, 0x00, 0xb2, 0x06, 0x2f, 0x21, 0x2e, + 0x59, 0xf0, 0x98, 0x2e, 0xd8, 0x00, 0x00, 0x2e, 0x00, 0x2e, 0xd0, 0x2e, + 0xfb, 0x6f, 0xf0, 0x5f, 0xb8, 0x2e, 0x01, 0x2e, 0xb1, 0xf0, 0x59, 0x52, + 0x01, 0x0a, 0x21, 0x2e, 0xb1, 0xf0, 0x01, 0x2e, 0x1c, 0x01, 0x0f, 0xbc, + 0x0f, 0xb8, 0x00, 0x90, 0x45, 0x50, 0x02, 0x2f, 0xc0, 0x2e, 0x21, 0x2e, + 0xbc, 0xf0, 0xc0, 0x2e, 0x21, 0x2e, 0xba, 0xf0, 0x1a, 0x24, 0x26, 0x00, + 0x80, 0x2e, 0x8f, 0x00, 0x03, 0x2e, 0x01, 0x01, 0x05, 0x2e, 0x01, 0x01, + 0x92, 0xbd, 0x20, 0x50, 0x03, 0x2e, 0x01, 0x01, 0xbf, 0xba, 0x21, 0xbd, + 0x2f, 0xbb, 0x1f, 0xba, 0x40, 0x91, 0xf0, 0x7f, 0x04, 0x2f, 0x80, 0x91, + 0x02, 0x2f, 0x00, 0xb3, 0x90, 0x2e, 0xc7, 0xb0, 0x03, 0x2e, 0x7b, 0x00, + 0x01, 0x80, 0x40, 0x90, 0x14, 0x2f, 0x41, 0x84, 0xf1, 0x6f, 0x25, 0x2e, + 0x7b, 0x00, 0x41, 0x40, 0x23, 0x2e, 0x5a, 0x00, 0x47, 0x52, 0x12, 0x40, + 0x52, 0x42, 0x02, 0x30, 0x00, 0x40, 0x40, 0x42, 0xe0, 0x5f, 0x25, 0x2e, + 0x57, 0x00, 0x25, 0x2e, 0x58, 0x00, 0x25, 0x2e, 0x5d, 0x00, 0xb8, 0x2e, + 0x07, 0x2e, 0x00, 0x01, 0x03, 0x2e, 0x01, 0x01, 0x05, 0x2e, 0x00, 0x01, + 0x24, 0xbd, 0x0f, 0x2e, 0x59, 0x00, 0xb5, 0xbd, 0x93, 0xbc, 0x2f, 0xb9, + 0xb5, 0xb9, 0x93, 0xb8, 0x3a, 0x1a, 0x06, 0x2f, 0x07, 0x30, 0x25, 0x2e, + 0x59, 0x00, 0x2f, 0x2e, 0x57, 0x00, 0x2f, 0x2e, 0x58, 0x00, 0x40, 0xb3, + 0x05, 0x30, 0x07, 0x30, 0x0a, 0x2f, 0xf7, 0x6f, 0xe6, 0x7f, 0x00, 0x2e, + 0xc6, 0x41, 0x0f, 0x2e, 0x5a, 0x00, 0xb7, 0x05, 0x80, 0xa9, 0xee, 0x05, + 0xf7, 0x23, 0xe6, 0x6f, 0x80, 0xb3, 0x06, 0x30, 0x09, 0x2f, 0xe7, 0x7f, + 0x00, 0x2e, 0x06, 0x40, 0x0f, 0x2e, 0x5b, 0x00, 0xb7, 0x05, 0x80, 0xa9, + 0xee, 0x05, 0xb7, 0x23, 0xe7, 0x6f, 0x00, 0xb3, 0x04, 0x30, 0x0b, 0x2f, + 0xf4, 0x6f, 0x02, 0x89, 0xe7, 0x7f, 0x00, 0x2e, 0x04, 0x41, 0x0f, 0x2e, + 0x5c, 0x00, 0x27, 0x05, 0x00, 0xa9, 0xec, 0x05, 0x27, 0x23, 0xe7, 0x6f, + 0x7b, 0x0f, 0x17, 0x30, 0x0b, 0x2f, 0x73, 0x0f, 0x05, 0x30, 0x17, 0x30, + 0x07, 0x2f, 0x63, 0x0f, 0x15, 0x30, 0x17, 0x30, 0x00, 0x2f, 0x07, 0x30, + 0xe3, 0x0e, 0x00, 0x2f, 0x05, 0x30, 0x80, 0x90, 0x05, 0x2e, 0x57, 0x00, + 0x13, 0x30, 0x13, 0x29, 0xf2, 0x6f, 0x47, 0x5c, 0x17, 0x2f, 0xc0, 0x91, + 0x05, 0x30, 0x0b, 0x2f, 0x07, 0x2e, 0x58, 0x00, 0xc1, 0x86, 0x2b, 0x2e, + 0x57, 0x00, 0x59, 0x0e, 0x27, 0x2e, 0x58, 0x00, 0x24, 0x2f, 0x2b, 0x2e, + 0x5d, 0x00, 0x22, 0x2d, 0x61, 0x0e, 0x29, 0x2e, 0x57, 0x00, 0x2b, 0x2e, + 0x58, 0x00, 0x1b, 0x2f, 0x27, 0x2e, 0x5d, 0x00, 0x19, 0x2d, 0x40, 0x91, + 0x05, 0x2f, 0x01, 0x30, 0x23, 0x2e, 0x57, 0x00, 0x23, 0x2e, 0x5d, 0x00, + 0x06, 0x2d, 0x29, 0x2e, 0x57, 0x00, 0x61, 0x0e, 0x01, 0x2f, 0x27, 0x2e, + 0x5d, 0x00, 0x81, 0x40, 0x23, 0x2e, 0x5a, 0x00, 0x30, 0x25, 0x47, 0x52, + 0xd4, 0x40, 0x54, 0x42, 0x00, 0x2e, 0xc3, 0x40, 0x43, 0x42, 0x00, 0x2e, + 0x03, 0x2e, 0x5d, 0x00, 0x40, 0xb2, 0x0d, 0x2f, 0x81, 0x40, 0x23, 0x2e, + 0x5a, 0x00, 0x11, 0x40, 0x91, 0x43, 0x01, 0x34, 0x00, 0x40, 0x80, 0x43, + 0x23, 0x2e, 0x5e, 0xf0, 0x03, 0x2d, 0x00, 0x30, 0x21, 0x2e, 0x7b, 0x00, + 0xe0, 0x5f, 0xb8, 0x2e, 0x50, 0x50, 0xf0, 0x7f, 0x1a, 0x25, 0x13, 0x40, + 0x7b, 0x84, 0xe0, 0x7f, 0x83, 0x42, 0x35, 0x30, 0x11, 0x40, 0x04, 0x40, + 0xc1, 0x7f, 0xd4, 0x7f, 0x86, 0x31, 0x07, 0x2e, 0x59, 0xf0, 0x03, 0x2e, + 0x1f, 0x01, 0x0d, 0x09, 0x02, 0xab, 0x05, 0x30, 0x8e, 0x09, 0x2c, 0x23, + 0xe3, 0xba, 0x42, 0xab, 0x16, 0x30, 0x75, 0x23, 0x59, 0x5c, 0x8e, 0x09, + 0x66, 0xbb, 0x82, 0xab, 0x27, 0x30, 0xbe, 0x23, 0x3e, 0x80, 0x25, 0x1a, + 0x06, 0x2f, 0x2e, 0x1a, 0x04, 0x2f, 0x26, 0x1a, 0x02, 0x2f, 0xf7, 0x3d, + 0x03, 0x2c, 0xdf, 0x08, 0x07, 0x32, 0xdf, 0x0a, 0x14, 0x01, 0x55, 0x01, + 0x04, 0x41, 0x14, 0x42, 0x16, 0x01, 0x42, 0x41, 0x45, 0x30, 0x4d, 0x09, + 0x04, 0x41, 0x12, 0x42, 0x04, 0x42, 0x40, 0xb3, 0x04, 0x2f, 0xf0, 0x6f, + 0x02, 0x30, 0x04, 0x40, 0x94, 0x04, 0x02, 0x42, 0x00, 0x32, 0x08, 0x08, + 0x00, 0xb2, 0x00, 0x30, 0x05, 0x2f, 0xe2, 0x6f, 0x00, 0x2e, 0x84, 0x40, + 0x04, 0x05, 0x84, 0x42, 0x00, 0x2e, 0x5b, 0x54, 0x4a, 0x08, 0x40, 0xb2, + 0xf1, 0x6f, 0x04, 0x2f, 0x42, 0x82, 0x00, 0x2e, 0x42, 0x40, 0x02, 0x04, + 0x40, 0x42, 0xb0, 0x5f, 0x27, 0x2e, 0x59, 0xf0, 0xb8, 0x2e, 0x50, 0x50, + 0xf7, 0x7f, 0x00, 0x2e, 0x0f, 0x2e, 0xb8, 0xf0, 0xf8, 0xbf, 0xff, 0xbb, + 0xc0, 0xb3, 0x2a, 0x2f, 0x0f, 0x2e, 0x01, 0xf0, 0xfe, 0xbf, 0xe6, 0x7f, + 0x7e, 0xbb, 0xd5, 0x7f, 0x37, 0x30, 0x5f, 0x5a, 0xbe, 0x05, 0x67, 0x41, + 0xc4, 0x7f, 0x78, 0xbe, 0x47, 0x41, 0x27, 0x0b, 0xb3, 0x7f, 0xe6, 0x11, + 0x41, 0x56, 0x43, 0x89, 0xd7, 0x42, 0x00, 0x2e, 0x27, 0x41, 0x05, 0x41, + 0xf8, 0xbf, 0x7d, 0x0b, 0x6e, 0x11, 0x03, 0x8f, 0xd5, 0x42, 0x14, 0x30, + 0xe5, 0x41, 0xc7, 0x41, 0xd8, 0xbe, 0x6f, 0x0b, 0x6e, 0x11, 0xc5, 0x42, + 0x29, 0x2e, 0x56, 0x00, 0x45, 0x56, 0x27, 0x2e, 0xb8, 0xf0, 0xe6, 0x6f, + 0xd5, 0x6f, 0xc4, 0x6f, 0xb3, 0x6f, 0xf7, 0x6f, 0xb0, 0x5f, 0xc8, 0x2e, + 0x50, 0x50, 0xe5, 0x7f, 0xd7, 0x7f, 0xf6, 0x7f, 0x36, 0x30, 0x0b, 0x2e, + 0x01, 0xf0, 0xde, 0xbe, 0xde, 0xbb, 0x61, 0x5a, 0xb7, 0x05, 0x67, 0x41, + 0xc4, 0x7f, 0x78, 0xbe, 0x47, 0x41, 0x27, 0x0b, 0xb3, 0x7f, 0xe6, 0x11, + 0x43, 0x56, 0x43, 0x89, 0xd7, 0x42, 0x00, 0x2e, 0x27, 0x41, 0x05, 0x41, + 0xf8, 0xbf, 0x7d, 0x0b, 0x6e, 0x11, 0x03, 0x8f, 0xd5, 0x42, 0x14, 0x30, + 0xe5, 0x41, 0xc7, 0x41, 0xd8, 0xbe, 0x6f, 0x0b, 0x6e, 0x11, 0xc5, 0x42, + 0x29, 0x2e, 0x55, 0x00, 0x03, 0x31, 0x27, 0x2e, 0xb8, 0xf0, 0xf6, 0x6f, + 0xe5, 0x6f, 0xd7, 0x6f, 0xc4, 0x6f, 0xb3, 0x6f, 0xb0, 0x5f, 0xc8, 0x2e, + 0x40, 0x50, 0xf6, 0x7f, 0x1a, 0x18, 0x63, 0x56, 0x33, 0x00, 0x06, 0x30, + 0xfe, 0x03, 0x0e, 0xb8, 0xf2, 0xbf, 0x07, 0x0a, 0x2a, 0x18, 0x63, 0x5a, + 0xb5, 0x01, 0x03, 0x30, 0xfb, 0x03, 0x6e, 0xbb, 0xf2, 0xbf, 0xe1, 0x7f, + 0xf7, 0x0b, 0x56, 0x40, 0x36, 0x25, 0x46, 0x40, 0x06, 0x28, 0xc7, 0x7f, + 0x22, 0x18, 0xd1, 0x7f, 0xb5, 0x00, 0x01, 0x30, 0x39, 0x03, 0x2e, 0xb9, + 0x42, 0xbe, 0x14, 0x0b, 0xf2, 0x6f, 0x10, 0x18, 0xb5, 0x00, 0xb9, 0x03, + 0x2e, 0xb9, 0x62, 0xbf, 0x96, 0x0a, 0xb6, 0x6f, 0x30, 0x18, 0x75, 0x01, + 0xb9, 0x03, 0x5c, 0x28, 0xe2, 0xbf, 0xde, 0xb9, 0xd6, 0x6f, 0xdf, 0x0a, + 0x8a, 0x28, 0xc4, 0x6f, 0x82, 0x43, 0x23, 0x29, 0xe5, 0x6f, 0xc0, 0x2e, + 0x44, 0x43, 0xc0, 0x5f, 0x40, 0x50, 0xd0, 0x7f, 0x4a, 0x17, 0x00, 0x40, + 0x01, 0x18, 0x46, 0x25, 0x07, 0x25, 0x65, 0x56, 0xd9, 0x04, 0x53, 0x18, + 0xeb, 0x18, 0x05, 0x30, 0x49, 0x16, 0x69, 0x06, 0xca, 0x18, 0xa6, 0x00, + 0xc7, 0x02, 0x65, 0x58, 0xcb, 0x7f, 0x98, 0x2e, 0x7f, 0xb6, 0xcb, 0x6f, + 0xd2, 0x6f, 0xc0, 0x2e, 0x80, 0x42, 0xc0, 0x5f, 0x09, 0x2e, 0x1b, 0x01, + 0x05, 0x2e, 0x1b, 0x01, 0xa3, 0xbc, 0x44, 0xbe, 0x90, 0x50, 0x4f, 0xb9, + 0x07, 0x2e, 0x1b, 0x01, 0x4a, 0x25, 0x9f, 0xb8, 0x39, 0x8f, 0xb2, 0xbd, + 0xf2, 0x7f, 0xbf, 0xb9, 0xeb, 0x7f, 0x8a, 0x0a, 0x37, 0x89, 0x0b, 0x30, + 0x93, 0x0a, 0x8b, 0x7f, 0xcb, 0x43, 0x0b, 0x43, 0x80, 0xb2, 0xd3, 0x7f, + 0xc1, 0x7f, 0x90, 0x2e, 0x87, 0xb2, 0x20, 0x25, 0x01, 0x2e, 0x64, 0x00, + 0x01, 0x90, 0x0e, 0x2f, 0x67, 0x52, 0x01, 0x2e, 0x61, 0x00, 0xb4, 0x7f, + 0xa2, 0x7f, 0x98, 0x2e, 0x8d, 0xb2, 0x00, 0x30, 0x21, 0x2e, 0x64, 0x00, + 0xc1, 0x6f, 0xd3, 0x6f, 0xa2, 0x6f, 0xb4, 0x6f, 0x0b, 0x30, 0x01, 0x2e, + 0x1b, 0x01, 0x06, 0xbc, 0x06, 0xbb, 0x57, 0x25, 0x01, 0x2e, 0x1b, 0x01, + 0x94, 0xb1, 0x05, 0xbc, 0xb6, 0x7f, 0x0f, 0xbb, 0x6b, 0x50, 0x80, 0xb3, + 0x0f, 0x2f, 0x0d, 0x2e, 0x1b, 0x01, 0x6f, 0x5e, 0xb7, 0x09, 0x2d, 0x2e, + 0x1b, 0x01, 0x71, 0x5c, 0x69, 0x5e, 0x9b, 0x43, 0x9b, 0x43, 0xdb, 0x43, + 0x9b, 0x43, 0x1b, 0x42, 0xcb, 0x43, 0x0b, 0x42, 0x8b, 0x43, 0x40, 0xb2, + 0x05, 0x2f, 0x69, 0x50, 0x00, 0x2e, 0x16, 0x40, 0x0b, 0x40, 0x76, 0x7f, + 0x8b, 0x7f, 0xcb, 0x0a, 0x01, 0x2e, 0x61, 0x00, 0x67, 0x52, 0x6d, 0x5c, + 0x98, 0x2e, 0xd3, 0xb2, 0x90, 0x6f, 0x00, 0xb2, 0x0b, 0x2f, 0xf0, 0x6f, + 0x00, 0xb2, 0x08, 0x2f, 0x69, 0x58, 0x6b, 0x50, 0x12, 0x41, 0x12, 0x42, + 0x21, 0x30, 0x04, 0x41, 0x04, 0x42, 0x23, 0x2e, 0x5e, 0xf0, 0xc0, 0x6f, + 0x00, 0xb2, 0x26, 0x2f, 0x74, 0x6f, 0x80, 0x6f, 0x71, 0x54, 0x88, 0xbd, + 0xc8, 0xb8, 0x4b, 0x0a, 0x94, 0x42, 0x91, 0x42, 0x90, 0x42, 0x88, 0xba, + 0x69, 0x52, 0xf3, 0x6f, 0x54, 0x42, 0x85, 0x42, 0xc0, 0x90, 0x40, 0x42, + 0x15, 0x2f, 0x6b, 0x52, 0x00, 0x2e, 0x52, 0x40, 0x41, 0x40, 0xa2, 0x04, + 0x41, 0x06, 0x40, 0xaa, 0x04, 0x2f, 0x40, 0x90, 0x0b, 0x2f, 0xb1, 0x6f, + 0x4a, 0x0f, 0x08, 0x2f, 0xb2, 0x6f, 0x80, 0xb2, 0x05, 0x2f, 0x6b, 0x54, + 0x21, 0x30, 0x94, 0x42, 0x80, 0x42, 0x23, 0x2e, 0x5e, 0xf0, 0xd0, 0x6f, + 0x00, 0xb2, 0x13, 0x2f, 0x01, 0x2e, 0x60, 0x00, 0x09, 0x2e, 0x7c, 0x00, + 0x04, 0x1a, 0x0d, 0x2f, 0x73, 0x50, 0x29, 0x2e, 0x60, 0x00, 0x24, 0x42, + 0x44, 0x30, 0x02, 0x40, 0x02, 0x42, 0x09, 0x80, 0x00, 0x2e, 0x04, 0x42, + 0x03, 0x2d, 0x10, 0x30, 0x21, 0x2e, 0x64, 0x00, 0xeb, 0x6f, 0x70, 0x5f, + 0xb8, 0x2e, 0x09, 0x86, 0x49, 0x54, 0xe4, 0x40, 0xc3, 0x80, 0x94, 0x04, + 0xc3, 0x40, 0x13, 0x05, 0x05, 0x40, 0x25, 0x05, 0x8a, 0x17, 0x73, 0x30, + 0x73, 0x09, 0x8c, 0x17, 0xf3, 0x08, 0xe3, 0x00, 0x4c, 0x82, 0x95, 0x00, + 0xb3, 0xb5, 0x23, 0xb5, 0x53, 0x42, 0x52, 0x42, 0x53, 0x42, 0x42, 0x42, + 0x71, 0x82, 0x75, 0x54, 0x52, 0x42, 0x10, 0x50, 0x77, 0x54, 0x52, 0x42, + 0xfb, 0x7f, 0x22, 0x30, 0x79, 0x56, 0x43, 0x42, 0x44, 0x82, 0x0b, 0x30, + 0x52, 0x42, 0x5b, 0x42, 0x7c, 0x84, 0x4b, 0x42, 0x35, 0x82, 0x8c, 0x80, + 0x8b, 0x42, 0x0b, 0x42, 0x39, 0x80, 0x04, 0x30, 0x0b, 0x42, 0x37, 0x80, + 0x15, 0x30, 0x60, 0x25, 0x98, 0x2e, 0xc6, 0xb2, 0x8b, 0x83, 0xfb, 0x6f, + 0x65, 0x42, 0xc0, 0x2e, 0x44, 0x42, 0xf0, 0x5f, 0x05, 0x80, 0x02, 0x30, + 0x51, 0x82, 0x02, 0x42, 0x13, 0x30, 0x41, 0x40, 0x4b, 0x08, 0x7b, 0x54, + 0x3e, 0x80, 0x51, 0x14, 0xc0, 0x2e, 0x01, 0x42, 0x00, 0x2e, 0x40, 0x51, + 0xd1, 0x7f, 0x12, 0x25, 0x02, 0x30, 0x42, 0x43, 0x32, 0x30, 0x82, 0x43, + 0xc6, 0x7f, 0xe5, 0x7f, 0xb4, 0x7f, 0xa3, 0x7f, 0x90, 0x7f, 0x8b, 0x7f, + 0x98, 0x2e, 0x54, 0x01, 0xc0, 0x7e, 0x00, 0xac, 0x01, 0x2f, 0x65, 0x50, + 0xc0, 0x7e, 0x00, 0x2e, 0x90, 0x6f, 0x09, 0x8a, 0xd1, 0x6f, 0x75, 0x7f, + 0x4c, 0x82, 0x63, 0x41, 0x65, 0x7f, 0x11, 0x7f, 0x00, 0x2e, 0x64, 0x41, + 0x44, 0x85, 0x52, 0x7f, 0x45, 0x7f, 0x00, 0x2e, 0xa6, 0x40, 0x80, 0x40, + 0x32, 0x7f, 0x82, 0x8e, 0xc2, 0x6e, 0x45, 0x41, 0xf0, 0x7f, 0x27, 0x7f, + 0x02, 0x7f, 0x98, 0x2e, 0x8a, 0xb1, 0x23, 0x6f, 0xd1, 0x6f, 0xc2, 0x40, + 0xf9, 0x86, 0x23, 0x7f, 0x80, 0xb2, 0xe0, 0x7e, 0x0f, 0x2f, 0x32, 0x6f, + 0x64, 0x6f, 0x82, 0x40, 0xf2, 0x7f, 0x4e, 0x82, 0x42, 0x6f, 0x50, 0x6f, + 0x73, 0x6f, 0x85, 0x40, 0xc3, 0x40, 0x04, 0x41, 0x06, 0x40, 0xe2, 0x6e, + 0x98, 0x2e, 0x8a, 0xb1, 0xe0, 0x7e, 0xf3, 0x31, 0x10, 0x6f, 0x36, 0x80, + 0xe1, 0x6e, 0x02, 0x40, 0x71, 0x7f, 0x51, 0x04, 0x02, 0x30, 0x40, 0xa8, + 0x91, 0x04, 0x4a, 0x22, 0x89, 0x16, 0x93, 0x08, 0x4a, 0x00, 0x95, 0xb4, + 0x09, 0x18, 0x8e, 0x16, 0x13, 0x30, 0x93, 0x08, 0x21, 0x6f, 0x60, 0x7f, + 0x4d, 0x86, 0x02, 0x80, 0xb2, 0x00, 0x41, 0x40, 0x21, 0xb5, 0x50, 0x7f, + 0x43, 0x7f, 0x98, 0x2e, 0xc2, 0xb1, 0x40, 0x6f, 0x62, 0x6f, 0x55, 0x6f, + 0x13, 0x40, 0x84, 0x40, 0x01, 0x40, 0x45, 0x41, 0x42, 0xbe, 0x1d, 0x18, + 0x4c, 0x04, 0x31, 0x0f, 0x04, 0x8a, 0xc0, 0x6f, 0x11, 0x30, 0x02, 0x2f, + 0x00, 0x2e, 0x03, 0x2c, 0x01, 0x42, 0x23, 0x30, 0x03, 0x42, 0x00, 0x2e, + 0xd6, 0x6f, 0x44, 0x41, 0x8a, 0x87, 0x76, 0x8b, 0x00, 0xb3, 0x53, 0x7f, + 0x15, 0x2f, 0x04, 0x6f, 0x7d, 0x5e, 0x8b, 0x8d, 0xe7, 0x01, 0xc0, 0xa5, + 0x84, 0x41, 0x01, 0x2f, 0x00, 0xa1, 0x03, 0x2f, 0xc0, 0xad, 0x08, 0x2f, + 0x00, 0xa5, 0x06, 0x2f, 0xc6, 0x40, 0x81, 0x8d, 0x07, 0x30, 0x3c, 0x05, + 0xd6, 0x42, 0x04, 0x2c, 0xc4, 0x42, 0x02, 0x2c, 0x07, 0x30, 0x07, 0x30, + 0x86, 0x86, 0x94, 0x6f, 0xd7, 0x7e, 0x0e, 0x8d, 0x00, 0x40, 0x74, 0x89, + 0xc7, 0x40, 0x02, 0xb2, 0xf9, 0x29, 0x45, 0x41, 0x86, 0x41, 0xbe, 0x80, + 0x21, 0x41, 0x75, 0x23, 0x82, 0x40, 0xc7, 0x42, 0x45, 0x7f, 0x34, 0x7f, + 0x20, 0x7f, 0x98, 0x2e, 0xc2, 0xb1, 0x31, 0x6f, 0x60, 0x6f, 0x24, 0x6f, + 0x22, 0x40, 0x05, 0x41, 0x43, 0x40, 0x13, 0x01, 0x43, 0x86, 0xac, 0x0f, + 0xd1, 0x6f, 0x30, 0x7f, 0x00, 0x2f, 0x44, 0x42, 0x48, 0x8a, 0x41, 0x88, + 0xe1, 0x40, 0x13, 0x7f, 0x04, 0x7f, 0xf5, 0x7e, 0x98, 0x2e, 0xc2, 0xb1, + 0x11, 0x6f, 0x60, 0x6f, 0x34, 0x6f, 0x42, 0x40, 0x03, 0x40, 0x9a, 0x04, + 0x04, 0x41, 0x43, 0x82, 0xa2, 0x0e, 0x03, 0x6f, 0x00, 0x2f, 0xc2, 0x42, + 0x00, 0x2e, 0x41, 0x40, 0x72, 0x6f, 0x98, 0x2e, 0xc2, 0xb1, 0x25, 0x6f, + 0x72, 0x6f, 0x53, 0x41, 0x93, 0x0e, 0xd1, 0x6f, 0x46, 0x80, 0x1b, 0x30, + 0x03, 0x30, 0x0c, 0x2f, 0x04, 0x40, 0x00, 0x91, 0x42, 0x42, 0x08, 0x2f, + 0xf6, 0x6e, 0x44, 0x6f, 0x86, 0x41, 0xb4, 0x0e, 0x03, 0x2f, 0x02, 0x88, + 0xdb, 0x7e, 0x03, 0x43, 0x0b, 0x42, 0x46, 0x8d, 0x44, 0x41, 0x47, 0x80, + 0x05, 0x6f, 0x94, 0x0f, 0x76, 0x7f, 0x60, 0x7f, 0x02, 0x2f, 0x45, 0x89, + 0x42, 0x43, 0x03, 0x43, 0x49, 0x88, 0xa5, 0x6f, 0x40, 0x91, 0xa4, 0x7f, + 0x15, 0x30, 0xe2, 0x6f, 0xd3, 0x6e, 0x03, 0x2f, 0x04, 0x30, 0x83, 0x42, + 0x80, 0x2e, 0x77, 0xb4, 0x04, 0x40, 0x25, 0x29, 0x04, 0x42, 0x83, 0x42, + 0x45, 0x82, 0x94, 0x6f, 0x04, 0x85, 0xc0, 0xb2, 0x90, 0x2e, 0x63, 0xb4, + 0x15, 0x87, 0x3c, 0x8c, 0xc4, 0x40, 0x46, 0x7f, 0xc2, 0x86, 0x07, 0x40, + 0x86, 0x41, 0xf4, 0xbf, 0x00, 0xb3, 0x0c, 0x2f, 0x90, 0x6f, 0x16, 0x80, + 0x46, 0x25, 0x00, 0x40, 0x57, 0x25, 0x04, 0x18, 0xae, 0x0e, 0x10, 0x30, + 0x06, 0x30, 0x75, 0x25, 0x46, 0x23, 0x60, 0x6f, 0x64, 0x25, 0xc4, 0x40, + 0xfa, 0x86, 0x00, 0xb3, 0x33, 0x7f, 0x09, 0x2f, 0x93, 0x6f, 0xd8, 0x88, + 0x53, 0x6f, 0x04, 0x41, 0xc3, 0x40, 0xdc, 0x0e, 0x13, 0x30, 0x04, 0x30, + 0xdc, 0x22, 0xb3, 0x25, 0x40, 0xb3, 0x02, 0x2f, 0x3b, 0x25, 0xc0, 0x90, + 0x05, 0x2f, 0x91, 0x6f, 0xd0, 0x6f, 0x98, 0x2e, 0xc6, 0xb2, 0x4d, 0x2c, + 0x04, 0x30, 0x8d, 0x88, 0x43, 0x40, 0x82, 0x40, 0x54, 0x7f, 0xda, 0x0f, + 0x04, 0x30, 0x08, 0x2f, 0xc1, 0x80, 0x40, 0x42, 0xc2, 0x0f, 0x02, 0x2f, + 0x00, 0x30, 0xc0, 0x7e, 0x1b, 0x2d, 0xc0, 0x7e, 0x19, 0x2d, 0xe1, 0xbc, + 0x92, 0x6f, 0x4f, 0x04, 0x90, 0x84, 0x40, 0xa8, 0x21, 0x05, 0x83, 0x40, + 0x4c, 0x22, 0x4b, 0x0e, 0xb6, 0x84, 0x21, 0x30, 0x02, 0x2f, 0x11, 0x30, + 0x04, 0x2c, 0xc1, 0x7e, 0xe3, 0x6f, 0xc1, 0x7e, 0xc1, 0x42, 0x00, 0x2e, + 0x00, 0x40, 0x81, 0x40, 0x04, 0xbd, 0x40, 0x6f, 0x98, 0x2e, 0xc2, 0xb1, + 0x50, 0x6f, 0x11, 0x30, 0x02, 0x40, 0x51, 0x08, 0xc3, 0x6e, 0x03, 0x80, + 0x99, 0x15, 0x0b, 0x40, 0xb1, 0x6f, 0xd0, 0x6f, 0xb6, 0x7f, 0x5b, 0x7f, + 0x04, 0x30, 0x4d, 0x54, 0x03, 0x30, 0x11, 0x2c, 0x10, 0x80, 0x55, 0x6f, + 0x06, 0x40, 0x75, 0x01, 0x58, 0xbb, 0x6a, 0x09, 0x05, 0x42, 0xc1, 0x86, + 0x47, 0x40, 0x51, 0x25, 0xbe, 0x01, 0x56, 0x43, 0x00, 0x2e, 0x46, 0x41, + 0xf4, 0x03, 0xb6, 0x6f, 0x47, 0x43, 0x5e, 0x0e, 0xed, 0x2f, 0x31, 0x6f, + 0x60, 0x6f, 0x42, 0x40, 0x15, 0x30, 0x02, 0x82, 0x95, 0x08, 0x04, 0x42, + 0x52, 0x42, 0x02, 0x2c, 0x44, 0x42, 0x04, 0x30, 0x3e, 0x8e, 0x91, 0x6f, + 0x4f, 0x8c, 0x02, 0x40, 0x83, 0x41, 0xb5, 0x8d, 0x93, 0x0e, 0xd0, 0x6f, + 0x01, 0x2f, 0x98, 0x2e, 0xc6, 0xb2, 0x00, 0x2e, 0xc0, 0x41, 0x81, 0x41, + 0xc1, 0x0f, 0xc0, 0x6f, 0x01, 0x2f, 0x04, 0x42, 0x00, 0x2e, 0x70, 0x6f, + 0x3c, 0x82, 0x00, 0x40, 0x41, 0x40, 0x89, 0x16, 0x95, 0x08, 0x4a, 0x00, + 0x04, 0xbc, 0x91, 0xb4, 0x01, 0x0e, 0xe0, 0x6f, 0x07, 0x2f, 0xa1, 0x6f, + 0x00, 0x2e, 0x41, 0x40, 0x40, 0xb2, 0x02, 0x2f, 0xa1, 0x6f, 0x05, 0x42, + 0x44, 0x42, 0x00, 0x2e, 0x8b, 0x6f, 0xc0, 0x5e, 0xb8, 0x2e, 0x03, 0x2e, + 0x1c, 0x01, 0x9c, 0xbc, 0x1d, 0xb9, 0x02, 0x82, 0x25, 0x2e, 0x8e, 0x00, + 0x83, 0x56, 0x13, 0x18, 0x01, 0x2e, 0x66, 0x00, 0x43, 0x40, 0xd8, 0x04, + 0x05, 0x2e, 0x65, 0x00, 0x40, 0x50, 0x27, 0x2e, 0x65, 0x00, 0xfb, 0x7f, + 0xda, 0x05, 0x8b, 0x50, 0x4b, 0x40, 0x02, 0x40, 0x81, 0x82, 0x01, 0x42, + 0x03, 0x80, 0x81, 0x52, 0xb1, 0x00, 0x03, 0x40, 0x3b, 0x82, 0x85, 0x58, + 0x14, 0x01, 0xc0, 0xb2, 0x37, 0x2e, 0x66, 0x00, 0xd1, 0x7f, 0xe2, 0x7f, + 0x04, 0x2f, 0x05, 0x2e, 0x6b, 0x00, 0x81, 0x84, 0x25, 0x2e, 0x6b, 0x00, + 0x62, 0x40, 0x3a, 0x0f, 0x45, 0x40, 0xc1, 0x7f, 0x21, 0x30, 0x12, 0x30, + 0x42, 0x2f, 0x0d, 0x2e, 0x69, 0x00, 0x3e, 0x0e, 0x33, 0x2f, 0x05, 0x2e, + 0x6a, 0x00, 0x01, 0x35, 0x91, 0x0e, 0x01, 0x30, 0x03, 0x2f, 0x09, 0x2e, + 0x6e, 0x00, 0x00, 0xb3, 0x24, 0x2f, 0xc0, 0x35, 0x90, 0x0e, 0x39, 0x2f, + 0x8f, 0x50, 0x02, 0x30, 0x01, 0x40, 0x7f, 0x82, 0x43, 0xa2, 0x02, 0x2f, + 0x00, 0x2e, 0x0c, 0x2c, 0x01, 0x30, 0xc0, 0xb2, 0x11, 0x30, 0x02, 0x2f, + 0x25, 0x2e, 0x6d, 0x00, 0x03, 0x2d, 0x23, 0x2e, 0x6d, 0x00, 0x21, 0x30, + 0x25, 0x2e, 0x6b, 0x00, 0x42, 0xb2, 0x04, 0x2f, 0x41, 0xb2, 0x02, 0x2f, + 0x25, 0x2e, 0x6d, 0x00, 0x31, 0x30, 0x3e, 0x80, 0x04, 0x86, 0x25, 0x2e, + 0x6c, 0x00, 0x02, 0x42, 0xc2, 0x42, 0x18, 0x2d, 0x02, 0x35, 0x01, 0x42, + 0x25, 0x2e, 0x6a, 0x00, 0x13, 0x2d, 0x2c, 0x04, 0x38, 0x1e, 0x21, 0x2e, + 0x69, 0x00, 0x7f, 0x50, 0x11, 0x30, 0x22, 0x30, 0x98, 0x2e, 0x66, 0xb5, + 0x09, 0x2c, 0x01, 0x30, 0x2c, 0x00, 0x38, 0x1c, 0x21, 0x2e, 0x68, 0x00, + 0x7f, 0x50, 0x98, 0x2e, 0x66, 0xb5, 0x01, 0x30, 0xc0, 0x6f, 0xd4, 0xb1, + 0xf5, 0xbd, 0x6b, 0xba, 0x91, 0x5a, 0x02, 0x40, 0x15, 0x18, 0xf5, 0xbe, + 0xeb, 0xbb, 0xe3, 0x0a, 0x3d, 0x0b, 0xd2, 0x6f, 0xe3, 0x00, 0x84, 0x40, + 0x63, 0x05, 0x93, 0x58, 0x2c, 0x18, 0xf5, 0xbe, 0x03, 0x42, 0xeb, 0xbb, + 0xfd, 0x0b, 0xe0, 0x6f, 0x58, 0x01, 0xdf, 0x01, 0x7d, 0x1f, 0x95, 0x42, + 0x18, 0x04, 0x85, 0x40, 0x5d, 0x05, 0x2c, 0x18, 0x75, 0xbe, 0xeb, 0xba, + 0x2c, 0x0b, 0xdc, 0x04, 0x18, 0x1c, 0x80, 0x42, 0x84, 0x80, 0x02, 0x30, + 0x00, 0x40, 0x00, 0xb2, 0x0c, 0x2f, 0x01, 0x2e, 0x6b, 0x00, 0x03, 0x35, + 0x83, 0x0e, 0x07, 0x2f, 0x8d, 0x50, 0x3e, 0x80, 0x25, 0x2e, 0x6d, 0x00, + 0x02, 0x42, 0x03, 0x80, 0x00, 0x2e, 0x02, 0x42, 0x40, 0xb2, 0x04, 0x2f, + 0x8b, 0x50, 0x04, 0x80, 0x25, 0x2e, 0x6a, 0x00, 0x02, 0x42, 0x42, 0xb2, + 0x89, 0x56, 0x9a, 0x22, 0x41, 0xb2, 0x01, 0x2e, 0x1c, 0x01, 0x87, 0x52, + 0x0b, 0xbc, 0x8a, 0x22, 0x0f, 0xb8, 0x00, 0x90, 0x01, 0x32, 0x06, 0x2f, + 0x10, 0x30, 0x90, 0x08, 0x80, 0xb2, 0x08, 0x2f, 0x23, 0x2e, 0x5e, 0xf0, + 0x06, 0x2d, 0x20, 0x30, 0x90, 0x08, 0x80, 0xb2, 0x01, 0x2f, 0x23, 0x2e, + 0x5e, 0xf0, 0xfb, 0x6f, 0xc0, 0x5f, 0xb8, 0x2e, 0x07, 0x86, 0xfc, 0x88, + 0xc6, 0x40, 0x05, 0x41, 0x31, 0x1a, 0x12, 0x2f, 0x80, 0x91, 0x22, 0x2f, + 0x01, 0x35, 0x29, 0x0f, 0x0a, 0x2f, 0x06, 0x80, 0x00, 0x2e, 0x00, 0x40, + 0x00, 0xb2, 0x01, 0x2f, 0x44, 0xa9, 0x03, 0x2f, 0x00, 0x30, 0xc0, 0x42, + 0x00, 0x43, 0xb8, 0x2e, 0xc2, 0x42, 0x01, 0x43, 0xb8, 0x2e, 0x01, 0x35, + 0xa9, 0x0e, 0x0e, 0x2f, 0x03, 0x3b, 0xeb, 0x00, 0xcc, 0xa8, 0x0a, 0x2f, + 0x05, 0x86, 0xc2, 0x80, 0xc3, 0x40, 0x02, 0x42, 0x3c, 0x84, 0xc1, 0x80, + 0x81, 0x42, 0x82, 0x84, 0xc0, 0x2e, 0x80, 0x42, 0x00, 0x2e, 0xb8, 0x2e, + 0x03, 0x2e, 0x1d, 0x01, 0x9f, 0xbc, 0x9f, 0xb8, 0x90, 0x50, 0x40, 0xb2, + 0x90, 0x2e, 0x71, 0xb6, 0x12, 0x40, 0x03, 0x30, 0x11, 0x40, 0x80, 0xa8, + 0x5a, 0x05, 0x9f, 0x58, 0x55, 0x23, 0x00, 0x40, 0x75, 0x7f, 0x40, 0xa8, + 0x16, 0x41, 0xd9, 0x05, 0xcf, 0x23, 0x56, 0x05, 0x40, 0xa9, 0x9d, 0x05, + 0x87, 0x7f, 0x6e, 0x23, 0x17, 0x41, 0xa5, 0x7f, 0x3e, 0x8b, 0x04, 0x41, + 0x52, 0x43, 0x00, 0xa8, 0x98, 0x05, 0xf2, 0x7f, 0x86, 0x22, 0xcf, 0x05, + 0xc0, 0xa9, 0x9f, 0x05, 0xbe, 0x23, 0x04, 0x05, 0x92, 0x7f, 0x00, 0xa9, + 0xdc, 0x05, 0x51, 0x43, 0xb6, 0x7f, 0x27, 0x23, 0xa7, 0x54, 0xe1, 0x7f, + 0x02, 0x18, 0x7d, 0x83, 0x40, 0x43, 0xeb, 0xba, 0x75, 0xbd, 0xaa, 0x0a, + 0x0b, 0x2e, 0x71, 0x00, 0x77, 0x5c, 0x2e, 0x18, 0xf5, 0xbe, 0x6b, 0xbb, + 0x75, 0x0b, 0xaa, 0x00, 0xc4, 0x7f, 0x25, 0x2e, 0x71, 0x00, 0xb2, 0x6f, + 0xa5, 0x6f, 0xaa, 0x00, 0x54, 0x01, 0x84, 0x6f, 0x72, 0x6f, 0x94, 0x05, + 0x80, 0xa9, 0xde, 0x05, 0xb7, 0x23, 0x99, 0x5e, 0x77, 0x0e, 0x41, 0x40, + 0x97, 0x5c, 0xb1, 0x01, 0xd5, 0x7f, 0x00, 0x2e, 0x85, 0x41, 0x0e, 0x2f, + 0x00, 0xa0, 0x0c, 0x2f, 0x14, 0x0f, 0x04, 0x2f, 0xe0, 0x6f, 0x00, 0xac, + 0x10, 0x30, 0x08, 0x2c, 0x18, 0x22, 0xf0, 0x6f, 0x00, 0xac, 0x30, 0x30, + 0x24, 0x30, 0x02, 0x2c, 0x20, 0x22, 0x40, 0x30, 0x0d, 0x2e, 0x71, 0x00, + 0x80, 0xa1, 0x1e, 0x23, 0x79, 0x5e, 0x37, 0x0f, 0xbc, 0x23, 0x00, 0x90, + 0x14, 0x30, 0x10, 0x30, 0x18, 0x2f, 0x9d, 0x50, 0x30, 0x00, 0x9b, 0x56, + 0x43, 0x0e, 0x02, 0x2f, 0x10, 0x30, 0x0a, 0x2c, 0x03, 0x30, 0x99, 0x50, + 0x10, 0x0e, 0x13, 0x30, 0x00, 0x2f, 0x03, 0x30, 0x90, 0x0f, 0x10, 0x30, + 0x00, 0x2f, 0x00, 0x30, 0x00, 0x90, 0x10, 0x30, 0x00, 0x2f, 0x00, 0x30, + 0xc0, 0x90, 0x13, 0x30, 0x00, 0x2f, 0x03, 0x30, 0x40, 0xb2, 0x87, 0x5c, + 0x22, 0x2f, 0x41, 0x90, 0x4a, 0x2f, 0xa5, 0x50, 0x00, 0x2e, 0x01, 0x40, + 0x41, 0x82, 0x01, 0x42, 0x02, 0x80, 0x4a, 0xa8, 0x01, 0x40, 0x06, 0x2f, + 0xd0, 0x6f, 0x85, 0x0e, 0x3e, 0x2f, 0x41, 0x80, 0x21, 0x2e, 0x78, 0x00, + 0x3b, 0x2d, 0x95, 0x50, 0xfb, 0x7f, 0x4a, 0xa8, 0x06, 0x2f, 0x98, 0x2e, + 0x73, 0xb6, 0xc0, 0x90, 0xfb, 0x6f, 0x32, 0x2f, 0x00, 0x2e, 0x30, 0x2d, + 0x98, 0x2e, 0x73, 0xb6, 0x29, 0x2e, 0x7a, 0x00, 0x2b, 0x2c, 0xfb, 0x6f, + 0xa1, 0x52, 0xd2, 0x6f, 0x95, 0x0e, 0x41, 0x40, 0x05, 0x2f, 0x00, 0x90, + 0x17, 0x2f, 0x05, 0x2e, 0x7a, 0x00, 0x80, 0x90, 0x13, 0x2f, 0x7f, 0x82, + 0x40, 0xac, 0x23, 0x2e, 0x77, 0x00, 0x01, 0x30, 0x18, 0x2f, 0xa1, 0x54, + 0x82, 0x84, 0x23, 0x2e, 0x77, 0x00, 0x82, 0x40, 0x80, 0xb2, 0x11, 0x2f, + 0x00, 0x90, 0x23, 0x2e, 0x79, 0x00, 0x0d, 0x2f, 0x29, 0x2e, 0x72, 0x00, + 0x0b, 0x2d, 0x41, 0x80, 0x21, 0x2e, 0x77, 0x00, 0x0f, 0xa4, 0x05, 0x2f, + 0xa3, 0x50, 0x3e, 0x80, 0xf1, 0x30, 0x29, 0x2e, 0x79, 0x00, 0x01, 0x42, + 0x06, 0x30, 0x34, 0x08, 0x00, 0xb2, 0x02, 0x2f, 0x80, 0x30, 0x21, 0x2e, + 0x5e, 0xf0, 0x70, 0x5f, 0xb8, 0x2e, 0x04, 0x84, 0x01, 0x30, 0x81, 0x42, + 0x82, 0x84, 0x01, 0x42, 0xa1, 0x42, 0x81, 0x42, 0x82, 0x84, 0x00, 0x2e, + 0x91, 0x42, 0x81, 0x42, 0xb8, 0x2e, 0x30, 0x50, 0xf3, 0x7f, 0xc0, 0xac, + 0xe4, 0x7f, 0xd5, 0x7f, 0x03, 0x2f, 0x00, 0x30, 0x82, 0x04, 0xf3, 0x6f, + 0xc3, 0x06, 0x40, 0xad, 0x05, 0x2f, 0xe0, 0x6f, 0x05, 0x30, 0x28, 0x04, + 0xd1, 0x6f, 0x69, 0x07, 0xe0, 0x7f, 0x40, 0xa1, 0x01, 0x30, 0x20, 0x2f, + 0x13, 0x25, 0x02, 0x25, 0x04, 0x32, 0x06, 0x30, 0x02, 0x30, 0x03, 0x30, + 0xaf, 0xbb, 0xb1, 0xbd, 0xdf, 0x0a, 0x9f, 0xbb, 0x21, 0xbd, 0x97, 0x0a, + 0x8f, 0xbb, 0x91, 0xbc, 0x01, 0xbc, 0x4f, 0x0a, 0x6b, 0x0e, 0x04, 0x2f, + 0x6b, 0x1a, 0x07, 0x2f, 0xe7, 0x6f, 0x7a, 0x0f, 0x04, 0x2f, 0xe7, 0x6f, + 0x97, 0x04, 0x17, 0x30, 0x07, 0x0a, 0xdd, 0x06, 0x81, 0x8d, 0x34, 0x0e, + 0xe6, 0x2f, 0x00, 0x2e, 0x0d, 0x2d, 0x6b, 0x0e, 0x00, 0x30, 0x05, 0x2f, + 0x6b, 0x1a, 0x07, 0x2f, 0xe0, 0x6f, 0x42, 0x0f, 0x00, 0x30, 0x03, 0x2f, + 0xe0, 0x6f, 0x90, 0x04, 0xdd, 0x06, 0x10, 0x30, 0xf5, 0x6f, 0xc3, 0x7f, + 0xb2, 0x7f, 0x40, 0xad, 0x06, 0x2f, 0x03, 0x30, 0xb2, 0x6f, 0x9a, 0x04, + 0xc4, 0x6f, 0xdc, 0x06, 0xb2, 0x7f, 0xc3, 0x7f, 0x00, 0x2e, 0xd2, 0x6f, + 0xaa, 0x0c, 0x80, 0xac, 0x02, 0x30, 0x01, 0x2f, 0x10, 0x04, 0x51, 0x06, + 0xd0, 0x5f, 0xb8, 0x2e, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00 +}; + +/***************************************************************************/ +/*! Static Function Declarations +****************************************************************************/ +/*! + * @brief This API update the length for read and write. + * + * @param[in] len : Length for read and write + * @param[in] feature : Variable to specify the features + * which are to be set in the sensor. + * @param[in] enable : Variable which specifies whether to enable or + * disable the features in the bma455 sensor. + * enable | Macros + * ----------------|------------------- + * 0x01 | BMA4_EN + * 0x00 | BMA4_DIS + * @param[in] dev : Structure instance of bma4_dev. + * + * @return none + */ +static void update_len(uint8_t *len, uint8_t feature, uint8_t enable); + +/*! + * @brief This API enables the features of sensor. + * + * @param[in] feature : Variable to specify the features + * which are to be set in the sensor. + * @param[in] len : length to read and write + * @param[in] feature_config : Array address which stores the feature + * configuration data + * @param[in] dev : Structure instance of bma4_dev. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any positive value mentioned in ERROR CODES -> Fail + */ +static uint16_t feature_enable(uint8_t feature, uint8_t len, uint8_t *feature_config, struct bma4_dev *dev); + +/*! + * @brief This API disables the features of sensor. + * + * @param[in] feature : Variable to specify the features + * which are to be unset in the sensor. + * @param[in] len : length to read and write + * @param[in] feature_config : Array address which stores the feature + * configuration data + * @param[in] dev : Structure instance of bma4_dev. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any positive value mentioned in ERROR CODES -> Fail + */ +static uint16_t feature_disable(uint8_t feature, uint8_t len, uint8_t *feature_config, struct bma4_dev *dev); + +/*! + * @brief This API update the settings of step counter into write array. + * + * @param[in] setting : Pointer to structure variable which stores the + * settings parameter1 to parameter25. + * @param[in] index : value for array traversing. + * @param[out] feature_config : Pointer to store the settings + * + * @return none + */ +static void update_stepcounter_parameter(const struct bma423_stepcounter_settings *setting, + uint8_t index, uint8_t *feature_config); +/*! + * @brief This API copy the settings of step counter into the + * structure of bma423_stepcounter_settings, which is read from sensor. + * + * @param[out] setting : Pointer to structure variable which stores the + * settings parameter1 to parameter25 read from sensor. + * @param[in] data_p : Pointer of array which stores the parameters. + * + * @return none + */ +static void extract_stepcounter_parameter(struct bma423_stepcounter_settings *setting, const uint16_t *data_p); + +/***************************************************************************/ +/**\name Function definitions +****************************************************************************/ + +/*! + * @brief This API is the entry point. + * Call this API before using all other APIs. + * This API reads the chip-id of the sensor and sets the resolution. + */ +#include +uint16_t bma423_init(struct bma4_dev *dev) +{ + uint16_t rslt; + + rslt = bma4_init(dev); + + if (rslt == BMA4_OK) { + if (dev->chip_id == BMA423_CHIP_ID) { + /* Resolution of BMA423 sensor is 12 bit */ + dev->resolution = 12; + dev->feature_len = BMA423_FEATURE_SIZE; + dev->variant = BMA42X_VARIANT; + } else { + rslt |= BMA4_E_INVALID_SENSOR; + } + } + + return rslt; +} + +/*! + * @brief This API is used to upload the config file to enable + * the features of the sensor. + */ +uint16_t bma423_write_config_file(struct bma4_dev *dev) +{ + uint16_t rslt = BMA4_OK; + + if (dev != NULL) { + if (dev->chip_id == BMA423_CHIP_ID) { + /* Config. stream read/write length boundary check */ + if ((dev->read_write_len >= BMA423_RD_WR_MIN_LEN) && + (dev->read_write_len <= BMA423_FEATURE_SIZE)) { + /* Even or odd check */ + if ((dev->read_write_len % 2) != 0) + dev->read_write_len = dev->read_write_len - 1; + /*Assign stream data */ + dev->config_file_ptr = bma423_config_file; + rslt = bma4_write_config_file(dev); + } else { + rslt = BMA4_E_RD_WR_LENGTH_INVALID; + } + } else { + rslt = BMA4_E_INVALID_SENSOR; + } + } else { + rslt = BMA4_E_NULL_PTR; + } + return rslt; +} + +/*! + * @brief This API is used to get the configuration id of the sensor. + */ +uint16_t bma423_get_config_id(uint16_t *config_id, struct bma4_dev *dev) +{ + uint8_t feature_config[BMA423_FEATURE_SIZE] = {0}; + uint8_t index = BMA423_CONFIG_ID_OFFSET; + uint16_t rslt = BMA4_OK; + uint16_t config_id_lsb = 0; + uint16_t config_id_msb = 0; + + if (dev != NULL) { + if (dev->chip_id == BMA423_CHIP_ID) { + rslt = bma4_read_regs(BMA4_FEATURE_CONFIG_ADDR, feature_config, BMA423_FEATURE_SIZE, dev); + if (rslt == BMA4_OK) { + config_id_lsb = (uint16_t)feature_config[index]; + config_id_msb = ((uint16_t)feature_config[index + 1]) << 8; + *config_id = config_id_lsb | config_id_msb; + } + } else { + rslt = BMA4_E_INVALID_SENSOR; + } + } else { + rslt = BMA4_E_NULL_PTR; + } + + return rslt; +} + +/*! + * @brief This API sets/unsets the user provided interrupt to either + * interrupt pin1 or pin2 in the sensor. + */ +uint16_t bma423_map_interrupt(uint8_t int_line, uint16_t int_map, uint8_t enable, struct bma4_dev *dev) +{ + uint16_t rslt = BMA4_OK; + + if (dev != NULL) { + if (dev->chip_id == BMA423_CHIP_ID) { + if (int_line <= 1) { + /* Map/Unmap the interrupt */ + rslt = bma4_map_interrupt(int_line, int_map, enable, dev); + } else { + rslt = BMA4_E_INT_LINE_INVALID; + } + } else { + rslt = BMA4_E_INVALID_SENSOR; + } + } else { + rslt = BMA4_E_NULL_PTR; + } + + return rslt; +} + +/*! + * @brief This API reads the bma423 interrupt status from the sensor. + */ +uint16_t bma423_read_int_status(uint16_t *int_status, struct bma4_dev *dev) +{ + uint16_t rslt = BMA4_OK; + + if (dev != NULL) { + if (dev->chip_id == BMA423_CHIP_ID) { + /* Read the interrupt status */ + rslt = bma4_read_int_status(int_status, dev); + } else { + rslt = BMA4_E_INVALID_SENSOR; + } + } else { + rslt = BMA4_E_NULL_PTR; + } + + return rslt; +} + +/*! + * @brief This API enables/disables the features of the sensor. + */ +uint16_t bma423_feature_enable(uint8_t feature, uint8_t enable, struct bma4_dev *dev) +{ + uint8_t feature_config[BMA423_FEATURE_SIZE] = {0}; + uint16_t rslt = BMA4_OK; + uint8_t len; + + if (dev != NULL) { + if (dev->chip_id == BMA423_CHIP_ID) { + /* Update the length for read and write */ + update_len(&len, feature, enable); + rslt = bma4_read_regs(BMA4_FEATURE_CONFIG_ADDR, feature_config, len, dev); + if (rslt == BMA4_OK) { + if (enable == TRUE) { + /* Enables the feature */ + rslt |= feature_enable(feature, len, feature_config, dev); + } else { + /* Disables the feature */ + rslt |= feature_disable(feature, len, feature_config, dev); + } + } + } else { + rslt = BMA4_E_INVALID_SENSOR; + } + } else { + rslt = BMA4_E_NULL_PTR; + } + + return rslt; +} + +/*! + * @brief This API performs x, y and z axis remapping in the sensor. + */ +uint16_t bma423_set_remap_axes(const struct bma423_axes_remap *remap_data, struct bma4_dev *dev) +{ + uint8_t feature_config[BMA423_FEATURE_SIZE] = {0}; + uint8_t index = BMA423_AXES_REMAP_OFFSET; + uint16_t rslt = BMA4_OK; + uint8_t x_axis = 0; + uint8_t x_axis_sign = 0; + uint8_t y_axis = 0; + uint8_t y_axis_sign = 0; + uint8_t z_axis = 0; + + if (dev != NULL) { + if (dev->chip_id == BMA423_CHIP_ID) { + rslt = bma4_read_regs(BMA4_FEATURE_CONFIG_ADDR, feature_config, BMA423_FEATURE_SIZE, dev); + if (rslt == BMA4_OK) { + x_axis = remap_data->x_axis & BMA423_X_AXIS_MASK; + x_axis_sign = (remap_data->x_axis_sign << 2) & BMA423_X_AXIS_SIGN_MASK; + y_axis = (remap_data->y_axis << 3) & BMA423_Y_AXIS_MASK; + y_axis_sign = (remap_data->y_axis_sign << 5) & BMA423_Y_AXIS_SIGN_MASK; + z_axis = (remap_data->z_axis << 6) & BMA423_Z_AXIS_MASK; + feature_config[index] = x_axis | x_axis_sign | y_axis | y_axis_sign | z_axis; + feature_config[index + 1] = remap_data->z_axis_sign & BMA423_Z_AXIS_SIGN_MASK; + rslt |= bma4_write_regs(BMA4_FEATURE_CONFIG_ADDR, feature_config, + BMA423_FEATURE_SIZE, dev); + } + } else { + rslt = BMA4_E_INVALID_SENSOR; + } + } else { + rslt = BMA4_E_NULL_PTR; + } + + return rslt; +} + +/*! + * @brief This API reads the x, y and z axis remap data from the sensor. + */ +uint16_t bma423_get_remap_axes(struct bma423_axes_remap *remap_data, struct bma4_dev *dev) +{ + uint8_t feature_config[BMA423_FEATURE_SIZE] = {0}; + uint8_t index = BMA423_AXES_REMAP_OFFSET; + uint16_t rslt = BMA4_OK; + + if (dev != NULL) { + if (dev->chip_id == BMA423_CHIP_ID) { + rslt = bma4_read_regs(BMA4_FEATURE_CONFIG_ADDR, feature_config, BMA423_FEATURE_SIZE, dev); + if (rslt == BMA4_OK) { + remap_data->x_axis = feature_config[index] & BMA423_X_AXIS_MASK; + remap_data->x_axis_sign = (feature_config[index] & BMA423_X_AXIS_SIGN_MASK) >> 2; + remap_data->y_axis = (feature_config[index] & BMA423_Y_AXIS_MASK) >> 3; + remap_data->y_axis_sign = (feature_config[index] & BMA423_Y_AXIS_SIGN_MASK) >> 5; + remap_data->z_axis = (feature_config[index] & BMA423_Z_AXIS_MASK) >> 6; + remap_data->z_axis_sign = (feature_config[index + 1] & BMA423_Z_AXIS_SIGN_MASK); + } + } else { + rslt = BMA4_E_INVALID_SENSOR; + } + } else { + rslt = BMA4_E_NULL_PTR; + } + + return rslt; +} + +/*! + * @brief This API enables the any motion feature according to the axis + * set by the user in the sensor. + */ +uint16_t bma423_anymotion_enable_axis(uint8_t axis, struct bma4_dev *dev) +{ + uint8_t feature_config[BMA423_ANYMOTION_EN_LEN + 2] = {0}; + /* Anymotion axis enable bit pos. is 3 byte ahead of the + anymotion base address(0x00) */ + uint8_t index = 3; + uint16_t rslt = BMA4_OK; + + if (dev != NULL) { + if (dev->chip_id == BMA423_CHIP_ID) { + rslt = bma4_read_regs(BMA4_FEATURE_CONFIG_ADDR, feature_config, + BMA423_ANYMOTION_EN_LEN + 2, dev); + if (rslt == BMA4_OK) { + feature_config[index] = BMA4_SET_BITSLICE(feature_config[index], + BMA423_ANY_NO_MOTION_AXIS_EN, axis); + rslt |= bma4_write_regs(BMA4_FEATURE_CONFIG_ADDR, feature_config, + BMA423_ANYMOTION_EN_LEN + 2, dev); + } + } else { + rslt = BMA4_E_INVALID_SENSOR; + } + } else { + rslt = BMA4_E_NULL_PTR; + } + + return rslt; +} + +/*! @brief This API sets the configuration of Any motion feature in + * the sensor. + */ +uint16_t bma423_set_any_motion_config(const struct bma423_anymotion_config *any_motion, struct bma4_dev *dev) +{ + uint8_t feature_config[BMA423_ANYMOTION_EN_LEN + 2] = {0}; + uint8_t index = BMA423_ANY_NO_MOTION_OFFSET; + uint16_t duration_lsb = 0; + uint16_t duration_msb = 0; + uint16_t duration = 0; + uint16_t rslt = BMA4_OK; + + if (dev != NULL) { + if (dev->chip_id == BMA423_CHIP_ID) { + rslt = bma4_read_regs(BMA4_FEATURE_CONFIG_ADDR, feature_config, + BMA423_ANYMOTION_EN_LEN + 2, dev); + if (rslt == BMA4_OK) { + /* Assign threshold value in feature config array */ + feature_config[index++] = BMA4_GET_LSB(any_motion->threshold); + feature_config[index] = BMA4_GET_MSB(any_motion->threshold); + /* Assign no motion selection value in feature config array*/ + feature_config[index++] |= (uint8_t) + (any_motion->nomotion_sel << BMA423_ANY_NO_MOTION_SEL_POS); + + /* Extract duration */ + duration_lsb = feature_config[index]; + duration_msb = feature_config[index + 1] << 8; + duration = duration_lsb | duration_msb; + duration = BMA4_SET_BITS_POS_0(duration, + BMA423_ANY_NO_MOTION_DUR, any_motion->duration); + /* Assign duration value in feature config array*/ + feature_config[index++] = BMA4_GET_LSB(duration); + feature_config[index] = BMA4_GET_MSB(duration); + + /* Write any motion settings to the sensor*/ + rslt |= bma4_write_regs(BMA4_FEATURE_CONFIG_ADDR, feature_config, + BMA423_ANYMOTION_EN_LEN + 2, dev); + } + } else { + rslt = BMA4_E_INVALID_SENSOR; + } + } else { + rslt = BMA4_E_NULL_PTR; + } + + return rslt; +} + +/*! @brief This API gets the configuration of any motion feature from + * the sensor. + */ +uint16_t bma423_get_any_motion_config(struct bma423_anymotion_config *any_motion, struct bma4_dev *dev) +{ + uint8_t feature_config[BMA423_ANYMOTION_EN_LEN + 2] = {0}; + uint8_t anymotion = 0; + uint16_t rslt = BMA4_OK; + uint16_t *data_p = (uint16_t *)feature_config; + + if (dev != NULL) { + if (dev->chip_id == BMA423_CHIP_ID) { + rslt = bma4_read_regs(BMA4_FEATURE_CONFIG_ADDR, feature_config, + BMA423_ANYMOTION_EN_LEN + 2, dev); + if (rslt == BMA4_OK) { + /* Extract threshold value */ + any_motion->threshold = (*data_p) & BMA423_ANY_NO_MOTION_THRES_MSK; + /* Extract threshold & nomotion selection + * data */ + anymotion = ((uint8_t)(*(data_p++) >> 8)) & BMA423_ANY_NO_MOTION_SEL_MSK; + /* Extract no motion field */ + any_motion->nomotion_sel = anymotion >> + BMA423_ANY_NO_MOTION_SEL_POS; + /* Extract duration value */ + any_motion->duration = (*(data_p)) & BMA423_ANY_NO_MOTION_DUR_MSK; + } + } else { + rslt = BMA4_E_INVALID_SENSOR; + } + } else { + rslt = BMA4_E_NULL_PTR; + } + + return rslt; +} + +/*! + * @brief This API enables or disables the step detector feature in the + * sensor. + */ +uint16_t bma423_step_detector_enable(uint8_t enable, struct bma4_dev *dev) +{ + uint8_t feature_config[BMA423_FEATURE_SIZE] = {0}; + uint16_t rslt = BMA4_OK; + /* Step detector enable bit pos. is 1 byte ahead of the base address */ + uint8_t index = BMA423_STEP_CNTR_OFFSET + 1; + + if (dev != NULL) { + if (dev->chip_id == BMA423_CHIP_ID) { + rslt = bma4_read_regs(BMA4_FEATURE_CONFIG_ADDR, feature_config, + BMA423_FEATURE_SIZE, dev); + if (rslt == BMA4_OK) { + feature_config[index] = BMA4_SET_BITSLICE(feature_config[index], + BMA423_STEP_DETECTOR_EN, enable); + rslt |= bma4_write_regs(BMA4_FEATURE_CONFIG_ADDR, feature_config, + BMA423_FEATURE_SIZE, dev); + } + } else { + rslt = BMA4_E_INVALID_SENSOR; + } + } else { + rslt = BMA4_E_NULL_PTR; + } + + return rslt; +} + +/*! + * @brief This API sets the watermark level for step counter + * interrupt in the sensor. + */ +uint16_t bma423_step_counter_set_watermark(uint16_t step_counter_wm, struct bma4_dev *dev) +{ + uint8_t feature_config[BMA423_FEATURE_SIZE] = {0}; + uint8_t index = BMA423_STEP_CNTR_OFFSET; + uint16_t wm_lsb = 0; + uint16_t wm_msb = 0; + uint16_t rslt = BMA4_OK; + uint16_t data = 0; + + if (dev != NULL) { + if (dev->chip_id == BMA423_CHIP_ID) { + rslt = bma4_read_regs(BMA4_FEATURE_CONFIG_ADDR, feature_config, + BMA423_FEATURE_SIZE, dev); + if (rslt == BMA4_OK) { + wm_lsb = feature_config[index]; + wm_msb = feature_config[index + 1] << 8; + data = wm_lsb | wm_msb; + /* Sets only watermark bits in the complete + 16 bits of data */ + data = BMA4_SET_BITS_POS_0(data, BMA423_STEP_CNTR_WM, step_counter_wm); + /* Splits 16 bits of data to individual + 8 bits data */ + feature_config[index] = BMA4_GET_LSB(data); + feature_config[index + 1] = BMA4_GET_MSB(data); + /* Writes stepcounter watermark settings + in the sensor */ + rslt |= bma4_write_regs(BMA4_FEATURE_CONFIG_ADDR, feature_config, + BMA423_FEATURE_SIZE, dev); + } + } else { + rslt = BMA4_E_INVALID_SENSOR; + } + } else { + rslt = BMA4_E_NULL_PTR; + } + + return rslt; +} + +/*! + * @brief This API gets the water mark level set for step counter interrupt + * in the sensor + */ +uint16_t bma423_step_counter_get_watermark(uint16_t *step_counter_wm, struct bma4_dev *dev) +{ + uint8_t feature_config[BMA423_FEATURE_SIZE] = {0}; + uint8_t index = BMA423_STEP_CNTR_OFFSET; + uint16_t wm_lsb = 0; + uint16_t wm_msb = 0; + uint16_t rslt = BMA4_OK; + uint16_t data = 0; + + if (dev != NULL) { + if (dev->chip_id == BMA423_CHIP_ID) { + rslt = bma4_read_regs(BMA4_FEATURE_CONFIG_ADDR, feature_config, + BMA423_FEATURE_SIZE, dev); + if (rslt == BMA4_OK) { + wm_lsb = feature_config[index]; + wm_msb = feature_config[index + 1] << 8; + data = wm_lsb | wm_msb; + *step_counter_wm = BMA4_GET_BITS_POS_0(data, BMA423_STEP_CNTR_WM); + } + } else { + rslt = BMA4_E_INVALID_SENSOR; + } + } else { + rslt = BMA4_E_NULL_PTR; + } + + return rslt; +} + +/*! + * @brief This API resets the counted steps of step counter. + */ +uint16_t bma423_reset_step_counter(struct bma4_dev *dev) +{ + uint8_t feature_config[BMA423_FEATURE_SIZE] = {0}; + /* Reset bit is 1 byte ahead of base address */ + uint8_t index = BMA423_STEP_CNTR_OFFSET + 1; + uint16_t rslt = BMA4_OK; + + if (dev != NULL) { + if (dev->chip_id == BMA423_CHIP_ID) { + rslt = bma4_read_regs(BMA4_FEATURE_CONFIG_ADDR, feature_config, + BMA423_FEATURE_SIZE, dev); + + if (rslt == BMA4_OK) { + feature_config[index] = BMA4_SET_BITSLICE(feature_config[index], + BMA423_STEP_CNTR_RST, 1); + rslt |= bma4_write_regs(BMA4_FEATURE_CONFIG_ADDR, feature_config, + BMA423_FEATURE_SIZE, dev); + } + } else { + rslt = BMA4_E_INVALID_SENSOR; + } + } else { + rslt = BMA4_E_NULL_PTR; + } + return rslt; +} + +/*! + * @brief This API gets the number of counted steps of the step counter + * feature from the sensor. + */ +uint16_t bma423_step_counter_output(uint32_t *step_count, struct bma4_dev *dev) +{ + uint8_t data[BMA423_STEP_CNTR_DATA_SIZE] = {0}; + uint16_t rslt = BMA4_OK; + uint32_t step_count_0 = 0; + uint32_t step_count_1 = 0; + uint32_t step_count_2 = 0; + uint32_t step_count_3 = 0; + + if (dev != NULL) { + if (dev->chip_id == BMA423_CHIP_ID) { + /* Reads the step counter output data from the + gpio register */ + rslt = bma4_read_regs(BMA4_STEP_CNT_OUT_0_ADDR, data, + BMA423_STEP_CNTR_DATA_SIZE, dev); + + if (rslt == BMA4_OK) { + step_count_0 = (uint32_t)data[0]; + step_count_1 = (uint32_t)data[1] << 8; + step_count_2 = (uint32_t)data[2] << 16; + step_count_3 = (uint32_t)data[3] << 24; + *step_count = step_count_0 | step_count_1 | step_count_2 | step_count_3; + } + } else { + rslt = BMA4_E_INVALID_SENSOR; + } + } else { + rslt = BMA4_E_NULL_PTR; + } + + return rslt; +} + +/*! + * @brief This API gets the output for activity feature. + */ +uint16_t bma423_activity_output(uint8_t *activity, struct bma4_dev *dev) +{ + uint8_t data = 0; + uint16_t rslt = BMA4_OK; + + if (dev != NULL) { + if (dev->chip_id == BMA423_CHIP_ID) { + /* Reads the activity output from the gpio register */ + rslt = bma4_read_regs(BMA4_ACTIVITY_OUT_ADDR, &data, 1, dev); + if (rslt == BMA4_OK) + *activity = data; + } else { + rslt = BMA4_E_INVALID_SENSOR; + } + } else { + rslt = BMA4_E_NULL_PTR; + } + + return rslt; +} + +/*! + * @brief This API select the platform configuration wrist(Default) or phone. + */ +uint16_t bma423_select_platform(uint8_t platform, struct bma4_dev *dev) +{ + uint16_t rslt = BMA4_OK; + struct bma423_stepcounter_settings sc_settings = {0}; + + if (dev != NULL) { + if (dev->chip_id == BMA423_CHIP_ID) { + switch (platform) { + case BMA423_PHONE_CONFIG: + sc_settings.param1 = BMA423_PHONE_SC_PARAM_1; + sc_settings.param2 = BMA423_PHONE_SC_PARAM_2; + sc_settings.param3 = BMA423_PHONE_SC_PARAM_3; + sc_settings.param4 = BMA423_PHONE_SC_PARAM_4; + sc_settings.param5 = BMA423_PHONE_SC_PARAM_5; + sc_settings.param6 = BMA423_PHONE_SC_PARAM_6; + sc_settings.param7 = BMA423_PHONE_SC_PARAM_7; + sc_settings.param8 = BMA423_PHONE_SC_PARAM_8; + sc_settings.param9 = BMA423_PHONE_SC_PARAM_9; + sc_settings.param10 = BMA423_PHONE_SC_PARAM_10; + sc_settings.param11 = BMA423_PHONE_SC_PARAM_11; + sc_settings.param12 = BMA423_PHONE_SC_PARAM_12; + sc_settings.param13 = BMA423_PHONE_SC_PARAM_13; + sc_settings.param14 = BMA423_PHONE_SC_PARAM_14; + sc_settings.param15 = BMA423_PHONE_SC_PARAM_15; + sc_settings.param16 = BMA423_PHONE_SC_PARAM_16; + sc_settings.param17 = BMA423_PHONE_SC_PARAM_17; + sc_settings.param18 = BMA423_PHONE_SC_PARAM_18; + sc_settings.param19 = BMA423_PHONE_SC_PARAM_19; + sc_settings.param20 = BMA423_PHONE_SC_PARAM_20; + sc_settings.param21 = BMA423_PHONE_SC_PARAM_21; + sc_settings.param22 = BMA423_PHONE_SC_PARAM_22; + sc_settings.param23 = BMA423_PHONE_SC_PARAM_23; + sc_settings.param24 = BMA423_PHONE_SC_PARAM_24; + sc_settings.param25 = BMA423_PHONE_SC_PARAM_25; + break; + + case BMA423_WRIST_CONFIG: + sc_settings.param1 = BMA423_WRIST_SC_PARAM_1; + sc_settings.param2 = BMA423_WRIST_SC_PARAM_2; + sc_settings.param3 = BMA423_WRIST_SC_PARAM_3; + sc_settings.param4 = BMA423_WRIST_SC_PARAM_4; + sc_settings.param5 = BMA423_WRIST_SC_PARAM_5; + sc_settings.param6 = BMA423_WRIST_SC_PARAM_6; + sc_settings.param7 = BMA423_WRIST_SC_PARAM_7; + sc_settings.param8 = BMA423_WRIST_SC_PARAM_8; + sc_settings.param9 = BMA423_WRIST_SC_PARAM_9; + sc_settings.param10 = BMA423_WRIST_SC_PARAM_10; + sc_settings.param11 = BMA423_WRIST_SC_PARAM_11; + sc_settings.param12 = BMA423_WRIST_SC_PARAM_12; + sc_settings.param13 = BMA423_WRIST_SC_PARAM_13; + sc_settings.param14 = BMA423_WRIST_SC_PARAM_14; + sc_settings.param15 = BMA423_WRIST_SC_PARAM_15; + sc_settings.param16 = BMA423_WRIST_SC_PARAM_16; + sc_settings.param17 = BMA423_WRIST_SC_PARAM_17; + sc_settings.param18 = BMA423_WRIST_SC_PARAM_18; + sc_settings.param19 = BMA423_WRIST_SC_PARAM_19; + sc_settings.param20 = BMA423_WRIST_SC_PARAM_20; + sc_settings.param21 = BMA423_WRIST_SC_PARAM_21; + sc_settings.param22 = BMA423_WRIST_SC_PARAM_22; + sc_settings.param23 = BMA423_WRIST_SC_PARAM_23; + sc_settings.param24 = BMA423_WRIST_SC_PARAM_24; + sc_settings.param25 = BMA423_WRIST_SC_PARAM_25; + break; + + default: + rslt = BMA4_E_OUT_OF_RANGE; + break; + } + } else { + rslt = BMA4_E_INVALID_SENSOR; + } + } else { + rslt = BMA4_E_NULL_PTR; + } + + if (rslt == BMA4_OK) { + /* Set the step counter parameter */ + rslt = bma423_stepcounter_set_parameter(&sc_settings, dev); + } + + return rslt; +} + +/*! + * @brief This API gets the parameter1 to parameter7 settings of the + * step counter feature. + */ +uint16_t bma423_stepcounter_get_parameter(struct bma423_stepcounter_settings *setting, struct bma4_dev *dev) +{ + uint8_t feature_config[BMA423_FEATURE_SIZE] = {0}; + uint16_t *data_p = (uint16_t *)feature_config; + uint16_t rslt = BMA4_OK; + + if (dev != NULL) { + if (dev->chip_id == BMA423_CHIP_ID) { + rslt = bma4_read_regs(BMA4_FEATURE_CONFIG_ADDR, feature_config, BMA423_FEATURE_SIZE, dev); + + if (rslt == BMA4_OK) { + /* To convert 8bit to 16 bit address */ + data_p = data_p + BMA423_STEP_CNTR_PARAM_OFFSET/2; + extract_stepcounter_parameter(setting, data_p); + } + } else { + rslt = BMA4_E_INVALID_SENSOR; + } + } else { + rslt = BMA4_E_NULL_PTR; + } + + return rslt; +} + +/*! + * @brief This API sets the parameter1 to parameter7 settings of the + * step counter feature in the sensor. + */ +uint16_t bma423_stepcounter_set_parameter(const struct bma423_stepcounter_settings *setting, struct bma4_dev *dev) +{ + uint8_t feature_config[BMA423_FEATURE_SIZE] = {0}; + uint8_t index = BMA423_STEP_CNTR_PARAM_OFFSET; + uint16_t rslt = BMA4_OK; + + if (dev != NULL) { + if (dev->chip_id == BMA423_CHIP_ID) { + rslt = bma4_read_regs(BMA4_FEATURE_CONFIG_ADDR, feature_config, BMA423_FEATURE_SIZE, dev); + if (rslt == BMA4_OK) { + update_stepcounter_parameter(setting, index, feature_config); + /* Writes stepcounter parameter settings + in the sensor */ + rslt = bma4_write_regs(BMA4_FEATURE_CONFIG_ADDR, feature_config, + BMA423_FEATURE_SIZE, dev); + } + } else { + rslt = BMA4_E_INVALID_SENSOR; + } + } else { + rslt = BMA4_E_NULL_PTR; + } + + return rslt; +} + +/*! + * @brief This API sets the sensitivity of wake up feature in the sensor + */ +uint16_t bma423_wakeup_set_sensitivity(uint8_t sensitivity, struct bma4_dev *dev) +{ + uint8_t feature_config[BMA423_FEATURE_SIZE] = {0}; + uint8_t index = BMA423_WAKEUP_OFFSET; + uint16_t rslt = BMA4_OK; + + if (dev != NULL) { + if (dev->chip_id == BMA423_CHIP_ID) { + rslt = bma4_read_regs(BMA4_FEATURE_CONFIG_ADDR, feature_config, BMA423_FEATURE_SIZE, dev); + if (rslt == BMA4_OK) { + feature_config[index] = BMA4_SET_BITSLICE(feature_config[index], + BMA423_WAKEUP_SENS, sensitivity); + /* Writes sensitivity settings in the sensor */ + rslt |= bma4_write_regs(BMA4_FEATURE_CONFIG_ADDR, feature_config, + BMA423_FEATURE_SIZE, dev); + } + } else { + rslt = BMA4_E_INVALID_SENSOR; + } + } else { + rslt = BMA4_E_NULL_PTR; + } + + return rslt; +} + +/*! + * @brief This API gets the sensitivity of wake up feature in the sensor + */ +uint16_t bma423_wakeup_get_sensitivity(uint8_t *sensitivity, struct bma4_dev *dev) +{ + uint8_t feature_config[BMA423_FEATURE_SIZE] = {0}; + uint8_t index = BMA423_WAKEUP_OFFSET; + uint16_t rslt = BMA4_OK; + + if (dev != NULL) { + if (dev->chip_id == BMA423_CHIP_ID) { + rslt = bma4_read_regs(BMA4_FEATURE_CONFIG_ADDR, feature_config, BMA423_FEATURE_SIZE, dev); + if (rslt == BMA4_OK) { + /* Extracts sensitivity data */ + *sensitivity = BMA4_GET_BITSLICE(feature_config[index], BMA423_WAKEUP_SENS); + } + } else { + rslt = BMA4_E_INVALID_SENSOR; + } + } else { + rslt = BMA4_E_NULL_PTR; + } + + return rslt; +} + +/*! + * @brief This API is used to select single/double tap + * feature in the sensor + */ +uint16_t bma423_tap_selection(const uint8_t tap_select, struct bma4_dev *dev) +{ + uint16_t rslt = BMA4_OK; + uint8_t feature_config[BMA423_FEATURE_SIZE] = {0,}; + uint8_t index = BMA423_WAKEUP_OFFSET; + + if (dev != NULL) { + if (dev->chip_id == BMA423_CHIP_ID) { + rslt = bma4_read_regs(BMA4_FEATURE_CONFIG_ADDR, feature_config, BMA423_FEATURE_SIZE, dev); + if (rslt == BMA4_OK) { + feature_config[index] = BMA4_SET_BITSLICE(feature_config[index], + BMA423_TAP_SEL, tap_select); + rslt = bma4_write_regs(BMA4_FEATURE_CONFIG_ADDR, feature_config, + BMA423_FEATURE_SIZE, dev); + } + } else { + rslt = BMA4_E_INVALID_SENSOR; + } + } else { + rslt = BMA4_E_NULL_PTR; + } + + return rslt; +} +/*! + * @brief This API update the length for read and write. + */ +static void update_len(uint8_t *len, uint8_t feature, uint8_t enable) +{ + uint8_t length = BMA423_FEATURE_SIZE; + + if ((feature == BMA423_ANY_MOTION) || (feature == BMA423_NO_MOTION)) { + /* Change the feature length to 2 for reading and writing of 2 bytes for + any/no-motion enable */ + length = BMA423_ANYMOTION_EN_LEN; + + /* Read and write 4 byte to disable the any/no motion completely along with + all axis */ + if (enable == BMA4_DISABLE) { + /*Change the feature length to 4 for reading and writing + of 4 bytes for any/no-motion enable */ + length = length + 2; + } + } + + *len = length; +} + +/*! + * @brief This API enables the features of the sensor. + */ +static uint16_t feature_enable(uint8_t feature, uint8_t len, uint8_t *feature_config, struct bma4_dev *dev) +{ + uint8_t index = 0; + uint16_t rslt; + + /* Enable step counter */ + if ((feature & BMA423_STEP_CNTR) > 0) { + /* Step counter enable bit pos. is 1 byte ahead of the + base address */ + index = BMA423_STEP_CNTR_OFFSET + 1; + feature_config[index] = feature_config[index] | BMA423_STEP_CNTR_EN_MSK; + } + + /* Enable activity */ + if ((feature & BMA423_ACTIVITY) > 0) { + /* Activity enable bit pos. is 1 byte ahead of the + base address */ + index = BMA423_STEP_CNTR_OFFSET + 1; + feature_config[index] = feature_config[index] | BMA423_ACTIVITY_EN_MSK; + } + /* Enable tilt */ + if ((feature & BMA423_TILT) > 0) { + /* Tilt enable bit pos. is the base address(0x3A) of tilt */ + index = BMA423_TILT_OFFSET; + feature_config[index] = feature_config[index] | BMA423_TILT_EN_MSK; + } + + /* Enable wakeup */ + if ((feature & BMA423_WAKEUP) > 0) { + /* Wakeup enable bit pos. is the base address(0x38) of wakeup */ + index = BMA423_WAKEUP_OFFSET; + feature_config[index] = feature_config[index] | BMA423_WAKEUP_EN_MSK; + } + + /* Enable anymotion/nomotion */ + if ((feature & BMA423_ANY_MOTION) > 0 || (feature & BMA423_NO_MOTION) > 0) { + /* Any/Nomotion enable bit pos. is 1 bytes ahead of the + any/nomotion base address(0x00) */ + index = 1; + + if ((feature & BMA423_ANY_MOTION) > 0) { + /* Enable anymotion */ + feature_config[index] = feature_config[index] & (~BMA423_ANY_NO_MOTION_SEL_MSK); + } else { + /* Enable nomotion */ + feature_config[index] = feature_config[index] | BMA423_ANY_NO_MOTION_SEL_MSK; + } + } + + /* Write the feature enable settings in the sensor */ + rslt = bma4_write_regs(BMA4_FEATURE_CONFIG_ADDR, feature_config, len, dev); + + return rslt; +} + +/*! + * @brief This API disables the features of the sensor. + */ +static uint16_t feature_disable(uint8_t feature, uint8_t len, uint8_t *feature_config, struct bma4_dev *dev) +{ + uint8_t index = 0; + uint16_t rslt; + + /* Disable step counter */ + if ((feature & BMA423_STEP_CNTR) > 0) { + /* Step counter enable bit pos. is 1 byte ahead of the + base address */ + index = BMA423_STEP_CNTR_OFFSET + 1; + feature_config[index] = feature_config[index] & (~BMA423_STEP_CNTR_EN_MSK); + } + + /* Disable activity */ + if ((feature & BMA423_ACTIVITY) > 0) { + /* Activity enable bit pos. is 1 byte ahead of the + base address */ + index = BMA423_STEP_CNTR_OFFSET + 1; + feature_config[index] = feature_config[index] & (~BMA423_ACTIVITY_EN_MSK); + } + /* Disable tilt */ + if ((feature & BMA423_TILT) > 0) { + /* Tilt enable bit pos. is the base address(0x3A) of tilt */ + index = BMA423_TILT_OFFSET; + feature_config[index] = feature_config[index] & (~BMA423_TILT_EN_MSK); + } + + /* Disable wakeup */ + if ((feature & BMA423_WAKEUP) > 0) { + /* Tilt enable bit pos. is the base address(0x38) of wakeup */ + index = BMA423_WAKEUP_OFFSET; + feature_config[index] = feature_config[index] & (~BMA423_WAKEUP_EN_MSK); + } + + /* Disable anymotion/nomotion */ + if ((feature & BMA423_ANY_MOTION) > 0 || (feature & BMA423_NO_MOTION) > 0) { + /* Any/Nomotion enable bit pos. is 1 bytes ahead of the + any/nomotion base address(0x00) */ + index = 1; + + if ((feature & BMA423_ANY_MOTION) > 0) { + /* Disable anymotion */ + feature_config[index] = feature_config[index] | BMA423_ANY_NO_MOTION_SEL_MSK; + } else { + /* Disable nomotion */ + feature_config[index] = feature_config[index] & (~BMA423_ANY_NO_MOTION_SEL_MSK); + } + /* Any/Nomotion axis enable bit pos. is 3 byte ahead of the + any/nomotion base address(0x00) */ + index = 3; + feature_config[index] = feature_config[index] & (~BMA423_ANY_NO_MOTION_AXIS_EN_MSK); + } + /* Write the configured settings in the sensor */ + rslt = bma4_write_regs(BMA4_FEATURE_CONFIG_ADDR, feature_config, len, dev); + + return rslt; +} + +/*! + * @brief This API update the settings of step counter. + */ +static void update_stepcounter_parameter(const struct bma423_stepcounter_settings *setting, + uint8_t index, uint8_t *feature_config) +{ + feature_config[index++] = BMA4_GET_LSB(setting->param1); + feature_config[index++] = BMA4_GET_MSB(setting->param1); + feature_config[index++] = BMA4_GET_LSB(setting->param2); + feature_config[index++] = BMA4_GET_MSB(setting->param2); + feature_config[index++] = BMA4_GET_LSB(setting->param3); + feature_config[index++] = BMA4_GET_MSB(setting->param3); + feature_config[index++] = BMA4_GET_LSB(setting->param4); + feature_config[index++] = BMA4_GET_MSB(setting->param4); + feature_config[index++] = BMA4_GET_LSB(setting->param5); + feature_config[index++] = BMA4_GET_MSB(setting->param5); + feature_config[index++] = BMA4_GET_LSB(setting->param6); + feature_config[index++] = BMA4_GET_MSB(setting->param6); + feature_config[index++] = BMA4_GET_LSB(setting->param7); + feature_config[index++] = BMA4_GET_MSB(setting->param7); + feature_config[index++] = BMA4_GET_LSB(setting->param8); + feature_config[index++] = BMA4_GET_MSB(setting->param8); + feature_config[index++] = BMA4_GET_LSB(setting->param9); + feature_config[index++] = BMA4_GET_MSB(setting->param9); + feature_config[index++] = BMA4_GET_LSB(setting->param10); + feature_config[index++] = BMA4_GET_MSB(setting->param10); + feature_config[index++] = BMA4_GET_LSB(setting->param11); + feature_config[index++] = BMA4_GET_MSB(setting->param11); + feature_config[index++] = BMA4_GET_LSB(setting->param12); + feature_config[index++] = BMA4_GET_MSB(setting->param12); + feature_config[index++] = BMA4_GET_LSB(setting->param13); + feature_config[index++] = BMA4_GET_MSB(setting->param13); + feature_config[index++] = BMA4_GET_LSB(setting->param14); + feature_config[index++] = BMA4_GET_MSB(setting->param14); + feature_config[index++] = BMA4_GET_LSB(setting->param15); + feature_config[index++] = BMA4_GET_MSB(setting->param15); + feature_config[index++] = BMA4_GET_LSB(setting->param16); + feature_config[index++] = BMA4_GET_MSB(setting->param16); + feature_config[index++] = BMA4_GET_LSB(setting->param17); + feature_config[index++] = BMA4_GET_MSB(setting->param17); + feature_config[index++] = BMA4_GET_LSB(setting->param18); + feature_config[index++] = BMA4_GET_MSB(setting->param18); + feature_config[index++] = BMA4_GET_LSB(setting->param19); + feature_config[index++] = BMA4_GET_MSB(setting->param19); + feature_config[index++] = BMA4_GET_LSB(setting->param20); + feature_config[index++] = BMA4_GET_MSB(setting->param20); + feature_config[index++] = BMA4_GET_LSB(setting->param21); + feature_config[index++] = BMA4_GET_MSB(setting->param21); + feature_config[index++] = BMA4_GET_LSB(setting->param22); + feature_config[index++] = BMA4_GET_MSB(setting->param22); + feature_config[index++] = BMA4_GET_LSB(setting->param23); + feature_config[index++] = BMA4_GET_MSB(setting->param23); + feature_config[index++] = BMA4_GET_LSB(setting->param24); + feature_config[index++] = BMA4_GET_MSB(setting->param24); + feature_config[index++] = BMA4_GET_LSB(setting->param25); + feature_config[index] = BMA4_GET_MSB(setting->param25); +} + +/*! + * @brief This API copy the settings of step counter into the + * structure of bma423_stepcounter_settings, which is read from sensor. + */ +static void extract_stepcounter_parameter(struct bma423_stepcounter_settings *setting, const uint16_t *data_p) +{ + setting->param1 = *(data_p++); + setting->param2 = *(data_p++); + setting->param3 = *(data_p++); + setting->param4 = *(data_p++); + setting->param5 = *(data_p++); + setting->param6 = *(data_p++); + setting->param7 = *(data_p++); + setting->param8 = *(data_p++); + setting->param9 = *(data_p++); + setting->param10 = *(data_p++); + setting->param11 = *(data_p++); + setting->param12 = *(data_p++); + setting->param13 = *(data_p++); + setting->param14 = *(data_p++); + setting->param15 = *(data_p++); + setting->param16 = *(data_p++); + setting->param17 = *(data_p++); + setting->param18 = *(data_p++); + setting->param19 = *(data_p++); + setting->param20 = *(data_p++); + setting->param21 = *(data_p++); + setting->param22 = *(data_p++); + setting->param23 = *(data_p++); + setting->param24 = *(data_p++); + setting->param25 = *data_p; +} diff --git a/lib/libesp32/TTGO_TWatch_Library/src/bma423.h b/lib/libesp32_div/TTGO_TWatch_Library/src/bma423.h old mode 100755 new mode 100644 similarity index 97% rename from lib/libesp32/TTGO_TWatch_Library/src/bma423.h rename to lib/libesp32_div/TTGO_TWatch_Library/src/bma423.h index 2137f36c2..f9f1f0824 --- a/lib/libesp32/TTGO_TWatch_Library/src/bma423.h +++ b/lib/libesp32_div/TTGO_TWatch_Library/src/bma423.h @@ -1,804 +1,804 @@ -/* -* -**************************************************************************** -* Copyright (C) 2017 - 2018 Bosch Sensortec GmbH -* -* File : bma423.h -* -* Date: 12 Oct 2017 -* -* Revision : 1.1.4 $ -* -* Usage: Sensor Driver for BMA423 sensor -* -**************************************************************************** -* -* Disclaimer -* -* Common: -* Bosch Sensortec products are developed for the consumer goods industry. -* They may only be used within the parameters of the respective valid -* product data sheet. Bosch Sensortec products are provided with the -* express understanding that there is no warranty of fitness for a -* particular purpose.They are not fit for use in life-sustaining, -* safety or security sensitive systems or any system or device -* that may lead to bodily harm or property damage if the system -* or device malfunctions. In addition,Bosch Sensortec products are -* not fit for use in products which interact with motor vehicle systems. -* The resale and or use of products are at the purchasers own risk and -* his own responsibility. The examination of fitness for the intended use -* is the sole responsibility of the Purchaser. -* -* The purchaser shall indemnify Bosch Sensortec from all third party -* claims, including any claims for incidental, or consequential damages, -* arising from any product use not covered by the parameters of -* the respective valid product data sheet or not approved by -* Bosch Sensortec and reimburse Bosch Sensortec for all costs in -* connection with such claims. -* -* The purchaser must monitor the market for the purchased products, -* particularly with regard to product safety and inform Bosch Sensortec -* without delay of all security relevant incidents. -* -* Engineering Samples are marked with an asterisk (*) or (e). -* Samples may vary from the valid technical specifications of the product -* series. They are therefore not intended or fit for resale to third -* parties or for use in end products. Their sole purpose is internal -* client testing. The testing of an engineering sample may in no way -* replace the testing of a product series. Bosch Sensortec assumes -* no liability for the use of engineering samples. -* By accepting the engineering samples, the Purchaser agrees to indemnify -* Bosch Sensortec from all claims arising from the use of engineering -* samples. -* -* Special: -* This software module (hereinafter called "Software") and any information -* on application-sheets (hereinafter called "Information") is provided -* free of charge for the sole purpose to support your application work. -* The Software and Information is subject to the following -* terms and conditions: -* -* The Software is specifically designed for the exclusive use for -* Bosch Sensortec products by personnel who have special experience -* and training. Do not use this Software if you do not have the -* proper experience or training. -* -* This Software package is provided `` as is `` and without any expressed -* or implied warranties,including without limitation, the implied warranties -* of merchantability and fitness for a particular purpose. -* -* Bosch Sensortec and their representatives and agents deny any liability -* for the functional impairment -* of this Software in terms of fitness, performance and safety. -* Bosch Sensortec and their representatives and agents shall not be liable -* for any direct or indirect damages or injury, except as -* otherwise stipulated in mandatory applicable law. -* -* The Information provided is believed to be accurate and reliable. -* Bosch Sensortec assumes no responsibility for the consequences of use -* of such Information nor for any infringement of patents or -* other rights of third parties which may result from its use. -* No license is granted by implication or otherwise under any patent or -* patent rights of Bosch. Specifications mentioned in the Information are -* subject to change without notice. -**************************************************************************/ -/*! \file bma423.h - \brief Sensor Driver for BMA423 sensor */ -#ifndef BMA423_H -#define BMA423_H - -#ifdef __cplusplus -extern "C" { -#endif -#include "bma4.h" - -/**\name Chip ID of BMA423 sensor */ -#define BMA423_CHIP_ID UINT8_C(0x13) - -/**\name Sensor feature size */ -#define BMA423_FEATURE_SIZE UINT8_C(64) -#define BMA423_ANYMOTION_EN_LEN UINT8_C(2) -#define BMA423_RD_WR_MIN_LEN UINT8_C(2) - -/**\name Feature offset address */ -#define BMA423_ANY_NO_MOTION_OFFSET UINT8_C(0x00) -#define BMA423_STEP_CNTR_OFFSET UINT8_C(0x36) -#define BMA423_STEP_CNTR_PARAM_OFFSET UINT8_C(0x04) -#define BMA423_WAKEUP_OFFSET UINT8_C(0x38) -#define BMA423_TILT_OFFSET UINT8_C(0x3A) -#define BMA423_CONFIG_ID_OFFSET UINT8_C(0x3C) -#define BMA423_AXES_REMAP_OFFSET UINT8_C(0x3E) - - -/**************************************************************/ -/**\name Remap Axes */ -/**************************************************************/ -#define BMA423_X_AXIS_MASK UINT8_C(0x03) -#define BMA423_X_AXIS_SIGN_MASK UINT8_C(0x04) -#define BMA423_Y_AXIS_MASK UINT8_C(0x18) -#define BMA423_Y_AXIS_SIGN_MASK UINT8_C(0x20) -#define BMA423_Z_AXIS_MASK UINT8_C(0xC0) -#define BMA423_Z_AXIS_SIGN_MASK UINT8_C(0x01) - -/**************************************************************/ -/**\name Step Counter & Detector */ -/**************************************************************/ -/**\name Step counter enable macros */ -#define BMA423_STEP_CNTR_EN_POS UINT8_C(4) -#define BMA423_STEP_CNTR_EN_MSK UINT8_C(0x10) -#define BMA423_ACTIVITY_EN_MSK UINT8_C(0x20) - -/**\name Step counter watermark macros */ -#define BMA423_STEP_CNTR_WM_MSK UINT16_C(0x03FF) - -/**\name Step counter reset macros */ -#define BMA423_STEP_CNTR_RST_POS UINT8_C(2) -#define BMA423_STEP_CNTR_RST_MSK UINT8_C(0x04) - -/**\name Step detector enable macros */ -#define BMA423_STEP_DETECTOR_EN_POS UINT8_C(3) -#define BMA423_STEP_DETECTOR_EN_MSK UINT8_C(0x08) - -/**\name Tilt enable macros */ -#define BMA423_TILT_EN_MSK UINT8_C(0x01) - -/**\name Step count output length*/ -#define BMA423_STEP_CNTR_DATA_SIZE UINT16_C(4) - -/**\name Wakeup enable macros */ -#define BMA423_WAKEUP_EN_MSK UINT8_C(0x01) - -/**\name Wake up sensitivity macros */ -#define BMA423_WAKEUP_SENS_POS UINT8_C(1) -#define BMA423_WAKEUP_SENS_MSK UINT8_C(0x0E) - -/**\name Tap selection macro */ -#define BMA423_TAP_SEL_POS UINT8_C(4) -#define BMA423_TAP_SEL_MSK UINT8_C(0x10) - -/**************************************************************/ -/**\name Any Motion */ -/**************************************************************/ -/**\name Any motion threshold macros */ -#define BMA423_ANY_NO_MOTION_THRES_POS UINT8_C(0) -#define BMA423_ANY_NO_MOTION_THRES_MSK UINT16_C(0x07FF) - -/**\name Any motion selection macros */ -#define BMA423_ANY_NO_MOTION_SEL_POS UINT8_C(3) -#define BMA423_ANY_NO_MOTION_SEL_MSK UINT8_C(0x08) - -/**\name Any motion enable macros */ -#define BMA423_ANY_NO_MOTION_AXIS_EN_POS UINT8_C(5) -#define BMA423_ANY_NO_MOTION_AXIS_EN_MSK UINT8_C(0xE0) - -/**\name Any motion duration macros */ -#define BMA423_ANY_NO_MOTION_DUR_MSK UINT16_C(0x1FFF) - -/**************************************************************/ -/**\name User macros */ -/**************************************************************/ - -/**\name Anymotion/Nomotion axis enable macros */ -#define BMA423_X_AXIS_EN UINT8_C(0x01) -#define BMA423_Y_AXIS_EN UINT8_C(0x02) -#define BMA423_Z_AXIS_EN UINT8_C(0x04) -#define BMA423_ALL_AXIS_EN UINT8_C(0x07) -#define BMA423_ALL_AXIS_DIS UINT8_C(0x00) - -/**\name Feature enable macros for the sensor */ -#define BMA423_STEP_CNTR UINT8_C(0x01) -/**\name Below macros are mutually exclusive */ -#define BMA423_ANY_MOTION UINT8_C(0x02) -#define BMA423_NO_MOTION UINT8_C(0x04) -#define BMA423_ACTIVITY UINT8_C(0x08) -#define BMA423_TILT UINT8_C(0x10) -#define BMA423_WAKEUP UINT8_C(0x20) - -/**\name Interrupt status macros */ -#define BMA423_STEP_CNTR_INT UINT8_C(0x02) -#define BMA423_ACTIVITY_INT UINT8_C(0x04) -#define BMA423_TILT_INT UINT8_C(0x08) -#define BMA423_WAKEUP_INT UINT8_C(0x20) -#define BMA423_ANY_NO_MOTION_INT UINT8_C(0x40) -#define BMA423_ERROR_INT UINT8_C(0x80) - -/**\name Activity recognition macros */ -#define BMA423_USER_STATIONARY UINT8_C(0x00) -#define BMA423_USER_WALKING UINT8_C(0x01) -#define BMA423_USER_RUNNING UINT8_C(0x02) -#define BMA423_STATE_INVALID UINT8_C(0x03) - -/**\name Configuration selection macros */ -#define BMA423_PHONE_CONFIG UINT8_C(0x00) -#define BMA423_WRIST_CONFIG UINT8_C(0x01) - -/**\name Step counter parameter setting(1-25) for phone */ -#define BMA423_PHONE_SC_PARAM_1 UINT16_C(0x132) -#define BMA423_PHONE_SC_PARAM_2 UINT16_C(0x78E6) -#define BMA423_PHONE_SC_PARAM_3 UINT16_C(0x84) -#define BMA423_PHONE_SC_PARAM_4 UINT16_C(0x6C9C) -#define BMA423_PHONE_SC_PARAM_5 UINT8_C(0x07) -#define BMA423_PHONE_SC_PARAM_6 UINT16_C(0x7564) -#define BMA423_PHONE_SC_PARAM_7 UINT16_C(0x7EAA) -#define BMA423_PHONE_SC_PARAM_8 UINT16_C(0x55F) -#define BMA423_PHONE_SC_PARAM_9 UINT16_C(0xABE) -#define BMA423_PHONE_SC_PARAM_10 UINT16_C(0x55F) -#define BMA423_PHONE_SC_PARAM_11 UINT16_C(0xE896) -#define BMA423_PHONE_SC_PARAM_12 UINT16_C(0x41EF) -#define BMA423_PHONE_SC_PARAM_13 UINT8_C(0x01) -#define BMA423_PHONE_SC_PARAM_14 UINT8_C(0x0C) -#define BMA423_PHONE_SC_PARAM_15 UINT8_C(0x0C) -#define BMA423_PHONE_SC_PARAM_16 UINT8_C(0x4A) -#define BMA423_PHONE_SC_PARAM_17 UINT8_C(0xA0) -#define BMA423_PHONE_SC_PARAM_18 UINT8_C(0x00) -#define BMA423_PHONE_SC_PARAM_19 UINT8_C(0x0C) -#define BMA423_PHONE_SC_PARAM_20 UINT16_C(0x3CF0) -#define BMA423_PHONE_SC_PARAM_21 UINT16_C(0x100) -#define BMA423_PHONE_SC_PARAM_22 UINT8_C(0x00) -#define BMA423_PHONE_SC_PARAM_23 UINT8_C(0x00) -#define BMA423_PHONE_SC_PARAM_24 UINT8_C(0x00) -#define BMA423_PHONE_SC_PARAM_25 UINT8_C(0x00) - -/**\name Step counter parameter setting(1-25) for wrist (Default) */ -#define BMA423_WRIST_SC_PARAM_1 UINT16_C(0x12D) -#define BMA423_WRIST_SC_PARAM_2 UINT16_C(0x7BD4) -#define BMA423_WRIST_SC_PARAM_3 UINT16_C(0x13B) -#define BMA423_WRIST_SC_PARAM_4 UINT16_C(0x7ADB) -#define BMA423_WRIST_SC_PARAM_5 UINT8_C(0x04) -#define BMA423_WRIST_SC_PARAM_6 UINT16_C(0x7B3F) -#define BMA423_WRIST_SC_PARAM_7 UINT16_C(0x6CCD) -#define BMA423_WRIST_SC_PARAM_8 UINT16_C(0x4C3) -#define BMA423_WRIST_SC_PARAM_9 UINT16_C(0x985) -#define BMA423_WRIST_SC_PARAM_10 UINT16_C(0x4C3) -#define BMA423_WRIST_SC_PARAM_11 UINT16_C(0xE6EC) -#define BMA423_WRIST_SC_PARAM_12 UINT16_C(0x460C) -#define BMA423_WRIST_SC_PARAM_13 UINT8_C(0x01) -#define BMA423_WRIST_SC_PARAM_14 UINT8_C(0x27) -#define BMA423_WRIST_SC_PARAM_15 UINT8_C(0x19) -#define BMA423_WRIST_SC_PARAM_16 UINT8_C(0x96) -#define BMA423_WRIST_SC_PARAM_17 UINT8_C(0xA0) -#define BMA423_WRIST_SC_PARAM_18 UINT8_C(0x01) -#define BMA423_WRIST_SC_PARAM_19 UINT8_C(0x0C) -#define BMA423_WRIST_SC_PARAM_20 UINT16_C(0x3CF0) -#define BMA423_WRIST_SC_PARAM_21 UINT16_C(0x100) -#define BMA423_WRIST_SC_PARAM_22 UINT8_C(0x01) -#define BMA423_WRIST_SC_PARAM_23 UINT8_C(0x03) -#define BMA423_WRIST_SC_PARAM_24 UINT8_C(0x01) -#define BMA423_WRIST_SC_PARAM_25 UINT8_C(0x0E) - -/*! - * @brief Any motion configuration - */ -struct bma423_anymotion_config { - /*! Expressed in 50 Hz samples (20 ms) */ - uint16_t duration; - /*! Threshold value for Any-motion / No-motion detection in - 5.11g format */ - uint16_t threshold; - /*! Indicates if No-motion or Any-motion is selected */ - uint8_t nomotion_sel; -}; - -/*! - * @brief Axes remapping configuration - */ -struct bma423_axes_remap { - uint8_t x_axis; - uint8_t x_axis_sign; - uint8_t y_axis; - uint8_t y_axis_sign; - uint8_t z_axis; - uint8_t z_axis_sign; -}; - -/*! - * @brief Step counter param settings - */ -struct bma423_stepcounter_settings { - /*! Step Counter param 1 */ - uint16_t param1; - /*! Step Counter param 2 */ - uint16_t param2; - /*! Step Counter param 3 */ - uint16_t param3; - /*! Step Counter param 4 */ - uint16_t param4; - /*! Step Counter param 5 */ - uint16_t param5; - /*! Step Counter param 6 */ - uint16_t param6; - /*! Step Counter param 7 */ - uint16_t param7; - /*! Step Counter param 8 */ - uint16_t param8; - /*! Step Counter param 9 */ - uint16_t param9; - /*! Step Counter param 10 */ - uint16_t param10; - /*! Step Counter param 11 */ - uint16_t param11; - /*! Step Counter param 12 */ - uint16_t param12; - /*! Step Counter param 13 */ - uint16_t param13; - /*! Step Counter param 14 */ - uint16_t param14; - /*! Step Counter param 15 */ - uint16_t param15; - /*! Step Counter param 16 */ - uint16_t param16; - /*! Step Counter param 17 */ - uint16_t param17; - /*! Step Counter param 18 */ - uint16_t param18; - /*! Step Counter param 19 */ - uint16_t param19; - /*! Step Counter param 20 */ - uint16_t param20; - /*! Step Counter param 21 */ - uint16_t param21; - /*! Step Counter param 22 */ - uint16_t param22; - /*! Step Counter param 23 */ - uint16_t param23; - /*! Step Counter param 24 */ - uint16_t param24; - /*! Step Counter param 25 */ - uint16_t param25; -}; - -/*! - * @brief This API is the entry point. - * Call this API before using all other APIs. - * This API reads the chip-id of the sensor and sets the resolution. - * - * @param[in,out] dev : Structure instance of bma4_dev - * - * @return Result of API execution status - * @retval 0 -> Success - * @retval Any non zero value -> Fail - */ -uint16_t bma423_init(struct bma4_dev *dev); - -/*! - * @brief This API is used to upload the config file to enable - * the features of the sensor. - * - * @param[in] dev : Structure instance of bma4_dev. - * - * @return Result of API execution status - * @retval 0 -> Success - * @retval Any non zero value -> Fail - */ -uint16_t bma423_write_config_file(struct bma4_dev *dev); - -/*! - * @brief This API is used to get the configuration id of the sensor. - * - * @param[out] config_id : Pointer variable used to store - * the configuration id. - * @param[in] dev : Structure instance of bma4_dev. - * - * @return Result of API execution status - * @retval 0 -> Success - * @retval Any non zero value -> Fail - */ -uint16_t bma423_get_config_id(uint16_t *config_id, struct bma4_dev *dev); - - -/*! - * @brief This API sets/unsets the user provided interrupt to either - * interrupt pin1 or pin2 in the sensor. - * - * @param[in] int_line: Variable to select either interrupt pin1 or pin2. - * int_line | Macros - * ------------|------------------- - * 0 | BMA4_INTR1_MAP - * 1 | BMA4_INTR2_MAP - * @param[in] int_map : Variable to specify the interrupts. - * @param[in] enable : Variable to specify mapping or unmapping of - * interrupts. - * enable | Macros - * --------------------|------------------- - * 0x00 | BMA4_DISABLE - * 0x01 | BMA4_ENABLE - * @param[in] dev : Structure instance of bma4_dev. - * - * @note Below macros specify the interrupts. - * Feature Interrupts - * - BMA423_STEP_CNTR_INT - * - BMA423_ACTIVITY_INT - * - BMA423_TILT_INT - * - BMA423_WAKEUP_INT - * - BMA423_ANY_NO_MOTION_INT - * - BMA423_ERROR_INT - * - * Hardware Interrupts - * - BMA4_FIFO_FULL_INT - * - BMA4_FIFO_WM_INT - * - BMA4_DATA_RDY_INT - * - * @return Result of API execution status - * @retval 0 -> Success - * @retval Any non zero value -> Fail - */ -uint16_t bma423_map_interrupt(uint8_t int_line, uint16_t int_map, uint8_t enable, struct bma4_dev *dev); - -/*! - * @brief This API reads the bma423 interrupt status from the sensor. - * - * @param[out] int_status : Variable to store the interrupt status - * read from the sensor. - * @param[in] dev : Structure instance of bma4_dev. - * - * @note Below macros are used to check the interrupt status. - * Feature Interrupts - * - * - BMA423_STEP_CNTR_INT - * - BMA423_ACTIVITY_INT - * - BMA423_TILT_INT - * - BMA423_WAKEUP_INT - * - BMA423_ANY_NO_MOTION_INT - * - BMA423_ERROR_INT - * - * - * Hardware Interrupts - * - BMA4_FIFO_FULL_INT - * - BMA4_FIFO_WM_INT - * - BMA4_MAG_DATA_RDY_INT - * - BMA4_ACCEL_DATA_RDY_INT - * - * @return Result of API execution status - * @retval 0 -> Success - * @retval Any non zero value -> Fail - */ -uint16_t bma423_read_int_status(uint16_t *int_status, struct bma4_dev *dev); - -/*! - * @brief This API enables/disables the features of the sensor. - * - * @param[in] feature : Variable to specify the features - * which are to be set in bma423 sensor. - * @param[in] enable : Variable which specifies whether to enable or - * disable the features in the bma423 sensor - * enable | Macros - * --------------------|------------------- - * 0x00 | BMA4_DISABLE - * 0x01 | BMA4_ENABLE - * @param[in] dev : Structure instance of bma4_dev. - * - * @note User should use the below macros to enable or disable the - * features of bma423 sensor - * - BMA423_STEP_CNTR - * - BMA423_ANY_MOTION (or) BMA423_NO_MOTION - * - BMA423_ACTIVITY - * - BMA423_WAKEUP - * - BMA423_TILT - * - * @return Result of API execution status - * @retval 0 -> Success - * @retval Any non zero value -> Fail - */ -uint16_t bma423_feature_enable(uint8_t feature, uint8_t enable, struct bma4_dev *dev); - - -/*! - * @brief This API performs x, y and z axis remapping in the sensor. - * - * @param[in] remap_data : Pointer to store axes remapping data. - * @param[in] dev : Structure instance of bma4_dev - * - * @return Result of API execution status - * @retval 0 -> Success - * @retval Any non zero value -> Fail - */ -uint16_t bma423_set_remap_axes(const struct bma423_axes_remap *remap_data, struct bma4_dev *dev); - -/*! - * @brief This API reads the x, y and z axis remap data from the sensor. - * - * @param[out] remap_data : Pointer to store axis remap data which is read - * from the bma423 sensor. - * @param[in] dev : Structure instance of bma4_dev - * - * @return Result of API execution status - * @retval 0 -> Success - * @retval Any non zero value -> Fail - */ -uint16_t bma423_get_remap_axes(struct bma423_axes_remap *remap_data, struct bma4_dev *dev); - - -/*! - * @brief This API sets the watermark level for step counter - * interrupt in the sensor. - * - * @param[in] step_counter_wm : Variable which specifies watermark level - * count - * @note Valid values are from 1 to 1023 - * @note Value 0 is used for step detector interrupt - * @param[in] dev : Structure instance of bma4_dev - * - * @return Result of API execution status - * @retval 0 -> Success - * @retval Any non zero value -> Fail - */ -uint16_t bma423_step_counter_set_watermark(uint16_t step_counter_wm, struct bma4_dev *dev); - -/*! - * @brief This API gets the water mark level set for step counter interrupt - * in the sensor - * - * @param[out] step_counter_wm : Pointer variable which stores - * the water mark level read from the sensor. - * @note valid values are from 1 to 1023 - * @note value 0 is used for step detector interrupt - * @param[in] dev : Structure instance of bma4_dev - * - * @return Result of API execution status - * @retval 0 -> Success - * @retval Any non zero value -> Fail - */ -uint16_t bma423_step_counter_get_watermark(uint16_t *step_counter_wm, struct bma4_dev *dev); - -/*! - * @brief This API resets the counted steps of step counter. - * - * @param[in] dev : structure instance of bma4_dev - * - * @return Result of API execution status - * @retval 0 -> Success - * @retval Any non zero value -> Fail - */ -uint16_t bma423_reset_step_counter(struct bma4_dev *dev); - -/*! - * @brief This API gets the number of counted steps of the step counter - * feature from the sensor. - * - * @param[out] step_count : Pointer variable which stores counted steps - * read from the sensor. - * @param[in] dev : Structure instance of bma4_dev - * - * @return Result of API execution status - * @retval 0 -> Success - * @retval Any non zero value -> Fail - */ -uint16_t bma423_step_counter_output(uint32_t *step_count, struct bma4_dev *dev); - -/*! - * @brief This API gets the output for activity feature. - * - * @param[out] activity : Pointer variable which stores activity output - * read from the sensor. - * activity | State - * --------------|------------------------ - * 0x00 | BMA423_USER_STATIONARY - * 0x01 | BMA423_USER_WALKING - * 0x02 | BMA423_USER_RUNNING - * 0x03 | BMA423_STATE_INVALID - * - * @param[in] dev : Structure instance of bma4_dev - * @return Result of API execution status - * @retval 0 -> Success - * @retval Any non zero value -> Fail - */ -uint16_t bma423_activity_output(uint8_t *activity, struct bma4_dev *dev); - -/*! - * @brief This API select the platform configuration wrist(default) or phone. - * - * @param[in] platform : Variable to select wrist/phone - * - * platform | Macros - * -------------|------------------------ - * 0x00 | BMA423_PHONE_CONFIG - * 0x01 | BMA423_WRIST_CONFIG - * - * @param[in] dev : Structure instance of bma4_dev - * @return Result of API execution status - * @retval 0 -> Success - * @retval Any non zero value -> Fail - */ -uint16_t bma423_select_platform(uint8_t platform, struct bma4_dev *dev); - -/*! - * @brief This API gets the parameter1 to parameter7 settings of the - * step counter feature. - * - * @param[out] setting : Pointer to structure variable which stores the - * parameter1 to parameter7 read from the sensor. - * @param[in] dev : Structure instance of bma4_dev - * - * @return Result of API execution status - * @retval 0 -> Success - * @retval Any non zero value -> Fail - */ -uint16_t bma423_stepcounter_get_parameter(struct bma423_stepcounter_settings *setting, struct bma4_dev *dev); - -/*! - * @brief This API sets the parameter1 to parameter7 settings of the - * step counter feature in the sensor. - * - * @param[in] setting : Pointer to structure variable which stores the - * parameter1 to parameter7 settings read from the sensor. - * @param[in] dev : Structure instance of bma4_dev - * - * @return Result of API execution status - * @retval 0 -> Success - * @retval Any non zero value -> Fail - */ -uint16_t bma423_stepcounter_set_parameter(const struct bma423_stepcounter_settings *setting, struct bma4_dev *dev); - -/*! - * @brief This API enables or disables the step detector feature in the - * sensor. - * - * @param[in] enable : Variable used to enable or disable step detector - * enable | Macros - * --------------------|------------------- - * 0x00 | BMA4_DISABLE - * 0x01 | BMA4_ENABLE - * @param[in] dev : Structure instance of bma4_dev - * - * @return Result of API execution status - * @retval 0 -> Success - * @retval Any non zero value -> Fail - */ -uint16_t bma423_step_detector_enable(uint8_t enable, struct bma4_dev *dev); - -/*! - * @brief This API enables the any motion feature according to the axis - * set by the user in the sensor. - * - * @param[in] axis : Variable to specify the axis of the any motion feature - * to be enabled in the sensor. - * Value | Axis - * ---------|------------------------- - * 0x00 | BMA423_ALL_AXIS_DIS - * 0x01 | BMA423_X_AXIS_EN - * 0x02 | BMA423_Y_AXIS_EN - * 0x04 | BMA423_Z_AXIS_EN - * 0x07 | BMA423_ALL_AXIS_EN - * @param[in] dev : Structure instance of bma4_dev - * - * @return result of API execution status - * @retval 0 -> Success - * @retval Any non zero value -> Fail - */ -uint16_t bma423_anymotion_enable_axis(uint8_t axis, struct bma4_dev *dev); - -/*! @brief This API sets the configuration of Any motion feature in - * the sensor. - * - * @param[in] any_motion : Pointer to structure variable to specify - * the any motion feature settings. - * Structure members are provided in the table below - *@verbatim - * ------------------------------------------------------------------------- - * Structure parameters | Description - * --------------------------------|---------------------------------------- - * | Defines the number of - * | consecutive data points for - * | which the threshold condition - * duration | must be respected, for interrupt - * | assertion. It is expressed in - * | 50 Hz samples (20 ms). - * | Range is 0 to 163sec. - * | Default value is 5 = 100ms. - * --------------------------------|---------------------------------------- - * | Slope threshold value for - * | Any-motion / No-motion detection - * threshold | in 5.11g format. - * | Range is 0 to 1g. - * | Default value is 0xAA = 83mg. - * --------------------------------|---------------------------------------- - * | Indicates if No motion (1) or - * nomotion_sel | Any-motion (0) is selected; - * | default value is 0 Any-motion. - * ------------------------------------------------------------------------- - *@endverbatim - * @param[in] dev : Structure instance of bma4_dev - * - * @return Result of API execution status - * @retval 0 -> Success - * @retval Any non zero value -> Fail - */ -uint16_t bma423_set_any_motion_config(const struct bma423_anymotion_config *any_motion, struct bma4_dev *dev); - -/*! @brief This API gets the configuration of any motion feature from - * the sensor. - * - * @param[out] any_motion : Pointer to structure variable used to store - * the any motion feature settings read from the sensor. - * Structure members are provided in the table below - *@verbatim - * ------------------------------------------------------------------------- - * Structure parameters | Description - * --------------------------------|---------------------------------------- - * | Defines the number of - * | consecutive data points for - * | which the threshold condition - * duration | must be respected, for interrupt - * | assertion. It is expressed in - * | 50 Hz samples (20 ms). - * | Range is 0 to 163sec. - * | Default value is 5 = 100ms. - * --------------------------------|---------------------------------------- - * | Slope threshold value for - * | Any-motion / No-motion detection - * threshold | in 5.11g format. - * | Range is 0 to 1g. - * | Default value is 0xAA = 83mg. - * --------------------------------|---------------------------------------- - * | Indicates if No motion (1) or - * nomotion_sel | Any-motion (0) is selected; - * | default value is 0 Any-motion. - * ------------------------------------------------------------------------- - *@endverbatim - * @param[in] dev : Structure instance of bma4_dev - * - * @return Result of API execution status - * @retval 0 -> Success - * @retval Any non zero value -> Fail - */ -uint16_t bma423_get_any_motion_config(struct bma423_anymotion_config *any_motion, struct bma4_dev *dev); - -/*! - * @brief This API sets the sensitivity of wake up feature in the sensor - * - * @param[in] sensitivity : Variable used to specify the sensitivity of the - * Wake up feature. - * Value | Sensitivity - * --------|------------------------- - * 0x00 | MOST SENSITIVE - * 0x07 | LEAST SENSITIVE - * @param[in] dev : Structure instance of bma4_dev - * - * @return Result of API execution status - * @retval 0 -> Success - * @retval Any non zero value -> Fail - */ -uint16_t bma423_wakeup_set_sensitivity(uint8_t sensitivity, struct bma4_dev *dev); - -/*! - * @brief This API gets the sensitivity of wake up feature in the sensor - * - * @param[out] sensitivity : Pointer variable which stores the sensitivity - * value read from the sensor. - * Value | Sensitivity - * --------|------------------------- - * 0x00 | MOST SENSITIVE - * 0x07 | LEAST SENSITIVE - * @param[in] dev : Structure instance of bma4_dev - * - * @return Result of API execution status - * @retval 0 -> Success - * @retval Any non zero value -> Fail - */ -uint16_t bma423_wakeup_get_sensitivity(uint8_t *sensitivity, struct bma4_dev *dev); - -/*! - * @brief This API is used to select single/double tap - * feature in the sensor - * - * @param tap_select : Variable used to specify the single or - * double tap selection in the sensor - * tap_select | description - * ------------|------------------------ - * 0x00 | Double tap selected - * 0x01 | single tap selected - * - * @param dev : Structure instance of bma4_dev - * - * @return results of stream_transfer operation - * @retval 0 -> Success - * @retval Any positive value mentioned in ERROR CODES -> Fail - * - */ -uint16_t bma423_tap_selection(const uint8_t tap_select, struct bma4_dev *dev); - -#ifdef __cplusplus -} -#endif /*End of CPP guard */ - -#endif /*End of header guard macro */ +/* +* +**************************************************************************** +* Copyright (C) 2017 - 2018 Bosch Sensortec GmbH +* +* File : bma423.h +* +* Date: 12 Oct 2017 +* +* Revision : 1.1.4 $ +* +* Usage: Sensor Driver for BMA423 sensor +* +**************************************************************************** +* +* Disclaimer +* +* Common: +* Bosch Sensortec products are developed for the consumer goods industry. +* They may only be used within the parameters of the respective valid +* product data sheet. Bosch Sensortec products are provided with the +* express understanding that there is no warranty of fitness for a +* particular purpose.They are not fit for use in life-sustaining, +* safety or security sensitive systems or any system or device +* that may lead to bodily harm or property damage if the system +* or device malfunctions. In addition,Bosch Sensortec products are +* not fit for use in products which interact with motor vehicle systems. +* The resale and or use of products are at the purchasers own risk and +* his own responsibility. The examination of fitness for the intended use +* is the sole responsibility of the Purchaser. +* +* The purchaser shall indemnify Bosch Sensortec from all third party +* claims, including any claims for incidental, or consequential damages, +* arising from any product use not covered by the parameters of +* the respective valid product data sheet or not approved by +* Bosch Sensortec and reimburse Bosch Sensortec for all costs in +* connection with such claims. +* +* The purchaser must monitor the market for the purchased products, +* particularly with regard to product safety and inform Bosch Sensortec +* without delay of all security relevant incidents. +* +* Engineering Samples are marked with an asterisk (*) or (e). +* Samples may vary from the valid technical specifications of the product +* series. They are therefore not intended or fit for resale to third +* parties or for use in end products. Their sole purpose is internal +* client testing. The testing of an engineering sample may in no way +* replace the testing of a product series. Bosch Sensortec assumes +* no liability for the use of engineering samples. +* By accepting the engineering samples, the Purchaser agrees to indemnify +* Bosch Sensortec from all claims arising from the use of engineering +* samples. +* +* Special: +* This software module (hereinafter called "Software") and any information +* on application-sheets (hereinafter called "Information") is provided +* free of charge for the sole purpose to support your application work. +* The Software and Information is subject to the following +* terms and conditions: +* +* The Software is specifically designed for the exclusive use for +* Bosch Sensortec products by personnel who have special experience +* and training. Do not use this Software if you do not have the +* proper experience or training. +* +* This Software package is provided `` as is `` and without any expressed +* or implied warranties,including without limitation, the implied warranties +* of merchantability and fitness for a particular purpose. +* +* Bosch Sensortec and their representatives and agents deny any liability +* for the functional impairment +* of this Software in terms of fitness, performance and safety. +* Bosch Sensortec and their representatives and agents shall not be liable +* for any direct or indirect damages or injury, except as +* otherwise stipulated in mandatory applicable law. +* +* The Information provided is believed to be accurate and reliable. +* Bosch Sensortec assumes no responsibility for the consequences of use +* of such Information nor for any infringement of patents or +* other rights of third parties which may result from its use. +* No license is granted by implication or otherwise under any patent or +* patent rights of Bosch. Specifications mentioned in the Information are +* subject to change without notice. +**************************************************************************/ +/*! \file bma423.h + \brief Sensor Driver for BMA423 sensor */ +#ifndef BMA423_H +#define BMA423_H + +#ifdef __cplusplus +extern "C" { +#endif +#include "bma4.h" + +/**\name Chip ID of BMA423 sensor */ +#define BMA423_CHIP_ID UINT8_C(0x13) + +/**\name Sensor feature size */ +#define BMA423_FEATURE_SIZE UINT8_C(64) +#define BMA423_ANYMOTION_EN_LEN UINT8_C(2) +#define BMA423_RD_WR_MIN_LEN UINT8_C(2) + +/**\name Feature offset address */ +#define BMA423_ANY_NO_MOTION_OFFSET UINT8_C(0x00) +#define BMA423_STEP_CNTR_OFFSET UINT8_C(0x36) +#define BMA423_STEP_CNTR_PARAM_OFFSET UINT8_C(0x04) +#define BMA423_WAKEUP_OFFSET UINT8_C(0x38) +#define BMA423_TILT_OFFSET UINT8_C(0x3A) +#define BMA423_CONFIG_ID_OFFSET UINT8_C(0x3C) +#define BMA423_AXES_REMAP_OFFSET UINT8_C(0x3E) + + +/**************************************************************/ +/**\name Remap Axes */ +/**************************************************************/ +#define BMA423_X_AXIS_MASK UINT8_C(0x03) +#define BMA423_X_AXIS_SIGN_MASK UINT8_C(0x04) +#define BMA423_Y_AXIS_MASK UINT8_C(0x18) +#define BMA423_Y_AXIS_SIGN_MASK UINT8_C(0x20) +#define BMA423_Z_AXIS_MASK UINT8_C(0xC0) +#define BMA423_Z_AXIS_SIGN_MASK UINT8_C(0x01) + +/**************************************************************/ +/**\name Step Counter & Detector */ +/**************************************************************/ +/**\name Step counter enable macros */ +#define BMA423_STEP_CNTR_EN_POS UINT8_C(4) +#define BMA423_STEP_CNTR_EN_MSK UINT8_C(0x10) +#define BMA423_ACTIVITY_EN_MSK UINT8_C(0x20) + +/**\name Step counter watermark macros */ +#define BMA423_STEP_CNTR_WM_MSK UINT16_C(0x03FF) + +/**\name Step counter reset macros */ +#define BMA423_STEP_CNTR_RST_POS UINT8_C(2) +#define BMA423_STEP_CNTR_RST_MSK UINT8_C(0x04) + +/**\name Step detector enable macros */ +#define BMA423_STEP_DETECTOR_EN_POS UINT8_C(3) +#define BMA423_STEP_DETECTOR_EN_MSK UINT8_C(0x08) + +/**\name Tilt enable macros */ +#define BMA423_TILT_EN_MSK UINT8_C(0x01) + +/**\name Step count output length*/ +#define BMA423_STEP_CNTR_DATA_SIZE UINT16_C(4) + +/**\name Wakeup enable macros */ +#define BMA423_WAKEUP_EN_MSK UINT8_C(0x01) + +/**\name Wake up sensitivity macros */ +#define BMA423_WAKEUP_SENS_POS UINT8_C(1) +#define BMA423_WAKEUP_SENS_MSK UINT8_C(0x0E) + +/**\name Tap selection macro */ +#define BMA423_TAP_SEL_POS UINT8_C(4) +#define BMA423_TAP_SEL_MSK UINT8_C(0x10) + +/**************************************************************/ +/**\name Any Motion */ +/**************************************************************/ +/**\name Any motion threshold macros */ +#define BMA423_ANY_NO_MOTION_THRES_POS UINT8_C(0) +#define BMA423_ANY_NO_MOTION_THRES_MSK UINT16_C(0x07FF) + +/**\name Any motion selection macros */ +#define BMA423_ANY_NO_MOTION_SEL_POS UINT8_C(3) +#define BMA423_ANY_NO_MOTION_SEL_MSK UINT8_C(0x08) + +/**\name Any motion enable macros */ +#define BMA423_ANY_NO_MOTION_AXIS_EN_POS UINT8_C(5) +#define BMA423_ANY_NO_MOTION_AXIS_EN_MSK UINT8_C(0xE0) + +/**\name Any motion duration macros */ +#define BMA423_ANY_NO_MOTION_DUR_MSK UINT16_C(0x1FFF) + +/**************************************************************/ +/**\name User macros */ +/**************************************************************/ + +/**\name Anymotion/Nomotion axis enable macros */ +#define BMA423_X_AXIS_EN UINT8_C(0x01) +#define BMA423_Y_AXIS_EN UINT8_C(0x02) +#define BMA423_Z_AXIS_EN UINT8_C(0x04) +#define BMA423_ALL_AXIS_EN UINT8_C(0x07) +#define BMA423_ALL_AXIS_DIS UINT8_C(0x00) + +/**\name Feature enable macros for the sensor */ +#define BMA423_STEP_CNTR UINT8_C(0x01) +/**\name Below macros are mutually exclusive */ +#define BMA423_ANY_MOTION UINT8_C(0x02) +#define BMA423_NO_MOTION UINT8_C(0x04) +#define BMA423_ACTIVITY UINT8_C(0x08) +#define BMA423_TILT UINT8_C(0x10) +#define BMA423_WAKEUP UINT8_C(0x20) + +/**\name Interrupt status macros */ +#define BMA423_STEP_CNTR_INT UINT8_C(0x02) +#define BMA423_ACTIVITY_INT UINT8_C(0x04) +#define BMA423_TILT_INT UINT8_C(0x08) +#define BMA423_WAKEUP_INT UINT8_C(0x20) +#define BMA423_ANY_NO_MOTION_INT UINT8_C(0x40) +#define BMA423_ERROR_INT UINT8_C(0x80) + +/**\name Activity recognition macros */ +#define BMA423_USER_STATIONARY UINT8_C(0x00) +#define BMA423_USER_WALKING UINT8_C(0x01) +#define BMA423_USER_RUNNING UINT8_C(0x02) +#define BMA423_STATE_INVALID UINT8_C(0x03) + +/**\name Configuration selection macros */ +#define BMA423_PHONE_CONFIG UINT8_C(0x00) +#define BMA423_WRIST_CONFIG UINT8_C(0x01) + +/**\name Step counter parameter setting(1-25) for phone */ +#define BMA423_PHONE_SC_PARAM_1 UINT16_C(0x132) +#define BMA423_PHONE_SC_PARAM_2 UINT16_C(0x78E6) +#define BMA423_PHONE_SC_PARAM_3 UINT16_C(0x84) +#define BMA423_PHONE_SC_PARAM_4 UINT16_C(0x6C9C) +#define BMA423_PHONE_SC_PARAM_5 UINT8_C(0x07) +#define BMA423_PHONE_SC_PARAM_6 UINT16_C(0x7564) +#define BMA423_PHONE_SC_PARAM_7 UINT16_C(0x7EAA) +#define BMA423_PHONE_SC_PARAM_8 UINT16_C(0x55F) +#define BMA423_PHONE_SC_PARAM_9 UINT16_C(0xABE) +#define BMA423_PHONE_SC_PARAM_10 UINT16_C(0x55F) +#define BMA423_PHONE_SC_PARAM_11 UINT16_C(0xE896) +#define BMA423_PHONE_SC_PARAM_12 UINT16_C(0x41EF) +#define BMA423_PHONE_SC_PARAM_13 UINT8_C(0x01) +#define BMA423_PHONE_SC_PARAM_14 UINT8_C(0x0C) +#define BMA423_PHONE_SC_PARAM_15 UINT8_C(0x0C) +#define BMA423_PHONE_SC_PARAM_16 UINT8_C(0x4A) +#define BMA423_PHONE_SC_PARAM_17 UINT8_C(0xA0) +#define BMA423_PHONE_SC_PARAM_18 UINT8_C(0x00) +#define BMA423_PHONE_SC_PARAM_19 UINT8_C(0x0C) +#define BMA423_PHONE_SC_PARAM_20 UINT16_C(0x3CF0) +#define BMA423_PHONE_SC_PARAM_21 UINT16_C(0x100) +#define BMA423_PHONE_SC_PARAM_22 UINT8_C(0x00) +#define BMA423_PHONE_SC_PARAM_23 UINT8_C(0x00) +#define BMA423_PHONE_SC_PARAM_24 UINT8_C(0x00) +#define BMA423_PHONE_SC_PARAM_25 UINT8_C(0x00) + +/**\name Step counter parameter setting(1-25) for wrist (Default) */ +#define BMA423_WRIST_SC_PARAM_1 UINT16_C(0x12D) +#define BMA423_WRIST_SC_PARAM_2 UINT16_C(0x7BD4) +#define BMA423_WRIST_SC_PARAM_3 UINT16_C(0x13B) +#define BMA423_WRIST_SC_PARAM_4 UINT16_C(0x7ADB) +#define BMA423_WRIST_SC_PARAM_5 UINT8_C(0x04) +#define BMA423_WRIST_SC_PARAM_6 UINT16_C(0x7B3F) +#define BMA423_WRIST_SC_PARAM_7 UINT16_C(0x6CCD) +#define BMA423_WRIST_SC_PARAM_8 UINT16_C(0x4C3) +#define BMA423_WRIST_SC_PARAM_9 UINT16_C(0x985) +#define BMA423_WRIST_SC_PARAM_10 UINT16_C(0x4C3) +#define BMA423_WRIST_SC_PARAM_11 UINT16_C(0xE6EC) +#define BMA423_WRIST_SC_PARAM_12 UINT16_C(0x460C) +#define BMA423_WRIST_SC_PARAM_13 UINT8_C(0x01) +#define BMA423_WRIST_SC_PARAM_14 UINT8_C(0x27) +#define BMA423_WRIST_SC_PARAM_15 UINT8_C(0x19) +#define BMA423_WRIST_SC_PARAM_16 UINT8_C(0x96) +#define BMA423_WRIST_SC_PARAM_17 UINT8_C(0xA0) +#define BMA423_WRIST_SC_PARAM_18 UINT8_C(0x01) +#define BMA423_WRIST_SC_PARAM_19 UINT8_C(0x0C) +#define BMA423_WRIST_SC_PARAM_20 UINT16_C(0x3CF0) +#define BMA423_WRIST_SC_PARAM_21 UINT16_C(0x100) +#define BMA423_WRIST_SC_PARAM_22 UINT8_C(0x01) +#define BMA423_WRIST_SC_PARAM_23 UINT8_C(0x03) +#define BMA423_WRIST_SC_PARAM_24 UINT8_C(0x01) +#define BMA423_WRIST_SC_PARAM_25 UINT8_C(0x0E) + +/*! + * @brief Any motion configuration + */ +struct bma423_anymotion_config { + /*! Expressed in 50 Hz samples (20 ms) */ + uint16_t duration; + /*! Threshold value for Any-motion / No-motion detection in + 5.11g format */ + uint16_t threshold; + /*! Indicates if No-motion or Any-motion is selected */ + uint8_t nomotion_sel; +}; + +/*! + * @brief Axes remapping configuration + */ +struct bma423_axes_remap { + uint8_t x_axis; + uint8_t x_axis_sign; + uint8_t y_axis; + uint8_t y_axis_sign; + uint8_t z_axis; + uint8_t z_axis_sign; +}; + +/*! + * @brief Step counter param settings + */ +struct bma423_stepcounter_settings { + /*! Step Counter param 1 */ + uint16_t param1; + /*! Step Counter param 2 */ + uint16_t param2; + /*! Step Counter param 3 */ + uint16_t param3; + /*! Step Counter param 4 */ + uint16_t param4; + /*! Step Counter param 5 */ + uint16_t param5; + /*! Step Counter param 6 */ + uint16_t param6; + /*! Step Counter param 7 */ + uint16_t param7; + /*! Step Counter param 8 */ + uint16_t param8; + /*! Step Counter param 9 */ + uint16_t param9; + /*! Step Counter param 10 */ + uint16_t param10; + /*! Step Counter param 11 */ + uint16_t param11; + /*! Step Counter param 12 */ + uint16_t param12; + /*! Step Counter param 13 */ + uint16_t param13; + /*! Step Counter param 14 */ + uint16_t param14; + /*! Step Counter param 15 */ + uint16_t param15; + /*! Step Counter param 16 */ + uint16_t param16; + /*! Step Counter param 17 */ + uint16_t param17; + /*! Step Counter param 18 */ + uint16_t param18; + /*! Step Counter param 19 */ + uint16_t param19; + /*! Step Counter param 20 */ + uint16_t param20; + /*! Step Counter param 21 */ + uint16_t param21; + /*! Step Counter param 22 */ + uint16_t param22; + /*! Step Counter param 23 */ + uint16_t param23; + /*! Step Counter param 24 */ + uint16_t param24; + /*! Step Counter param 25 */ + uint16_t param25; +}; + +/*! + * @brief This API is the entry point. + * Call this API before using all other APIs. + * This API reads the chip-id of the sensor and sets the resolution. + * + * @param[in,out] dev : Structure instance of bma4_dev + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + */ +uint16_t bma423_init(struct bma4_dev *dev); + +/*! + * @brief This API is used to upload the config file to enable + * the features of the sensor. + * + * @param[in] dev : Structure instance of bma4_dev. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + */ +uint16_t bma423_write_config_file(struct bma4_dev *dev); + +/*! + * @brief This API is used to get the configuration id of the sensor. + * + * @param[out] config_id : Pointer variable used to store + * the configuration id. + * @param[in] dev : Structure instance of bma4_dev. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + */ +uint16_t bma423_get_config_id(uint16_t *config_id, struct bma4_dev *dev); + + +/*! + * @brief This API sets/unsets the user provided interrupt to either + * interrupt pin1 or pin2 in the sensor. + * + * @param[in] int_line: Variable to select either interrupt pin1 or pin2. + * int_line | Macros + * ------------|------------------- + * 0 | BMA4_INTR1_MAP + * 1 | BMA4_INTR2_MAP + * @param[in] int_map : Variable to specify the interrupts. + * @param[in] enable : Variable to specify mapping or unmapping of + * interrupts. + * enable | Macros + * --------------------|------------------- + * 0x00 | BMA4_DISABLE + * 0x01 | BMA4_ENABLE + * @param[in] dev : Structure instance of bma4_dev. + * + * @note Below macros specify the interrupts. + * Feature Interrupts + * - BMA423_STEP_CNTR_INT + * - BMA423_ACTIVITY_INT + * - BMA423_TILT_INT + * - BMA423_WAKEUP_INT + * - BMA423_ANY_NO_MOTION_INT + * - BMA423_ERROR_INT + * + * Hardware Interrupts + * - BMA4_FIFO_FULL_INT + * - BMA4_FIFO_WM_INT + * - BMA4_DATA_RDY_INT + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + */ +uint16_t bma423_map_interrupt(uint8_t int_line, uint16_t int_map, uint8_t enable, struct bma4_dev *dev); + +/*! + * @brief This API reads the bma423 interrupt status from the sensor. + * + * @param[out] int_status : Variable to store the interrupt status + * read from the sensor. + * @param[in] dev : Structure instance of bma4_dev. + * + * @note Below macros are used to check the interrupt status. + * Feature Interrupts + * + * - BMA423_STEP_CNTR_INT + * - BMA423_ACTIVITY_INT + * - BMA423_TILT_INT + * - BMA423_WAKEUP_INT + * - BMA423_ANY_NO_MOTION_INT + * - BMA423_ERROR_INT + * + * + * Hardware Interrupts + * - BMA4_FIFO_FULL_INT + * - BMA4_FIFO_WM_INT + * - BMA4_MAG_DATA_RDY_INT + * - BMA4_ACCEL_DATA_RDY_INT + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + */ +uint16_t bma423_read_int_status(uint16_t *int_status, struct bma4_dev *dev); + +/*! + * @brief This API enables/disables the features of the sensor. + * + * @param[in] feature : Variable to specify the features + * which are to be set in bma423 sensor. + * @param[in] enable : Variable which specifies whether to enable or + * disable the features in the bma423 sensor + * enable | Macros + * --------------------|------------------- + * 0x00 | BMA4_DISABLE + * 0x01 | BMA4_ENABLE + * @param[in] dev : Structure instance of bma4_dev. + * + * @note User should use the below macros to enable or disable the + * features of bma423 sensor + * - BMA423_STEP_CNTR + * - BMA423_ANY_MOTION (or) BMA423_NO_MOTION + * - BMA423_ACTIVITY + * - BMA423_WAKEUP + * - BMA423_TILT + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + */ +uint16_t bma423_feature_enable(uint8_t feature, uint8_t enable, struct bma4_dev *dev); + + +/*! + * @brief This API performs x, y and z axis remapping in the sensor. + * + * @param[in] remap_data : Pointer to store axes remapping data. + * @param[in] dev : Structure instance of bma4_dev + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + */ +uint16_t bma423_set_remap_axes(const struct bma423_axes_remap *remap_data, struct bma4_dev *dev); + +/*! + * @brief This API reads the x, y and z axis remap data from the sensor. + * + * @param[out] remap_data : Pointer to store axis remap data which is read + * from the bma423 sensor. + * @param[in] dev : Structure instance of bma4_dev + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + */ +uint16_t bma423_get_remap_axes(struct bma423_axes_remap *remap_data, struct bma4_dev *dev); + + +/*! + * @brief This API sets the watermark level for step counter + * interrupt in the sensor. + * + * @param[in] step_counter_wm : Variable which specifies watermark level + * count + * @note Valid values are from 1 to 1023 + * @note Value 0 is used for step detector interrupt + * @param[in] dev : Structure instance of bma4_dev + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + */ +uint16_t bma423_step_counter_set_watermark(uint16_t step_counter_wm, struct bma4_dev *dev); + +/*! + * @brief This API gets the water mark level set for step counter interrupt + * in the sensor + * + * @param[out] step_counter_wm : Pointer variable which stores + * the water mark level read from the sensor. + * @note valid values are from 1 to 1023 + * @note value 0 is used for step detector interrupt + * @param[in] dev : Structure instance of bma4_dev + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + */ +uint16_t bma423_step_counter_get_watermark(uint16_t *step_counter_wm, struct bma4_dev *dev); + +/*! + * @brief This API resets the counted steps of step counter. + * + * @param[in] dev : structure instance of bma4_dev + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + */ +uint16_t bma423_reset_step_counter(struct bma4_dev *dev); + +/*! + * @brief This API gets the number of counted steps of the step counter + * feature from the sensor. + * + * @param[out] step_count : Pointer variable which stores counted steps + * read from the sensor. + * @param[in] dev : Structure instance of bma4_dev + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + */ +uint16_t bma423_step_counter_output(uint32_t *step_count, struct bma4_dev *dev); + +/*! + * @brief This API gets the output for activity feature. + * + * @param[out] activity : Pointer variable which stores activity output + * read from the sensor. + * activity | State + * --------------|------------------------ + * 0x00 | BMA423_USER_STATIONARY + * 0x01 | BMA423_USER_WALKING + * 0x02 | BMA423_USER_RUNNING + * 0x03 | BMA423_STATE_INVALID + * + * @param[in] dev : Structure instance of bma4_dev + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + */ +uint16_t bma423_activity_output(uint8_t *activity, struct bma4_dev *dev); + +/*! + * @brief This API select the platform configuration wrist(default) or phone. + * + * @param[in] platform : Variable to select wrist/phone + * + * platform | Macros + * -------------|------------------------ + * 0x00 | BMA423_PHONE_CONFIG + * 0x01 | BMA423_WRIST_CONFIG + * + * @param[in] dev : Structure instance of bma4_dev + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + */ +uint16_t bma423_select_platform(uint8_t platform, struct bma4_dev *dev); + +/*! + * @brief This API gets the parameter1 to parameter7 settings of the + * step counter feature. + * + * @param[out] setting : Pointer to structure variable which stores the + * parameter1 to parameter7 read from the sensor. + * @param[in] dev : Structure instance of bma4_dev + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + */ +uint16_t bma423_stepcounter_get_parameter(struct bma423_stepcounter_settings *setting, struct bma4_dev *dev); + +/*! + * @brief This API sets the parameter1 to parameter7 settings of the + * step counter feature in the sensor. + * + * @param[in] setting : Pointer to structure variable which stores the + * parameter1 to parameter7 settings read from the sensor. + * @param[in] dev : Structure instance of bma4_dev + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + */ +uint16_t bma423_stepcounter_set_parameter(const struct bma423_stepcounter_settings *setting, struct bma4_dev *dev); + +/*! + * @brief This API enables or disables the step detector feature in the + * sensor. + * + * @param[in] enable : Variable used to enable or disable step detector + * enable | Macros + * --------------------|------------------- + * 0x00 | BMA4_DISABLE + * 0x01 | BMA4_ENABLE + * @param[in] dev : Structure instance of bma4_dev + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + */ +uint16_t bma423_step_detector_enable(uint8_t enable, struct bma4_dev *dev); + +/*! + * @brief This API enables the any motion feature according to the axis + * set by the user in the sensor. + * + * @param[in] axis : Variable to specify the axis of the any motion feature + * to be enabled in the sensor. + * Value | Axis + * ---------|------------------------- + * 0x00 | BMA423_ALL_AXIS_DIS + * 0x01 | BMA423_X_AXIS_EN + * 0x02 | BMA423_Y_AXIS_EN + * 0x04 | BMA423_Z_AXIS_EN + * 0x07 | BMA423_ALL_AXIS_EN + * @param[in] dev : Structure instance of bma4_dev + * + * @return result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + */ +uint16_t bma423_anymotion_enable_axis(uint8_t axis, struct bma4_dev *dev); + +/*! @brief This API sets the configuration of Any motion feature in + * the sensor. + * + * @param[in] any_motion : Pointer to structure variable to specify + * the any motion feature settings. + * Structure members are provided in the table below + *@verbatim + * ------------------------------------------------------------------------- + * Structure parameters | Description + * --------------------------------|---------------------------------------- + * | Defines the number of + * | consecutive data points for + * | which the threshold condition + * duration | must be respected, for interrupt + * | assertion. It is expressed in + * | 50 Hz samples (20 ms). + * | Range is 0 to 163sec. + * | Default value is 5 = 100ms. + * --------------------------------|---------------------------------------- + * | Slope threshold value for + * | Any-motion / No-motion detection + * threshold | in 5.11g format. + * | Range is 0 to 1g. + * | Default value is 0xAA = 83mg. + * --------------------------------|---------------------------------------- + * | Indicates if No motion (1) or + * nomotion_sel | Any-motion (0) is selected; + * | default value is 0 Any-motion. + * ------------------------------------------------------------------------- + *@endverbatim + * @param[in] dev : Structure instance of bma4_dev + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + */ +uint16_t bma423_set_any_motion_config(const struct bma423_anymotion_config *any_motion, struct bma4_dev *dev); + +/*! @brief This API gets the configuration of any motion feature from + * the sensor. + * + * @param[out] any_motion : Pointer to structure variable used to store + * the any motion feature settings read from the sensor. + * Structure members are provided in the table below + *@verbatim + * ------------------------------------------------------------------------- + * Structure parameters | Description + * --------------------------------|---------------------------------------- + * | Defines the number of + * | consecutive data points for + * | which the threshold condition + * duration | must be respected, for interrupt + * | assertion. It is expressed in + * | 50 Hz samples (20 ms). + * | Range is 0 to 163sec. + * | Default value is 5 = 100ms. + * --------------------------------|---------------------------------------- + * | Slope threshold value for + * | Any-motion / No-motion detection + * threshold | in 5.11g format. + * | Range is 0 to 1g. + * | Default value is 0xAA = 83mg. + * --------------------------------|---------------------------------------- + * | Indicates if No motion (1) or + * nomotion_sel | Any-motion (0) is selected; + * | default value is 0 Any-motion. + * ------------------------------------------------------------------------- + *@endverbatim + * @param[in] dev : Structure instance of bma4_dev + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + */ +uint16_t bma423_get_any_motion_config(struct bma423_anymotion_config *any_motion, struct bma4_dev *dev); + +/*! + * @brief This API sets the sensitivity of wake up feature in the sensor + * + * @param[in] sensitivity : Variable used to specify the sensitivity of the + * Wake up feature. + * Value | Sensitivity + * --------|------------------------- + * 0x00 | MOST SENSITIVE + * 0x07 | LEAST SENSITIVE + * @param[in] dev : Structure instance of bma4_dev + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + */ +uint16_t bma423_wakeup_set_sensitivity(uint8_t sensitivity, struct bma4_dev *dev); + +/*! + * @brief This API gets the sensitivity of wake up feature in the sensor + * + * @param[out] sensitivity : Pointer variable which stores the sensitivity + * value read from the sensor. + * Value | Sensitivity + * --------|------------------------- + * 0x00 | MOST SENSITIVE + * 0x07 | LEAST SENSITIVE + * @param[in] dev : Structure instance of bma4_dev + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + */ +uint16_t bma423_wakeup_get_sensitivity(uint8_t *sensitivity, struct bma4_dev *dev); + +/*! + * @brief This API is used to select single/double tap + * feature in the sensor + * + * @param tap_select : Variable used to specify the single or + * double tap selection in the sensor + * tap_select | description + * ------------|------------------------ + * 0x00 | Double tap selected + * 0x01 | single tap selected + * + * @param dev : Structure instance of bma4_dev + * + * @return results of stream_transfer operation + * @retval 0 -> Success + * @retval Any positive value mentioned in ERROR CODES -> Fail + * + */ +uint16_t bma423_tap_selection(const uint8_t tap_select, struct bma4_dev *dev); + +#ifdef __cplusplus +} +#endif /*End of CPP guard */ + +#endif /*End of header guard macro */ diff --git a/lib/libesp32/TTGO_TWatch_Library/src/bma4_defs.h b/lib/libesp32_div/TTGO_TWatch_Library/src/bma4_defs.h old mode 100755 new mode 100644 similarity index 96% rename from lib/libesp32/TTGO_TWatch_Library/src/bma4_defs.h rename to lib/libesp32_div/TTGO_TWatch_Library/src/bma4_defs.h index 9ff81d659..83a595078 --- a/lib/libesp32/TTGO_TWatch_Library/src/bma4_defs.h +++ b/lib/libesp32_div/TTGO_TWatch_Library/src/bma4_defs.h @@ -1,960 +1,960 @@ -/* -* -**************************************************************************** -* Copyright (C) 2017 - 2018 Bosch Sensortec GmbH -* -* File : bma4_defs.h -* -* Date: 12 Oct 2017 -* -* Revision: 2.1.9 $ -* -* Usage: Sensor Driver for BMA4 family of sensors -* -**************************************************************************** -* -* Disclaimer -* -* Common: -* Bosch Sensortec products are developed for the consumer goods industry. -* They may only be used within the parameters of the respective valid -* product data sheet. Bosch Sensortec products are provided with the -* express understanding that there is no warranty of fitness for a -* particular purpose.They are not fit for use in life-sustaining, -* safety or security sensitive systems or any system or device -* that may lead to bodily harm or property damage if the system -* or device malfunctions. In addition,Bosch Sensortec products are -* not fit for use in products which interact with motor vehicle systems. -* The resale and or use of products are at the purchasers own risk and -* his own responsibility. The examination of fitness for the intended use -* is the sole responsibility of the Purchaser. -* -* The purchaser shall indemnify Bosch Sensortec from all third party -* claims, including any claims for incidental, or consequential damages, -* arising from any product use not covered by the parameters of -* the respective valid product data sheet or not approved by -* Bosch Sensortec and reimburse Bosch Sensortec for all costs in -* connection with such claims. -* -* The purchaser must monitor the market for the purchased products, -* particularly with regard to product safety and inform Bosch Sensortec -* without delay of all security relevant incidents. -* -* Engineering Samples are marked with an asterisk (*) or (e). -* Samples may vary from the valid technical specifications of the product -* series. They are therefore not intended or fit for resale to third -* parties or for use in end products. Their sole purpose is internal -* client testing. The testing of an engineering sample may in no way -* replace the testing of a product series. Bosch Sensortec assumes -* no liability for the use of engineering samples. -* By accepting the engineering samples, the Purchaser agrees to indemnify -* Bosch Sensortec from all claims arising from the use of engineering -* samples. -* -* Special: -* This software module (hereinafter called "Software") and any information -* on application-sheets (hereinafter called "Information") is provided -* free of charge for the sole purpose to support your application work. -* The Software and Information is subject to the following -* terms and conditions: -* -* The Software is specifically designed for the exclusive use for -* Bosch Sensortec products by personnel who have special experience -* and training. Do not use this Software if you do not have the -* proper experience or training. -* -* This Software package is provided `` as is `` and without any expressed -* or implied warranties,including without limitation, the implied warranties -* of merchantability and fitness for a particular purpose. -* -* Bosch Sensortec and their representatives and agents deny any liability -* for the functional impairment -* of this Software in terms of fitness, performance and safety. -* Bosch Sensortec and their representatives and agents shall not be liable -* for any direct or indirect damages or injury, except as -* otherwise stipulated in mandatory applicable law. -* -* The Information provided is believed to be accurate and reliable. -* Bosch Sensortec assumes no responsibility for the consequences of use -* of such Information nor for any infringement of patents or -* other rights of third parties which may result from its use. -* No license is granted by implication or otherwise under any patent or -* patent rights of Bosch. Specifications mentioned in the Information are -* subject to change without notice. -**************************************************************************/ -/*! \file bma4_defs.h - \brief Sensor Driver for BMA4 family of sensors */ -#ifndef BMA4_DEFS_H__ -#define BMA4_DEFS_H__ -/*********************************************************************/ -/**\ header files */ -#ifdef __KERNEL__ -#include -#else -#include -#include -#include -#endif - -/*********************************************************************/ -/* macro definitions */ - -/* -#if (LONG_MAX) > 0x7fffffff -#define __have_long64 1 -#elif (LONG_MAX) == 0x7fffffff -#define __have_long32 1 -#endif -*/ - -#if !defined(UINT8_C) -#define INT8_C(x) x -#if (INT_MAX) > 0x7f -#define UINT8_C(x) x -#else -#define UINT8_C(x) x##U -#endif -#endif - -#if !defined(UINT16_C) -#define INT16_C(x) x -#if (INT_MAX) > 0x7fff -#define UINT16_C(x) x -#else -#define UINT16_C(x) x##U -#endif -#endif - -#if !defined(INT32_C) && !defined(UINT32_C) -#if __have_long32 -#define INT32_C(x) x##L -#define UINT32_C(x) x##UL -#else -#define INT32_C(x) x -#define UINT32_C(x) x##U -#endif -#endif - -#if !defined(INT64_C) && !defined(UINT64_C) -#if __have_long64 -#define INT64_C(x) x##L -#define UINT64_C(x) x##UL -#else -#define INT64_C(x) x##LL -#define UINT64_C(x) x##ULL -#endif -#endif - -/**\name CHIP ID ADDRESS*/ -#define BMA4_CHIP_ID_ADDR UINT8_C(0x00) - -/**\name ERROR STATUS*/ -#define BMA4_ERROR_ADDR UINT8_C(0X02) - -/**\name STATUS REGISTER FOR SENSOR STATUS FLAG*/ -#define BMA4_STATUS_ADDR UINT8_C(0X03) - -/**\name AUX/ACCEL DATA BASE ADDRESS REGISTERS*/ -#define BMA4_DATA_0_ADDR UINT8_C(0X0A) -#define BMA4_DATA_8_ADDR UINT8_C(0X12) - -/**\name SENSOR TIME REGISTERS*/ -#define BMA4_SENSORTIME_0_ADDR UINT8_C(0X18) - -/**\name INTERRUPT/FEATURE STATUS REGISTERS*/ -#define BMA4_INT_STAT_0_ADDR UINT8_C(0X1C) - -/**\name INTERRUPT/FEATURE STATUS REGISTERS*/ -#define BMA4_INT_STAT_1_ADDR UINT8_C(0X1D) - -/**\name TEMPERATURE REGISTERS*/ -#define BMA4_TEMPERATURE_ADDR UINT8_C(0X22) - -/**\name FIFO REGISTERS*/ -#define BMA4_FIFO_LENGTH_0_ADDR UINT8_C(0X24) -#define BMA4_FIFO_DATA_ADDR UINT8_C(0X26) - -/**\name ACCEL CONFIG REGISTERS*/ -#define BMA4_ACCEL_CONFIG_ADDR UINT8_C(0X40) - -/**\name ACCEL RANGE ADDRESS*/ -#define BMA4_ACCEL_RANGE_ADDR UINT8_C(0X41) - -/**\name AUX CONFIG REGISTERS*/ -#define BMA4_AUX_CONFIG_ADDR UINT8_C(0X44) - -/**\name FIFO DOWN SAMPLING REGISTER ADDRESS FOR ACCEL*/ -#define BMA4_FIFO_DOWN_ADDR UINT8_C(0X45) - -/**\name FIFO WATERMARK REGISTER ADDRESS*/ -#define BMA4_FIFO_WTM_0_ADDR UINT8_C(0X46) - -/**\name FIFO CONFIG REGISTERS*/ -#define BMA4_FIFO_CONFIG_0_ADDR UINT8_C(0X48) -#define BMA4_FIFO_CONFIG_1_ADDR UINT8_C(0X49) - -/**\name MAG INTERFACE REGISTERS*/ -#define BMA4_AUX_DEV_ID_ADDR UINT8_C(0X4B) -#define BMA4_AUX_IF_CONF_ADDR UINT8_C(0X4C) -#define BMA4_AUX_RD_ADDR UINT8_C(0X4D) -#define BMA4_AUX_WR_ADDR UINT8_C(0X4E) -#define BMA4_AUX_WR_DATA_ADDR UINT8_C(0X4F) - -/**\name INTERRUPT ENABLE REGISTERS*/ -#define BMA4_INT1_IO_CTRL_ADDR UINT8_C(0X53) -#define BMA4_INT2_IO_CTRL_ADDR UINT8_C(0X54) - -/**\name LATCH DURATION REGISTERS*/ -#define BMA4_INTR_LATCH_ADDR UINT8_C(0X55) - -/**\name MAP INTERRUPT 1 and 2 REGISTERS*/ -#define BMA4_INT_MAP_1_ADDR UINT8_C(0X56) -#define BMA4_INT_MAP_2_ADDR UINT8_C(0X57) -#define BMA4_INT_MAP_DATA_ADDR UINT8_C(0x58) -#define BMA4_INIT_CTRL_ADDR UINT8_C(0x59) - -/**\name FEATURE CONFIG RELATED */ -#define BMA4_RESERVED_REG_5B_ADDR UINT8_C(0x5B) -#define BMA4_RESERVED_REG_5C_ADDR UINT8_C(0x5C) -#define BMA4_FEATURE_CONFIG_ADDR UINT8_C(0x5E) -#define BMA4_INTERNAL_ERROR UINT8_C(0x5F) - -/**\name SERIAL INTERFACE SETTINGS REGISTER*/ -#define BMA4_IF_CONFIG_ADDR UINT8_C(0X6B) - -/**\name SELF_TEST REGISTER*/ -#define BMA4_ACC_SELF_TEST_ADDR UINT8_C(0X6D) - -/**\name SPI,I2C SELECTION REGISTER*/ -#define BMA4_NV_CONFIG_ADDR UINT8_C(0x70) - -/**\name ACCEL OFFSET REGISTERS*/ -#define BMA4_OFFSET_0_ADDR UINT8_C(0X71) -#define BMA4_OFFSET_1_ADDR UINT8_C(0X72) -#define BMA4_OFFSET_2_ADDR UINT8_C(0X73) - -/**\name POWER_CTRL REGISTER*/ -#define BMA4_POWER_CONF_ADDR UINT8_C(0x7C) -#define BMA4_POWER_CTRL_ADDR UINT8_C(0x7D) - -/**\name COMMAND REGISTER*/ -#define BMA4_CMD_ADDR UINT8_C(0X7E) - -/**\name GPIO REGISTERS*/ -#define BMA4_STEP_CNT_OUT_0_ADDR UINT8_C(0x1E) -#define BMA4_HIGH_G_OUT_ADDR UINT8_C(0x1F) -#define BMA4_ACTIVITY_OUT_ADDR UINT8_C(0x27) -#define BMA4_ORIENTATION_OUT_ADDR UINT8_C(0x28) -#define BMA4_INTERNAL_STAT UINT8_C(0x2A) - -/*! - * @brief Block size for config write */ -#define BMA4_BLOCK_SIZE UINT8_C(32) - -/**\name I2C slave address */ -#define BMA4_I2C_ADDR_PRIMARY UINT8_C(0x18) -#define BMA4_I2C_ADDR_SECONDARY UINT8_C(0x19) -#define BMA4_I2C_BMM150_ADDR UINT8_C(0x10) - -/**\name Interface selection macro */ -#define BMA4_SPI_INTERFACE UINT8_C(1) -#define BMA4_I2C_INTERFACE UINT8_C(2) - -/**\name Interface selection macro */ -#define BMA4_SPI_WR_MASK UINT8_C(0x7F) -#define BMA4_SPI_RD_MASK UINT8_C(0x80) - -/**\name Chip ID macros */ -#define BMA4_CHIP_ID_MIN UINT8_C(0x10) -#define BMA4_CHIP_ID_MAX UINT8_C(0x15) - -/**\name Auxiliary sensor selection macro */ -#define BMM150_SENSOR UINT8_C(1) -#define AKM9916_SENSOR UINT8_C(2) -#define BMA4_ASIC_INITIALIZED UINT8_C(0x01) - -/**\name Auxiliary sensor chip id macros */ -#define BMM150_CHIP_ID UINT8_C(0x32) - -/**\name Auxiliary sensor other macros */ -#define BMM150_POWER_CONTROL_REG UINT8_C(0x4B) -#define BMM150_POWER_MODE_REG UINT8_C(0x4C) - -/**\name CONSTANTS */ -#define BMA4_FIFO_CONFIG_LENGTH UINT8_C(2) -#define BMA4_ACCEL_CONFIG_LENGTH UINT8_C(2) -#define BMA4_FIFO_WM_LENGTH UINT8_C(2) -#define BMA4_CONFIG_STREAM_SIZE UINT16_C(6144) -#define BMA4_NON_LATCH_MODE UINT8_C(0) -#define BMA4_LATCH_MODE UINT8_C(1) -#define BMA4_OPEN_DRAIN UINT8_C(1) -#define BMA4_PUSH_PULL UINT8_C(0) -#define BMA4_ACTIVE_HIGH UINT8_C(1) -#define BMA4_ACTIVE_LOW UINT8_C(0) -#define BMA4_EDGE_TRIGGER UINT8_C(1) -#define BMA4_LEVEL_TRIGGER UINT8_C(0) -#define BMA4_OUTPUT_ENABLE UINT8_C(1) -#define BMA4_OUTPUT_DISABLE UINT8_C(0) -#define BMA4_INPUT_ENABLE UINT8_C(1) -#define BMA4_INPUT_DISABLE UINT8_C(0) - -/**\name ACCEL RANGE CHECK*/ -#define BMA4_ACCEL_RANGE_2G UINT8_C(0) -#define BMA4_ACCEL_RANGE_4G UINT8_C(1) -#define BMA4_ACCEL_RANGE_8G UINT8_C(2) -#define BMA4_ACCEL_RANGE_16G UINT8_C(3) - -/**\name CONDITION CHECK FOR READING AND WRTING DATA*/ -#define BMA4_MAX_VALUE_FIFO_FILTER UINT8_C(1) -#define BMA4_MAX_VALUE_SPI3 UINT8_C(1) -#define BMA4_MAX_VALUE_SELFTEST_AMP UINT8_C(1) -#define BMA4_MAX_IF_MODE UINT8_C(3) -#define BMA4_MAX_VALUE_SELFTEST_SIGN UINT8_C(1) - -/**\name BUS READ AND WRITE LENGTH FOR MAG & ACCEL*/ -#define BMA4_MAG_TRIM_DATA_SIZE UINT8_C(16) -#define BMA4_MAG_XYZ_DATA_LENGTH UINT8_C(6) -#define BMA4_MAG_XYZR_DATA_LENGTH UINT8_C(8) -#define BMA4_ACCEL_DATA_LENGTH UINT8_C(6) -#define BMA4_FIFO_DATA_LENGTH UINT8_C(2) -#define BMA4_TEMP_DATA_SIZE UINT8_C(1) - -/**\name TEMPERATURE CONSTANT */ -#define BMA4_OFFSET_TEMP UINT8_C(23) -#define BMA4_DEG UINT8_C(1) -#define BMA4_FAHREN UINT8_C(2) -#define BMA4_KELVIN UINT8_C(3) - -/**\name DELAY DEFINITION IN MSEC*/ -#define BMA4_AUX_IF_DELAY UINT8_C(5) -#define BMA4_BMM150_WAKEUP_DELAY1 UINT8_C(2) -#define BMA4_BMM150_WAKEUP_DELAY2 UINT8_C(3) -#define BMA4_BMM150_WAKEUP_DELAY3 UINT8_C(1) -#define BMA4_GEN_READ_WRITE_DELAY UINT8_C(1) -#define BMA4_AUX_COM_DELAY UINT8_C(10) - -/**\name ARRAY PARAMETER DEFINITIONS*/ -#define BMA4_SENSOR_TIME_MSB_BYTE UINT8_C(2) -#define BMA4_SENSOR_TIME_XLSB_BYTE UINT8_C(1) -#define BMA4_SENSOR_TIME_LSB_BYTE UINT8_C(0) -#define BMA4_MAG_X_LSB_BYTE UINT8_C(0) -#define BMA4_MAG_X_MSB_BYTE UINT8_C(1) -#define BMA4_MAG_Y_LSB_BYTE UINT8_C(2) -#define BMA4_MAG_Y_MSB_BYTE UINT8_C(3) -#define BMA4_MAG_Z_LSB_BYTE UINT8_C(4) -#define BMA4_MAG_Z_MSB_BYTE UINT8_C(5) -#define BMA4_MAG_R_LSB_BYTE UINT8_C(6) -#define BMA4_MAG_R_MSB_BYTE UINT8_C(7) -#define BMA4_TEMP_BYTE UINT8_C(0) -#define BMA4_FIFO_LENGTH_MSB_BYTE UINT8_C(1) - -/**\name ERROR CODES */ -#define BMA4_OK UINT16_C(0) -#define BMA4_E_NULL_PTR UINT16_C(1) -#define BMA4_E_OUT_OF_RANGE UINT16_C(1 << 1) -#define BMA4_E_INVALID_SENSOR UINT16_C(1 << 2) -#define BMA4_E_CONFIG_STREAM_ERROR UINT16_C(1 << 3) -#define BMA4_E_SELF_TEST_FAIL UINT16_C(1 << 4) -#define BMA4_E_FOC_FAIL UINT16_C(1 << 5) -#define BMA4_E_FAIL UINT16_C(1 << 6) -#define BMA4_E_INT_LINE_INVALID UINT16_C(1 << 7) -#define BMA4_E_RD_WR_LENGTH_INVALID UINT16_C(1 << 8) -#define BMA4_E_AUX_CONFIG_FAIL UINT16_C(1 << 9) -#define BMA4_E_SC_FIFO_HEADER_ERR UINT16_C(1 << 10) -#define BMA4_E_SC_FIFO_CONFIG_ERR UINT16_C(1 << 11) - -/**\name UTILITY MACROS */ -#define BMA4_SET_LOW_BYTE UINT16_C(0x00FF) -#define BMA4_SET_HIGH_BYTE UINT16_C(0xFF00) -#define BMA4_SET_LOW_NIBBLE UINT8_C(0x0F) - -/**\name FOC RELATED MACROS */ -#define BMA4_ACCEL_CONFIG_FOC UINT8_C(0xB7) - -/* Macros used for Self test */ -/* Self-test: Resulting minimum difference signal in mg for BMA42x */ -#define BMA42X_ST_ACC_X_AXIS_SIGNAL_DIFF UINT16_C(400) -#define BMA42X_ST_ACC_Y_AXIS_SIGNAL_DIFF UINT16_C(800) -#define BMA42X_ST_ACC_Z_AXIS_SIGNAL_DIFF UINT16_C(400) - -/* Self-test: Resulting minimum difference signal in mg for BMA45x */ -#define BMA45X_ST_ACC_X_AXIS_SIGNAL_DIFF UINT16_C(1800) -#define BMA45X_ST_ACC_Y_AXIS_SIGNAL_DIFF UINT16_C(1800) -#define BMA45X_ST_ACC_Z_AXIS_SIGNAL_DIFF UINT16_C(1800) - -/**\name BOOLEAN TYPES*/ -#ifndef TRUE -#define TRUE UINT8_C(0x01) -#endif - -#ifndef FALSE -#define FALSE UINT8_C(0x00) -#endif - -#ifndef NULL -#define NULL UINT8_C(0x00) -#endif - -/**\name ERROR STATUS POSITION AND MASK*/ -#define BMA4_FATAL_ERR_MSK UINT8_C(0x01) -#define BMA4_CMD_ERR_POS UINT8_C(1) -#define BMA4_CMD_ERR_MSK UINT8_C(0x02) -#define BMA4_ERR_CODE_POS UINT8_C(2) -#define BMA4_ERR_CODE_MSK UINT8_C(0x1C) -#define BMA4_FIFO_ERR_POS UINT8_C(6) -#define BMA4_FIFO_ERR_MSK UINT8_C(0x40) -#define BMA4_AUX_ERR_POS UINT8_C(7) -#define BMA4_AUX_ERR_MSK UINT8_C(0x80) - -/**\name Maximum number of bytes to be read from the sensor */ -#define BMA4_MAX_BUFFER_SIZE UINT8_C(81) - -/**\name NV_CONFIG POSITION AND MASK*/ -/* NV_CONF Description - Reg Addr --> (0x70), Bit --> 3 */ -#define BMA4_NV_ACCEL_OFFSET_POS UINT8_C(3) -#define BMA4_NV_ACCEL_OFFSET_MSK UINT8_C(0x08) - -/**\name MAG DATA XYZ POSITION AND MASK*/ -#define BMA4_DATA_MAG_X_LSB_POS UINT8_C(3) -#define BMA4_DATA_MAG_X_LSB_MSK UINT8_C(0xF8) -#define BMA4_DATA_MAG_Y_LSB_POS UINT8_C(3) -#define BMA4_DATA_MAG_Y_LSB_MSK UINT8_C(0xF8) -#define BMA4_DATA_MAG_Z_LSB_POS UINT8_C(1) -#define BMA4_DATA_MAG_Z_LSB_MSK UINT8_C(0xFE) -#define BMA4_DATA_MAG_R_LSB_POS UINT8_C(2) -#define BMA4_DATA_MAG_R_LSB_MSK UINT8_C(0xFC) - -/**\name ACCEL DATA READY POSITION AND MASK*/ -#define BMA4_STAT_DATA_RDY_ACCEL_POS UINT8_C(7) -#define BMA4_STAT_DATA_RDY_ACCEL_MSK UINT8_C(0x80) - -/**\name MAG DATA READY POSITION AND MASK*/ -#define BMA4_STAT_DATA_RDY_MAG_POS UINT8_C(5) -#define BMA4_STAT_DATA_RDY_MAG_MSK UINT8_C(0x20) - -/**\name ADVANCE POWER SAVE POSITION AND MASK*/ -#define BMA4_ADVANCE_POWER_SAVE_MSK UINT8_C(0x01) - -/**\name ACCELEROMETER ENABLE POSITION AND MASK*/ -#define BMA4_ACCEL_ENABLE_POS UINT8_C(2) -#define BMA4_ACCEL_ENABLE_MSK UINT8_C(0x04) - -/**\name MAGNETOMETER ENABLE POSITION AND MASK*/ -#define BMA4_MAG_ENABLE_MSK UINT8_C(0x01) - -/**\name ACCEL CONFIGURATION POSITION AND MASK*/ -#define BMA4_ACCEL_ODR_MSK UINT8_C(0x0F) -#define BMA4_ACCEL_BW_POS UINT8_C(4) -#define BMA4_ACCEL_BW_MSK UINT8_C(0x70) -#define BMA4_ACCEL_RANGE_MSK UINT8_C(0x03) -#define BMA4_ACCEL_PERFMODE_POS UINT8_C(7) -#define BMA4_ACCEL_PERFMODE_MSK UINT8_C(0x80) - -/**\name MAG CONFIGURATION POSITION AND MASK*/ -#define BMA4_MAG_CONFIG_OFFSET_POS UINT8_C(4) -#define BMA4_MAG_CONFIG_OFFSET_LEN UINT8_C(4) -#define BMA4_MAG_CONFIG_OFFSET_MSK UINT8_C(0xF0) -#define BMA4_MAG_CONFIG_OFFSET_REG (BMA4_AUX_CONFIG_ADDR) - -/**\name FIFO SELF WAKE UP POSITION AND MASK*/ -#define BMA4_FIFO_SELF_WAKE_UP_POS UINT8_C(1) -#define BMA4_FIFO_SELF_WAKE_UP_MSK UINT8_C(0x02) - -/**\name FIFO BYTE COUNTER POSITION AND MASK*/ -#define BMA4_FIFO_BYTE_COUNTER_MSB_MSK UINT8_C(0x3F) - -/**\name FIFO DATA POSITION AND MASK*/ -#define BMA4_FIFO_DATA_POS UINT8_C(0) -#define BMA4_FIFO_DATA_MSK UINT8_C(0xFF) - -/**\name FIFO FILTER FOR ACCEL POSITION AND MASK*/ -#define BMA4_FIFO_DOWN_ACCEL_POS UINT8_C(4) -#define BMA4_FIFO_DOWN_ACCEL_MSK UINT8_C(0x70) -#define BMA4_FIFO_FILTER_ACCEL_POS UINT8_C(7) -#define BMA4_FIFO_FILTER_ACCEL_MSK UINT8_C(0x80) - -/**\name FIFO HEADER DATA DEFINITIONS */ -#define FIFO_HEAD_A UINT8_C(0x84) -#define FIFO_HEAD_M UINT8_C(0x90) -#define FIFO_HEAD_M_A UINT8_C(0x94) -#define FIFO_HEAD_SENSOR_TIME UINT8_C(0x44) -#define FIFO_HEAD_INPUT_CONFIG UINT8_C(0x48) -#define FIFO_HEAD_SKIP_FRAME UINT8_C(0x40) -#define FIFO_HEAD_OVER_READ_MSB UINT8_C(0x80) -#define FIFO_HEAD_SAMPLE_DROP UINT8_C(0x50) - -/**\name FIFO HEADERLESS MODE DATA ENABLE DEFINITIONS */ -#define BMA4_FIFO_M_A_ENABLE UINT8_C(0x60) -#define BMA4_FIFO_A_ENABLE UINT8_C(0x40) -#define BMA4_FIFO_M_ENABLE UINT8_C(0x20) - -/**\name FIFO CONFIGURATION SELECTION */ -#define BMA4_FIFO_STOP_ON_FULL UINT8_C(0x01) -#define BMA4_FIFO_TIME UINT8_C(0x02) -#define BMA4_FIFO_TAG_INTR2 UINT8_C(0x04) -#define BMA4_FIFO_TAG_INTR1 UINT8_C(0x08) -#define BMA4_FIFO_HEADER UINT8_C(0x10) -#define BMA4_FIFO_MAG UINT8_C(0x20) -#define BMA4_FIFO_ACCEL UINT8_C(0x40) -#define BMA4_FIFO_ALL UINT8_C(0x7F) -#define BMA4_FIFO_CONFIG_0_MASK UINT8_C(0x03) -#define BMA4_FIFO_CONFIG_1_MASK UINT8_C(0xFC) - -/**\name FIFO FRAME COUNT DEFINITION */ -#define FIFO_LSB_CONFIG_CHECK UINT8_C(0x00) -#define FIFO_MSB_CONFIG_CHECK UINT8_C(0x80) -#define BMA4_FIFO_TAG_INTR_MASK UINT8_C(0xFC) - -/**\name FIFO DROPPED FRAME DEFINITION */ -#define AUX_FIFO_DROP UINT8_C(0x04) -#define ACCEL_AUX_FIFO_DROP UINT8_C(0x05) -#define ACCEL_FIFO_DROP UINT8_C(0x01) - -/**\name FIFO MAG DEFINITION*/ -#define BMA4_MA_FIFO_A_X_LSB UINT8_C(8) - -/**\name FIFO sensor time length definitions*/ -#define BMA4_SENSOR_TIME_LENGTH UINT8_C(3) - -/**\name FIFO LENGTH DEFINITION*/ -#define BMA4_FIFO_A_LENGTH UINT8_C(6) -#define BMA4_FIFO_M_LENGTH UINT8_C(8) -#define BMA4_FIFO_MA_LENGTH UINT8_C(14) - -/**\name MAG I2C ADDRESS SELECTION POSITION AND MASK*/ -#define BMA4_I2C_DEVICE_ADDR_POS UINT8_C(1) -#define BMA4_I2C_DEVICE_ADDR_MSK UINT8_C(0xFE) - -/**\name MAG CONFIGURATION FOR SECONDARY INTERFACE POSITION AND MASK*/ -#define BMA4_MAG_BURST_MSK UINT8_C(0x03) -#define BMA4_MAG_MANUAL_ENABLE_POS UINT8_C(7) -#define BMA4_MAG_MANUAL_ENABLE_MSK UINT8_C(0x80) -#define BMA4_READ_ADDR_MSK UINT8_C(0xFF) -#define BMA4_WRITE_ADDR_MSK UINT8_C(0xFF) -#define BMA4_WRITE_DATA_MSK UINT8_C(0xFF) - -/**\name OUTPUT TYPE ENABLE POSITION AND MASK*/ -#define BMA4_INT_EDGE_CTRL_MASK UINT8_C(0x01) -#define BMA4_INT_EDGE_CTRL_POS UINT8_C(0x00) -#define BMA4_INT_LEVEL_MASK UINT8_C(0x02) -#define BMA4_INT_LEVEL_POS UINT8_C(0x01) -#define BMA4_INT_OPEN_DRAIN_MASK UINT8_C(0x04) -#define BMA4_INT_OPEN_DRAIN_POS UINT8_C(0x02) -#define BMA4_INT_OUTPUT_EN_MASK UINT8_C(0x08) -#define BMA4_INT_OUTPUT_EN_POS UINT8_C(0x03) -#define BMA4_INT_INPUT_EN_MASK UINT8_C(0x10) -#define BMA4_INT_INPUT_EN_POS UINT8_C(0x04) - -/**\name IF CONFIG POSITION AND MASK*/ -#define BMA4_CONFIG_SPI3_MSK UINT8_C(0x01) -#define BMA4_IF_CONFIG_IF_MODE_POS UINT8_C(4) -#define BMA4_IF_CONFIG_IF_MODE_MSK UINT8_C(0x10) - -/**\name ACCEL SELF TEST POSITION AND MASK*/ -#define BMA4_ACCEL_SELFTEST_ENABLE_MSK UINT8_C(0x01) -#define BMA4_ACCEL_SELFTEST_SIGN_POS UINT8_C(2) -#define BMA4_ACCEL_SELFTEST_SIGN_MSK UINT8_C(0x04) -#define BMA4_SELFTEST_AMP_POS UINT8_C(3) -#define BMA4_SELFTEST_AMP_MSK UINT8_C(0x08) - -/**\name ACCEL ODR */ -#define BMA4_OUTPUT_DATA_RATE_0_78HZ UINT8_C(0x01) -#define BMA4_OUTPUT_DATA_RATE_1_56HZ UINT8_C(0x02) -#define BMA4_OUTPUT_DATA_RATE_3_12HZ UINT8_C(0x03) -#define BMA4_OUTPUT_DATA_RATE_6_25HZ UINT8_C(0x04) -#define BMA4_OUTPUT_DATA_RATE_12_5HZ UINT8_C(0x05) -#define BMA4_OUTPUT_DATA_RATE_25HZ UINT8_C(0x06) -#define BMA4_OUTPUT_DATA_RATE_50HZ UINT8_C(0x07) -#define BMA4_OUTPUT_DATA_RATE_100HZ UINT8_C(0x08) -#define BMA4_OUTPUT_DATA_RATE_200HZ UINT8_C(0x09) -#define BMA4_OUTPUT_DATA_RATE_400HZ UINT8_C(0x0A) -#define BMA4_OUTPUT_DATA_RATE_800HZ UINT8_C(0x0B) -#define BMA4_OUTPUT_DATA_RATE_1600HZ UINT8_C(0x0C) - -/**\name ACCEL BANDWIDTH PARAMETER */ -#define BMA4_ACCEL_OSR4_AVG1 UINT8_C(0) -#define BMA4_ACCEL_OSR2_AVG2 UINT8_C(1) -#define BMA4_ACCEL_NORMAL_AVG4 UINT8_C(2) -#define BMA4_ACCEL_CIC_AVG8 UINT8_C(3) -#define BMA4_ACCEL_RES_AVG16 UINT8_C(4) -#define BMA4_ACCEL_RES_AVG32 UINT8_C(5) -#define BMA4_ACCEL_RES_AVG64 UINT8_C(6) -#define BMA4_ACCEL_RES_AVG128 UINT8_C(7) - -/**\name ACCEL PERFMODE PARAMETER */ -#define BMA4_CIC_AVG_MODE UINT8_C(0) -#define BMA4_CONTINUOUS_MODE UINT8_C(1) - -/**\name MAG OFFSET */ -#define BMA4_MAG_OFFSET_MAX UINT8_C(0x00) - -/**\name ENABLE/DISABLE SELECTIONS */ -#define BMA4_X_AXIS UINT8_C(0) -#define BMA4_Y_AXIS UINT8_C(1) -#define BMA4_Z_AXIS UINT8_C(2) - -/**\name SELF TEST*/ -#define BMA4_SELFTEST_PASS UINT8_C(0) -#define BMA4_SELFTEST_FAIL UINT8_C(1) - -/**\name INTERRUPT MAPS */ -#define BMA4_INTR1_MAP UINT8_C(0) -#define BMA4_INTR2_MAP UINT8_C(1) - -/**\name INTERRUPT MASKS */ -#define BMA4_FIFO_FULL_INT UINT16_C(0x0100) -#define BMA4_FIFO_WM_INT UINT16_C(0x0200) -#define BMA4_DATA_RDY_INT UINT16_C(0x0400) -#define BMA4_MAG_DATA_RDY_INT UINT16_C(0x2000) -#define BMA4_ACCEL_DATA_RDY_INT UINT16_C(0x8000) - - -/**\name AKM POWER MODE SELECTION */ -#define AKM_POWER_DOWN_MODE UINT8_C(0) -#define AKM_SINGLE_MEAS_MODE UINT8_C(1) - -/**\name SECONDARY_MAG POWER MODE SELECTION */ -#define BMA4_MAG_FORCE_MODE UINT8_C(0) -#define BMA4_MAG_SUSPEND_MODE UINT8_C(1) - -/**\name MAG POWER MODE SELECTION */ -#define FORCE_MODE UINT8_C(0) -#define SUSPEND_MODE UINT8_C(1) - -/**\name ACCEL POWER MODE */ -#define ACCEL_MODE_NORMAL UINT8_C(0x11) - -/**\name MAG POWER MODE */ -#define MAG_MODE_SUSPEND UINT8_C(0x18) - -/**\name ENABLE/DISABLE BIT VALUES */ -#define BMA4_ENABLE UINT8_C(0x01) -#define BMA4_DISABLE UINT8_C(0x00) - -/**\name DEFINITION USED FOR DIFFERENT WRITE */ -#define BMA4_MANUAL_DISABLE UINT8_C(0x00) -#define BMA4_MANUAL_ENABLE UINT8_C(0x01) -#define BMA4_ENABLE_MAG_IF_MODE UINT8_C(0x01) -#define BMA4_MAG_DATA_READ_REG UINT8_C(0x0A) -#define BMA4_BMM_POWER_MODE_REG UINT8_C(0x06) -#define BMA4_SEC_IF_NULL UINT8_C(0) -#define BMA4_SEC_IF_BMM150 UINT8_C(1) -#define BMA4_SEC_IF_AKM09916 UINT8_C(2) -#define BMA4_ENABLE_AUX_IF_MODE UINT8_C(0x01) - -/**\name SENSOR RESOLUTION */ -#define BMA4_12_BIT_RESOLUTION UINT8_C(12) -#define BMA4_14_BIT_RESOLUTION UINT8_C(14) -#define BMA4_16_BIT_RESOLUTION UINT8_C(16) - -/**\name MULTIPLIER */ -/*! for handling micro-g values */ -#define BMA4XY_MULTIPLIER UINT32_C(1000000) -/*! for handling float temperature values */ -#define BMA4_SCALE_TEMP INT32_C(1000) -/* BMA4_FAHREN_SCALED = 1.8 * 1000 */ -#define BMA4_FAHREN_SCALED INT32_C(1800) -/* BMA4_KELVIN_SCALED = 273.15 * 1000 */ -#define BMA4_KELVIN_SCALED INT32_C(273150) - - -/**\name MAP BURST READ LENGTHS */ -#define BMA4_AUX_READ_LEN_0 0 -#define BMA4_AUX_READ_LEN_1 1 -#define BMA4_AUX_READ_LEN_2 2 -#define BMA4_AUX_READ_LEN_3 3 - -#ifndef ABS -#define ABS(a) ((a) > 0 ? (a) : -(a)) /*!< Absolute value */ -#endif - -/**\name BIT SLICE GET AND SET FUNCTIONS */ -#define BMA4_GET_BITSLICE(regvar, bitname)\ - ((regvar & bitname##_MSK) >> bitname##_POS) -#define BMA4_SET_BITSLICE(regvar, bitname, val)\ - ((regvar & ~bitname##_MSK) | \ - ((val<> 8) - -#define BMA4_SET_BIT_VAL_0(reg_data, bitname) (reg_data & ~(bitname##_MSK)) - -#define BMA4_SET_BITS_POS_0(reg_data, bitname, data) \ - ((reg_data & ~(bitname##_MSK)) | \ - (data & bitname##_MSK)) - -#define BMA4_GET_BITS_POS_0(reg_data, bitname) (reg_data & (bitname##_MSK)) - -/**\name TYPEDEF DEFINITIONS */ -/*! - * @brief Bus communication function pointer which should be mapped to - * the platform specific read and write functions of the user - */ -typedef uint16_t (*bma4_com_fptr_t)(uint8_t dev_addr, uint8_t reg_addr, uint8_t *read_data, uint16_t len); - -/*! delay function pointer */ -typedef void (*bma4_delay_fptr_t)(uint32_t); - -/******************************************************************************/ -/*! @name Enum Declarations */ -/******************************************************************************/ - -/*! @name Enum to define BMA4 variants */ -enum bma4_variant { - BMA42X_VARIANT = 1, - BMA45X_VARIANT -}; - -/**\name STRUCTURE DEFINITIONS*/ - -/*! - * @brief - * This structure holds asic info. for feature configuration. - */ -struct bma4_asic_data { - /* Feature config start addr (0-3 bits)*/ - uint8_t asic_lsb; - /* Feature config start addr (4-11 bits)*/ - uint8_t asic_msb; -}; - -/*! - * @brief Auxiliary configuration structure for user settings - */ -struct bma4_aux_config { - /*! Device address of auxiliary sensor */ - uint8_t aux_dev_addr; - /*! To enable manual or auto mode */ - uint8_t manual_enable; - /*! No of bytes to be read at a time */ - uint8_t burst_read_length; - /*! Variable to set the auxiliary interface */ - uint8_t if_mode; -}; - -/*! - * @brief - * This structure holds all relevant information about BMA4 - */ -struct bma4_dev { - /*! Chip id of BMA4 */ - uint8_t chip_id; - /*! Chip id of auxiliary sensor */ - uint8_t aux_chip_id; - /*! Device address of BMA4 */ - uint8_t dev_addr; - /*! Interface detail */ - uint8_t interface; - /*! Auxiliary sensor information */ - uint8_t aux_sensor; - /*! Decide SPI or I2C read mechanism */ - uint8_t dummy_byte; - /*! Resolution for FOC */ - uint8_t resolution; - /*! Define the BMA4 variant BMA42X or BMA45X */ - enum bma4_variant variant; -/* ! Used to check mag manual/auto mode status - int8_t mag_manual_enable;*/ - /*! FIFO related configurations */ - struct bma4_fifo_frame *fifo; - /*! Config stream data buffer address will be assigned*/ - const uint8_t *config_file_ptr; - /*! Max read/write length (maximum supported length is 32). - To be set by the user */ - uint8_t read_write_len; - /*! Feature len */ - uint8_t feature_len; - /*! Contains asic information */ - struct bma4_asic_data asic_data; - /*! Contains aux configuration settings */ - struct bma4_aux_config aux_config; - /*! Bus read function pointer */ - bma4_com_fptr_t bus_read; - /*! Bus write function pointer */ - bma4_com_fptr_t bus_write; - /*! delay(in ms) function pointer */ - bma4_delay_fptr_t delay; -}; - -/*! - * @brief This structure holds the information for usage of - * FIFO by the user. - */ -struct bma4_fifo_frame { - /*! Data buffer of user defined length is to be mapped here */ - uint8_t *data; - /*! Number of bytes of FIFO to be read as specified by the user */ - uint16_t length; - /*! Enabling of the FIFO header to stream in header mode */ - uint8_t fifo_header_enable; - /*! Streaming of the Accelerometer, Auxiliary - * sensor data or both in FIFO */ - uint8_t fifo_data_enable; - /*! Will be equal to length when no more frames are there to parse */ - uint16_t accel_byte_start_idx; - /*! Will be equal to length when no more frames are there to parse */ - uint16_t mag_byte_start_idx; - /*! Will be equal to length when no more frames are there to parse */ - uint16_t sc_frame_byte_start_idx; - /*! Value of FIFO sensor time time */ - uint32_t sensor_time; - /*! Value of Skipped frame counts */ - uint8_t skipped_frame_count; - /*! Value of accel dropped frame count */ - uint8_t accel_dropped_frame_count; - /*! Value of mag dropped frame count */ - uint8_t mag_dropped_frame_count; -}; - -/*! - * @brief Error Status structure - */ -struct bma4_err_reg { - /*! Indicates fatal error */ - uint8_t fatal_err; - /*! Indicates command error */ - uint8_t cmd_err; - /*! Indicates error code */ - uint8_t err_code; - /*! Indicates fifo error */ - uint8_t fifo_err; - /*! Indicates mag error */ - uint8_t aux_err; -}; - -/*! - * @brief Asic Status structure - */ -struct bma4_asic_status { - /*! Asic is in sleep/halt state */ - uint8_t sleep; - /*! Dedicated interrupt is set again before previous interrupt - was acknowledged */ - uint8_t irq_ovrn; - /*! Watchcell event detected (asic stopped) */ - uint8_t wc_event; - /*! Stream transfer has started and transactions are ongoing */ - uint8_t stream_transfer_active; -}; - -/*! - * @brief Interrupt Pin Configuration structure - */ -struct bma4_int_pin_config { - /*! Trigger condition of interrupt pin */ - uint8_t edge_ctrl; - /*! Level of interrupt pin */ - uint8_t lvl; - /*! Behaviour of interrupt pin to open drain */ - uint8_t od; - /*! Output enable for interrupt pin */ - uint8_t output_en; - /*! Input enable for interrupt pin */ - uint8_t input_en; -}; - -/*! -* @brief Accelerometer configuration structure */ -struct bma4_accel_config { - /*! Output data rate in Hz */ - uint8_t odr; - /*! Bandwidth parameter, determines filter configuration */ - uint8_t bandwidth; - /*! Filter performance mode */ - uint8_t perf_mode; - /*! G-range */ - uint8_t range; -}; - -/*! - * @brief Auxiliary magnetometer configuration structure - */ -struct bma4_aux_mag_config { - /*! Poll rate for the sensor attached to the Magnetometer interface */ - uint8_t odr; - /*! Trigger-readout offset in units of 2.5 ms. - If set to zero, the offset is maximum, i.e. after readout a trigger - is issued immediately */ - uint8_t offset; -}; - -/*! - * @brief ASIC Config structure - */ -struct bma4_asic_config { - /*! Enable/Disable ASIC Wake Up */ - uint8_t asic_en; - /*! Configure stream_transfer/FIFO mode */ - uint8_t fifo_mode_en; - /*! Mapping of instance RAM1 */ - uint8_t mem_conf_ram1; - /*! Mapping of instance RAM2 */ - uint8_t mem_conf_ram2; - /*! Mapping of instance RAM3 */ - uint8_t mem_conf_ram3; -}; -/*! - * @brief bmm150 or akm09916 - * magnetometer values structure - */ -struct bma4_mag { - /*! BMM150 and AKM09916 X raw data */ - int32_t x; - /*! BMM150 and AKM09916 Y raw data */ - int32_t y; - /*! BMM150 and AKM09916 Z raw data */ - int32_t z; -}; - -/*! - * @brief bmm150 xyz data structure - */ -struct bma4_mag_xyzr { - /*! BMM150 X raw data */ - int16_t x; - /*! BMM150 Y raw data */ - int16_t y; - /*! BMM150 Z raw data */ - int16_t z; - /*! BMM150 R raw data */ - uint16_t r; -}; - -/*! - * @brief Accel xyz data structure - */ -struct bma4_accel { - /*! Accel X data */ - int16_t x; - /*! Accel Y data */ - int16_t y; - /*! Accel Z data */ - int16_t z; -}; - -/*! - * @brief FIFO mag data structure - */ -struct bma4_mag_fifo_data { - /*! The value of mag x LSB data */ - uint8_t mag_x_lsb; - /*! The value of mag x MSB data */ - uint8_t mag_x_msb; - /*! The value of mag y LSB data */ - uint8_t mag_y_lsb; - /*! The value of mag y MSB data */ - uint8_t mag_y_msb; - /*! The value of mag z LSB data */ - uint8_t mag_z_lsb; - /*! The value of mag z MSB data */ - uint8_t mag_z_msb; - /*! The value of mag r for BMM150 Y2 for YAMAHA LSB data */ - uint8_t mag_r_y2_lsb; - /*! The value of mag r for BMM150 Y2 for YAMAHA MSB data */ - uint8_t mag_r_y2_msb; -}; - -#endif -/* End of __BMA4_H__ */ +/* +* +**************************************************************************** +* Copyright (C) 2017 - 2018 Bosch Sensortec GmbH +* +* File : bma4_defs.h +* +* Date: 12 Oct 2017 +* +* Revision: 2.1.9 $ +* +* Usage: Sensor Driver for BMA4 family of sensors +* +**************************************************************************** +* +* Disclaimer +* +* Common: +* Bosch Sensortec products are developed for the consumer goods industry. +* They may only be used within the parameters of the respective valid +* product data sheet. Bosch Sensortec products are provided with the +* express understanding that there is no warranty of fitness for a +* particular purpose.They are not fit for use in life-sustaining, +* safety or security sensitive systems or any system or device +* that may lead to bodily harm or property damage if the system +* or device malfunctions. In addition,Bosch Sensortec products are +* not fit for use in products which interact with motor vehicle systems. +* The resale and or use of products are at the purchasers own risk and +* his own responsibility. The examination of fitness for the intended use +* is the sole responsibility of the Purchaser. +* +* The purchaser shall indemnify Bosch Sensortec from all third party +* claims, including any claims for incidental, or consequential damages, +* arising from any product use not covered by the parameters of +* the respective valid product data sheet or not approved by +* Bosch Sensortec and reimburse Bosch Sensortec for all costs in +* connection with such claims. +* +* The purchaser must monitor the market for the purchased products, +* particularly with regard to product safety and inform Bosch Sensortec +* without delay of all security relevant incidents. +* +* Engineering Samples are marked with an asterisk (*) or (e). +* Samples may vary from the valid technical specifications of the product +* series. They are therefore not intended or fit for resale to third +* parties or for use in end products. Their sole purpose is internal +* client testing. The testing of an engineering sample may in no way +* replace the testing of a product series. Bosch Sensortec assumes +* no liability for the use of engineering samples. +* By accepting the engineering samples, the Purchaser agrees to indemnify +* Bosch Sensortec from all claims arising from the use of engineering +* samples. +* +* Special: +* This software module (hereinafter called "Software") and any information +* on application-sheets (hereinafter called "Information") is provided +* free of charge for the sole purpose to support your application work. +* The Software and Information is subject to the following +* terms and conditions: +* +* The Software is specifically designed for the exclusive use for +* Bosch Sensortec products by personnel who have special experience +* and training. Do not use this Software if you do not have the +* proper experience or training. +* +* This Software package is provided `` as is `` and without any expressed +* or implied warranties,including without limitation, the implied warranties +* of merchantability and fitness for a particular purpose. +* +* Bosch Sensortec and their representatives and agents deny any liability +* for the functional impairment +* of this Software in terms of fitness, performance and safety. +* Bosch Sensortec and their representatives and agents shall not be liable +* for any direct or indirect damages or injury, except as +* otherwise stipulated in mandatory applicable law. +* +* The Information provided is believed to be accurate and reliable. +* Bosch Sensortec assumes no responsibility for the consequences of use +* of such Information nor for any infringement of patents or +* other rights of third parties which may result from its use. +* No license is granted by implication or otherwise under any patent or +* patent rights of Bosch. Specifications mentioned in the Information are +* subject to change without notice. +**************************************************************************/ +/*! \file bma4_defs.h + \brief Sensor Driver for BMA4 family of sensors */ +#ifndef BMA4_DEFS_H__ +#define BMA4_DEFS_H__ +/*********************************************************************/ +/**\ header files */ +#ifdef __KERNEL__ +#include +#else +#include +#include +#include +#endif + +/*********************************************************************/ +/* macro definitions */ + +/* +#if (LONG_MAX) > 0x7fffffff +#define __have_long64 1 +#elif (LONG_MAX) == 0x7fffffff +#define __have_long32 1 +#endif +*/ + +#if !defined(UINT8_C) +#define INT8_C(x) x +#if (INT_MAX) > 0x7f +#define UINT8_C(x) x +#else +#define UINT8_C(x) x##U +#endif +#endif + +#if !defined(UINT16_C) +#define INT16_C(x) x +#if (INT_MAX) > 0x7fff +#define UINT16_C(x) x +#else +#define UINT16_C(x) x##U +#endif +#endif + +#if !defined(INT32_C) && !defined(UINT32_C) +#if __have_long32 +#define INT32_C(x) x##L +#define UINT32_C(x) x##UL +#else +#define INT32_C(x) x +#define UINT32_C(x) x##U +#endif +#endif + +#if !defined(INT64_C) && !defined(UINT64_C) +#if __have_long64 +#define INT64_C(x) x##L +#define UINT64_C(x) x##UL +#else +#define INT64_C(x) x##LL +#define UINT64_C(x) x##ULL +#endif +#endif + +/**\name CHIP ID ADDRESS*/ +#define BMA4_CHIP_ID_ADDR UINT8_C(0x00) + +/**\name ERROR STATUS*/ +#define BMA4_ERROR_ADDR UINT8_C(0X02) + +/**\name STATUS REGISTER FOR SENSOR STATUS FLAG*/ +#define BMA4_STATUS_ADDR UINT8_C(0X03) + +/**\name AUX/ACCEL DATA BASE ADDRESS REGISTERS*/ +#define BMA4_DATA_0_ADDR UINT8_C(0X0A) +#define BMA4_DATA_8_ADDR UINT8_C(0X12) + +/**\name SENSOR TIME REGISTERS*/ +#define BMA4_SENSORTIME_0_ADDR UINT8_C(0X18) + +/**\name INTERRUPT/FEATURE STATUS REGISTERS*/ +#define BMA4_INT_STAT_0_ADDR UINT8_C(0X1C) + +/**\name INTERRUPT/FEATURE STATUS REGISTERS*/ +#define BMA4_INT_STAT_1_ADDR UINT8_C(0X1D) + +/**\name TEMPERATURE REGISTERS*/ +#define BMA4_TEMPERATURE_ADDR UINT8_C(0X22) + +/**\name FIFO REGISTERS*/ +#define BMA4_FIFO_LENGTH_0_ADDR UINT8_C(0X24) +#define BMA4_FIFO_DATA_ADDR UINT8_C(0X26) + +/**\name ACCEL CONFIG REGISTERS*/ +#define BMA4_ACCEL_CONFIG_ADDR UINT8_C(0X40) + +/**\name ACCEL RANGE ADDRESS*/ +#define BMA4_ACCEL_RANGE_ADDR UINT8_C(0X41) + +/**\name AUX CONFIG REGISTERS*/ +#define BMA4_AUX_CONFIG_ADDR UINT8_C(0X44) + +/**\name FIFO DOWN SAMPLING REGISTER ADDRESS FOR ACCEL*/ +#define BMA4_FIFO_DOWN_ADDR UINT8_C(0X45) + +/**\name FIFO WATERMARK REGISTER ADDRESS*/ +#define BMA4_FIFO_WTM_0_ADDR UINT8_C(0X46) + +/**\name FIFO CONFIG REGISTERS*/ +#define BMA4_FIFO_CONFIG_0_ADDR UINT8_C(0X48) +#define BMA4_FIFO_CONFIG_1_ADDR UINT8_C(0X49) + +/**\name MAG INTERFACE REGISTERS*/ +#define BMA4_AUX_DEV_ID_ADDR UINT8_C(0X4B) +#define BMA4_AUX_IF_CONF_ADDR UINT8_C(0X4C) +#define BMA4_AUX_RD_ADDR UINT8_C(0X4D) +#define BMA4_AUX_WR_ADDR UINT8_C(0X4E) +#define BMA4_AUX_WR_DATA_ADDR UINT8_C(0X4F) + +/**\name INTERRUPT ENABLE REGISTERS*/ +#define BMA4_INT1_IO_CTRL_ADDR UINT8_C(0X53) +#define BMA4_INT2_IO_CTRL_ADDR UINT8_C(0X54) + +/**\name LATCH DURATION REGISTERS*/ +#define BMA4_INTR_LATCH_ADDR UINT8_C(0X55) + +/**\name MAP INTERRUPT 1 and 2 REGISTERS*/ +#define BMA4_INT_MAP_1_ADDR UINT8_C(0X56) +#define BMA4_INT_MAP_2_ADDR UINT8_C(0X57) +#define BMA4_INT_MAP_DATA_ADDR UINT8_C(0x58) +#define BMA4_INIT_CTRL_ADDR UINT8_C(0x59) + +/**\name FEATURE CONFIG RELATED */ +#define BMA4_RESERVED_REG_5B_ADDR UINT8_C(0x5B) +#define BMA4_RESERVED_REG_5C_ADDR UINT8_C(0x5C) +#define BMA4_FEATURE_CONFIG_ADDR UINT8_C(0x5E) +#define BMA4_INTERNAL_ERROR UINT8_C(0x5F) + +/**\name SERIAL INTERFACE SETTINGS REGISTER*/ +#define BMA4_IF_CONFIG_ADDR UINT8_C(0X6B) + +/**\name SELF_TEST REGISTER*/ +#define BMA4_ACC_SELF_TEST_ADDR UINT8_C(0X6D) + +/**\name SPI,I2C SELECTION REGISTER*/ +#define BMA4_NV_CONFIG_ADDR UINT8_C(0x70) + +/**\name ACCEL OFFSET REGISTERS*/ +#define BMA4_OFFSET_0_ADDR UINT8_C(0X71) +#define BMA4_OFFSET_1_ADDR UINT8_C(0X72) +#define BMA4_OFFSET_2_ADDR UINT8_C(0X73) + +/**\name POWER_CTRL REGISTER*/ +#define BMA4_POWER_CONF_ADDR UINT8_C(0x7C) +#define BMA4_POWER_CTRL_ADDR UINT8_C(0x7D) + +/**\name COMMAND REGISTER*/ +#define BMA4_CMD_ADDR UINT8_C(0X7E) + +/**\name GPIO REGISTERS*/ +#define BMA4_STEP_CNT_OUT_0_ADDR UINT8_C(0x1E) +#define BMA4_HIGH_G_OUT_ADDR UINT8_C(0x1F) +#define BMA4_ACTIVITY_OUT_ADDR UINT8_C(0x27) +#define BMA4_ORIENTATION_OUT_ADDR UINT8_C(0x28) +#define BMA4_INTERNAL_STAT UINT8_C(0x2A) + +/*! + * @brief Block size for config write */ +#define BMA4_BLOCK_SIZE UINT8_C(32) + +/**\name I2C slave address */ +#define BMA4_I2C_ADDR_PRIMARY UINT8_C(0x18) +#define BMA4_I2C_ADDR_SECONDARY UINT8_C(0x19) +#define BMA4_I2C_BMM150_ADDR UINT8_C(0x10) + +/**\name Interface selection macro */ +#define BMA4_SPI_INTERFACE UINT8_C(1) +#define BMA4_I2C_INTERFACE UINT8_C(2) + +/**\name Interface selection macro */ +#define BMA4_SPI_WR_MASK UINT8_C(0x7F) +#define BMA4_SPI_RD_MASK UINT8_C(0x80) + +/**\name Chip ID macros */ +#define BMA4_CHIP_ID_MIN UINT8_C(0x10) +#define BMA4_CHIP_ID_MAX UINT8_C(0x15) + +/**\name Auxiliary sensor selection macro */ +#define BMM150_SENSOR UINT8_C(1) +#define AKM9916_SENSOR UINT8_C(2) +#define BMA4_ASIC_INITIALIZED UINT8_C(0x01) + +/**\name Auxiliary sensor chip id macros */ +#define BMM150_CHIP_ID UINT8_C(0x32) + +/**\name Auxiliary sensor other macros */ +#define BMM150_POWER_CONTROL_REG UINT8_C(0x4B) +#define BMM150_POWER_MODE_REG UINT8_C(0x4C) + +/**\name CONSTANTS */ +#define BMA4_FIFO_CONFIG_LENGTH UINT8_C(2) +#define BMA4_ACCEL_CONFIG_LENGTH UINT8_C(2) +#define BMA4_FIFO_WM_LENGTH UINT8_C(2) +#define BMA4_CONFIG_STREAM_SIZE UINT16_C(6144) +#define BMA4_NON_LATCH_MODE UINT8_C(0) +#define BMA4_LATCH_MODE UINT8_C(1) +#define BMA4_OPEN_DRAIN UINT8_C(1) +#define BMA4_PUSH_PULL UINT8_C(0) +#define BMA4_ACTIVE_HIGH UINT8_C(1) +#define BMA4_ACTIVE_LOW UINT8_C(0) +#define BMA4_EDGE_TRIGGER UINT8_C(1) +#define BMA4_LEVEL_TRIGGER UINT8_C(0) +#define BMA4_OUTPUT_ENABLE UINT8_C(1) +#define BMA4_OUTPUT_DISABLE UINT8_C(0) +#define BMA4_INPUT_ENABLE UINT8_C(1) +#define BMA4_INPUT_DISABLE UINT8_C(0) + +/**\name ACCEL RANGE CHECK*/ +#define BMA4_ACCEL_RANGE_2G UINT8_C(0) +#define BMA4_ACCEL_RANGE_4G UINT8_C(1) +#define BMA4_ACCEL_RANGE_8G UINT8_C(2) +#define BMA4_ACCEL_RANGE_16G UINT8_C(3) + +/**\name CONDITION CHECK FOR READING AND WRTING DATA*/ +#define BMA4_MAX_VALUE_FIFO_FILTER UINT8_C(1) +#define BMA4_MAX_VALUE_SPI3 UINT8_C(1) +#define BMA4_MAX_VALUE_SELFTEST_AMP UINT8_C(1) +#define BMA4_MAX_IF_MODE UINT8_C(3) +#define BMA4_MAX_VALUE_SELFTEST_SIGN UINT8_C(1) + +/**\name BUS READ AND WRITE LENGTH FOR MAG & ACCEL*/ +#define BMA4_MAG_TRIM_DATA_SIZE UINT8_C(16) +#define BMA4_MAG_XYZ_DATA_LENGTH UINT8_C(6) +#define BMA4_MAG_XYZR_DATA_LENGTH UINT8_C(8) +#define BMA4_ACCEL_DATA_LENGTH UINT8_C(6) +#define BMA4_FIFO_DATA_LENGTH UINT8_C(2) +#define BMA4_TEMP_DATA_SIZE UINT8_C(1) + +/**\name TEMPERATURE CONSTANT */ +#define BMA4_OFFSET_TEMP UINT8_C(23) +#define BMA4_DEG UINT8_C(1) +#define BMA4_FAHREN UINT8_C(2) +#define BMA4_KELVIN UINT8_C(3) + +/**\name DELAY DEFINITION IN MSEC*/ +#define BMA4_AUX_IF_DELAY UINT8_C(5) +#define BMA4_BMM150_WAKEUP_DELAY1 UINT8_C(2) +#define BMA4_BMM150_WAKEUP_DELAY2 UINT8_C(3) +#define BMA4_BMM150_WAKEUP_DELAY3 UINT8_C(1) +#define BMA4_GEN_READ_WRITE_DELAY UINT8_C(1) +#define BMA4_AUX_COM_DELAY UINT8_C(10) + +/**\name ARRAY PARAMETER DEFINITIONS*/ +#define BMA4_SENSOR_TIME_MSB_BYTE UINT8_C(2) +#define BMA4_SENSOR_TIME_XLSB_BYTE UINT8_C(1) +#define BMA4_SENSOR_TIME_LSB_BYTE UINT8_C(0) +#define BMA4_MAG_X_LSB_BYTE UINT8_C(0) +#define BMA4_MAG_X_MSB_BYTE UINT8_C(1) +#define BMA4_MAG_Y_LSB_BYTE UINT8_C(2) +#define BMA4_MAG_Y_MSB_BYTE UINT8_C(3) +#define BMA4_MAG_Z_LSB_BYTE UINT8_C(4) +#define BMA4_MAG_Z_MSB_BYTE UINT8_C(5) +#define BMA4_MAG_R_LSB_BYTE UINT8_C(6) +#define BMA4_MAG_R_MSB_BYTE UINT8_C(7) +#define BMA4_TEMP_BYTE UINT8_C(0) +#define BMA4_FIFO_LENGTH_MSB_BYTE UINT8_C(1) + +/**\name ERROR CODES */ +#define BMA4_OK UINT16_C(0) +#define BMA4_E_NULL_PTR UINT16_C(1) +#define BMA4_E_OUT_OF_RANGE UINT16_C(1 << 1) +#define BMA4_E_INVALID_SENSOR UINT16_C(1 << 2) +#define BMA4_E_CONFIG_STREAM_ERROR UINT16_C(1 << 3) +#define BMA4_E_SELF_TEST_FAIL UINT16_C(1 << 4) +#define BMA4_E_FOC_FAIL UINT16_C(1 << 5) +#define BMA4_E_FAIL UINT16_C(1 << 6) +#define BMA4_E_INT_LINE_INVALID UINT16_C(1 << 7) +#define BMA4_E_RD_WR_LENGTH_INVALID UINT16_C(1 << 8) +#define BMA4_E_AUX_CONFIG_FAIL UINT16_C(1 << 9) +#define BMA4_E_SC_FIFO_HEADER_ERR UINT16_C(1 << 10) +#define BMA4_E_SC_FIFO_CONFIG_ERR UINT16_C(1 << 11) + +/**\name UTILITY MACROS */ +#define BMA4_SET_LOW_BYTE UINT16_C(0x00FF) +#define BMA4_SET_HIGH_BYTE UINT16_C(0xFF00) +#define BMA4_SET_LOW_NIBBLE UINT8_C(0x0F) + +/**\name FOC RELATED MACROS */ +#define BMA4_ACCEL_CONFIG_FOC UINT8_C(0xB7) + +/* Macros used for Self test */ +/* Self-test: Resulting minimum difference signal in mg for BMA42x */ +#define BMA42X_ST_ACC_X_AXIS_SIGNAL_DIFF UINT16_C(400) +#define BMA42X_ST_ACC_Y_AXIS_SIGNAL_DIFF UINT16_C(800) +#define BMA42X_ST_ACC_Z_AXIS_SIGNAL_DIFF UINT16_C(400) + +/* Self-test: Resulting minimum difference signal in mg for BMA45x */ +#define BMA45X_ST_ACC_X_AXIS_SIGNAL_DIFF UINT16_C(1800) +#define BMA45X_ST_ACC_Y_AXIS_SIGNAL_DIFF UINT16_C(1800) +#define BMA45X_ST_ACC_Z_AXIS_SIGNAL_DIFF UINT16_C(1800) + +/**\name BOOLEAN TYPES*/ +#ifndef TRUE +#define TRUE UINT8_C(0x01) +#endif + +#ifndef FALSE +#define FALSE UINT8_C(0x00) +#endif + +#ifndef NULL +#define NULL UINT8_C(0x00) +#endif + +/**\name ERROR STATUS POSITION AND MASK*/ +#define BMA4_FATAL_ERR_MSK UINT8_C(0x01) +#define BMA4_CMD_ERR_POS UINT8_C(1) +#define BMA4_CMD_ERR_MSK UINT8_C(0x02) +#define BMA4_ERR_CODE_POS UINT8_C(2) +#define BMA4_ERR_CODE_MSK UINT8_C(0x1C) +#define BMA4_FIFO_ERR_POS UINT8_C(6) +#define BMA4_FIFO_ERR_MSK UINT8_C(0x40) +#define BMA4_AUX_ERR_POS UINT8_C(7) +#define BMA4_AUX_ERR_MSK UINT8_C(0x80) + +/**\name Maximum number of bytes to be read from the sensor */ +#define BMA4_MAX_BUFFER_SIZE UINT8_C(81) + +/**\name NV_CONFIG POSITION AND MASK*/ +/* NV_CONF Description - Reg Addr --> (0x70), Bit --> 3 */ +#define BMA4_NV_ACCEL_OFFSET_POS UINT8_C(3) +#define BMA4_NV_ACCEL_OFFSET_MSK UINT8_C(0x08) + +/**\name MAG DATA XYZ POSITION AND MASK*/ +#define BMA4_DATA_MAG_X_LSB_POS UINT8_C(3) +#define BMA4_DATA_MAG_X_LSB_MSK UINT8_C(0xF8) +#define BMA4_DATA_MAG_Y_LSB_POS UINT8_C(3) +#define BMA4_DATA_MAG_Y_LSB_MSK UINT8_C(0xF8) +#define BMA4_DATA_MAG_Z_LSB_POS UINT8_C(1) +#define BMA4_DATA_MAG_Z_LSB_MSK UINT8_C(0xFE) +#define BMA4_DATA_MAG_R_LSB_POS UINT8_C(2) +#define BMA4_DATA_MAG_R_LSB_MSK UINT8_C(0xFC) + +/**\name ACCEL DATA READY POSITION AND MASK*/ +#define BMA4_STAT_DATA_RDY_ACCEL_POS UINT8_C(7) +#define BMA4_STAT_DATA_RDY_ACCEL_MSK UINT8_C(0x80) + +/**\name MAG DATA READY POSITION AND MASK*/ +#define BMA4_STAT_DATA_RDY_MAG_POS UINT8_C(5) +#define BMA4_STAT_DATA_RDY_MAG_MSK UINT8_C(0x20) + +/**\name ADVANCE POWER SAVE POSITION AND MASK*/ +#define BMA4_ADVANCE_POWER_SAVE_MSK UINT8_C(0x01) + +/**\name ACCELEROMETER ENABLE POSITION AND MASK*/ +#define BMA4_ACCEL_ENABLE_POS UINT8_C(2) +#define BMA4_ACCEL_ENABLE_MSK UINT8_C(0x04) + +/**\name MAGNETOMETER ENABLE POSITION AND MASK*/ +#define BMA4_MAG_ENABLE_MSK UINT8_C(0x01) + +/**\name ACCEL CONFIGURATION POSITION AND MASK*/ +#define BMA4_ACCEL_ODR_MSK UINT8_C(0x0F) +#define BMA4_ACCEL_BW_POS UINT8_C(4) +#define BMA4_ACCEL_BW_MSK UINT8_C(0x70) +#define BMA4_ACCEL_RANGE_MSK UINT8_C(0x03) +#define BMA4_ACCEL_PERFMODE_POS UINT8_C(7) +#define BMA4_ACCEL_PERFMODE_MSK UINT8_C(0x80) + +/**\name MAG CONFIGURATION POSITION AND MASK*/ +#define BMA4_MAG_CONFIG_OFFSET_POS UINT8_C(4) +#define BMA4_MAG_CONFIG_OFFSET_LEN UINT8_C(4) +#define BMA4_MAG_CONFIG_OFFSET_MSK UINT8_C(0xF0) +#define BMA4_MAG_CONFIG_OFFSET_REG (BMA4_AUX_CONFIG_ADDR) + +/**\name FIFO SELF WAKE UP POSITION AND MASK*/ +#define BMA4_FIFO_SELF_WAKE_UP_POS UINT8_C(1) +#define BMA4_FIFO_SELF_WAKE_UP_MSK UINT8_C(0x02) + +/**\name FIFO BYTE COUNTER POSITION AND MASK*/ +#define BMA4_FIFO_BYTE_COUNTER_MSB_MSK UINT8_C(0x3F) + +/**\name FIFO DATA POSITION AND MASK*/ +#define BMA4_FIFO_DATA_POS UINT8_C(0) +#define BMA4_FIFO_DATA_MSK UINT8_C(0xFF) + +/**\name FIFO FILTER FOR ACCEL POSITION AND MASK*/ +#define BMA4_FIFO_DOWN_ACCEL_POS UINT8_C(4) +#define BMA4_FIFO_DOWN_ACCEL_MSK UINT8_C(0x70) +#define BMA4_FIFO_FILTER_ACCEL_POS UINT8_C(7) +#define BMA4_FIFO_FILTER_ACCEL_MSK UINT8_C(0x80) + +/**\name FIFO HEADER DATA DEFINITIONS */ +#define FIFO_HEAD_A UINT8_C(0x84) +#define FIFO_HEAD_M UINT8_C(0x90) +#define FIFO_HEAD_M_A UINT8_C(0x94) +#define FIFO_HEAD_SENSOR_TIME UINT8_C(0x44) +#define FIFO_HEAD_INPUT_CONFIG UINT8_C(0x48) +#define FIFO_HEAD_SKIP_FRAME UINT8_C(0x40) +#define FIFO_HEAD_OVER_READ_MSB UINT8_C(0x80) +#define FIFO_HEAD_SAMPLE_DROP UINT8_C(0x50) + +/**\name FIFO HEADERLESS MODE DATA ENABLE DEFINITIONS */ +#define BMA4_FIFO_M_A_ENABLE UINT8_C(0x60) +#define BMA4_FIFO_A_ENABLE UINT8_C(0x40) +#define BMA4_FIFO_M_ENABLE UINT8_C(0x20) + +/**\name FIFO CONFIGURATION SELECTION */ +#define BMA4_FIFO_STOP_ON_FULL UINT8_C(0x01) +#define BMA4_FIFO_TIME UINT8_C(0x02) +#define BMA4_FIFO_TAG_INTR2 UINT8_C(0x04) +#define BMA4_FIFO_TAG_INTR1 UINT8_C(0x08) +#define BMA4_FIFO_HEADER UINT8_C(0x10) +#define BMA4_FIFO_MAG UINT8_C(0x20) +#define BMA4_FIFO_ACCEL UINT8_C(0x40) +#define BMA4_FIFO_ALL UINT8_C(0x7F) +#define BMA4_FIFO_CONFIG_0_MASK UINT8_C(0x03) +#define BMA4_FIFO_CONFIG_1_MASK UINT8_C(0xFC) + +/**\name FIFO FRAME COUNT DEFINITION */ +#define FIFO_LSB_CONFIG_CHECK UINT8_C(0x00) +#define FIFO_MSB_CONFIG_CHECK UINT8_C(0x80) +#define BMA4_FIFO_TAG_INTR_MASK UINT8_C(0xFC) + +/**\name FIFO DROPPED FRAME DEFINITION */ +#define AUX_FIFO_DROP UINT8_C(0x04) +#define ACCEL_AUX_FIFO_DROP UINT8_C(0x05) +#define ACCEL_FIFO_DROP UINT8_C(0x01) + +/**\name FIFO MAG DEFINITION*/ +#define BMA4_MA_FIFO_A_X_LSB UINT8_C(8) + +/**\name FIFO sensor time length definitions*/ +#define BMA4_SENSOR_TIME_LENGTH UINT8_C(3) + +/**\name FIFO LENGTH DEFINITION*/ +#define BMA4_FIFO_A_LENGTH UINT8_C(6) +#define BMA4_FIFO_M_LENGTH UINT8_C(8) +#define BMA4_FIFO_MA_LENGTH UINT8_C(14) + +/**\name MAG I2C ADDRESS SELECTION POSITION AND MASK*/ +#define BMA4_I2C_DEVICE_ADDR_POS UINT8_C(1) +#define BMA4_I2C_DEVICE_ADDR_MSK UINT8_C(0xFE) + +/**\name MAG CONFIGURATION FOR SECONDARY INTERFACE POSITION AND MASK*/ +#define BMA4_MAG_BURST_MSK UINT8_C(0x03) +#define BMA4_MAG_MANUAL_ENABLE_POS UINT8_C(7) +#define BMA4_MAG_MANUAL_ENABLE_MSK UINT8_C(0x80) +#define BMA4_READ_ADDR_MSK UINT8_C(0xFF) +#define BMA4_WRITE_ADDR_MSK UINT8_C(0xFF) +#define BMA4_WRITE_DATA_MSK UINT8_C(0xFF) + +/**\name OUTPUT TYPE ENABLE POSITION AND MASK*/ +#define BMA4_INT_EDGE_CTRL_MASK UINT8_C(0x01) +#define BMA4_INT_EDGE_CTRL_POS UINT8_C(0x00) +#define BMA4_INT_LEVEL_MASK UINT8_C(0x02) +#define BMA4_INT_LEVEL_POS UINT8_C(0x01) +#define BMA4_INT_OPEN_DRAIN_MASK UINT8_C(0x04) +#define BMA4_INT_OPEN_DRAIN_POS UINT8_C(0x02) +#define BMA4_INT_OUTPUT_EN_MASK UINT8_C(0x08) +#define BMA4_INT_OUTPUT_EN_POS UINT8_C(0x03) +#define BMA4_INT_INPUT_EN_MASK UINT8_C(0x10) +#define BMA4_INT_INPUT_EN_POS UINT8_C(0x04) + +/**\name IF CONFIG POSITION AND MASK*/ +#define BMA4_CONFIG_SPI3_MSK UINT8_C(0x01) +#define BMA4_IF_CONFIG_IF_MODE_POS UINT8_C(4) +#define BMA4_IF_CONFIG_IF_MODE_MSK UINT8_C(0x10) + +/**\name ACCEL SELF TEST POSITION AND MASK*/ +#define BMA4_ACCEL_SELFTEST_ENABLE_MSK UINT8_C(0x01) +#define BMA4_ACCEL_SELFTEST_SIGN_POS UINT8_C(2) +#define BMA4_ACCEL_SELFTEST_SIGN_MSK UINT8_C(0x04) +#define BMA4_SELFTEST_AMP_POS UINT8_C(3) +#define BMA4_SELFTEST_AMP_MSK UINT8_C(0x08) + +/**\name ACCEL ODR */ +#define BMA4_OUTPUT_DATA_RATE_0_78HZ UINT8_C(0x01) +#define BMA4_OUTPUT_DATA_RATE_1_56HZ UINT8_C(0x02) +#define BMA4_OUTPUT_DATA_RATE_3_12HZ UINT8_C(0x03) +#define BMA4_OUTPUT_DATA_RATE_6_25HZ UINT8_C(0x04) +#define BMA4_OUTPUT_DATA_RATE_12_5HZ UINT8_C(0x05) +#define BMA4_OUTPUT_DATA_RATE_25HZ UINT8_C(0x06) +#define BMA4_OUTPUT_DATA_RATE_50HZ UINT8_C(0x07) +#define BMA4_OUTPUT_DATA_RATE_100HZ UINT8_C(0x08) +#define BMA4_OUTPUT_DATA_RATE_200HZ UINT8_C(0x09) +#define BMA4_OUTPUT_DATA_RATE_400HZ UINT8_C(0x0A) +#define BMA4_OUTPUT_DATA_RATE_800HZ UINT8_C(0x0B) +#define BMA4_OUTPUT_DATA_RATE_1600HZ UINT8_C(0x0C) + +/**\name ACCEL BANDWIDTH PARAMETER */ +#define BMA4_ACCEL_OSR4_AVG1 UINT8_C(0) +#define BMA4_ACCEL_OSR2_AVG2 UINT8_C(1) +#define BMA4_ACCEL_NORMAL_AVG4 UINT8_C(2) +#define BMA4_ACCEL_CIC_AVG8 UINT8_C(3) +#define BMA4_ACCEL_RES_AVG16 UINT8_C(4) +#define BMA4_ACCEL_RES_AVG32 UINT8_C(5) +#define BMA4_ACCEL_RES_AVG64 UINT8_C(6) +#define BMA4_ACCEL_RES_AVG128 UINT8_C(7) + +/**\name ACCEL PERFMODE PARAMETER */ +#define BMA4_CIC_AVG_MODE UINT8_C(0) +#define BMA4_CONTINUOUS_MODE UINT8_C(1) + +/**\name MAG OFFSET */ +#define BMA4_MAG_OFFSET_MAX UINT8_C(0x00) + +/**\name ENABLE/DISABLE SELECTIONS */ +#define BMA4_X_AXIS UINT8_C(0) +#define BMA4_Y_AXIS UINT8_C(1) +#define BMA4_Z_AXIS UINT8_C(2) + +/**\name SELF TEST*/ +#define BMA4_SELFTEST_PASS UINT8_C(0) +#define BMA4_SELFTEST_FAIL UINT8_C(1) + +/**\name INTERRUPT MAPS */ +#define BMA4_INTR1_MAP UINT8_C(0) +#define BMA4_INTR2_MAP UINT8_C(1) + +/**\name INTERRUPT MASKS */ +#define BMA4_FIFO_FULL_INT UINT16_C(0x0100) +#define BMA4_FIFO_WM_INT UINT16_C(0x0200) +#define BMA4_DATA_RDY_INT UINT16_C(0x0400) +#define BMA4_MAG_DATA_RDY_INT UINT16_C(0x2000) +#define BMA4_ACCEL_DATA_RDY_INT UINT16_C(0x8000) + + +/**\name AKM POWER MODE SELECTION */ +#define AKM_POWER_DOWN_MODE UINT8_C(0) +#define AKM_SINGLE_MEAS_MODE UINT8_C(1) + +/**\name SECONDARY_MAG POWER MODE SELECTION */ +#define BMA4_MAG_FORCE_MODE UINT8_C(0) +#define BMA4_MAG_SUSPEND_MODE UINT8_C(1) + +/**\name MAG POWER MODE SELECTION */ +#define FORCE_MODE UINT8_C(0) +#define SUSPEND_MODE UINT8_C(1) + +/**\name ACCEL POWER MODE */ +#define ACCEL_MODE_NORMAL UINT8_C(0x11) + +/**\name MAG POWER MODE */ +#define MAG_MODE_SUSPEND UINT8_C(0x18) + +/**\name ENABLE/DISABLE BIT VALUES */ +#define BMA4_ENABLE UINT8_C(0x01) +#define BMA4_DISABLE UINT8_C(0x00) + +/**\name DEFINITION USED FOR DIFFERENT WRITE */ +#define BMA4_MANUAL_DISABLE UINT8_C(0x00) +#define BMA4_MANUAL_ENABLE UINT8_C(0x01) +#define BMA4_ENABLE_MAG_IF_MODE UINT8_C(0x01) +#define BMA4_MAG_DATA_READ_REG UINT8_C(0x0A) +#define BMA4_BMM_POWER_MODE_REG UINT8_C(0x06) +#define BMA4_SEC_IF_NULL UINT8_C(0) +#define BMA4_SEC_IF_BMM150 UINT8_C(1) +#define BMA4_SEC_IF_AKM09916 UINT8_C(2) +#define BMA4_ENABLE_AUX_IF_MODE UINT8_C(0x01) + +/**\name SENSOR RESOLUTION */ +#define BMA4_12_BIT_RESOLUTION UINT8_C(12) +#define BMA4_14_BIT_RESOLUTION UINT8_C(14) +#define BMA4_16_BIT_RESOLUTION UINT8_C(16) + +/**\name MULTIPLIER */ +/*! for handling micro-g values */ +#define BMA4XY_MULTIPLIER UINT32_C(1000000) +/*! for handling float temperature values */ +#define BMA4_SCALE_TEMP INT32_C(1000) +/* BMA4_FAHREN_SCALED = 1.8 * 1000 */ +#define BMA4_FAHREN_SCALED INT32_C(1800) +/* BMA4_KELVIN_SCALED = 273.15 * 1000 */ +#define BMA4_KELVIN_SCALED INT32_C(273150) + + +/**\name MAP BURST READ LENGTHS */ +#define BMA4_AUX_READ_LEN_0 0 +#define BMA4_AUX_READ_LEN_1 1 +#define BMA4_AUX_READ_LEN_2 2 +#define BMA4_AUX_READ_LEN_3 3 + +#ifndef ABS +#define ABS(a) ((a) > 0 ? (a) : -(a)) /*!< Absolute value */ +#endif + +/**\name BIT SLICE GET AND SET FUNCTIONS */ +#define BMA4_GET_BITSLICE(regvar, bitname)\ + ((regvar & bitname##_MSK) >> bitname##_POS) +#define BMA4_SET_BITSLICE(regvar, bitname, val)\ + ((regvar & ~bitname##_MSK) | \ + ((val<> 8) + +#define BMA4_SET_BIT_VAL_0(reg_data, bitname) (reg_data & ~(bitname##_MSK)) + +#define BMA4_SET_BITS_POS_0(reg_data, bitname, data) \ + ((reg_data & ~(bitname##_MSK)) | \ + (data & bitname##_MSK)) + +#define BMA4_GET_BITS_POS_0(reg_data, bitname) (reg_data & (bitname##_MSK)) + +/**\name TYPEDEF DEFINITIONS */ +/*! + * @brief Bus communication function pointer which should be mapped to + * the platform specific read and write functions of the user + */ +typedef uint16_t (*bma4_com_fptr_t)(uint8_t dev_addr, uint8_t reg_addr, uint8_t *read_data, uint16_t len); + +/*! delay function pointer */ +typedef void (*bma4_delay_fptr_t)(uint32_t); + +/******************************************************************************/ +/*! @name Enum Declarations */ +/******************************************************************************/ + +/*! @name Enum to define BMA4 variants */ +enum bma4_variant { + BMA42X_VARIANT = 1, + BMA45X_VARIANT +}; + +/**\name STRUCTURE DEFINITIONS*/ + +/*! + * @brief + * This structure holds asic info. for feature configuration. + */ +struct bma4_asic_data { + /* Feature config start addr (0-3 bits)*/ + uint8_t asic_lsb; + /* Feature config start addr (4-11 bits)*/ + uint8_t asic_msb; +}; + +/*! + * @brief Auxiliary configuration structure for user settings + */ +struct bma4_aux_config { + /*! Device address of auxiliary sensor */ + uint8_t aux_dev_addr; + /*! To enable manual or auto mode */ + uint8_t manual_enable; + /*! No of bytes to be read at a time */ + uint8_t burst_read_length; + /*! Variable to set the auxiliary interface */ + uint8_t if_mode; +}; + +/*! + * @brief + * This structure holds all relevant information about BMA4 + */ +struct bma4_dev { + /*! Chip id of BMA4 */ + uint8_t chip_id; + /*! Chip id of auxiliary sensor */ + uint8_t aux_chip_id; + /*! Device address of BMA4 */ + uint8_t dev_addr; + /*! Interface detail */ + uint8_t interface; + /*! Auxiliary sensor information */ + uint8_t aux_sensor; + /*! Decide SPI or I2C read mechanism */ + uint8_t dummy_byte; + /*! Resolution for FOC */ + uint8_t resolution; + /*! Define the BMA4 variant BMA42X or BMA45X */ + enum bma4_variant variant; +/* ! Used to check mag manual/auto mode status + int8_t mag_manual_enable;*/ + /*! FIFO related configurations */ + struct bma4_fifo_frame *fifo; + /*! Config stream data buffer address will be assigned*/ + const uint8_t *config_file_ptr; + /*! Max read/write length (maximum supported length is 32). + To be set by the user */ + uint8_t read_write_len; + /*! Feature len */ + uint8_t feature_len; + /*! Contains asic information */ + struct bma4_asic_data asic_data; + /*! Contains aux configuration settings */ + struct bma4_aux_config aux_config; + /*! Bus read function pointer */ + bma4_com_fptr_t bus_read; + /*! Bus write function pointer */ + bma4_com_fptr_t bus_write; + /*! delay(in ms) function pointer */ + bma4_delay_fptr_t delay; +}; + +/*! + * @brief This structure holds the information for usage of + * FIFO by the user. + */ +struct bma4_fifo_frame { + /*! Data buffer of user defined length is to be mapped here */ + uint8_t *data; + /*! Number of bytes of FIFO to be read as specified by the user */ + uint16_t length; + /*! Enabling of the FIFO header to stream in header mode */ + uint8_t fifo_header_enable; + /*! Streaming of the Accelerometer, Auxiliary + * sensor data or both in FIFO */ + uint8_t fifo_data_enable; + /*! Will be equal to length when no more frames are there to parse */ + uint16_t accel_byte_start_idx; + /*! Will be equal to length when no more frames are there to parse */ + uint16_t mag_byte_start_idx; + /*! Will be equal to length when no more frames are there to parse */ + uint16_t sc_frame_byte_start_idx; + /*! Value of FIFO sensor time time */ + uint32_t sensor_time; + /*! Value of Skipped frame counts */ + uint8_t skipped_frame_count; + /*! Value of accel dropped frame count */ + uint8_t accel_dropped_frame_count; + /*! Value of mag dropped frame count */ + uint8_t mag_dropped_frame_count; +}; + +/*! + * @brief Error Status structure + */ +struct bma4_err_reg { + /*! Indicates fatal error */ + uint8_t fatal_err; + /*! Indicates command error */ + uint8_t cmd_err; + /*! Indicates error code */ + uint8_t err_code; + /*! Indicates fifo error */ + uint8_t fifo_err; + /*! Indicates mag error */ + uint8_t aux_err; +}; + +/*! + * @brief Asic Status structure + */ +struct bma4_asic_status { + /*! Asic is in sleep/halt state */ + uint8_t sleep; + /*! Dedicated interrupt is set again before previous interrupt + was acknowledged */ + uint8_t irq_ovrn; + /*! Watchcell event detected (asic stopped) */ + uint8_t wc_event; + /*! Stream transfer has started and transactions are ongoing */ + uint8_t stream_transfer_active; +}; + +/*! + * @brief Interrupt Pin Configuration structure + */ +struct bma4_int_pin_config { + /*! Trigger condition of interrupt pin */ + uint8_t edge_ctrl; + /*! Level of interrupt pin */ + uint8_t lvl; + /*! Behaviour of interrupt pin to open drain */ + uint8_t od; + /*! Output enable for interrupt pin */ + uint8_t output_en; + /*! Input enable for interrupt pin */ + uint8_t input_en; +}; + +/*! +* @brief Accelerometer configuration structure */ +struct bma4_accel_config { + /*! Output data rate in Hz */ + uint8_t odr; + /*! Bandwidth parameter, determines filter configuration */ + uint8_t bandwidth; + /*! Filter performance mode */ + uint8_t perf_mode; + /*! G-range */ + uint8_t range; +}; + +/*! + * @brief Auxiliary magnetometer configuration structure + */ +struct bma4_aux_mag_config { + /*! Poll rate for the sensor attached to the Magnetometer interface */ + uint8_t odr; + /*! Trigger-readout offset in units of 2.5 ms. + If set to zero, the offset is maximum, i.e. after readout a trigger + is issued immediately */ + uint8_t offset; +}; + +/*! + * @brief ASIC Config structure + */ +struct bma4_asic_config { + /*! Enable/Disable ASIC Wake Up */ + uint8_t asic_en; + /*! Configure stream_transfer/FIFO mode */ + uint8_t fifo_mode_en; + /*! Mapping of instance RAM1 */ + uint8_t mem_conf_ram1; + /*! Mapping of instance RAM2 */ + uint8_t mem_conf_ram2; + /*! Mapping of instance RAM3 */ + uint8_t mem_conf_ram3; +}; +/*! + * @brief bmm150 or akm09916 + * magnetometer values structure + */ +struct bma4_mag { + /*! BMM150 and AKM09916 X raw data */ + int32_t x; + /*! BMM150 and AKM09916 Y raw data */ + int32_t y; + /*! BMM150 and AKM09916 Z raw data */ + int32_t z; +}; + +/*! + * @brief bmm150 xyz data structure + */ +struct bma4_mag_xyzr { + /*! BMM150 X raw data */ + int16_t x; + /*! BMM150 Y raw data */ + int16_t y; + /*! BMM150 Z raw data */ + int16_t z; + /*! BMM150 R raw data */ + uint16_t r; +}; + +/*! + * @brief Accel xyz data structure + */ +struct bma4_accel { + /*! Accel X data */ + int16_t x; + /*! Accel Y data */ + int16_t y; + /*! Accel Z data */ + int16_t z; +}; + +/*! + * @brief FIFO mag data structure + */ +struct bma4_mag_fifo_data { + /*! The value of mag x LSB data */ + uint8_t mag_x_lsb; + /*! The value of mag x MSB data */ + uint8_t mag_x_msb; + /*! The value of mag y LSB data */ + uint8_t mag_y_lsb; + /*! The value of mag y MSB data */ + uint8_t mag_y_msb; + /*! The value of mag z LSB data */ + uint8_t mag_z_lsb; + /*! The value of mag z MSB data */ + uint8_t mag_z_msb; + /*! The value of mag r for BMM150 Y2 for YAMAHA LSB data */ + uint8_t mag_r_y2_lsb; + /*! The value of mag r for BMM150 Y2 for YAMAHA MSB data */ + uint8_t mag_r_y2_msb; +}; + +#endif +/* End of __BMA4_H__ */ diff --git a/lib/libesp32/TTGO_TWatch_Library/src/i2c_bus.cpp b/lib/libesp32_div/TTGO_TWatch_Library/src/i2c_bus.cpp old mode 100755 new mode 100644 similarity index 96% rename from lib/libesp32/TTGO_TWatch_Library/src/i2c_bus.cpp rename to lib/libesp32_div/TTGO_TWatch_Library/src/i2c_bus.cpp index d643098b0..27705b21d --- a/lib/libesp32/TTGO_TWatch_Library/src/i2c_bus.cpp +++ b/lib/libesp32_div/TTGO_TWatch_Library/src/i2c_bus.cpp @@ -1,94 +1,94 @@ -#include "i2c_bus.h" -#include "Wire.h" -#include - -void I2CBus::scan(void) -{ - uint8_t err, addr; - int nDevices = 0; - for (addr = 1; addr < 127; addr++) { - _port->beginTransmission(addr); - err = _port->endTransmission(); - if (err == 0) { - Serial.print("I2C device found at address 0x"); - if (addr < 16) - Serial.print("0"); - Serial.print(addr, HEX); - Serial.println(" !"); - nDevices++; - } else if (err == 4) { - Serial.print("Unknow error at address 0x"); - if (addr < 16) - Serial.print("0"); - Serial.println(addr, HEX); - } - } - if (nDevices == 0) - Serial.println("No I2C devices found\n"); - else - Serial.println("done\n"); -} - - -uint16_t I2CBus::readBytes(uint8_t addr, uint8_t *data, uint16_t len, uint16_t delay_ms) -{ - uint16_t ret = 0; - xSemaphoreTakeRecursive(_i2c_mux, portMAX_DELAY); - uint8_t cnt = _port->requestFrom(addr, (uint8_t)len, (uint8_t)1); - if (!cnt) { - ret = 1 << 13; - } - uint16_t index = 0; - while (_port->available()) { - if (index > len)return 1 << 14; - if (delay_ms)delay(delay_ms); - data[index++] = _port->read(); - } - xSemaphoreGiveRecursive(_i2c_mux); - return ret; -} - - -uint16_t I2CBus::readBytes(uint8_t addr, uint8_t reg, uint8_t *data, uint16_t len) -{ - uint16_t ret = 0; - xSemaphoreTakeRecursive(_i2c_mux, portMAX_DELAY); - _port->beginTransmission(addr); - _port->write(reg); - _port->endTransmission(false); - uint8_t cnt = _port->requestFrom(addr, (uint8_t)len, (uint8_t)1); - if (!cnt) { - ret = 1 << 13; - } - uint16_t index = 0; - while (_port->available()) { - if (index > len)return 1 << 14; - data[index++] = _port->read(); - } - xSemaphoreGiveRecursive(_i2c_mux); - return ret; -} - -uint16_t I2CBus::writeBytes(uint8_t addr, uint8_t reg, uint8_t *data, uint16_t len) -{ - uint16_t ret = 0; - xSemaphoreTakeRecursive(_i2c_mux, portMAX_DELAY); - _port->beginTransmission(addr); - _port->write(reg); - for (uint16_t i = 0; i < len; i++) { - _port->write(data[i]); - } - ret = _port->endTransmission(); - xSemaphoreGiveRecursive(_i2c_mux); - return ret ? 1 << 12 : ret; -} - -bool I2CBus::deviceProbe(uint8_t addr) -{ - uint16_t ret = 0; - xSemaphoreTakeRecursive(_i2c_mux, portMAX_DELAY); - _port->beginTransmission(addr); - ret = _port->endTransmission(); - xSemaphoreGiveRecursive(_i2c_mux); - return (ret == 0); +#include "i2c_bus.h" +#include "Wire.h" +#include + +void I2CBus::scan(void) +{ + uint8_t err, addr; + int nDevices = 0; + for (addr = 1; addr < 127; addr++) { + _port->beginTransmission(addr); + err = _port->endTransmission(); + if (err == 0) { + Serial.print("I2C device found at address 0x"); + if (addr < 16) + Serial.print("0"); + Serial.print(addr, HEX); + Serial.println(" !"); + nDevices++; + } else if (err == 4) { + Serial.print("Unknow error at address 0x"); + if (addr < 16) + Serial.print("0"); + Serial.println(addr, HEX); + } + } + if (nDevices == 0) + Serial.println("No I2C devices found\n"); + else + Serial.println("done\n"); +} + + +uint16_t I2CBus::readBytes(uint8_t addr, uint8_t *data, uint16_t len, uint16_t delay_ms) +{ + uint16_t ret = 0; + xSemaphoreTakeRecursive(_i2c_mux, portMAX_DELAY); + uint8_t cnt = _port->requestFrom(addr, (uint8_t)len, (uint8_t)1); + if (!cnt) { + ret = 1 << 13; + } + uint16_t index = 0; + while (_port->available()) { + if (index > len)return 1 << 14; + if (delay_ms)delay(delay_ms); + data[index++] = _port->read(); + } + xSemaphoreGiveRecursive(_i2c_mux); + return ret; +} + + +uint16_t I2CBus::readBytes(uint8_t addr, uint8_t reg, uint8_t *data, uint16_t len) +{ + uint16_t ret = 0; + xSemaphoreTakeRecursive(_i2c_mux, portMAX_DELAY); + _port->beginTransmission(addr); + _port->write(reg); + _port->endTransmission(false); + uint8_t cnt = _port->requestFrom(addr, (uint8_t)len, (uint8_t)1); + if (!cnt) { + ret = 1 << 13; + } + uint16_t index = 0; + while (_port->available()) { + if (index > len)return 1 << 14; + data[index++] = _port->read(); + } + xSemaphoreGiveRecursive(_i2c_mux); + return ret; +} + +uint16_t I2CBus::writeBytes(uint8_t addr, uint8_t reg, uint8_t *data, uint16_t len) +{ + uint16_t ret = 0; + xSemaphoreTakeRecursive(_i2c_mux, portMAX_DELAY); + _port->beginTransmission(addr); + _port->write(reg); + for (uint16_t i = 0; i < len; i++) { + _port->write(data[i]); + } + ret = _port->endTransmission(); + xSemaphoreGiveRecursive(_i2c_mux); + return ret ? 1 << 12 : ret; +} + +bool I2CBus::deviceProbe(uint8_t addr) +{ + uint16_t ret = 0; + xSemaphoreTakeRecursive(_i2c_mux, portMAX_DELAY); + _port->beginTransmission(addr); + ret = _port->endTransmission(); + xSemaphoreGiveRecursive(_i2c_mux); + return (ret == 0); } \ No newline at end of file diff --git a/lib/libesp32/TTGO_TWatch_Library/src/i2c_bus.h b/lib/libesp32_div/TTGO_TWatch_Library/src/i2c_bus.h old mode 100755 new mode 100644 similarity index 96% rename from lib/libesp32/TTGO_TWatch_Library/src/i2c_bus.h rename to lib/libesp32_div/TTGO_TWatch_Library/src/i2c_bus.h index b8d261758..92067e280 --- a/lib/libesp32/TTGO_TWatch_Library/src/i2c_bus.h +++ b/lib/libesp32_div/TTGO_TWatch_Library/src/i2c_bus.h @@ -1,26 +1,26 @@ -#ifndef TTGO_I2CBUF_H -#define TTGO_I2CBUF_H - -#include -#include "freertos/FreeRTOS.h" -#include "freertos/semphr.h" -class I2CBus -{ -public: - I2CBus(TwoWire &port = Wire, int sda = 21, int scl = 22) - { - _port = &port; - _port->begin(sda, scl); - _i2c_mux = xSemaphoreCreateRecursiveMutex(); - }; - void scan(); - uint16_t readBytes(uint8_t addr, uint8_t *data, uint16_t len, uint16_t delay_ms = 0); - uint16_t readBytes(uint8_t addr, uint8_t reg, uint8_t *data, uint16_t len); - uint16_t writeBytes(uint8_t addr, uint8_t reg, uint8_t *data, uint16_t len); - bool deviceProbe(uint8_t addr); -private: - TwoWire *_port; - SemaphoreHandle_t _i2c_mux = NULL; -}; - +#ifndef TTGO_I2CBUF_H +#define TTGO_I2CBUF_H + +#include +#include "freertos/FreeRTOS.h" +#include "freertos/semphr.h" +class I2CBus +{ +public: + I2CBus(TwoWire &port = Wire, int sda = 21, int scl = 22) + { + _port = &port; + _port->begin(sda, scl); + _i2c_mux = xSemaphoreCreateRecursiveMutex(); + }; + void scan(); + uint16_t readBytes(uint8_t addr, uint8_t *data, uint16_t len, uint16_t delay_ms = 0); + uint16_t readBytes(uint8_t addr, uint8_t reg, uint8_t *data, uint16_t len); + uint16_t writeBytes(uint8_t addr, uint8_t reg, uint8_t *data, uint16_t len); + bool deviceProbe(uint8_t addr); +private: + TwoWire *_port; + SemaphoreHandle_t _i2c_mux = NULL; +}; + #endif \ No newline at end of file diff --git a/platformio_override_sample.ini b/platformio_override_sample.ini index 3b7ff4d7a..e8e6e089f 100644 --- a/platformio_override_sample.ini +++ b/platformio_override_sample.ini @@ -121,6 +121,8 @@ upload_port = COM4 lib_extra_dirs = ${library.lib_extra_dirs} ; *** ESP32 lib. ALWAYS needed for ESP32 !!! lib/libesp32 +; *** uncomment the following line if you want to use Bluetooth or Apple Homekit in a Tasmota32 build +; lib/libesp32_div [core32] ; Activate Stage Core32 by removing ";" in next 3 lines, if you want to override the standard core32 diff --git a/platformio_tasmota32.ini b/platformio_tasmota32.ini index caa655c4f..0c5320620 100644 --- a/platformio_tasmota32.ini +++ b/platformio_tasmota32.ini @@ -66,6 +66,8 @@ lib_compat_mode = ${common.lib_compat_mode} shared_libdeps_dir = lib lib_extra_dirs = lib/libesp32 +; uncomment the following line if you need Bluetooth, Homekit or TTGO Watch libraries in your Tasmota32 build +; lib/libesp32_div lib/lib_basic lib/lib_i2c lib/lib_display diff --git a/platformio_tasmota_env32.ini b/platformio_tasmota_env32.ini index 2324a9dd5..fe2382b82 100644 --- a/platformio_tasmota_env32.ini +++ b/platformio_tasmota_env32.ini @@ -34,7 +34,9 @@ lib_ignore = extends = env:tasmota32 board = esp32cam board_build.f_cpu = 240000000L -build_flags = ${common32.build_flags} -DFIRMWARE_WEBCAM +board_build.flash_mode = qio +board_build.f_flash = 80000000L +build_flags = ${common32.build_flags} -DBOARD_HAS_PSRAM -mfix-esp32-psram-cache-issue -lc-psram-workaround -lm-psram-workaround -DFIRMWARE_WEBCAM lib_extra_dirs = lib/libesp32, lib/lib_basic [env:tasmota32-odroidgo] @@ -45,7 +47,7 @@ board_build.flash_mode = qio board_build.f_flash = 80000000L upload_speed = 2000000 board_build.partitions = esp32_partition_app1984k_spiffs12M.csv -build_flags = ${common32.build_flags} -DBOARD_HAS_PSRAM -mfix-esp32-psram-cache-issue -DFIRMWARE_ODROID_GO +build_flags = ${common32.build_flags} -DBOARD_HAS_PSRAM -mfix-esp32-psram-cache-issue -lc-psram-workaround -lm-psram-workaround -DFIRMWARE_ODROID_GO lib_extra_dirs = lib/libesp32, lib/lib_basic, lib/lib_i2c, lib/lib_rf, lib/lib_div, lib/lib_ssl, lib/lib_display [env:tasmota32-core2] @@ -56,13 +58,13 @@ board_build.flash_mode = qio board_build.f_flash = 80000000L upload_speed = 2000000 board_build.partitions = esp32_partition_app1984k_spiffs12M.csv -build_flags = ${common32.build_flags} -DBOARD_HAS_PSRAM -mfix-esp32-psram-cache-issue -DFIRMWARE_M5STACK_CORE2 +build_flags = ${common32.build_flags} -DBOARD_HAS_PSRAM -mfix-esp32-psram-cache-issue -lc-psram-workaround -lm-psram-workaround -DFIRMWARE_M5STACK_CORE2 lib_extra_dirs = lib/libesp32, lib/lib_basic, lib/lib_i2c, lib/lib_rf, lib/lib_div, lib/lib_ssl, lib/lib_display, lib/lib_audio [env:tasmota32-bluetooth] extends = env:tasmota32 build_flags = ${common32.build_flags} -DFIRMWARE_BLUETOOTH -lib_extra_dirs = lib/libesp32, lib/lib_basic, lib/lib_i2c, lib/lib_ssl +lib_extra_dirs = lib/libesp32, lib/libesp32_div, lib/lib_basic, lib/lib_i2c, lib/lib_ssl [env:tasmota32-lite] extends = env:tasmota32 diff --git a/tasmota/homekit.c b/tasmota/homekit.c new file mode 100755 index 000000000..f8bb77e22 --- /dev/null +++ b/tasmota/homekit.c @@ -0,0 +1,601 @@ +/* + * ESPRESSIF MIT License + * + * Copyright (c) 2018 + * + * Permission is hereby granted for use on ESPRESSIF SYSTEMS products only, in which case, + * it is 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. + * + */ +/* HomeKit Smart Outlet Example +*/ + +#ifdef USE_HOMEKIT +#ifdef ESP32 + +#include +#include +#include +#include +#include +#include +#include +#include + + +#include + +#include +#include +#include + +//#include +//#include + +static const char *TAG = "HAP outlet"; +char *hk_desc; +char hk_code[12]; + +extern void Ext_Replace_Cmd_Vars(char *srcbuf, uint32_t srcsize, char *dstbuf, uint32_t dstsize); +extern uint32_t Ext_UpdVar(char *vname, float *fvar, uint32_t mode); + +#define MAX_HAP_DEFS 16 +struct HAP_DESC { + char hap_name[16]; + char var_name[16]; + char var2_name[16]; + char var3_name[16]; + char var4_name[16]; + uint8_t hap_cid; + uint8_t type; + hap_acc_t *accessory; + hap_serv_t *service; +} hap_devs[MAX_HAP_DEFS]; + +#define HK_SRCBSIZE 256 + + +#define SMART_OUTLET_TASK_PRIORITY 1 +#define SMART_OUTLET_TASK_STACKSIZE 4 * 1024 +#define SMART_OUTLET_TASK_NAME "hap_outlet" + +//#define OUTLET_IN_USE_GPIO GPIO_NUM_0 +#define OUTLET_IN_USE_GPIO -1 + +#define ESP_INTR_FLAG_DEFAULT 0 + +static xQueueHandle s_esp_evt_queue = NULL; +/** + * @brief the recover outlet in use gpio interrupt function + */ +static void IRAM_ATTR outlet_in_use_isr(void* arg) +{ + uint32_t gpio_num = (uint32_t) arg; + xQueueSendFromISR(s_esp_evt_queue, &gpio_num, NULL); +} + +/** + * Enable a GPIO Pin for Outlet in Use Detection + */ +static void outlet_in_use_key_init(uint32_t key_gpio_pin) +{ + gpio_config_t io_conf; + /* Interrupt for both the edges */ + io_conf.intr_type = GPIO_INTR_ANYEDGE; + /* Bit mask of the pins */ + io_conf.pin_bit_mask = 1 << key_gpio_pin; + /* Set as input mode */ + io_conf.mode = GPIO_MODE_INPUT; + /* Enable internal pull-up */ + io_conf.pull_up_en = 1; + /* Disable internal pull-down */ + io_conf.pull_down_en = 0; + /* Set the GPIO configuration */ + gpio_config(&io_conf); + + /* Install gpio isr service */ + gpio_install_isr_service(ESP_INTR_FLAG_DEFAULT); + /* Hook isr handler for specified gpio pin */ + gpio_isr_handler_add(key_gpio_pin, outlet_in_use_isr, (void*)key_gpio_pin); +} + +/** + * Initialize the Smart Outlet Hardware.Here, we just enebale the Outlet-In-Use detection. + */ +void smart_outlet_hardware_init(int32_t gpio_num) { + s_esp_evt_queue = xQueueCreate(2, sizeof(uint32_t)); + + if (gpio_num < 0) return; + + if (s_esp_evt_queue != NULL) { + outlet_in_use_key_init(gpio_num); + } +} + + +static int bridge_identify(hap_acc_t *ha) +{ + ESP_LOGI(TAG, "Bridge identified"); + return HAP_SUCCESS; +} + +static int accessory_identify(hap_acc_t *ha) +{ + hap_serv_t *hs = hap_acc_get_serv_by_uuid(ha, HAP_SERV_UUID_ACCESSORY_INFORMATION); + hap_char_t *hc = hap_serv_get_char_by_uuid(hs, HAP_CHAR_UUID_NAME); + const hap_val_t *val = hap_char_get_val(hc); + char *name = val->s; + + ESP_LOGI(TAG, "Bridged Accessory %s identified", name); + return HAP_SUCCESS; +} + +/* A dummy callback for handling a write on the "On" characteristic of Outlet. + * In an actual accessory, this should control the hardware + */ +static int sensor_write(hap_write_data_t write_data[], int count, void *serv_priv, void *write_priv, uint32_t index) { + int i, ret = HAP_SUCCESS; + hap_write_data_t *write; + for (i = 0; i < count; i++) { + write = &write_data[i]; + const char *hcp = hap_char_get_type_uuid(write->hc); + if (!strcmp(hcp, HAP_CHAR_UUID_ON)) { + //ESP_LOGI(TAG, "Received Write. Outlet %s", write->val.b ? "On" : "Off"); + ESP_LOG_LEVEL(ESP_LOG_INFO, TAG, "Received Write. Outlet %s", write->val.b ? "On" : "Off"); + hap_char_update_val(write->hc, &(write->val)); + float fvar = write->val.b; + Ext_UpdVar(hap_devs[index].var_name, &fvar, 1); + *(write->status) = HAP_STATUS_SUCCESS; + } else if (!strcmp(hcp, HAP_CHAR_UUID_HUE)) { + hap_char_update_val(write->hc, &(write->val)); + float fvar = write->val.f; + Ext_UpdVar(hap_devs[index].var2_name, &fvar, 1); + *(write->status) = HAP_STATUS_SUCCESS; + } else if (!strcmp(hcp, HAP_CHAR_UUID_SATURATION)) { + hap_char_update_val(write->hc, &(write->val)); + float fvar = write->val.f; + Ext_UpdVar(hap_devs[index].var3_name, &fvar, 1); + *(write->status) = HAP_STATUS_SUCCESS; + } else if (!strcmp(hcp, HAP_CHAR_UUID_BRIGHTNESS)) { + hap_char_update_val(write->hc, &(write->val)); + float fvar = write->val.u; + Ext_UpdVar(hap_devs[index].var4_name, &fvar, 1); + *(write->status) = HAP_STATUS_SUCCESS; + } else { + *(write->status) = HAP_STATUS_RES_ABSENT; + } + } + return ret; +} + + +// common read routine +static int sensor_read(hap_char_t *hc, hap_status_t *status_code, void *serv_priv, void *read_priv, uint32_t index) { + hap_val_t new_val; + float fvar = 0; + + if (hap_req_get_ctrl_id(read_priv)) { + ESP_LOGI(TAG, "Received read from %s", hap_req_get_ctrl_id(read_priv)); + } + + const char *hcp = hap_char_get_type_uuid(hc); + + if (!strcmp(hcp, HAP_CHAR_UUID_CURRENT_TEMPERATURE) + || !strcmp(hcp, HAP_CHAR_UUID_CURRENT_RELATIVE_HUMIDITY) + || !strcmp(hcp, HAP_CHAR_UUID_CURRENT_AMBIENT_LIGHT_LEVEL) + ) { + + Ext_UpdVar(hap_devs[index].var_name, &fvar, 0); + new_val.f = fvar; + hap_char_update_val(hc, &new_val); + *status_code = HAP_STATUS_SUCCESS; + } + if (!strcmp(hcp, HAP_CHAR_UUID_ON)) { + Ext_UpdVar(hap_devs[index].var_name, &fvar, 0); + new_val.b = fvar; + hap_char_update_val(hc, &new_val); + *status_code = HAP_STATUS_SUCCESS; + } + if (!strcmp(hcp, HAP_CHAR_UUID_HUE)) { + Ext_UpdVar(hap_devs[index].var2_name, &fvar, 0); + new_val.f = fvar; + hap_char_update_val(hc, &new_val); + *status_code = HAP_STATUS_SUCCESS; + } + if (!strcmp(hcp, HAP_CHAR_UUID_SATURATION)) { + Ext_UpdVar(hap_devs[index].var3_name, &fvar, 0); + new_val.f = fvar; + hap_char_update_val(hc, &new_val); + *status_code = HAP_STATUS_SUCCESS; + } + if (!strcmp(hcp, HAP_CHAR_UUID_BRIGHTNESS)) { + Ext_UpdVar(hap_devs[index].var4_name, &fvar, 0); + new_val.u = fvar; + hap_char_update_val(hc, &new_val); + *status_code = HAP_STATUS_SUCCESS; + } + return HAP_SUCCESS; +} + +#define HAP_READ hap_char_t *hc, hap_status_t *status_code, void *serv_priv, void *read_priv) { return sensor_read(hc, status_code, serv_priv, read_priv + +static int sensor_read1(HAP_READ, 0);} +static int sensor_read2(HAP_READ, 1);} +static int sensor_read3(HAP_READ, 2);} +static int sensor_read4(HAP_READ, 3);} +static int sensor_read5(HAP_READ, 4);} +static int sensor_read6(HAP_READ, 5);} +static int sensor_read7(HAP_READ, 6);} +static int sensor_read8(HAP_READ, 7);} +static int sensor_read9(HAP_READ, 8);} +static int sensor_read10(HAP_READ, 9);} +static int sensor_read11(HAP_READ, 10);} +static int sensor_read12(HAP_READ, 11);} +static int sensor_read13(HAP_READ, 12);} +static int sensor_read14(HAP_READ, 13);} +static int sensor_read15(HAP_READ, 14);} +static int sensor_read16(HAP_READ, 15);} + +void hap_set_read(hap_serv_t *service, uint32_t index) { + switch (index) { + case 0: hap_serv_set_read_cb(service, sensor_read1);break; + case 1: hap_serv_set_read_cb(service, sensor_read2);break; + case 2: hap_serv_set_read_cb(service, sensor_read3);break; + case 3: hap_serv_set_read_cb(service, sensor_read4);break; + case 4: hap_serv_set_read_cb(service, sensor_read5);break; + case 5: hap_serv_set_read_cb(service, sensor_read6);break; + case 6: hap_serv_set_read_cb(service, sensor_read7);break; + case 7: hap_serv_set_read_cb(service, sensor_read8);break; + case 8: hap_serv_set_read_cb(service, sensor_read9);break; + case 9: hap_serv_set_read_cb(service, sensor_read10);break; + case 10: hap_serv_set_read_cb(service, sensor_read11);break; + case 11: hap_serv_set_read_cb(service, sensor_read12);break; + case 12: hap_serv_set_read_cb(service, sensor_read13);break; + case 13: hap_serv_set_read_cb(service, sensor_read14);break; + case 14: hap_serv_set_read_cb(service, sensor_read15);break; + case 15: hap_serv_set_read_cb(service, sensor_read16);break; + } +} + + +#define HAP_WRITE hap_write_data_t write_data[], int count, void *serv_priv, void *write_priv) { return sensor_write(write_data, count, serv_priv, write_priv + +static int sensor_write1(HAP_WRITE, 0);} +static int sensor_write2(HAP_WRITE, 1);} +static int sensor_write3(HAP_WRITE, 2);} +static int sensor_write4(HAP_WRITE, 3);} +static int sensor_write5(HAP_WRITE, 4);} +static int sensor_write6(HAP_WRITE, 5);} +static int sensor_write7(HAP_WRITE, 6);} +static int sensor_write8(HAP_WRITE, 7);} +static int sensor_write9(HAP_WRITE, 8);} +static int sensor_write10(HAP_WRITE, 9);} +static int sensor_write11(HAP_WRITE, 10);} +static int sensor_write12(HAP_WRITE, 11);} +static int sensor_write13(HAP_WRITE, 12);} +static int sensor_write14(HAP_WRITE, 13);} +static int sensor_write15(HAP_WRITE, 14);} +static int sensor_write16(HAP_WRITE, 15);} + + +void hap_set_write(hap_serv_t *service, uint32_t index) { + switch (index) { + case 0: hap_serv_set_write_cb(service, sensor_write1);break; + case 1: hap_serv_set_write_cb(service, sensor_write2);break; + case 2: hap_serv_set_write_cb(service, sensor_write3);break; + case 3: hap_serv_set_write_cb(service, sensor_write4);break; + case 4: hap_serv_set_write_cb(service, sensor_write5);break; + case 5: hap_serv_set_write_cb(service, sensor_write6);break; + case 6: hap_serv_set_write_cb(service, sensor_write7);break; + case 7: hap_serv_set_write_cb(service, sensor_write8);break; + case 8: hap_serv_set_write_cb(service, sensor_write9);break; + case 9: hap_serv_set_write_cb(service, sensor_write10);break; + case 10: hap_serv_set_write_cb(service, sensor_write11);break; + case 11: hap_serv_set_write_cb(service, sensor_write12);break; + case 12: hap_serv_set_write_cb(service, sensor_write13);break; + case 13: hap_serv_set_write_cb(service, sensor_write14);break; + case 14: hap_serv_set_write_cb(service, sensor_write15);break; + case 15: hap_serv_set_write_cb(service, sensor_write16);break; + } +} + + +uint32_t HK_getlinelen(char *lp) { +uint32_t cnt; + for (cnt=0; cnt= 0) { + hap_val_t appliance_value = { + .b = true, + }; + + /* Listen for Outlet-In-Use state change events. Other read/write functionality will be handled + * by the HAP Core. + * When the Outlet in Use GPIO goes low, it means Outlet is not in use. + * When the Outlet in Use GPIO goes high, it means Outlet is in use. + * Applications can define own logic as per their hardware. + */ + while (1) { + if (xQueueReceive(s_esp_evt_queue, &io_num, portMAX_DELAY) == pdFALSE) { + ESP_LOGI(TAG, "Outlet-In-Use trigger FAIL"); + } else { + appliance_value.b = gpio_get_level(io_num); + /* If any state change is detected, update the Outlet In Use characteristic value */ + hap_char_update_val(outlet_in_use, &appliance_value); + ESP_LOGI(TAG, "Outlet-In-Use triggered [%d]", appliance_value.b); + } + } + } else { + while (1) { + } + } +} + + +#define HK_MAXSIZE 1024 + +void homekit_main(char *desc) { + if (desc) { + char *cp = desc; + cp += 2; + while (*cp == ' ') cp++; + // "111-11-111" + uint32_t cnt; + for (cnt = 0; cnt < 10; cnt++) { + hk_code[cnt] = *cp++; + } + hk_code[cnt] = 0; + if (*cp != '\n') { + printf("init error\n"); + return; + } + cp++; + hk_desc = cp; + } else { + hap_platfrom_keystore_erase_partition("nvs"); + return; + } + + if (!hk_desc) return; + + /* Create the application thread */ + xTaskCreate(smart_outlet_thread_entry, SMART_OUTLET_TASK_NAME, SMART_OUTLET_TASK_STACKSIZE, NULL, SMART_OUTLET_TASK_PRIORITY, NULL); +} + +#endif // ESP32 +#endif // USE_HOMEKIT \ No newline at end of file diff --git a/tasmota/i18n.h b/tasmota/i18n.h index 2a4000d98..061b240b4 100644 --- a/tasmota/i18n.h +++ b/tasmota/i18n.h @@ -330,7 +330,7 @@ #define D_CMND_DEVGROUP_SEND "DevGroupSend" #define D_CMND_DEVGROUP_SHARE "DevGroupShare" #define D_CMND_DEVGROUPSTATUS "DevGroupStatus" -#define D_CMND_DEVGROUP_DEVICE "DevGroupTie" +#define D_CMND_DEVGROUP_TIE "DevGroupTie" #define D_CMND_SERIALSEND "SerialSend" #define D_CMND_SERIALDELIMITER "SerialDelimiter" #define D_CMND_BAUDRATE "Baudrate" diff --git a/tasmota/my_user_config.h b/tasmota/my_user_config.h index a89fd65eb..3275e76cf 100644 --- a/tasmota/my_user_config.h +++ b/tasmota/my_user_config.h @@ -494,7 +494,9 @@ // -- Optional light modules ---------------------- #define USE_WS2812 // WS2812 Led string using library NeoPixelBus (+5k code, +1k mem, 232 iram) - Disable by // -// #define USE_WS2812_DMA // DMA supports only GPIO03 (= Serial RXD) (+1k mem). When USE_WS2812_DMA is enabled expect Exceptions on Pow +// #define USE_WS2812_DMA // ESP8266 only, DMA supports only GPIO03 (= Serial RXD) (+1k mem). When USE_WS2812_DMA is enabled expect Exceptions on Pow + #define USE_WS2812_RMT 0 // ESP32 only, hardware RMT support (default). Specify the RMT channel 0..7. This should be preferred to software bit bang. +// #define USE_WS2812_I2S 0 // ESP32 only, hardware I2S support. Specify the I2S channel 0..2. This is exclusive from RMT. By default, prefer RMT support // #define USE_WS2812_INVERTED // Use inverted data signal #define USE_WS2812_HARDWARE NEO_HW_WS2812 // Hardware type (NEO_HW_WS2812, NEO_HW_WS2812X, NEO_HW_WS2813, NEO_HW_SK6812, NEO_HW_LC8812, NEO_HW_APA106, NEO_HW_P9813) #define USE_WS2812_CTYPE NEO_GRB // Color type (NEO_RGB, NEO_GRB, NEO_BRG, NEO_RBG, NEO_RGBW, NEO_GRBW) diff --git a/tasmota/settings.h b/tasmota/settings.h index c4c1d0467..25b0145da 100644 --- a/tasmota/settings.h +++ b/tasmota/settings.h @@ -148,7 +148,7 @@ typedef union { // Restricted by MISRA-C Rule 18.4 bu uint32_t zb_topic_endpoint : 1; // bit 6 (v9.2.0.4) - SetOption120 - (Zigbee) Append endpoint number to topic if device dependent (use with SetOption89) uint32_t mqtt_state_retain : 1; // bit 7 (v9.3.0.1) - CMND_STATERETAIN uint32_t mqtt_info_retain : 1; // bit 8 (v9.3.0.1) - CMND_INFORETAIN - uint32_t spare09 : 1; // bit 9 + uint32_t wiegand_hex_output : 1; // bit 9 (v9.3.1.1) - SetOption123 - (Wiegand) switch tag number output to hex format (1) uint32_t spare10 : 1; // bit 10 uint32_t spare11 : 1; // bit 11 uint32_t spare12 : 1; // bit 12 diff --git a/tasmota/settings.ino b/tasmota/settings.ino index db0b620fc..c1996da99 100644 --- a/tasmota/settings.ino +++ b/tasmota/settings.ino @@ -999,6 +999,9 @@ void SettingsDefaultSet2(void) { Settings.dimmer_step = DEFAULT_DIMMER_STEP; + // Device Groups + *(uint32_t *)&Settings.device_group_tie = 0x04030201; + // Display // Settings.display_model = 0; Settings.display_mode = 1; diff --git a/tasmota/support.ino b/tasmota/support.ino index d5ba2d914..85e1a7341 100644 --- a/tasmota/support.ino +++ b/tasmota/support.ino @@ -1969,7 +1969,8 @@ int8_t I2cWriteBuffer(uint8_t addr, uint8_t reg, uint8_t *reg_data, uint16_t len return 0; } -void I2cScan(char *devs, unsigned int devs_len) +void I2cScan(char *devs, unsigned int devs_len, uint32_t bus = 0); +void I2cScan(char *devs, unsigned int devs_len, uint32_t bus) { // Return error codes defined in twi.h and core_esp8266_si2c.c // I2C_OK 0 @@ -1984,8 +1985,13 @@ void I2cScan(char *devs, unsigned int devs_len) snprintf_P(devs, devs_len, PSTR("{\"" D_CMND_I2CSCAN "\":\"" D_JSON_I2CSCAN_DEVICES_FOUND_AT)); for (address = 1; address <= 127; address++) { - Wire.beginTransmission(address); - error = Wire.endTransmission(); +#ifdef ESP32 + TwoWire & myWire = (bus == 0) ? Wire : Wire1; +#else + TwoWire & myWire = Wire; +#endif + myWire.beginTransmission(address); + error = myWire.endTransmission(); if (0 == error) { any = 1; snprintf_P(devs, devs_len, PSTR("%s 0x%02x"), devs, address); diff --git a/tasmota/support_command.ino b/tasmota/support_command.ino index 1a16279ad..de6879f16 100644 --- a/tasmota/support_command.ino +++ b/tasmota/support_command.ino @@ -36,7 +36,7 @@ const char kTasmotaCommands[] PROGMEM = "|" // No prefix #ifdef USE_DEVICE_GROUPS_SEND D_CMND_DEVGROUP_SEND "|" #endif // USE_DEVICE_GROUPS_SEND - D_CMND_DEVGROUP_SHARE "|" D_CMND_DEVGROUPSTATUS "|" D_CMND_DEVGROUP_DEVICE "|" + D_CMND_DEVGROUP_SHARE "|" D_CMND_DEVGROUPSTATUS "|" D_CMND_DEVGROUP_TIE "|" #endif // USE_DEVICE_GROUPS D_CMND_SENSOR "|" D_CMND_DRIVER #ifdef ESP32 @@ -2071,9 +2071,14 @@ void CmndWifiPower(void) #ifdef USE_I2C void CmndI2cScan(void) { - if (TasmotaGlobal.i2c_enabled) { + if ((1 == XdrvMailbox.index) && (TasmotaGlobal.i2c_enabled)) { I2cScan(TasmotaGlobal.mqtt_data, sizeof(TasmotaGlobal.mqtt_data)); } +#ifdef ESP32 + if ((2 == XdrvMailbox.index) && (TasmotaGlobal.i2c_enabled_2)) { + I2cScan(TasmotaGlobal.mqtt_data, sizeof(TasmotaGlobal.mqtt_data), 1); + } +#endif } void CmndI2cDriver(void) @@ -2138,7 +2143,13 @@ void CmndDevGroupTie(void) if (XdrvMailbox.data_len > 0) { Settings.device_group_tie[XdrvMailbox.index - 1] = XdrvMailbox.payload; } - ResponseCmndIdxNumber(Settings.device_group_tie[XdrvMailbox.index - 1]); + char * ptr = TasmotaGlobal.mqtt_data; + *ptr++ = '{'; + for (uint32_t i = 0; i < MAX_DEV_GROUP_NAMES; i++) { + ptr += sprintf(ptr, PSTR("\"%s%u\":%u,"), D_CMND_DEVGROUP_TIE, i + 1, Settings.device_group_tie[i]); + } + *(ptr - 1) = '}'; + *ptr = 0; } } #endif // USE_DEVICE_GROUPS diff --git a/tasmota/support_tasmota.ino b/tasmota/support_tasmota.ino index 9604be4ee..4c20486b2 100644 --- a/tasmota/support_tasmota.ino +++ b/tasmota/support_tasmota.ino @@ -1742,6 +1742,12 @@ void GpioInit(void) if (TasmotaGlobal.i2c_enabled) { Wire.begin(Pin(GPIO_I2C_SDA), Pin(GPIO_I2C_SCL)); } +#ifdef ESP32 + TasmotaGlobal.i2c_enabled_2 = (PinUsed(GPIO_I2C_SCL, 1) && PinUsed(GPIO_I2C_SDA, 1)); + if (TasmotaGlobal.i2c_enabled_2) { + Wire1.begin(Pin(GPIO_I2C_SDA, 1), Pin(GPIO_I2C_SCL, 1)); + } +#endif #endif // USE_I2C TasmotaGlobal.devices_present = 0; diff --git a/tasmota/tasmota.h b/tasmota/tasmota.h index 5f2f73c0b..87e5f01b3 100644 --- a/tasmota/tasmota.h +++ b/tasmota/tasmota.h @@ -84,6 +84,12 @@ const uint8_t MAX_PCF8574 = 4; // Max number of PCF8574 devices const uint8_t MAX_RULE_SETS = 3; // Max number of rule sets of size 512 characters const uint16_t MAX_RULE_SIZE = 512; // Max number of characters in rules +#ifdef ESP32 +const uint8_t MAX_I2C = 2; // Max number of I2C controllers (ESP32 = 2) +#else +const uint8_t MAX_I2C = 0; // Max number of I2C controllers (ESP8266 = 0, no choice) +#endif + // Changes to the following MAX_ defines need to be in line with enum SettingsTextIndex const uint8_t MAX_MQTT_PREFIXES = 3; // Max number of MQTT prefixes (cmnd, stat, tele) const uint8_t MAX_SSIDS = 2; // Max number of SSIDs diff --git a/tasmota/tasmota.ino b/tasmota/tasmota.ino index 637d2b84b..54db9ae17 100644 --- a/tasmota/tasmota.ino +++ b/tasmota/tasmota.ino @@ -141,6 +141,9 @@ struct { bool blinkstate; // LED state bool pwm_present; // Any PWM channel configured with SetOption15 0 bool i2c_enabled; // I2C configured +#ifdef ESP32 + bool i2c_enabled_2; // I2C configured, second controller on ESP32, Wire1 +#endif bool ntp_force_sync; // Force NTP sync bool skip_light_fade; // Temporarily skip light fading bool restart_halt; // Do not restart but stay in wait loop diff --git a/tasmota/tasmota_template.h b/tasmota/tasmota_template.h index a96d15830..e034fb8d1 100644 --- a/tasmota/tasmota_template.h +++ b/tasmota/tasmota_template.h @@ -386,8 +386,8 @@ const uint16_t kGpioNiceList[] PROGMEM = { \*-------------------------------------------------------------------------------------------*/ #ifdef USE_I2C - AGPIO(GPIO_I2C_SCL), // I2C SCL - AGPIO(GPIO_I2C_SDA), // I2C SDA + AGPIO(GPIO_I2C_SCL) + MAX_I2C, // I2C SCL + AGPIO(GPIO_I2C_SDA) + MAX_I2C, // I2C SDA #endif #ifdef USE_SPI diff --git a/tasmota/xdrv_04_light.ino b/tasmota/xdrv_04_light.ino index f6b58e491..814a88c51 100644 --- a/tasmota/xdrv_04_light.ino +++ b/tasmota/xdrv_04_light.ino @@ -2210,7 +2210,7 @@ void LightHandleDevGroupItem(void) static bool send_state = false; static bool restore_power = false; - if (Settings.device_group_tie[*XdrvMailbox.topic] != Light.device) return; + if (Settings.flag4.multiple_device_groups ? Settings.device_group_tie[*XdrvMailbox.topic] != Light.device : !(XdrvMailbox.index & DGR_FLAG_LOCAL)) return; bool more_to_come; uint32_t value = XdrvMailbox.payload; switch (XdrvMailbox.command_code) { diff --git a/tasmota/xdrv_10_scripter.ino b/tasmota/xdrv_10_scripter.ino index 10a7db17f..3c230c8b1 100755 --- a/tasmota/xdrv_10_scripter.ino +++ b/tasmota/xdrv_10_scripter.ino @@ -201,10 +201,12 @@ void alt_eeprom_readBytes(uint32_t adr, uint32_t len, uint8_t *buf) { // offsets epoch readings by 1.1.2019 00:00:00 to fit into float with second resolution +#ifndef EPOCH_OFFSET #define EPOCH_OFFSET 1546300800 +#endif enum {OPER_EQU=1,OPER_PLS,OPER_MIN,OPER_MUL,OPER_DIV,OPER_PLSEQU,OPER_MINEQU,OPER_MULEQU,OPER_DIVEQU,OPER_EQUEQU,OPER_NOTEQU,OPER_GRTEQU,OPER_LOWEQU,OPER_GRT,OPER_LOW,OPER_PERC,OPER_XOR,OPER_AND,OPER_OR,OPER_ANDEQU,OPER_OREQU,OPER_XOREQU,OPER_PERCEQU}; -enum {SCRIPT_LOGLEVEL=1,SCRIPT_TELEPERIOD,SCRIPT_EVENT_HANDLED,SML_JSON_ENABLE}; +enum {SCRIPT_LOGLEVEL=1,SCRIPT_TELEPERIOD,SCRIPT_EVENT_HANDLED,SML_JSON_ENABLE,SCRIPT_EPOFFS}; #ifdef USE_UFILESYS @@ -219,6 +221,7 @@ extern FS *ufsp; #endif // USE_UFILESYS +extern "C" void homekit_main(char *); #ifdef SUPPORT_MQTT_EVENT #include // Import LinkedList library @@ -413,6 +416,11 @@ struct SCRIPT_MEM { #ifdef USE_BUTTON_EVENT int8_t script_button[MAX_KEYS]; #endif //USE_BUTTON_EVENT + +#ifdef USE_HOMEKIT + bool homekit_running = false; +#endif // USE_HOMEKIT + uint32_t epoch_offset = EPOCH_OFFSET; } glob_script_mem; @@ -476,6 +484,19 @@ void ScriptEverySecond(void) { } } Run_Scripter(">S", 2, 0); + +#ifdef USE_HOMEKIT + if (glob_script_mem.homekit_running == false) { + uint8_t homekit_found = Run_Scripter(">h", -2, 0); + if (homekit_found == 99) { + if (!TasmotaGlobal.global_state.wifi_down) { + homekit_main(glob_script_mem.section_ptr); + glob_script_mem.homekit_running = true; + } + } + } +#endif // USE_HOMEKIT + } } @@ -1680,7 +1701,7 @@ char *isvar(char *lp, uint8_t *vtype, struct T_INDEX *tind, float *fp, char *sp, } else { if (fp) { if (!strncmp(vn.c_str(), "Epoch", 5)) { - *fp = atoi(str_value) - (uint32_t)EPOCH_OFFSET; + *fp = atoi(str_value) - (uint32_t)glob_script_mem.epoch_offset; } else { *fp = CharToFloat((char*)str_value); } @@ -1846,9 +1867,14 @@ chknext: break; case 'e': if (!strncmp(vname, "epoch", 5)) { - fvar = UtcTime() - (uint32_t)EPOCH_OFFSET; + fvar = UtcTime() - (uint32_t)glob_script_mem.epoch_offset; goto exit; } + if (!strncmp(vname, "epoffs", 6)) { + fvar = (uint32_t)glob_script_mem.epoch_offset; + tind->index = SCRIPT_EPOFFS; + goto exit_settable; + } if (!strncmp(vname, "eres", 4)) { fvar = glob_script_mem.event_handeled; tind->index = SCRIPT_EVENT_HANDLED; @@ -2469,6 +2495,19 @@ chknext: goto exit; } #endif //USE_LIGHT + +#ifdef USE_HOMEKIT + if (!strncmp(vname, "hki", 3)) { + if (!TasmotaGlobal.global_state.wifi_down) { + // erase nvs + homekit_main(0); + // restart homekit + glob_script_mem.homekit_running = false; + } + fvar = 0; + goto exit; + } +#endif break; case 'i': if (!strncmp(vname, "int(", 4)) { @@ -3529,6 +3568,40 @@ char *ForceStringVar(char *lp, char *dstr) { return lp; } +extern "C" { + uint32_t Ext_UpdVar(char *vname, float *fvar, uint32_t mode) { + return UpdVar(vname, fvar, mode); + } +} + +uint32_t UpdVar(char *vname, float *fvar, uint32_t mode) { + struct T_INDEX ind; + uint8_t vtype; + float res = *fvar; + isvar(vname, &vtype, &ind, fvar, 0, 0); + if (vtype != VAR_NV) { + // found variable as result + if (vtype == NUM_RES || (vtype & STYPE) == 0) { + if (mode) { + // set var + uint8_t index = glob_script_mem.type[ind.index].index; + glob_script_mem.fvars[index] = res; + glob_script_mem.type[index].bits.changed = 1; + } + return 0; + } else { + // break; + } + } + return 1; +} + + +extern "C" { + void Ext_Replace_Cmd_Vars(char *srcbuf, uint32_t srcsize, char *dstbuf, uint32_t dstsize) { + Replace_Cmd_Vars(srcbuf, srcsize, dstbuf, dstsize); + } +} // replace vars in cmd %var% void Replace_Cmd_Vars(char *srcbuf, uint32_t srcsize, char *dstbuf, uint32_t dstsize) { char *cp; @@ -3624,6 +3697,7 @@ void Replace_Cmd_Vars(char *srcbuf, uint32_t srcsize, char *dstbuf, uint32_t dst dstbuf[count] = 0; } + void toLog(const char *str) { if (!str) return; AddLog(LOG_LEVEL_INFO, str); @@ -4528,6 +4602,9 @@ int16_t Run_script_sub(const char *type, int8_t tlen, struct GVARS *gv) { case SCRIPT_EVENT_HANDLED: glob_script_mem.event_handeled = *dfvar; break; + case SCRIPT_EPOFFS: + glob_script_mem.epoch_offset = *dfvar; + break; #if defined(USE_SML_M) && defined (USE_SML_SCRIPT_CMD) case SML_JSON_ENABLE: sml_json_enable = *dfvar; @@ -5993,7 +6070,7 @@ bool ScriptMqttData(void) char sbuffer[128]; if (!strncmp(lkey.c_str(), "Epoch", 5)) { - uint32_t ep = atoi(value.c_str()) - (uint32_t)EPOCH_OFFSET; + uint32_t ep = atoi(value.c_str()) - (uint32_t)glob_script_mem.epoch_offset; snprintf_P(sbuffer, sizeof(sbuffer), PSTR(">%s=%d\n"), event_item.Event.c_str(), ep); } else { snprintf_P(sbuffer, sizeof(sbuffer), PSTR(">%s=\"%s\"\n"), event_item.Event.c_str(), value.c_str()); @@ -7392,7 +7469,6 @@ int32_t http_req(char *host, char *request) { #include #endif //ESP8266 - // get tesla powerwall info page json string uint32_t call2https(const char *host, const char *path) { if (TasmotaGlobal.global_state.wifi_down) return 1; @@ -7771,6 +7847,5 @@ bool Xdrv10(uint8_t function) return result; } - #endif // Do not USE_RULES #endif // USE_SCRIPT diff --git a/tasmota/xlgt_01_ws2812.ino b/tasmota/xlgt_01_ws2812.ino index fcd685931..b41884a22 100644 --- a/tasmota/xlgt_01_ws2812.ino +++ b/tasmota/xlgt_01_ws2812.ino @@ -47,81 +47,106 @@ void (* const Ws2812Command[])(void) PROGMEM = { #include -#if (USE_WS2812_HARDWARE == NEO_HW_P9813) - typedef P9813BgrFeature selectedNeoFeatureType; - #undef USE_WS2812_DMA - #undef USE_WS2812_INVERTED -#elif (USE_WS2812_CTYPE == NEO_GRB) - typedef NeoGrbFeature selectedNeoFeatureType; -#elif (USE_WS2812_CTYPE == NEO_BRG) - typedef NeoBrgFeature selectedNeoFeatureType; -#elif (USE_WS2812_CTYPE == NEO_RBG) - typedef NeoRbgFeature selectedNeoFeatureType; -#elif (USE_WS2812_CTYPE == NEO_RGBW) - typedef NeoRgbwFeature selectedNeoFeatureType; -#elif (USE_WS2812_CTYPE == NEO_GRBW) - typedef NeoGrbwFeature selectedNeoFeatureType; -#else // USE_WS2812_CTYPE - typedef NeoRgbFeature selectedNeoFeatureType; -#endif // USE_WS2812_CTYPE - -#ifdef USE_WS2812_DMA - -#ifdef USE_WS2812_INVERTED // See NeoEspDmaMethod.h for available options - -#if (USE_WS2812_HARDWARE == NEO_HW_WS2812X) - typedef NeoEsp8266DmaInvertedWs2812xMethod selectedNeoSpeedType; -#elif (USE_WS2812_HARDWARE == NEO_HW_SK6812) - typedef NeoEsp8266DmaInvertedSk6812Method selectedNeoSpeedType; -#elif (USE_WS2812_HARDWARE == NEO_HW_APA106) - typedef NeoEsp8266DmaInvertedApa106Method selectedNeoSpeedType; -#else // USE_WS2812_HARDWARE - typedef NeoEsp8266DmaInverted800KbpsMethod selectedNeoSpeedType; -#endif // USE_WS2812_HARDWARE - -#else // No USE_WS2812_INVERTED - -#if (USE_WS2812_HARDWARE == NEO_HW_WS2812X) - typedef NeoEsp8266DmaWs2812xMethod selectedNeoSpeedType; -#elif (USE_WS2812_HARDWARE == NEO_HW_SK6812) - typedef NeoEsp8266DmaSk6812Method selectedNeoSpeedType; -#elif (USE_WS2812_HARDWARE == NEO_HW_APA106) - typedef NeoEsp8266DmaApa106Method selectedNeoSpeedType; -#else // USE_WS2812_HARDWARE - typedef NeoEsp8266Dma800KbpsMethod selectedNeoSpeedType; -#endif // USE_WS2812_HARDWARE - -#endif // No USE_WS2812_INVERTED - -#else // No USE_WS2812_DMA - -#ifdef USE_WS2812_INVERTED // See NeoEspBitBangMethod.h for available options +// Build `selectedNeoFeatureType` as Neo-Rgb-Feature +// parametrized as: NEO_FEATURE_NEO+NEO_FEATURE_TYPE+NEO_FEATURE_FEATURE +#define CONCAT2(A,B) CONCAT2_(A,B) // ensures expansion first, see https://stackoverflow.com/questions/3221896/how-can-i-guarantee-full-macro-expansion-of-a-parameter-before-paste +#define CONCAT2_(A,B) A ## B +#define CONCAT3(A,B,C) CONCAT3_(A,B,C) // ensures expansion first, see https://stackoverflow.com/questions/3221896/how-can-i-guarantee-full-macro-expansion-of-a-parameter-before-paste +#define CONCAT3_(A,B,C) A ## B ## C + +#define NEO_FEATURE_NEO Neo +#define NEO_FEATURE_FEATURE Feature + +// select the right Neo feature based on USE_WS2812_CTYPE +// NEO_FEATURE_TYPE can be one of: Rgb (default), Grb, Brg, Rgb, Rgbw, Grbw +#if (USE_WS2812_CTYPE == NEO_GRB) + #define NEO_FEATURE_TYPE Grb +#elif (USE_WS2812_CTYPE == NEO_BRG) + #define NEO_FEATURE_TYPE Brg +#elif (USE_WS2812_CTYPE == NEO_RBG) + #define NEO_FEATURE_TYPE Rbg +#elif (USE_WS2812_CTYPE == NEO_RGBW) + #define NEO_FEATURE_TYPE Rbgw +#elif (USE_WS2812_CTYPE == NEO_GRBW) + #define NEO_FEATURE_TYPE Grbw +#else + #define NEO_FEATURE_TYPE Rgb +#endif + +// Exception for NEO_HW_P9813 +#if (USE_WS2812_HARDWARE == NEO_HW_P9813) + #undef NEO_FEATURE_NEO + #undef NEO_FEATURE_TYPE + #define NEO_FEATURE_NEO P9813 // P9813BgrFeature + #define NEO_FEATURE_TYPE Bgr + #undef USE_WS2812_DMA + #undef USE_WS2812_INVERTED +#endif // USE_WS2812_CTYPE + +typedef CONCAT3(NEO_FEATURE_NEO,NEO_FEATURE_TYPE,NEO_FEATURE_FEATURE) selectedNeoFeatureType; + +// selectedNeoSpeedType is built as Neo+Esp8266+Dma+Inverted+Ws2812x+Method +// Or NEO_NEO+NEO_CHIP+NEO_PROTO+NEO_INV+NEO_HW+Method +#define CONCAT6(A,B,C,D,E,F) CONCAT6_(A,B,C,D,E,F) // ensures expansion first, see https://stackoverflow.com/questions/3221896/how-can-i-guarantee-full-macro-expansion-of-a-parameter-before-paste +#define CONCAT6_(A,B,C,D,E,F) A ## B ## C ## D ## E ## F + +#define NEO_NEO Neo + +#ifdef ESP32 + #define NEO_CHIP Esp32 +#else + #define NEO_CHIP Esp8266 +#endif + +// Proto = DMA or BigBang +#if defined(USE_WS2812_DMA) && defined(ESP8266) + #define NEO_PROTO Dma +#elif defined(USE_WS2812_RMT) && defined(ESP32) + #define NEO_PROTO CONCAT2(Rmt,USE_WS2812_RMT) +#elif defined(USE_WS2812_I2S) && defined(ESP32) + #define NEO_PROTO CONCAT2(I2s,USE_WS2812_I2S) +#else + #define NEO_PROTO BitBang +#endif + +#ifdef USE_WS2812_INVERTED + #define NEO_INV Inverted +#else + #define NEO_INV +#endif + #if (USE_WS2812_HARDWARE == NEO_HW_WS2812X) - typedef NeoEsp8266BitBangWs2812xInvertedMethod selectedNeoSpeedType; + #define NEO_HW Ws2812x #elif (USE_WS2812_HARDWARE == NEO_HW_SK6812) - typedef NeoEsp8266BitBangSk6812InvertedMethod selectedNeoSpeedType; + #define NEO_HW Sk6812 +#elif (USE_WS2812_HARDWARE == NEO_HW_APA106) + #define NEO_HW Apa106 #else // USE_WS2812_HARDWARE - typedef NeoEsp8266BitBang400KbpsInvertedMethod selectedNeoSpeedType; + #define NEO_HW 800Kbps #endif // USE_WS2812_HARDWARE -#else // No USE_WS2812_INVERTED #if (USE_WS2812_HARDWARE == NEO_HW_P9813) - typedef P9813Method selectedNeoSpeedType; -#elif (USE_WS2812_HARDWARE == NEO_HW_WS2812X) - typedef NeoEsp8266BitBangWs2812xMethod selectedNeoSpeedType; -#elif (USE_WS2812_HARDWARE == NEO_HW_SK6812) - typedef NeoEsp8266BitBangSk6812Method selectedNeoSpeedType; -#else // USE_WS2812_HARDWARE - typedef NeoEsp8266BitBang800KbpsMethod selectedNeoSpeedType; -#endif // USE_WS2812_HARDWARE + #undef NEO_NEO + #define NEO_NEO + #undef NEO_CHIP + #define NEO_CHIP + #undef NEO_PROTO + #define NEO_PROTO + #undef NEO_INV + #define NEO_INV + #undef NEO_HW + #define NEO_HW P9813 // complete driver is P9813Method +#endif -#endif // No USE_WS2812_INVERTED - -#endif // No USE_WS2812_DMA +#if defined(ESP8266) && defined(USE_WS2812_DMA) +typedef CONCAT6(NEO_NEO,NEO_CHIP,NEO_PROTO,NEO_INV,NEO_HW,Method) selectedNeoSpeedType; +#else // Dma : different naming scheme +typedef CONCAT6(NEO_NEO,NEO_CHIP,NEO_PROTO,NEO_HW,NEO_INV,Method) selectedNeoSpeedType; +#endif NeoPixelBus *strip = nullptr; diff --git a/tasmota/xsns_82_wiegand.ino b/tasmota/xsns_82_wiegand.ino index b0607ef07..4fff9c5d1 100644 --- a/tasmota/xsns_82_wiegand.ino +++ b/tasmota/xsns_82_wiegand.ino @@ -36,22 +36,30 @@ * * Rule: * on wiegand#uid=4302741608 do publish cmnd/ailight/power 2 endon + * + * contains: + * - fix for #11047 Wiegand 26/34 missed some key press if they are press at normal speed + * - removed testing code for tests without attached hardware + * - added SetOption123 0-Wiegand UID decimal (default) 1-Wiegand UID hexadecimal + * - added SetOption124 0-Keypad every key a single tag (default) 1-all keys up to ending char (#) send as one tag \*********************************************************************************************/ #warning **** Wiegand interface enabled **** #define XSNS_82 82 -#define WIEGAND_BIT_TIMEOUT 25 // Time in mSec to be wait after last bit detected. +#define WIEGAND_CODE_GAP_FACTOR 3 // Gap between 2 complete RFID codes send by the device. (WIEGAND_CODE_GAP_FACTOR * bitTime) to detect the end of a code +#define WIEGAND_BIT_TIME_DEFAULT 1250 // period time of one bit (impluse + impulse_gap time) 1250µs measured by oscilloscope on my RFID Reader +#define WIEGAND_RFID_ARRAY_SIZE 5 // storage of rfids found between 2 calls of FUNC_EVERY_100_MSECOND +#define WIEGAND_OPTION_HEX 123 // Index of option to switch output between hex (1) an decimal (0) (default) -// Use only a randomly generate RFID for testing. using #define will save some space in the final code -// DEV_WIEGAND_TEST_MODE 1 : testing with random rfid without hardware connected, but GPIOs set correctly +// using #define will save some space in the final code // DEV_WIEGAND_TEST_MODE 2 : testing with hardware correctly connected. #define DEV_WIEGAND_TEST_MODE 0 #ifdef DEV_WIEGAND_TEST_MODE #if (DEV_WIEGAND_TEST_MODE==0) #elif (DEV_WIEGAND_TEST_MODE==1) - #warning "Wiegand Interface compiled with 'DEV_WIEGAND_TEST_MODE' 1 (Random RFID)" + #warning "(no longer available) Wiegand Interface compiled with 'DEV_WIEGAND_TEST_MODE' 1 (Random RFID)" #elif (DEV_WIEGAND_TEST_MODE==2) #warning "Wiegand Interface compiled with 'DEV_WIEGAND_TEST_MODE' 2 (Hardware connected)" #else @@ -59,6 +67,8 @@ #endif #endif +typedef struct rfid_store { uint64_t RFID; uint16_t bitCount; } RFID_store; + class Wiegand { public: @@ -70,29 +80,34 @@ class Wiegand { #endif // USE_WEBSERVER bool isInit = false; - uint8_t scanDelay; private: - - uint64_t HexStringToDec(uint64_t); + //uint64_t HexStringToDec(uint64_t); uint64_t CheckAndConvertRfid(uint64_t,uint16_t); char translateEnterEscapeKeyPress(char); uint8_t CalculateParities(uint64_t, int); - bool WiegandConversion (void); + bool WiegandConversion (uint64_t , uint16_t ); + void setOutputFormat(void); // fix output HEX format + static void handleD0Interrupt(void); static void handleD1Interrupt(void); + static void handleDxInterrupt(int in); // fix #11047 uint64_t rfid; uint8_t tagSize; + char outFormat; static volatile uint64_t rfidBuffer; static volatile uint16_t bitCount; static volatile uint32_t lastFoundTime; - static volatile uint8_t timeOut; - -#if (DEV_WIEGAND_TEST_MODE)==1 - uint64_t GetRandomRfid(uint8_t); -#endif // DEV_WIEGAND_TEST_MODE==1 + // fix #11047 + static volatile uint32_t bitTime; + static volatile uint32_t FirstBitTimeStamp; + static volatile uint32_t CodeGapTime; + static volatile bool CodeComplete; + static volatile RFID_store rfid_found[]; + static volatile int currentFoundRFIDcount; + }; Wiegand* oWiegand = new Wiegand(); @@ -100,7 +115,13 @@ Wiegand* oWiegand = new Wiegand(); volatile uint64_t Wiegand::rfidBuffer; volatile uint16_t Wiegand::bitCount; volatile uint32_t Wiegand::lastFoundTime; -volatile uint8_t Wiegand::timeOut; +// fix for #11047 +volatile uint32_t Wiegand::bitTime; +volatile uint32_t Wiegand::FirstBitTimeStamp; +volatile uint32_t Wiegand::CodeGapTime; +volatile bool Wiegand::CodeComplete; +volatile RFID_store Wiegand::rfid_found[WIEGAND_RFID_ARRAY_SIZE]; +volatile int Wiegand::currentFoundRFIDcount; Wiegand::Wiegand() { rfid = 0; @@ -108,73 +129,69 @@ Wiegand::Wiegand() { tagSize = 0; rfidBuffer = 0; bitCount = 0 ; - timeOut = 0; isInit = false; - scanDelay = 1; -} - -#if (DEV_WIEGAND_TEST_MODE)==1 -uint64_t Wiegand::GetRandomRfid(uint8_t tag_size=34) { - // Todo add support for 4 and 8 bit keyboard "tags" - uint64_t result = (uint32_t)HwRandom(); - uint8_t parities = 0; - bitCount = tag_size; - timeOut = millis() - WIEGAND_BIT_TIMEOUT; - result = result << 32; - result += HwRandom(); - - switch (tag_size){ - case 24: - result = (result & 0x7FFFFE) >>1; - break; - case 26: - result = (result & 0x1FFFFFE) >>1; - break; - case 32: - result = (result & 0x7FFFFFFE) >>1; - break; - case 34: - result = (result & 0x3FFFFFFFE) >>1; - break; - default: - break; + // fix #11047 + bitTime = WIEGAND_BIT_TIME_DEFAULT; + FirstBitTimeStamp = 0; + CodeGapTime = WIEGAND_CODE_GAP_FACTOR * bitTime; + CodeComplete = false; + currentFoundRFIDcount=0; + for (int i=0; i < WIEGAND_RFID_ARRAY_SIZE; i++ ) + { + rfid_found[i].RFID=0; + rfid_found[i].bitCount=0; } - parities = CalculateParities(result, tag_size); - - result = (result << 1) | (parities & 0x01); // Set LSB parity - if (parities & 0x80) { // MSB parity is 1 - switch (tag_size) { - case 24: - result |= 0x800000; - break; - case 26: - result |= 0x2000000; - break; - case 32: - result |= 0x80000000; - break; - case 34: - result |= 0x400000000; - break; - default: - break; - } - } - - return result; + outFormat='u'; // standard output format decimal } -#endif // DEV_WIEGAND_TEST_MODE==1 void ICACHE_RAM_ATTR Wiegand::handleD1Interrupt() { // Receive a 1 bit. (D0=high & D1=low) - rfidBuffer = (rfidBuffer << 1) | 1; // Leftshift + 1 bit - bitCount++; // Increment the counter - lastFoundTime = millis(); // Last time bit found + handleDxInterrupt(1); } void ICACHE_RAM_ATTR Wiegand::handleD0Interrupt() { // Receive a 0 bit. (D0=low & D1=high) - rfidBuffer = rfidBuffer << 1; // Leftshift the 0 bit is now at the end of rfidBuffer - bitCount++; // Increment the counter - lastFoundTime = millis(); // Last time bit found + handleDxInterrupt(0); +} + +void ICACHE_RAM_ATTR Wiegand::handleDxInterrupt(int in) { + + unsigned long curTime = micros(); // to be sure I will use micros() instead of millis() overflow is handle by using the minus operator to compare + unsigned long diffTime= curTime - lastFoundTime; + if (diffTime > 3000000 ) { //cancel noisy bits in buffer and start a new tag + rfidBuffer = 0; + bitCount = 0; + FirstBitTimeStamp = 0; + } + if ( (diffTime > CodeGapTime) && (bitCount > 0)) { + // previous RFID tag (key pad numer)is complete. Will be detected by the code ending gap + // one bit will take the time of impulse_time + impulse_gap_time. it (bitTime) will be recalculated each time an impulse is detected + // the devices will add some inter_code_gap_time to separate codes this will be much longer than the bit_time. (WIEGAND_CODE_GAP_FACTOR) + // unfortunately there's no timing defined for Wiegang. On my test reader the impulse time = 125 µs impulse gap time = 950 µs. + if (currentFoundRFIDcount < WIEGAND_RFID_ARRAY_SIZE) { // when reaching the end of rfid buffer we will overwrite the last one. + currentFoundRFIDcount++; + } + // start a new tag + rfidBuffer = 0; + bitCount = 0; + FirstBitTimeStamp = 0; + } + if (in ==3) {// called by ScanForTag to get the last tag, because the interrupt handler is no longer called after receiving the last bit + return; + } + if (in == 0) { rfidBuffer = rfidBuffer << 1; } // Receive a 0 bit. (D0=low & D1=high): Leftshift the 0 bit is now at the end of rfidBuffer + else {rfidBuffer = (rfidBuffer << 1) | 1; } // Receive a 1 bit. (D0=high & D1=low): Leftshift + 1 bit + + bitCount++; + if (bitCount == 1) { // first bit was detected + FirstBitTimeStamp = (curTime != 0) ? curTime : 1; // accept 1µs differenct to avoid a miss the first timestamp if curTime is 0. + } + else if (bitCount == 2) { // only calculate once per RFID tag + bitTime = diffTime; //calc maximum current length of one bit + CodeGapTime = WIEGAND_CODE_GAP_FACTOR * bitTime; + } + //save current rfid in array otherwise we will never see the last found tag + rfid_found[currentFoundRFIDcount].RFID=rfidBuffer; + rfid_found[currentFoundRFIDcount].bitCount= bitCount; + lastFoundTime = curTime; // Last time a bit was detected } void Wiegand::Init() { @@ -201,11 +218,11 @@ void Wiegand::Init() { #endif // DEV_WIEGAND_TEST_MODE>0 } -uint64_t Wiegand::CheckAndConvertRfid(uint64_t rfidIn, uint16_t bitcount) { +uint64_t Wiegand::CheckAndConvertRfid(uint64_t rfidIn, uint16_t bitCount) { uint8_t evenParityBit = 0; uint8_t oddParityBit = (uint8_t) (rfidIn & 0x1); // Last bit = odd parity uint8_t calcParity = 0; - switch (bitcount) { + switch (bitCount) { case 24: evenParityBit = (rfidIn & 0x800000) ? 0x80 : 0; rfidIn = (rfidIn & 0x7FFFFE) >>1; @@ -282,18 +299,14 @@ char Wiegand::translateEnterEscapeKeyPress(char oKeyPressed) { } } -bool Wiegand::WiegandConversion () { +bool Wiegand::WiegandConversion (uint64_t rfidBuffer, uint16_t bitCount) { bool bRet = false; - unsigned long nowTick = millis(); + // unsigned long nowTick = micros(); // Add a maximum wait time for new bits - unsigned long diffTicks = nowTick - lastFoundTime; - if ((diffTicks > WIEGAND_BIT_TIMEOUT) && (diffTicks >= 5000 )) { // Max. 5 secs between 2 bits comming in - bitCount = 0; - rfidBuffer = 0; - lastFoundTime = nowTick; - return bRet; - } - if (diffTicks > WIEGAND_BIT_TIMEOUT) { // Last bit found is WIEGAND_BIT_TIMEOUT ms ago + // unsigned long diffTicks = nowTick - lastFoundTime; + // unsigned long inter_code_gap = WIEGAND_CODE_GAP_FACTOR * bitTime; + // if ((diffTicks > inter_code_gap) && (diffTicks >= 1000000 )) { // Max. 4-8 secs between 2 bits comming in. depends on micros() resolution + #if (DEV_WIEGAND_TEST_MODE)>0 AddLog(LOG_LEVEL_INFO, PSTR("WIE: Raw tag %llu, Bit count %u"), rfidBuffer, bitCount); #endif // DEV_WIEGAND_TEST_MODE>0 @@ -319,69 +332,78 @@ bool Wiegand::WiegandConversion () { rfid = (int)translateEnterEscapeKeyPress(lowNibble); bRet = true; } else { - lastFoundTime = nowTick; + // lastFoundTime = nowTick; bRet = false; } tagSize = bitCount; } else { // Time reached but unknown bitCount, clear and start again - lastFoundTime = nowTick; + // lastFoundTime = nowTick; bRet = false; } - bitCount = 0; - rfidBuffer = 0; - } else { - bRet = false; // Watching time not finished - } #if (DEV_WIEGAND_TEST_MODE)>0 AddLog(LOG_LEVEL_INFO, PSTR("WIE: Tag out %llu, tag size %u "), rfid, tagSize); #endif // DEV_WIEGAND_TEST_MODE>0 return bRet; } +void Wiegand::setOutputFormat(void) +{ + if (GetOption(WIEGAND_OPTION_HEX) == 0) { outFormat = 'u'; } + else { outFormat = 'X'; } +} + void Wiegand::ScanForTag() { -#if (DEV_WIEGAND_TEST_MODE)>0 - AddLog(LOG_LEVEL_INFO, PSTR("WIE: ScanForTag().")); -#if (DEV_WIEGAND_TEST_MODE==1) - switch (millis() %4) { - case 0: - rfidBuffer = GetRandomRfid(24); - break; - case 1: - rfidBuffer = GetRandomRfid(26); - break; - case 2: - rfidBuffer = GetRandomRfid(32); - break; - case 3: - rfidBuffer = GetRandomRfid(34); - break; - default: - rfidBuffer = GetRandomRfid(34); - break; - } - AddLog(LOG_LEVEL_INFO, PSTR("WIE: Raw generated %lX"), rfidBuffer); // For tests without reader attaiched -#endif // DEV_WIEGAND_TEST_MODE==1 -#endif // DEV_WIEGAND_TEST_MODE>0 - if (bitCount > 0) { - uint64_t oldTag = rfid; - bool validKey = WiegandConversion(); -#if (DEV_WIEGAND_TEST_MODE)>0 - AddLog(LOG_LEVEL_INFO, PSTR("WIE: Previous tag %llu"), oldTag); -#endif // DEV_WIEGAND_TEST_MODE>0 - if (validKey) { // Only in case of valid key do action. Issue#10585 - if (oldTag == rfid) { - AddLog(LOG_LEVEL_DEBUG, PSTR("WIE: Old tag")); + unsigned long startTime = micros(); + handleDxInterrupt(3); + if (currentFoundRFIDcount > 0) { + unsigned int lastFoundRFIDcount = currentFoundRFIDcount; + #if (DEV_WIEGAND_TEST_MODE)>0 + AddLog(LOG_LEVEL_INFO, PSTR("WIE: ScanForTag(). bitTime: %0lu lastFoundTime: %0lu RFIDS in buffer: %lu"), bitTime, lastFoundTime, currentFoundRFIDcount); + #endif + // format MQTT output + setOutputFormat(); + char sFormat[50]; + snprintf( sFormat, 50, PSTR(",\"Wiegand\":{\"UID\":%%0ll%c,\"" D_JSON_SIZE "\":%%%c}}"), outFormat, outFormat); + + for (int i= 0; i < WIEGAND_RFID_ARRAY_SIZE; i++) + { + if (rfid_found[i].RFID != 0) { + uint64_t oldTag = rfid; + bool validKey = WiegandConversion(rfid_found[i].RFID, rfid_found[i].bitCount); + #if (DEV_WIEGAND_TEST_MODE)>0 + AddLog(LOG_LEVEL_INFO, PSTR("WIE: Previous tag %llu"), oldTag); + #endif // DEV_WIEGAND_TEST_MODE>0 + if (validKey) { // Only in case of valid key do action. Issue#10585 + if (oldTag == rfid) { + AddLog(LOG_LEVEL_DEBUG, PSTR("WIE: Old tag")); + } + ResponseTime_P(sFormat, rfid,tagSize); + MqttPublishTeleSensor(); + } + rfid_found[i].RFID=0; + rfid_found[i].bitCount=0; } - ResponseTime_P(PSTR(",\"Wiegand\":{\"UID\":%0llu,\"" D_JSON_SIZE "\":%u}}"), rfid, tagSize); - MqttPublishTeleSensor(); } + if (currentFoundRFIDcount > lastFoundRFIDcount) { + // if that happens: we need to move the id found during the loop to top of the array + // and correct the currentFoundRFIDcount + } + currentFoundRFIDcount=0; //reset array + #if (DEV_WIEGAND_TEST_MODE)>0 + AddLog(LOG_LEVEL_INFO, PSTR("WIE: ScanForTag() time elapsed %lu"), (micros() - startTime)); + #endif } + } #ifdef USE_WEBSERVER void Wiegand::Show(void) { - WSContentSend_PD(PSTR("{s}Wiegand UID{m}%llu {e}"), rfid); + setOutputFormat(); + char sFormat [30]; + snprintf( sFormat, 30,PSTR("{s}Wiegand UID{m}%%ll%c {e}"), outFormat); + WSContentSend_PD(sFormat, rfid); + //WSContentSend_PD(PSTR("{s}Wiegand UID{m}%llX {e}"), rfid); #if (DEV_WIEGAND_TEST_MODE)>0 AddLog(LOG_LEVEL_INFO, PSTR("WIE: Tag %llu, Bits %u"), rfid, bitCount); #endif // DEV_WIEGAND_TEST_MODE>0 @@ -400,18 +422,8 @@ bool Xsns82(byte function) { } else if (oWiegand->isInit) { switch (function) { - case FUNC_EVERY_250_MSECOND: // Some tags need more time, don't try shorter period -#if (DEV_WIEGAND_TEST_MODE)==1 - if (oWiegand->scanDelay >= 4) // Give a second because of the log entries to be send. -#else - if (oWiegand->scanDelay >= 2) // Only run every (delay * 250 ms) (every 250ms is too fast for some tags) -#endif - { - oWiegand->ScanForTag(); - oWiegand->scanDelay = 1; - } else { - oWiegand->scanDelay++; - } + case FUNC_EVERY_100_MSECOND: // fix for #11047 Wiegand 26/34 missed some key press + oWiegand->ScanForTag(); break; #ifdef USE_WEBSERVER case FUNC_WEB_SENSOR: