ソースを参照

Merge branch 'feature/optimize_bluetooth_architecture_0616' into 'master'

Feature/optimize bluetooth architecture

See merge request espressif/esp-idf!18553
Jiang Jiang Jian 3 年 前
コミット
3cc134672b
91 ファイル変更15721 行追加998 行削除
  1. 73 77
      components/bt/CMakeLists.txt
  2. 0 1
      components/bt/Kconfig
  3. 184 149
      components/bt/controller/esp32c2/Kconfig.in
  4. 60 63
      components/bt/controller/esp32c2/bt.c
  5. 224 140
      components/bt/controller/esp32h2/Kconfig.in
  6. 373 206
      components/bt/controller/esp32h2/bt.c
  7. 1 1
      components/bt/controller/lib_esp32c2/esp32c2-bt-lib
  8. 4 6
      components/bt/host/nimble/Kconfig.in
  9. 1 0
      components/bt/host/nimble/esp-hci/src/esp_nimble_hci.c
  10. 1 1
      components/bt/host/nimble/nimble
  11. 0 37
      components/bt/host/nimble/port/include/esp_nimble_cfg.h
  12. 15 0
      components/bt/host/nimble/port/include/esp_nimble_main.h
  13. 6 3
      components/bt/host/nimble/port/include/esp_nimble_mem.h
  14. 100 0
      components/bt/host/nimble/port/src/esp_nimble_main.c
  15. 11 145
      components/bt/include/esp32c2/include/esp_bt.h
  16. 209 0
      components/bt/include/esp32c2/include/esp_bt_cfg.h
  17. 11 146
      components/bt/include/esp32h2/include/esp_bt.h
  18. 209 0
      components/bt/include/esp32h2/include/esp_bt_cfg.h
  19. 15 0
      components/bt/porting/ext/tinycrypt/AUTHORS
  20. 61 0
      components/bt/porting/ext/tinycrypt/LICENSE
  21. 70 0
      components/bt/porting/ext/tinycrypt/README
  22. 1 0
      components/bt/porting/ext/tinycrypt/VERSION
  23. 352 0
      components/bt/porting/ext/tinycrypt/documentation/tinycrypt.rst
  24. 130 0
      components/bt/porting/ext/tinycrypt/include/tinycrypt/aes.h
  25. 151 0
      components/bt/porting/ext/tinycrypt/include/tinycrypt/cbc_mode.h
  26. 211 0
      components/bt/porting/ext/tinycrypt/include/tinycrypt/ccm_mode.h
  27. 194 0
      components/bt/porting/ext/tinycrypt/include/tinycrypt/cmac_mode.h
  28. 61 0
      components/bt/porting/ext/tinycrypt/include/tinycrypt/constants.h
  29. 108 0
      components/bt/porting/ext/tinycrypt/include/tinycrypt/ctr_mode.h
  30. 166 0
      components/bt/porting/ext/tinycrypt/include/tinycrypt/ctr_prng.h
  31. 545 0
      components/bt/porting/ext/tinycrypt/include/tinycrypt/ecc.h
  32. 131 0
      components/bt/porting/ext/tinycrypt/include/tinycrypt/ecc_dh.h
  33. 139 0
      components/bt/porting/ext/tinycrypt/include/tinycrypt/ecc_dsa.h
  34. 81 0
      components/bt/porting/ext/tinycrypt/include/tinycrypt/ecc_platform_specific.h
  35. 139 0
      components/bt/porting/ext/tinycrypt/include/tinycrypt/hmac.h
  36. 164 0
      components/bt/porting/ext/tinycrypt/include/tinycrypt/hmac_prng.h
  37. 129 0
      components/bt/porting/ext/tinycrypt/include/tinycrypt/sha256.h
  38. 95 0
      components/bt/porting/ext/tinycrypt/include/tinycrypt/utils.h
  39. 164 0
      components/bt/porting/ext/tinycrypt/src/aes_decrypt.c
  40. 191 0
      components/bt/porting/ext/tinycrypt/src/aes_encrypt.c
  41. 114 0
      components/bt/porting/ext/tinycrypt/src/cbc_mode.c
  42. 266 0
      components/bt/porting/ext/tinycrypt/src/ccm_mode.c
  43. 254 0
      components/bt/porting/ext/tinycrypt/src/cmac_mode.c
  44. 85 0
      components/bt/porting/ext/tinycrypt/src/ctr_mode.c
  45. 279 0
      components/bt/porting/ext/tinycrypt/src/ctr_prng.c
  46. 939 0
      components/bt/porting/ext/tinycrypt/src/ecc.c
  47. 200 0
      components/bt/porting/ext/tinycrypt/src/ecc_dh.c
  48. 294 0
      components/bt/porting/ext/tinycrypt/src/ecc_dsa.c
  49. 104 0
      components/bt/porting/ext/tinycrypt/src/ecc_platform_specific.c
  50. 148 0
      components/bt/porting/ext/tinycrypt/src/hmac.c
  51. 212 0
      components/bt/porting/ext/tinycrypt/src/hmac_prng.c
  52. 217 0
      components/bt/porting/ext/tinycrypt/src/sha256.c
  53. 74 0
      components/bt/porting/ext/tinycrypt/src/utils.c
  54. 75 0
      components/bt/porting/include/mem_api.h
  55. 13 4
      components/bt/porting/mem/bt_osi_mem.c
  56. 21 0
      components/bt/porting/mem/bt_osi_mem.h
  57. 318 0
      components/bt/porting/nimble/include/nimble/ble.h
  58. 407 0
      components/bt/porting/nimble/include/nimble/ble_hci_trans.h
  59. 1883 0
      components/bt/porting/nimble/include/nimble/hci_common.h
  60. 180 0
      components/bt/porting/nimble/include/nimble/nimble_npl.h
  61. 34 0
      components/bt/porting/nimble/include/nimble/nimble_opt.h
  62. 124 0
      components/bt/porting/nimble/include/nimble/nimble_opt_auto.h
  63. 57 0
      components/bt/porting/nimble/include/nimble/nimble_port.h
  64. 296 0
      components/bt/porting/nimble/include/os/endian.h
  65. 74 0
      components/bt/porting/nimble/include/os/os.h
  66. 69 0
      components/bt/porting/nimble/include/os/os_error.h
  67. 1146 0
      components/bt/porting/nimble/include/os/os_mbuf.h
  68. 408 0
      components/bt/porting/nimble/include/os/os_mempool.h
  69. 218 0
      components/bt/porting/nimble/include/os/queue.h
  70. 45 0
      components/bt/porting/nimble/include/os/util.h
  71. 206 0
      components/bt/porting/nimble/src/os_msys_init.c
  72. 381 0
      components/bt/porting/npl/freertos/include/nimble/nimble_npl_os.h
  73. 28 0
      components/bt/porting/npl/freertos/include/nimble/nimble_port_freertos.h
  74. 108 0
      components/bt/porting/npl/freertos/include/nimble/npl_freertos.h
  75. 1211 0
      components/bt/porting/npl/freertos/src/npl_os_freertos.c
  76. 90 0
      components/bt/porting/transport/include/hci_uart.h
  77. 190 0
      components/bt/porting/transport/uart/hci_uart.c
  78. 0 3
      components/esp_rom/esp32c2/ld/esp32c2.rom.ld
  79. 9 0
      examples/bluetooth/bluedroid/ble/gatt_server/sdkconfig.defaults.esp32c2
  80. 8 0
      examples/bluetooth/nimble/blecent/sdkconfig.defaults.esp32c2
  81. 7 0
      examples/bluetooth/nimble/blehr/sdkconfig.defaults.esp32c2
  82. 6 6
      examples/bluetooth/nimble/bleprph/main/main.c
  83. 8 0
      examples/bluetooth/nimble/bleprph/sdkconfig.defaults.esp32c2
  84. 4 10
      examples/bluetooth/nimble/bleprph/sdkconfig.defaults.esp32h2
  85. 6 0
      examples/bluetooth/nimble/hci/CMakeLists.txt
  86. 63 0
      examples/bluetooth/nimble/hci/README.md
  87. 4 0
      examples/bluetooth/nimble/hci/main/CMakeLists.txt
  88. 4 0
      examples/bluetooth/nimble/hci/main/component.mk
  89. 43 0
      examples/bluetooth/nimble/hci/main/main.c
  90. 9 0
      examples/bluetooth/nimble/hci/sdkconfig.defaults
  91. 2 0
      tools/ci/check_copyright_config.yaml

+ 73 - 77
components/bt/CMakeLists.txt

@@ -26,16 +26,20 @@ if(CONFIG_BT_ENABLED)
         list(APPEND include_dirs include/esp32c2/include)
     endif()
 
+
     # Common
     list(APPEND include_dirs common/osi/include)
 
     list(APPEND priv_include_dirs
             common/btc/include
-            common/include)
+            common/include
+            porting/mem/
+        )
     list(APPEND include_dirs
          common/api/include/api
          common/btc/profile/esp/blufi/include
-         common/btc/profile/esp/include)
+         common/btc/profile/esp/include
+        )
 
 
     list(APPEND srcs "common/btc/core/btc_alarm.c"
@@ -56,7 +60,9 @@ if(CONFIG_BT_ENABLED)
          "common/osi/mutex.c"
          "common/osi/thread.c"
          "common/osi/osi.c"
-         "common/osi/semaphore.c")
+         "common/osi/semaphore.c"
+         "porting/mem/bt_osi_mem.c"
+         )
 
     # Host Bluedroid
     if(CONFIG_BT_BLUEDROID_ENABLED)
@@ -352,12 +358,7 @@ if(CONFIG_BT_ENABLED)
                    "host/bluedroid/stack/smp/smp_l2c.c"
                    "host/bluedroid/stack/smp/smp_main.c"
                    "host/bluedroid/stack/smp/smp_utils.c")
-        if(CONFIG_IDF_TARGET_ESP32H2 OR CONFIG_IDF_TARGET_ESP32C2)
-                   list(APPEND srcs
-                   "host/nimble/nimble/porting/npl/freertos/src/npl_os_freertos.c"
-                   "host/nimble/nimble/porting/nimble/src/os_msys_init.c"
-                   "host/nimble/port/src/esp_nimble_mem.c")
-        endif()
+
 
         list(APPEND srcs "common/btc/profile/esp/blufi/bluedroid_host/esp_blufi.c")
 
@@ -466,67 +467,48 @@ if(CONFIG_BT_ENABLED)
     endif()
 
 
-    # Nimble
-    # Nimble common
-    if(CONFIG_BT_NIMBLE_ENABLED OR
-       (CONFIG_BT_CONTROLLER_ENABLED AND (CONFIG_IDF_TARGET_ESP32C2 OR CONFIG_IDF_TARGET_ESP32H2)))
-        list(APPEND srcs
-                "host/nimble/nimble/porting/npl/freertos/src/nimble_port_freertos.c"
-                "host/nimble/nimble/porting/npl/freertos/src/npl_os_freertos.c"
-                "host/nimble/nimble/porting/nimble/src/os_cputime_pwr2.c"
-                "host/nimble/nimble/porting/nimble/src/hal_timer.c"
-                "host/nimble/nimble/porting/nimble/src/os_msys_init.c"
-                "host/nimble/nimble/porting/nimble/src/nimble_port.c"
-                "host/nimble/port/src/esp_nimble_mem.c"
-                "host/nimble/esp-hci/src/esp_nimble_hci.c"
-                "host/nimble/nimble/porting/nimble/src/os_cputime.c"
-        )
 
-        list(APPEND include_dirs
-                host/nimble/nimble/porting/nimble/include
-                host/nimble/port/include
-                host/nimble/nimble/nimble/include
-                host/nimble/nimble/porting/npl/freertos/include
-                host/nimble/esp-hci/include
-        )
-
-        if(NOT CONFIG_BT_NIMBLE_CRYPTO_STACK_MBEDTLS)
-
-            list(APPEND include_dirs
-                        host/nimble/nimble/ext/tinycrypt/include)
-
-            list(APPEND srcs "host/nimble/nimble/ext/tinycrypt/src/utils.c"
-                        "host/nimble/nimble/ext/tinycrypt/src/sha256.c"
-                        "host/nimble/nimble/ext/tinycrypt/src/ecc.c"
-                        "host/nimble/nimble/ext/tinycrypt/src/ctr_prng.c"
-                        "host/nimble/nimble/ext/tinycrypt/src/ctr_mode.c"
-                        "host/nimble/nimble/ext/tinycrypt/src/aes_decrypt.c"
-                        "host/nimble/nimble/ext/tinycrypt/src/aes_encrypt.c"
-                        "host/nimble/nimble/ext/tinycrypt/src/ccm_mode.c"
-                        "host/nimble/nimble/ext/tinycrypt/src/ecc_dsa.c"
-                        "host/nimble/nimble/ext/tinycrypt/src/cmac_mode.c"
-                        "host/nimble/nimble/ext/tinycrypt/src/ecc_dh.c"
-                        "host/nimble/nimble/ext/tinycrypt/src/hmac_prng.c"
-                        "host/nimble/nimble/ext/tinycrypt/src/ecc_platform_specific.c"
-                        "host/nimble/nimble/ext/tinycrypt/src/hmac.c"
-                        "host/nimble/nimble/ext/tinycrypt/src/cbc_mode.c")
-        endif()
-
-        if(CONFIG_BT_LE_HCI_INTERFACE_USE_UART)
+    if(CONFIG_BT_LE_CONTROLLER_NPL_OS_PORTING_SUPPORT)
             list(APPEND srcs
-                "host/nimble/nimble/porting/nimble/src/hal_uart.c"
-                )
-            list(APPEND include_dirs
-                host/nimble/nimble/nimble/transport/uart/include
-                )
-        else()
+                    "porting/npl/freertos/src/npl_os_freertos.c"
+                    "porting/nimble/src/os_msys_init.c"
+            )
+
             list(APPEND include_dirs
-                host/nimble/nimble/nimble/transport/ram/include
-                )
-        endif()
+                    porting/include
+                    porting/nimble/include
+                    porting/npl/freertos/include
+                    porting/transport/include
+            )
+
+            if(CONFIG_BT_LE_HCI_INTERFACE_USE_UART)
+                list(APPEND srcs
+                        "porting/transport/uart/hci_uart.c"
+                    )
+            endif()
     endif()
 
 
+    if(NOT (CONFIG_BT_LE_CRYPTO_STACK_MBEDTLS OR CONFIG_BT_NIMBLE_CRYPTO_STACK_MBEDTLS))
+        list(APPEND include_dirs
+                porting/ext/tinycrypt/include
+            )
+        list(APPEND srcs "porting/ext/tinycrypt/src/utils.c"
+                "porting/ext/tinycrypt/src/sha256.c"
+                "porting/ext/tinycrypt/src/ecc.c"
+                "porting/ext/tinycrypt/src/ctr_prng.c"
+                "porting/ext/tinycrypt/src/ctr_mode.c"
+                "porting/ext/tinycrypt/src/aes_decrypt.c"
+                "porting/ext/tinycrypt/src/aes_encrypt.c"
+                "porting/ext/tinycrypt/src/ccm_mode.c"
+                "porting/ext/tinycrypt/src/ecc_dsa.c"
+                "porting/ext/tinycrypt/src/cmac_mode.c"
+                "porting/ext/tinycrypt/src/ecc_dh.c"
+                "porting/ext/tinycrypt/src/hmac_prng.c"
+                "porting/ext/tinycrypt/src/ecc_platform_specific.c"
+                "porting/ext/tinycrypt/src/hmac.c"
+                "porting/ext/tinycrypt/src/cbc_mode.c")
+    endif()
 
     if(CONFIG_BT_NIMBLE_ENABLED)
 
@@ -606,26 +588,40 @@ if(CONFIG_BT_ENABLED)
                     "host/nimble/nimble/nimble/host/store/config/src/ble_store_nvs.c"
                 )
 
-        if(CONFIG_IDF_TARGET_ESP32)
-            list(APPEND srcs
-                    "host/nimble/nimble/porting/nimble/src/endian.c"
-                    "host/nimble/nimble/porting/nimble/src/os_mempool.c"
-                    "host/nimble/nimble/porting/nimble/src/mem.c"
-                    "host/nimble/nimble/porting/nimble/src/os_mbuf.c")
-        elseif(CONFIG_IDF_TARGET_ESP32C3)
             list(APPEND srcs
-                    "host/nimble/nimble/porting/nimble/src/endian.c"
-                    "host/nimble/nimble/porting/nimble/src/os_mempool.c"
-                    "host/nimble/nimble/porting/nimble/src/mem.c"
-                    "host/nimble/nimble/porting/nimble/src/os_mbuf.c")
-        elseif(CONFIG_IDF_TARGET_ESP32S3)
+                "host/nimble/nimble/porting/nimble/src/nimble_port.c"
+                "host/nimble/nimble/porting/npl/freertos/src/nimble_port_freertos.c"
+            )
+            list(APPEND include_dirs
+                porting/include
+                host/nimble/nimble/porting/nimble/include
+                host/nimble/port/include
+            )
+
+        if(NOT CONFIG_BT_LE_CONTROLLER_NPL_OS_PORTING_SUPPORT)
             list(APPEND srcs
                     "host/nimble/nimble/porting/nimble/src/endian.c"
                     "host/nimble/nimble/porting/nimble/src/os_mempool.c"
                     "host/nimble/nimble/porting/nimble/src/mem.c"
-                    "host/nimble/nimble/porting/nimble/src/os_mbuf.c")
+                    "host/nimble/nimble/porting/nimble/src/os_mbuf.c"
+                    "host/nimble/nimble/porting/nimble/src/os_msys_init.c"
+                    "host/nimble/nimble/porting/npl/freertos/src/npl_os_freertos.c"
+                    )
+            list(APPEND include_dirs
+                    host/nimble/nimble/porting/npl/freertos/include
+                    host/nimble/nimble/porting/nimble/include
+                    host/nimble/nimble/nimble/include
+            )
         endif()
 
+        if(CONFIG_IDF_TARGET_ESP32 OR CONFIG_IDF_TARGET_ESP32C3 OR CONFIG_IDF_TARGET_ESP32S3 OR TRUE)
+            list(APPEND srcs
+                "host/nimble/esp-hci/src/esp_nimble_hci.c"
+            )
+            list(APPEND include_dirs
+                host/nimble/esp-hci/include
+            )
+        endif()
 
         list(APPEND srcs
                     "common/btc/profile/esp/blufi/nimble_host/esp_blufi.c")

+ 0 - 1
components/bt/Kconfig

@@ -45,7 +45,6 @@ menu "Bluetooth"
             bool "Enabled"
             help
                 This option is recommended for Bluetooth controller usecases
-                This option is recommended for Bluetooth controller usecases
 
         config BT_CONTROLLER_DISABLED
             bool "Disabled"

+ 184 - 149
components/bt/controller/esp32c2/Kconfig.in

@@ -8,11 +8,11 @@ menu "HCI Config"
         config BT_LE_HCI_INTERFACE_USE_RAM
             bool "ram"
             help
-                    Use RAM as HCI interface
+                Use RAM as HCI interface
         config BT_LE_HCI_INTERFACE_USE_UART
             bool "uart"
             help
-                    Use UART as HCI interface
+                Use UART as HCI interface
     endchoice
 
     config BT_LE_HCI_UART_PORT
@@ -22,6 +22,11 @@ menu "HCI Config"
         help
             Set the port number of HCI UART
 
+    config BT_LE_HCI_UART_FLOWCTRL
+        bool "HCI uart Hardware Flow ctrl"
+        depends on BT_LE_HCI_INTERFACE_USE_UART
+        default n
+
     config BT_LE_HCI_UART_TX_PIN
         int "HCI uart Tx gpio"
         depends on BT_LE_HCI_INTERFACE_USE_UART
@@ -32,72 +37,142 @@ menu "HCI Config"
         depends on BT_LE_HCI_INTERFACE_USE_UART
         default 10
 
-    config BT_LE_HCI_UART_TASK_STACK_SIZE
-        int "HCI uart task stack size"
-        depends on BT_LE_HCI_INTERFACE_USE_UART
-        default 1000
-        help
-                Set the size of uart task stack
+    config BT_LE_HCI_UART_RTS_PIN
+        int "HCI uart RTS gpio"
+        depends on BT_LE_HCI_UART_FLOWCTRL
+        default 4
+
+    config BT_LE_HCI_UART_CTS_PIN
+        int "HCI uart CTS gpio"
+        depends on BT_LE_HCI_UART_FLOWCTRL
+        default 5
 
     config BT_LE_HCI_UART_BAUD
         int "HCI uart baudrate"
         depends on BT_LE_HCI_INTERFACE_USE_UART
         default 921600
         help
-                HCI uart baud rate 115200 ~ 1000000
+            HCI uart baud rate 115200 ~ 1000000
+
+    choice BT_LE_HCI_UART_PARITY
+        prompt "select uart parity"
+        depends on BT_LE_HCI_INTERFACE_USE_UART
+        default BT_LE_HCI_UART_UART_PARITY_DISABLE
+
+        config BT_LE_HCI_UART_UART_PARITY_DISABLE
+            bool "PARITY_DISABLE"
+            help
+                UART_PARITY_DISABLE
+        config BT_LE_HCI_UART_UART_PARITY_EVEN
+            bool "PARITY_EVEN"
+            help
+                UART_PARITY_EVEN
+        config BT_LE_HCI_UART_UART_PARITY_ODD
+            bool "PARITY_ODD"
+            help
+                UART_PARITY_ODD
+    endchoice
 
+    config BT_LE_HCI_UART_TASK_STACK_SIZE
+        int "HCI uart task stack size"
+        depends on BT_LE_HCI_INTERFACE_USE_UART
+        default 1000
+        help
+            Set the size of uart task stack
 endmenu
 
-config BT_LE_CONTROLLER_TASK_STACK_SIZE
-    int "Controller task stack size"
-    default 5120 if BLE_MESH
-    default 4096
+config BT_LE_CONTROLLER_NPL_OS_PORTING_SUPPORT
+    bool
+    default y
     help
-            This configures stack size of NimBLE controller task
+        Enable NPL porting for controller.
 
-config BT_LE_LL_RESOLV_LIST_SIZE
-    int "BLE LL Resolving list size"
-    range 1 5 if IDF_TARGET_ESP32C2
-    default 4
-    help
-            Configure the size of resolving list used in link layer.
 
-menuconfig BT_LE_SECURITY_ENABLE
-    bool "Enable BLE SM feature"
+menuconfig BT_LE_50_FEATURE_SUPPORT
+    bool "Enable BLE 5 feature"
     depends on !BT_NIMBLE_ENABLED
     default y
     help
-            Enable BLE sm feature
+        Enable BLE 5 feature
 
-config BT_LE_SM_LEGACY
-    bool "Security manager legacy pairing"
-    depends on BT_LE_SECURITY_ENABLE
+config BT_LE_LL_CFG_FEAT_LE_2M_PHY
+    bool "Enable 2M Phy"
+    depends on BT_LE_50_FEATURE_SUPPORT
     default y
     help
-        Enable security manager legacy pairing
+        Enable 2M-PHY
 
-config BT_LE_SM_SC
-    bool "Security manager secure connections (4.2)"
-    depends on BT_LE_SECURITY_ENABLE
+config BT_LE_LL_CFG_FEAT_LE_CODED_PHY
+    bool "Enable coded Phy"
+    depends on BT_LE_50_FEATURE_SUPPORT
     default y
     help
-        Enable security manager secure connections
+        Enable coded-PHY
 
-config BT_LE_SM_SC_DEBUG_KEYS
-    bool "Use predefined public-private key pair"
-    default n
-    depends on BT_LE_SECURITY_ENABLE && BT_LE_SM_SC
+config BT_LE_EXT_ADV
+    bool "Enable extended advertising"
+    depends on BT_LE_50_FEATURE_SUPPORT
+    default y
     help
-        If this option is enabled, SM uses predefined DH key pair as described
-        in Core Specification, Vol. 3, Part H, 2.3.5.6.1. This allows to
-        decrypt air traffic easily and thus should only be used for debugging.
+        Enable this option to do extended advertising. Extended advertising
+        will be supported from BLE 5.0 onwards.
 
-config BT_LE_LL_CFG_FEAT_LE_ENCRYPTION
-    bool "Enable LE encryption"
-    depends on BT_LE_SECURITY_ENABLE
-    default y
+if BT_LE_EXT_ADV
+    config BT_LE_MAX_EXT_ADV_INSTANCES
+        int "Maximum number of extended advertising instances."
+        range 0 4
+        default 1
+        depends on BT_LE_EXT_ADV
+        help
+            Change this option to set maximum number of extended advertising
+            instances. Minimum there is always one instance of
+            advertising. Enter how many more advertising instances you
+            want.
+
+    config BT_LE_EXT_ADV_MAX_SIZE
+        int "Maximum length of the advertising data."
+        range 0 1650
+        default 1650
+        depends on BT_LE_EXT_ADV
+        help
+            Defines the length of the extended adv data. The value should not
+            exceed 1650.
+
+    config BT_LE_ENABLE_PERIODIC_ADV
+        bool "Enable periodic advertisement."
+        default y
+        depends on BT_LE_EXT_ADV
+        help
+            Enable this option to start periodic advertisement.
+
+    config BT_LE_PERIODIC_ADV_SYNC_TRANSFER
+        bool "Enable Transer Sync Events"
+        depends on BT_LE_ENABLE_PERIODIC_ADV
+        default y
+        help
+            This enables controller transfer periodic sync events to host
+
+endif
+
+config BT_LE_MAX_PERIODIC_SYNCS
+    int "Maximum number of periodic advertising syncs"
+    depends on BT_LE_50_FEATURE_SUPPORT && !BT_NIMBLE_ENABLED
+
+    range 0 3
+    default 1 if BT_LE_ENABLE_PERIODIC_ADV
+    default 0
+    help
+        Set this option to set the upper limit for number of periodic sync
+        connections. This should be less than maximum connections allowed by
+        controller.
+
+config BT_LE_MAX_PERIODIC_ADVERTISER_LIST
+    int "Maximum number of periodic advertiser list"
+    depends on BT_LE_50_FEATURE_SUPPORT && !BT_NIMBLE_ENABLED
+    range 1 5
+    default 5
     help
-            Enable encryption connection
+        Set this option to set the upper limit for number of periodic advertiser list.
 
 menu "Memory Settings"
     depends on !BT_NIMBLE_ENABLED
@@ -112,22 +187,22 @@ menu "Memory Settings"
             count.
 
     config BT_LE_MSYS_1_BLOCK_SIZE
-        int    "MSYS_1 Block Size"
+        int "MSYS_1 Block Size"
         default 256
         help
-                Dynamic memory size of block 1
+            Dynamic memory size of block 1
 
     config BT_LE_MSYS_2_BLOCK_COUNT
-        int    "MSYS_2 Block Count"
+        int "MSYS_2 Block Count"
         default 24
         help
-                Dynamic memory count
+            Dynamic memory count
 
     config BT_LE_MSYS_2_BLOCK_SIZE
-        int    "MSYS_2 Block Size"
+        int "MSYS_2 Block Size"
         default 320
         help
-                Dynamic memory size of block 2
+            Dynamic memory size of block 2
 
     config BT_LE_ACL_BUF_COUNT
         int "ACL Buffer count"
@@ -170,135 +245,95 @@ menu "Memory Settings"
             get dropped
 endmenu
 
-config BT_LE_CRYPTO_STACK_MBEDTLS
-    bool "Override TinyCrypt with mbedTLS for crypto computations"
-    default y
-    depends on !BT_NIMBLE_ENABLED
-    select MBEDTLS_ECP_RESTARTABLE
-    select MBEDTLS_CMAC_C
+config BT_LE_CONTROLLER_TASK_STACK_SIZE
+    int "Controller task stack size"
+    default 5120 if BLE_MESH
+    default 4096
     help
-        Enable this option to choose mbedTLS instead of TinyCrypt for crypto
-        computations.
+        This configures stack size of NimBLE controller task
 
-menuconfig BT_LE_50_FEATURE_SUPPORT
-    bool "Enable BLE 5 feature"
+config BT_LE_LL_RESOLV_LIST_SIZE
+    int "BLE LL Resolving list size"
+    range 1 5
+    default 4
+    help
+        Configure the size of resolving list used in link layer.
+
+menuconfig BT_LE_SECURITY_ENABLE
+    bool "Enable BLE SM feature"
     depends on !BT_NIMBLE_ENABLED
     default y
     help
-            Enable BLE 5 feature
+        Enable BLE sm feature
 
-config BT_LE_LL_CFG_FEAT_LE_2M_PHY
-    bool "Enable 2M Phy"
-    depends on BT_LE_50_FEATURE_SUPPORT
+config BT_LE_SM_LEGACY
+    bool "Security manager legacy pairing"
+    depends on BT_LE_SECURITY_ENABLE
     default y
     help
-            Enable 2M-PHY
+        Enable security manager legacy pairing
 
-config BT_LE_LL_CFG_FEAT_LE_CODED_PHY
-    bool "Enable coded Phy"
-    depends on BT_LE_50_FEATURE_SUPPORT
+config BT_LE_SM_SC
+    bool "Security manager secure connections (4.2)"
+    depends on BT_LE_SECURITY_ENABLE
     default y
     help
-            Enable coded-PHY
+        Enable security manager secure connections
 
-config BT_LE_EXT_ADV
-    bool "Enable extended advertising"
-    depends on BT_LE_50_FEATURE_SUPPORT
+config BT_LE_SM_SC_DEBUG_KEYS
+    bool "Use predefined public-private key pair"
     default n
+    depends on BT_LE_SECURITY_ENABLE && BT_LE_SM_SC
     help
-        Enable this option to do extended advertising. Extended advertising
-        will be supported from BLE 5.0 onwards.
-
-if BT_LE_EXT_ADV
-    config BT_LE_MAX_EXT_ADV_INSTANCES
-        int "Maximum number of extended advertising instances."
-        range 0 4
-        default 1 if BT_LE_EXT_ADV
-        default 0
-        depends on BT_LE_EXT_ADV
-        help
-            Change this option to set maximum number of extended advertising
-            instances. Minimum there is always one instance of
-            advertising. Enter how many more advertising instances you
-            want.
-
-    config BT_LE_EXT_ADV_MAX_SIZE
-        int "Maximum length of the advertising data."
-        range 0 1650
-        default 1650 if BT_LE_EXT_ADV
-        default 0
-        depends on BT_LE_EXT_ADV
-        help
-            Defines the length of the extended adv data. The value should not
-            exceed 1650.
-
-    config BT_LE_ENABLE_PERIODIC_ADV
-        bool "Enable periodic advertisement."
-        default y
-        depends on BT_LE_EXT_ADV
-        help
-            Enable this option to start periodic advertisement.
-
-    config BT_LE_PERIODIC_ADV_SYNC_TRANSFER
-        bool "Enable Transer Sync Events"
-        depends on BT_LE_ENABLE_PERIODIC_ADV
-        default y
-        help
-                This enables controller transfer periodic sync events to host
-
-endif
-
-config BT_LE_MAX_PERIODIC_SYNCS
-    int "Maximum number of periodic advertising syncs"
-    depends on BT_LE_50_FEATURE_SUPPORT && !BT_NIMBLE_ENABLED
+        If this option is enabled, SM uses predefined DH key pair as described
+        in Core Specification, Vol. 3, Part H, 2.3.5.6.1. This allows to
+        decrypt air traffic easily and thus should only be used for debugging.
 
-    range 0 8 if !IDF_TARGET_ESP32C2
-    range 0 3 if IDF_TARGET_ESP32C2
-    default 1 if BT_LE_ENABLE_PERIODIC_ADV
-    default 0
+config BT_LE_LL_CFG_FEAT_LE_ENCRYPTION
+    bool "Enable LE encryption"
+    depends on BT_LE_SECURITY_ENABLE
+    default y
     help
-        Set this option to set the upper limit for number of periodic sync
-        connections. This should be less than maximum connections allowed by
-        controller.
+        Enable encryption connection
 
-config BT_LE_MAX_PERIODIC_ADVERTISER_LIST
-    int "Maximum number of periodic advertiser list"
-    depends on BT_LE_50_FEATURE_SUPPORT && IDF_TARGET_ESP32C2 && !BT_NIMBLE_ENABLED
-    range 1 5
-    default 5 if BT_LE_50_FEATURE_SUPPORT
+config BT_LE_CRYPTO_STACK_MBEDTLS
+    bool "Override TinyCrypt with mbedTLS for crypto computations"
+    default y
+    depends on !BT_NIMBLE_ENABLED
+    select MBEDTLS_ECP_RESTARTABLE
+    select MBEDTLS_CMAC_C
     help
-        Set this option to set the upper limit for number of periodic advertiser list.
+        Enable this option to choose mbedTLS instead of TinyCrypt for crypto
+        computations.
 
 config BT_LE_WHITELIST_SIZE
     int "BLE white list size"
-    range 1 5 if IDF_TARGET_ESP32C2
-    default 5 if IDF_TARGET_ESP32C2
+    range 1 15
+    default 12
     depends on !BT_NIMBLE_ENABLED
 
     help
-            BLE list size
+        BLE list size
 
 config BT_LE_LL_DUP_SCAN_LIST_COUNT
     int "BLE duplicate scan list count"
     range 1 100
     default 20
     help
-            config the max count of duplicate scan list
+        config the max count of duplicate scan list
 
 config BT_LE_LL_SCA
     int "BLE Sleep clock accuracy"
     range 0 500
     default 60
     help
-            Sleep clock accuracy of our device (in ppm)
+        Sleep clock accuracy of our device (in ppm)
 
 config BT_LE_MAX_CONNECTIONS
     int "Maximum number of concurrent connections"
     depends on !BT_NIMBLE_ENABLED
-    range 1 8 if IDF_TARGET_ESP32H2
-    default 3 if IDF_TARGET_ESP32H2
-    range 1 2 if IDF_TARGET_ESP32C2
-    default 2 if IDF_TARGET_ESP32C2
+    range 1 2
+    default 2
     help
         Defines maximum number of concurrent BLE connections. For ESP32, user
         is expected to configure BTDM_CTRL_BLE_MAX_CONN from controller menu
@@ -311,23 +346,23 @@ choice BT_LE_COEX_PHY_CODED_TX_RX_TLIM
     default BT_LE_COEX_PHY_CODED_TX_RX_TLIM_DIS
     depends on !BT_NIMBLE_ENABLED
     help
-            When using PHY-Coded in BLE connection, limitation on max tx/rx time can be applied to
-            better avoid dramatic performance deterioration of Wi-Fi.
+        When using PHY-Coded in BLE connection, limitation on max tx/rx time can be applied to
+        better avoid dramatic performance deterioration of Wi-Fi.
 
-        config BT_LE_COEX_PHY_CODED_TX_RX_TLIM_EN
-            bool "Force Enable"
-            help
-                Always enable the limitation on max tx/rx time for Coded-PHY connection
+    config BT_LE_COEX_PHY_CODED_TX_RX_TLIM_EN
+        bool "Force Enable"
+        help
+            Always enable the limitation on max tx/rx time for Coded-PHY connection
 
-        config BT_LE_COEX_PHY_CODED_TX_RX_TLIM_DIS
-            bool "Force Disable"
-            help
-                Disable the limitation on max tx/rx time for Coded-PHY connection
+    config BT_LE_COEX_PHY_CODED_TX_RX_TLIM_DIS
+        bool "Force Disable"
+        help
+            Disable the limitation on max tx/rx time for Coded-PHY connection
 endchoice
 
 config BT_LE_COEX_PHY_CODED_TX_RX_TLIM_EFF
     int
-    default 0 if !BT_NIMBLE_ENABLED
+    depends on !BT_NIMBLE_ENABLED
     default 1 if BT_LE_COEX_PHY_CODED_TX_RX_TLIM_EN
     default 0 if BT_LE_COEX_PHY_CODED_TX_RX_TLIM_DIS
 

+ 60 - 63
components/bt/controller/esp32c2/bt.c

@@ -14,8 +14,6 @@
 
 #include "sdkconfig.h"
 
-#include "os/os.h"
-#include "sysinit/sysinit.h"
 #include "nimble/nimble_port.h"
 #include "nimble/nimble_port_freertos.h"
 
@@ -27,24 +25,21 @@
 #include "esp_coexist_internal.h"
 #endif
 
-#ifdef CONFIG_BT_LE_HCI_INTERFACE_USE_UART
-#include "transport/uart/ble_hci_uart.h"
-#else
-#include "transport/ram/ble_hci_ram.h"
-#endif
+#include "nimble/nimble_npl_os.h"
 #include "nimble/ble_hci_trans.h"
+#include "os/endian.h"
 
-#include "nimble/nimble_npl_os.h"
 #include "esp_bt.h"
 #include "esp_intr_alloc.h"
-#include "nimble/nimble_npl_os.h"
 #include "esp_sleep.h"
 #include "esp_pm.h"
 #include "esp_phy_init.h"
 #include "soc/syscon_reg.h"
 #include "soc/modem_clkrst_reg.h"
 #include "esp_private/periph_ctrl.h"
-#include "hal/hal_uart.h"
+#include "hci_uart.h"
+#include "bt_osi_mem.h"
+
 #ifdef CONFIG_BT_BLUEDROID_ENABLED
 #include "hci/hci_hal.h"
 #endif
@@ -86,8 +81,8 @@ struct ext_funcs_t {
     void *(* _malloc)(size_t size);
     void (*_free)(void *p);
     void (*_hal_uart_start_tx)(int);
-    int (*_hal_uart_init_cbs)(int, hal_uart_tx_char, hal_uart_tx_done, hal_uart_rx_char, void *);
-    int (*_hal_uart_config)(int, int32_t, uint8_t, uint8_t, enum hal_uart_parity, enum hal_uart_flow_ctl);
+    int (*_hal_uart_init_cbs)(int, hci_uart_tx_char, hci_uart_tx_done, hci_uart_rx_char, void *);
+    int (*_hal_uart_config)(int, int32_t, uint8_t, uint8_t, uart_parity_t, uart_hw_flowcontrol_t);
     int (*_hal_uart_close)(int);
     void (*_hal_uart_blocking_tx)(int, uint8_t);
     int (*_hal_uart_init)(int, void *);
@@ -108,7 +103,7 @@ struct ext_funcs_t {
 
 extern int ble_osi_coex_funcs_register(struct osi_coex_funcs_t *coex_funcs);
 extern int coex_core_ble_conn_dyn_prio_get(bool *low, bool *high);
-extern int ble_controller_init(struct esp_bt_controller_config_t *cfg);
+extern int ble_controller_init(esp_bt_controller_config_t *cfg);
 extern int ble_controller_deinit(void);
 extern int ble_controller_enable(uint8_t mode);
 extern int ble_controller_disable(void);
@@ -134,14 +129,16 @@ static void coex_schm_status_bit_set_wrapper(uint32_t type, uint32_t status);
 static void coex_schm_status_bit_clear_wrapper(uint32_t type, uint32_t status);
 static int task_create_wrapper(void *task_func, const char *name, uint32_t stack_depth, void *param, uint32_t prio, void *task_handle, uint32_t core_id);
 static void task_delete_wrapper(void *task_handle);
-static void hal_uart_start_tx_wrapper(int uart_no);
-static int hal_uart_init_cbs_wrapper(int uart_no, hal_uart_tx_char tx_func,
-                                     hal_uart_tx_done tx_done, hal_uart_rx_char rx_func, void *arg);
-static int hal_uart_config_wrapper(int uart_no, int32_t speed, uint8_t databits, uint8_t stopbits,
-                                   enum hal_uart_parity parity, enum hal_uart_flow_ctl flow_ctl);
-static int hal_uart_close_wrapper(int uart_no);
-static void hal_uart_blocking_tx_wrapper(int port, uint8_t data);
-static int hal_uart_init_wrapper(int uart_no, void *cfg);
+#if CONFIG_BT_LE_HCI_INTERFACE_USE_UART
+static void hci_uart_start_tx_wrapper(int uart_no);
+static int hci_uart_init_cbs_wrapper(int uart_no, hci_uart_tx_char tx_func,
+                                     hci_uart_tx_done tx_done, hci_uart_rx_char rx_func, void *arg);
+static int hci_uart_config_wrapper(int uart_no, int32_t speed, uint8_t databits, uint8_t stopbits,
+                                   uart_parity_t parity, uart_hw_flowcontrol_t flow_ctl);
+static int hci_uart_close_wrapper(int uart_no);
+static void hci_uart_blocking_tx_wrapper(int port, uint8_t data);
+static int hci_uart_init_wrapper(int uart_no, void *cfg);
+#endif
 static int esp_intr_alloc_wrapper(int source, int flags, intr_handler_t handler, void *arg, void **ret_handle_in);
 static int esp_intr_free_wrapper(void **ret_handle);
 static void osi_assert_wrapper(const uint32_t ln, const char *fn, uint32_t param1, uint32_t param2);
@@ -191,14 +188,16 @@ struct ext_funcs_t ext_funcs_ro = {
     .ext_version = EXT_FUNC_VERSION,
     ._esp_intr_alloc = esp_intr_alloc_wrapper,
     ._esp_intr_free = esp_intr_free_wrapper,
-    ._malloc = malloc,
-    ._free = free,
-    ._hal_uart_start_tx     =  hal_uart_start_tx_wrapper,
-    ._hal_uart_init_cbs     =  hal_uart_init_cbs_wrapper,
-    ._hal_uart_config       =  hal_uart_config_wrapper,
-    ._hal_uart_close        =  hal_uart_close_wrapper,
-    ._hal_uart_blocking_tx  =  hal_uart_blocking_tx_wrapper,
-    ._hal_uart_init         =  hal_uart_init_wrapper,
+    ._malloc = bt_osi_mem_malloc_internal,
+    ._free = bt_osi_mem_free,
+#if CONFIG_BT_LE_HCI_INTERFACE_USE_UART
+    ._hal_uart_start_tx     =  hci_uart_start_tx_wrapper,
+    ._hal_uart_init_cbs     =  hci_uart_init_cbs_wrapper,
+    ._hal_uart_config       =  hci_uart_config_wrapper,
+    ._hal_uart_close        =  hci_uart_close_wrapper,
+    ._hal_uart_blocking_tx  =  hci_uart_blocking_tx_wrapper,
+    ._hal_uart_init         =  hci_uart_init_wrapper,
+#endif //CONFIG_BT_LE_HCI_INTERFACE_USE_UART
     ._task_create = task_create_wrapper,
     ._task_delete = task_delete_wrapper,
     ._osi_assert = osi_assert_wrapper,
@@ -328,56 +327,53 @@ static void task_delete_wrapper(void *task_handle)
     vTaskDelete(task_handle);
 }
 
-static void hal_uart_start_tx_wrapper(int uart_no)
-{
 #ifdef CONFIG_BT_LE_HCI_INTERFACE_USE_UART
-    hal_uart_start_tx(uart_no);
-#endif
+static void hci_uart_start_tx_wrapper(int uart_no)
+{
+    hci_uart_start_tx(uart_no);
 }
 
-static int hal_uart_init_cbs_wrapper(int uart_no, hal_uart_tx_char tx_func,
-                                     hal_uart_tx_done tx_done, hal_uart_rx_char rx_func, void *arg)
+static int hci_uart_init_cbs_wrapper(int uart_no, hci_uart_tx_char tx_func,
+                                     hci_uart_tx_done tx_done, hci_uart_rx_char rx_func, void *arg)
 {
     int rc = -1;
-#ifdef CONFIG_BT_LE_HCI_INTERFACE_USE_UART
-    rc = hal_uart_init_cbs(uart_no, tx_func, tx_done, rx_func, arg);
-#endif
+    rc = hci_uart_init_cbs(uart_no, tx_func, tx_done, rx_func, arg);
     return rc;
 }
 
-static int hal_uart_config_wrapper(int uart_no, int32_t speed, uint8_t databits, uint8_t stopbits,
-                                   enum hal_uart_parity parity, enum hal_uart_flow_ctl flow_ctl)
+
+static int hci_uart_config_wrapper(int port_num, int32_t baud_rate, uint8_t data_bits, uint8_t stop_bits,
+                                   uart_parity_t parity, uart_hw_flowcontrol_t flow_ctl)
 {
     int rc = -1;
-#ifdef CONFIG_BT_LE_HCI_INTERFACE_USE_UART
-    rc = hal_uart_config(uart_no, speed, databits, stopbits, parity, flow_ctl);
-#endif
+    rc = hci_uart_config(port_num, baud_rate, data_bits, stop_bits, parity, flow_ctl);
     return rc;
 }
 
-static int hal_uart_close_wrapper(int uart_no)
+static int hci_uart_close_wrapper(int uart_no)
 {
     int rc = -1;
-#ifdef CONFIG_BT_LE_HCI_INTERFACE_USE_UART
-    rc = hal_uart_close(uart_no);
-#endif
+    rc = hci_uart_close(uart_no);
     return rc;
 }
 
-static void hal_uart_blocking_tx_wrapper(int port, uint8_t data)
+static void hci_uart_blocking_tx_wrapper(int port, uint8_t data)
 {
-#ifdef CONFIG_BT_LE_HCI_INTERFACE_USE_UART
-    hal_uart_blocking_tx(port, data);
-#endif
+    //This function is nowhere to use.
 }
 
-static int hal_uart_init_wrapper(int uart_no, void *cfg)
+static int hci_uart_init_wrapper(int uart_no, void *cfg)
 {
-    int rc = -1;
-#ifdef CONFIG_BT_LE_HCI_INTERFACE_USE_UART
-    rc = hal_uart_init(uart_no, cfg);
-#endif
-    return rc;
+    //This function is nowhere to use.
+    return 0;
+}
+
+#endif //CONFIG_BT_LE_HCI_INTERFACE_USE_UART
+
+static int ble_hci_unregistered_hook(void*, void*)
+{
+    ESP_LOGD(NIMBLE_PORT_LOG_TAG,"%s ble hci rx_evt is not registered.",__func__);
+    return 0;
 }
 
 static int esp_intr_alloc_wrapper(int source, int flags, intr_handler_t handler, void *arg, void **ret_handle_in)
@@ -494,12 +490,12 @@ void controller_sleep_init(void)
     if (esp_timer_create(&create_args, &s_btdm_slp_tmr) != ESP_OK) {
         goto error;
     }
-    ESP_LOGW(NIMBLE_PORT_LOG_TAG, "Enable light sleep, the wake up source is ESP timer\n");
+    ESP_LOGW(NIMBLE_PORT_LOG_TAG, "Enable light sleep, the wake up source is ESP timer");
 #endif //CONFIG_BT_LE_WAKEUP_SOURCE_CPU_RTC_TIMER
 
 #ifdef CONFIG_BT_LE_WAKEUP_SOURCE_BLE_RTC_TIMER
     esp_sleep_enable_bt_wakeup();
-    ESP_LOGW(NIMBLE_PORT_LOG_TAG, "Enable light sleep, the wake up source is BLE timer\n");
+    ESP_LOGW(NIMBLE_PORT_LOG_TAG, "Enable light sleep, the wake up source is BLE timer");
 #endif // CONFIG_BT_LE_WAKEUP_SOURCE_BLE_RTC_TIMER
 
     s_pm_lock_acquired = true;
@@ -590,7 +586,7 @@ void ble_rtc_clk_init(void)
 }
 
 
-esp_err_t esp_bt_controller_init(struct esp_bt_controller_config_t *cfg)
+esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg)
 {
     if (ble_controller_status != ESP_BT_CONTROLLER_STATUS_IDLE) {
         ESP_LOGW(NIMBLE_PORT_LOG_TAG, "invalid controller state");
@@ -672,9 +668,10 @@ esp_err_t esp_bt_controller_init(struct esp_bt_controller_config_t *cfg)
     esp_ble_ll_set_public_addr(mac);
 
     ble_controller_status = ESP_BT_CONTROLLER_STATUS_INITED;
-#ifdef CONFIG_BT_BLUEDROID_ENABLED
-    ble_hci_trans_cfg_hs(ble_hs_hci_rx_evt, NULL, ble_hs_rx_data, NULL);
-#endif
+
+    ble_hci_trans_cfg_hs((ble_hci_trans_rx_cmd_fn *)ble_hci_unregistered_hook,NULL,
+                         (ble_hci_trans_rx_acl_fn *)ble_hci_unregistered_hook,NULL);
+
     return ESP_OK;
 }
 

+ 224 - 140
components/bt/controller/esp32h2/Kconfig.in

@@ -8,11 +8,11 @@ menu "HCI Config"
         config BT_LE_HCI_INTERFACE_USE_RAM
             bool "ram"
             help
-                    Use RAM as HCI interface
+                Use RAM as HCI interface
         config BT_LE_HCI_INTERFACE_USE_UART
             bool "uart"
             help
-                    Use UART as HCI interface
+                Use UART as HCI interface
     endchoice
 
     config BT_LE_HCI_UART_PORT
@@ -22,6 +22,11 @@ menu "HCI Config"
         help
             Set the port number of HCI UART
 
+    config BT_LE_HCI_UART_FLOWCTRL
+        bool "HCI uart Hardware Flow ctrl"
+        depends on BT_LE_HCI_INTERFACE_USE_UART
+        default n
+
     config BT_LE_HCI_UART_TX_PIN
         int "HCI uart Tx gpio"
         depends on BT_LE_HCI_INTERFACE_USE_UART
@@ -32,151 +37,82 @@ menu "HCI Config"
         depends on BT_LE_HCI_INTERFACE_USE_UART
         default 10
 
-    config BT_LE_HCI_UART_TASK_STACK_SIZE
-        int "HCI uart task stack size"
-        depends on BT_LE_HCI_INTERFACE_USE_UART
-        default 1000
-        help
-                Set the size of uart task stack
+    config BT_LE_HCI_UART_RTS_PIN
+        int "HCI uart RTS gpio"
+        depends on BT_LE_HCI_UART_FLOWCTRL
+        default 4
+
+    config BT_LE_HCI_UART_CTS_PIN
+        int "HCI uart CTS gpio"
+        depends on BT_LE_HCI_UART_FLOWCTRL
+        default 5
 
     config BT_LE_HCI_UART_BAUD
         int "HCI uart baudrate"
         depends on BT_LE_HCI_INTERFACE_USE_UART
         default 921600
         help
-                HCI uart baud rate 115200 ~ 1000000
-
-endmenu
-
-config BT_LE_CONTROLLER_TASK_STACK_SIZE
-    int "Controller task stack size"
-    default 5120 if BLE_MESH
-    default 4096
-    help
-            This configures stack size of NimBLE controller task
-
-config BT_LE_LL_RESOLV_LIST_SIZE
-    int "BLE LL Resolving list size"
-    range 1 5 if IDF_TARGET_ESP32C2
-    default 4
-    help
-            Configure the size of resolving list used in link layer.
-
-menuconfig BT_LE_SECURITY_ENABLE
-    bool "Enable BLE SM feature"
-    depends on !BT_NIMBLE_ENABLED
-    default y
-    help
-            Enable BLE sm feature
-
-config BT_LE_SM_LEGACY
-    bool "Security manager legacy pairing"
-    depends on BT_LE_SECURITY_ENABLE
-    default y
-    help
-        Enable security manager legacy pairing
-
-config BT_LE_SM_SC
-    bool "Security manager secure connections (4.2)"
-    depends on BT_LE_SECURITY_ENABLE
-    default y
-    help
-        Enable security manager secure connections
-
-config BT_LE_SM_SC_DEBUG_KEYS
-    bool "Use predefined public-private key pair"
-    default n
-    depends on BT_LE_SECURITY_ENABLE && BT_LE_SM_SC
-    help
-        If this option is enabled, SM uses predefined DH key pair as described
-        in Core Specification, Vol. 3, Part H, 2.3.5.6.1. This allows to
-        decrypt air traffic easily and thus should only be used for debugging.
-
-config BT_LE_LL_CFG_FEAT_LE_ENCRYPTION
-    bool "Enable LE encryption"
-    depends on BT_LE_SECURITY_ENABLE
-    default y
-    help
-            Enable encryption connection
-
-menu "Memory Settings"
-    depends on !BT_NIMBLE_ENABLED
-    config BT_LE_ACL_BUF_COUNT
-        int "ACL Buffer count"
-        default 24
-        help
-            The number of ACL data buffers.
+            HCI uart baud rate 115200 ~ 1000000
 
-    config BT_LE_ACL_BUF_SIZE
-        int "ACL Buffer size"
-        default 255
-        help
-            This is the maximum size of the data portion of HCI ACL data packets.
-            It does not include the HCI data header (of 4 bytes)
-
-    config BT_LE_HCI_EVT_BUF_SIZE
-        int "HCI Event Buffer size"
-        default 257 if BT_LE_EXT_ADV
-        default 70
-        help
-            This is the size of each HCI event buffer in bytes. In case of
-            extended advertising, packets can be fragmented. 257 bytes is the
-            maximum size of a packet.
+    choice BT_LE_HCI_UART_PARITY
+        prompt "select uart parity"
+        depends on BT_LE_HCI_INTERFACE_USE_UART
+        default BT_LE_HCI_UART_UART_PARITY_DISABLE
 
-    config BT_LE_HCI_EVT_HI_BUF_COUNT
-        int "High Priority HCI Event Buffer count"
-        default 30
-        help
-            This is the high priority HCI events' buffer size. High-priority
-            event buffers are for everything except advertising reports. If there
-            are no free high-priority event buffers then host will try to allocate a
-            low-priority buffer instead
+        config BT_LE_HCI_UART_UART_PARITY_DISABLE
+            bool "PARITY_DISABLE"
+            help
+                UART_PARITY_DISABLE
+        config BT_LE_HCI_UART_UART_PARITY_EVEN
+            bool "PARITY_EVEN"
+            help
+                UART_PARITY_EVEN
+        config BT_LE_HCI_UART_UART_PARITY_ODD
+            bool "PARITY_ODD"
+            help
+                UART_PARITY_ODD
+    endchoice
 
-    config BT_LE_HCI_EVT_LO_BUF_COUNT
-        int "Low Priority HCI Event Buffer count"
-        default 8
+    config BT_LE_HCI_UART_TASK_STACK_SIZE
+        int "HCI uart task stack size"
+        depends on BT_LE_HCI_INTERFACE_USE_UART
+        default 1000
         help
-            This is the low priority HCI events' buffer size. Low-priority event
-            buffers are only used for advertising reports. If there are no free
-            low-priority event buffers, then an incoming advertising report will
-            get dropped
+            Set the size of uart task stack
 endmenu
 
-config BT_LE_CRYPTO_STACK_MBEDTLS
-    bool "Override TinyCrypt with mbedTLS for crypto computations"
+config BT_LE_CONTROLLER_NPL_OS_PORTING_SUPPORT
+    bool
     default y
-    depends on !BT_NIMBLE_ENABLED
-    select MBEDTLS_ECP_RESTARTABLE
-    select MBEDTLS_CMAC_C
     help
-        Enable this option to choose mbedTLS instead of TinyCrypt for crypto
-        computations.
+        Enable NPL porting for controller.
+
 
 menuconfig BT_LE_50_FEATURE_SUPPORT
     bool "Enable BLE 5 feature"
     depends on !BT_NIMBLE_ENABLED
     default y
     help
-            Enable BLE 5 feature
+        Enable BLE 5 feature
 
 config BT_LE_LL_CFG_FEAT_LE_2M_PHY
     bool "Enable 2M Phy"
     depends on BT_LE_50_FEATURE_SUPPORT
     default y
     help
-            Enable 2M-PHY
+        Enable 2M-PHY
 
 config BT_LE_LL_CFG_FEAT_LE_CODED_PHY
     bool "Enable coded Phy"
     depends on BT_LE_50_FEATURE_SUPPORT
     default y
     help
-            Enable coded-PHY
+        Enable coded-PHY
 
 config BT_LE_EXT_ADV
     bool "Enable extended advertising"
     depends on BT_LE_50_FEATURE_SUPPORT
-    default n
+    default y
     help
         Enable this option to do extended advertising. Extended advertising
         will be supported from BLE 5.0 onwards.
@@ -185,8 +121,7 @@ if BT_LE_EXT_ADV
     config BT_LE_MAX_EXT_ADV_INSTANCES
         int "Maximum number of extended advertising instances."
         range 0 4
-        default 1 if BT_LE_EXT_ADV
-        default 0
+        default 1
         depends on BT_LE_EXT_ADV
         help
             Change this option to set maximum number of extended advertising
@@ -197,8 +132,7 @@ if BT_LE_EXT_ADV
     config BT_LE_EXT_ADV_MAX_SIZE
         int "Maximum length of the advertising data."
         range 0 1650
-        default 1650 if BT_LE_EXT_ADV
-        default 0
+        default 1650
         depends on BT_LE_EXT_ADV
         help
             Defines the length of the extended adv data. The value should not
@@ -216,7 +150,7 @@ if BT_LE_EXT_ADV
         depends on BT_LE_ENABLE_PERIODIC_ADV
         default y
         help
-                This enables controller transfer periodic sync events to host
+            This enables controller transfer periodic sync events to host
 
 endif
 
@@ -224,8 +158,7 @@ config BT_LE_MAX_PERIODIC_SYNCS
     int "Maximum number of periodic advertising syncs"
     depends on BT_LE_50_FEATURE_SUPPORT && !BT_NIMBLE_ENABLED
 
-    range 0 8 if !IDF_TARGET_ESP32C2
-    range 0 3 if IDF_TARGET_ESP32C2
+    range 0 3
     default 1 if BT_LE_ENABLE_PERIODIC_ADV
     default 0
     help
@@ -235,42 +168,172 @@ config BT_LE_MAX_PERIODIC_SYNCS
 
 config BT_LE_MAX_PERIODIC_ADVERTISER_LIST
     int "Maximum number of periodic advertiser list"
-    depends on BT_LE_50_FEATURE_SUPPORT && IDF_TARGET_ESP32C2 && !BT_NIMBLE_ENABLED
+    depends on BT_LE_50_FEATURE_SUPPORT && !BT_NIMBLE_ENABLED
     range 1 5
-    default 5 if BT_LE_50_FEATURE_SUPPORT
+    default 5
     help
         Set this option to set the upper limit for number of periodic advertiser list.
 
+menu "Memory Settings"
+    depends on !BT_NIMBLE_ENABLED
+
+    config BT_LE_MSYS_1_BLOCK_COUNT
+        int "MSYS_1 Block Count"
+        default 12
+        help
+            MSYS is a system level mbuf registry. For prepare write & prepare
+            responses MBUFs are allocated out of msys_1 pool. For NIMBLE_MESH
+            enabled cases, this block count is increased by 8 than user defined
+            count.
+
+    config BT_LE_MSYS_1_BLOCK_SIZE
+        int "MSYS_1 Block Size"
+        default 256
+        help
+            Dynamic memory size of block 1
+
+    config BT_LE_MSYS_2_BLOCK_COUNT
+        int "MSYS_2 Block Count"
+        default 24
+        help
+            Dynamic memory count
+
+    config BT_LE_MSYS_2_BLOCK_SIZE
+        int "MSYS_2 Block Size"
+        default 320
+        help
+            Dynamic memory size of block 2
+
+    config BT_LE_ACL_BUF_COUNT
+        int "ACL Buffer count"
+        default 24
+        help
+            The number of ACL data buffers.
+
+    config BT_LE_ACL_BUF_SIZE
+        int "ACL Buffer size"
+        default 255
+        help
+            This is the maximum size of the data portion of HCI ACL data packets.
+            It does not include the HCI data header (of 4 bytes)
+
+    config BT_LE_HCI_EVT_BUF_SIZE
+        int "HCI Event Buffer size"
+        default 257 if BT_LE_EXT_ADV
+        default 70
+        help
+            This is the size of each HCI event buffer in bytes. In case of
+            extended advertising, packets can be fragmented. 257 bytes is the
+            maximum size of a packet.
+
+    config BT_LE_HCI_EVT_HI_BUF_COUNT
+        int "High Priority HCI Event Buffer count"
+        default 30
+        help
+            This is the high priority HCI events' buffer size. High-priority
+            event buffers are for everything except advertising reports. If there
+            are no free high-priority event buffers then host will try to allocate a
+            low-priority buffer instead
+
+    config BT_LE_HCI_EVT_LO_BUF_COUNT
+        int "Low Priority HCI Event Buffer count"
+        default 8
+        help
+            This is the low priority HCI events' buffer size. Low-priority event
+            buffers are only used for advertising reports. If there are no free
+            low-priority event buffers, then an incoming advertising report will
+            get dropped
+endmenu
+
+config BT_LE_CONTROLLER_TASK_STACK_SIZE
+    int "Controller task stack size"
+    default 5120 if BLE_MESH
+    default 4096
+    help
+        This configures stack size of NimBLE controller task
+
+config BT_LE_LL_RESOLV_LIST_SIZE
+    int "BLE LL Resolving list size"
+    range 1 5
+    default 4
+    help
+        Configure the size of resolving list used in link layer.
+
+menuconfig BT_LE_SECURITY_ENABLE
+    bool "Enable BLE SM feature"
+    depends on !BT_NIMBLE_ENABLED
+    default y
+    help
+        Enable BLE sm feature
+
+config BT_LE_SM_LEGACY
+    bool "Security manager legacy pairing"
+    depends on BT_LE_SECURITY_ENABLE
+    default y
+    help
+        Enable security manager legacy pairing
+
+config BT_LE_SM_SC
+    bool "Security manager secure connections (4.2)"
+    depends on BT_LE_SECURITY_ENABLE
+    default y
+    help
+        Enable security manager secure connections
+
+config BT_LE_SM_SC_DEBUG_KEYS
+    bool "Use predefined public-private key pair"
+    default n
+    depends on BT_LE_SECURITY_ENABLE && BT_LE_SM_SC
+    help
+        If this option is enabled, SM uses predefined DH key pair as described
+        in Core Specification, Vol. 3, Part H, 2.3.5.6.1. This allows to
+        decrypt air traffic easily and thus should only be used for debugging.
+
+config BT_LE_LL_CFG_FEAT_LE_ENCRYPTION
+    bool "Enable LE encryption"
+    depends on BT_LE_SECURITY_ENABLE
+    default y
+    help
+        Enable encryption connection
+
+config BT_LE_CRYPTO_STACK_MBEDTLS
+    bool "Override TinyCrypt with mbedTLS for crypto computations"
+    default y
+    depends on !BT_NIMBLE_ENABLED
+    select MBEDTLS_ECP_RESTARTABLE
+    select MBEDTLS_CMAC_C
+    help
+        Enable this option to choose mbedTLS instead of TinyCrypt for crypto
+        computations.
+
 config BT_LE_WHITELIST_SIZE
     int "BLE white list size"
-    range 1 5 if IDF_TARGET_ESP32C2
-    default 5 if IDF_TARGET_ESP32C2
+    range 1 15
+    default 12
     depends on !BT_NIMBLE_ENABLED
 
     help
-            BLE list size
+        BLE list size
 
 config BT_LE_LL_DUP_SCAN_LIST_COUNT
     int "BLE duplicate scan list count"
     range 1 100
     default 20
     help
-            config the max count of duplicate scan list
+        config the max count of duplicate scan list
 
 config BT_LE_LL_SCA
     int "BLE Sleep clock accuracy"
     range 0 500
     default 60
     help
-            Sleep clock accuracy of our device (in ppm)
+        Sleep clock accuracy of our device (in ppm)
 
 config BT_LE_MAX_CONNECTIONS
     int "Maximum number of concurrent connections"
     depends on !BT_NIMBLE_ENABLED
-    range 1 8 if IDF_TARGET_ESP32H2
-    default 3 if IDF_TARGET_ESP32H2
-    range 1 2 if IDF_TARGET_ESP32C2
-    default 2 if IDF_TARGET_ESP32C2
+    range 1 8
+    default 3
     help
         Defines maximum number of concurrent BLE connections. For ESP32, user
         is expected to configure BTDM_CTRL_BLE_MAX_CONN from controller menu
@@ -283,22 +346,43 @@ choice BT_LE_COEX_PHY_CODED_TX_RX_TLIM
     default BT_LE_COEX_PHY_CODED_TX_RX_TLIM_DIS
     depends on !BT_NIMBLE_ENABLED
     help
-            When using PHY-Coded in BLE connection, limitation on max tx/rx time can be applied to
-            better avoid dramatic performance deterioration of Wi-Fi.
+        When using PHY-Coded in BLE connection, limitation on max tx/rx time can be applied to
+        better avoid dramatic performance deterioration of Wi-Fi.
 
-        config BT_LE_COEX_PHY_CODED_TX_RX_TLIM_EN
-            bool "Force Enable"
-            help
-                Always enable the limitation on max tx/rx time for Coded-PHY connection
+    config BT_LE_COEX_PHY_CODED_TX_RX_TLIM_EN
+        bool "Force Enable"
+        help
+            Always enable the limitation on max tx/rx time for Coded-PHY connection
 
-        config BT_LE_COEX_PHY_CODED_TX_RX_TLIM_DIS
-            bool "Force Disable"
-            help
-                Disable the limitation on max tx/rx time for Coded-PHY connection
+    config BT_LE_COEX_PHY_CODED_TX_RX_TLIM_DIS
+        bool "Force Disable"
+        help
+            Disable the limitation on max tx/rx time for Coded-PHY connection
 endchoice
 
 config BT_LE_COEX_PHY_CODED_TX_RX_TLIM_EFF
     int
-    default 0 if !BT_NIMBLE_ENABLED
+    depends on !BT_NIMBLE_ENABLED
     default 1 if BT_LE_COEX_PHY_CODED_TX_RX_TLIM_EN
     default 0 if BT_LE_COEX_PHY_CODED_TX_RX_TLIM_DIS
+
+config BT_LE_SLEEP_ENABLE
+    bool "Enable BLE sleep"
+    default n
+    help
+        Enable BLE sleep
+
+choice BT_LE_WAKEUP_SOURCE
+    prompt "BLE light sleep wakeup source"
+    depends on BT_LE_SLEEP_ENABLE
+    default BT_LE_WAKEUP_SOURCE_BLE_RTC_TIMER
+    config BT_LE_WAKEUP_SOURCE_CPU_RTC_TIMER
+        bool "Use ESP timer to wakeup CPU"
+        help
+            Use esp timer to wakeup CPU
+
+    config BT_LE_WAKEUP_SOURCE_BLE_RTC_TIMER
+        bool "Use BLE rtc timer to wakeup CPU"
+        help
+            Use BLE rtc timer to wakeup CPU
+endchoice

+ 373 - 206
components/bt/controller/esp32h2/bt.c

@@ -9,13 +9,11 @@
 #include <stdio.h>
 #include <string.h>
 
-#include <esp_random.h>
+#include "esp_random.h"
 #include <esp_mac.h>
 
 #include "sdkconfig.h"
 
-#include "os/os.h"
-#include "sysinit/sysinit.h"
 #include "nimble/nimble_port.h"
 #include "nimble/nimble_port_freertos.h"
 
@@ -27,21 +25,20 @@
 #include "esp_coexist_internal.h"
 #endif
 
-#ifdef CONFIG_BT_LE_HCI_INTERFACE_USE_UART
-#include "transport/uart/ble_hci_uart.h"
-#else
-#include "transport/ram/ble_hci_ram.h"
-#endif
+#include "nimble/nimble_npl_os.h"
 #include "nimble/ble_hci_trans.h"
+#include "os/endian.h"
 
-#include "nimble/nimble_npl_os.h"
 #include "esp_bt.h"
 #include "esp_intr_alloc.h"
 #include "esp_sleep.h"
 #include "esp_pm.h"
 #include "esp_phy_init.h"
 #include "soc/system_reg.h"
-#include "hal/hal_uart.h"
+
+#include "hci_uart.h"
+#include "bt_osi_mem.h"
+
 #ifdef CONFIG_BT_BLUEDROID_ENABLED
 #include "hci/hci_hal.h"
 #endif
@@ -50,7 +47,8 @@
 #include "freertos/task.h"
 
 #include "esp_private/periph_ctrl.h"
-#include "nimble/hci_common.h"
+#include "esp_sleep.h"
+
 /* Macro definition
  ************************************************************************
  */
@@ -79,8 +77,8 @@ struct ext_funcs_t {
     void *(* _malloc)(size_t size);
     void (*_free)(void *p);
     void (*_hal_uart_start_tx)(int);
-    int (*_hal_uart_init_cbs)(int, hal_uart_tx_char, hal_uart_tx_done, hal_uart_rx_char, void *);
-    int (*_hal_uart_config)(int, int32_t, uint8_t, uint8_t, enum hal_uart_parity, enum hal_uart_flow_ctl);
+    int (*_hal_uart_init_cbs)(int, hci_uart_tx_char, hci_uart_tx_done, hci_uart_rx_char, void *);
+    int (*_hal_uart_config)(int, int32_t, uint8_t, uint8_t, uart_parity_t, uart_hw_flowcontrol_t);
     int (*_hal_uart_close)(int);
     void (*_hal_uart_blocking_tx)(int, uint8_t);
     int (*_hal_uart_init)(int, void *);
@@ -99,7 +97,7 @@ struct ext_funcs_t {
 extern int ble_plf_set_log_level(int level);
 extern int ble_osi_coex_funcs_register(struct osi_coex_funcs_t *coex_funcs);
 extern int coex_core_ble_conn_dyn_prio_get(bool *low, bool *high);
-extern int ble_controller_init(struct esp_bt_controller_config_t *cfg);
+extern int ble_controller_init(esp_bt_controller_config_t *cfg);
 extern int ble_controller_deinit(void);
 extern int ble_controller_enable(uint8_t mode);
 extern int ble_controller_disable(void);
@@ -119,7 +117,6 @@ extern uint32_t r_os_cputime_ticks_to_usecs(uint32_t ticks);
 extern void r_ble_ll_rfmgmt_set_sleep_cb(void *s_cb, void *w_cb, void *s_arg, void *w_arg, uint32_t us_to_enabled);
 extern int os_msys_init(void);
 extern void os_msys_buf_free(void);
-extern void esp_ble_register_trace_funcs(struct ble_ll_trace_func_t *funcs);
 extern void bt_bb_set_le_tx_on_delay(uint32_t delay_us);
 
 /* Local Function Declaration
@@ -129,14 +126,16 @@ static void coex_schm_status_bit_set_wrapper(uint32_t type, uint32_t status);
 static void coex_schm_status_bit_clear_wrapper(uint32_t type, uint32_t status);
 static int task_create_wrapper(void *task_func, const char *name, uint32_t stack_depth, void *param, uint32_t prio, void *task_handle, uint32_t core_id);
 static void task_delete_wrapper(void *task_handle);
-static void hal_uart_start_tx_wrapper(int uart_no);
-static int hal_uart_init_cbs_wrapper(int uart_no, hal_uart_tx_char tx_func,
-                                     hal_uart_tx_done tx_done, hal_uart_rx_char rx_func, void *arg);
-static int hal_uart_config_wrapper(int uart_no, int32_t speed, uint8_t databits, uint8_t stopbits,
-                                   enum hal_uart_parity parity, enum hal_uart_flow_ctl flow_ctl);
-static int hal_uart_close_wrapper(int uart_no);
-static void hal_uart_blocking_tx_wrapper(int port, uint8_t data);
-static int hal_uart_init_wrapper(int uart_no, void *cfg);
+#if CONFIG_BT_LE_HCI_INTERFACE_USE_UART
+static void hci_uart_start_tx_wrapper(int uart_no);
+static int hci_uart_init_cbs_wrapper(int uart_no, hci_uart_tx_char tx_func,
+                                     hci_uart_tx_done tx_done, hci_uart_rx_char rx_func, void *arg);
+static int hci_uart_config_wrapper(int uart_no, int32_t speed, uint8_t databits, uint8_t stopbits,
+                                   uart_parity_t parity, uart_hw_flowcontrol_t flow_ctl);
+static int hci_uart_close_wrapper(int uart_no);
+static void hci_uart_blocking_tx_wrapper(int port, uint8_t data);
+static int hci_uart_init_wrapper(int uart_no, void *cfg);
+#endif
 static int esp_intr_alloc_wrapper(int source, int flags, intr_handler_t handler, void *arg, void **ret_handle_in);
 static int esp_intr_free_wrapper(void **ret_handle);
 static void osi_assert_wrapper(const uint32_t ln, const char *fn, uint32_t param1, uint32_t param2);
@@ -148,29 +147,24 @@ static uint32_t osi_random_wrapper(void);
 
 /* Static variable declare */
 static DRAM_ATTR esp_bt_controller_status_t ble_controller_status = ESP_BT_CONTROLLER_STATUS_IDLE;
-static bool s_is_sleep_state = false;
-
-#ifdef CONFIG_PM_ENABLE
-#ifdef CONFIG_BT_NIMBLE_WAKEUP_SOURCE_CPU_RTC_TIMER
-uint32_t s_sleep_tick;
-#endif
-#endif
 
 #ifdef CONFIG_PM_ENABLE
-static DRAM_ATTR esp_timer_handle_t s_btdm_slp_tmr = NULL;
 static DRAM_ATTR esp_pm_lock_handle_t s_pm_lock = NULL;
 static bool s_pm_lock_acquired = true;
 static DRAM_ATTR bool s_btdm_allow_light_sleep;
 // pm_lock to prevent light sleep when using main crystal as Bluetooth low power clock
 static DRAM_ATTR esp_pm_lock_handle_t s_light_sleep_pm_lock;
-static void btdm_slp_tmr_callback(void *arg);
 #define BTDM_MIN_TIMER_UNCERTAINTY_US      (200)
 #endif /* #ifdef CONFIG_PM_ENABLE */
 
-#ifdef CONFIG_BT_NIMBLE_WAKEUP_SOURCE_BLE_RTC_TIMER
+#ifdef CONFIG_BT_LE_WAKEUP_SOURCE_BLE_RTC_TIMER
 #define BLE_RTC_DELAY_US                    (1100)
-#else
+#endif
+
+#ifdef CONFIG_BT_LE_WAKEUP_SOURCE_CPU_RTC_TIMER
 #define BLE_RTC_DELAY_US                    (0)
+static void btdm_slp_tmr_callback(void *arg);
+static DRAM_ATTR esp_timer_handle_t s_btdm_slp_tmr = NULL;
 #endif
 
 static const struct osi_coex_funcs_t s_osi_coex_funcs_ro = {
@@ -186,14 +180,16 @@ struct ext_funcs_t ext_funcs_ro = {
     .ext_version = 0xE0000001,
     ._esp_intr_alloc = esp_intr_alloc_wrapper,
     ._esp_intr_free = esp_intr_free_wrapper,
-    ._malloc = malloc,
-    ._free = free,
-    ._hal_uart_start_tx     =  hal_uart_start_tx_wrapper,
-    ._hal_uart_init_cbs     =  hal_uart_init_cbs_wrapper,
-    ._hal_uart_config       =  hal_uart_config_wrapper,
-    ._hal_uart_close        =  hal_uart_close_wrapper,
-    ._hal_uart_blocking_tx  =  hal_uart_blocking_tx_wrapper,
-    ._hal_uart_init         =  hal_uart_init_wrapper,
+    ._malloc = bt_osi_mem_malloc_internal,
+    ._free = bt_osi_mem_free,
+#if CONFIG_BT_LE_HCI_INTERFACE_USE_UART
+    ._hal_uart_start_tx     =  hci_uart_start_tx_wrapper,
+    ._hal_uart_init_cbs     =  hci_uart_init_cbs_wrapper,
+    ._hal_uart_config       =  hci_uart_config_wrapper,
+    ._hal_uart_close        =  hci_uart_close_wrapper,
+    ._hal_uart_blocking_tx  =  hci_uart_blocking_tx_wrapper,
+    ._hal_uart_init         =  hci_uart_init_wrapper,
+#endif //CONFIG_BT_LE_HCI_INTERFACE_USE_UART
     ._task_create = task_create_wrapper,
     ._task_delete = task_delete_wrapper,
     ._osi_assert = osi_assert_wrapper,
@@ -203,6 +199,7 @@ struct ext_funcs_t ext_funcs_ro = {
 
 static void IRAM_ATTR osi_assert_wrapper(const uint32_t ln, const char *fn, uint32_t param1, uint32_t param2)
 {
+    ESP_LOGE(NIMBLE_PORT_LOG_TAG, "BLE assert: line %d in function %s, param: 0x%x, 0x%x", ln, fn, param1, param2);
     assert(0);
 }
 
@@ -236,8 +233,7 @@ bool esp_vhci_host_check_send_available(void)
 /**
  * Allocates an mbuf for use by the nimble host.
  */
-static struct os_mbuf *
-ble_hs_mbuf_gen_pkt(uint16_t leading_space)
+static struct os_mbuf *ble_hs_mbuf_gen_pkt(uint16_t leading_space)
 {
     struct os_mbuf *om;
     int rc;
@@ -264,8 +260,7 @@ ble_hs_mbuf_gen_pkt(uint16_t leading_space)
  * @return                  An empty mbuf on success; null on memory
  *                              exhaustion.
  */
-struct os_mbuf *
-ble_hs_mbuf_acl_pkt(void)
+struct os_mbuf *ble_hs_mbuf_acl_pkt(void)
 {
     return ble_hs_mbuf_gen_pkt(4 + 1);
 }
@@ -300,7 +295,7 @@ esp_err_t esp_vhci_host_register_callback(const esp_vhci_host_callback_t *callba
         return ESP_FAIL;
     }
 
-    ble_hci_trans_cfg_hs(ble_hs_hci_rx_evt,NULL,ble_hs_rx_data,NULL);
+    ble_hci_trans_cfg_hs(ble_hs_hci_rx_evt, NULL, ble_hs_rx_data, NULL);
 
     return ESP_OK;
 }
@@ -316,56 +311,53 @@ static void task_delete_wrapper(void *task_handle)
     vTaskDelete(task_handle);
 }
 
-static void hal_uart_start_tx_wrapper(int uart_no)
-{
 #ifdef CONFIG_BT_LE_HCI_INTERFACE_USE_UART
-    hal_uart_start_tx(uart_no);
-#endif
+static void hci_uart_start_tx_wrapper(int uart_no)
+{
+    hci_uart_start_tx(uart_no);
 }
 
-static int hal_uart_init_cbs_wrapper(int uart_no, hal_uart_tx_char tx_func,
-                                     hal_uart_tx_done tx_done, hal_uart_rx_char rx_func, void *arg)
+static int hci_uart_init_cbs_wrapper(int uart_no, hci_uart_tx_char tx_func,
+                                     hci_uart_tx_done tx_done, hci_uart_rx_char rx_func, void *arg)
 {
     int rc = -1;
-#ifdef CONFIG_BT_LE_HCI_INTERFACE_USE_UART
-    rc = hal_uart_init_cbs(uart_no, tx_func, tx_done, rx_func, arg);
-#endif
+    rc = hci_uart_init_cbs(uart_no, tx_func, tx_done, rx_func, arg);
     return rc;
 }
 
-static int hal_uart_config_wrapper(int uart_no, int32_t speed, uint8_t databits, uint8_t stopbits,
-                                   enum hal_uart_parity parity, enum hal_uart_flow_ctl flow_ctl)
+
+static int hci_uart_config_wrapper(int port_num, int32_t baud_rate, uint8_t data_bits, uint8_t stop_bits,
+                                   uart_parity_t parity, uart_hw_flowcontrol_t flow_ctl)
 {
     int rc = -1;
-#ifdef CONFIG_BT_LE_HCI_INTERFACE_USE_UART
-    rc = hal_uart_config(uart_no, speed, databits, stopbits, parity, flow_ctl);
-#endif
+    rc = hci_uart_config(port_num, baud_rate, data_bits, stop_bits, parity, flow_ctl);
     return rc;
 }
 
-static int hal_uart_close_wrapper(int uart_no)
+static int hci_uart_close_wrapper(int uart_no)
 {
     int rc = -1;
-#ifdef CONFIG_BT_LE_HCI_INTERFACE_USE_UART
-    rc = hal_uart_close(uart_no);
-#endif
+    rc = hci_uart_close(uart_no);
     return rc;
 }
 
-static void hal_uart_blocking_tx_wrapper(int port, uint8_t data)
+static void hci_uart_blocking_tx_wrapper(int port, uint8_t data)
 {
-#ifdef CONFIG_BT_LE_HCI_INTERFACE_USE_UART
-    hal_uart_blocking_tx(port, data);
-#endif
+    //This function is nowhere to use.
 }
 
-static int hal_uart_init_wrapper(int uart_no, void *cfg)
+static int hci_uart_init_wrapper(int uart_no, void *cfg)
 {
-    int rc = -1;
-#ifdef CONFIG_BT_LE_HCI_INTERFACE_USE_UART
-    rc = hal_uart_init(uart_no, cfg);
-#endif
-    return rc;
+    //This function is nowhere to use.
+    return 0;
+}
+
+#endif //CONFIG_BT_LE_HCI_INTERFACE_USE_UART
+
+static int ble_hci_unregistered_hook(void*, void*)
+{
+    ESP_LOGD(NIMBLE_PORT_LOG_TAG,"%s ble hci rx_evt is not registered.",__func__);
+    return 0;
 }
 
 static int esp_intr_alloc_wrapper(int source, int flags, intr_handler_t handler, void *arg, void **ret_handle_in)
@@ -384,26 +376,32 @@ static int esp_intr_free_wrapper(void **ret_handle)
 
 IRAM_ATTR void controller_sleep_cb(uint32_t enable_tick, void *arg)
 {
-    if (s_is_sleep_state) {
-        ESP_LOGW(NIMBLE_PORT_LOG_TAG, "sleep state error");
-        assert(0);
-    }
-    s_is_sleep_state = true;
+    esp_phy_disable();
 #ifdef CONFIG_PM_ENABLE
-#ifdef CONFIG_BT_NIMBLE_WAKEUP_SOURCE_CPU_RTC_TIMER
-    uint32_t tick_invalid = *(uint32_t *)(arg);
-    if (!tick_invalid) {
-        s_sleep_tick = r_os_cputime_get32();
-        assert(enable_tick >= s_sleep_tick);
+#ifdef CONFIG_BT_LE_WAKEUP_SOURCE_CPU_RTC_TIMER
+    uint32_t tick_invalid = *(uint32_t*)(arg);
+    assert(arg != NULL);
+    if(!tick_invalid) {
+        uint32_t sleep_tick = r_os_cputime_get32();
+        if(enable_tick <= sleep_tick) {
+            return;
+        }
         // start a timer to wake up and acquire the pm_lock before modem_sleep awakes
-        uint32_t us_to_sleep = os_cputime_ticks_to_usecs(enable_tick - s_sleep_tick);
+        uint32_t us_to_sleep = r_os_cputime_ticks_to_usecs(enable_tick - sleep_tick);
         assert(us_to_sleep > BTDM_MIN_TIMER_UNCERTAINTY_US);
-        if (esp_timer_start_once(s_btdm_slp_tmr, us_to_sleep - BTDM_MIN_TIMER_UNCERTAINTY_US) != ESP_OK) {
-            ESP_LOGW(NIMBLE_PORT_LOG_TAG, "timer start failed");
+        esp_err_t err = esp_timer_start_once(s_btdm_slp_tmr, us_to_sleep - BTDM_MIN_TIMER_UNCERTAINTY_US);
+        if (err != ESP_OK) {
+            ESP_LOGW(NIMBLE_PORT_LOG_TAG, "ESP timer start failed\n");
+            return;
         }
     }
-#endif // CONFIG_NIMBLE_WAKEUP_SOURCE_CPU_RTC_TIMER
+#endif // CONFIG_BT_LE_WAKEUP_SOURCE_CPU_RTC_TIMER
+
+#ifdef CONFIG_BT_LE_WAKEUP_SOURCE_BLE_RTC_TIMER
+    r_ble_rtc_wake_up_state_clr();
+#endif
     if (s_pm_lock_acquired) {
+        assert(s_pm_lock != NULL);
         esp_pm_lock_release(s_pm_lock);
         s_pm_lock_acquired = false;
     }
@@ -413,61 +411,49 @@ IRAM_ATTR void controller_sleep_cb(uint32_t enable_tick, void *arg)
 
 IRAM_ATTR void controller_wakeup_cb(void *arg)
 {
-    if (!s_is_sleep_state) {
-        ESP_LOGW(NIMBLE_PORT_LOG_TAG, "wake up state error");
-        assert(0);
-    }
-    s_is_sleep_state = false;
-
-// need to check if need to call pm lock here
+    esp_phy_enable();
+    // need to check if need to call pm lock here
 #ifdef CONFIG_PM_ENABLE
+    assert(s_pm_lock != NULL);
     if (!s_pm_lock_acquired) {
         s_pm_lock_acquired = true;
         esp_pm_lock_acquire(s_pm_lock);
     }
-#ifdef CONFIG_BT_NIMBLE_WAKEUP_SOURCE_CPU_RTC_TIMER
-    if (esp_sleep_get_wakeup_cause() != ESP_SLEEP_WAKEUP_TIMER) {
-        ESP_LOGW(NIMBLE_PORT_LOG_TAG, "wake up source %d", esp_sleep_get_wakeup_cause());
-    }
-#endif
-#ifdef CONFIG_BT_NIMBLE_WAKEUP_SOURCE_BLE_RTC_TIMER
-    if (esp_sleep_get_wakeup_cause() != ESP_SLEEP_WAKEUP_BT) {
-        ESP_LOGW(NIMBLE_PORT_LOG_TAG, "wake up source %d", esp_sleep_get_wakeup_cause());
-    }
-#endif
-#endif
+#endif //CONFIG_PM_ENABLE
 }
 
 #ifdef CONFIG_PM_ENABLE
-#ifdef CONFIG_BT_NIMBLE_WAKEUP_SOURCE_CPU_RTC_TIMER
-static void btdm_slp_tmr_callback(void *arg)
+#ifdef CONFIG_BT_LE_WAKEUP_SOURCE_CPU_RTC_TIMER
+static void btdm_slp_tmr_callback(void * arg)
 {
     (void)(arg);
     if (!s_pm_lock_acquired) {
+        assert(s_pm_lock != NULL);
         s_pm_lock_acquired = true;
         esp_pm_lock_acquire(s_pm_lock);
     }
 }
 
-#endif
+#endif // CONFIG_BT_LE_WAKEUP_SOURCE_CPU_RTC_TIMER
 #endif // CONFIG_PM_ENABLE
 
 void controller_sleep_init(void)
 {
 
-#ifdef CONFIG_NIMBLE_SLEEP_ENABLE
-    s_is_sleep_state = false;
 #ifdef CONFIG_PM_ENABLE
-    s_btdm_allow_light_sleep = true;
+    s_btdm_allow_light_sleep = false;
 #endif // CONFIG_PM_ENABLE
-    ESP_LOGW(NIMBLE_PORT_LOG_TAG, "BLE modem sleep is enabled");
-    // register sleep callbacks
-    r_ble_ll_rfmgmt_set_sleep_cb(controller_sleep_cb, controller_wakeup_cb, 0, 0, 500 + BLE_RTC_DELAY_US);
-#else
+
+#ifdef CONFIG_BT_LE_SLEEP_ENABLE
+    ESP_LOGW(NIMBLE_PORT_LOG_TAG, "BLE modem sleep is enabled\n");
+    r_ble_lll_rfmgmt_set_sleep_cb(controller_sleep_cb, controller_wakeup_cb, 0, 0, 500 + BLE_RTC_DELAY_US);
+
 #ifdef CONFIG_PM_ENABLE
-    s_btdm_allow_light_sleep = false;
+    s_btdm_allow_light_sleep = true;
+    esp_sleep_pd_config(ESP_PD_DOMAIN_XTAL, ESP_PD_OPTION_ON);
 #endif // CONFIG_PM_ENABLE
-#endif // CONFIG_NIMBLE_SLEEP_ENABLE
+
+#endif // CONFIG_BT_LE_SLEEP_ENABLE
 
     // enable light sleep
 #ifdef CONFIG_PM_ENABLE
@@ -479,22 +465,22 @@ void controller_sleep_init(void)
     if (esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 0, "bt", &s_pm_lock) != ESP_OK) {
         goto error;
     }
-#ifdef CONFIG_BT_NIMBLE_WAKEUP_SOURCE_CPU_RTC_TIMER
+#ifdef CONFIG_BT_LE_WAKEUP_SOURCE_CPU_RTC_TIMER
     esp_timer_create_args_t create_args = {
         .callback = btdm_slp_tmr_callback,
         .arg = NULL,
         .name = "btSlp"
     };
-    if ( esp_timer_create(&create_args, &s_btdm_slp_tmr) != ESP_OK) {
+    if (esp_timer_create(&create_args, &s_btdm_slp_tmr) != ESP_OK) {
         goto error;
     }
-    ESP_LOGW(NIMBLE_PORT_LOG_TAG, "light sleep enable success, CPU RTC timer wake up");
-#endif //CONFIG_NIMBLE_WAKEUP_SOURCE_CPU_RTC_TIMER
+    ESP_LOGW(NIMBLE_PORT_LOG_TAG, "Enable light sleep, the wake up source is ESP timer");
+#endif //CONFIG_BT_LE_WAKEUP_SOURCE_CPU_RTC_TIMER
 
-#ifdef CONFIG_BT_NIMBLE_WAKEUP_SOURCE_BLE_RTC_TIMER
+#ifdef CONFIG_BT_LE_WAKEUP_SOURCE_BLE_RTC_TIMER
     esp_sleep_enable_bt_wakeup();
-    ESP_LOGW(NIMBLE_PORT_LOG_TAG, "light sleep enable success, BLE RTC timer wake up");
-#endif // CONFIG_NIMBLE_WAKEUP_SOURCE_BLE_RTC_TIMER
+    ESP_LOGW(NIMBLE_PORT_LOG_TAG, "Enable light sleep, the wake up source is BLE timer");
+#endif // CONFIG_BT_LE_WAKEUP_SOURCE_BLE_RTC_TIMER
 
     s_pm_lock_acquired = true;
 
@@ -518,16 +504,18 @@ error:
         esp_pm_lock_delete(s_pm_lock);
         s_pm_lock = NULL;
     }
-#ifdef CONFIG_BT_NIMBLE_WAKEUP_SOURCE_CPU_RTC_TIMER
+#ifdef CONFIG_BT_LE_WAKEUP_SOURCE_CPU_RTC_TIMER
     if (s_btdm_slp_tmr != NULL) {
         esp_timer_delete(s_btdm_slp_tmr);
         s_btdm_slp_tmr = NULL;
     }
-#endif // CONFIG_BT_NIMBLE_WAKEUP_SOURCE_CPU_RTC_TIMER
-#ifdef CONFIG_BT_NIMBLE_WAKEUP_SOURCE_BLE_RTC_TIMER
+#endif // CONFIG_BT_LE_WAKEUP_SOURCE_CPU_RTC_TIMER
+
+#ifdef CONFIG_BT_LE_WAKEUP_SOURCE_BLE_RTC_TIMER
     esp_sleep_disable_bt_wakeup();
-#endif // CONFIG_BT_NIMBLE_WAKEUP_SOURCE_BLE_RTC_TIMER
-#endif
+#endif // CONFIG_BT_LE_WAKEUP_SOURCE_BLE_RTC_TIMER
+
+#endif //CONFIG_PM_ENABLE
 
 }
 
@@ -544,8 +532,8 @@ void controller_sleep_deinit(void)
         esp_pm_lock_delete(s_pm_lock);
         s_pm_lock = NULL;
     }
-#ifdef CONFIG_BT_NIMBLE_WAKEUP_SOURCE_CPU_RTC_TIMER
-    if (s_btdm_slp_tmr != NULL) {
+#ifdef CONFIG_BT_LE_WAKEUP_SOURCE_CPU_RTC_TIMER
+    if(s_btdm_slp_tmr != NULL) {
         esp_timer_stop(s_btdm_slp_tmr);
         esp_timer_delete(s_btdm_slp_tmr);
         s_btdm_slp_tmr = NULL;
@@ -556,17 +544,19 @@ void controller_sleep_deinit(void)
 
 }
 
-esp_err_t esp_bt_controller_init(struct esp_bt_controller_config_t *cfg)
+esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg)
 {
     if (ble_controller_status != ESP_BT_CONTROLLER_STATUS_IDLE) {
         ESP_LOGW(NIMBLE_PORT_LOG_TAG, "invalid controller state");
         return ESP_FAIL;
     }
     if (cfg == NULL) {
+        ESP_LOGW(NIMBLE_PORT_LOG_TAG, "cfg is NULL");
         return ESP_ERR_INVALID_ARG;
     }
 
     if (esp_register_ext_funcs(&ext_funcs_ro) != 0) {
+        ESP_LOGW(NIMBLE_PORT_LOG_TAG, "register extend functions failed");
         return ESP_ERR_INVALID_ARG;
     }
 
@@ -617,8 +607,9 @@ esp_err_t esp_bt_controller_init(struct esp_bt_controller_config_t *cfg)
 #if CONFIG_SW_COEXIST_ENABLE
     coex_init();
 #endif
-
-    if (ble_controller_init(cfg) != 0) {
+    int rc = ble_controller_init(cfg);
+    if (rc != 0) {
+        ESP_LOGW(NIMBLE_PORT_LOG_TAG, "ble_controller_init failed %d", rc);
         return ESP_ERR_NO_MEM;
     }
 
@@ -632,9 +623,10 @@ esp_err_t esp_bt_controller_init(struct esp_bt_controller_config_t *cfg)
     esp_ble_ll_set_public_addr(mac);
 
     ble_controller_status = ESP_BT_CONTROLLER_STATUS_INITED;
-#ifdef CONFIG_BT_BLUEDROID_ENABLED
-    ble_hci_trans_cfg_hs(ble_hs_hci_rx_evt,NULL,ble_hs_rx_data,NULL);
-#endif
+
+    ble_hci_trans_cfg_hs((ble_hci_trans_rx_cmd_fn *)ble_hci_unregistered_hook,NULL,
+                         (ble_hci_trans_rx_acl_fn *)ble_hci_unregistered_hook,NULL);
+
     return ESP_OK;
 }
 
@@ -672,70 +664,6 @@ esp_err_t esp_bt_controller_deinit(void)
     return ESP_OK;
 }
 
-esp_bt_controller_status_t esp_bt_controller_get_status(void)
-{
-    return ble_controller_status;
-}
-
-/* extra functions */
-esp_err_t esp_ble_tx_power_set(esp_ble_power_type_t power_type, esp_power_level_t power_level)
-{
-    esp_err_t stat = ESP_FAIL;
-
-    switch (power_type) {
-    case ESP_BLE_PWR_TYPE_ADV:
-    case ESP_BLE_PWR_TYPE_SCAN:
-    case ESP_BLE_PWR_TYPE_DEFAULT:
-        if (ble_txpwr_set(power_type, power_level) == 0) {
-            stat = ESP_OK;
-        }
-        break;
-    default:
-        stat = ESP_ERR_NOT_SUPPORTED;
-        break;
-    }
-
-    return stat;
-}
-
-int ble_txpwr_get(int power_type)
-{
-    return 0;
-}
-
-int ble_txpwr_set(int power_type, int power_level)
-{
-    return 0;
-}
-esp_power_level_t esp_ble_tx_power_get(esp_ble_power_type_t power_type)
-{
-    esp_power_level_t lvl;
-
-    switch (power_type) {
-    case ESP_BLE_PWR_TYPE_ADV:
-    case ESP_BLE_PWR_TYPE_SCAN:
-        lvl = (esp_power_level_t)ble_txpwr_get(power_type);
-        break;
-    case ESP_BLE_PWR_TYPE_CONN_HDL0:
-    case ESP_BLE_PWR_TYPE_CONN_HDL1:
-    case ESP_BLE_PWR_TYPE_CONN_HDL2:
-    case ESP_BLE_PWR_TYPE_CONN_HDL3:
-    case ESP_BLE_PWR_TYPE_CONN_HDL4:
-    case ESP_BLE_PWR_TYPE_CONN_HDL5:
-    case ESP_BLE_PWR_TYPE_CONN_HDL6:
-    case ESP_BLE_PWR_TYPE_CONN_HDL7:
-    case ESP_BLE_PWR_TYPE_CONN_HDL8:
-    case ESP_BLE_PWR_TYPE_DEFAULT:
-        lvl = (esp_power_level_t)ble_txpwr_get(ESP_BLE_PWR_TYPE_DEFAULT);
-        break;
-    default:
-        lvl = ESP_PWR_LVL_INVALID;
-        break;
-    }
-
-    return lvl;
-}
-
 esp_err_t esp_bt_controller_enable(esp_bt_mode_t mode)
 {
     if (mode != ESP_BT_MODE_BLE) {
@@ -746,15 +674,12 @@ esp_err_t esp_bt_controller_enable(esp_bt_mode_t mode)
         ESP_LOGW(NIMBLE_PORT_LOG_TAG, "invalid controller state");
         return ESP_FAIL;
     }
-
 #if CONFIG_SW_COEXIST_ENABLE
     coex_enable();
 #endif
-
     if (ble_controller_enable(mode) != 0) {
         return ESP_FAIL;
     }
-
     ble_controller_status = ESP_BT_CONTROLLER_STATUS_ENABLED;
     return ESP_OK;
 }
@@ -768,6 +693,7 @@ esp_err_t esp_bt_controller_disable(void)
     if (ble_controller_disable() != 0) {
         return ESP_FAIL;
     }
+    ble_controller_status = ESP_BT_CONTROLLER_STATUS_INITED;
     return ESP_OK;
 }
 
@@ -782,3 +708,244 @@ esp_err_t esp_bt_mem_release(esp_bt_mode_t mode)
     ESP_LOGW(NIMBLE_PORT_LOG_TAG, "%s not implemented, return OK", __func__);
     return ESP_OK;
 }
+
+
+esp_bt_controller_status_t esp_bt_controller_get_status(void)
+{
+    return ble_controller_status;
+}
+
+/* extra functions */
+esp_err_t esp_ble_tx_power_set(esp_ble_power_type_t power_type, esp_power_level_t power_level)
+{
+    ESP_LOGW(NIMBLE_PORT_LOG_TAG, "%s not implemented, return OK", __func__);
+    return ESP_OK;
+}
+
+esp_power_level_t esp_ble_tx_power_get(esp_ble_power_type_t power_type)
+{
+    ESP_LOGW(NIMBLE_PORT_LOG_TAG, "%s not implemented, return OK", __func__);
+    return ESP_PWR_LVL_N0;
+}
+
+#if (!CONFIG_BT_NIMBLE_ENABLED) && (CONFIG_BT_CONTROLLER_ENABLED == true)
+
+#define BLE_SM_KEY_ERR 0x17
+
+#if CONFIG_BT_LE_CRYPTO_STACK_MBEDTLS
+#include "mbedtls/aes.h"
+
+#if CONFIG_BT_LE_SM_SC
+#include "mbedtls/cipher.h"
+#include "mbedtls/entropy.h"
+#include "mbedtls/ctr_drbg.h"
+#include "mbedtls/cmac.h"
+#include "mbedtls/ecdh.h"
+#include "mbedtls/ecp.h"
+#endif
+
+#else
+#include "tinycrypt/aes.h"
+#include "tinycrypt/constants.h"
+#include "tinycrypt/utils.h"
+
+#if CONFIG_BT_LE_SM_SC
+#include "tinycrypt/cmac_mode.h"
+#include "tinycrypt/ecc_dh.h"
+#endif
+
+#endif
+
+#if CONFIG_BT_LE_CRYPTO_STACK_MBEDTLS
+#if CONFIG_BT_LE_SM_SC
+static mbedtls_ecp_keypair keypair;
+#endif
+#endif
+
+int ble_sm_alg_gen_dhkey(const uint8_t *peer_pub_key_x, const uint8_t *peer_pub_key_y,
+                         const uint8_t *our_priv_key, uint8_t *out_dhkey)
+{
+    uint8_t dh[32];
+    uint8_t pk[64];
+    uint8_t priv[32];
+    int rc = BLE_SM_KEY_ERR;
+
+    swap_buf(pk, peer_pub_key_x, 32);
+    swap_buf(&pk[32], peer_pub_key_y, 32);
+    swap_buf(priv, our_priv_key, 32);
+
+#if CONFIG_BT_LE_CRYPTO_STACK_MBEDTLS
+    struct mbedtls_ecp_point pt = {0}, Q = {0};
+    mbedtls_mpi z = {0}, d = {0};
+    mbedtls_ctr_drbg_context ctr_drbg = {0};
+    mbedtls_entropy_context entropy = {0};
+
+    uint8_t pub[65] = {0};
+    /* Hardcoded first byte of pub key for MBEDTLS_ECP_PF_UNCOMPRESSED */
+    pub[0] = 0x04;
+    memcpy(&pub[1], pk, 64);
+
+    /* Initialize the required structures here */
+    mbedtls_ecp_point_init(&pt);
+    mbedtls_ecp_point_init(&Q);
+    mbedtls_ctr_drbg_init(&ctr_drbg);
+    mbedtls_entropy_init(&entropy);
+    mbedtls_mpi_init(&d);
+    mbedtls_mpi_init(&z);
+
+    /* Below 3 steps are to validate public key on curve secp256r1 */
+    if (mbedtls_ecp_group_load(&keypair.MBEDTLS_PRIVATE(grp), MBEDTLS_ECP_DP_SECP256R1) != 0) {
+        goto exit;
+    }
+
+    if (mbedtls_ecp_point_read_binary(&keypair.MBEDTLS_PRIVATE(grp), &pt, pub, 65) != 0) {
+        goto exit;
+    }
+
+    if (mbedtls_ecp_check_pubkey(&keypair.MBEDTLS_PRIVATE(grp), &pt) != 0) {
+        goto exit;
+    }
+
+    /* Set PRNG */
+    if ((rc = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy,
+                                    NULL, 0)) != 0) {
+        goto exit;
+    }
+
+    /* Prepare point Q from pub key */
+    if (mbedtls_ecp_point_read_binary(&keypair.MBEDTLS_PRIVATE(grp), &Q, pub, 65) != 0) {
+        goto exit;
+    }
+
+    if (mbedtls_mpi_read_binary(&d, priv, 32) != 0) {
+        goto exit;
+    }
+
+    rc = mbedtls_ecdh_compute_shared(&keypair.MBEDTLS_PRIVATE(grp), &z, &Q, &d,
+                                     mbedtls_ctr_drbg_random, &ctr_drbg);
+    if (rc != 0) {
+        goto exit;
+    }
+
+    rc = mbedtls_mpi_write_binary(&z, dh, 32);
+    if (rc != 0) {
+        goto exit;
+    }
+
+exit:
+    mbedtls_ecp_point_free(&pt);
+    mbedtls_mpi_free(&z);
+    mbedtls_mpi_free(&d);
+    mbedtls_ecp_point_free(&Q);
+    mbedtls_entropy_free(&entropy);
+    mbedtls_ctr_drbg_free(&ctr_drbg);
+    if (rc != 0) {
+        return BLE_SM_KEY_ERR;
+    }
+
+#else
+    if (uECC_valid_public_key(pk, &curve_secp256r1) < 0) {
+        return BLE_SM_KEY_ERR;
+    }
+
+    rc = uECC_shared_secret(pk, priv, dh, &curve_secp256r1);
+    if (rc == TC_CRYPTO_FAIL) {
+        return BLE_SM_KEY_ERR;
+    }
+#endif
+
+    swap_buf(out_dhkey, dh, 32);
+    return 0;
+}
+
+/* based on Core Specification 4.2 Vol 3. Part H 2.3.5.6.1 */
+static const uint8_t ble_sm_alg_dbg_priv_key[32] = {
+    0x3f, 0x49, 0xf6, 0xd4, 0xa3, 0xc5, 0x5f, 0x38, 0x74, 0xc9, 0xb3, 0xe3,
+    0xd2, 0x10, 0x3f, 0x50, 0x4a, 0xff, 0x60, 0x7b, 0xeb, 0x40, 0xb7, 0x99,
+    0x58, 0x99, 0xb8, 0xa6, 0xcd, 0x3c, 0x1a, 0xbd
+};
+
+#if CONFIG_BT_LE_CRYPTO_STACK_MBEDTLS
+static int mbedtls_gen_keypair(uint8_t *public_key, uint8_t *private_key)
+{
+    int rc = BLE_SM_KEY_ERR;
+    mbedtls_entropy_context entropy = {0};
+    mbedtls_ctr_drbg_context ctr_drbg = {0};
+
+    mbedtls_entropy_init(&entropy);
+    mbedtls_ctr_drbg_init(&ctr_drbg);
+    mbedtls_ecp_keypair_init(&keypair);
+
+    if ((rc = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy,
+                                    NULL, 0)) != 0) {
+        goto exit;
+    }
+
+    if ((rc = mbedtls_ecp_gen_key(MBEDTLS_ECP_DP_SECP256R1, &keypair,
+                                  mbedtls_ctr_drbg_random, &ctr_drbg)) != 0) {
+        goto exit;
+    }
+
+    if ((rc = mbedtls_mpi_write_binary(&keypair.MBEDTLS_PRIVATE(d), private_key, 32)) != 0) {
+        goto exit;
+    }
+
+    size_t olen = 0;
+    uint8_t pub[65] = {0};
+
+    if ((rc = mbedtls_ecp_point_write_binary(&keypair.MBEDTLS_PRIVATE(grp), &keypair.MBEDTLS_PRIVATE(Q), MBEDTLS_ECP_PF_UNCOMPRESSED,
+              &olen, pub, 65)) != 0) {
+        goto exit;
+    }
+
+    memcpy(public_key, &pub[1], 64);
+
+exit:
+    mbedtls_ctr_drbg_free(&ctr_drbg);
+    mbedtls_entropy_free(&entropy);
+    if (rc != 0) {
+        mbedtls_ecp_keypair_free(&keypair);
+        return BLE_SM_KEY_ERR;
+    }
+
+    return 0;
+}
+#endif
+
+/**
+ * pub: 64 bytes
+ * priv: 32 bytes
+ */
+int ble_sm_alg_gen_key_pair(uint8_t *pub, uint8_t *priv)
+{
+#if CONFIG_BT_LE_SM_SC_DEBUG_KEYS
+    swap_buf(pub, ble_sm_alg_dbg_pub_key, 32);
+    swap_buf(&pub[32], &ble_sm_alg_dbg_pub_key[32], 32);
+    swap_buf(priv, ble_sm_alg_dbg_priv_key, 32);
+#else
+    uint8_t pk[64];
+
+    do {
+
+#if CONFIG_BT_LE_CRYPTO_STACK_MBEDTLS
+        if (mbedtls_gen_keypair(pk, priv) != 0) {
+            return BLE_SM_KEY_ERR;
+        }
+#else
+        if (uECC_make_key(pk, priv, &curve_secp256r1) != TC_CRYPTO_SUCCESS) {
+            return BLE_SM_KEY_ERR;
+        }
+#endif
+
+        /* Make sure generated key isn't debug key. */
+    } while (memcmp(priv, ble_sm_alg_dbg_priv_key, 32) == 0);
+
+    swap_buf(pub, pk, 32);
+    swap_buf(&pub[32], &pk[32], 32);
+    swap_in_place(priv, 32);
+#endif
+
+    return 0;
+}
+
+#endif

+ 1 - 1
components/bt/controller/lib_esp32c2/esp32c2-bt-lib

@@ -1 +1 @@
-Subproject commit 5f1b106c7501d3a61c5d084d6abf2824ae31b8e8
+Subproject commit 14e64db09a260545f0d26f5bbd55965b0c068c1c

+ 4 - 6
components/bt/host/nimble/Kconfig.in

@@ -315,8 +315,8 @@ endmenu
 config BT_NIMBLE_HS_FLOW_CTRL
     bool "Enable Host Flow control"
     depends on BT_NIMBLE_ENABLED
-    default n if BT_SOC_SUPPORT_5_0
-    default y
+    default y if IDF_TARGET_ESP32
+    default n
     help
         Enable Host Flow control
 
@@ -605,10 +605,8 @@ config BT_NIMBLE_COEX_PHY_CODED_TX_RX_TLIM_EFF
 config BT_NIMBLE_WHITELIST_SIZE
     int "BLE white list size"
     depends on BT_NIMBLE_ENABLED
-    range 1 15 if !IDF_TARGET_ESP32C2
-    default 12 if !IDF_TARGET_ESP32C2
-    range 1 5 if IDF_TARGET_ESP32C2
-    default 5 if IDF_TARGET_ESP32C2
+    range 1 15
+    default 12
     help
             BLE list size
 

+ 1 - 0
components/bt/host/nimble/esp-hci/src/esp_nimble_hci.c

@@ -14,6 +14,7 @@
 #include "nimble/nimble_port_freertos.h"
 #include "esp_nimble_hci.h"
 #include "esp_nimble_mem.h"
+#include "bt_osi_mem.h"
 #include "esp_bt.h"
 #include "freertos/semphr.h"
 #include "esp_compiler.h"

+ 1 - 1
components/bt/host/nimble/nimble

@@ -1 +1 @@
-Subproject commit d48bc4e78ef2478a0ac32db3d832d1e8178451db
+Subproject commit b9fdfe4b7aa4a9dc241f79ac5de4643030351824

+ 0 - 37
components/bt/host/nimble/port/include/esp_nimble_cfg.h

@@ -22,31 +22,6 @@
 #define IRAM_ATTR_64MCPU IRAM_ATTR
 #endif
 
-#define BLE_LL_CTRL_PROC_TIMEOUT_MS_N   (40000) /* ms */
-
-#define BLE_LL_CFG_NUM_HCI_CMD_PKTS_N   (1)
-
-#define BLE_LL_SCHED_ADV_MAX_USECS_N    (852)
-
-#define BLE_LL_SCHED_DIRECT_ADV_MAX_USECS_N (502)
-
-#define BLE_LL_SCHED_MAX_ADV_PDU_USECS_N    (376)
-
-#define BLE_LL_SUB_VERS_NR_N                (0x0000)
-
-#define BLE_LL_JITTER_USECS_N               (16)
-
-#define BLE_PHY_MAX_PWR_DBM_N               (10)
-
-#define BLE_LL_CONN_DEF_AUTH_PYLD_TMO_N     (3000)
-
-#if CONFIG_IDF_TARGET_ESP32H2
-#define RTC_FREQ_N                          (32768) /* in Hz */
-#else
-#define RTC_FREQ_N                          (32000) /* in Hz */
-#endif
-
-#define BLE_LL_TX_PWR_DBM_N                 (0)
 
 #if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3
 #define NIMBLE_CFG_CONTROLLER    0
@@ -1594,18 +1569,6 @@
 #define MYNEWT_VAL_BLE_HCI_UART_STOP_BITS (1)
 #endif
 
-#ifndef CONFIG_BLE_TX_CCA_ENABLED
-#define MYNEWT_VAL_BLE_TX_CCA_ENABLED   (0)
-#else
-#define MYNEWT_VAL_BLE_TX_CCA_ENABLED   (CONFIG_BLE_TX_CCA_ENABLED)
-#endif
-
-#ifndef CONFIG_BLE_CCA_RSSI_THRESH
-#define MYNEWT_VAL_BLE_CCA_RSSI_THRESH   (50)
-#else
-#define MYNEWT_VAL_BLE_CCA_RSSI_THRESH   (CONFIG_BLE_CCA_RSSI_THRESH)
-#endif
-
 
 #ifndef MYNEWT_VAL_NEWT_FEATURE_LOGCFG
 #define MYNEWT_VAL_NEWT_FEATURE_LOGCFG (1)

+ 15 - 0
components/bt/host/nimble/port/include/esp_nimble_main.h

@@ -0,0 +1,15 @@
+/*
+ * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include "esp_err.h"
+
+esp_err_t esp_nimble_init();
+
+esp_err_t esp_nimble_enable(void *host_task);
+
+esp_err_t esp_nimble_disable();
+
+esp_err_t esp_nimble_deinit();

+ 6 - 3
components/bt/host/nimble/port/include/esp_nimble_mem.h

@@ -13,9 +13,12 @@
 extern "C" {
 #endif
 
-void *nimble_platform_mem_malloc(size_t size);
-void *nimble_platform_mem_calloc(size_t n, size_t size);
-void nimble_platform_mem_free(void *ptr);
+// #pragma message "This file should be replaced with bt_osi_mem.h, used here for compatibility"
+
+#include "bt_osi_mem.h"
+#define nimble_platform_mem_malloc bt_osi_mem_malloc
+#define nimble_platform_mem_calloc bt_osi_mem_calloc
+#define nimble_platform_mem_free bt_osi_mem_free
 
 #ifdef __cplusplus
 }

+ 100 - 0
components/bt/host/nimble/port/src/esp_nimble_main.c

@@ -0,0 +1,100 @@
+/*
+ * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include "esp_attr.h"
+#include "esp_heap_caps.h"
+#include "sdkconfig.h"
+#include "esp_nimble_mem.h"
+#include "host/ble_hs.h"
+
+static TaskHandle_t host_task_h;
+
+extern void ble_hs_deinit(void);
+static struct ble_hs_stop_listener stop_listener;
+
+static struct ble_npl_eventq g_eventq_dflt;
+static struct ble_npl_sem ble_hs_stop_sem;
+static struct ble_npl_event ble_hs_ev_stop;
+
+esp_err_t esp_nimble_init(void)
+{
+#if !SOC_ESP_NIMBLE_CONTROLLER
+    /* Initialize the function pointers for OS porting */
+    npl_freertos_funcs_init();
+
+    npl_freertos_mempool_init();
+
+    /* Initialize default event queue */
+
+    ble_npl_eventq_init(&g_eventq_dflt);
+
+
+    os_msys_init();
+
+    void ble_store_ram_init(void); // Do we need this?
+    /* XXX Need to have template for store */
+    ble_store_ram_init();
+#endif
+
+    /* Initialize the host */
+    ble_hs_init();
+    return ESP_OK;
+}
+
+esp_err_t esp_nimble_enable(void *host_task)
+{
+    /*
+     * Create task where NimBLE host will run. It is not strictly necessary to
+     * have separate task for NimBLE host, but since something needs to handle
+     * default queue it is just easier to make separate task which does this.
+     */
+    xTaskCreatePinnedToCore(host_task, "nimble_host", NIMBLE_HS_STACK_SIZE,
+                            NULL, (configMAX_PRIORITIES - 4), &host_task_h, NIMBLE_CORE);
+    return ESP_OK;
+
+}
+
+esp_err_t esp_nimble_disable(void)
+{
+    esp_err_t err = ESP_OK;
+    ble_npl_sem_init(&ble_hs_stop_sem, 0);
+
+    /* Initiate a host stop procedure. */
+    rc = ble_hs_stop(&stop_listener, ble_hs_stop_cb,
+                     NULL);
+    if (rc != 0) {
+        ble_npl_sem_deinit(&ble_hs_stop_sem);
+        return rc;
+    }
+
+    /* Wait till the host stop procedure is complete */
+    ble_npl_sem_pend(&ble_hs_stop_sem, BLE_NPL_TIME_FOREVER);
+
+    ble_npl_event_init(&ble_hs_ev_stop, nimble_port_stop_cb,
+                       NULL);
+    ble_npl_eventq_put(&g_eventq_dflt, &ble_hs_ev_stop);
+
+    /* Wait till the event is serviced */
+    ble_npl_sem_pend(&ble_hs_stop_sem, BLE_NPL_TIME_FOREVER);
+
+    ble_npl_sem_deinit(&ble_hs_stop_sem);
+
+    return ESP_OK;
+
+}
+
+esp_err_t esp_nimble_deinit(void)
+{
+#if !(SOC_ESP_NIMBLE_CONTROLLER && CONFIG_BT_CONTROLLER_ENABLED)
+    ble_npl_eventq_deinit(&g_eventq_dflt);
+#endif
+
+    if (host_task_h) {
+        vTaskDelete(host_task_h);
+    }
+    ble_hs_deinit();
+    return ESP_OK;
+}

+ 11 - 145
components/bt/include/esp32c2/include/esp_bt.h

@@ -14,15 +14,14 @@
 #include "esp_task.h"
 
 #include "nimble/nimble_npl.h"
-#include "syscfg/syscfg.h"
-#include "esp_nimble_cfg.h"
+#include "esp_bt_cfg.h"
 
-#ifdef __cplusplus
-extern "C" {
+#ifdef CONFIG_BT_LE_HCI_INTERFACE_USE_UART
+#include "driver/uart.h"
 #endif
 
-#if (SOC_ESP_NIMBLE_CONTROLLER)
-#define NIMBLE_LL_STACK_SIZE CONFIG_BT_LE_CONTROLLER_TASK_STACK_SIZE
+#ifdef __cplusplus
+extern "C" {
 #endif
 
 /**
@@ -128,7 +127,7 @@ esp_power_level_t esp_ble_tx_power_get(esp_ble_power_type_t power_type);
  *        some options or parameters of some functions enabled by config mask.
  */
 
-struct esp_bt_controller_config_t{
+typedef struct {
     uint32_t config_version;
     uint16_t ble_ll_resolv_list_size;
     uint16_t ble_hci_evt_hi_buf_count;
@@ -175,141 +174,8 @@ struct esp_bt_controller_config_t{
     uint8_t dis_scan_backoff;
     uint8_t esp_scan_filter_en;
     uint32_t config_magic;
-};
-
-typedef struct esp_bt_controller_config_t esp_bt_controller_config_t;
-
-#define RUN_BQB_TEST                0
-#define RUN_QA_TEST                 0
-#define NIMBLE_DISABLE_SCAN_BACKOFF 0
-
-#ifdef CONFIG_BT_LE_HCI_INTERFACE_USE_UART
-#define HCI_UART_EN CONFIG_BT_LE_HCI_INTERFACE_USE_UART
-#else
-#define HCI_UART_EN 0 // hci ram mode
-#endif
-
-#if CONFIG_BT_LE_LL_CFG_FEAT_LE_CODED_PHY
-#define BLE_LL_SCAN_PHY_NUMBER_N (2)
-#else
-#define BLE_LL_SCAN_PHY_NUMBER_N (1)
-#endif
-
-#ifdef CONFIG_BT_LE_SLEEP_ENABLE
-#define NIMBLE_SLEEP_ENABLE CONFIG_BT_LE_SLEEP_ENABLE
-#else
-#define NIMBLE_SLEEP_ENABLE  0
-#endif
-
-
-#if CONFIG_BT_NIMBLE_ENABLED
-
-#define DEFAULT_BT_LE_MAX_PERIODIC_ADVERTISER_LIST MYNEWT_VAL(BLE_MAX_PERIODIC_ADVERTISER_LIST)
-#define DEFAULT_BT_LE_MAX_PERIODIC_SYNCS MYNEWT_VAL(BLE_MAX_PERIODIC_SYNCS)
-#define DEFAULT_BT_LE_MAX_CONNECTIONS MYNEWT_VAL(BLE_MAX_CONNECTIONS)
-#define DEFAULT_BT_LE_ACL_BUF_SIZE MYNEWT_VAL(BLE_ACL_BUF_SIZE)
-#define DEFAULT_BT_LE_ACL_BUF_COUNT MYNEWT_VAL(BLE_ACL_BUF_COUNT)
-#define DEFAULT_BT_LE_HCI_EVT_BUF_SIZE MYNEWT_VAL(BLE_HCI_EVT_BUF_SIZE)
-#define DEFAULT_BT_LE_EXT_ADV_MAX_SIZE MYNEWT_VAL(BLE_EXT_ADV_MAX_SIZE)
-#define DEFAULT_BT_LE_MAX_EXT_ADV_INSTANCES MYNEWT_VAL(BLE_MULTI_ADV_INSTANCES)
-#define DEFAULT_BT_NIMBLE_WHITELIST_SIZE MYNEWT_VAL(BLE_LL_WHITELIST_SIZE)
-#define DEFAULT_BT_LE_HCI_EVT_HI_BUF_COUNT MYNEWT_VAL(BLE_HCI_EVT_HI_BUF_COUNT)
-#define DEFAULT_BT_LE_HCI_EVT_LO_BUF_COUNT MYNEWT_VAL(BLE_HCI_EVT_LO_BUF_COUNT)
-#define DEFAULT_BT_LE_COEX_PHY_CODED_TX_RX_TLIM_EFF CONFIG_BT_NIMBLE_COEX_PHY_CODED_TX_RX_TLIM_EFF
-
-#else
-# if defined(CONFIG_BT_LE_MAX_PERIODIC_ADVERTISER_LIST)
-    #define DEFAULT_BT_LE_MAX_PERIODIC_ADVERTISER_LIST (CONFIG_BT_LE_MAX_PERIODIC_ADVERTISER_LIST)
-#else
-    #define DEFAULT_BT_LE_MAX_PERIODIC_ADVERTISER_LIST (0)
-#endif
-
-#if defined(CONFIG_BT_LE_MAX_PERIODIC_SYNCS)
-    #define DEFAULT_BT_LE_MAX_PERIODIC_SYNCS (CONFIG_BT_LE_MAX_PERIODIC_SYNCS)
-#else
-    #define DEFAULT_BT_LE_MAX_PERIODIC_SYNCS (0)
-#endif
+} esp_bt_controller_config_t;
 
-#if defined(CONFIG_BT_LE_MAX_CONNECTIONS)
-    #define DEFAULT_BT_LE_MAX_CONNECTIONS (CONFIG_BT_LE_MAX_CONNECTIONS)
-#else
-    #define DEFAULT_BT_LE_MAX_CONNECTIONS (0)
-#endif
-
-#if defined(CONFIG_BT_LE_ACL_BUF_SIZE)
-    #define DEFAULT_BT_LE_ACL_BUF_SIZE (CONFIG_BT_LE_ACL_BUF_SIZE)
-#else
-    #define DEFAULT_BT_LE_ACL_BUF_SIZE (0)
-#endif
-
-#if defined(CONFIG_BT_LE_ACL_BUF_COUNT)
-    #define DEFAULT_BT_LE_ACL_BUF_COUNT (CONFIG_BT_LE_ACL_BUF_COUNT)
-#else
-    #define DEFAULT_BT_LE_ACL_BUF_COUNT (0)
-#endif
-
-#if defined(CONFIG_BT_LE_HCI_EVT_BUF_SIZE)
-    #define DEFAULT_BT_LE_HCI_EVT_BUF_SIZE (CONFIG_BT_LE_HCI_EVT_BUF_SIZE)
-#else
-    #define DEFAULT_BT_LE_HCI_EVT_BUF_SIZE (0)
-#endif
-
-#if defined(CONFIG_BT_LE_EXT_ADV_MAX_SIZE)
-    #define DEFAULT_BT_LE_EXT_ADV_MAX_SIZE (CONFIG_BT_LE_EXT_ADV_MAX_SIZE)
-#else
-    #define DEFAULT_BT_LE_EXT_ADV_MAX_SIZE (0)
-#endif
-
-#if defined(CONFIG_BT_LE_MAX_EXT_ADV_INSTANCES)
-    #define DEFAULT_BT_LE_MAX_EXT_ADV_INSTANCES (CONFIG_BT_LE_MAX_EXT_ADV_INSTANCES)
-#else
-    #define DEFAULT_BT_LE_MAX_EXT_ADV_INSTANCES (0)
-#endif
-
-#if defined(CONFIG_BT_LE_WHITELIST_SIZE)
-    #define DEFAULT_BT_NIMBLE_WHITELIST_SIZE (CONFIG_BT_LE_WHITELIST_SIZE)
-#else
-    #define DEFAULT_BT_NIMBLE_WHITELIST_SIZE (0)
-#endif
-
-#if defined(CONFIG_BT_LE_HCI_EVT_HI_BUF_COUNT)
-    #define DEFAULT_BT_LE_HCI_EVT_HI_BUF_COUNT (CONFIG_BT_LE_HCI_EVT_HI_BUF_COUNT)
-#else
-    #define DEFAULT_BT_LE_HCI_EVT_HI_BUF_COUNT (0)
-#endif
-
-#if defined(CONFIG_BT_LE_HCI_EVT_LO_BUF_COUNT)
-    #define DEFAULT_BT_LE_HCI_EVT_LO_BUF_COUNT (CONFIG_BT_LE_HCI_EVT_LO_BUF_COUNT)
-#else
-    #define DEFAULT_BT_LE_HCI_EVT_LO_BUF_COUNT (0)
-#endif
-
-#define DEFAULT_BT_LE_COEX_PHY_CODED_TX_RX_TLIM_EFF CONFIG_BT_LE_COEX_PHY_CODED_TX_RX_TLIM_EFF
-
-#endif
-
-
-#ifdef BT_LE_HCI_INTERFACE_USE_UART
-    #define DEFAULT_BT_LE_HCI_UART_TX_PIN (CONFIG_BT_LE_HCI_UART_TX_PIN)
-    #define DEFAULT_BT_LE_HCI_UART_RX_PIN (CONFIG_BT_LE_HCI_UART_RX_PIN)
-    #define DEFAULT_BT_LE_HCI_UART_PORT (CONFIG_BT_LE_HCI_UART_PORT)
-    #define DEFAULT_BT_LE_HCI_UART_BAUD (CONFIG_BT_LE_HCI_UART_BAUD)
-    #define DEFAULT_BT_LE_HCI_UART_DATA_BITS (CONFIG_BT_LE_HCI_UART_DATA_BITS)
-    #define DEFAULT_BT_LE_HCI_UART_STOP_BITS (CONFIG_BT_LE_HCI_UART_STOP_BITS)
-    #define DEFAULT_BT_LE_HCI_UART_PARITY (CONFIG_BT_LE_HCI_UART_BAUD)
-    #define DEFAULT_BT_LE_HCI_UART_TASK_STACK_SIZE (CONFIG_BT_LE_HCI_UART_TASK_STACK_SIZE)
-    #define DEFAULT_BT_LE_HCI_UART_FLOW_CTRL (CONFIG_BT_LE_HCI_UART_FLOW_CTRL)
-#else
-    #define DEFAULT_BT_LE_HCI_UART_TX_PIN (0)
-    #define DEFAULT_BT_LE_HCI_UART_RX_PIN (0)
-    #define DEFAULT_BT_LE_HCI_UART_PORT (0)
-    #define DEFAULT_BT_LE_HCI_UART_BAUD (0)
-    #define DEFAULT_BT_LE_HCI_UART_DATA_BITS (8)
-    #define DEFAULT_BT_LE_HCI_UART_STOP_BITS (1)
-    #define DEFAULT_BT_LE_HCI_UART_PARITY (0)
-    #define DEFAULT_BT_LE_HCI_UART_TASK_STACK_SIZE (0)
-    #define DEFAULT_BT_LE_HCI_UART_FLOW_CTRL (0)
-#endif
 
 #define BT_CONTROLLER_INIT_CONFIG_DEFAULT() {                                           \
     .config_version = CONFIG_VERSION,                                                   \
@@ -329,7 +195,7 @@ typedef struct esp_bt_controller_config_t esp_bt_controller_config_t;
     .ble_ll_sched_max_adv_pdu_usecs = BLE_LL_SCHED_MAX_ADV_PDU_USECS_N,                 \
     .ble_ll_sched_direct_adv_max_usecs = BLE_LL_SCHED_DIRECT_ADV_MAX_USECS_N,           \
     .ble_ll_sched_adv_max_usecs = BLE_LL_SCHED_ADV_MAX_USECS_N,                         \
-    .ble_scan_rsp_data_max_len = BLE_SCAN_RSP_DATA_MAX_LEN_N,                           \
+    .ble_scan_rsp_data_max_len = DEFAULT_BT_LE_SCAN_RSP_DATA_MAX_LEN_N,                 \
     .ble_ll_cfg_num_hci_cmd_pkts = BLE_LL_CFG_NUM_HCI_CMD_PKTS_N,                       \
     .ble_ll_ctrl_proc_timeout_ms = BLE_LL_CTRL_PROC_TIMEOUT_MS_N,                       \
     .nimble_max_connections = DEFAULT_BT_LE_MAX_CONNECTIONS,                            \
@@ -351,8 +217,8 @@ typedef struct esp_bt_controller_config_t esp_bt_controller_config_t;
     .ble_hci_uart_stop_bits     = DEFAULT_BT_LE_HCI_UART_STOP_BITS,                     \
     .ble_hci_uart_flow_ctrl     = DEFAULT_BT_LE_HCI_UART_FLOW_CTRL,                     \
     .ble_hci_uart_uart_parity   = DEFAULT_BT_LE_HCI_UART_PARITY,                        \
-    .enable_tx_cca              = MYNEWT_VAL(BLE_TX_CCA_ENABLED),                       \
-    .cca_rssi_thresh            = 256 - MYNEWT_VAL(BLE_CCA_RSSI_THRESH),                \
+    .enable_tx_cca              = DEFAULT_BT_LE_TX_CCA_ENABLED,                         \
+    .cca_rssi_thresh            = 256 - DEFAULT_BT_LE_CCA_RSSI_THRESH,                  \
     .sleep_en                   = NIMBLE_SLEEP_ENABLE,                                  \
     .coex_phy_coded_tx_rx_time_limit = DEFAULT_BT_LE_COEX_PHY_CODED_TX_RX_TLIM_EFF,     \
     .dis_scan_backoff           = NIMBLE_DISABLE_SCAN_BACKOFF,                          \
@@ -360,7 +226,7 @@ typedef struct esp_bt_controller_config_t esp_bt_controller_config_t;
     .config_magic = CONFIG_MAGIC,                                                       \
 };
 
-esp_err_t esp_bt_controller_init(struct esp_bt_controller_config_t *cfg);
+esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg);
 
 /**
  * @brief  Get BT controller is initialised/de-initialised/enabled/disabled

+ 209 - 0
components/bt/include/esp32c2/include/esp_bt_cfg.h

@@ -0,0 +1,209 @@
+/*
+ * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef __ESP_BT_CFG_H__
+#define __ESP_BT_CFG_H__
+
+#include <stdint.h>
+#include <stdbool.h>
+#include "esp_err.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if CONFIG_BT_NIMBLE_ENABLED
+#include "syscfg/syscfg.h"
+#endif
+
+#define NIMBLE_LL_STACK_SIZE CONFIG_BT_LE_CONTROLLER_TASK_STACK_SIZE
+
+#if CONFIG_BT_NIMBLE_ENABLED
+
+    #if CONFIG_BT_NIMBLE_LL_CFG_FEAT_LE_CODED_PHY
+    #define BLE_LL_SCAN_PHY_NUMBER_N (2)
+    #else
+    #define BLE_LL_SCAN_PHY_NUMBER_N (1)
+    #endif
+
+    #define DEFAULT_BT_LE_MAX_PERIODIC_ADVERTISER_LIST MYNEWT_VAL(BLE_MAX_PERIODIC_ADVERTISER_LIST)
+    #define DEFAULT_BT_LE_MAX_PERIODIC_SYNCS MYNEWT_VAL(BLE_MAX_PERIODIC_SYNCS)
+    #define DEFAULT_BT_LE_MAX_CONNECTIONS MYNEWT_VAL(BLE_MAX_CONNECTIONS)
+    #define DEFAULT_BT_LE_ACL_BUF_SIZE MYNEWT_VAL(BLE_ACL_BUF_SIZE)
+    #define DEFAULT_BT_LE_ACL_BUF_COUNT MYNEWT_VAL(BLE_ACL_BUF_COUNT)
+    #define DEFAULT_BT_LE_HCI_EVT_BUF_SIZE MYNEWT_VAL(BLE_HCI_EVT_BUF_SIZE)
+    #define DEFAULT_BT_LE_EXT_ADV_MAX_SIZE MYNEWT_VAL(BLE_EXT_ADV_MAX_SIZE)
+    #define DEFAULT_BT_LE_MAX_EXT_ADV_INSTANCES MYNEWT_VAL(BLE_MULTI_ADV_INSTANCES)
+    #define DEFAULT_BT_NIMBLE_WHITELIST_SIZE MYNEWT_VAL(BLE_LL_WHITELIST_SIZE)
+    #define DEFAULT_BT_LE_HCI_EVT_HI_BUF_COUNT MYNEWT_VAL(BLE_HCI_EVT_HI_BUF_COUNT)
+    #define DEFAULT_BT_LE_HCI_EVT_LO_BUF_COUNT MYNEWT_VAL(BLE_HCI_EVT_LO_BUF_COUNT)
+    #define DEFAULT_BT_LE_COEX_PHY_CODED_TX_RX_TLIM_EFF CONFIG_BT_NIMBLE_COEX_PHY_CODED_TX_RX_TLIM_EFF
+
+#else
+
+    #if CONFIG_BT_LE_LL_CFG_FEAT_LE_CODED_PHY
+    #define BLE_LL_SCAN_PHY_NUMBER_N (2)
+    #else
+    #define BLE_LL_SCAN_PHY_NUMBER_N (1)
+    #endif
+
+    #if defined(CONFIG_BT_LE_MAX_PERIODIC_ADVERTISER_LIST)
+        #define DEFAULT_BT_LE_MAX_PERIODIC_ADVERTISER_LIST (CONFIG_BT_LE_MAX_PERIODIC_ADVERTISER_LIST)
+    #else
+        #define DEFAULT_BT_LE_MAX_PERIODIC_ADVERTISER_LIST (0)
+    #endif
+
+    #if defined(CONFIG_BT_LE_MAX_PERIODIC_SYNCS)
+        #define DEFAULT_BT_LE_MAX_PERIODIC_SYNCS (CONFIG_BT_LE_MAX_PERIODIC_SYNCS)
+    #else
+        #define DEFAULT_BT_LE_MAX_PERIODIC_SYNCS (0)
+    #endif
+
+    #if defined(CONFIG_BT_LE_MAX_CONNECTIONS)
+        #define DEFAULT_BT_LE_MAX_CONNECTIONS (CONFIG_BT_LE_MAX_CONNECTIONS)
+    #else
+        #define DEFAULT_BT_LE_MAX_CONNECTIONS (0)
+    #endif
+
+    #if defined(CONFIG_BT_LE_ACL_BUF_SIZE)
+        #define DEFAULT_BT_LE_ACL_BUF_SIZE (CONFIG_BT_LE_ACL_BUF_SIZE)
+    #else
+        #define DEFAULT_BT_LE_ACL_BUF_SIZE (0)
+    #endif
+
+    #if defined(CONFIG_BT_LE_ACL_BUF_COUNT)
+        #define DEFAULT_BT_LE_ACL_BUF_COUNT (CONFIG_BT_LE_ACL_BUF_COUNT)
+    #else
+        #define DEFAULT_BT_LE_ACL_BUF_COUNT (0)
+    #endif
+
+    #if defined(CONFIG_BT_LE_HCI_EVT_BUF_SIZE)
+        #define DEFAULT_BT_LE_HCI_EVT_BUF_SIZE (CONFIG_BT_LE_HCI_EVT_BUF_SIZE)
+    #else
+        #define DEFAULT_BT_LE_HCI_EVT_BUF_SIZE (0)
+    #endif
+
+    #if defined(CONFIG_BT_LE_EXT_ADV_MAX_SIZE)
+        #define DEFAULT_BT_LE_EXT_ADV_MAX_SIZE (CONFIG_BT_LE_EXT_ADV_MAX_SIZE)
+    #else
+        #define DEFAULT_BT_LE_EXT_ADV_MAX_SIZE (0)
+    #endif
+
+    #if defined(CONFIG_BT_LE_MAX_EXT_ADV_INSTANCES)
+        #define DEFAULT_BT_LE_MAX_EXT_ADV_INSTANCES (CONFIG_BT_LE_MAX_EXT_ADV_INSTANCES)
+    #else
+        #define DEFAULT_BT_LE_MAX_EXT_ADV_INSTANCES (0)
+    #endif
+
+    #if defined(CONFIG_BT_LE_WHITELIST_SIZE)
+        #define DEFAULT_BT_NIMBLE_WHITELIST_SIZE (CONFIG_BT_LE_WHITELIST_SIZE)
+    #else
+        #define DEFAULT_BT_NIMBLE_WHITELIST_SIZE (0)
+    #endif
+
+    #if defined(CONFIG_BT_LE_HCI_EVT_HI_BUF_COUNT)
+        #define DEFAULT_BT_LE_HCI_EVT_HI_BUF_COUNT (CONFIG_BT_LE_HCI_EVT_HI_BUF_COUNT)
+    #else
+        #define DEFAULT_BT_LE_HCI_EVT_HI_BUF_COUNT (0)
+    #endif
+
+    #if defined(CONFIG_BT_LE_HCI_EVT_LO_BUF_COUNT)
+        #define DEFAULT_BT_LE_HCI_EVT_LO_BUF_COUNT (CONFIG_BT_LE_HCI_EVT_LO_BUF_COUNT)
+    #else
+        #define DEFAULT_BT_LE_HCI_EVT_LO_BUF_COUNT (0)
+    #endif
+
+    #define DEFAULT_BT_LE_COEX_PHY_CODED_TX_RX_TLIM_EFF CONFIG_BT_LE_COEX_PHY_CODED_TX_RX_TLIM_EFF
+
+#endif
+
+
+
+#ifdef CONFIG_BT_LE_HCI_INTERFACE_USE_UART
+#define HCI_UART_EN CONFIG_BT_LE_HCI_INTERFACE_USE_UART
+#else
+#define HCI_UART_EN 0 // hci ram mode
+#endif
+
+#ifdef CONFIG_BT_NIMBLE_SLEEP_ENABLE
+#define NIMBLE_SLEEP_ENABLE CONFIG_BT_NIMBLE_SLEEP_ENABLE
+#else
+#define NIMBLE_SLEEP_ENABLE  0
+#endif
+
+
+#ifdef CONFIG_BT_LE_TX_CCA_ENABLED
+    #define DEFAULT_BT_LE_TX_CCA_ENABLED (CONFIG_BT_LE_TX_CCA_ENABLED)
+#else
+    #define DEFAULT_BT_LE_TX_CCA_ENABLED (0)
+#endif
+
+#ifdef CONFIG_BT_LE_CCA_RSSI_THRESH
+    #define DEFAULT_BT_LE_CCA_RSSI_THRESH (CONFIG_BT_LE_CCA_RSSI_THRESH)
+#else
+    #define DEFAULT_BT_LE_CCA_RSSI_THRESH (50)
+#endif
+
+#define DEFAULT_BT_LE_SCAN_RSP_DATA_MAX_LEN_N DEFAULT_BT_LE_EXT_ADV_MAX_SIZE
+
+
+#if HCI_UART_EN
+    #define DEFAULT_BT_LE_HCI_UART_TX_PIN (CONFIG_BT_LE_HCI_UART_TX_PIN)
+    #define DEFAULT_BT_LE_HCI_UART_RX_PIN (CONFIG_BT_LE_HCI_UART_RX_PIN)
+    #define DEFAULT_BT_LE_HCI_UART_PORT (CONFIG_BT_LE_HCI_UART_PORT)
+    #define DEFAULT_BT_LE_HCI_UART_BAUD (CONFIG_BT_LE_HCI_UART_BAUD)
+    #define DEFAULT_BT_LE_HCI_UART_DATA_BITS (UART_DATA_8_BITS)
+    #define DEFAULT_BT_LE_HCI_UART_STOP_BITS (UART_STOP_BITS_1)
+    #define DEFAULT_BT_LE_HCI_UART_PARITY (0)
+    #define DEFAULT_BT_LE_HCI_UART_TASK_STACK_SIZE (CONFIG_BT_LE_HCI_UART_TASK_STACK_SIZE)
+    #define DEFAULT_BT_LE_HCI_UART_FLOW_CTRL (0)
+#else
+    #define DEFAULT_BT_LE_HCI_UART_TX_PIN (0)
+    #define DEFAULT_BT_LE_HCI_UART_RX_PIN (0)
+    #define DEFAULT_BT_LE_HCI_UART_PORT (0)
+    #define DEFAULT_BT_LE_HCI_UART_BAUD (0)
+    #define DEFAULT_BT_LE_HCI_UART_DATA_BITS (0)
+    #define DEFAULT_BT_LE_HCI_UART_STOP_BITS (0)
+    #define DEFAULT_BT_LE_HCI_UART_PARITY (0)
+    #define DEFAULT_BT_LE_HCI_UART_TASK_STACK_SIZE (0)
+    #define DEFAULT_BT_LE_HCI_UART_FLOW_CTRL (0)
+#endif
+
+/* Unchanged configuration */
+
+#define BLE_LL_CTRL_PROC_TIMEOUT_MS_N       (40000) /* ms */
+
+#define BLE_LL_CFG_NUM_HCI_CMD_PKTS_N       (1)
+
+#define BLE_LL_SCHED_ADV_MAX_USECS_N        (852)
+
+#define BLE_LL_SCHED_DIRECT_ADV_MAX_USECS_N (502)
+
+#define BLE_LL_SCHED_MAX_ADV_PDU_USECS_N    (376)
+
+#define BLE_LL_SUB_VERS_NR_N                (0x0000)
+
+#define BLE_LL_JITTER_USECS_N               (16)
+
+#define BLE_PHY_MAX_PWR_DBM_N               (10)
+
+#define BLE_LL_CONN_DEF_AUTH_PYLD_TMO_N     (3000)
+
+#define RTC_FREQ_N                          (32000) /* in Hz */
+
+#define BLE_LL_TX_PWR_DBM_N                 (0)
+
+
+#define RUN_BQB_TEST                        (0)
+#define RUN_QA_TEST                         (0)
+#define NIMBLE_DISABLE_SCAN_BACKOFF         (0)
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __ESP_BT_CFG_H__ */

+ 11 - 146
components/bt/include/esp32h2/include/esp_bt.h

@@ -14,20 +14,17 @@
 #include "esp_task.h"
 
 #include "nimble/nimble_npl.h"
-#include "syscfg/syscfg.h"
-#if CONFIG_BT_NIMBLE_ENABLED
-#include "esp_nimble_cfg.h"
+#include "esp_bt_cfg.h"
+
+#ifdef CONFIG_BT_LE_HCI_INTERFACE_USE_UART
+#include "driver/uart.h"
 #endif
-#include "nimble/ble.h"
+
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
-#if (SOC_ESP_NIMBLE_CONTROLLER)
-#define NIMBLE_LL_STACK_SIZE CONFIG_BT_LE_CONTROLLER_TASK_STACK_SIZE
-#endif
-
 /**
  * @brief Bluetooth mode for controller enable/disable
  */
@@ -131,7 +128,7 @@ esp_power_level_t esp_ble_tx_power_get(esp_ble_power_type_t power_type);
  *        some options or parameters of some functions enabled by config mask.
  */
 
-struct esp_bt_controller_config_t{
+typedef struct {
     uint32_t config_version;
     uint16_t ble_ll_resolv_list_size;
     uint16_t ble_hci_evt_hi_buf_count;
@@ -176,140 +173,8 @@ struct esp_bt_controller_config_t{
     uint8_t sleep_en;
     uint8_t coex_phy_coded_tx_rx_time_limit;
     uint32_t config_magic;
-};
+} esp_bt_controller_config_t;
 
-typedef struct esp_bt_controller_config_t esp_bt_controller_config_t;
-
-#define RUN_BQB_TEST                0
-#define RUN_QA_TEST                 0
-
-#ifdef CONFIG_BT_NIMBLE_HCI_INTERFACE_USE_UART
-#define HCI_UART_EN CONFIG_BT_NIMBLE_HCI_INTERFACE_USE_UART
-#else
-#define HCI_UART_EN 0 // hci ram mode
-#endif
-
-#if CONFIG_BT_LE_LL_CFG_FEAT_LE_CODED_PHY
-#define BLE_LL_SCAN_PHY_NUMBER_N (2)
-#else
-#define BLE_LL_SCAN_PHY_NUMBER_N (1)
-#endif
-
-#ifdef CONFIG_BT_NIMBLE_SLEEP_ENABLE
-#define NIMBLE_SLEEP_ENABLE CONFIG_BT_NIMBLE_SLEEP_ENABLE
-#else
-#define NIMBLE_SLEEP_ENABLE  0
-#endif
-
-#if CONFIG_BT_NIMBLE_ENABLED
-
-#define DEFAULT_BT_LE_MAX_PERIODIC_ADVERTISER_LIST MYNEWT_VAL(BLE_MAX_PERIODIC_ADVERTISER_LIST)
-#define DEFAULT_BT_LE_MAX_PERIODIC_SYNCS MYNEWT_VAL(BLE_MAX_PERIODIC_SYNCS)
-#define DEFAULT_BT_LE_MAX_CONNECTIONS MYNEWT_VAL(BLE_MAX_CONNECTIONS)
-#define DEFAULT_BT_LE_ACL_BUF_SIZE MYNEWT_VAL(BLE_ACL_BUF_SIZE)
-#define DEFAULT_BT_LE_ACL_BUF_COUNT MYNEWT_VAL(BLE_ACL_BUF_COUNT)
-#define DEFAULT_BT_LE_HCI_EVT_BUF_SIZE MYNEWT_VAL(BLE_HCI_EVT_BUF_SIZE)
-#define DEFAULT_BT_LE_EXT_ADV_MAX_SIZE MYNEWT_VAL(BLE_EXT_ADV_MAX_SIZE)
-#define DEFAULT_BT_LE_MAX_EXT_ADV_INSTANCES MYNEWT_VAL(BLE_MULTI_ADV_INSTANCES)
-#define DEFAULT_BT_NIMBLE_WHITELIST_SIZE MYNEWT_VAL(BLE_LL_WHITELIST_SIZE)
-#define DEFAULT_BT_LE_HCI_EVT_HI_BUF_COUNT MYNEWT_VAL(BLE_HCI_EVT_HI_BUF_COUNT)
-#define DEFAULT_BT_LE_HCI_EVT_LO_BUF_COUNT MYNEWT_VAL(BLE_HCI_EVT_LO_BUF_COUNT)
-#define DEFAULT_BT_LE_COEX_PHY_CODED_TX_RX_TLIM_EFF CONFIG_BT_NIMBLE_COEX_PHY_CODED_TX_RX_TLIM_EFF
-
-#else
-# if defined(CONFIG_BT_LE_MAX_PERIODIC_ADVERTISER_LIST)
-    #define DEFAULT_BT_LE_MAX_PERIODIC_ADVERTISER_LIST (CONFIG_BT_LE_MAX_PERIODIC_ADVERTISER_LIST)
-#else
-    #define DEFAULT_BT_LE_MAX_PERIODIC_ADVERTISER_LIST (0)
-#endif
-
-#if defined(CONFIG_BT_LE_MAX_PERIODIC_SYNCS)
-    #define DEFAULT_BT_LE_MAX_PERIODIC_SYNCS (CONFIG_BT_LE_MAX_PERIODIC_SYNCS)
-#else
-    #define DEFAULT_BT_LE_MAX_PERIODIC_SYNCS (0)
-#endif
-
-#if defined(CONFIG_BT_LE_MAX_CONNECTIONS)
-    #define DEFAULT_BT_LE_MAX_CONNECTIONS (CONFIG_BT_LE_MAX_CONNECTIONS)
-#else
-    #define DEFAULT_BT_LE_MAX_CONNECTIONS (0)
-#endif
-
-#if defined(CONFIG_BT_LE_ACL_BUF_SIZE)
-    #define DEFAULT_BT_LE_ACL_BUF_SIZE (CONFIG_BT_LE_ACL_BUF_SIZE)
-#else
-    #define DEFAULT_BT_LE_ACL_BUF_SIZE (0)
-#endif
-
-#if defined(CONFIG_BT_LE_ACL_BUF_COUNT)
-    #define DEFAULT_BT_LE_ACL_BUF_COUNT (CONFIG_BT_LE_ACL_BUF_COUNT)
-#else
-    #define DEFAULT_BT_LE_ACL_BUF_COUNT (0)
-#endif
-
-#if defined(CONFIG_BT_LE_HCI_EVT_BUF_SIZE)
-    #define DEFAULT_BT_LE_HCI_EVT_BUF_SIZE (CONFIG_BT_LE_HCI_EVT_BUF_SIZE)
-#else
-    #define DEFAULT_BT_LE_HCI_EVT_BUF_SIZE (0)
-#endif
-
-#if defined(CONFIG_BT_LE_EXT_ADV_MAX_SIZE)
-    #define DEFAULT_BT_LE_EXT_ADV_MAX_SIZE (CONFIG_BT_LE_EXT_ADV_MAX_SIZE)
-#else
-    #define DEFAULT_BT_LE_EXT_ADV_MAX_SIZE (0)
-#endif
-
-#if defined(CONFIG_BT_LE_MAX_EXT_ADV_INSTANCES)
-    #define DEFAULT_BT_LE_MAX_EXT_ADV_INSTANCES (CONFIG_BT_LE_MAX_EXT_ADV_INSTANCES)
-#else
-    #define DEFAULT_BT_LE_MAX_EXT_ADV_INSTANCES (0)
-#endif
-
-#if defined(CONFIG_BT_LE_WHITELIST_SIZE)
-    #define DEFAULT_BT_NIMBLE_WHITELIST_SIZE (CONFIG_BT_LE_WHITELIST_SIZE)
-#else
-    #define DEFAULT_BT_NIMBLE_WHITELIST_SIZE (0)
-#endif
-
-#if defined(CONFIG_BT_LE_HCI_EVT_HI_BUF_COUNT)
-    #define DEFAULT_BT_LE_HCI_EVT_HI_BUF_COUNT (CONFIG_BT_LE_HCI_EVT_HI_BUF_COUNT)
-#else
-    #define DEFAULT_BT_LE_HCI_EVT_HI_BUF_COUNT (0)
-#endif
-
-#if defined(CONFIG_BT_LE_HCI_EVT_LO_BUF_COUNT)
-    #define DEFAULT_BT_LE_HCI_EVT_LO_BUF_COUNT (CONFIG_BT_LE_HCI_EVT_LO_BUF_COUNT)
-#else
-    #define DEFAULT_BT_LE_HCI_EVT_LO_BUF_COUNT (0)
-#endif
-
-#define DEFAULT_BT_LE_COEX_PHY_CODED_TX_RX_TLIM_EFF CONFIG_BT_LE_COEX_PHY_CODED_TX_RX_TLIM_EFF
-
-#endif
-
-
-#ifdef BT_LE_HCI_INTERFACE_USE_UART
-    #define DEFAULT_BT_LE_HCI_UART_TX_PIN (CONFIG_BT_LE_HCI_UART_TX_PIN)
-    #define DEFAULT_BT_LE_HCI_UART_RX_PIN (CONFIG_BT_LE_HCI_UART_RX_PIN)
-    #define DEFAULT_BT_LE_HCI_UART_PORT (CONFIG_BT_LE_HCI_UART_PORT)
-    #define DEFAULT_BT_LE_HCI_UART_BAUD (CONFIG_BT_LE_HCI_UART_BAUD)
-    #define DEFAULT_BT_LE_HCI_UART_DATA_BITS (CONFIG_BT_LE_HCI_UART_DATA_BITS)
-    #define DEFAULT_BT_LE_HCI_UART_STOP_BITS (CONFIG_BT_LE_HCI_UART_STOP_BITS)
-    #define DEFAULT_BT_LE_HCI_UART_PARITY (CONFIG_BT_LE_HCI_UART_BAUD)
-    #define DEFAULT_BT_LE_HCI_UART_TASK_STACK_SIZE (CONFIG_BT_LE_HCI_UART_TASK_STACK_SIZE)
-    #define DEFAULT_BT_LE_HCI_UART_FLOW_CTRL (CONFIG_BT_LE_HCI_UART_FLOW_CTRL)
-#else
-    #warning "DEFAULT_BT_LE_HCI_UART is not set"
-    #define DEFAULT_BT_LE_HCI_UART_TX_PIN (0)
-    #define DEFAULT_BT_LE_HCI_UART_RX_PIN (0)
-    #define DEFAULT_BT_LE_HCI_UART_PORT (0)
-    #define DEFAULT_BT_LE_HCI_UART_BAUD (0)
-    #define DEFAULT_BT_LE_HCI_UART_DATA_BITS (8)
-    #define DEFAULT_BT_LE_HCI_UART_STOP_BITS (1)
-    #define DEFAULT_BT_LE_HCI_UART_PARITY (0)
-    #define DEFAULT_BT_LE_HCI_UART_TASK_STACK_SIZE (0)
-    #define DEFAULT_BT_LE_HCI_UART_FLOW_CTRL (0)
-#endif
 
 #define BT_CONTROLLER_INIT_CONFIG_DEFAULT() {                                           \
     .config_version = CONFIG_VERSION,                                                   \
@@ -329,7 +194,7 @@ typedef struct esp_bt_controller_config_t esp_bt_controller_config_t;
     .ble_ll_sched_max_adv_pdu_usecs = BLE_LL_SCHED_MAX_ADV_PDU_USECS_N,                 \
     .ble_ll_sched_direct_adv_max_usecs = BLE_LL_SCHED_DIRECT_ADV_MAX_USECS_N,           \
     .ble_ll_sched_adv_max_usecs = BLE_LL_SCHED_ADV_MAX_USECS_N,                         \
-    .ble_scan_rsp_data_max_len = BLE_SCAN_RSP_DATA_MAX_LEN_N,                           \
+    .ble_scan_rsp_data_max_len = DEFAULT_BT_LE_SCAN_RSP_DATA_MAX_LEN_N,                 \
     .ble_ll_cfg_num_hci_cmd_pkts = BLE_LL_CFG_NUM_HCI_CMD_PKTS_N,                       \
     .ble_ll_ctrl_proc_timeout_ms = BLE_LL_CTRL_PROC_TIMEOUT_MS_N,                       \
     .nimble_max_connections = DEFAULT_BT_LE_MAX_CONNECTIONS,                            \
@@ -351,14 +216,14 @@ typedef struct esp_bt_controller_config_t esp_bt_controller_config_t;
     .ble_hci_uart_stop_bits     = DEFAULT_BT_LE_HCI_UART_STOP_BITS,                     \
     .ble_hci_uart_flow_ctrl     = DEFAULT_BT_LE_HCI_UART_FLOW_CTRL,                     \
     .ble_hci_uart_uart_parity   = DEFAULT_BT_LE_HCI_UART_PARITY,                        \
-    .enable_tx_cca              = MYNEWT_VAL(BLE_TX_CCA_ENABLED),                       \
-    .cca_rssi_thresh            = 256 - MYNEWT_VAL(BLE_CCA_RSSI_THRESH),                \
+    .enable_tx_cca              = DEFAULT_BT_LE_TX_CCA_ENABLED,                         \
+    .cca_rssi_thresh            = 256 - DEFAULT_BT_LE_CCA_RSSI_THRESH,                  \
     .sleep_en                   = NIMBLE_SLEEP_ENABLE,                                  \
     .coex_phy_coded_tx_rx_time_limit = DEFAULT_BT_LE_COEX_PHY_CODED_TX_RX_TLIM_EFF,     \
     .config_magic = CONFIG_MAGIC,                                                       \
 };
 
-esp_err_t esp_bt_controller_init(struct esp_bt_controller_config_t *cfg);
+esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg);
 
 /**
  * @brief  Get BT controller is initialised/de-initialised/enabled/disabled

+ 209 - 0
components/bt/include/esp32h2/include/esp_bt_cfg.h

@@ -0,0 +1,209 @@
+/*
+ * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef __ESP_BT_CFG_H__
+#define __ESP_BT_CFG_H__
+
+#include <stdint.h>
+#include <stdbool.h>
+#include "esp_err.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if CONFIG_BT_NIMBLE_ENABLED
+#include "syscfg/syscfg.h"
+#endif
+
+#define NIMBLE_LL_STACK_SIZE CONFIG_BT_LE_CONTROLLER_TASK_STACK_SIZE
+
+#if CONFIG_BT_NIMBLE_ENABLED
+
+    #if CONFIG_BT_NIMBLE_LL_CFG_FEAT_LE_CODED_PHY
+    #define BLE_LL_SCAN_PHY_NUMBER_N (2)
+    #else
+    #define BLE_LL_SCAN_PHY_NUMBER_N (1)
+    #endif
+
+    #define DEFAULT_BT_LE_MAX_PERIODIC_ADVERTISER_LIST MYNEWT_VAL(BLE_MAX_PERIODIC_ADVERTISER_LIST)
+    #define DEFAULT_BT_LE_MAX_PERIODIC_SYNCS MYNEWT_VAL(BLE_MAX_PERIODIC_SYNCS)
+    #define DEFAULT_BT_LE_MAX_CONNECTIONS MYNEWT_VAL(BLE_MAX_CONNECTIONS)
+    #define DEFAULT_BT_LE_ACL_BUF_SIZE MYNEWT_VAL(BLE_ACL_BUF_SIZE)
+    #define DEFAULT_BT_LE_ACL_BUF_COUNT MYNEWT_VAL(BLE_ACL_BUF_COUNT)
+    #define DEFAULT_BT_LE_HCI_EVT_BUF_SIZE MYNEWT_VAL(BLE_HCI_EVT_BUF_SIZE)
+    #define DEFAULT_BT_LE_EXT_ADV_MAX_SIZE MYNEWT_VAL(BLE_EXT_ADV_MAX_SIZE)
+    #define DEFAULT_BT_LE_MAX_EXT_ADV_INSTANCES MYNEWT_VAL(BLE_MULTI_ADV_INSTANCES)
+    #define DEFAULT_BT_NIMBLE_WHITELIST_SIZE MYNEWT_VAL(BLE_LL_WHITELIST_SIZE)
+    #define DEFAULT_BT_LE_HCI_EVT_HI_BUF_COUNT MYNEWT_VAL(BLE_HCI_EVT_HI_BUF_COUNT)
+    #define DEFAULT_BT_LE_HCI_EVT_LO_BUF_COUNT MYNEWT_VAL(BLE_HCI_EVT_LO_BUF_COUNT)
+    #define DEFAULT_BT_LE_COEX_PHY_CODED_TX_RX_TLIM_EFF CONFIG_BT_NIMBLE_COEX_PHY_CODED_TX_RX_TLIM_EFF
+
+#else
+
+    #if CONFIG_BT_LE_LL_CFG_FEAT_LE_CODED_PHY
+    #define BLE_LL_SCAN_PHY_NUMBER_N (2)
+    #else
+    #define BLE_LL_SCAN_PHY_NUMBER_N (1)
+    #endif
+
+    #if defined(CONFIG_BT_LE_MAX_PERIODIC_ADVERTISER_LIST)
+        #define DEFAULT_BT_LE_MAX_PERIODIC_ADVERTISER_LIST (CONFIG_BT_LE_MAX_PERIODIC_ADVERTISER_LIST)
+    #else
+        #define DEFAULT_BT_LE_MAX_PERIODIC_ADVERTISER_LIST (0)
+    #endif
+
+    #if defined(CONFIG_BT_LE_MAX_PERIODIC_SYNCS)
+        #define DEFAULT_BT_LE_MAX_PERIODIC_SYNCS (CONFIG_BT_LE_MAX_PERIODIC_SYNCS)
+    #else
+        #define DEFAULT_BT_LE_MAX_PERIODIC_SYNCS (0)
+    #endif
+
+    #if defined(CONFIG_BT_LE_MAX_CONNECTIONS)
+        #define DEFAULT_BT_LE_MAX_CONNECTIONS (CONFIG_BT_LE_MAX_CONNECTIONS)
+    #else
+        #define DEFAULT_BT_LE_MAX_CONNECTIONS (0)
+    #endif
+
+    #if defined(CONFIG_BT_LE_ACL_BUF_SIZE)
+        #define DEFAULT_BT_LE_ACL_BUF_SIZE (CONFIG_BT_LE_ACL_BUF_SIZE)
+    #else
+        #define DEFAULT_BT_LE_ACL_BUF_SIZE (0)
+    #endif
+
+    #if defined(CONFIG_BT_LE_ACL_BUF_COUNT)
+        #define DEFAULT_BT_LE_ACL_BUF_COUNT (CONFIG_BT_LE_ACL_BUF_COUNT)
+    #else
+        #define DEFAULT_BT_LE_ACL_BUF_COUNT (0)
+    #endif
+
+    #if defined(CONFIG_BT_LE_HCI_EVT_BUF_SIZE)
+        #define DEFAULT_BT_LE_HCI_EVT_BUF_SIZE (CONFIG_BT_LE_HCI_EVT_BUF_SIZE)
+    #else
+        #define DEFAULT_BT_LE_HCI_EVT_BUF_SIZE (0)
+    #endif
+
+    #if defined(CONFIG_BT_LE_EXT_ADV_MAX_SIZE)
+        #define DEFAULT_BT_LE_EXT_ADV_MAX_SIZE (CONFIG_BT_LE_EXT_ADV_MAX_SIZE)
+    #else
+        #define DEFAULT_BT_LE_EXT_ADV_MAX_SIZE (0)
+    #endif
+
+    #if defined(CONFIG_BT_LE_MAX_EXT_ADV_INSTANCES)
+        #define DEFAULT_BT_LE_MAX_EXT_ADV_INSTANCES (CONFIG_BT_LE_MAX_EXT_ADV_INSTANCES)
+    #else
+        #define DEFAULT_BT_LE_MAX_EXT_ADV_INSTANCES (0)
+    #endif
+
+    #if defined(CONFIG_BT_LE_WHITELIST_SIZE)
+        #define DEFAULT_BT_NIMBLE_WHITELIST_SIZE (CONFIG_BT_LE_WHITELIST_SIZE)
+    #else
+        #define DEFAULT_BT_NIMBLE_WHITELIST_SIZE (0)
+    #endif
+
+    #if defined(CONFIG_BT_LE_HCI_EVT_HI_BUF_COUNT)
+        #define DEFAULT_BT_LE_HCI_EVT_HI_BUF_COUNT (CONFIG_BT_LE_HCI_EVT_HI_BUF_COUNT)
+    #else
+        #define DEFAULT_BT_LE_HCI_EVT_HI_BUF_COUNT (0)
+    #endif
+
+    #if defined(CONFIG_BT_LE_HCI_EVT_LO_BUF_COUNT)
+        #define DEFAULT_BT_LE_HCI_EVT_LO_BUF_COUNT (CONFIG_BT_LE_HCI_EVT_LO_BUF_COUNT)
+    #else
+        #define DEFAULT_BT_LE_HCI_EVT_LO_BUF_COUNT (0)
+    #endif
+
+    #define DEFAULT_BT_LE_COEX_PHY_CODED_TX_RX_TLIM_EFF CONFIG_BT_LE_COEX_PHY_CODED_TX_RX_TLIM_EFF
+
+#endif
+
+
+
+#ifdef CONFIG_BT_LE_HCI_INTERFACE_USE_UART
+#define HCI_UART_EN CONFIG_BT_LE_HCI_INTERFACE_USE_UART
+#else
+#define HCI_UART_EN 0 // hci ram mode
+#endif
+
+#ifdef CONFIG_BT_NIMBLE_SLEEP_ENABLE
+#define NIMBLE_SLEEP_ENABLE CONFIG_BT_NIMBLE_SLEEP_ENABLE
+#else
+#define NIMBLE_SLEEP_ENABLE  0
+#endif
+
+
+#ifdef CONFIG_BT_LE_TX_CCA_ENABLED
+    #define DEFAULT_BT_LE_TX_CCA_ENABLED (CONFIG_BT_LE_TX_CCA_ENABLED)
+#else
+    #define DEFAULT_BT_LE_TX_CCA_ENABLED (0)
+#endif
+
+#ifdef CONFIG_BT_LE_CCA_RSSI_THRESH
+    #define DEFAULT_BT_LE_CCA_RSSI_THRESH (CONFIG_BT_LE_CCA_RSSI_THRESH)
+#else
+    #define DEFAULT_BT_LE_CCA_RSSI_THRESH (50)
+#endif
+
+#define DEFAULT_BT_LE_SCAN_RSP_DATA_MAX_LEN_N DEFAULT_BT_LE_EXT_ADV_MAX_SIZE
+
+
+#if HCI_UART_EN
+    #define DEFAULT_BT_LE_HCI_UART_TX_PIN (CONFIG_BT_LE_HCI_UART_TX_PIN)
+    #define DEFAULT_BT_LE_HCI_UART_RX_PIN (CONFIG_BT_LE_HCI_UART_RX_PIN)
+    #define DEFAULT_BT_LE_HCI_UART_PORT (CONFIG_BT_LE_HCI_UART_PORT)
+    #define DEFAULT_BT_LE_HCI_UART_BAUD (CONFIG_BT_LE_HCI_UART_BAUD)
+    #define DEFAULT_BT_LE_HCI_UART_DATA_BITS (UART_DATA_8_BITS)
+    #define DEFAULT_BT_LE_HCI_UART_STOP_BITS (UART_STOP_BITS_1)
+    #define DEFAULT_BT_LE_HCI_UART_PARITY (0)
+    #define DEFAULT_BT_LE_HCI_UART_TASK_STACK_SIZE (CONFIG_BT_LE_HCI_UART_TASK_STACK_SIZE)
+    #define DEFAULT_BT_LE_HCI_UART_FLOW_CTRL (0)
+#else
+    #define DEFAULT_BT_LE_HCI_UART_TX_PIN (0)
+    #define DEFAULT_BT_LE_HCI_UART_RX_PIN (0)
+    #define DEFAULT_BT_LE_HCI_UART_PORT (0)
+    #define DEFAULT_BT_LE_HCI_UART_BAUD (0)
+    #define DEFAULT_BT_LE_HCI_UART_DATA_BITS (0)
+    #define DEFAULT_BT_LE_HCI_UART_STOP_BITS (0)
+    #define DEFAULT_BT_LE_HCI_UART_PARITY (0)
+    #define DEFAULT_BT_LE_HCI_UART_TASK_STACK_SIZE (0)
+    #define DEFAULT_BT_LE_HCI_UART_FLOW_CTRL (0)
+#endif
+
+/* Unchanged configuration */
+
+#define BLE_LL_CTRL_PROC_TIMEOUT_MS_N       (40000) /* ms */
+
+#define BLE_LL_CFG_NUM_HCI_CMD_PKTS_N       (1)
+
+#define BLE_LL_SCHED_ADV_MAX_USECS_N        (852)
+
+#define BLE_LL_SCHED_DIRECT_ADV_MAX_USECS_N (502)
+
+#define BLE_LL_SCHED_MAX_ADV_PDU_USECS_N    (376)
+
+#define BLE_LL_SUB_VERS_NR_N                (0x0000)
+
+#define BLE_LL_JITTER_USECS_N               (16)
+
+#define BLE_PHY_MAX_PWR_DBM_N               (10)
+
+#define BLE_LL_CONN_DEF_AUTH_PYLD_TMO_N     (3000)
+
+#define RTC_FREQ_N                          (32000) /* in Hz */
+
+#define BLE_LL_TX_PWR_DBM_N                 (0)
+
+
+#define RUN_BQB_TEST                        (0)
+#define RUN_QA_TEST                         (0)
+#define NIMBLE_DISABLE_SCAN_BACKOFF         (0)
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __ESP_BT_CFG_H__ */

+ 15 - 0
components/bt/porting/ext/tinycrypt/AUTHORS

@@ -0,0 +1,15 @@
+Architect:
+Rafael Misoczki <rafael.misoczki@intel.com>
+
+Open Source Maintainer:
+Constanza Heath <constanza.m.heath@intel.com>
+Rafael Misoczki <rafael.misoczki@intel.com>
+
+Contributors:
+Constanza Heath <constanza.m.heath@intel.com>
+Rafael Misoczki <rafael.misoczki@intel.com>
+Flavio Santes <flavio.santes@intel.com>
+Jarkko Sakkinen <jarkko.sakkinen@intel.com>
+Chris Morrison
+Marti Bolivar
+Colin Ian King

+ 61 - 0
components/bt/porting/ext/tinycrypt/LICENSE

@@ -0,0 +1,61 @@
+
+================================================================================
+
+                     TinyCrypt Cryptographic Library
+
+================================================================================
+
+          Copyright (c) 2017, Intel Corporation. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+  - 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 the Intel Corporation nor the names of its contributors
+      may be used to endorse or promote products derived from this software
+      without specific prior written permission.
+
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 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.
+
+================================================================================
+Copyright (c) 2014, Kenneth MacKay
+All rights reserved.
+
+https://github.com/kmackay/micro-ecc
+
+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.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+================================================================================

+ 70 - 0
components/bt/porting/ext/tinycrypt/README

@@ -0,0 +1,70 @@
+
+================================================================================
+
+                     TinyCrypt Cryptographic Library
+
+================================================================================
+
+          Copyright (c) 2017, Intel Corporation. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+  - 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 the Intel Corporation nor the names of its contributors
+      may be used to endorse or promote products derived from this software
+      without specific prior written permission.
+
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 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.
+
+================================================================================
+
+Overview:
+
+The TinyCrypt Library provides an implementation for constrained devices of a
+minimal set of standard cryptography primitives.
+
+Please, ***SEE THE DOCUMENTATION*** folder for more information on the supported
+cryptographic primitives and the limitations of TinyCrypt library. For usage,
+security and technicalities, please see the corresponding header file of each
+cryptographic primitive.
+
+================================================================================
+
+Organization:
+
+/lib: C source code of the cryptographic primitives.
+/lib/include/tinycrypt: C header files of the cryptographic primitives.
+/tests: Test vectors of the cryptographic primitives.
+/doc: Documentation of TinyCrypt.
+
+================================================================================
+
+Building:
+
+1) In Makefile.conf set:
+    - CFLAGS for compiler flags.
+    - CC for compiler.
+    - ENABLE_TESTS for enabling (true) or disabling (false) tests compilation.
+2) In lib/Makefile select the primitives required by your project.
+3) In tests/Makefile select the corresponding tests of the selected primitives.
+4) make
+5) run tests in tests/
+
+================================================================================

+ 1 - 0
components/bt/porting/ext/tinycrypt/VERSION

@@ -0,0 +1 @@
+0.2.8

+ 352 - 0
components/bt/porting/ext/tinycrypt/documentation/tinycrypt.rst

@@ -0,0 +1,352 @@
+
+TinyCrypt Cryptographic Library
+###############################
+Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
+
+Overview
+********
+The TinyCrypt Library provides an implementation for targeting constrained devices
+with a minimal set of standard cryptography primitives, as listed below. To better
+serve applications targeting constrained devices, TinyCrypt implementations differ
+from the standard specifications (see the Important Remarks section for some
+important differences). Certain cryptographic primitives depend on other
+primitives, as mentioned in the list below.
+
+Aside from the Important Remarks section below, valuable information on the usage,
+security and technicalities of each cryptographic primitive are found in the
+corresponding header file.
+
+* SHA-256:
+
+  * Type of primitive: Hash function.
+  * Standard Specification: NIST FIPS PUB 180-4.
+  * Requires: --
+
+* HMAC-SHA256:
+
+  * Type of primitive: Message authentication code.
+  * Standard Specification: RFC 2104.
+  * Requires: SHA-256
+
+* HMAC-PRNG:
+
+  * Type of primitive: Pseudo-random number generator (256-bit strength).
+  * Standard Specification: NIST SP 800-90A.
+  * Requires: SHA-256 and HMAC-SHA256.
+
+* AES-128:
+
+  * Type of primitive: Block cipher.
+  * Standard Specification: NIST FIPS PUB 197.
+  * Requires: --
+
+* AES-CBC mode:
+
+  * Type of primitive: Encryption mode of operation.
+  * Standard Specification: NIST SP 800-38A.
+  * Requires: AES-128.
+
+* AES-CTR mode:
+
+  * Type of primitive: Encryption mode of operation.
+  * Standard Specification: NIST SP 800-38A.
+  * Requires: AES-128.
+
+* AES-CMAC mode:
+
+  * Type of primitive: Message authentication code.
+  * Standard Specification: NIST SP 800-38B.
+  * Requires: AES-128.
+
+* AES-CCM mode:
+
+  * Type of primitive: Authenticated encryption.
+  * Standard Specification: NIST SP 800-38C.
+  * Requires: AES-128.
+
+* CTR-PRNG:
+
+  * Type of primitive: Pseudo-random number generator (128-bit strength).
+  * Standard Specification: NIST SP 800-90A.
+  * Requires: AES-128.
+  
+* ECC-DH:
+
+  * Type of primitive: Key exchange based on curve NIST p-256.
+  * Standard Specification: RFC 6090.
+  * Requires: ECC auxiliary functions (ecc.h/c).
+
+* ECC-DSA:
+
+  * Type of primitive: Digital signature based on curve NIST p-256.
+  * Standard Specification: RFC 6090.
+  * Requires: ECC auxiliary functions (ecc.h/c).
+
+Design Goals
+************
+
+* Minimize the code size of each cryptographic primitive. This means minimize
+ the size of a platform-independent implementation, as presented in TinyCrypt.
+ Note that various applications may require further features, optimizations with
+ respect to other metrics and countermeasures for particular threats. These
+ peculiarities would increase the code size and thus are not considered here.
+
+* Minimize the dependencies among the cryptographic primitives. This means
+ that it is unnecessary to build and allocate object code for more primitives
+ than the ones strictly required by the intended application. In other words,
+ one can select and compile only the primitives required by the application.
+
+
+Important Remarks
+*****************
+
+The cryptographic implementations in TinyCrypt library have some limitations.
+Some of these limitations are inherent to the cryptographic primitives
+themselves, while others are specific to TinyCrypt. These limitations were accepted
+in order to meet its design goals (in special, minimal code size) and to better 
+serve applications targeting constrained devices in general. Some of these 
+limitations are discussed in-depth below.
+
+General Remarks
+***************
+
+* TinyCrypt does **not** intend to be fully side-channel resistant. Due to the
+  variety of side-channel attacks, many of them only relevant to certain 
+  platforms. In this sense, instead of penalizing all library users with
+  side-channel countermeasures such as increasing the overall code size,
+  TinyCrypt only implements certain generic timing-attack countermeasures.
+
+Specific Remarks
+****************
+
+* SHA-256:
+
+  * The number of bits_hashed in the state is not checked for overflow. Note
+    however that this will only be a problem if you intend to hash more than
+    2^64 bits, which is an extremely large window.
+
+* HMAC:
+
+  * The HMAC verification process is assumed to be performed by the application.
+    This compares the computed tag with some given tag.
+    Note that conventional memory-comparison methods (such as memcmp function)
+    might be vulnerable to timing attacks; thus be sure to use a constant-time
+    memory comparison function (such as compare_constant_time
+    function provided in lib/utils.c).
+
+  * The tc_hmac_final function, responsible for computing the message tag,
+    cleans the state context before exiting. Thus, applications do not need to
+    clean the TCHmacState_t ctx after calling tc_hmac_final. This should not
+    be changed in future versions of the library as there are applications
+    currently relying on this good-practice/feature of TinyCrypt.
+
+* HMAC-PRNG:
+
+  * Before using HMAC-PRNG, you *must* find an entropy source to produce a seed.
+    PRNGs only stretch the seed into a seemingly random output of arbitrary
+    length. The security of the output is exactly equal to the
+    unpredictability of the seed.
+
+  * NIST SP 800-90A requires three items as seed material in the initialization
+    step: entropy seed, personalization and a nonce (which is not implemented).
+    TinyCrypt requires the personalization byte array and automatically creates
+    the entropy seed using a mandatory call to the re-seed function.
+
+* AES-128:
+
+  * The current implementation does not support other key-lengths (such as 256
+    bits). Note that if you need AES-256, it doesn't sound as though your
+    application is running in a constrained environment. AES-256 requires keys
+    twice the size as for AES-128, and the key schedule is 40% larger.
+
+* CTR mode:
+
+  * The AES-CTR mode limits the size of a data message they encrypt to 2^32
+    blocks. If you need to encrypt larger data sets, your application would
+    need to replace the key after 2^32 block encryptions.
+
+* CTR-PRNG:
+
+  * Before using CTR-PRNG, you *must* find an entropy source to produce a seed.
+    PRNGs only stretch the seed into a seemingly random output of arbitrary
+    length. The security of the output is exactly equal to the
+    unpredictability of the seed.
+
+* CBC mode:
+
+  * TinyCrypt CBC decryption assumes that the iv and the ciphertext are
+    contiguous (as produced by TinyCrypt CBC encryption). This allows for a
+    very efficient decryption algorithm that would not otherwise be possible.
+
+* CMAC mode:
+
+  * AES128-CMAC mode of operation offers 64 bits of security against collision
+    attacks. Note however that an external attacker cannot generate the tags
+    him/herself without knowing the MAC key. In this sense, to attack the
+    collision property of AES128-CMAC, an external attacker would need the
+    cooperation of the legal user to produce an exponentially high number of
+    tags (e.g. 2^64) to finally be able to look for collisions and benefit
+    from them. As an extra precaution, the current implementation allows to at
+    most 2^48 calls to tc_cmac_update function before re-calling tc_cmac_setup
+    (allowing a new key to be set), as suggested in Appendix B of SP 800-38B.
+
+* CCM mode:
+
+  * There are a few tradeoffs for the selection of the parameters of CCM mode.
+    In special, there is a tradeoff between the maximum number of invocations
+    of CCM under a given key and the maximum payload length for those
+    invocations. Both things are related to the parameter 'q' of CCM mode. The
+    maximum number of invocations of CCM under a given key is determined by
+    the nonce size, which is: 15-q bytes. The maximum payload length for those
+    invocations is defined as 2^(8q) bytes.
+
+    To achieve minimal code size, TinyCrypt CCM implementation fixes q = 2,
+    which is a quite reasonable choice for constrained applications. The
+    implications of this choice are:
+
+    The nonce size is: 13 bytes.
+
+    The maximum payload length is: 2^16 bytes = 65 KB.
+
+    The mac size parameter is an important parameter to estimate the security
+    against collision attacks (that aim at finding different messages that
+    produce the same authentication tag). TinyCrypt CCM implementation
+    accepts any even integer between 4 and 16, as suggested in SP 800-38C.
+
+  * TinyCrypt CCM implementation accepts associated data of any length between
+    0 and (2^16 - 2^8) = 65280 bytes.
+
+  * TinyCrypt CCM implementation accepts:
+
+        * Both non-empty payload and associated data (it encrypts and
+          authenticates the payload and only authenticates the associated data);
+
+        * Non-empty payload and empty associated data (it encrypts and
+          authenticates the payload);
+
+        * Non-empty associated data and empty payload (it degenerates to an
+          authentication-only mode on the associated data).
+
+   * RFC-3610, which also specifies CCM, presents a few relevant security
+     suggestions, such as: it is recommended for most applications to use a
+     mac size greater than 8. Besides, it is emphasized that the usage of the
+     same nonce for two different messages which are encrypted with the same
+     key obviously destroys the security properties of CCM mode.
+
+* ECC-DH and ECC-DSA:
+
+  * TinyCrypt ECC implementation is based on micro-ecc (see
+    https://github.com/kmackay/micro-ecc). In the original micro-ecc 
+    documentation, there is an important remark about the way integers are
+    represented:
+
+    "Integer representation: To reduce code size, all large integers are
+    represented using little-endian words - so the least significant word is
+    first. You can use the 'ecc_bytes2native()' and 'ecc_native2bytes()'
+    functions to convert between the native integer representation and the
+    standardized octet representation."
+
+    Note that the assumed bit layout is: {31, 30, ..., 0}, {63, 62, ..., 32},
+    {95, 94, ..., 64}, {127, 126, ..., 96} for a very-long-integer (vli)
+    consisting of 4 unsigned integers (as an example).
+
+  * A cryptographically-secure PRNG function must be set (using uECC_set_rng())
+    before calling uECC_make_key() or uECC_sign().
+
+Examples of Applications
+************************
+It is possible to do useful cryptography with only the given small set of
+primitives. With this list of primitives it becomes feasible to support a range
+of cryptography usages:
+
+ * Measurement of code, data structures, and other digital artifacts (SHA256);
+
+ * Generate commitments (SHA256);
+
+ * Construct keys (HMAC-SHA256);
+
+ * Extract entropy from strings containing some randomness (HMAC-SHA256);
+
+ * Construct random mappings (HMAC-SHA256);
+
+ * Construct nonces and challenges (HMAC-PRNG, CTR-PRNG);
+
+ * Authenticate using a shared secret (HMAC-SHA256);
+
+ * Create an authenticated, replay-protected session (HMAC-SHA256 + HMAC-PRNG);
+
+ * Authenticated encryption (AES-128 + AES-CCM);
+
+ * Key-exchange (EC-DH);
+
+ * Digital signature (EC-DSA);
+
+Test Vectors
+************
+
+The library provides a test program for each cryptographic primitive (see 'test'
+folder). Besides illustrating how to use the primitives, these tests evaluate
+the correctness of the implementations by checking the results against
+well-known publicly validated test vectors.
+
+For the case of the HMAC-PRNG, due to the necessity of performing an extensive
+battery test to produce meaningful conclusions, we suggest the user to evaluate
+the unpredictability of the implementation by using the NIST Statistical Test
+Suite (see References).
+
+For the case of the EC-DH and EC-DSA implementations, most of the test vectors
+were obtained from the site of the NIST Cryptographic Algorithm Validation
+Program (CAVP), see References.
+
+References
+**********
+
+* `NIST FIPS PUB 180-4 (SHA-256)`_
+
+.. _NIST FIPS PUB 180-4 (SHA-256):
+   http://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf
+
+* `NIST FIPS PUB 197 (AES-128)`_
+
+.. _NIST FIPS PUB 197 (AES-128):
+   http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf
+
+* `NIST SP800-90A (HMAC-PRNG)`_
+
+.. _NIST SP800-90A (HMAC-PRNG):
+   http://csrc.nist.gov/publications/nistpubs/800-90A/SP800-90A.pdf
+
+* `NIST SP 800-38A (AES-CBC and AES-CTR)`_
+
+.. _NIST SP 800-38A (AES-CBC and AES-CTR):
+   http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
+
+* `NIST SP 800-38B (AES-CMAC)`_
+
+.. _NIST SP 800-38B (AES-CMAC):
+   http://csrc.nist.gov/publications/nistpubs/800-38B/SP_800-38B.pdf
+
+* `NIST SP 800-38C (AES-CCM)`_
+
+.. _NIST SP 800-38C (AES-CCM):
+    http://csrc.nist.gov/publications/nistpubs/800-38C/SP800-38C_updated-July20_2007.pdf
+
+* `NIST Statistical Test Suite (useful for testing HMAC-PRNG)`_
+
+.. _NIST Statistical Test Suite (useful for testing HMAC-PRNG):
+   http://csrc.nist.gov/groups/ST/toolkit/rng/documentation_software.html
+
+* `NIST Cryptographic Algorithm Validation Program (CAVP) site`_
+
+.. _NIST Cryptographic Algorithm Validation Program (CAVP) site:
+   http://csrc.nist.gov/groups/STM/cavp/
+
+* `RFC 2104 (HMAC-SHA256)`_
+
+.. _RFC 2104 (HMAC-SHA256):
+   https://www.ietf.org/rfc/rfc2104.txt
+
+* `RFC 6090 (ECC-DH and ECC-DSA)`_
+
+.. _RFC 6090 (ECC-DH and ECC-DSA):
+   https://www.ietf.org/rfc/rfc6090.txt

+ 130 - 0
components/bt/porting/ext/tinycrypt/include/tinycrypt/aes.h

@@ -0,0 +1,130 @@
+/* aes.h - TinyCrypt interface to an AES-128 implementation */
+
+/*
+ *  Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *    - 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 Intel Corporation nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 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.
+ */
+
+/**
+ * @file
+ * @brief -- Interface to an AES-128 implementation.
+ *
+ *  Overview:   AES-128 is a NIST approved block cipher specified in
+ *              FIPS 197. Block ciphers are deterministic algorithms that
+ *              perform a transformation specified by a symmetric key in fixed-
+ *              length data sets, also called blocks.
+ *
+ *  Security:   AES-128 provides approximately 128 bits of security.
+ *
+ *  Usage:      1) call tc_aes128_set_encrypt/decrypt_key to set the key.
+ *
+ *              2) call tc_aes_encrypt/decrypt to process the data.
+ */
+
+#ifndef __TC_AES_H__
+#define __TC_AES_H__
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define Nb (4)  /* number of columns (32-bit words) comprising the state */
+#define Nk (4)  /* number of 32-bit words comprising the key */
+#define Nr (10) /* number of rounds */
+#define TC_AES_BLOCK_SIZE (Nb*Nk)
+#define TC_AES_KEY_SIZE (Nb*Nk)
+
+typedef struct tc_aes_key_sched_struct {
+	unsigned int words[Nb*(Nr+1)];
+} *TCAesKeySched_t;
+
+/**
+ *  @brief Set AES-128 encryption key
+ *  Uses key k to initialize s
+ *  @return  returns TC_CRYPTO_SUCCESS (1)
+ *           returns TC_CRYPTO_FAIL (0) if: s == NULL or k == NULL
+ *  @note       This implementation skips the additional steps required for keys
+ *              larger than 128 bits, and must not be used for AES-192 or
+ *              AES-256 key schedule -- see FIPS 197 for details
+ *  @param      s IN/OUT -- initialized struct tc_aes_key_sched_struct
+ *  @param      k IN -- points to the AES key
+ */
+int tc_aes128_set_encrypt_key(TCAesKeySched_t s, const uint8_t *k);
+
+/**
+ *  @brief AES-128 Encryption procedure
+ *  Encrypts contents of in buffer into out buffer under key;
+ *              schedule s
+ *  @note Assumes s was initialized by aes_set_encrypt_key;
+ *              out and in point to 16 byte buffers
+ *  @return  returns TC_CRYPTO_SUCCESS (1)
+ *           returns TC_CRYPTO_FAIL (0) if: out == NULL or in == NULL or s == NULL
+ *  @param out IN/OUT -- buffer to receive ciphertext block
+ *  @param in IN -- a plaintext block to encrypt
+ *  @param s IN -- initialized AES key schedule
+ */
+int tc_aes_encrypt(uint8_t *out, const uint8_t *in,
+		   const TCAesKeySched_t s);
+
+/**
+ *  @brief Set the AES-128 decryption key
+ *  Uses key k to initialize s
+ *  @return returns TC_CRYPTO_SUCCESS (1)
+ *          returns TC_CRYPTO_FAIL (0) if: s == NULL or k == NULL
+ *  @note       This is the implementation of the straightforward inverse cipher
+ *              using the cipher documented in FIPS-197 figure 12, not the
+ *              equivalent inverse cipher presented in Figure 15
+ *  @warning    This routine skips the additional steps required for keys larger
+ *              than 128, and must not be used for AES-192 or AES-256 key
+ *              schedule -- see FIPS 197 for details
+ *  @param s  IN/OUT -- initialized struct tc_aes_key_sched_struct
+ *  @param k  IN -- points to the AES key
+ */
+int tc_aes128_set_decrypt_key(TCAesKeySched_t s, const uint8_t *k);
+
+/**
+ *  @brief AES-128 Encryption procedure
+ *  Decrypts in buffer into out buffer under key schedule s
+ *  @return returns TC_CRYPTO_SUCCESS (1)
+ *          returns TC_CRYPTO_FAIL (0) if: out is NULL or in is NULL or s is NULL
+ *  @note   Assumes s was initialized by aes_set_encrypt_key
+ *          out and in point to 16 byte buffers
+ *  @param out IN/OUT -- buffer to receive ciphertext block
+ *  @param in IN -- a plaintext block to encrypt
+ *  @param s IN -- initialized AES key schedule
+ */
+int tc_aes_decrypt(uint8_t *out, const uint8_t *in,
+		   const TCAesKeySched_t s);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __TC_AES_H__ */

+ 151 - 0
components/bt/porting/ext/tinycrypt/include/tinycrypt/cbc_mode.h

@@ -0,0 +1,151 @@
+/* cbc_mode.h - TinyCrypt interface to a CBC mode implementation */
+
+/*
+ *  Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *    - 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 Intel Corporation nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 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.
+ */
+
+/**
+ * @file
+ * @brief Interface to a CBC mode implementation.
+ *
+ *  Overview: CBC (for "cipher block chaining") mode is a NIST approved mode of
+ *            operation defined in SP 800-38a. It can be used with any block
+ *            cipher to provide confidentiality of strings whose lengths are
+ *            multiples of the block_size of the underlying block cipher.
+ *            TinyCrypt hard codes AES as the block cipher.
+ *
+ *  Security: CBC mode provides data confidentiality given that the maximum
+ *            number q of blocks encrypted under a single key satisfies
+ *            q < 2^63, which is not a practical constraint (it is considered a
+ *            good practice to replace the encryption when q == 2^56). CBC mode
+ *            provides NO data integrity.
+ *
+ *            CBC mode assumes that the IV value input into the
+ *            tc_cbc_mode_encrypt is randomly generated. The TinyCrypt library
+ *            provides HMAC-PRNG module, which generates suitable IVs. Other
+ *            methods for generating IVs are acceptable, provided that the
+ *            values of the IVs generated appear random to any adversary,
+ *            including someone with complete knowledge of the system design.
+ *
+ *            The randomness property on which CBC mode's security depends is
+ *            the unpredictability of the IV. Since it is unpredictable, this
+ *            means in practice that CBC mode requires that the IV is stored
+ *            somehow with the ciphertext in order to recover the plaintext.
+ *
+ *            TinyCrypt CBC encryption prepends the IV to the ciphertext,
+ *            because this affords a more efficient (few buffers) decryption.
+ *            Hence tc_cbc_mode_encrypt assumes the ciphertext buffer is always
+ *            16 bytes larger than the plaintext buffer.
+ *
+ *  Requires: AES-128
+ *
+ *  Usage:    1) call tc_cbc_mode_encrypt to encrypt data.
+ *
+ *            2) call tc_cbc_mode_decrypt to decrypt data.
+ *
+ */
+
+#ifndef __TC_CBC_MODE_H__
+#define __TC_CBC_MODE_H__
+
+#include <tinycrypt/aes.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ *  @brief CBC encryption procedure
+ *  CBC encrypts inlen bytes of the in buffer into the out buffer
+ *  using the encryption key schedule provided, prepends iv to out
+ *  @return returns TC_CRYPTO_SUCCESS (1)
+ *          returns TC_CRYPTO_FAIL (0) if:
+ *                out == NULL or
+ *                in == NULL or
+ *                ctr == NULL or
+ *                sched == NULL or
+ *                inlen == 0 or
+ *                (inlen % TC_AES_BLOCK_SIZE) != 0 or
+ *                (outlen % TC_AES_BLOCK_SIZE) != 0 or
+ *                outlen != inlen + TC_AES_BLOCK_SIZE
+ *  @note Assumes: - sched has been configured by aes_set_encrypt_key
+ *              - iv contains a 16 byte random string
+ *              - out buffer is large enough to hold the ciphertext + iv
+ *              - out buffer is a contiguous buffer
+ *              - in holds the plaintext and is a contiguous buffer
+ *              - inlen gives the number of bytes in the in buffer
+ *  @param out IN/OUT -- buffer to receive the ciphertext
+ *  @param outlen IN -- length of ciphertext buffer in bytes
+ *  @param in IN -- plaintext to encrypt
+ *  @param inlen IN -- length of plaintext buffer in bytes
+ *  @param iv IN -- the IV for the this encrypt/decrypt
+ *  @param sched IN --  AES key schedule for this encrypt
+ */
+int tc_cbc_mode_encrypt(uint8_t *out, unsigned int outlen, const uint8_t *in,
+			unsigned int inlen, const uint8_t *iv,
+			const TCAesKeySched_t sched);
+
+/**
+ * @brief CBC decryption procedure
+ * CBC decrypts inlen bytes of the in buffer into the out buffer
+ * using the provided encryption key schedule
+ * @return returns TC_CRYPTO_SUCCESS (1)
+ *         returns TC_CRYPTO_FAIL (0) if:
+ *                out == NULL or
+ *                in == NULL or
+ *                sched == NULL or
+ *                inlen == 0 or
+ *                outlen == 0 or
+ *                (inlen % TC_AES_BLOCK_SIZE) != 0 or
+ *                (outlen % TC_AES_BLOCK_SIZE) != 0 or
+ *                outlen != inlen + TC_AES_BLOCK_SIZE
+ * @note Assumes:- in == iv + ciphertext, i.e. the iv and the ciphertext are
+ *                contiguous. This allows for a very efficient decryption
+ *                algorithm that would not otherwise be possible
+ *              - sched was configured by aes_set_decrypt_key
+ *              - out buffer is large enough to hold the decrypted plaintext
+ *              and is a contiguous buffer
+ *              - inlen gives the number of bytes in the in buffer
+ * @param out IN/OUT -- buffer to receive decrypted data
+ * @param outlen IN -- length of plaintext buffer in bytes
+ * @param in IN -- ciphertext to decrypt, including IV
+ * @param inlen IN -- length of ciphertext buffer in bytes
+ * @param iv IN -- the IV for the this encrypt/decrypt
+ * @param sched IN --  AES key schedule for this decrypt
+ *
+ */
+int tc_cbc_mode_decrypt(uint8_t *out, unsigned int outlen, const uint8_t *in,
+			unsigned int inlen, const uint8_t *iv,
+			const TCAesKeySched_t sched);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __TC_CBC_MODE_H__ */

+ 211 - 0
components/bt/porting/ext/tinycrypt/include/tinycrypt/ccm_mode.h

@@ -0,0 +1,211 @@
+/* ccm_mode.h - TinyCrypt interface to a CCM mode implementation */
+
+/*
+ *  Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *    - 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 Intel Corporation nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 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.
+ */
+
+/**
+ * @file
+ * @brief Interface to a CCM mode implementation.
+ *
+ *  Overview: CCM (for "Counter with CBC-MAC") mode is a NIST approved mode of
+ *            operation defined in SP 800-38C.
+ *
+ *            TinyCrypt CCM implementation accepts:
+ *
+ *            1) Both non-empty payload and associated data (it encrypts and
+ *            authenticates the payload and also authenticates the associated
+ *            data);
+ *            2) Non-empty payload and empty associated data (it encrypts and
+ *            authenticates the payload);
+ *            3) Non-empty associated data and empty payload (it degenerates to
+ *            an authentication mode on the associated data).
+ *
+ *            TinyCrypt CCM implementation accepts associated data of any length
+ *            between 0 and (2^16 - 2^8) bytes.
+ *
+ *  Security: The mac length parameter is an important parameter to estimate the
+ *            security against collision attacks (that aim at finding different
+ *            messages that produce the same authentication tag). TinyCrypt CCM
+ *            implementation accepts any even integer between 4 and 16, as
+ *            suggested in SP 800-38C.
+ *
+ *            RFC-3610, which also specifies CCM, presents a few relevant
+ *            security suggestions, such as: it is recommended for most
+ *            applications to use a mac length greater than 8. Besides, the
+ *            usage of the same nonce for two different messages which are
+ *            encrypted with the same key destroys the security of CCM mode.
+ *
+ *  Requires: AES-128
+ *
+ *  Usage:    1) call tc_ccm_config to configure.
+ *
+ *            2) call tc_ccm_mode_encrypt to encrypt data and generate tag.
+ *
+ *            3) call tc_ccm_mode_decrypt to decrypt data and verify tag.
+ */
+
+#ifndef __TC_CCM_MODE_H__
+#define __TC_CCM_MODE_H__
+
+#include <tinycrypt/aes.h>
+#include <stddef.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* max additional authenticated size in bytes: 2^16 - 2^8 = 65280 */
+#define TC_CCM_AAD_MAX_BYTES 0xff00
+
+/* max message size in bytes: 2^(8L) = 2^16 = 65536 */
+#define TC_CCM_PAYLOAD_MAX_BYTES 0x10000
+
+/* struct tc_ccm_mode_struct represents the state of a CCM computation */
+typedef struct tc_ccm_mode_struct {
+	TCAesKeySched_t sched; /* AES key schedule */
+	uint8_t *nonce; /* nonce required by CCM */
+	unsigned int mlen; /* mac length in bytes (parameter t in SP-800 38C) */
+} *TCCcmMode_t;
+
+/**
+ * @brief CCM configuration procedure
+ * @return returns TC_CRYPTO_SUCCESS (1)
+ *          returns TC_CRYPTO_FAIL (0) if:
+ *                c == NULL or
+ *                sched == NULL or
+ *                nonce == NULL or
+ *                mlen != {4, 6, 8, 10, 12, 16}
+ * @param c -- CCM state
+ * @param sched IN -- AES key schedule
+ * @param nonce IN - nonce
+ * @param nlen -- nonce length in bytes
+ * @param mlen -- mac length in bytes (parameter t in SP-800 38C)
+ */
+int tc_ccm_config(TCCcmMode_t c, TCAesKeySched_t sched, uint8_t *nonce,
+		  unsigned int nlen, unsigned int mlen);
+
+/**
+ * @brief CCM tag generation and encryption procedure
+ * @return returns TC_CRYPTO_SUCCESS (1)
+ *         returns TC_CRYPTO_FAIL (0) if:
+ *                out == NULL or
+ *                c == NULL or
+ *                ((plen > 0) and (payload == NULL)) or
+ *                ((alen > 0) and (associated_data == NULL)) or
+ *                (alen >= TC_CCM_AAD_MAX_BYTES) or
+ *                (plen >= TC_CCM_PAYLOAD_MAX_BYTES) or
+ *                (olen < plen + maclength)
+ *
+ * @param out OUT -- encrypted data
+ * @param olen IN -- output length in bytes
+ * @param associated_data IN -- associated data
+ * @param alen IN -- associated data length in bytes
+ * @param payload IN -- payload
+ * @param plen IN -- payload length in bytes
+ * @param c IN -- CCM state
+ *
+ * @note: out buffer should be at least (plen + c->mlen) bytes long.
+ *
+ * @note: The sequence b for encryption is formatted as follows:
+ *        b = [FLAGS | nonce | counter ], where:
+ *          FLAGS is 1 byte long
+ *          nonce is 13 bytes long
+ *          counter is 2 bytes long
+ *        The byte FLAGS is composed by the following 8 bits:
+ *          0-2 bits: used to represent the value of q-1
+ *          3-7 btis: always 0's
+ *
+ * @note: The sequence b for authentication is formatted as follows:
+ *        b = [FLAGS | nonce | length(mac length)], where:
+ *          FLAGS is 1 byte long
+ *          nonce is 13 bytes long
+ *          length(mac length) is 2 bytes long
+ *        The byte FLAGS is composed by the following 8 bits:
+ *          0-2 bits: used to represent the value of q-1
+ *          3-5 bits: mac length (encoded as: (mlen-2)/2)
+ *          6: Adata (0 if alen == 0, and 1 otherwise)
+ *          7: always 0
+ */
+int tc_ccm_generation_encryption(uint8_t *out, unsigned int olen,
+			   	 const uint8_t *associated_data,
+			   	 unsigned int alen, const uint8_t *payload,
+				 unsigned int plen, TCCcmMode_t c);
+
+/**
+ * @brief CCM decryption and tag verification procedure
+ * @return returns TC_CRYPTO_SUCCESS (1)
+ *         returns TC_CRYPTO_FAIL (0) if:
+ *                out == NULL or
+ *                c == NULL or
+ *                ((plen > 0) and (payload == NULL)) or
+ *                ((alen > 0) and (associated_data == NULL)) or
+ *                (alen >= TC_CCM_AAD_MAX_BYTES) or
+ *                (plen >= TC_CCM_PAYLOAD_MAX_BYTES) or
+ *                (olen < plen - c->mlen)
+ *
+ * @param out OUT -- decrypted data
+ * @param associated_data IN -- associated data
+ * @param alen IN -- associated data length in bytes
+ * @param payload IN -- payload
+ * @param plen IN -- payload length in bytes
+ * @param c IN -- CCM state
+ *
+ * @note: out buffer should be at least (plen - c->mlen) bytes long.
+ *
+ * @note: The sequence b for encryption is formatted as follows:
+ *        b = [FLAGS | nonce | counter ], where:
+ *          FLAGS is 1 byte long
+ *          nonce is 13 bytes long
+ *          counter is 2 bytes long
+ *        The byte FLAGS is composed by the following 8 bits:
+ *          0-2 bits: used to represent the value of q-1
+ *          3-7 btis: always 0's
+ *
+ * @note: The sequence b for authentication is formatted as follows:
+ *        b = [FLAGS | nonce | length(mac length)], where:
+ *          FLAGS is 1 byte long
+ *          nonce is 13 bytes long
+ *          length(mac length) is 2 bytes long
+ *        The byte FLAGS is composed by the following 8 bits:
+ *          0-2 bits: used to represent the value of q-1
+ *          3-5 bits: mac length (encoded as: (mlen-2)/2)
+ *          6: Adata (0 if alen == 0, and 1 otherwise)
+ *          7: always 0
+ */
+int tc_ccm_decryption_verification(uint8_t *out, unsigned int olen,
+				   const uint8_t *associated_data,
+				   unsigned int alen, const uint8_t *payload, unsigned int plen,
+				   TCCcmMode_t c);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __TC_CCM_MODE_H__ */

+ 194 - 0
components/bt/porting/ext/tinycrypt/include/tinycrypt/cmac_mode.h

@@ -0,0 +1,194 @@
+/*  cmac_mode.h -- interface to a CMAC implementation */
+
+/*
+ *  Copyright (C) 2017 by Intel Corporation, All Rights Reserved
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *    - 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 Intel Corporation nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 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.
+ */
+
+/**
+ * @file
+ * @brief Interface to a CMAC implementation.
+ *
+ *  Overview: CMAC is defined NIST in SP 800-38B, and is the standard algorithm
+ *            for computing a MAC using a block cipher. It can compute the MAC
+ *            for a byte string of any length. It is distinguished from CBC-MAC
+ *            in the processing of the final message block; CMAC uses a
+ *            different technique to compute the final message block is full
+ *            size or only partial, while CBC-MAC uses the same technique for
+ *            both. This difference permits CMAC to be applied to variable
+ *            length messages, while all messages authenticated by CBC-MAC must
+ *            be the same length.
+ *
+ *  Security: AES128-CMAC mode of operation offers 64 bits of security against
+ *            collision attacks. Note however that an external attacker cannot
+ *            generate the tags him/herself without knowing the MAC key. In this
+ *            sense, to attack the collision property of AES128-CMAC, an
+ *            external attacker would need the cooperation of the legal user to
+ *            produce an exponentially high number of tags (e.g. 2^64) to
+ *            finally be able to look for collisions and benefit from them. As
+ *            an extra precaution, the current implementation allows to at most
+ *            2^48 calls to the tc_cmac_update function before re-calling
+ *            tc_cmac_setup (allowing a new key to be set), as suggested in
+ *            Appendix B of SP 800-38B.
+ *
+ *  Requires: AES-128
+ *
+ *  Usage:   This implementation provides a "scatter-gather" interface, so that
+ *           the CMAC value can be computed incrementally over a message
+ *           scattered in different segments throughout memory. Experience shows
+ *           this style of interface tends to minimize the burden of programming
+ *           correctly. Like all symmetric key operations, it is session
+ *           oriented.
+ *
+ *           To begin a CMAC session, use tc_cmac_setup to initialize a struct
+ *           tc_cmac_struct with encryption key and buffer. Our implementation
+ *           always assume that the AES key to be the same size as the block
+ *           cipher block size. Once setup, this data structure can be used for
+ *           many CMAC computations.
+ *
+ *           Once the state has been setup with a key, computing the CMAC of
+ *           some data requires three steps:
+ *
+ *           (1) first use tc_cmac_init to initialize a new CMAC computation.
+ *           (2) next mix all of the data into the CMAC computation state using
+ *               tc_cmac_update. If all of the data resides in a single data
+ *               segment then only one tc_cmac_update call is needed; if data
+ *               is scattered throughout memory in n data segments, then n calls
+ *               will be needed. CMAC IS ORDER SENSITIVE, to be able to detect
+ *               attacks that swap bytes, so the order in which data is mixed
+ *               into the state is critical!
+ *           (3) Once all of the data for a message has been mixed, use
+ *               tc_cmac_final to compute the CMAC tag value.
+ *
+ *           Steps (1)-(3) can be repeated as many times as you want to CMAC
+ *           multiple messages. A practical limit is 2^48 1K messages before you
+ *           have to change the key.
+ *
+ *           Once you are done computing CMAC with a key, it is a good idea to
+ *           destroy the state so an attacker cannot recover the key; use
+ *           tc_cmac_erase to accomplish this.
+ */
+
+#ifndef __TC_CMAC_MODE_H__
+#define __TC_CMAC_MODE_H__
+
+#include <tinycrypt/aes.h>
+
+#include <stddef.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* padding for last message block */
+#define TC_CMAC_PADDING 0x80
+
+/* struct tc_cmac_struct represents the state of a CMAC computation */
+typedef struct tc_cmac_struct {
+/* initialization vector */
+	uint8_t iv[TC_AES_BLOCK_SIZE];
+/* used if message length is a multiple of block_size bytes */
+	uint8_t K1[TC_AES_BLOCK_SIZE];
+/* used if message length isn't a multiple block_size bytes */
+	uint8_t K2[TC_AES_BLOCK_SIZE];
+/* where to put bytes that didn't fill a block */
+	uint8_t leftover[TC_AES_BLOCK_SIZE];
+/* identifies the encryption key */
+	unsigned int keyid;
+/* next available leftover location */
+	unsigned int leftover_offset;
+/* AES key schedule */
+	TCAesKeySched_t sched;
+/* calls to tc_cmac_update left before re-key */
+	uint64_t countdown;
+} *TCCmacState_t;
+
+/**
+ * @brief Configures the CMAC state to use the given AES key
+ * @return returns TC_CRYPTO_SUCCESS (1) after having configured the CMAC state
+ *         returns TC_CRYPTO_FAIL (0) if:
+ *              s == NULL or
+ *              key == NULL
+ *
+ * @param s IN/OUT -- the state to set up
+ * @param key IN -- the key to use
+ * @param sched IN -- AES key schedule
+ */
+int tc_cmac_setup(TCCmacState_t s, const uint8_t *key,
+		      TCAesKeySched_t sched);
+
+/**
+ * @brief Erases the CMAC state
+ * @return returns TC_CRYPTO_SUCCESS (1) after having configured the CMAC state
+ *         returns TC_CRYPTO_FAIL (0) if:
+ *              s == NULL
+ *
+ * @param s IN/OUT -- the state to erase
+ */
+int tc_cmac_erase(TCCmacState_t s);
+
+/**
+ * @brief Initializes a new CMAC computation
+ * @return returns TC_CRYPTO_SUCCESS (1) after having initialized the CMAC state
+ *         returns TC_CRYPTO_FAIL (0) if:
+ *              s == NULL
+ *
+ * @param s IN/OUT -- the state to initialize
+ */
+int tc_cmac_init(TCCmacState_t s);
+
+/**
+ * @brief Incrementally computes CMAC over the next data segment
+ * @return returns TC_CRYPTO_SUCCESS (1) after successfully updating the CMAC state
+ *         returns TC_CRYPTO_FAIL (0) if:
+ *              s == NULL or
+ *              if data == NULL when dlen > 0
+ *
+ * @param s IN/OUT -- the CMAC state
+ * @param data IN -- the next data segment to MAC
+ * @param dlen IN -- the length of data in bytes
+ */
+int tc_cmac_update(TCCmacState_t s, const uint8_t *data, size_t dlen);
+
+/**
+ * @brief Generates the tag from the CMAC state
+ * @return returns TC_CRYPTO_SUCCESS (1) after successfully generating the tag
+ *         returns TC_CRYPTO_FAIL (0) if:
+ *              tag == NULL or
+ *              s == NULL
+ *
+ * @param tag OUT -- the CMAC tag
+ * @param s IN -- CMAC state
+ */
+int tc_cmac_final(uint8_t *tag, TCCmacState_t s);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __TC_CMAC_MODE_H__ */

+ 61 - 0
components/bt/porting/ext/tinycrypt/include/tinycrypt/constants.h

@@ -0,0 +1,61 @@
+/* constants.h - TinyCrypt interface to constants */
+
+/*
+ *  Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *    - 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 Intel Corporation nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 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.
+ */
+
+/**
+ * @file
+ * @brief -- Interface to constants.
+ *
+ */
+
+#ifndef __TC_CONSTANTS_H__
+#define __TC_CONSTANTS_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdbool.h>
+
+#ifndef NULL
+#define NULL ((void *)0)
+#endif
+
+#define TC_CRYPTO_SUCCESS 1
+#define TC_CRYPTO_FAIL 0
+
+#define TC_ZERO_BYTE 0x00
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __TC_CONSTANTS_H__ */

+ 108 - 0
components/bt/porting/ext/tinycrypt/include/tinycrypt/ctr_mode.h

@@ -0,0 +1,108 @@
+/* ctr_mode.h - TinyCrypt interface to CTR mode */
+
+/*
+ *  Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *    - 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 Intel Corporation nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 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.
+ */
+
+/**
+ * @file
+ * @brief Interface to CTR mode.
+ *
+ *  Overview:  CTR (pronounced "counter") mode is a NIST approved mode of
+ *             operation defined in SP 800-38a. It can be used with any
+ *             block cipher to provide confidentiality of strings of any
+ *             length. TinyCrypt hard codes AES128 as the block cipher.
+ *
+ *  Security:  CTR mode achieves confidentiality only if the counter value is
+ *             never reused with a same encryption key. If the counter is
+ *             repeated, than an adversary might be able to defeat the scheme.
+ *
+ *             A usual method to ensure different counter values refers to
+ *             initialize the counter in a given value (0, for example) and
+ *             increases it every time a new block is enciphered. This naturally
+ *             leaves to a limitation on the number q of blocks that can be
+ *             enciphered using a same key: q < 2^(counter size).
+ *
+ *             TinyCrypt uses a counter of 32 bits. This means that after 2^32
+ *             block encryptions, the counter will be reused (thus losing CBC
+ *             security). 2^32 block encryptions should be enough for most of
+ *             applications targeting constrained devices. Applications intended
+ *             to encrypt a larger number of blocks must replace the key after
+ *             2^32 block encryptions.
+ *
+ *             CTR mode provides NO data integrity.
+ *
+ *  Requires: AES-128
+ *
+ *  Usage:     1) call tc_ctr_mode to process the data to encrypt/decrypt.
+ *
+ */
+
+#ifndef __TC_CTR_MODE_H__
+#define __TC_CTR_MODE_H__
+
+#include <tinycrypt/aes.h>
+#include <tinycrypt/constants.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ *  @brief CTR mode encryption/decryption procedure.
+ *  CTR mode encrypts (or decrypts) inlen bytes from in buffer into out buffer
+ *  @return returns TC_CRYPTO_SUCCESS (1)
+ *          returns TC_CRYPTO_FAIL (0) if:
+ *                out == NULL or
+ *                in == NULL or
+ *                ctr == NULL or
+ *                sched == NULL or
+ *                inlen == 0 or
+ *                outlen == 0 or
+ *                inlen != outlen
+ *  @note Assumes:- The current value in ctr has NOT been used with sched
+ *              - out points to inlen bytes
+ *              - in points to inlen bytes
+ *              - ctr is an integer counter in littleEndian format
+ *              - sched was initialized by aes_set_encrypt_key
+ * @param out OUT -- produced ciphertext (plaintext)
+ * @param outlen IN -- length of ciphertext buffer in bytes
+ * @param in IN -- data to encrypt (or decrypt)
+ * @param inlen IN -- length of input data in bytes
+ * @param ctr IN/OUT -- the current counter value
+ * @param sched IN -- an initialized AES key schedule
+ */
+int tc_ctr_mode(uint8_t *out, unsigned int outlen, const uint8_t *in,
+		unsigned int inlen, uint8_t *ctr, const TCAesKeySched_t sched);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __TC_CTR_MODE_H__ */

+ 166 - 0
components/bt/porting/ext/tinycrypt/include/tinycrypt/ctr_prng.h

@@ -0,0 +1,166 @@
+/* ctr_prng.h - TinyCrypt interface to a CTR-PRNG implementation */
+
+/*
+ * Copyright (c) 2016, Chris Morrison
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @file
+ * @brief Interface to a CTR-PRNG implementation.
+ *
+ *  Overview:   A pseudo-random number generator (PRNG) generates a sequence
+ *              of numbers that have a distribution close to the one expected
+ *              for a sequence of truly random numbers. The NIST Special
+ *              Publication 800-90A specifies several mechanisms to generate
+ *              sequences of pseudo random numbers, including the CTR-PRNG one
+ *              which is based on AES. TinyCrypt implements CTR-PRNG with
+ *              AES-128.
+ *
+ *  Security:   A cryptographically secure PRNG depends on the existence of an
+ *              entropy source to provide a truly random seed as well as the
+ *              security of the primitives used as the building blocks (AES-128
+ *              in this instance).
+ *
+ *  Requires:   - AES-128
+ *
+ *  Usage:      1) call tc_ctr_prng_init to seed the prng context
+ *
+ *              2) call tc_ctr_prng_reseed to mix in additional entropy into
+ *              the prng context
+ *
+ *              3) call tc_ctr_prng_generate to output the pseudo-random data
+ *
+ *              4) call tc_ctr_prng_uninstantiate to zero out the prng context
+ */
+
+#ifndef __TC_CTR_PRNG_H__
+#define __TC_CTR_PRNG_H__
+
+#include <tinycrypt/aes.h>
+
+#define TC_CTR_PRNG_RESEED_REQ -1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct {
+	/* updated each time another BLOCKLEN_BYTES bytes are produced */
+	uint8_t V[TC_AES_BLOCK_SIZE];
+
+	/* updated whenever the PRNG is reseeded */
+	struct tc_aes_key_sched_struct key;
+
+	/* number of requests since initialization/reseeding */
+	uint64_t reseedCount;
+} TCCtrPrng_t;
+
+
+/**
+ *  @brief CTR-PRNG initialization procedure
+ *  Initializes prng context with entropy and personalization string (if any)
+ *  @return returns TC_CRYPTO_SUCCESS (1)
+ *          returns TC_CRYPTO_FAIL (0) if:
+ *                ctx == NULL,
+ *                entropy == NULL,
+ *                entropyLen < (TC_AES_KEY_SIZE + TC_AES_BLOCK_SIZE)
+ *  @note       Only the first (TC_AES_KEY_SIZE + TC_AES_BLOCK_SIZE) bytes of
+ *              both the entropy and personalization inputs are used -
+ *              supplying additional bytes has no effect.
+ *  @param ctx IN/OUT -- the PRNG context to initialize
+ *  @param entropy IN -- entropy used to seed the PRNG
+ *  @param entropyLen IN -- entropy length in bytes
+ *  @param personalization IN -- personalization string used to seed the PRNG
+ *  (may be null)
+ *  @param plen IN -- personalization length in bytes
+ *
+ */
+int tc_ctr_prng_init(TCCtrPrng_t * const ctx,
+		     uint8_t const * const entropy,
+		     unsigned int entropyLen,
+		     uint8_t const * const personalization,
+		     unsigned int pLen);
+
+/**
+ *  @brief CTR-PRNG reseed procedure
+ *  Mixes entropy and additional_input into the prng context
+ *  @return returns  TC_CRYPTO_SUCCESS (1)
+ *  returns TC_CRYPTO_FAIL (0) if:
+ *          ctx == NULL,
+ *          entropy == NULL,
+ *          entropylen < (TC_AES_KEY_SIZE + TC_AES_BLOCK_SIZE)
+ *  @note It is better to reseed an existing prng context rather than
+ *        re-initialise, so that any existing entropy in the context is
+ *        presereved.  This offers some protection against undetected failures
+ *        of the entropy source.
+ *  @note Assumes tc_ctr_prng_init has been called for ctx
+ *  @param ctx IN/OUT -- the PRNG state
+ *  @param entropy IN -- entropy to mix into the prng
+ *  @param entropylen IN -- length of entropy in bytes
+ *  @param additional_input IN -- additional input to the prng (may be null)
+ *  @param additionallen IN -- additional input length in bytes
+ */
+int tc_ctr_prng_reseed(TCCtrPrng_t * const ctx,
+		       uint8_t const * const entropy,
+		       unsigned int entropyLen,
+		       uint8_t const * const additional_input,
+		       unsigned int additionallen);
+
+/**
+ *  @brief CTR-PRNG generate procedure
+ *  Generates outlen pseudo-random bytes into out buffer, updates prng
+ *  @return returns TC_CRYPTO_SUCCESS (1)
+ *          returns TC_CTR_PRNG_RESEED_REQ (-1) if a reseed is needed
+ *             returns TC_CRYPTO_FAIL (0) if:
+ *                ctx == NULL,
+ *                out == NULL,
+ *                outlen >= 2^16
+ *  @note Assumes tc_ctr_prng_init has been called for ctx
+ *  @param ctx IN/OUT -- the PRNG context
+ *  @param additional_input IN -- additional input to the prng (may be null)
+ *  @param additionallen IN -- additional input length in bytes
+ *  @param out IN/OUT -- buffer to receive output
+ *  @param outlen IN -- size of out buffer in bytes
+ */
+int tc_ctr_prng_generate(TCCtrPrng_t * const ctx,
+			 uint8_t const * const additional_input,
+			 unsigned int additionallen,
+			 uint8_t * const out,
+			 unsigned int outlen);
+
+/**
+ *  @brief CTR-PRNG uninstantiate procedure
+ *  Zeroes the internal state of the supplied prng context
+ *  @return none
+ *  @param ctx IN/OUT -- the PRNG context
+ */
+void tc_ctr_prng_uninstantiate(TCCtrPrng_t * const ctx);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __TC_CTR_PRNG_H__ */

+ 545 - 0
components/bt/porting/ext/tinycrypt/include/tinycrypt/ecc.h

@@ -0,0 +1,545 @@
+/* ecc.h - TinyCrypt interface to common ECC functions */
+
+/* Copyright (c) 2014, Kenneth MacKay
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ *  Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *    - 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 Intel Corporation nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 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.
+ */
+
+/**
+ * @file
+ * @brief -- Interface to common ECC functions.
+ *
+ *  Overview: This software is an implementation of common functions
+ *            necessary to elliptic curve cryptography. This implementation uses
+ *            curve NIST p-256.
+ *
+ *  Security: The curve NIST p-256 provides approximately 128 bits of security.
+ *
+ */
+
+#ifndef __TC_UECC_H__
+#define __TC_UECC_H__
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Word size (4 bytes considering 32-bits architectures) */
+#define uECC_WORD_SIZE 4
+
+/* setting max number of calls to prng: */
+#ifndef uECC_RNG_MAX_TRIES
+#define uECC_RNG_MAX_TRIES 64
+#endif
+
+/* defining data types to store word and bit counts: */
+typedef int8_t wordcount_t;
+typedef int16_t bitcount_t;
+/* defining data type for comparison result: */
+typedef int8_t cmpresult_t;
+/* defining data type to store ECC coordinate/point in 32bits words: */
+typedef unsigned int uECC_word_t;
+/* defining data type to store an ECC coordinate/point in 64bits words: */
+typedef uint64_t uECC_dword_t;
+
+/* defining masks useful for ecc computations: */
+#define HIGH_BIT_SET 0x80000000
+#define uECC_WORD_BITS 32
+#define uECC_WORD_BITS_SHIFT 5
+#define uECC_WORD_BITS_MASK 0x01F
+
+/* Number of words of 32 bits to represent an element of the the curve p-256: */
+#define NUM_ECC_WORDS 8
+/* Number of bytes to represent an element of the the curve p-256: */
+#define NUM_ECC_BYTES (uECC_WORD_SIZE*NUM_ECC_WORDS)
+
+/* structure that represents an elliptic curve (e.g. p256):*/
+struct uECC_Curve_t;
+typedef const struct uECC_Curve_t * uECC_Curve;
+struct uECC_Curve_t {
+  wordcount_t num_words;
+  wordcount_t num_bytes;
+  bitcount_t num_n_bits;
+  uECC_word_t p[NUM_ECC_WORDS];
+  uECC_word_t n[NUM_ECC_WORDS];
+  uECC_word_t G[NUM_ECC_WORDS * 2];
+  uECC_word_t b[NUM_ECC_WORDS];
+  void (*double_jacobian)(uECC_word_t * X1, uECC_word_t * Y1, uECC_word_t * Z1,
+	uECC_Curve curve);
+  void (*x_side)(uECC_word_t *result, const uECC_word_t *x, uECC_Curve curve);
+  void (*mmod_fast)(uECC_word_t *result, uECC_word_t *product);
+};
+
+/*
+ * @brief computes doubling of point ion jacobian coordinates, in place.
+ * @param X1 IN/OUT -- x coordinate
+ * @param Y1 IN/OUT -- y coordinate
+ * @param Z1 IN/OUT -- z coordinate
+ * @param curve IN -- elliptic curve
+ */
+void double_jacobian_default(uECC_word_t * X1, uECC_word_t * Y1,
+			     uECC_word_t * Z1, uECC_Curve curve);
+
+/*
+ * @brief Computes x^3 + ax + b. result must not overlap x.
+ * @param result OUT -- x^3 + ax + b
+ * @param x IN -- value of x
+ * @param curve IN -- elliptic curve
+ */
+void x_side_default(uECC_word_t *result, const uECC_word_t *x,
+		    uECC_Curve curve);
+
+/*
+ * @brief Computes result = product % curve_p
+ * from http://www.nsa.gov/ia/_files/nist-routines.pdf
+ * @param result OUT -- product % curve_p
+ * @param product IN -- value to be reduced mod curve_p
+ */
+void vli_mmod_fast_secp256r1(unsigned int *result, unsigned int *product);
+
+/* Bytes to words ordering: */
+#define BYTES_TO_WORDS_8(a, b, c, d, e, f, g, h) 0x##d##c##b##a, 0x##h##g##f##e
+#define BYTES_TO_WORDS_4(a, b, c, d) 0x##d##c##b##a
+#define BITS_TO_WORDS(num_bits) \
+	((num_bits + ((uECC_WORD_SIZE * 8) - 1)) / (uECC_WORD_SIZE * 8))
+#define BITS_TO_BYTES(num_bits) ((num_bits + 7) / 8)
+
+/* definition of curve NIST p-256: */
+static const struct uECC_Curve_t curve_secp256r1 = {
+	NUM_ECC_WORDS,
+	NUM_ECC_BYTES,
+	256, /* num_n_bits */ {
+		BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF),
+		BYTES_TO_WORDS_8(FF, FF, FF, FF, 00, 00, 00, 00),
+        	BYTES_TO_WORDS_8(00, 00, 00, 00, 00, 00, 00, 00),
+        	BYTES_TO_WORDS_8(01, 00, 00, 00, FF, FF, FF, FF)
+	}, {
+		BYTES_TO_WORDS_8(51, 25, 63, FC, C2, CA, B9, F3),
+            	BYTES_TO_WORDS_8(84, 9E, 17, A7, AD, FA, E6, BC),
+            	BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF),
+            	BYTES_TO_WORDS_8(00, 00, 00, 00, FF, FF, FF, FF)
+	}, {
+		BYTES_TO_WORDS_8(96, C2, 98, D8, 45, 39, A1, F4),
+                BYTES_TO_WORDS_8(A0, 33, EB, 2D, 81, 7D, 03, 77),
+                BYTES_TO_WORDS_8(F2, 40, A4, 63, E5, E6, BC, F8),
+                BYTES_TO_WORDS_8(47, 42, 2C, E1, F2, D1, 17, 6B),
+
+                BYTES_TO_WORDS_8(F5, 51, BF, 37, 68, 40, B6, CB),
+                BYTES_TO_WORDS_8(CE, 5E, 31, 6B, 57, 33, CE, 2B),
+                BYTES_TO_WORDS_8(16, 9E, 0F, 7C, 4A, EB, E7, 8E),
+                BYTES_TO_WORDS_8(9B, 7F, 1A, FE, E2, 42, E3, 4F)
+	}, {
+		BYTES_TO_WORDS_8(4B, 60, D2, 27, 3E, 3C, CE, 3B),
+                BYTES_TO_WORDS_8(F6, B0, 53, CC, B0, 06, 1D, 65),
+                BYTES_TO_WORDS_8(BC, 86, 98, 76, 55, BD, EB, B3),
+                BYTES_TO_WORDS_8(E7, 93, 3A, AA, D8, 35, C6, 5A)
+	},
+        &double_jacobian_default,
+        &x_side_default,
+        &vli_mmod_fast_secp256r1
+};
+
+uECC_Curve uECC_secp256r1(void);
+
+/*
+ * @brief Generates a random integer in the range 0 < random < top.
+ * Both random and top have num_words words.
+ * @param random OUT -- random integer in the range 0 < random < top
+ * @param top IN -- upper limit
+ * @param num_words IN -- number of words
+ * @return a random integer in the range 0 < random < top
+ */
+int uECC_generate_random_int(uECC_word_t *random, const uECC_word_t *top,
+			     wordcount_t num_words);
+
+
+/* uECC_RNG_Function type
+ * The RNG function should fill 'size' random bytes into 'dest'. It should
+ * return 1 if 'dest' was filled with random data, or 0 if the random data could
+ * not be generated. The filled-in values should be either truly random, or from
+ * a cryptographically-secure PRNG.
+ *
+ * A correctly functioning RNG function must be set (using uECC_set_rng())
+ * before calling uECC_make_key() or uECC_sign().
+ *
+ * Setting a correctly functioning RNG function improves the resistance to
+ * side-channel attacks for uECC_shared_secret().
+ *
+ * A correct RNG function is set by default. If you are building on another
+ * POSIX-compliant system that supports /dev/random or /dev/urandom, you can
+ * define uECC_POSIX to use the predefined RNG.
+ */
+typedef int(*uECC_RNG_Function)(uint8_t *dest, unsigned int size);
+
+/*
+ * @brief Set the function that will be used to generate random bytes. The RNG
+ * function should return 1 if the random data was generated, or 0 if the random
+ * data could not be generated.
+ *
+ * @note On platforms where there is no predefined RNG function, this must be
+ * called before uECC_make_key() or uECC_sign() are used.
+ *
+ * @param rng_function IN -- function that will be used to generate random bytes
+ */
+void uECC_set_rng(uECC_RNG_Function rng_function);
+
+/*
+ * @brief provides current uECC_RNG_Function.
+ * @return Returns the function that will be used to generate random bytes.
+ */
+uECC_RNG_Function uECC_get_rng(void);
+
+/*
+ * @brief computes the size of a private key for the curve in bytes.
+ * @param curve IN -- elliptic curve
+ * @return size of a private key for the curve in bytes.
+ */
+int uECC_curve_private_key_size(uECC_Curve curve);
+
+/*
+ * @brief computes the size of a public key for the curve in bytes.
+ * @param curve IN -- elliptic curve
+ * @return the size of a public key for the curve in bytes.
+ */
+int uECC_curve_public_key_size(uECC_Curve curve);
+
+/*
+ * @brief Compute the corresponding public key for a private key.
+ * @param private_key IN -- The private key to compute the public key for
+ * @param public_key OUT -- Will be filled in with the corresponding public key
+ * @param curve
+ * @return Returns 1 if key was computed successfully, 0 if an error occurred.
+ */
+int uECC_compute_public_key(const uint8_t *private_key,
+			    uint8_t *public_key, uECC_Curve curve);
+
+/*
+ * @brief Compute public-key.
+ * @return corresponding public-key.
+ * @param result OUT -- public-key
+ * @param private_key IN -- private-key
+ * @param curve IN -- elliptic curve
+ */
+uECC_word_t EccPoint_compute_public_key(uECC_word_t *result,
+					uECC_word_t *private_key, uECC_Curve curve);
+
+/*
+ * @brief Regularize the bitcount for the private key so that attackers cannot
+ * use a side channel attack to learn the number of leading zeros.
+ * @return Regularized k
+ * @param k IN -- private-key
+ * @param k0 IN/OUT -- regularized k
+ * @param k1 IN/OUT -- regularized k
+ * @param curve IN -- elliptic curve
+ */
+uECC_word_t regularize_k(const uECC_word_t * const k, uECC_word_t *k0,
+			 uECC_word_t *k1, uECC_Curve curve);
+
+/*
+ * @brief Point multiplication algorithm using Montgomery's ladder with co-Z
+ * coordinates. See http://eprint.iacr.org/2011/338.pdf.
+ * @note Result may overlap point.
+ * @param result OUT -- returns scalar*point
+ * @param point IN -- elliptic curve point
+ * @param scalar IN -- scalar
+ * @param initial_Z IN -- initial value for z
+ * @param num_bits IN -- number of bits in scalar
+ * @param curve IN -- elliptic curve
+ */
+void EccPoint_mult(uECC_word_t * result, const uECC_word_t * point,
+		   const uECC_word_t * scalar, const uECC_word_t * initial_Z,
+		   bitcount_t num_bits, uECC_Curve curve);
+
+/*
+ * @brief Constant-time comparison to zero - secure way to compare long integers
+ * @param vli IN -- very long integer
+ * @param num_words IN -- number of words in the vli
+ * @return 1 if vli == 0, 0 otherwise.
+ */
+uECC_word_t uECC_vli_isZero(const uECC_word_t *vli, wordcount_t num_words);
+
+/*
+ * @brief Check if 'point' is the point at infinity
+ * @param point IN -- elliptic curve point
+ * @param curve IN -- elliptic curve
+ * @return if 'point' is the point at infinity, 0 otherwise.
+ */
+uECC_word_t EccPoint_isZero(const uECC_word_t *point, uECC_Curve curve);
+
+/*
+ * @brief computes the sign of left - right, in constant time.
+ * @param left IN -- left term to be compared
+ * @param right IN -- right term to be compared
+ * @param num_words IN -- number of words
+ * @return the sign of left - right
+ */
+cmpresult_t uECC_vli_cmp(const uECC_word_t *left, const uECC_word_t *right,
+			 wordcount_t num_words);
+
+/*
+ * @brief computes sign of left - right, not in constant time.
+ * @note should not be used if inputs are part of a secret
+ * @param left IN -- left term to be compared
+ * @param right IN -- right term to be compared
+ * @param num_words IN -- number of words
+ * @return the sign of left - right
+ */
+cmpresult_t uECC_vli_cmp_unsafe(const uECC_word_t *left, const uECC_word_t *right,
+				wordcount_t num_words);
+
+/*
+ * @brief Computes result = (left - right) % mod.
+ * @note Assumes that (left < mod) and (right < mod), and that result does not
+ * overlap mod.
+ * @param result OUT -- (left - right) % mod
+ * @param left IN -- leftright term in modular subtraction
+ * @param right IN -- right term in modular subtraction
+ * @param mod IN -- mod
+ * @param num_words IN -- number of words
+ */
+void uECC_vli_modSub(uECC_word_t *result, const uECC_word_t *left,
+		     const uECC_word_t *right, const uECC_word_t *mod,
+		     wordcount_t num_words);
+
+/*
+ * @brief Computes P' = (x1', y1', Z3), P + Q = (x3, y3, Z3) or
+ * P => P', Q => P + Q
+ * @note assumes Input P = (x1, y1, Z), Q = (x2, y2, Z)
+ * @param X1 IN -- x coordinate of P
+ * @param Y1 IN -- y coordinate of P
+ * @param X2 IN -- x coordinate of Q
+ * @param Y2 IN -- y coordinate of Q
+ * @param curve IN -- elliptic curve
+ */
+void XYcZ_add(uECC_word_t * X1, uECC_word_t * Y1, uECC_word_t * X2,
+	      uECC_word_t * Y2, uECC_Curve curve);
+
+/*
+ * @brief Computes (x1 * z^2, y1 * z^3)
+ * @param X1 IN -- previous x1 coordinate
+ * @param Y1 IN -- previous y1 coordinate
+ * @param Z IN -- z value
+ * @param curve IN -- elliptic curve
+ */
+void apply_z(uECC_word_t * X1, uECC_word_t * Y1, const uECC_word_t * const Z,
+	     uECC_Curve curve);
+
+/*
+ * @brief Check if bit is set.
+ * @return Returns nonzero if bit 'bit' of vli is set.
+ * @warning It is assumed that the value provided in 'bit' is within the
+ * boundaries of the word-array 'vli'.
+ * @note The bit ordering layout assumed for vli is: {31, 30, ..., 0},
+ * {63, 62, ..., 32}, {95, 94, ..., 64}, {127, 126,..., 96} for a vli consisting
+ * of 4 uECC_word_t elements.
+ */
+uECC_word_t uECC_vli_testBit(const uECC_word_t *vli, bitcount_t bit);
+
+/*
+ * @brief Computes result = product % mod, where product is 2N words long.
+ * @param result OUT -- product % mod
+ * @param mod IN -- module
+ * @param num_words IN -- number of words
+ * @warning Currently only designed to work for curve_p or curve_n.
+ */
+void uECC_vli_mmod(uECC_word_t *result, uECC_word_t *product,
+		   const uECC_word_t *mod, wordcount_t num_words);
+
+/*
+ * @brief Computes modular product (using curve->mmod_fast)
+ * @param result OUT -- (left * right) mod % curve_p
+ * @param left IN -- left term in product
+ * @param right IN -- right term in product
+ * @param curve IN -- elliptic curve
+ */
+void uECC_vli_modMult_fast(uECC_word_t *result, const uECC_word_t *left,
+			   const uECC_word_t *right, uECC_Curve curve);
+
+/*
+ * @brief Computes result = left - right.
+ * @note Can modify in place.
+ * @param result OUT -- left - right
+ * @param left IN -- left term in subtraction
+ * @param right IN -- right term in subtraction
+ * @param num_words IN -- number of words
+ * @return borrow
+ */
+uECC_word_t uECC_vli_sub(uECC_word_t *result, const uECC_word_t *left,
+			 const uECC_word_t *right, wordcount_t num_words);
+
+/*
+ * @brief Constant-time comparison function(secure way to compare long ints)
+ * @param left IN -- left term in comparison
+ * @param right IN -- right term in comparison
+ * @param num_words IN -- number of words
+ * @return Returns 0 if left == right, 1 otherwise.
+ */
+uECC_word_t uECC_vli_equal(const uECC_word_t *left, const uECC_word_t *right,
+			   wordcount_t num_words);
+
+/*
+ * @brief Computes (left * right) % mod
+ * @param result OUT -- (left * right) % mod
+ * @param left IN -- left term in product
+ * @param right IN -- right term in product
+ * @param mod IN -- mod
+ * @param num_words IN -- number of words
+ */
+void uECC_vli_modMult(uECC_word_t *result, const uECC_word_t *left,
+		      const uECC_word_t *right, const uECC_word_t *mod,
+	              wordcount_t num_words);
+
+/*
+ * @brief Computes (1 / input) % mod
+ * @note All VLIs are the same size.
+ * @note See "Euclid's GCD to Montgomery Multiplication to the Great Divide"
+ * @param result OUT -- (1 / input) % mod
+ * @param input IN -- value to be modular inverted
+ * @param mod IN -- mod
+ * @param num_words -- number of words
+ */
+void uECC_vli_modInv(uECC_word_t *result, const uECC_word_t *input,
+		     const uECC_word_t *mod, wordcount_t num_words);
+
+/*
+ * @brief Sets dest = src.
+ * @param dest OUT -- destination buffer
+ * @param src IN --  origin buffer
+ * @param num_words IN -- number of words
+ */
+void uECC_vli_set(uECC_word_t *dest, const uECC_word_t *src,
+		  wordcount_t num_words);
+
+/*
+ * @brief Computes (left + right) % mod.
+ * @note Assumes that (left < mod) and right < mod), and that result does not
+ * overlap mod.
+ * @param result OUT -- (left + right) % mod.
+ * @param left IN -- left term in addition
+ * @param right IN -- right term in addition
+ * @param mod IN -- mod
+ * @param num_words IN -- number of words
+ */
+void uECC_vli_modAdd(uECC_word_t *result,  const uECC_word_t *left,
+    		     const uECC_word_t *right, const uECC_word_t *mod,
+   		     wordcount_t num_words);
+
+/*
+ * @brief Counts the number of bits required to represent vli.
+ * @param vli IN -- very long integer
+ * @param max_words IN -- number of words
+ * @return number of bits in given vli
+ */
+bitcount_t uECC_vli_numBits(const uECC_word_t *vli,
+			    const wordcount_t max_words);
+
+/*
+ * @brief Erases (set to 0) vli
+ * @param vli IN -- very long integer
+ * @param num_words IN -- number of words
+ */
+void uECC_vli_clear(uECC_word_t *vli, wordcount_t num_words);
+
+/*
+ * @brief check if it is a valid point in the curve
+ * @param point IN -- point to be checked
+ * @param curve IN -- elliptic curve
+ * @return 0 if point is valid
+ * @exception returns -1 if it is a point at infinity
+ * @exception returns -2 if x or y is smaller than p,
+ * @exception returns -3 if y^2 != x^3 + ax + b.
+ */
+int uECC_valid_point(const uECC_word_t *point, uECC_Curve curve);
+
+/*
+ * @brief Check if a public key is valid.
+ * @param public_key IN -- The public key to be checked.
+ * @return returns 0 if the public key is valid
+ * @exception returns -1 if it is a point at infinity
+ * @exception returns -2 if x or y is smaller than p,
+ * @exception returns -3 if y^2 != x^3 + ax + b.
+ * @exception returns -4 if public key is the group generator.
+ *
+ * @note Note that you are not required to check for a valid public key before
+ * using any other uECC functions. However, you may wish to avoid spending CPU
+ * time computing a shared secret or verifying a signature using an invalid
+ * public key.
+ */
+int uECC_valid_public_key(const uint8_t *public_key, uECC_Curve curve);
+
+ /*
+  * @brief Converts an integer in uECC native format to big-endian bytes.
+  * @param bytes OUT -- bytes representation
+  * @param num_bytes IN -- number of bytes
+  * @param native IN -- uECC native representation
+  */
+void uECC_vli_nativeToBytes(uint8_t *bytes, int num_bytes,
+    			    const unsigned int *native);
+
+/*
+ * @brief Converts big-endian bytes to an integer in uECC native format.
+ * @param native OUT -- uECC native representation
+ * @param bytes IN -- bytes representation
+ * @param num_bytes IN -- number of bytes
+ */
+void uECC_vli_bytesToNative(unsigned int *native, const uint8_t *bytes,
+			    int num_bytes);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __TC_UECC_H__ */

+ 131 - 0
components/bt/porting/ext/tinycrypt/include/tinycrypt/ecc_dh.h

@@ -0,0 +1,131 @@
+/* ecc_dh.h - TinyCrypt interface to EC-DH implementation */
+
+/*
+ * Copyright (c) 2014, Kenneth MacKay
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *    - 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 Intel Corporation nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 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.
+ */
+
+/**
+ * @file
+ * @brief -- Interface to EC-DH implementation.
+ *
+ *  Overview: This software is an implementation of EC-DH. This implementation
+ *            uses curve NIST p-256.
+ *
+ *  Security: The curve NIST p-256 provides approximately 128 bits of security.
+ */
+
+#ifndef __TC_ECC_DH_H__
+#define __TC_ECC_DH_H__
+
+#include <tinycrypt/ecc.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief Create a public/private key pair.
+ * @return returns TC_CRYPTO_SUCCESS (1) if the key pair was generated successfully
+ *         returns TC_CRYPTO_FAIL (0) if error while generating key pair
+ *
+ * @param p_public_key OUT -- Will be filled in with the public key. Must be at
+ * least 2 * the curve size (in bytes) long. For curve secp256r1, p_public_key
+ * must be 64 bytes long.
+ * @param p_private_key OUT -- Will be filled in with the private key. Must be as
+ * long as the curve order (for secp256r1, p_private_key must be 32 bytes long).
+ *
+ * @note side-channel countermeasure: algorithm strengthened against timing
+ * attack.
+ * @warning A cryptographically-secure PRNG function must be set (using
+ * uECC_set_rng()) before calling uECC_make_key().
+ */
+int uECC_make_key(uint8_t *p_public_key, uint8_t *p_private_key, uECC_Curve curve);
+
+#ifdef ENABLE_TESTS
+
+/**
+ * @brief Create a public/private key pair given a specific d.
+ *
+ * @note THIS FUNCTION SHOULD BE CALLED ONLY FOR TEST PURPOSES. Refer to
+ * uECC_make_key() function for real applications.
+ */
+int uECC_make_key_with_d(uint8_t *p_public_key, uint8_t *p_private_key,
+    			 unsigned int *d, uECC_Curve curve);
+#endif
+
+/**
+ * @brief Compute a shared secret given your secret key and someone else's
+ * public key.
+ * @return returns TC_CRYPTO_SUCCESS (1) if the shared secret was computed successfully
+ *         returns TC_CRYPTO_FAIL (0) otherwise
+ *
+ * @param p_secret OUT -- Will be filled in with the shared secret value. Must be
+ * the same size as the curve size (for curve secp256r1, secret must be 32 bytes
+ * long.
+ * @param p_public_key IN -- The public key of the remote party.
+ * @param p_private_key IN -- Your private key.
+ *
+ * @warning It is recommended to use the output of uECC_shared_secret() as the
+ * input of a recommended Key Derivation Function (see NIST SP 800-108) in
+ * order to produce a cryptographically secure symmetric key.
+ */
+int uECC_shared_secret(const uint8_t *p_public_key, const uint8_t *p_private_key,
+		       uint8_t *p_secret, uECC_Curve curve);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __TC_ECC_DH_H__ */

+ 139 - 0
components/bt/porting/ext/tinycrypt/include/tinycrypt/ecc_dsa.h

@@ -0,0 +1,139 @@
+/* ecc_dh.h - TinyCrypt interface to EC-DSA implementation */
+
+/*
+ * Copyright (c) 2014, Kenneth MacKay
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *    - 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 Intel Corporation nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 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.
+ */
+
+/**
+ * @file
+ * @brief -- Interface to EC-DSA implementation.
+ *
+ *  Overview: This software is an implementation of EC-DSA. This implementation
+ *            uses curve NIST p-256.
+ *
+ *  Security: The curve NIST p-256 provides approximately 128 bits of security.
+ *
+ *  Usage:  - To sign: Compute a hash of the data you wish to sign (SHA-2 is
+ *          recommended) and pass it in to ecdsa_sign function along with your
+ *          private key and a random number. You must use a new non-predictable
+ *          random number to generate each new signature.
+ *          - To verify a signature: Compute the hash of the signed data using
+ *          the same hash as the signer and pass it to this function along with
+ *          the signer's public key and the signature values (r and s).
+ */
+
+#ifndef __TC_ECC_DSA_H__
+#define __TC_ECC_DSA_H__
+
+#include <tinycrypt/ecc.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief Generate an ECDSA signature for a given hash value.
+ * @return returns TC_CRYPTO_SUCCESS (1) if the signature generated successfully
+ *         returns TC_CRYPTO_FAIL (0) if an error occurred.
+ *
+ * @param p_private_key IN -- Your private key.
+ * @param p_message_hash IN -- The hash of the message to sign.
+ * @param p_hash_size IN -- The size of p_message_hash in bytes.
+ * @param p_signature OUT -- Will be filled in with the signature value. Must be
+ * at least 2 * curve size long (for secp256r1, signature must be 64 bytes long).
+ *
+ * @warning A cryptographically-secure PRNG function must be set (using
+ * uECC_set_rng()) before calling uECC_sign().
+ * @note Usage: Compute a hash of the data you wish to sign (SHA-2 is
+ * recommended) and pass it in to this function along with your private key.
+ * @note side-channel countermeasure: algorithm strengthened against timing
+ * attack.
+ */
+int uECC_sign(const uint8_t *p_private_key, const uint8_t *p_message_hash,
+	      unsigned p_hash_size, uint8_t *p_signature, uECC_Curve curve);
+
+#ifdef ENABLE_TESTS
+/*
+ * THIS FUNCTION SHOULD BE CALLED FOR TEST PURPOSES ONLY.
+ * Refer to uECC_sign() function for real applications.
+ */
+int uECC_sign_with_k(const uint8_t *private_key, const uint8_t *message_hash,
+		     unsigned int hash_size, uECC_word_t *k, uint8_t *signature,
+		     uECC_Curve curve);
+#endif
+
+/**
+ * @brief Verify an ECDSA signature.
+ * @return returns TC_SUCCESS (1) if the signature is valid
+ * 	   returns TC_FAIL (0) if the signature is invalid.
+ *
+ * @param p_public_key IN -- The signer's public key.
+ * @param p_message_hash IN -- The hash of the signed data.
+ * @param p_hash_size IN -- The size of p_message_hash in bytes.
+ * @param p_signature IN -- The signature values.
+ *
+ * @note Usage: Compute the hash of the signed data using the same hash as the
+ * signer and pass it to this function along with the signer's public key and
+ * the signature values (hash_size and signature).
+ */
+int uECC_verify(const uint8_t *p_public_key, const uint8_t *p_message_hash,
+		unsigned int p_hash_size, const uint8_t *p_signature, uECC_Curve curve);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __TC_ECC_DSA_H__ */

+ 81 - 0
components/bt/porting/ext/tinycrypt/include/tinycrypt/ecc_platform_specific.h

@@ -0,0 +1,81 @@
+/*  uECC_platform_specific.h - Interface to platform specific functions*/
+
+/* Copyright (c) 2014, Kenneth MacKay
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.*/
+
+/*
+ *  Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *    - 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 Intel Corporation nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 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.
+ *
+ *  uECC_platform_specific.h -- Interface to platform specific functions
+ */
+
+#ifndef __UECC_PLATFORM_SPECIFIC_H_
+#define __UECC_PLATFORM_SPECIFIC_H_
+
+/*
+ * The RNG function should fill 'size' random bytes into 'dest'. It should
+ * return 1 if 'dest' was filled with random data, or 0 if the random data could
+ * not be generated. The filled-in values should be either truly random, or from
+ * a cryptographically-secure PRNG.
+ *
+ * A cryptographically-secure PRNG function must be set (using uECC_set_rng())
+ * before calling uECC_make_key() or uECC_sign().
+ *
+ * Setting a cryptographically-secure PRNG function improves the resistance to
+ * side-channel attacks for uECC_shared_secret().
+ *
+ * A correct PRNG function is set by default (default_RNG_defined = 1) and works
+ * for some platforms, such as Unix and Linux. For other platforms, you may need
+ * to provide another PRNG function.
+*/
+#define default_RNG_defined 0
+
+int default_CSPRNG(uint8_t *dest, unsigned int size);
+
+#endif /* __UECC_PLATFORM_SPECIFIC_H_ */

+ 139 - 0
components/bt/porting/ext/tinycrypt/include/tinycrypt/hmac.h

@@ -0,0 +1,139 @@
+/* hmac.h - TinyCrypt interface to an HMAC implementation */
+
+/*
+ *  Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *    - 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 Intel Corporation nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 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.
+ */
+
+/**
+ * @file
+ * @brief Interface to an HMAC implementation.
+ *
+ *  Overview:   HMAC is a message authentication code based on hash functions.
+ *              TinyCrypt hard codes SHA-256 as the hash function. A message
+ *              authentication code based on hash functions is also called a
+ *              keyed cryptographic hash function since it performs a
+ *              transformation specified by a key in an arbitrary length data
+ *              set into a fixed length data set (also called tag).
+ *
+ *  Security:   The security of the HMAC depends on the length of the key and
+ *              on the security of the hash function. Note that HMAC primitives
+ *              are much less affected by collision attacks than their
+ *              corresponding hash functions.
+ *
+ *  Requires:   SHA-256
+ *
+ *  Usage:      1) call tc_hmac_set_key to set the HMAC key.
+ *
+ *              2) call tc_hmac_init to initialize a struct hash_state before
+ *              processing the data.
+ *
+ *              3) call tc_hmac_update to process the next input segment;
+ *              tc_hmac_update can be called as many times as needed to process
+ *              all of the segments of the input; the order is important.
+ *
+ *              4) call tc_hmac_final to out put the tag.
+ */
+
+#ifndef __TC_HMAC_H__
+#define __TC_HMAC_H__
+
+#include <tinycrypt/sha256.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct tc_hmac_state_struct {
+	/* the internal state required by h */
+	struct tc_sha256_state_struct hash_state;
+	/* HMAC key schedule */
+	uint8_t key[2*TC_SHA256_BLOCK_SIZE];
+};
+typedef struct tc_hmac_state_struct *TCHmacState_t;
+
+/**
+ *  @brief HMAC set key procedure
+ *  Configures ctx to use key
+ *  @return returns TC_CRYPTO_SUCCESS (1)
+ *          returns TC_CRYPTO_FAIL (0) if
+ *                ctx == NULL or
+ *                key == NULL or
+ *                key_size == 0
+ * @param ctx IN/OUT -- the struct tc_hmac_state_struct to initial
+ * @param key IN -- the HMAC key to configure
+ * @param key_size IN -- the HMAC key size
+ */
+int tc_hmac_set_key(TCHmacState_t ctx, const uint8_t *key,
+		    unsigned int key_size);
+
+/**
+ * @brief HMAC init procedure
+ * Initializes ctx to begin the next HMAC operation
+ * @return returns TC_CRYPTO_SUCCESS (1)
+ *         returns TC_CRYPTO_FAIL (0) if: ctx == NULL or key == NULL
+ * @param ctx IN/OUT -- struct tc_hmac_state_struct buffer to init
+ */
+int tc_hmac_init(TCHmacState_t ctx);
+
+/**
+ *  @brief HMAC update procedure
+ *  Mixes data_length bytes addressed by data into state
+ *  @return returns TC_CRYPTO_SUCCCESS (1)
+ *          returns TC_CRYPTO_FAIL (0) if: ctx == NULL or key == NULL
+ *  @note Assumes state has been initialized by tc_hmac_init
+ *  @param ctx IN/OUT -- state of HMAC computation so far
+ *  @param data IN -- data to incorporate into state
+ *  @param data_length IN -- size of data in bytes
+ */
+int tc_hmac_update(TCHmacState_t ctx, const void *data,
+		   unsigned int data_length);
+
+/**
+ *  @brief HMAC final procedure
+ *  Writes the HMAC tag into the tag buffer
+ *  @return returns TC_CRYPTO_SUCCESS (1)
+ *          returns TC_CRYPTO_FAIL (0) if:
+ *                tag == NULL or
+ *                ctx == NULL or
+ *                key == NULL or
+ *                taglen != TC_SHA256_DIGEST_SIZE
+ *  @note ctx is erased before exiting. This should never be changed/removed.
+ *  @note Assumes the tag bufer is at least sizeof(hmac_tag_size(state)) bytes
+ *  state has been initialized by tc_hmac_init
+ *  @param tag IN/OUT -- buffer to receive computed HMAC tag
+ *  @param taglen IN -- size of tag in bytes
+ *  @param ctx IN/OUT -- the HMAC state for computing tag
+ */
+int tc_hmac_final(uint8_t *tag, unsigned int taglen, TCHmacState_t ctx);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /*__TC_HMAC_H__*/

+ 164 - 0
components/bt/porting/ext/tinycrypt/include/tinycrypt/hmac_prng.h

@@ -0,0 +1,164 @@
+/* hmac_prng.h - TinyCrypt interface to an HMAC-PRNG implementation */
+
+/*
+ *  Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *    - 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 Intel Corporation nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 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.
+ */
+
+/**
+ * @file
+ * @brief Interface to an HMAC-PRNG implementation.
+ *
+ *  Overview:   A pseudo-random number generator (PRNG) generates a sequence
+ *              of numbers that have a distribution close to the one expected
+ *              for a sequence of truly random numbers. The NIST Special
+ *              Publication 800-90A specifies several mechanisms to generate
+ *              sequences of pseudo random numbers, including the HMAC-PRNG one
+ *              which is based on HMAC. TinyCrypt implements HMAC-PRNG with
+ *              certain modifications from the NIST SP 800-90A spec.
+ *
+ *  Security:   A cryptographically secure PRNG depends on the existence of an
+ *              entropy source to provide a truly random seed as well as the
+ *              security of the primitives used as the building blocks (HMAC and
+ *              SHA256, for TinyCrypt).
+ *
+ *              The NIST SP 800-90A standard tolerates a null personalization,
+ *              while TinyCrypt requires a non-null personalization. This is
+ *              because a personalization string (the host name concatenated
+ *              with a time stamp, for example) is easily computed and might be
+ *              the last line of defense against failure of the entropy source.
+ *
+ *  Requires:   - SHA-256
+ *              - HMAC
+ *
+ *  Usage:      1) call tc_hmac_prng_init to set the HMAC key and process the
+ *              personalization data.
+ *
+ *              2) call tc_hmac_prng_reseed to process the seed and additional
+ *              input.
+ *
+ *              3) call tc_hmac_prng_generate to out put the pseudo-random data.
+ */
+
+#ifndef __TC_HMAC_PRNG_H__
+#define __TC_HMAC_PRNG_H__
+
+#include <tinycrypt/sha256.h>
+#include <tinycrypt/hmac.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define TC_HMAC_PRNG_RESEED_REQ -1
+
+struct tc_hmac_prng_struct {
+	/* the HMAC instance for this PRNG */
+	struct tc_hmac_state_struct h;
+	/* the PRNG key */
+	uint8_t key[TC_SHA256_DIGEST_SIZE];
+	/* PRNG state */
+	uint8_t v[TC_SHA256_DIGEST_SIZE];
+	/* calls to tc_hmac_prng_generate left before re-seed */
+	unsigned int countdown;
+};
+
+typedef struct tc_hmac_prng_struct *TCHmacPrng_t;
+
+/**
+ *  @brief HMAC-PRNG initialization procedure
+ *  Initializes prng with personalization, disables tc_hmac_prng_generate
+ *  @return returns TC_CRYPTO_SUCCESS (1)
+ *          returns TC_CRYPTO_FAIL (0) if:
+ *                prng == NULL,
+ *                personalization == NULL,
+ *                plen > MAX_PLEN
+ *  @note Assumes: - personalization != NULL.
+ *              The personalization is a platform unique string (e.g., the host
+ *              name) and is the last line of defense against failure of the
+ *              entropy source
+ *  @warning    NIST SP 800-90A specifies 3 items as seed material during
+ *              initialization: entropy seed, personalization, and an optional
+ *              nonce. TinyCrypts requires instead a non-null personalization
+ *              (which is easily computed) and indirectly requires an entropy
+ *              seed (since the reseed function is mandatorily called after
+ *              init)
+ *  @param prng IN/OUT -- the PRNG state to initialize
+ *  @param personalization IN -- personalization string
+ *  @param plen IN -- personalization length in bytes
+ */
+int tc_hmac_prng_init(TCHmacPrng_t prng,
+		      const uint8_t *personalization,
+		      unsigned int plen);
+
+/**
+ *  @brief HMAC-PRNG reseed procedure
+ *  Mixes seed into prng, enables tc_hmac_prng_generate
+ *  @return returns  TC_CRYPTO_SUCCESS (1)
+ *  	    returns TC_CRYPTO_FAIL (0) if:
+ *          prng == NULL,
+ *          seed == NULL,
+ *          seedlen < MIN_SLEN,
+ *          seendlen > MAX_SLEN,
+ *          additional_input != (const uint8_t *) 0 && additionallen == 0,
+ *          additional_input != (const uint8_t *) 0 && additionallen > MAX_ALEN
+ *  @note Assumes:- tc_hmac_prng_init has been called for prng
+ *              - seed has sufficient entropy.
+ *
+ *  @param prng IN/OUT -- the PRNG state
+ *  @param seed IN -- entropy to mix into the prng
+ *  @param seedlen IN -- length of seed in bytes
+ *  @param additional_input IN -- additional input to the prng
+ *  @param additionallen IN -- additional input length in bytes
+ */
+int tc_hmac_prng_reseed(TCHmacPrng_t prng, const uint8_t *seed,
+			unsigned int seedlen, const uint8_t *additional_input,
+			unsigned int additionallen);
+
+/**
+ *  @brief HMAC-PRNG generate procedure
+ *  Generates outlen pseudo-random bytes into out buffer, updates prng
+ *  @return returns TC_CRYPTO_SUCCESS (1)
+ *          returns TC_HMAC_PRNG_RESEED_REQ (-1) if a reseed is needed
+ *          returns TC_CRYPTO_FAIL (0) if:
+ *                out == NULL,
+ *                prng == NULL,
+ *                outlen == 0,
+ *                outlen >= MAX_OUT
+ *  @note Assumes tc_hmac_prng_init has been called for prng
+ *  @param out IN/OUT -- buffer to receive output
+ *  @param outlen IN -- size of out buffer in bytes
+ *  @param prng IN/OUT -- the PRNG state
+ */
+int tc_hmac_prng_generate(uint8_t *out, unsigned int outlen, TCHmacPrng_t prng);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __TC_HMAC_PRNG_H__ */

+ 129 - 0
components/bt/porting/ext/tinycrypt/include/tinycrypt/sha256.h

@@ -0,0 +1,129 @@
+/* sha256.h - TinyCrypt interface to a SHA-256 implementation */
+
+/*
+ *  Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *    - 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 Intel Corporation nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 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.
+ */
+
+/**
+ * @file
+ * @brief Interface to a SHA-256 implementation.
+ *
+ *  Overview:   SHA-256 is a NIST approved cryptographic hashing algorithm
+ *              specified in FIPS 180. A hash algorithm maps data of arbitrary
+ *              size to data of fixed length.
+ *
+ *  Security:   SHA-256 provides 128 bits of security against collision attacks
+ *              and 256 bits of security against pre-image attacks. SHA-256 does
+ *              NOT behave like a random oracle, but it can be used as one if
+ *              the string being hashed is prefix-free encoded before hashing.
+ *
+ *  Usage:      1) call tc_sha256_init to initialize a struct
+ *              tc_sha256_state_struct before hashing a new string.
+ *
+ *              2) call tc_sha256_update to hash the next string segment;
+ *              tc_sha256_update can be called as many times as needed to hash
+ *              all of the segments of a string; the order is important.
+ *
+ *              3) call tc_sha256_final to out put the digest from a hashing
+ *              operation.
+ */
+
+#ifndef __TC_SHA256_H__
+#define __TC_SHA256_H__
+
+#include <stddef.h>
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define TC_SHA256_BLOCK_SIZE (64)
+#define TC_SHA256_DIGEST_SIZE (32)
+#define TC_SHA256_STATE_BLOCKS (TC_SHA256_DIGEST_SIZE/4)
+
+struct tc_sha256_state_struct {
+	unsigned int iv[TC_SHA256_STATE_BLOCKS];
+	uint64_t bits_hashed;
+	uint8_t leftover[TC_SHA256_BLOCK_SIZE];
+	size_t leftover_offset;
+};
+
+typedef struct tc_sha256_state_struct *TCSha256State_t;
+
+/**
+ *  @brief SHA256 initialization procedure
+ *  Initializes s
+ *  @return returns TC_CRYPTO_SUCCESS (1)
+ *          returns TC_CRYPTO_FAIL (0) if s == NULL
+ *  @param s Sha256 state struct
+ */
+int tc_sha256_init(TCSha256State_t s);
+
+/**
+ *  @brief SHA256 update procedure
+ *  Hashes data_length bytes addressed by data into state s
+ *  @return returns TC_CRYPTO_SUCCESS (1)
+ *          returns TC_CRYPTO_FAIL (0) if:
+ *                s == NULL,
+ *                s->iv == NULL,
+ *                data == NULL
+ *  @note Assumes s has been initialized by tc_sha256_init
+ *  @warning The state buffer 'leftover' is left in memory after processing
+ *           If your application intends to have sensitive data in this
+ *           buffer, remind to erase it after the data has been processed
+ *  @param s Sha256 state struct
+ *  @param data message to hash
+ *  @param datalen length of message to hash
+ */
+int tc_sha256_update (TCSha256State_t s, const uint8_t *data, size_t datalen);
+
+/**
+ *  @brief SHA256 final procedure
+ *  Inserts the completed hash computation into digest
+ *  @return returns TC_CRYPTO_SUCCESS (1)
+ *          returns TC_CRYPTO_FAIL (0) if:
+ *                s == NULL,
+ *                s->iv == NULL,
+ *                digest == NULL
+ *  @note Assumes: s has been initialized by tc_sha256_init
+ *        digest points to at least TC_SHA256_DIGEST_SIZE bytes
+ *  @warning The state buffer 'leftover' is left in memory after processing
+ *           If your application intends to have sensitive data in this
+ *           buffer, remind to erase it after the data has been processed
+ *  @param digest unsigned eight bit integer
+ *  @param Sha256 state struct
+ */
+int tc_sha256_final(uint8_t *digest, TCSha256State_t s);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __TC_SHA256_H__ */

+ 95 - 0
components/bt/porting/ext/tinycrypt/include/tinycrypt/utils.h

@@ -0,0 +1,95 @@
+/* utils.h - TinyCrypt interface to platform-dependent run-time operations */
+
+/*
+ *  Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *    - 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 Intel Corporation nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 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.
+ */
+
+/**
+ * @file
+ * @brief Interface to platform-dependent run-time operations.
+ *
+ */
+
+#ifndef __TC_UTILS_H__
+#define __TC_UTILS_H__
+
+#include <stdint.h>
+#include <stddef.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief Copy the the buffer 'from' to the buffer 'to'.
+ * @return returns TC_CRYPTO_SUCCESS (1)
+ *         returns TC_CRYPTO_FAIL (0) if:
+ *                from_len > to_len.
+ *
+ * @param to OUT -- destination buffer
+ * @param to_len IN -- length of destination buffer
+ * @param from IN -- origin buffer
+ * @param from_len IN -- length of origin buffer
+ */
+unsigned int _copy(uint8_t *to, unsigned int to_len,
+	           const uint8_t *from, unsigned int from_len);
+
+/**
+ * @brief Set the value 'val' into the buffer 'to', 'len' times.
+ *
+ * @param to OUT -- destination buffer
+ * @param val IN -- value to be set in 'to'
+ * @param len IN -- number of times the value will be copied
+ */
+void _set(void *to, uint8_t val, unsigned int len);
+
+/*
+ * @brief AES specific doubling function, which utilizes
+ * the finite field used by AES.
+ * @return Returns a^2
+ *
+ * @param a IN/OUT -- value to be doubled
+ */
+uint8_t _double_byte(uint8_t a);
+
+/*
+ * @brief Constant-time algorithm to compare if two sequences of bytes are equal
+ * @return Returns 0 if equal, and non-zero otherwise
+ *
+ * @param a IN -- sequence of bytes a
+ * @param b IN -- sequence of bytes b
+ * @param size IN -- size of sequences a and b
+ */
+int _compare(const uint8_t *a, const uint8_t *b, size_t size);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __TC_UTILS_H__ */

+ 164 - 0
components/bt/porting/ext/tinycrypt/src/aes_decrypt.c

@@ -0,0 +1,164 @@
+/* aes_decrypt.c - TinyCrypt implementation of AES decryption procedure */
+
+/*
+ *  Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *    - 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 Intel Corporation nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 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.
+ */
+
+#include <tinycrypt/aes.h>
+#include <tinycrypt/constants.h>
+#include <tinycrypt/utils.h>
+
+static const uint8_t inv_sbox[256] = {
+	0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e,
+	0x81, 0xf3, 0xd7, 0xfb, 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87,
+	0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, 0x54, 0x7b, 0x94, 0x32,
+	0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
+	0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49,
+	0x6d, 0x8b, 0xd1, 0x25, 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16,
+	0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, 0x6c, 0x70, 0x48, 0x50,
+	0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
+	0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05,
+	0xb8, 0xb3, 0x45, 0x06, 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02,
+	0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, 0x3a, 0x91, 0x11, 0x41,
+	0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
+	0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8,
+	0x1c, 0x75, 0xdf, 0x6e, 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89,
+	0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, 0xfc, 0x56, 0x3e, 0x4b,
+	0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
+	0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59,
+	0x27, 0x80, 0xec, 0x5f, 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d,
+	0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, 0xa0, 0xe0, 0x3b, 0x4d,
+	0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
+	0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63,
+	0x55, 0x21, 0x0c, 0x7d
+};
+
+int tc_aes128_set_decrypt_key(TCAesKeySched_t s, const uint8_t *k)
+{
+	return tc_aes128_set_encrypt_key(s, k);
+}
+
+#define mult8(a)(_double_byte(_double_byte(_double_byte(a))))
+#define mult9(a)(mult8(a)^(a))
+#define multb(a)(mult8(a)^_double_byte(a)^(a))
+#define multd(a)(mult8(a)^_double_byte(_double_byte(a))^(a))
+#define multe(a)(mult8(a)^_double_byte(_double_byte(a))^_double_byte(a))
+
+static inline void mult_row_column(uint8_t *out, const uint8_t *in)
+{
+	out[0] = multe(in[0]) ^ multb(in[1]) ^ multd(in[2]) ^ mult9(in[3]);
+	out[1] = mult9(in[0]) ^ multe(in[1]) ^ multb(in[2]) ^ multd(in[3]);
+	out[2] = multd(in[0]) ^ mult9(in[1]) ^ multe(in[2]) ^ multb(in[3]);
+	out[3] = multb(in[0]) ^ multd(in[1]) ^ mult9(in[2]) ^ multe(in[3]);
+}
+
+static inline void inv_mix_columns(uint8_t *s)
+{
+	uint8_t t[Nb*Nk];
+
+	mult_row_column(t, s);
+	mult_row_column(&t[Nb], s+Nb);
+	mult_row_column(&t[2*Nb], s+(2*Nb));
+	mult_row_column(&t[3*Nb], s+(3*Nb));
+	(void)_copy(s, sizeof(t), t, sizeof(t));
+}
+
+static inline void add_round_key(uint8_t *s, const unsigned int *k)
+{
+	s[0] ^= (uint8_t)(k[0] >> 24); s[1] ^= (uint8_t)(k[0] >> 16);
+	s[2] ^= (uint8_t)(k[0] >> 8); s[3] ^= (uint8_t)(k[0]);
+	s[4] ^= (uint8_t)(k[1] >> 24); s[5] ^= (uint8_t)(k[1] >> 16);
+	s[6] ^= (uint8_t)(k[1] >> 8); s[7] ^= (uint8_t)(k[1]);
+	s[8] ^= (uint8_t)(k[2] >> 24); s[9] ^= (uint8_t)(k[2] >> 16);
+	s[10] ^= (uint8_t)(k[2] >> 8); s[11] ^= (uint8_t)(k[2]);
+	s[12] ^= (uint8_t)(k[3] >> 24); s[13] ^= (uint8_t)(k[3] >> 16);
+	s[14] ^= (uint8_t)(k[3] >> 8); s[15] ^= (uint8_t)(k[3]);
+}
+
+static inline void inv_sub_bytes(uint8_t *s)
+{
+	unsigned int i;
+
+	for (i = 0; i < (Nb*Nk); ++i) {
+		s[i] = inv_sbox[s[i]];
+	}
+}
+
+/*
+ * This inv_shift_rows also implements the matrix flip required for
+ * inv_mix_columns, but performs it here to reduce the number of memory
+ * operations.
+ */
+static inline void inv_shift_rows(uint8_t *s)
+{
+	uint8_t t[Nb*Nk];
+
+	t[0]  = s[0]; t[1] = s[13]; t[2] = s[10]; t[3] = s[7];
+	t[4]  = s[4]; t[5] = s[1]; t[6] = s[14]; t[7] = s[11];
+	t[8]  = s[8]; t[9] = s[5]; t[10] = s[2]; t[11] = s[15];
+	t[12] = s[12]; t[13] = s[9]; t[14] = s[6]; t[15] = s[3];
+	(void)_copy(s, sizeof(t), t, sizeof(t));
+}
+
+int tc_aes_decrypt(uint8_t *out, const uint8_t *in, const TCAesKeySched_t s)
+{
+	uint8_t state[Nk*Nb];
+	unsigned int i;
+
+	if (out == (uint8_t *) 0) {
+		return TC_CRYPTO_FAIL;
+	} else if (in == (const uint8_t *) 0) {
+		return TC_CRYPTO_FAIL;
+	} else if (s == (TCAesKeySched_t) 0) {
+		return TC_CRYPTO_FAIL;
+	}
+
+	(void)_copy(state, sizeof(state), in, sizeof(state));
+
+	add_round_key(state, s->words + Nb*Nr);
+
+	for (i = Nr - 1; i > 0; --i) {
+		inv_shift_rows(state);
+		inv_sub_bytes(state);
+		add_round_key(state, s->words + Nb*i);
+		inv_mix_columns(state);
+	}
+
+	inv_shift_rows(state);
+	inv_sub_bytes(state);
+	add_round_key(state, s->words);
+
+	(void)_copy(out, sizeof(state), state, sizeof(state));
+
+	/*zeroing out the state buffer */
+	_set(state, TC_ZERO_BYTE, sizeof(state));
+
+
+	return TC_CRYPTO_SUCCESS;
+}

+ 191 - 0
components/bt/porting/ext/tinycrypt/src/aes_encrypt.c

@@ -0,0 +1,191 @@
+/* aes_encrypt.c - TinyCrypt implementation of AES encryption procedure */
+
+/*
+ *  Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *    - 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 Intel Corporation nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 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.
+ */
+
+#include <tinycrypt/aes.h>
+#include <tinycrypt/utils.h>
+#include <tinycrypt/constants.h>
+
+static const uint8_t sbox[256] = {
+	0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b,
+	0xfe, 0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0,
+	0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 0xb7, 0xfd, 0x93, 0x26,
+	0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
+	0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2,
+	0xeb, 0x27, 0xb2, 0x75, 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0,
+	0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, 0x53, 0xd1, 0x00, 0xed,
+	0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
+	0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f,
+	0x50, 0x3c, 0x9f, 0xa8, 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5,
+	0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 0xcd, 0x0c, 0x13, 0xec,
+	0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
+	0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14,
+	0xde, 0x5e, 0x0b, 0xdb, 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c,
+	0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 0xe7, 0xc8, 0x37, 0x6d,
+	0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
+	0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f,
+	0x4b, 0xbd, 0x8b, 0x8a, 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e,
+	0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, 0xe1, 0xf8, 0x98, 0x11,
+	0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
+	0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f,
+	0xb0, 0x54, 0xbb, 0x16
+};
+
+static inline unsigned int rotword(unsigned int a)
+{
+	return (((a) >> 24)|((a) << 8));
+}
+
+#define subbyte(a, o)(sbox[((a) >> (o))&0xff] << (o))
+#define subword(a)(subbyte(a, 24)|subbyte(a, 16)|subbyte(a, 8)|subbyte(a, 0))
+
+int tc_aes128_set_encrypt_key(TCAesKeySched_t s, const uint8_t *k)
+{
+	const unsigned int rconst[11] = {
+		0x00000000, 0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000,
+		0x20000000, 0x40000000, 0x80000000, 0x1b000000, 0x36000000
+	};
+	unsigned int i;
+	unsigned int t;
+
+	if (s == (TCAesKeySched_t) 0) {
+		return TC_CRYPTO_FAIL;
+	} else if (k == (const uint8_t *) 0) {
+		return TC_CRYPTO_FAIL;
+	}
+
+	for (i = 0; i < Nk; ++i) {
+		s->words[i] = (k[Nb*i]<<24) | (k[Nb*i+1]<<16) |
+			      (k[Nb*i+2]<<8) | (k[Nb*i+3]);
+	}
+
+	for (; i < (Nb * (Nr + 1)); ++i) {
+		t = s->words[i-1];
+		if ((i % Nk) == 0) {
+			t = subword(rotword(t)) ^ rconst[i/Nk];
+		}
+		s->words[i] = s->words[i-Nk] ^ t;
+	}
+
+	return TC_CRYPTO_SUCCESS;
+}
+
+static inline void add_round_key(uint8_t *s, const unsigned int *k)
+{
+	s[0] ^= (uint8_t)(k[0] >> 24); s[1] ^= (uint8_t)(k[0] >> 16);
+	s[2] ^= (uint8_t)(k[0] >> 8); s[3] ^= (uint8_t)(k[0]);
+	s[4] ^= (uint8_t)(k[1] >> 24); s[5] ^= (uint8_t)(k[1] >> 16);
+	s[6] ^= (uint8_t)(k[1] >> 8); s[7] ^= (uint8_t)(k[1]);
+	s[8] ^= (uint8_t)(k[2] >> 24); s[9] ^= (uint8_t)(k[2] >> 16);
+	s[10] ^= (uint8_t)(k[2] >> 8); s[11] ^= (uint8_t)(k[2]);
+	s[12] ^= (uint8_t)(k[3] >> 24); s[13] ^= (uint8_t)(k[3] >> 16);
+	s[14] ^= (uint8_t)(k[3] >> 8); s[15] ^= (uint8_t)(k[3]);
+}
+
+static inline void sub_bytes(uint8_t *s)
+{
+	unsigned int i;
+
+	for (i = 0; i < (Nb * Nk); ++i) {
+		s[i] = sbox[s[i]];
+	}
+}
+
+#define triple(a)(_double_byte(a)^(a))
+
+static inline void mult_row_column(uint8_t *out, const uint8_t *in)
+{
+	out[0] = _double_byte(in[0]) ^ triple(in[1]) ^ in[2] ^ in[3];
+	out[1] = in[0] ^ _double_byte(in[1]) ^ triple(in[2]) ^ in[3];
+	out[2] = in[0] ^ in[1] ^ _double_byte(in[2]) ^ triple(in[3]);
+	out[3] = triple(in[0]) ^ in[1] ^ in[2] ^ _double_byte(in[3]);
+}
+
+static inline void mix_columns(uint8_t *s)
+{
+	uint8_t t[Nb*Nk];
+
+	mult_row_column(t, s);
+	mult_row_column(&t[Nb], s+Nb);
+	mult_row_column(&t[2 * Nb], s + (2 * Nb));
+	mult_row_column(&t[3 * Nb], s + (3 * Nb));
+	(void) _copy(s, sizeof(t), t, sizeof(t));
+}
+
+/*
+ * This shift_rows also implements the matrix flip required for mix_columns, but
+ * performs it here to reduce the number of memory operations.
+ */
+static inline void shift_rows(uint8_t *s)
+{
+	uint8_t t[Nb * Nk];
+
+	t[0]  = s[0]; t[1] = s[5]; t[2] = s[10]; t[3] = s[15];
+	t[4]  = s[4]; t[5] = s[9]; t[6] = s[14]; t[7] = s[3];
+	t[8]  = s[8]; t[9] = s[13]; t[10] = s[2]; t[11] = s[7];
+	t[12] = s[12]; t[13] = s[1]; t[14] = s[6]; t[15] = s[11];
+	(void) _copy(s, sizeof(t), t, sizeof(t));
+}
+
+int tc_aes_encrypt(uint8_t *out, const uint8_t *in, const TCAesKeySched_t s)
+{
+	uint8_t state[Nk*Nb];
+	unsigned int i;
+
+	if (out == (uint8_t *) 0) {
+		return TC_CRYPTO_FAIL;
+	} else if (in == (const uint8_t *) 0) {
+		return TC_CRYPTO_FAIL;
+	} else if (s == (TCAesKeySched_t) 0) {
+		return TC_CRYPTO_FAIL;
+	}
+
+	(void)_copy(state, sizeof(state), in, sizeof(state));
+	add_round_key(state, s->words);
+
+	for (i = 0; i < (Nr - 1); ++i) {
+		sub_bytes(state);
+		shift_rows(state);
+		mix_columns(state);
+		add_round_key(state, s->words + Nb*(i+1));
+	}
+
+	sub_bytes(state);
+	shift_rows(state);
+	add_round_key(state, s->words + Nb*(i+1));
+
+	(void)_copy(out, sizeof(state), state, sizeof(state));
+
+	/* zeroing out the state buffer */
+	_set(state, TC_ZERO_BYTE, sizeof(state));
+
+	return TC_CRYPTO_SUCCESS;
+}

+ 114 - 0
components/bt/porting/ext/tinycrypt/src/cbc_mode.c

@@ -0,0 +1,114 @@
+/* cbc_mode.c - TinyCrypt implementation of CBC mode encryption & decryption */
+
+/*
+ *  Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *    - 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 Intel Corporation nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 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.
+ */
+
+#include <tinycrypt/cbc_mode.h>
+#include <tinycrypt/constants.h>
+#include <tinycrypt/utils.h>
+
+int tc_cbc_mode_encrypt(uint8_t *out, unsigned int outlen, const uint8_t *in,
+			    unsigned int inlen, const uint8_t *iv,
+			    const TCAesKeySched_t sched)
+{
+
+	uint8_t buffer[TC_AES_BLOCK_SIZE];
+	unsigned int n, m;
+
+	/* input sanity check: */
+	if (out == (uint8_t *) 0 ||
+	    in == (const uint8_t *) 0 ||
+	    sched == (TCAesKeySched_t) 0 ||
+	    inlen == 0 ||
+	    outlen == 0 ||
+	    (inlen % TC_AES_BLOCK_SIZE) != 0 ||
+	    (outlen % TC_AES_BLOCK_SIZE) != 0 ||
+	    outlen != inlen + TC_AES_BLOCK_SIZE) {
+		return TC_CRYPTO_FAIL;
+	}
+
+	/* copy iv to the buffer */
+	(void)_copy(buffer, TC_AES_BLOCK_SIZE, iv, TC_AES_BLOCK_SIZE);
+	/* copy iv to the output buffer */
+	(void)_copy(out, TC_AES_BLOCK_SIZE, iv, TC_AES_BLOCK_SIZE);
+	out += TC_AES_BLOCK_SIZE;
+
+	for (n = m = 0; n < inlen; ++n) {
+		buffer[m++] ^= *in++;
+		if (m == TC_AES_BLOCK_SIZE) {
+			(void)tc_aes_encrypt(buffer, buffer, sched);
+			(void)_copy(out, TC_AES_BLOCK_SIZE,
+				    buffer, TC_AES_BLOCK_SIZE);
+			out += TC_AES_BLOCK_SIZE;
+			m = 0;
+		}
+	}
+
+	return TC_CRYPTO_SUCCESS;
+}
+
+int tc_cbc_mode_decrypt(uint8_t *out, unsigned int outlen, const uint8_t *in,
+			    unsigned int inlen, const uint8_t *iv,
+			    const TCAesKeySched_t sched)
+{
+
+	uint8_t buffer[TC_AES_BLOCK_SIZE];
+	const uint8_t *p;
+	unsigned int n, m;
+
+	/* sanity check the inputs */
+	if (out == (uint8_t *) 0 ||
+	    in == (const uint8_t *) 0 ||
+	    sched == (TCAesKeySched_t) 0 ||
+	    inlen == 0 ||
+	    outlen == 0 ||
+	    (inlen % TC_AES_BLOCK_SIZE) != 0 ||
+	    (outlen % TC_AES_BLOCK_SIZE) != 0 ||
+	    outlen != inlen - TC_AES_BLOCK_SIZE) {
+		return TC_CRYPTO_FAIL;
+	}
+
+	/*
+	 * Note that in == iv + ciphertext, i.e. the iv and the ciphertext are
+	 * contiguous. This allows for a very efficient decryption algorithm
+	 * that would not otherwise be possible.
+	 */
+	p = iv;
+	for (n = m = 0; n < inlen; ++n) {
+		if ((n % TC_AES_BLOCK_SIZE) == 0) {
+			(void)tc_aes_decrypt(buffer, in, sched);
+			in += TC_AES_BLOCK_SIZE;
+			m = 0;
+		}
+		*out++ = buffer[m++] ^ *p++;
+	}
+
+	return TC_CRYPTO_SUCCESS;
+}

+ 266 - 0
components/bt/porting/ext/tinycrypt/src/ccm_mode.c

@@ -0,0 +1,266 @@
+/* ccm_mode.c - TinyCrypt implementation of CCM mode */
+
+/*
+ *  Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *    - 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 Intel Corporation nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 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.
+ */
+
+#include <tinycrypt/ccm_mode.h>
+#include <tinycrypt/constants.h>
+#include <tinycrypt/utils.h>
+
+#include <stdio.h>
+
+int tc_ccm_config(TCCcmMode_t c, TCAesKeySched_t sched, uint8_t *nonce,
+		  unsigned int nlen, unsigned int mlen)
+{
+
+	/* input sanity check: */
+	if (c == (TCCcmMode_t) 0 ||
+	    sched == (TCAesKeySched_t) 0 ||
+	    nonce == (uint8_t *) 0) {
+		return TC_CRYPTO_FAIL;
+	} else if (nlen != 13) {
+		return TC_CRYPTO_FAIL; /* The allowed nonce size is: 13. See documentation.*/
+	} else if ((mlen < 4) || (mlen > 16) || (mlen & 1)) {
+		return TC_CRYPTO_FAIL; /* The allowed mac sizes are: 4, 6, 8, 10, 12, 14, 16.*/
+	}
+
+	c->mlen = mlen;
+	c->sched = sched;
+	c->nonce = nonce;
+
+	return TC_CRYPTO_SUCCESS;
+}
+
+/**
+ * Variation of CBC-MAC mode used in CCM.
+ */
+static void ccm_cbc_mac(uint8_t *T, const uint8_t *data, unsigned int dlen,
+			unsigned int flag, TCAesKeySched_t sched)
+{
+
+	unsigned int i;
+
+	if (flag > 0) {
+		T[0] ^= (uint8_t)(dlen >> 8);
+		T[1] ^= (uint8_t)(dlen);
+		dlen += 2; i = 2;
+	} else {
+		i = 0;
+	}
+
+	while (i < dlen) {
+		T[i++ % (Nb * Nk)] ^= *data++;
+		if (((i % (Nb * Nk)) == 0) || dlen == i) {
+			(void) tc_aes_encrypt(T, T, sched);
+		}
+	}
+}
+
+/**
+ * Variation of CTR mode used in CCM.
+ * The CTR mode used by CCM is slightly different than the conventional CTR
+ * mode (the counter is increased before encryption, instead of after
+ * encryption). Besides, it is assumed that the counter is stored in the last
+ * 2 bytes of the nonce.
+ */
+static int ccm_ctr_mode(uint8_t *out, unsigned int outlen, const uint8_t *in,
+			unsigned int inlen, uint8_t *ctr, const TCAesKeySched_t sched)
+{
+
+	uint8_t buffer[TC_AES_BLOCK_SIZE];
+	uint8_t nonce[TC_AES_BLOCK_SIZE];
+	uint16_t block_num;
+	unsigned int i;
+
+	/* input sanity check: */
+	if (out == (uint8_t *) 0 ||
+	    in == (uint8_t *) 0 ||
+	    ctr == (uint8_t *) 0 ||
+	    sched == (TCAesKeySched_t) 0 ||
+	    inlen == 0 ||
+	    outlen == 0 ||
+	    outlen != inlen) {
+		return TC_CRYPTO_FAIL;
+	}
+
+	/* copy the counter to the nonce */
+	(void) _copy(nonce, sizeof(nonce), ctr, sizeof(nonce));
+
+	/* select the last 2 bytes of the nonce to be incremented */
+	block_num = (uint16_t) ((nonce[14] << 8)|(nonce[15]));
+	for (i = 0; i < inlen; ++i) {
+		if ((i % (TC_AES_BLOCK_SIZE)) == 0) {
+			block_num++;
+			nonce[14] = (uint8_t)(block_num >> 8);
+			nonce[15] = (uint8_t)(block_num);
+			if (!tc_aes_encrypt(buffer, nonce, sched)) {
+				return TC_CRYPTO_FAIL;
+			}
+		}
+		/* update the output */
+		*out++ = buffer[i % (TC_AES_BLOCK_SIZE)] ^ *in++;
+	}
+
+	/* update the counter */
+	ctr[14] = nonce[14]; ctr[15] = nonce[15];
+
+	return TC_CRYPTO_SUCCESS;
+}
+
+int tc_ccm_generation_encryption(uint8_t *out, unsigned int olen,
+				 const uint8_t *associated_data,
+				 unsigned int alen, const uint8_t *payload,
+				 unsigned int plen, TCCcmMode_t c)
+{
+
+	/* input sanity check: */
+	if ((out == (uint8_t *) 0) ||
+		(c == (TCCcmMode_t) 0) ||
+		((plen > 0) && (payload == (uint8_t *) 0)) ||
+		((alen > 0) && (associated_data == (uint8_t *) 0)) ||
+		(alen >= TC_CCM_AAD_MAX_BYTES) || /* associated data size unsupported */
+		(plen >= TC_CCM_PAYLOAD_MAX_BYTES) || /* payload size unsupported */
+		(olen < (plen + c->mlen))) {  /* invalid output buffer size */
+		return TC_CRYPTO_FAIL;
+	}
+
+	uint8_t b[Nb * Nk];
+	uint8_t tag[Nb * Nk];
+	unsigned int i;
+
+	/* GENERATING THE AUTHENTICATION TAG: */
+
+	/* formatting the sequence b for authentication: */
+	b[0] = ((alen > 0) ? 0x40:0) | (((c->mlen - 2) / 2 << 3)) | (1);
+	for (i = 1; i <= 13; ++i) {
+		b[i] = c->nonce[i - 1];
+	}
+	b[14] = (uint8_t)(plen >> 8);
+	b[15] = (uint8_t)(plen);
+
+	/* computing the authentication tag using cbc-mac: */
+	(void) tc_aes_encrypt(tag, b, c->sched);
+	if (alen > 0) {
+		ccm_cbc_mac(tag, associated_data, alen, 1, c->sched);
+	}
+	if (plen > 0) {
+		ccm_cbc_mac(tag, payload, plen, 0, c->sched);
+	}
+
+	/* ENCRYPTION: */
+
+	/* formatting the sequence b for encryption: */
+	b[0] = 1; /* q - 1 = 2 - 1 = 1 */
+	b[14] = b[15] = TC_ZERO_BYTE;
+
+	/* encrypting payload using ctr mode: */
+	ccm_ctr_mode(out, plen, payload, plen, b, c->sched);
+
+	b[14] = b[15] = TC_ZERO_BYTE; /* restoring initial counter for ctr_mode (0):*/
+
+	/* encrypting b and adding the tag to the output: */
+	(void) tc_aes_encrypt(b, b, c->sched);
+	out += plen;
+	for (i = 0; i < c->mlen; ++i) {
+		*out++ = tag[i] ^ b[i];
+	}
+
+	return TC_CRYPTO_SUCCESS;
+}
+
+int tc_ccm_decryption_verification(uint8_t *out, unsigned int olen,
+				   const uint8_t *associated_data,
+				   unsigned int alen, const uint8_t *payload,
+				   unsigned int plen, TCCcmMode_t c)
+{
+
+	/* input sanity check: */
+	if ((out == (uint8_t *) 0) ||
+	    (c == (TCCcmMode_t) 0) ||
+	    ((plen > 0) && (payload == (uint8_t *) 0)) ||
+	    ((alen > 0) && (associated_data == (uint8_t *) 0)) ||
+	    (alen >= TC_CCM_AAD_MAX_BYTES) || /* associated data size unsupported */
+	    (plen >= TC_CCM_PAYLOAD_MAX_BYTES) || /* payload size unsupported */
+	    (olen < plen - c->mlen)) { /* invalid output buffer size */
+		return TC_CRYPTO_FAIL;
+  }
+
+	uint8_t b[Nb * Nk];
+	uint8_t tag[Nb * Nk];
+	unsigned int i;
+
+	/* DECRYPTION: */
+
+	/* formatting the sequence b for decryption: */
+	b[0] = 1; /* q - 1 = 2 - 1 = 1 */
+	for (i = 1; i < 14; ++i) {
+		b[i] = c->nonce[i - 1];
+	}
+	b[14] = b[15] = TC_ZERO_BYTE; /* initial counter value is 0 */
+
+	/* decrypting payload using ctr mode: */
+	ccm_ctr_mode(out, plen - c->mlen, payload, plen - c->mlen, b, c->sched);
+
+	b[14] = b[15] = TC_ZERO_BYTE; /* restoring initial counter value (0) */
+
+	/* encrypting b and restoring the tag from input: */
+	(void) tc_aes_encrypt(b, b, c->sched);
+	for (i = 0; i < c->mlen; ++i) {
+		tag[i] = *(payload + plen - c->mlen + i) ^ b[i];
+	}
+
+	/* VERIFYING THE AUTHENTICATION TAG: */
+
+	/* formatting the sequence b for authentication: */
+	b[0] = ((alen > 0) ? 0x40:0)|(((c->mlen - 2) / 2 << 3)) | (1);
+	for (i = 1; i < 14; ++i) {
+		b[i] = c->nonce[i - 1];
+	}
+	b[14] = (uint8_t)((plen - c->mlen) >> 8);
+	b[15] = (uint8_t)(plen - c->mlen);
+
+	/* computing the authentication tag using cbc-mac: */
+	(void) tc_aes_encrypt(b, b, c->sched);
+	if (alen > 0) {
+		ccm_cbc_mac(b, associated_data, alen, 1, c->sched);
+	}
+	if (plen > 0) {
+		ccm_cbc_mac(b, out, plen - c->mlen, 0, c->sched);
+	}
+
+	/* comparing the received tag and the computed one: */
+	if (_compare(b, tag, c->mlen) == 0) {
+		return TC_CRYPTO_SUCCESS;
+  	} else {
+		/* erase the decrypted buffer in case of mac validation failure: */
+		_set(out, 0, plen - c->mlen);
+		return TC_CRYPTO_FAIL;
+	}
+}

+ 254 - 0
components/bt/porting/ext/tinycrypt/src/cmac_mode.c

@@ -0,0 +1,254 @@
+/* cmac_mode.c - TinyCrypt CMAC mode implementation */
+
+/*
+ *  Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *    - 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 Intel Corporation nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 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.
+ */
+
+#include <tinycrypt/aes.h>
+#include <tinycrypt/cmac_mode.h>
+#include <tinycrypt/constants.h>
+#include <tinycrypt/utils.h>
+
+/* max number of calls until change the key (2^48).*/
+const static uint64_t MAX_CALLS = ((uint64_t)1 << 48);
+
+/*
+ *  gf_wrap -- In our implementation, GF(2^128) is represented as a 16 byte
+ *  array with byte 0 the most significant and byte 15 the least significant.
+ *  High bit carry reduction is based on the primitive polynomial
+ *
+ *                     X^128 + X^7 + X^2 + X + 1,
+ *
+ *  which leads to the reduction formula X^128 = X^7 + X^2 + X + 1. Indeed,
+ *  since 0 = (X^128 + X^7 + X^2 + 1) mod (X^128 + X^7 + X^2 + X + 1) and since
+ *  addition of polynomials with coefficients in Z/Z(2) is just XOR, we can
+ *  add X^128 to both sides to get
+ *
+ *       X^128 = (X^7 + X^2 + X + 1) mod (X^128 + X^7 + X^2 + X + 1)
+ *
+ *  and the coefficients of the polynomial on the right hand side form the
+ *  string 1000 0111 = 0x87, which is the value of gf_wrap.
+ *
+ *  This gets used in the following way. Doubling in GF(2^128) is just a left
+ *  shift by 1 bit, except when the most significant bit is 1. In the latter
+ *  case, the relation X^128 = X^7 + X^2 + X + 1 says that the high order bit
+ *  that overflows beyond 128 bits can be replaced by addition of
+ *  X^7 + X^2 + X + 1 <--> 0x87 to the low order 128 bits. Since addition
+ *  in GF(2^128) is represented by XOR, we therefore only have to XOR 0x87
+ *  into the low order byte after a left shift when the starting high order
+ *  bit is 1.
+ */
+const unsigned char gf_wrap = 0x87;
+
+/*
+ *  assumes: out != NULL and points to a GF(2^n) value to receive the
+ *            doubled value;
+ *           in != NULL and points to a 16 byte GF(2^n) value
+ *            to double;
+ *           the in and out buffers do not overlap.
+ *  effects: doubles the GF(2^n) value pointed to by "in" and places
+ *           the result in the GF(2^n) value pointed to by "out."
+ */
+void gf_double(uint8_t *out, uint8_t *in)
+{
+
+	/* start with low order byte */
+	uint8_t *x = in + (TC_AES_BLOCK_SIZE - 1);
+
+	/* if msb == 1, we need to add the gf_wrap value, otherwise add 0 */
+	uint8_t carry = (in[0] >> 7) ? gf_wrap : 0;
+
+	out += (TC_AES_BLOCK_SIZE - 1);
+	for (;;) {
+		*out-- = (*x << 1) ^ carry;
+		if (x == in) {
+			break;
+		}
+		carry = *x-- >> 7;
+	}
+}
+
+int tc_cmac_setup(TCCmacState_t s, const uint8_t *key, TCAesKeySched_t sched)
+{
+
+	/* input sanity check: */
+	if (s == (TCCmacState_t) 0 ||
+	    key == (const uint8_t *) 0) {
+		return TC_CRYPTO_FAIL;
+	}
+
+	/* put s into a known state */
+	_set(s, 0, sizeof(*s));
+	s->sched = sched;
+
+	/* configure the encryption key used by the underlying block cipher */
+	tc_aes128_set_encrypt_key(s->sched, key);
+
+	/* compute s->K1 and s->K2 from s->iv using s->keyid */
+	_set(s->iv, 0, TC_AES_BLOCK_SIZE);
+	tc_aes_encrypt(s->iv, s->iv, s->sched);
+	gf_double (s->K1, s->iv);
+	gf_double (s->K2, s->K1);
+
+	/* reset s->iv to 0 in case someone wants to compute now */
+	tc_cmac_init(s);
+
+	return TC_CRYPTO_SUCCESS;
+}
+
+int tc_cmac_erase(TCCmacState_t s)
+{
+	if (s == (TCCmacState_t) 0) {
+		return TC_CRYPTO_FAIL;
+	}
+
+	/* destroy the current state */
+	_set(s, 0, sizeof(*s));
+
+	return TC_CRYPTO_SUCCESS;
+}
+
+int tc_cmac_init(TCCmacState_t s)
+{
+	/* input sanity check: */
+	if (s == (TCCmacState_t) 0) {
+		return TC_CRYPTO_FAIL;
+	}
+
+	/* CMAC starts with an all zero initialization vector */
+	_set(s->iv, 0, TC_AES_BLOCK_SIZE);
+
+	/* and the leftover buffer is empty */
+	_set(s->leftover, 0, TC_AES_BLOCK_SIZE);
+	s->leftover_offset = 0;
+
+	/* Set countdown to max number of calls allowed before re-keying: */
+	s->countdown = MAX_CALLS;
+
+	return TC_CRYPTO_SUCCESS;
+}
+
+int tc_cmac_update(TCCmacState_t s, const uint8_t *data, size_t data_length)
+{
+	unsigned int i;
+
+	/* input sanity check: */
+	if (s == (TCCmacState_t) 0) {
+		return TC_CRYPTO_FAIL;
+	}
+	if (data_length == 0) {
+		return  TC_CRYPTO_SUCCESS;
+	}
+	if (data == (const uint8_t *) 0) {
+		return TC_CRYPTO_FAIL;
+	}
+
+	if (s->countdown == 0) {
+		return TC_CRYPTO_FAIL;
+	}
+
+	s->countdown--;
+
+	if (s->leftover_offset > 0) {
+		/* last data added to s didn't end on a TC_AES_BLOCK_SIZE byte boundary */
+		size_t remaining_space = TC_AES_BLOCK_SIZE - s->leftover_offset;
+
+		if (data_length < remaining_space) {
+			/* still not enough data to encrypt this time either */
+			_copy(&s->leftover[s->leftover_offset], data_length, data, data_length);
+			s->leftover_offset += data_length;
+			return TC_CRYPTO_SUCCESS;
+		}
+		/* leftover block is now full; encrypt it first */
+		_copy(&s->leftover[s->leftover_offset],
+		      remaining_space,
+		      data,
+		      remaining_space);
+		data_length -= remaining_space;
+		data += remaining_space;
+		s->leftover_offset = 0;
+
+		for (i = 0; i < TC_AES_BLOCK_SIZE; ++i) {
+			s->iv[i] ^= s->leftover[i];
+		}
+		tc_aes_encrypt(s->iv, s->iv, s->sched);
+	}
+
+	/* CBC encrypt each (except the last) of the data blocks */
+	while (data_length > TC_AES_BLOCK_SIZE) {
+		for (i = 0; i < TC_AES_BLOCK_SIZE; ++i) {
+			s->iv[i] ^= data[i];
+		}
+		tc_aes_encrypt(s->iv, s->iv, s->sched);
+		data += TC_AES_BLOCK_SIZE;
+		data_length  -= TC_AES_BLOCK_SIZE;
+	}
+
+	if (data_length > 0) {
+		/* save leftover data for next time */
+		_copy(s->leftover, data_length, data, data_length);
+		s->leftover_offset = data_length;
+	}
+
+	return TC_CRYPTO_SUCCESS;
+}
+
+int tc_cmac_final(uint8_t *tag, TCCmacState_t s)
+{
+	uint8_t *k;
+	unsigned int i;
+
+	/* input sanity check: */
+	if (tag == (uint8_t *) 0 ||
+	    s == (TCCmacState_t) 0) {
+		return TC_CRYPTO_FAIL;
+	}
+
+	if (s->leftover_offset == TC_AES_BLOCK_SIZE) {
+		/* the last message block is a full-sized block */
+		k = (uint8_t *) s->K1;
+	} else {
+		/* the final message block is not a full-sized  block */
+		size_t remaining = TC_AES_BLOCK_SIZE - s->leftover_offset;
+
+		_set(&s->leftover[s->leftover_offset], 0, remaining);
+		s->leftover[s->leftover_offset] = TC_CMAC_PADDING;
+		k = (uint8_t *) s->K2;
+	}
+	for (i = 0; i < TC_AES_BLOCK_SIZE; ++i) {
+		s->iv[i] ^= s->leftover[i] ^ k[i];
+	}
+
+	tc_aes_encrypt(tag, s->iv, s->sched);
+
+	/* erasing state: */
+	tc_cmac_erase(s);
+
+	return TC_CRYPTO_SUCCESS;
+}

+ 85 - 0
components/bt/porting/ext/tinycrypt/src/ctr_mode.c

@@ -0,0 +1,85 @@
+/* ctr_mode.c - TinyCrypt CTR mode implementation */
+
+/*
+ *  Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *    - 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 Intel Corporation nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 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.
+ */
+
+#include <tinycrypt/constants.h>
+#include <tinycrypt/ctr_mode.h>
+#include <tinycrypt/utils.h>
+
+int tc_ctr_mode(uint8_t *out, unsigned int outlen, const uint8_t *in,
+		unsigned int inlen, uint8_t *ctr, const TCAesKeySched_t sched)
+{
+
+	uint8_t buffer[TC_AES_BLOCK_SIZE];
+	uint8_t nonce[TC_AES_BLOCK_SIZE];
+	unsigned int block_num;
+	unsigned int i;
+
+	/* input sanity check: */
+	if (out == (uint8_t *) 0 ||
+	    in == (uint8_t *) 0 ||
+	    ctr == (uint8_t *) 0 ||
+	    sched == (TCAesKeySched_t) 0 ||
+	    inlen == 0 ||
+	    outlen == 0 ||
+	    outlen != inlen) {
+		return TC_CRYPTO_FAIL;
+	}
+
+	/* copy the ctr to the nonce */
+	(void)_copy(nonce, sizeof(nonce), ctr, sizeof(nonce));
+
+	/* select the last 4 bytes of the nonce to be incremented */
+	block_num = (nonce[12] << 24) | (nonce[13] << 16) |
+		    (nonce[14] << 8) | (nonce[15]);
+	for (i = 0; i < inlen; ++i) {
+		if ((i % (TC_AES_BLOCK_SIZE)) == 0) {
+			/* encrypt data using the current nonce */
+			if (tc_aes_encrypt(buffer, nonce, sched)) {
+				block_num++;
+				nonce[12] = (uint8_t)(block_num >> 24);
+				nonce[13] = (uint8_t)(block_num >> 16);
+				nonce[14] = (uint8_t)(block_num >> 8);
+				nonce[15] = (uint8_t)(block_num);
+			} else {
+				return TC_CRYPTO_FAIL;
+			}
+		}
+		/* update the output */
+		*out++ = buffer[i%(TC_AES_BLOCK_SIZE)] ^ *in++;
+	}
+
+	/* update the counter */
+	ctr[12] = nonce[12]; ctr[13] = nonce[13];
+	ctr[14] = nonce[14]; ctr[15] = nonce[15];
+
+	return TC_CRYPTO_SUCCESS;
+}

+ 279 - 0
components/bt/porting/ext/tinycrypt/src/ctr_prng.c

@@ -0,0 +1,279 @@
+/* ctr_prng.c - TinyCrypt implementation of CTR-PRNG */
+
+/*
+ * Copyright (c) 2016, Chris Morrison
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <tinycrypt/ctr_prng.h>
+#include <tinycrypt/utils.h>
+#include <tinycrypt/constants.h>
+#include <string.h>
+
+/*
+ * This PRNG is based on the CTR_DRBG described in Recommendation for Random
+ * Number Generation Using Deterministic Random Bit Generators,
+ * NIST SP 800-90A Rev. 1.
+ *
+ * Annotations to particular steps (e.g. 10.2.1.2 Step 1) refer to the steps
+ * described in that document.
+ *
+ */
+
+/**
+ *  @brief Array incrementer
+ *  Treats the supplied array as one contiguous number (MSB in arr[0]), and
+ *  increments it by one
+ *  @return none
+ *  @param arr IN/OUT -- array to be incremented
+ *  @param len IN -- size of arr in bytes
+ */
+static void arrInc(uint8_t arr[], unsigned int len)
+{
+	unsigned int i;
+	if (0 != arr) {
+		for (i = len; i > 0U; i--) {
+			if (++arr[i-1] != 0U) {
+				break;
+			}
+		}
+	}
+}
+
+/**
+ *  @brief CTR PRNG update
+ *  Updates the internal state of supplied the CTR PRNG context
+ *  increments it by one
+ *  @return none
+ *  @note Assumes: providedData is (TC_AES_KEY_SIZE + TC_AES_BLOCK_SIZE) bytes long
+ *  @param ctx IN/OUT -- CTR PRNG state
+ *  @param providedData IN -- data used when updating the internal state
+ */
+static void tc_ctr_prng_update(TCCtrPrng_t * const ctx, uint8_t const * const providedData)
+{
+	if (0 != ctx) {
+		/* 10.2.1.2 step 1 */
+		uint8_t temp[TC_AES_KEY_SIZE + TC_AES_BLOCK_SIZE];
+		unsigned int len = 0U;
+
+		/* 10.2.1.2 step 2 */
+		while (len < sizeof temp) {
+			unsigned int blocklen = sizeof(temp) - len;
+			uint8_t output_block[TC_AES_BLOCK_SIZE];
+
+			/* 10.2.1.2 step 2.1 */
+			arrInc(ctx->V, sizeof ctx->V);
+
+			/* 10.2.1.2 step 2.2 */
+			if (blocklen > TC_AES_BLOCK_SIZE) {
+				blocklen = TC_AES_BLOCK_SIZE;
+			}
+			(void)tc_aes_encrypt(output_block, ctx->V, &ctx->key);
+
+			/* 10.2.1.2 step 2.3/step 3 */
+			memcpy(&(temp[len]), output_block, blocklen);
+
+			len += blocklen;
+		}
+
+		/* 10.2.1.2 step 4 */
+		if (0 != providedData) {
+			unsigned int i;
+			for (i = 0U; i < sizeof temp; i++) {
+				temp[i] ^= providedData[i];
+			}
+		}
+
+		/* 10.2.1.2 step 5 */
+		(void)tc_aes128_set_encrypt_key(&ctx->key, temp);
+
+		/* 10.2.1.2 step 6 */
+		memcpy(ctx->V, &(temp[TC_AES_KEY_SIZE]), TC_AES_BLOCK_SIZE);
+	}
+}
+
+int tc_ctr_prng_init(TCCtrPrng_t * const ctx,
+		     uint8_t const * const entropy,
+		     unsigned int entropyLen,
+		     uint8_t const * const personalization,
+		     unsigned int pLen)
+{
+	int result = TC_CRYPTO_FAIL;
+	unsigned int i;
+	uint8_t personalization_buf[TC_AES_KEY_SIZE + TC_AES_BLOCK_SIZE] = {0U};
+	uint8_t seed_material[TC_AES_KEY_SIZE + TC_AES_BLOCK_SIZE];
+	uint8_t zeroArr[TC_AES_BLOCK_SIZE] = {0U};
+
+	if (0 != personalization) {
+		/* 10.2.1.3.1 step 1 */
+		unsigned int len = pLen;
+		if (len > sizeof personalization_buf) {
+			len = sizeof personalization_buf;
+		}
+
+		/* 10.2.1.3.1 step 2 */
+		memcpy(personalization_buf, personalization, len);
+	}
+
+	if ((0 != ctx) && (0 != entropy) && (entropyLen >= sizeof seed_material)) {
+		/* 10.2.1.3.1 step 3 */
+		memcpy(seed_material, entropy, sizeof seed_material);
+		for (i = 0U; i < sizeof seed_material; i++) {
+			seed_material[i] ^= personalization_buf[i];
+		}
+
+		/* 10.2.1.3.1 step 4 */
+		(void)tc_aes128_set_encrypt_key(&ctx->key, zeroArr);
+
+		/* 10.2.1.3.1 step 5 */
+		memset(ctx->V,   0x00, sizeof ctx->V);
+
+		/* 10.2.1.3.1 step 6 */
+		tc_ctr_prng_update(ctx, seed_material);
+
+		/* 10.2.1.3.1 step 7 */
+		ctx->reseedCount = 1U;
+
+		result = TC_CRYPTO_SUCCESS;
+	}
+	return result;
+}
+
+int tc_ctr_prng_reseed(TCCtrPrng_t * const ctx,
+			uint8_t const * const entropy,
+			unsigned int entropyLen,
+			uint8_t const * const additional_input,
+			unsigned int additionallen)
+{
+	unsigned int i;
+	int result = TC_CRYPTO_FAIL;
+	uint8_t additional_input_buf[TC_AES_KEY_SIZE + TC_AES_BLOCK_SIZE] = {0U};
+	uint8_t seed_material[TC_AES_KEY_SIZE + TC_AES_BLOCK_SIZE];
+
+	if (0 != additional_input) {
+		/* 10.2.1.4.1 step 1 */
+		unsigned int len = additionallen;
+		if (len > sizeof additional_input_buf) {
+			len = sizeof additional_input_buf;
+		}
+
+		/* 10.2.1.4.1 step 2 */
+		memcpy(additional_input_buf, additional_input, len);
+	}
+
+	unsigned int seedlen = (unsigned int)TC_AES_KEY_SIZE + (unsigned int)TC_AES_BLOCK_SIZE;
+	if ((0 != ctx) && (entropyLen >= seedlen)) {
+		/* 10.2.1.4.1 step 3 */
+		memcpy(seed_material, entropy, sizeof seed_material);
+		for (i = 0U; i < sizeof seed_material; i++) {
+			seed_material[i] ^= additional_input_buf[i];
+		}
+
+		/* 10.2.1.4.1 step 4 */
+		tc_ctr_prng_update(ctx, seed_material);
+
+		/* 10.2.1.4.1 step 5 */
+		ctx->reseedCount = 1U;
+
+		result = TC_CRYPTO_SUCCESS;
+	}
+	return result;
+}
+
+int tc_ctr_prng_generate(TCCtrPrng_t * const ctx,
+			uint8_t const * const additional_input,
+			unsigned int additionallen,
+			uint8_t * const out,
+			unsigned int outlen)
+{
+	/* 2^48 - see section 10.2.1 */
+	static const uint64_t MAX_REQS_BEFORE_RESEED = 0x1000000000000ULL;
+
+	/* 2^19 bits - see section 10.2.1 */
+	static const unsigned int MAX_BYTES_PER_REQ = 65536U;
+
+	unsigned int result = TC_CRYPTO_FAIL;
+
+	if ((0 != ctx) && (0 != out) && (outlen < MAX_BYTES_PER_REQ)) {
+		/* 10.2.1.5.1 step 1 */
+		if (ctx->reseedCount > MAX_REQS_BEFORE_RESEED) {
+			result = TC_CTR_PRNG_RESEED_REQ;
+		} else {
+			uint8_t additional_input_buf[TC_AES_KEY_SIZE + TC_AES_BLOCK_SIZE] = {0U};
+			if (0 != additional_input) {
+				/* 10.2.1.5.1 step 2  */
+				unsigned int len = additionallen;
+				if (len > sizeof additional_input_buf) {
+					len = sizeof additional_input_buf;
+				}
+				memcpy(additional_input_buf, additional_input, len);
+				tc_ctr_prng_update(ctx, additional_input_buf);
+			}
+
+			/* 10.2.1.5.1 step 3 - implicit */
+
+			/* 10.2.1.5.1 step 4 */
+			unsigned int len = 0U;
+			while (len < outlen) {
+				unsigned int blocklen = outlen - len;
+				uint8_t output_block[TC_AES_BLOCK_SIZE];
+
+				/* 10.2.1.5.1 step 4.1 */
+				arrInc(ctx->V, sizeof ctx->V);
+
+				/* 10.2.1.5.1 step 4.2 */
+				(void)tc_aes_encrypt(output_block, ctx->V, &ctx->key);
+
+				/* 10.2.1.5.1 step 4.3/step 5 */
+				if (blocklen > TC_AES_BLOCK_SIZE) {
+					blocklen = TC_AES_BLOCK_SIZE;
+				}
+				memcpy(&(out[len]), output_block, blocklen);
+
+				len += blocklen;
+			}
+
+			/* 10.2.1.5.1 step 6 */
+			tc_ctr_prng_update(ctx, additional_input_buf);
+
+			/* 10.2.1.5.1 step 7 */
+			ctx->reseedCount++;
+
+			/* 10.2.1.5.1 step 8 */
+			result = TC_CRYPTO_SUCCESS;
+		}
+	}
+
+	return result;
+}
+
+void tc_ctr_prng_uninstantiate(TCCtrPrng_t * const ctx)
+{
+	if (0 != ctx) {
+		memset(ctx->key.words, 0x00, sizeof ctx->key.words);
+		memset(ctx->V,         0x00, sizeof ctx->V);
+		ctx->reseedCount = 0U;
+	}
+}

+ 939 - 0
components/bt/porting/ext/tinycrypt/src/ecc.c

@@ -0,0 +1,939 @@
+/* ecc.c - TinyCrypt implementation of common ECC functions */
+
+/*
+ * Copyright (c) 2014, Kenneth MacKay
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *    - 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 Intel Corporation nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 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.
+ */
+
+#include <tinycrypt/ecc.h>
+#include <tinycrypt/ecc_platform_specific.h>
+#include <string.h>
+
+/* IMPORTANT: Make sure a cryptographically-secure PRNG is set and the platform
+ * has access to enough entropy in order to feed the PRNG regularly. */
+#if default_RNG_defined
+static uECC_RNG_Function g_rng_function = &default_CSPRNG;
+#else
+static uECC_RNG_Function g_rng_function = 0;
+#endif
+
+void uECC_set_rng(uECC_RNG_Function rng_function)
+{
+	g_rng_function = rng_function;
+}
+
+uECC_RNG_Function uECC_get_rng(void)
+{
+	return g_rng_function;
+}
+
+int uECC_curve_private_key_size(uECC_Curve curve)
+{
+	return BITS_TO_BYTES(curve->num_n_bits);
+}
+
+int uECC_curve_public_key_size(uECC_Curve curve)
+{
+	return 2 * curve->num_bytes;
+}
+
+void uECC_vli_clear(uECC_word_t *vli, wordcount_t num_words)
+{
+	wordcount_t i;
+	for (i = 0; i < num_words; ++i) {
+		 vli[i] = 0;
+	}
+}
+
+uECC_word_t uECC_vli_isZero(const uECC_word_t *vli, wordcount_t num_words)
+{
+	uECC_word_t bits = 0;
+	wordcount_t i;
+	for (i = 0; i < num_words; ++i) {
+		bits |= vli[i];
+	}
+	return (bits == 0);
+}
+
+uECC_word_t uECC_vli_testBit(const uECC_word_t *vli, bitcount_t bit)
+{
+	return (vli[bit >> uECC_WORD_BITS_SHIFT] &
+		((uECC_word_t)1 << (bit & uECC_WORD_BITS_MASK)));
+}
+
+/* Counts the number of words in vli. */
+static wordcount_t vli_numDigits(const uECC_word_t *vli,
+				 const wordcount_t max_words)
+{
+
+	wordcount_t i;
+	/* Search from the end until we find a non-zero digit. We do it in reverse
+	 * because we expect that most digits will be nonzero. */
+	for (i = max_words - 1; i >= 0 && vli[i] == 0; --i) {
+	}
+
+	return (i + 1);
+}
+
+bitcount_t uECC_vli_numBits(const uECC_word_t *vli,
+			    const wordcount_t max_words)
+{
+
+	uECC_word_t i;
+	uECC_word_t digit;
+
+	wordcount_t num_digits = vli_numDigits(vli, max_words);
+	if (num_digits == 0) {
+		return 0;
+	}
+
+	digit = vli[num_digits - 1];
+	for (i = 0; digit; ++i) {
+		digit >>= 1;
+	}
+
+	return (((bitcount_t)(num_digits - 1) << uECC_WORD_BITS_SHIFT) + i);
+}
+
+void uECC_vli_set(uECC_word_t *dest, const uECC_word_t *src,
+		  wordcount_t num_words)
+{
+	wordcount_t i;
+
+	for (i = 0; i < num_words; ++i) {
+		dest[i] = src[i];
+  	}
+}
+
+cmpresult_t uECC_vli_cmp_unsafe(const uECC_word_t *left,
+				const uECC_word_t *right,
+				wordcount_t num_words)
+{
+	wordcount_t i;
+
+	for (i = num_words - 1; i >= 0; --i) {
+		if (left[i] > right[i]) {
+			return 1;
+		} else if (left[i] < right[i]) {
+			return -1;
+		}
+	}
+	return 0;
+}
+
+uECC_word_t uECC_vli_equal(const uECC_word_t *left, const uECC_word_t *right,
+			   wordcount_t num_words)
+{
+
+	uECC_word_t diff = 0;
+	wordcount_t i;
+
+	for (i = num_words - 1; i >= 0; --i) {
+		diff |= (left[i] ^ right[i]);
+	}
+	return !(diff == 0);
+}
+
+uECC_word_t cond_set(uECC_word_t p_true, uECC_word_t p_false, unsigned int cond)
+{
+	return (p_true*(cond)) | (p_false*(!cond));
+}
+
+/* Computes result = left - right, returning borrow, in constant time.
+ * Can modify in place. */
+uECC_word_t uECC_vli_sub(uECC_word_t *result, const uECC_word_t *left,
+			 const uECC_word_t *right, wordcount_t num_words)
+{
+	uECC_word_t borrow = 0;
+	wordcount_t i;
+	for (i = 0; i < num_words; ++i) {
+		uECC_word_t diff = left[i] - right[i] - borrow;
+		uECC_word_t val = (diff > left[i]);
+		borrow = cond_set(val, borrow, (diff != left[i]));
+
+		result[i] = diff;
+	}
+	return borrow;
+}
+
+/* Computes result = left + right, returning carry, in constant time.
+ * Can modify in place. */
+static uECC_word_t uECC_vli_add(uECC_word_t *result, const uECC_word_t *left,
+				const uECC_word_t *right, wordcount_t num_words)
+{
+	uECC_word_t carry = 0;
+	wordcount_t i;
+	for (i = 0; i < num_words; ++i) {
+		uECC_word_t sum = left[i] + right[i] + carry;
+		uECC_word_t val = (sum < left[i]);
+		carry = cond_set(val, carry, (sum != left[i]));
+		result[i] = sum;
+	}
+	return carry;
+}
+
+cmpresult_t uECC_vli_cmp(const uECC_word_t *left, const uECC_word_t *right,
+			 wordcount_t num_words)
+{
+	uECC_word_t tmp[NUM_ECC_WORDS];
+	uECC_word_t neg = !!uECC_vli_sub(tmp, left, right, num_words);
+	uECC_word_t equal = uECC_vli_isZero(tmp, num_words);
+	return (!equal - 2 * neg);
+}
+
+/* Computes vli = vli >> 1. */
+static void uECC_vli_rshift1(uECC_word_t *vli, wordcount_t num_words)
+{
+	uECC_word_t *end = vli;
+	uECC_word_t carry = 0;
+
+	vli += num_words;
+	while (vli-- > end) {
+		uECC_word_t temp = *vli;
+		*vli = (temp >> 1) | carry;
+		carry = temp << (uECC_WORD_BITS - 1);
+	}
+}
+
+static void muladd(uECC_word_t a, uECC_word_t b, uECC_word_t *r0,
+		   uECC_word_t *r1, uECC_word_t *r2)
+{
+
+	uECC_dword_t p = (uECC_dword_t)a * b;
+	uECC_dword_t r01 = ((uECC_dword_t)(*r1) << uECC_WORD_BITS) | *r0;
+	r01 += p;
+	*r2 += (r01 < p);
+	*r1 = r01 >> uECC_WORD_BITS;
+	*r0 = (uECC_word_t)r01;
+
+}
+
+/* Computes result = left * right. Result must be 2 * num_words long. */
+static void uECC_vli_mult(uECC_word_t *result, const uECC_word_t *left,
+			  const uECC_word_t *right, wordcount_t num_words)
+{
+
+	uECC_word_t r0 = 0;
+	uECC_word_t r1 = 0;
+	uECC_word_t r2 = 0;
+	wordcount_t i, k;
+
+	/* Compute each digit of result in sequence, maintaining the carries. */
+	for (k = 0; k < num_words; ++k) {
+
+		for (i = 0; i <= k; ++i) {
+			muladd(left[i], right[k - i], &r0, &r1, &r2);
+		}
+
+		result[k] = r0;
+		r0 = r1;
+		r1 = r2;
+		r2 = 0;
+	}
+
+	for (k = num_words; k < num_words * 2 - 1; ++k) {
+
+		for (i = (k + 1) - num_words; i < num_words; ++i) {
+			muladd(left[i], right[k - i], &r0, &r1, &r2);
+		}
+		result[k] = r0;
+		r0 = r1;
+		r1 = r2;
+		r2 = 0;
+	}
+	result[num_words * 2 - 1] = r0;
+}
+
+void uECC_vli_modAdd(uECC_word_t *result, const uECC_word_t *left,
+		     const uECC_word_t *right, const uECC_word_t *mod,
+		     wordcount_t num_words)
+{
+	uECC_word_t carry = uECC_vli_add(result, left, right, num_words);
+	if (carry || uECC_vli_cmp_unsafe(mod, result, num_words) != 1) {
+	/* result > mod (result = mod + remainder), so subtract mod to get
+	 * remainder. */
+		uECC_vli_sub(result, result, mod, num_words);
+	}
+}
+
+void uECC_vli_modSub(uECC_word_t *result, const uECC_word_t *left,
+		     const uECC_word_t *right, const uECC_word_t *mod,
+		     wordcount_t num_words)
+{
+	uECC_word_t l_borrow = uECC_vli_sub(result, left, right, num_words);
+	if (l_borrow) {
+		/* In this case, result == -diff == (max int) - diff. Since -x % d == d - x,
+		 * we can get the correct result from result + mod (with overflow). */
+		uECC_vli_add(result, result, mod, num_words);
+	}
+}
+
+/* Computes result = product % mod, where product is 2N words long. */
+/* Currently only designed to work for curve_p or curve_n. */
+void uECC_vli_mmod(uECC_word_t *result, uECC_word_t *product,
+    		   const uECC_word_t *mod, wordcount_t num_words)
+{
+	uECC_word_t mod_multiple[2 * NUM_ECC_WORDS];
+	uECC_word_t tmp[2 * NUM_ECC_WORDS];
+	uECC_word_t *v[2] = {tmp, product};
+	uECC_word_t index;
+
+	/* Shift mod so its highest set bit is at the maximum position. */
+	bitcount_t shift = (num_words * 2 * uECC_WORD_BITS) -
+			   uECC_vli_numBits(mod, num_words);
+	wordcount_t word_shift = shift / uECC_WORD_BITS;
+	wordcount_t bit_shift = shift % uECC_WORD_BITS;
+	uECC_word_t carry = 0;
+	uECC_vli_clear(mod_multiple, word_shift);
+	if (bit_shift > 0) {
+		for(index = 0; index < (uECC_word_t)num_words; ++index) {
+			mod_multiple[word_shift + index] = (mod[index] << bit_shift) | carry;
+			carry = mod[index] >> (uECC_WORD_BITS - bit_shift);
+		}
+	} else {
+		uECC_vli_set(mod_multiple + word_shift, mod, num_words);
+	}
+
+	for (index = 1; shift >= 0; --shift) {
+		uECC_word_t borrow = 0;
+		wordcount_t i;
+		for (i = 0; i < num_words * 2; ++i) {
+			uECC_word_t diff = v[index][i] - mod_multiple[i] - borrow;
+			if (diff != v[index][i]) {
+				borrow = (diff > v[index][i]);
+			}
+			v[1 - index][i] = diff;
+		}
+		/* Swap the index if there was no borrow */
+		index = !(index ^ borrow);
+		uECC_vli_rshift1(mod_multiple, num_words);
+		mod_multiple[num_words - 1] |= mod_multiple[num_words] <<
+					       (uECC_WORD_BITS - 1);
+		uECC_vli_rshift1(mod_multiple + num_words, num_words);
+	}
+	uECC_vli_set(result, v[index], num_words);
+}
+
+void uECC_vli_modMult(uECC_word_t *result, const uECC_word_t *left,
+		      const uECC_word_t *right, const uECC_word_t *mod,
+		      wordcount_t num_words)
+{
+	uECC_word_t product[2 * NUM_ECC_WORDS];
+	uECC_vli_mult(product, left, right, num_words);
+	uECC_vli_mmod(result, product, mod, num_words);
+}
+
+void uECC_vli_modMult_fast(uECC_word_t *result, const uECC_word_t *left,
+			   const uECC_word_t *right, uECC_Curve curve)
+{
+	uECC_word_t product[2 * NUM_ECC_WORDS];
+	uECC_vli_mult(product, left, right, curve->num_words);
+
+	curve->mmod_fast(result, product);
+}
+
+static void uECC_vli_modSquare_fast(uECC_word_t *result,
+				    const uECC_word_t *left,
+				    uECC_Curve curve)
+{
+	uECC_vli_modMult_fast(result, left, left, curve);
+}
+
+
+#define EVEN(vli) (!(vli[0] & 1))
+
+static void vli_modInv_update(uECC_word_t *uv,
+			      const uECC_word_t *mod,
+			      wordcount_t num_words)
+{
+
+	uECC_word_t carry = 0;
+
+	if (!EVEN(uv)) {
+		carry = uECC_vli_add(uv, uv, mod, num_words);
+	}
+	uECC_vli_rshift1(uv, num_words);
+	if (carry) {
+		uv[num_words - 1] |= HIGH_BIT_SET;
+	}
+}
+
+void uECC_vli_modInv(uECC_word_t *result, const uECC_word_t *input,
+		     const uECC_word_t *mod, wordcount_t num_words)
+{
+	uECC_word_t a[NUM_ECC_WORDS], b[NUM_ECC_WORDS];
+	uECC_word_t u[NUM_ECC_WORDS], v[NUM_ECC_WORDS];
+	cmpresult_t cmpResult;
+
+	if (uECC_vli_isZero(input, num_words)) {
+		uECC_vli_clear(result, num_words);
+		return;
+	}
+
+	uECC_vli_set(a, input, num_words);
+	uECC_vli_set(b, mod, num_words);
+	uECC_vli_clear(u, num_words);
+	u[0] = 1;
+	uECC_vli_clear(v, num_words);
+	while ((cmpResult = uECC_vli_cmp_unsafe(a, b, num_words)) != 0) {
+		if (EVEN(a)) {
+			uECC_vli_rshift1(a, num_words);
+      			vli_modInv_update(u, mod, num_words);
+    		} else if (EVEN(b)) {
+			uECC_vli_rshift1(b, num_words);
+			vli_modInv_update(v, mod, num_words);
+		} else if (cmpResult > 0) {
+			uECC_vli_sub(a, a, b, num_words);
+			uECC_vli_rshift1(a, num_words);
+			if (uECC_vli_cmp_unsafe(u, v, num_words) < 0) {
+        			uECC_vli_add(u, u, mod, num_words);
+      			}
+      			uECC_vli_sub(u, u, v, num_words);
+      			vli_modInv_update(u, mod, num_words);
+    		} else {
+      			uECC_vli_sub(b, b, a, num_words);
+      			uECC_vli_rshift1(b, num_words);
+      			if (uECC_vli_cmp_unsafe(v, u, num_words) < 0) {
+        			uECC_vli_add(v, v, mod, num_words);
+      			}
+      			uECC_vli_sub(v, v, u, num_words);
+      			vli_modInv_update(v, mod, num_words);
+    		}
+  	}
+  	uECC_vli_set(result, u, num_words);
+}
+
+/* ------ Point operations ------ */
+
+void double_jacobian_default(uECC_word_t * X1, uECC_word_t * Y1,
+			     uECC_word_t * Z1, uECC_Curve curve)
+{
+	/* t1 = X, t2 = Y, t3 = Z */
+	uECC_word_t t4[NUM_ECC_WORDS];
+	uECC_word_t t5[NUM_ECC_WORDS];
+	wordcount_t num_words = curve->num_words;
+
+	if (uECC_vli_isZero(Z1, num_words)) {
+		return;
+	}
+
+	uECC_vli_modSquare_fast(t4, Y1, curve);   /* t4 = y1^2 */
+	uECC_vli_modMult_fast(t5, X1, t4, curve); /* t5 = x1*y1^2 = A */
+	uECC_vli_modSquare_fast(t4, t4, curve);   /* t4 = y1^4 */
+	uECC_vli_modMult_fast(Y1, Y1, Z1, curve); /* t2 = y1*z1 = z3 */
+	uECC_vli_modSquare_fast(Z1, Z1, curve);   /* t3 = z1^2 */
+
+	uECC_vli_modAdd(X1, X1, Z1, curve->p, num_words); /* t1 = x1 + z1^2 */
+	uECC_vli_modAdd(Z1, Z1, Z1, curve->p, num_words); /* t3 = 2*z1^2 */
+	uECC_vli_modSub(Z1, X1, Z1, curve->p, num_words); /* t3 = x1 - z1^2 */
+	uECC_vli_modMult_fast(X1, X1, Z1, curve); /* t1 = x1^2 - z1^4 */
+
+	uECC_vli_modAdd(Z1, X1, X1, curve->p, num_words); /* t3 = 2*(x1^2 - z1^4) */
+	uECC_vli_modAdd(X1, X1, Z1, curve->p, num_words); /* t1 = 3*(x1^2 - z1^4) */
+	if (uECC_vli_testBit(X1, 0)) {
+		uECC_word_t l_carry = uECC_vli_add(X1, X1, curve->p, num_words);
+		uECC_vli_rshift1(X1, num_words);
+		X1[num_words - 1] |= l_carry << (uECC_WORD_BITS - 1);
+	} else {
+		uECC_vli_rshift1(X1, num_words);
+	}
+
+	/* t1 = 3/2*(x1^2 - z1^4) = B */
+	uECC_vli_modSquare_fast(Z1, X1, curve); /* t3 = B^2 */
+	uECC_vli_modSub(Z1, Z1, t5, curve->p, num_words); /* t3 = B^2 - A */
+	uECC_vli_modSub(Z1, Z1, t5, curve->p, num_words); /* t3 = B^2 - 2A = x3 */
+	uECC_vli_modSub(t5, t5, Z1, curve->p, num_words); /* t5 = A - x3 */
+	uECC_vli_modMult_fast(X1, X1, t5, curve); /* t1 = B * (A - x3) */
+	/* t4 = B * (A - x3) - y1^4 = y3: */
+	uECC_vli_modSub(t4, X1, t4, curve->p, num_words);
+
+	uECC_vli_set(X1, Z1, num_words);
+	uECC_vli_set(Z1, Y1, num_words);
+	uECC_vli_set(Y1, t4, num_words);
+}
+
+void x_side_default(uECC_word_t *result,
+		    const uECC_word_t *x,
+		    uECC_Curve curve)
+{
+	uECC_word_t _3[NUM_ECC_WORDS] = {3}; /* -a = 3 */
+	wordcount_t num_words = curve->num_words;
+
+	uECC_vli_modSquare_fast(result, x, curve); /* r = x^2 */
+	uECC_vli_modSub(result, result, _3, curve->p, num_words); /* r = x^2 - 3 */
+	uECC_vli_modMult_fast(result, result, x, curve); /* r = x^3 - 3x */
+	/* r = x^3 - 3x + b: */
+	uECC_vli_modAdd(result, result, curve->b, curve->p, num_words);
+}
+
+uECC_Curve uECC_secp256r1(void)
+{
+	return &curve_secp256r1;
+}
+
+void vli_mmod_fast_secp256r1(unsigned int *result, unsigned int*product)
+{
+	unsigned int tmp[NUM_ECC_WORDS];
+	int carry;
+
+	/* t */
+	uECC_vli_set(result, product, NUM_ECC_WORDS);
+
+	/* s1 */
+	tmp[0] = tmp[1] = tmp[2] = 0;
+	tmp[3] = product[11];
+	tmp[4] = product[12];
+	tmp[5] = product[13];
+	tmp[6] = product[14];
+	tmp[7] = product[15];
+	carry = uECC_vli_add(tmp, tmp, tmp, NUM_ECC_WORDS);
+	carry += uECC_vli_add(result, result, tmp, NUM_ECC_WORDS);
+
+	/* s2 */
+	tmp[3] = product[12];
+	tmp[4] = product[13];
+	tmp[5] = product[14];
+	tmp[6] = product[15];
+	tmp[7] = 0;
+	carry += uECC_vli_add(tmp, tmp, tmp, NUM_ECC_WORDS);
+	carry += uECC_vli_add(result, result, tmp, NUM_ECC_WORDS);
+
+	/* s3 */
+	tmp[0] = product[8];
+	tmp[1] = product[9];
+	tmp[2] = product[10];
+	tmp[3] = tmp[4] = tmp[5] = 0;
+	tmp[6] = product[14];
+	tmp[7] = product[15];
+  	carry += uECC_vli_add(result, result, tmp, NUM_ECC_WORDS);
+
+	/* s4 */
+	tmp[0] = product[9];
+	tmp[1] = product[10];
+	tmp[2] = product[11];
+	tmp[3] = product[13];
+	tmp[4] = product[14];
+	tmp[5] = product[15];
+	tmp[6] = product[13];
+	tmp[7] = product[8];
+	carry += uECC_vli_add(result, result, tmp, NUM_ECC_WORDS);
+
+	/* d1 */
+	tmp[0] = product[11];
+	tmp[1] = product[12];
+	tmp[2] = product[13];
+	tmp[3] = tmp[4] = tmp[5] = 0;
+	tmp[6] = product[8];
+	tmp[7] = product[10];
+	carry -= uECC_vli_sub(result, result, tmp, NUM_ECC_WORDS);
+
+	/* d2 */
+	tmp[0] = product[12];
+	tmp[1] = product[13];
+	tmp[2] = product[14];
+	tmp[3] = product[15];
+	tmp[4] = tmp[5] = 0;
+	tmp[6] = product[9];
+	tmp[7] = product[11];
+	carry -= uECC_vli_sub(result, result, tmp, NUM_ECC_WORDS);
+
+	/* d3 */
+	tmp[0] = product[13];
+	tmp[1] = product[14];
+	tmp[2] = product[15];
+	tmp[3] = product[8];
+	tmp[4] = product[9];
+	tmp[5] = product[10];
+	tmp[6] = 0;
+	tmp[7] = product[12];
+	carry -= uECC_vli_sub(result, result, tmp, NUM_ECC_WORDS);
+
+	/* d4 */
+	tmp[0] = product[14];
+	tmp[1] = product[15];
+	tmp[2] = 0;
+	tmp[3] = product[9];
+	tmp[4] = product[10];
+	tmp[5] = product[11];
+	tmp[6] = 0;
+	tmp[7] = product[13];
+	carry -= uECC_vli_sub(result, result, tmp, NUM_ECC_WORDS);
+
+	if (carry < 0) {
+		do {
+			carry += uECC_vli_add(result, result, curve_secp256r1.p, NUM_ECC_WORDS);
+		}
+		while (carry < 0);
+	} else  {
+		while (carry ||
+		       uECC_vli_cmp_unsafe(curve_secp256r1.p, result, NUM_ECC_WORDS) != 1) {
+			carry -= uECC_vli_sub(result, result, curve_secp256r1.p, NUM_ECC_WORDS);
+		}
+	}
+}
+
+uECC_word_t EccPoint_isZero(const uECC_word_t *point, uECC_Curve curve)
+{
+	return uECC_vli_isZero(point, curve->num_words * 2);
+}
+
+void apply_z(uECC_word_t * X1, uECC_word_t * Y1, const uECC_word_t * const Z,
+	     uECC_Curve curve)
+{
+	uECC_word_t t1[NUM_ECC_WORDS];
+
+	uECC_vli_modSquare_fast(t1, Z, curve);    /* z^2 */
+	uECC_vli_modMult_fast(X1, X1, t1, curve); /* x1 * z^2 */
+	uECC_vli_modMult_fast(t1, t1, Z, curve);  /* z^3 */
+	uECC_vli_modMult_fast(Y1, Y1, t1, curve); /* y1 * z^3 */
+}
+
+/* P = (x1, y1) => 2P, (x2, y2) => P' */
+static void XYcZ_initial_double(uECC_word_t * X1, uECC_word_t * Y1,
+				uECC_word_t * X2, uECC_word_t * Y2,
+				const uECC_word_t * const initial_Z,
+				uECC_Curve curve)
+{
+	uECC_word_t z[NUM_ECC_WORDS];
+	wordcount_t num_words = curve->num_words;
+	if (initial_Z) {
+		uECC_vli_set(z, initial_Z, num_words);
+	} else {
+		uECC_vli_clear(z, num_words);
+		z[0] = 1;
+	}
+
+	uECC_vli_set(X2, X1, num_words);
+	uECC_vli_set(Y2, Y1, num_words);
+
+	apply_z(X1, Y1, z, curve);
+	curve->double_jacobian(X1, Y1, z, curve);
+	apply_z(X2, Y2, z, curve);
+}
+
+void XYcZ_add(uECC_word_t * X1, uECC_word_t * Y1,
+	      uECC_word_t * X2, uECC_word_t * Y2,
+	      uECC_Curve curve)
+{
+	/* t1 = X1, t2 = Y1, t3 = X2, t4 = Y2 */
+	uECC_word_t t5[NUM_ECC_WORDS];
+	wordcount_t num_words = curve->num_words;
+
+	uECC_vli_modSub(t5, X2, X1, curve->p, num_words); /* t5 = x2 - x1 */
+	uECC_vli_modSquare_fast(t5, t5, curve); /* t5 = (x2 - x1)^2 = A */
+	uECC_vli_modMult_fast(X1, X1, t5, curve); /* t1 = x1*A = B */
+	uECC_vli_modMult_fast(X2, X2, t5, curve); /* t3 = x2*A = C */
+	uECC_vli_modSub(Y2, Y2, Y1, curve->p, num_words); /* t4 = y2 - y1 */
+	uECC_vli_modSquare_fast(t5, Y2, curve); /* t5 = (y2 - y1)^2 = D */
+
+	uECC_vli_modSub(t5, t5, X1, curve->p, num_words); /* t5 = D - B */
+	uECC_vli_modSub(t5, t5, X2, curve->p, num_words); /* t5 = D - B - C = x3 */
+	uECC_vli_modSub(X2, X2, X1, curve->p, num_words); /* t3 = C - B */
+	uECC_vli_modMult_fast(Y1, Y1, X2, curve); /* t2 = y1*(C - B) */
+	uECC_vli_modSub(X2, X1, t5, curve->p, num_words); /* t3 = B - x3 */
+	uECC_vli_modMult_fast(Y2, Y2, X2, curve); /* t4 = (y2 - y1)*(B - x3) */
+	uECC_vli_modSub(Y2, Y2, Y1, curve->p, num_words); /* t4 = y3 */
+
+	uECC_vli_set(X2, t5, num_words);
+}
+
+/* Input P = (x1, y1, Z), Q = (x2, y2, Z)
+   Output P + Q = (x3, y3, Z3), P - Q = (x3', y3', Z3)
+   or P => P - Q, Q => P + Q
+ */
+static void XYcZ_addC(uECC_word_t * X1, uECC_word_t * Y1,
+		      uECC_word_t * X2, uECC_word_t * Y2,
+		      uECC_Curve curve)
+{
+	/* t1 = X1, t2 = Y1, t3 = X2, t4 = Y2 */
+	uECC_word_t t5[NUM_ECC_WORDS];
+	uECC_word_t t6[NUM_ECC_WORDS];
+	uECC_word_t t7[NUM_ECC_WORDS];
+	wordcount_t num_words = curve->num_words;
+
+	uECC_vli_modSub(t5, X2, X1, curve->p, num_words); /* t5 = x2 - x1 */
+	uECC_vli_modSquare_fast(t5, t5, curve); /* t5 = (x2 - x1)^2 = A */
+	uECC_vli_modMult_fast(X1, X1, t5, curve); /* t1 = x1*A = B */
+	uECC_vli_modMult_fast(X2, X2, t5, curve); /* t3 = x2*A = C */
+	uECC_vli_modAdd(t5, Y2, Y1, curve->p, num_words); /* t5 = y2 + y1 */
+	uECC_vli_modSub(Y2, Y2, Y1, curve->p, num_words); /* t4 = y2 - y1 */
+
+	uECC_vli_modSub(t6, X2, X1, curve->p, num_words); /* t6 = C - B */
+	uECC_vli_modMult_fast(Y1, Y1, t6, curve); /* t2 = y1 * (C - B) = E */
+	uECC_vli_modAdd(t6, X1, X2, curve->p, num_words); /* t6 = B + C */
+	uECC_vli_modSquare_fast(X2, Y2, curve); /* t3 = (y2 - y1)^2 = D */
+	uECC_vli_modSub(X2, X2, t6, curve->p, num_words); /* t3 = D - (B + C) = x3 */
+
+	uECC_vli_modSub(t7, X1, X2, curve->p, num_words); /* t7 = B - x3 */
+	uECC_vli_modMult_fast(Y2, Y2, t7, curve); /* t4 = (y2 - y1)*(B - x3) */
+	/* t4 = (y2 - y1)*(B - x3) - E = y3: */
+	uECC_vli_modSub(Y2, Y2, Y1, curve->p, num_words);
+
+	uECC_vli_modSquare_fast(t7, t5, curve); /* t7 = (y2 + y1)^2 = F */
+	uECC_vli_modSub(t7, t7, t6, curve->p, num_words); /* t7 = F - (B + C) = x3' */
+	uECC_vli_modSub(t6, t7, X1, curve->p, num_words); /* t6 = x3' - B */
+	uECC_vli_modMult_fast(t6, t6, t5, curve); /* t6 = (y2+y1)*(x3' - B) */
+	/* t2 = (y2+y1)*(x3' - B) - E = y3': */
+	uECC_vli_modSub(Y1, t6, Y1, curve->p, num_words);
+
+	uECC_vli_set(X1, t7, num_words);
+}
+
+void EccPoint_mult(uECC_word_t * result, const uECC_word_t * point,
+		   const uECC_word_t * scalar,
+		   const uECC_word_t * initial_Z,
+		   bitcount_t num_bits, uECC_Curve curve)
+{
+	/* R0 and R1 */
+	uECC_word_t Rx[2][NUM_ECC_WORDS];
+	uECC_word_t Ry[2][NUM_ECC_WORDS];
+	uECC_word_t z[NUM_ECC_WORDS];
+	bitcount_t i;
+	uECC_word_t nb;
+	wordcount_t num_words = curve->num_words;
+
+	uECC_vli_set(Rx[1], point, num_words);
+  	uECC_vli_set(Ry[1], point + num_words, num_words);
+
+	XYcZ_initial_double(Rx[1], Ry[1], Rx[0], Ry[0], initial_Z, curve);
+
+	for (i = num_bits - 2; i > 0; --i) {
+		nb = !uECC_vli_testBit(scalar, i);
+		XYcZ_addC(Rx[1 - nb], Ry[1 - nb], Rx[nb], Ry[nb], curve);
+		XYcZ_add(Rx[nb], Ry[nb], Rx[1 - nb], Ry[1 - nb], curve);
+	}
+
+	nb = !uECC_vli_testBit(scalar, 0);
+	XYcZ_addC(Rx[1 - nb], Ry[1 - nb], Rx[nb], Ry[nb], curve);
+
+	/* Find final 1/Z value. */
+	uECC_vli_modSub(z, Rx[1], Rx[0], curve->p, num_words); /* X1 - X0 */
+	uECC_vli_modMult_fast(z, z, Ry[1 - nb], curve); /* Yb * (X1 - X0) */
+	uECC_vli_modMult_fast(z, z, point, curve); /* xP * Yb * (X1 - X0) */
+	uECC_vli_modInv(z, z, curve->p, num_words); /* 1 / (xP * Yb * (X1 - X0))*/
+	/* yP / (xP * Yb * (X1 - X0)) */
+	uECC_vli_modMult_fast(z, z, point + num_words, curve);
+	/* Xb * yP / (xP * Yb * (X1 - X0)) */
+	uECC_vli_modMult_fast(z, z, Rx[1 - nb], curve);
+	/* End 1/Z calculation */
+
+	XYcZ_add(Rx[nb], Ry[nb], Rx[1 - nb], Ry[1 - nb], curve);
+	apply_z(Rx[0], Ry[0], z, curve);
+
+	uECC_vli_set(result, Rx[0], num_words);
+	uECC_vli_set(result + num_words, Ry[0], num_words);
+}
+
+uECC_word_t regularize_k(const uECC_word_t * const k, uECC_word_t *k0,
+			 uECC_word_t *k1, uECC_Curve curve)
+{
+
+	wordcount_t num_n_words = BITS_TO_WORDS(curve->num_n_bits);
+
+	bitcount_t num_n_bits = curve->num_n_bits;
+
+	uECC_word_t carry = uECC_vli_add(k0, k, curve->n, num_n_words) ||
+			     (num_n_bits < ((bitcount_t)num_n_words * uECC_WORD_SIZE * 8) &&
+			     uECC_vli_testBit(k0, num_n_bits));
+
+	uECC_vli_add(k1, k0, curve->n, num_n_words);
+
+	return carry;
+}
+
+uECC_word_t EccPoint_compute_public_key(uECC_word_t *result,
+					uECC_word_t *private_key,
+					uECC_Curve curve)
+{
+
+	uECC_word_t tmp1[NUM_ECC_WORDS];
+ 	uECC_word_t tmp2[NUM_ECC_WORDS];
+	uECC_word_t *p2[2] = {tmp1, tmp2};
+	uECC_word_t carry;
+
+	/* Regularize the bitcount for the private key so that attackers cannot
+	 * use a side channel attack to learn the number of leading zeros. */
+	carry = regularize_k(private_key, tmp1, tmp2, curve);
+
+	EccPoint_mult(result, curve->G, p2[!carry], 0, curve->num_n_bits + 1, curve);
+
+	if (EccPoint_isZero(result, curve)) {
+		return 0;
+	}
+	return 1;
+}
+
+/* Converts an integer in uECC native format to big-endian bytes. */
+void uECC_vli_nativeToBytes(uint8_t *bytes, int num_bytes,
+			    const unsigned int *native)
+{
+	wordcount_t i;
+	for (i = 0; i < num_bytes; ++i) {
+		unsigned b = num_bytes - 1 - i;
+		bytes[i] = native[b / uECC_WORD_SIZE] >> (8 * (b % uECC_WORD_SIZE));
+	}
+}
+
+/* Converts big-endian bytes to an integer in uECC native format. */
+void uECC_vli_bytesToNative(unsigned int *native, const uint8_t *bytes,
+			    int num_bytes)
+{
+	wordcount_t i;
+	uECC_vli_clear(native, (num_bytes + (uECC_WORD_SIZE - 1)) / uECC_WORD_SIZE);
+	for (i = 0; i < num_bytes; ++i) {
+		unsigned b = num_bytes - 1 - i;
+		native[b / uECC_WORD_SIZE] |=
+			(uECC_word_t)bytes[i] << (8 * (b % uECC_WORD_SIZE));
+  	}
+}
+
+int uECC_generate_random_int(uECC_word_t *random, const uECC_word_t *top,
+			     wordcount_t num_words)
+{
+	uECC_word_t mask = (uECC_word_t)-1;
+	uECC_word_t tries;
+	bitcount_t num_bits = uECC_vli_numBits(top, num_words);
+
+	if (!g_rng_function) {
+		return 0;
+	}
+
+	for (tries = 0; tries < uECC_RNG_MAX_TRIES; ++tries) {
+		if (!g_rng_function((uint8_t *)random, num_words * uECC_WORD_SIZE)) {
+      			return 0;
+    		}
+		random[num_words - 1] &=
+        		mask >> ((bitcount_t)(num_words * uECC_WORD_SIZE * 8 - num_bits));
+		if (!uECC_vli_isZero(random, num_words) &&
+			uECC_vli_cmp(top, random, num_words) == 1) {
+			return 1;
+		}
+	}
+	return 0;
+}
+
+
+int uECC_valid_point(const uECC_word_t *point, uECC_Curve curve)
+{
+	uECC_word_t tmp1[NUM_ECC_WORDS];
+	uECC_word_t tmp2[NUM_ECC_WORDS];
+	wordcount_t num_words = curve->num_words;
+
+	/* The point at infinity is invalid. */
+	if (EccPoint_isZero(point, curve)) {
+		return -1;
+	}
+
+	/* x and y must be smaller than p. */
+	if (uECC_vli_cmp_unsafe(curve->p, point, num_words) != 1 ||
+		uECC_vli_cmp_unsafe(curve->p, point + num_words, num_words) != 1) {
+		return -2;
+	}
+
+	uECC_vli_modSquare_fast(tmp1, point + num_words, curve);
+	curve->x_side(tmp2, point, curve); /* tmp2 = x^3 + ax + b */
+
+	/* Make sure that y^2 == x^3 + ax + b */
+	if (uECC_vli_equal(tmp1, tmp2, num_words) != 0)
+		return -3;
+
+	return 0;
+}
+
+int uECC_valid_public_key(const uint8_t *public_key, uECC_Curve curve)
+{
+
+	uECC_word_t _public[NUM_ECC_WORDS * 2];
+
+	uECC_vli_bytesToNative(_public, public_key, curve->num_bytes);
+	uECC_vli_bytesToNative(
+	_public + curve->num_words,
+	public_key + curve->num_bytes,
+	curve->num_bytes);
+
+	if (uECC_vli_cmp_unsafe(_public, curve->G, NUM_ECC_WORDS * 2) == 0) {
+		return -4;
+	}
+
+	return uECC_valid_point(_public, curve);
+}
+
+int uECC_compute_public_key(const uint8_t *private_key, uint8_t *public_key,
+			    uECC_Curve curve)
+{
+
+	uECC_word_t _private[NUM_ECC_WORDS];
+	uECC_word_t _public[NUM_ECC_WORDS * 2];
+
+	uECC_vli_bytesToNative(
+	_private,
+	private_key,
+	BITS_TO_BYTES(curve->num_n_bits));
+
+	/* Make sure the private key is in the range [1, n-1]. */
+	if (uECC_vli_isZero(_private, BITS_TO_WORDS(curve->num_n_bits))) {
+		return 0;
+	}
+
+	if (uECC_vli_cmp(curve->n, _private, BITS_TO_WORDS(curve->num_n_bits)) != 1) {
+		return 0;
+	}
+
+	/* Compute public key. */
+	if (!EccPoint_compute_public_key(_public, _private, curve)) {
+		return 0;
+	}
+
+	uECC_vli_nativeToBytes(public_key, curve->num_bytes, _public);
+	uECC_vli_nativeToBytes(
+	public_key +
+	curve->num_bytes, curve->num_bytes, _public + curve->num_words);
+	return 1;
+}

+ 200 - 0
components/bt/porting/ext/tinycrypt/src/ecc_dh.c

@@ -0,0 +1,200 @@
+/* ec_dh.c - TinyCrypt implementation of EC-DH */
+
+/*
+ * Copyright (c) 2014, Kenneth MacKay
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ *  Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *    - 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 Intel Corporation nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 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.
+ */
+#include <tinycrypt/constants.h>
+#include <tinycrypt/ecc.h>
+#include <tinycrypt/ecc_dh.h>
+#include <string.h>
+
+#if default_RNG_defined
+static uECC_RNG_Function g_rng_function = &default_CSPRNG;
+#else
+static uECC_RNG_Function g_rng_function = 0;
+#endif
+
+int uECC_make_key_with_d(uint8_t *public_key, uint8_t *private_key,
+			 unsigned int *d, uECC_Curve curve)
+{
+
+	uECC_word_t _private[NUM_ECC_WORDS];
+	uECC_word_t _public[NUM_ECC_WORDS * 2];
+
+	/* This function is designed for test purposes-only (such as validating NIST
+	 * test vectors) as it uses a provided value for d instead of generating
+	 * it uniformly at random. */
+	memcpy (_private, d, NUM_ECC_BYTES);
+
+	/* Computing public-key from private: */
+	if (EccPoint_compute_public_key(_public, _private, curve)) {
+
+		/* Converting buffers to correct bit order: */
+		uECC_vli_nativeToBytes(private_key,
+				       BITS_TO_BYTES(curve->num_n_bits),
+				       _private);
+		uECC_vli_nativeToBytes(public_key,
+				       curve->num_bytes,
+				       _public);
+		uECC_vli_nativeToBytes(public_key + curve->num_bytes,
+				       curve->num_bytes,
+				       _public + curve->num_words);
+
+		/* erasing temporary buffer used to store secret: */
+		memset(_private, 0, NUM_ECC_BYTES);
+
+		return 1;
+	}
+	return 0;
+}
+
+int uECC_make_key(uint8_t *public_key, uint8_t *private_key, uECC_Curve curve)
+{
+
+	uECC_word_t _random[NUM_ECC_WORDS * 2];
+	uECC_word_t _private[NUM_ECC_WORDS];
+	uECC_word_t _public[NUM_ECC_WORDS * 2];
+	uECC_word_t tries;
+
+	for (tries = 0; tries < uECC_RNG_MAX_TRIES; ++tries) {
+		/* Generating _private uniformly at random: */
+		uECC_RNG_Function rng_function = uECC_get_rng();
+		if (!rng_function ||
+			!rng_function((uint8_t *)_random, 2 * NUM_ECC_WORDS*uECC_WORD_SIZE)) {
+        		return 0;
+		}
+
+		/* computing modular reduction of _random (see FIPS 186.4 B.4.1): */
+		uECC_vli_mmod(_private, _random, curve->n, BITS_TO_WORDS(curve->num_n_bits));
+
+		/* Computing public-key from private: */
+		if (EccPoint_compute_public_key(_public, _private, curve)) {
+
+			/* Converting buffers to correct bit order: */
+			uECC_vli_nativeToBytes(private_key,
+					       BITS_TO_BYTES(curve->num_n_bits),
+					       _private);
+			uECC_vli_nativeToBytes(public_key,
+					       curve->num_bytes,
+					       _public);
+			uECC_vli_nativeToBytes(public_key + curve->num_bytes,
+ 					       curve->num_bytes,
+					       _public + curve->num_words);
+
+			/* erasing temporary buffer that stored secret: */
+			memset(_private, 0, NUM_ECC_BYTES);
+
+      			return 1;
+    		}
+  	}
+	return 0;
+}
+
+int uECC_shared_secret(const uint8_t *public_key, const uint8_t *private_key,
+		       uint8_t *secret, uECC_Curve curve)
+{
+
+	uECC_word_t _public[NUM_ECC_WORDS * 2];
+	uECC_word_t _private[NUM_ECC_WORDS];
+
+	uECC_word_t tmp[NUM_ECC_WORDS];
+	uECC_word_t *p2[2] = {_private, tmp};
+	uECC_word_t *initial_Z = 0;
+	uECC_word_t carry;
+	wordcount_t num_words = curve->num_words;
+	wordcount_t num_bytes = curve->num_bytes;
+	int r;
+
+	/* Converting buffers to correct bit order: */
+	uECC_vli_bytesToNative(_private,
+      			       private_key,
+			       BITS_TO_BYTES(curve->num_n_bits));
+	uECC_vli_bytesToNative(_public,
+      			       public_key,
+			       num_bytes);
+	uECC_vli_bytesToNative(_public + num_words,
+			       public_key + num_bytes,
+			       num_bytes);
+
+	/* Regularize the bitcount for the private key so that attackers cannot use a
+	 * side channel attack to learn the number of leading zeros. */
+	carry = regularize_k(_private, _private, tmp, curve);
+
+	/* If an RNG function was specified, try to get a random initial Z value to
+	 * improve protection against side-channel attacks. */
+	if (g_rng_function) {
+		if (!uECC_generate_random_int(p2[carry], curve->p, num_words)) {
+			r = 0;
+			goto clear_and_out;
+    		}
+    		initial_Z = p2[carry];
+  	}
+
+	EccPoint_mult(_public, _public, p2[!carry], initial_Z, curve->num_n_bits + 1,
+		      curve);
+
+	uECC_vli_nativeToBytes(secret, num_bytes, _public);
+	r = !EccPoint_isZero(_public, curve);
+
+clear_and_out:
+	/* erasing temporary buffer used to store secret: */
+	memset(p2, 0, sizeof(p2));
+	__asm__ __volatile__("" :: "g"(p2) : "memory");
+	memset(tmp, 0, sizeof(tmp));
+	__asm__ __volatile__("" :: "g"(tmp) : "memory");
+	memset(_private, 0, sizeof(_private));
+	__asm__ __volatile__("" :: "g"(_private) : "memory");
+
+	return r;
+}

+ 294 - 0
components/bt/porting/ext/tinycrypt/src/ecc_dsa.c

@@ -0,0 +1,294 @@
+/* ec_dsa.c - TinyCrypt implementation of EC-DSA */
+
+/* Copyright (c) 2014, Kenneth MacKay
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.*/
+
+/*
+ *  Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *    - 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 Intel Corporation nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 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.
+ */
+
+#include <tinycrypt/constants.h>
+#include <tinycrypt/ecc.h>
+#include <tinycrypt/ecc_dsa.h>
+
+#if default_RNG_defined
+static uECC_RNG_Function g_rng_function = &default_CSPRNG;
+#else
+static uECC_RNG_Function g_rng_function = 0;
+#endif
+
+static void bits2int(uECC_word_t *native, const uint8_t *bits,
+		     unsigned bits_size, uECC_Curve curve)
+{
+	unsigned num_n_bytes = BITS_TO_BYTES(curve->num_n_bits);
+	unsigned num_n_words = BITS_TO_WORDS(curve->num_n_bits);
+	int shift;
+	uECC_word_t carry;
+	uECC_word_t *ptr;
+
+	if (bits_size > num_n_bytes) {
+		bits_size = num_n_bytes;
+	}
+
+	uECC_vli_clear(native, num_n_words);
+	uECC_vli_bytesToNative(native, bits, bits_size);
+	if (bits_size * 8 <= (unsigned)curve->num_n_bits) {
+		return;
+	}
+	shift = bits_size * 8 - curve->num_n_bits;
+	carry = 0;
+	ptr = native + num_n_words;
+	while (ptr-- > native) {
+		uECC_word_t temp = *ptr;
+		*ptr = (temp >> shift) | carry;
+		carry = temp << (uECC_WORD_BITS - shift);
+	}
+
+	/* Reduce mod curve_n */
+	if (uECC_vli_cmp_unsafe(curve->n, native, num_n_words) != 1) {
+		uECC_vli_sub(native, native, curve->n, num_n_words);
+	}
+}
+
+int uECC_sign_with_k(const uint8_t *private_key, const uint8_t *message_hash,
+		     unsigned hash_size, uECC_word_t *k, uint8_t *signature,
+		     uECC_Curve curve)
+{
+
+	uECC_word_t tmp[NUM_ECC_WORDS];
+	uECC_word_t s[NUM_ECC_WORDS];
+	uECC_word_t *k2[2] = {tmp, s};
+	uECC_word_t p[NUM_ECC_WORDS * 2];
+	uECC_word_t carry;
+	wordcount_t num_words = curve->num_words;
+	wordcount_t num_n_words = BITS_TO_WORDS(curve->num_n_bits);
+	bitcount_t num_n_bits = curve->num_n_bits;
+
+	/* Make sure 0 < k < curve_n */
+  	if (uECC_vli_isZero(k, num_words) ||
+	    uECC_vli_cmp(curve->n, k, num_n_words) != 1) {
+		return 0;
+	}
+
+	carry = regularize_k(k, tmp, s, curve);
+	EccPoint_mult(p, curve->G, k2[!carry], 0, num_n_bits + 1, curve);
+	if (uECC_vli_isZero(p, num_words)) {
+		return 0;
+	}
+
+	/* If an RNG function was specified, get a random number
+	to prevent side channel analysis of k. */
+	if (!g_rng_function) {
+		uECC_vli_clear(tmp, num_n_words);
+		tmp[0] = 1;
+	}
+	else if (!uECC_generate_random_int(tmp, curve->n, num_n_words)) {
+		return 0;
+	}
+
+	/* Prevent side channel analysis of uECC_vli_modInv() to determine
+	bits of k / the private key by premultiplying by a random number */
+	uECC_vli_modMult(k, k, tmp, curve->n, num_n_words); /* k' = rand * k */
+	uECC_vli_modInv(k, k, curve->n, num_n_words);       /* k = 1 / k' */
+	uECC_vli_modMult(k, k, tmp, curve->n, num_n_words); /* k = 1 / k */
+
+	uECC_vli_nativeToBytes(signature, curve->num_bytes, p); /* store r */
+
+	/* tmp = d: */
+	uECC_vli_bytesToNative(tmp, private_key, BITS_TO_BYTES(curve->num_n_bits));
+
+	s[num_n_words - 1] = 0;
+	uECC_vli_set(s, p, num_words);
+	uECC_vli_modMult(s, tmp, s, curve->n, num_n_words); /* s = r*d */
+
+	bits2int(tmp, message_hash, hash_size, curve);
+	uECC_vli_modAdd(s, tmp, s, curve->n, num_n_words); /* s = e + r*d */
+	uECC_vli_modMult(s, s, k, curve->n, num_n_words);  /* s = (e + r*d) / k */
+	if (uECC_vli_numBits(s, num_n_words) > (bitcount_t)curve->num_bytes * 8) {
+		return 0;
+	}
+
+	uECC_vli_nativeToBytes(signature + curve->num_bytes, curve->num_bytes, s);
+	return 1;
+}
+
+int uECC_sign(const uint8_t *private_key, const uint8_t *message_hash,
+	      unsigned hash_size, uint8_t *signature, uECC_Curve curve)
+{
+	      uECC_word_t _random[2*NUM_ECC_WORDS];
+	      uECC_word_t k[NUM_ECC_WORDS];
+	      uECC_word_t tries;
+
+	for (tries = 0; tries < uECC_RNG_MAX_TRIES; ++tries) {
+		/* Generating _random uniformly at random: */
+		uECC_RNG_Function rng_function = uECC_get_rng();
+		if (!rng_function ||
+		    !rng_function((uint8_t *)_random, 2*NUM_ECC_WORDS*uECC_WORD_SIZE)) {
+			return 0;
+		}
+
+		// computing k as modular reduction of _random (see FIPS 186.4 B.5.1):
+		uECC_vli_mmod(k, _random, curve->n, BITS_TO_WORDS(curve->num_n_bits));
+
+		if (uECC_sign_with_k(private_key, message_hash, hash_size, k, signature,
+		    curve)) {
+			return 1;
+		}
+	}
+	return 0;
+}
+
+static bitcount_t smax(bitcount_t a, bitcount_t b)
+{
+	return (a > b ? a : b);
+}
+
+int uECC_verify(const uint8_t *public_key, const uint8_t *message_hash,
+		unsigned hash_size, const uint8_t *signature,
+	        uECC_Curve curve)
+{
+
+	uECC_word_t u1[NUM_ECC_WORDS], u2[NUM_ECC_WORDS];
+	uECC_word_t z[NUM_ECC_WORDS];
+	uECC_word_t sum[NUM_ECC_WORDS * 2];
+	uECC_word_t rx[NUM_ECC_WORDS];
+	uECC_word_t ry[NUM_ECC_WORDS];
+	uECC_word_t tx[NUM_ECC_WORDS];
+	uECC_word_t ty[NUM_ECC_WORDS];
+	uECC_word_t tz[NUM_ECC_WORDS];
+	const uECC_word_t *points[4];
+	const uECC_word_t *point;
+	bitcount_t num_bits;
+	bitcount_t i;
+
+	uECC_word_t _public[NUM_ECC_WORDS * 2];
+	uECC_word_t r[NUM_ECC_WORDS], s[NUM_ECC_WORDS];
+	wordcount_t num_words = curve->num_words;
+	wordcount_t num_n_words = BITS_TO_WORDS(curve->num_n_bits);
+
+	rx[num_n_words - 1] = 0;
+	r[num_n_words - 1] = 0;
+	s[num_n_words - 1] = 0;
+
+	uECC_vli_bytesToNative(_public, public_key, curve->num_bytes);
+	uECC_vli_bytesToNative(_public + num_words, public_key + curve->num_bytes,
+			       curve->num_bytes);
+	uECC_vli_bytesToNative(r, signature, curve->num_bytes);
+	uECC_vli_bytesToNative(s, signature + curve->num_bytes, curve->num_bytes);
+
+	/* r, s must not be 0. */
+	if (uECC_vli_isZero(r, num_words) || uECC_vli_isZero(s, num_words)) {
+		return 0;
+	}
+
+	/* r, s must be < n. */
+	if (uECC_vli_cmp_unsafe(curve->n, r, num_n_words) != 1 ||
+	    uECC_vli_cmp_unsafe(curve->n, s, num_n_words) != 1) {
+		return 0;
+	}
+
+	/* Calculate u1 and u2. */
+	uECC_vli_modInv(z, s, curve->n, num_n_words); /* z = 1/s */
+	u1[num_n_words - 1] = 0;
+	bits2int(u1, message_hash, hash_size, curve);
+	uECC_vli_modMult(u1, u1, z, curve->n, num_n_words); /* u1 = e/s */
+	uECC_vli_modMult(u2, r, z, curve->n, num_n_words); /* u2 = r/s */
+
+	/* Calculate sum = G + Q. */
+	uECC_vli_set(sum, _public, num_words);
+	uECC_vli_set(sum + num_words, _public + num_words, num_words);
+	uECC_vli_set(tx, curve->G, num_words);
+	uECC_vli_set(ty, curve->G + num_words, num_words);
+	uECC_vli_modSub(z, sum, tx, curve->p, num_words); /* z = x2 - x1 */
+	XYcZ_add(tx, ty, sum, sum + num_words, curve);
+	uECC_vli_modInv(z, z, curve->p, num_words); /* z = 1/z */
+	apply_z(sum, sum + num_words, z, curve);
+
+	/* Use Shamir's trick to calculate u1*G + u2*Q */
+	points[0] = 0;
+	points[1] = curve->G;
+	points[2] = _public;
+	points[3] = sum;
+	num_bits = smax(uECC_vli_numBits(u1, num_n_words),
+	uECC_vli_numBits(u2, num_n_words));
+
+	point = points[(!!uECC_vli_testBit(u1, num_bits - 1)) |
+                       ((!!uECC_vli_testBit(u2, num_bits - 1)) << 1)];
+	uECC_vli_set(rx, point, num_words);
+	uECC_vli_set(ry, point + num_words, num_words);
+	uECC_vli_clear(z, num_words);
+	z[0] = 1;
+
+	for (i = num_bits - 2; i >= 0; --i) {
+		uECC_word_t index;
+		curve->double_jacobian(rx, ry, z, curve);
+
+		index = (!!uECC_vli_testBit(u1, i)) | ((!!uECC_vli_testBit(u2, i)) << 1);
+		point = points[index];
+		if (point) {
+			uECC_vli_set(tx, point, num_words);
+			uECC_vli_set(ty, point + num_words, num_words);
+			apply_z(tx, ty, z, curve);
+			uECC_vli_modSub(tz, rx, tx, curve->p, num_words); /* Z = x2 - x1 */
+			XYcZ_add(tx, ty, rx, ry, curve);
+			uECC_vli_modMult_fast(z, z, tz, curve);
+		}
+  	}
+
+	uECC_vli_modInv(z, z, curve->p, num_words); /* Z = 1/Z */
+	apply_z(rx, ry, z, curve);
+
+	/* v = x1 (mod n) */
+	if (uECC_vli_cmp_unsafe(curve->n, rx, num_n_words) != 1) {
+		uECC_vli_sub(rx, rx, curve->n, num_n_words);
+	}
+
+	/* Accept only if v == r. */
+	return (int)(uECC_vli_equal(rx, r, num_words) == 0);
+}

+ 104 - 0
components/bt/porting/ext/tinycrypt/src/ecc_platform_specific.c

@@ -0,0 +1,104 @@
+/*  uECC_platform_specific.c - Implementation of platform specific functions*/
+
+/* Copyright (c) 2014, Kenneth MacKay
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.*/
+
+/*
+ *  Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *    - 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 Intel Corporation nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 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.
+ *
+ *  uECC_platform_specific.c -- Implementation of platform specific functions
+ */
+
+
+#if defined(unix) || defined(__linux__) || defined(__unix__) || \
+    defined(__unix) |  (defined(__APPLE__) && defined(__MACH__)) || \
+    defined(uECC_POSIX)
+
+/* Some POSIX-like system with /dev/urandom or /dev/random. */
+#include <sys/types.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <stdint.h>
+
+#ifndef O_CLOEXEC
+#define O_CLOEXEC 0
+#endif
+
+int default_CSPRNG(uint8_t *dest, unsigned int size) {
+
+  /* input sanity check: */
+  if (dest == (uint8_t *) 0 || (size <= 0))
+    return 0;
+
+  int fd = open("/dev/urandom", O_RDONLY | O_CLOEXEC);
+  if (fd == -1) {
+    fd = open("/dev/random", O_RDONLY | O_CLOEXEC);
+    if (fd == -1) {
+      return 0;
+    }
+  }
+
+  char *ptr = (char *)dest;
+  size_t left = (size_t) size;
+  while (left > 0) {
+    ssize_t bytes_read = read(fd, ptr, left);
+    if (bytes_read <= 0) { // read failed
+      close(fd);
+      return 0;
+    }
+    left -= bytes_read;
+    ptr += bytes_read;
+  }
+
+  close(fd);
+  return 1;
+}
+
+#endif /* platform */

+ 148 - 0
components/bt/porting/ext/tinycrypt/src/hmac.c

@@ -0,0 +1,148 @@
+/* hmac.c - TinyCrypt implementation of the HMAC algorithm */
+
+/*
+ *  Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *    - 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 Intel Corporation nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 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.
+ */
+
+#include <tinycrypt/hmac.h>
+#include <tinycrypt/constants.h>
+#include <tinycrypt/utils.h>
+
+static void rekey(uint8_t *key, const uint8_t *new_key, unsigned int key_size)
+{
+	const uint8_t inner_pad = (uint8_t) 0x36;
+	const uint8_t outer_pad = (uint8_t) 0x5c;
+	unsigned int i;
+
+	for (i = 0; i < key_size; ++i) {
+		key[i] = inner_pad ^ new_key[i];
+		key[i + TC_SHA256_BLOCK_SIZE] = outer_pad ^ new_key[i];
+	}
+	for (; i < TC_SHA256_BLOCK_SIZE; ++i) {
+		key[i] = inner_pad; key[i + TC_SHA256_BLOCK_SIZE] = outer_pad;
+	}
+}
+
+int tc_hmac_set_key(TCHmacState_t ctx, const uint8_t *key,
+		    unsigned int key_size)
+{
+
+	/* input sanity check: */
+	if (ctx == (TCHmacState_t) 0 ||
+	    key == (const uint8_t *) 0 ||
+	    key_size == 0) {
+		return TC_CRYPTO_FAIL;
+	}
+
+	const uint8_t dummy_key[key_size];
+	struct tc_hmac_state_struct dummy_state;
+
+	if (key_size <= TC_SHA256_BLOCK_SIZE) {
+		/*
+		 * The next three lines consist of dummy calls just to avoid
+		 * certain timing attacks. Without these dummy calls,
+		 * adversaries would be able to learn whether the key_size is
+		 * greater than TC_SHA256_BLOCK_SIZE by measuring the time
+		 * consumed in this process.
+		 */
+		(void)tc_sha256_init(&dummy_state.hash_state);
+		(void)tc_sha256_update(&dummy_state.hash_state,
+				       dummy_key,
+				       key_size);
+		(void)tc_sha256_final(&dummy_state.key[TC_SHA256_DIGEST_SIZE],
+				      &dummy_state.hash_state);
+
+		/* Actual code for when key_size <= TC_SHA256_BLOCK_SIZE: */
+		rekey(ctx->key, key, key_size);
+	} else {
+		(void)tc_sha256_init(&ctx->hash_state);
+		(void)tc_sha256_update(&ctx->hash_state, key, key_size);
+		(void)tc_sha256_final(&ctx->key[TC_SHA256_DIGEST_SIZE],
+				      &ctx->hash_state);
+		rekey(ctx->key,
+		      &ctx->key[TC_SHA256_DIGEST_SIZE],
+		      TC_SHA256_DIGEST_SIZE);
+	}
+
+	return TC_CRYPTO_SUCCESS;
+}
+
+int tc_hmac_init(TCHmacState_t ctx)
+{
+
+	/* input sanity check: */
+	if (ctx == (TCHmacState_t) 0) {
+		return TC_CRYPTO_FAIL;
+	}
+
+  (void) tc_sha256_init(&ctx->hash_state);
+  (void) tc_sha256_update(&ctx->hash_state, ctx->key, TC_SHA256_BLOCK_SIZE);
+
+	return TC_CRYPTO_SUCCESS;
+}
+
+int tc_hmac_update(TCHmacState_t ctx,
+		   const void *data,
+		   unsigned int data_length)
+{
+
+	/* input sanity check: */
+	if (ctx == (TCHmacState_t) 0) {
+		return TC_CRYPTO_FAIL;
+	}
+
+	(void)tc_sha256_update(&ctx->hash_state, data, data_length);
+
+	return TC_CRYPTO_SUCCESS;
+}
+
+int tc_hmac_final(uint8_t *tag, unsigned int taglen, TCHmacState_t ctx)
+{
+
+	/* input sanity check: */
+	if (tag == (uint8_t *) 0 ||
+	    taglen != TC_SHA256_DIGEST_SIZE ||
+	    ctx == (TCHmacState_t) 0) {
+		return TC_CRYPTO_FAIL;
+	}
+
+	(void) tc_sha256_final(tag, &ctx->hash_state);
+
+	(void)tc_sha256_init(&ctx->hash_state);
+	(void)tc_sha256_update(&ctx->hash_state,
+			       &ctx->key[TC_SHA256_BLOCK_SIZE],
+				TC_SHA256_BLOCK_SIZE);
+	(void)tc_sha256_update(&ctx->hash_state, tag, TC_SHA256_DIGEST_SIZE);
+	(void)tc_sha256_final(tag, &ctx->hash_state);
+
+	/* destroy the current state */
+	_set(ctx, 0, sizeof(*ctx));
+
+	return TC_CRYPTO_SUCCESS;
+}

+ 212 - 0
components/bt/porting/ext/tinycrypt/src/hmac_prng.c

@@ -0,0 +1,212 @@
+/* hmac_prng.c - TinyCrypt implementation of HMAC-PRNG */
+
+/*
+ *  Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *    - 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 Intel Corporation nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 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.
+ */
+
+#include <tinycrypt/hmac_prng.h>
+#include <tinycrypt/hmac.h>
+#include <tinycrypt/constants.h>
+#include <tinycrypt/utils.h>
+
+/*
+ * min bytes in the seed string.
+ * MIN_SLEN*8 must be at least the expected security level.
+ */
+static const unsigned int MIN_SLEN = 32;
+
+/*
+ * max bytes in the seed string;
+ * SP800-90A specifies a maximum of 2^35 bits (i.e., 2^32 bytes).
+ */
+static const unsigned int MAX_SLEN = UINT32_MAX;
+
+/*
+ * max bytes in the personalization string;
+ * SP800-90A specifies a maximum of 2^35 bits (i.e., 2^32 bytes).
+ */
+static const unsigned int MAX_PLEN = UINT32_MAX;
+
+/*
+ * max bytes in the additional_info string;
+ * SP800-90A specifies a maximum of 2^35 bits (i.e., 2^32 bytes).
+ */
+static const unsigned int MAX_ALEN = UINT32_MAX;
+
+/*
+ * max number of generates between re-seeds;
+ * TinyCrypt accepts up to (2^32 - 1) which is the maximal value of
+ * a 32-bit unsigned int variable, while SP800-90A specifies a maximum of 2^48.
+ */
+static const unsigned int MAX_GENS = UINT32_MAX;
+
+/*
+ * maximum bytes per generate call;
+ * SP800-90A specifies a maximum up to 2^19.
+ */
+static const unsigned int  MAX_OUT = (1 << 19);
+
+/*
+ * Assumes: prng != NULL, e != NULL, len >= 0.
+ */
+static void update(TCHmacPrng_t prng, const uint8_t *e, unsigned int len)
+{
+	const uint8_t separator0 = 0x00;
+	const uint8_t separator1 = 0x01;
+
+	/* use current state, e and separator 0 to compute a new prng key: */
+	(void)tc_hmac_init(&prng->h);
+	(void)tc_hmac_update(&prng->h, prng->v, sizeof(prng->v));
+	(void)tc_hmac_update(&prng->h, &separator0, sizeof(separator0));
+	(void)tc_hmac_update(&prng->h, e, len);
+	(void)tc_hmac_final(prng->key, sizeof(prng->key), &prng->h);
+	/* configure the new prng key into the prng's instance of hmac */
+	(void)tc_hmac_set_key(&prng->h, prng->key, sizeof(prng->key));
+
+	/* use the new key to compute a new state variable v */
+	(void)tc_hmac_init(&prng->h);
+	(void)tc_hmac_update(&prng->h, prng->v, sizeof(prng->v));
+	(void)tc_hmac_final(prng->v, sizeof(prng->v), &prng->h);
+
+	/* use current state, e and separator 1 to compute a new prng key: */
+	(void)tc_hmac_init(&prng->h);
+	(void)tc_hmac_update(&prng->h, prng->v, sizeof(prng->v));
+	(void)tc_hmac_update(&prng->h, &separator1, sizeof(separator1));
+	(void)tc_hmac_update(&prng->h, e, len);
+	(void)tc_hmac_final(prng->key, sizeof(prng->key), &prng->h);
+	/* configure the new prng key into the prng's instance of hmac */
+	(void)tc_hmac_set_key(&prng->h, prng->key, sizeof(prng->key));
+
+	/* use the new key to compute a new state variable v */
+	(void)tc_hmac_init(&prng->h);
+	(void)tc_hmac_update(&prng->h, prng->v, sizeof(prng->v));
+	(void)tc_hmac_final(prng->v, sizeof(prng->v), &prng->h);
+}
+
+int tc_hmac_prng_init(TCHmacPrng_t prng,
+		      const uint8_t *personalization,
+		      unsigned int plen)
+{
+
+	/* input sanity check: */
+	if (prng == (TCHmacPrng_t) 0 ||
+	    personalization == (uint8_t *) 0 ||
+	    plen > MAX_PLEN) {
+		return TC_CRYPTO_FAIL;
+	}
+
+	/* put the generator into a known state: */
+	_set(prng->key, 0x00, sizeof(prng->key));
+	_set(prng->v, 0x01, sizeof(prng->v));
+	tc_hmac_set_key(&prng->h, prng->key, sizeof(prng->key));
+	/* update assumes SOME key has been configured into HMAC */
+
+	update(prng, personalization, plen);
+
+	/* force a reseed before allowing tc_hmac_prng_generate to succeed: */
+	prng->countdown = 0;
+
+	return TC_CRYPTO_SUCCESS;
+}
+
+int tc_hmac_prng_reseed(TCHmacPrng_t prng,
+			const uint8_t *seed,
+			unsigned int seedlen,
+			const uint8_t *additional_input,
+			unsigned int additionallen)
+{
+
+	/* input sanity check: */
+	if (prng == (TCHmacPrng_t) 0 ||
+	    seed == (const uint8_t *) 0 ||
+	    seedlen < MIN_SLEN ||
+	    seedlen > MAX_SLEN) {
+		return TC_CRYPTO_FAIL;
+	}
+
+	if (additional_input != (const uint8_t *) 0) {
+		/*
+		 * Abort if additional_input is provided but has inappropriate
+		 * length
+		 */
+		if (additionallen == 0 ||
+		    additionallen > MAX_ALEN) {
+			return TC_CRYPTO_FAIL;
+		} else {
+		/* call update for the seed and additional_input */
+		update(prng, seed, seedlen);
+		update(prng, additional_input, additionallen);
+		}
+	} else {
+		/* call update only for the seed */
+		update(prng, seed, seedlen);
+	}
+
+	/* ... and enable hmac_prng_generate */
+	prng->countdown = MAX_GENS;
+
+	return TC_CRYPTO_SUCCESS;
+}
+
+int tc_hmac_prng_generate(uint8_t *out, unsigned int outlen, TCHmacPrng_t prng)
+{
+	unsigned int bufferlen;
+
+	/* input sanity check: */
+	if (out == (uint8_t *) 0 ||
+	    prng == (TCHmacPrng_t) 0 ||
+	    outlen == 0 ||
+	    outlen > MAX_OUT) {
+		return TC_CRYPTO_FAIL;
+	} else if (prng->countdown == 0) {
+		return TC_HMAC_PRNG_RESEED_REQ;
+	}
+
+	prng->countdown--;
+
+	while (outlen != 0) {
+		/* operate HMAC in OFB mode to create "random" outputs */
+		(void)tc_hmac_init(&prng->h);
+		(void)tc_hmac_update(&prng->h, prng->v, sizeof(prng->v));
+		(void)tc_hmac_final(prng->v, sizeof(prng->v), &prng->h);
+
+		bufferlen = (TC_SHA256_DIGEST_SIZE > outlen) ?
+			outlen : TC_SHA256_DIGEST_SIZE;
+		(void)_copy(out, bufferlen, prng->v, bufferlen);
+
+		out += bufferlen;
+		outlen = (outlen > TC_SHA256_DIGEST_SIZE) ?
+			(outlen - TC_SHA256_DIGEST_SIZE) : 0;
+	}
+
+	/* block future PRNG compromises from revealing past state */
+	update(prng, prng->v, TC_SHA256_DIGEST_SIZE);
+
+	return TC_CRYPTO_SUCCESS;
+}

+ 217 - 0
components/bt/porting/ext/tinycrypt/src/sha256.c

@@ -0,0 +1,217 @@
+/* sha256.c - TinyCrypt SHA-256 crypto hash algorithm implementation */
+
+/*
+ *  Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *    - 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 Intel Corporation nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 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.
+ */
+
+#include <tinycrypt/sha256.h>
+#include <tinycrypt/constants.h>
+#include <tinycrypt/utils.h>
+
+static void compress(unsigned int *iv, const uint8_t *data);
+
+int tc_sha256_init(TCSha256State_t s)
+{
+	/* input sanity check: */
+	if (s == (TCSha256State_t) 0) {
+		return TC_CRYPTO_FAIL;
+	}
+
+	/*
+	 * Setting the initial state values.
+	 * These values correspond to the first 32 bits of the fractional parts
+	 * of the square roots of the first 8 primes: 2, 3, 5, 7, 11, 13, 17
+	 * and 19.
+	 */
+	_set((uint8_t *) s, 0x00, sizeof(*s));
+	s->iv[0] = 0x6a09e667;
+	s->iv[1] = 0xbb67ae85;
+	s->iv[2] = 0x3c6ef372;
+	s->iv[3] = 0xa54ff53a;
+	s->iv[4] = 0x510e527f;
+	s->iv[5] = 0x9b05688c;
+	s->iv[6] = 0x1f83d9ab;
+	s->iv[7] = 0x5be0cd19;
+
+	return TC_CRYPTO_SUCCESS;
+}
+
+int tc_sha256_update(TCSha256State_t s, const uint8_t *data, size_t datalen)
+{
+	/* input sanity check: */
+	if (s == (TCSha256State_t) 0 ||
+	    data == (void *) 0) {
+		return TC_CRYPTO_FAIL;
+	} else if (datalen == 0) {
+		return TC_CRYPTO_SUCCESS;
+	}
+
+	while (datalen-- > 0) {
+		s->leftover[s->leftover_offset++] = *(data++);
+		if (s->leftover_offset >= TC_SHA256_BLOCK_SIZE) {
+			compress(s->iv, s->leftover);
+			s->leftover_offset = 0;
+			s->bits_hashed += (TC_SHA256_BLOCK_SIZE << 3);
+		}
+	}
+
+	return TC_CRYPTO_SUCCESS;
+}
+
+int tc_sha256_final(uint8_t *digest, TCSha256State_t s)
+{
+	unsigned int i;
+
+	/* input sanity check: */
+	if (digest == (uint8_t *) 0 ||
+	    s == (TCSha256State_t) 0) {
+		return TC_CRYPTO_FAIL;
+	}
+
+	s->bits_hashed += (s->leftover_offset << 3);
+
+	s->leftover[s->leftover_offset++] = 0x80; /* always room for one byte */
+	if (s->leftover_offset > (sizeof(s->leftover) - 8)) {
+		/* there is not room for all the padding in this block */
+		_set(s->leftover + s->leftover_offset, 0x00,
+		     sizeof(s->leftover) - s->leftover_offset);
+		compress(s->iv, s->leftover);
+		s->leftover_offset = 0;
+	}
+
+	/* add the padding and the length in big-Endian format */
+	_set(s->leftover + s->leftover_offset, 0x00,
+	     sizeof(s->leftover) - 8 - s->leftover_offset);
+	s->leftover[sizeof(s->leftover) - 1] = (uint8_t)(s->bits_hashed);
+	s->leftover[sizeof(s->leftover) - 2] = (uint8_t)(s->bits_hashed >> 8);
+	s->leftover[sizeof(s->leftover) - 3] = (uint8_t)(s->bits_hashed >> 16);
+	s->leftover[sizeof(s->leftover) - 4] = (uint8_t)(s->bits_hashed >> 24);
+	s->leftover[sizeof(s->leftover) - 5] = (uint8_t)(s->bits_hashed >> 32);
+	s->leftover[sizeof(s->leftover) - 6] = (uint8_t)(s->bits_hashed >> 40);
+	s->leftover[sizeof(s->leftover) - 7] = (uint8_t)(s->bits_hashed >> 48);
+	s->leftover[sizeof(s->leftover) - 8] = (uint8_t)(s->bits_hashed >> 56);
+
+	/* hash the padding and length */
+	compress(s->iv, s->leftover);
+
+	/* copy the iv out to digest */
+	for (i = 0; i < TC_SHA256_STATE_BLOCKS; ++i) {
+		unsigned int t = *((unsigned int *) &s->iv[i]);
+		*digest++ = (uint8_t)(t >> 24);
+		*digest++ = (uint8_t)(t >> 16);
+		*digest++ = (uint8_t)(t >> 8);
+		*digest++ = (uint8_t)(t);
+	}
+
+	/* destroy the current state */
+	_set(s, 0, sizeof(*s));
+
+	return TC_CRYPTO_SUCCESS;
+}
+
+/*
+ * Initializing SHA-256 Hash constant words K.
+ * These values correspond to the first 32 bits of the fractional parts of the
+ * cube roots of the first 64 primes between 2 and 311.
+ */
+static const unsigned int k256[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
+};
+
+static inline unsigned int ROTR(unsigned int a, unsigned int n)
+{
+	return (((a) >> n) | ((a) << (32 - n)));
+}
+
+#define Sigma0(a)(ROTR((a), 2) ^ ROTR((a), 13) ^ ROTR((a), 22))
+#define Sigma1(a)(ROTR((a), 6) ^ ROTR((a), 11) ^ ROTR((a), 25))
+#define sigma0(a)(ROTR((a), 7) ^ ROTR((a), 18) ^ ((a) >> 3))
+#define sigma1(a)(ROTR((a), 17) ^ ROTR((a), 19) ^ ((a) >> 10))
+
+#define Ch(a, b, c)(((a) & (b)) ^ ((~(a)) & (c)))
+#define Maj(a, b, c)(((a) & (b)) ^ ((a) & (c)) ^ ((b) & (c)))
+
+static inline unsigned int BigEndian(const uint8_t **c)
+{
+	unsigned int n = 0;
+
+	n = (((unsigned int)(*((*c)++))) << 24);
+	n |= ((unsigned int)(*((*c)++)) << 16);
+	n |= ((unsigned int)(*((*c)++)) << 8);
+	n |= ((unsigned int)(*((*c)++)));
+	return n;
+}
+
+static void compress(unsigned int *iv, const uint8_t *data)
+{
+	unsigned int a, b, c, d, e, f, g, h;
+	unsigned int s0, s1;
+	unsigned int t1, t2;
+	unsigned int work_space[16];
+	unsigned int n;
+	unsigned int i;
+
+	a = iv[0]; b = iv[1]; c = iv[2]; d = iv[3];
+	e = iv[4]; f = iv[5]; g = iv[6]; h = iv[7];
+
+	for (i = 0; i < 16; ++i) {
+		n = BigEndian(&data);
+		t1 = work_space[i] = n;
+		t1 += h + Sigma1(e) + Ch(e, f, g) + k256[i];
+		t2 = Sigma0(a) + Maj(a, b, c);
+		h = g; g = f; f = e; e = d + t1;
+		d = c; c = b; b = a; a = t1 + t2;
+	}
+
+	for ( ; i < 64; ++i) {
+		s0 = work_space[(i+1)&0x0f];
+		s0 = sigma0(s0);
+		s1 = work_space[(i+14)&0x0f];
+		s1 = sigma1(s1);
+
+		t1 = work_space[i&0xf] += s0 + s1 + work_space[(i+9)&0xf];
+		t1 += h + Sigma1(e) + Ch(e, f, g) + k256[i];
+		t2 = Sigma0(a) + Maj(a, b, c);
+		h = g; g = f; f = e; e = d + t1;
+		d = c; c = b; b = a; a = t1 + t2;
+	}
+
+	iv[0] += a; iv[1] += b; iv[2] += c; iv[3] += d;
+	iv[4] += e; iv[5] += f; iv[6] += g; iv[7] += h;
+}

+ 74 - 0
components/bt/porting/ext/tinycrypt/src/utils.c

@@ -0,0 +1,74 @@
+/* utils.c - TinyCrypt platform-dependent run-time operations */
+
+/*
+ *  Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *    - 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 Intel Corporation nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 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.
+ */
+
+#include <tinycrypt/utils.h>
+#include <tinycrypt/constants.h>
+
+#include <string.h>
+
+#define MASK_TWENTY_SEVEN 0x1b
+
+unsigned int _copy(uint8_t *to, unsigned int to_len,
+		   const uint8_t *from, unsigned int from_len)
+{
+	if (from_len <= to_len) {
+		(void)memcpy(to, from, from_len);
+		return from_len;
+	} else {
+		return TC_CRYPTO_FAIL;
+	}
+}
+
+void _set(void *to, uint8_t val, unsigned int len)
+{
+	(void)memset(to, val, len);
+}
+
+/*
+ * Doubles the value of a byte for values up to 127.
+ */
+uint8_t _double_byte(uint8_t a)
+{
+	return ((a<<1) ^ ((a>>7) * MASK_TWENTY_SEVEN));
+}
+
+int _compare(const uint8_t *a, const uint8_t *b, size_t size)
+{
+	const uint8_t *tempa = a;
+	const uint8_t *tempb = b;
+	uint8_t result = 0;
+
+	for (unsigned int i = 0; i < size; i++) {
+		result |= tempa[i] ^ tempb[i];
+	}
+	return result;
+}

+ 75 - 0
components/bt/porting/include/mem_api.h

@@ -0,0 +1,75 @@
+/*
+ * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if SOC_ESP_NIMBLE_CONTROLLER
+
+struct os_mempool;
+struct os_mbuf_pool;
+
+
+int r_mem_malloc_mempool(struct os_mempool *mempool, uint16_t num_blocks,
+                       uint32_t block_size, char *name, void **out_buf);
+#define mem_malloc_mempool r_mem_malloc_mempool
+
+int r_mem_malloc_mempool_ext(struct os_mempool_ext *mempool, uint16_t num_blocks,
+                           uint32_t block_size, char *name, void **out_buf);
+#define mem_malloc_mempool_ext r_mem_malloc_mempool_ext
+
+
+int r_mem_malloc_mbuf_pool(struct os_mempool *mempool,
+                         struct os_mbuf_pool *mbuf_pool, uint16_t num_blocks,
+                         uint32_t block_size, char *name,
+                         void **out_buf);
+#define mem_malloc_mbuf_pool r_mem_malloc_mbuf_pool
+
+int r_mem_malloc_mbufpkt_pool(struct os_mempool *mempool,
+                            struct os_mbuf_pool *mbuf_pool, int num_blocks,
+                            int block_size, char *name,
+                            void **out_buf);
+#define mem_malloc_mbufpkt_pool r_mem_malloc_mbufpkt_pool
+
+int r_mem_init_mbuf_pool(void *mem, struct os_mempool *mempool,
+                       struct os_mbuf_pool *mbuf_pool, int num_blocks,
+                       int block_size, const char *name);
+#define mem_init_mbuf_pool r_mem_init_mbuf_pool
+
+
+
+/**
+ * Specifies a function used as a callback.  Functions of this type allocate an
+ * mbuf chain meant to hold a packet fragment.  The resulting mbuf must contain
+ * a pkthdr.
+ *
+ * @param frag_size             The number of data bytes that the mbuf will
+ *                                  eventually contain.
+ * @param arg                   A generic parameter.
+ *
+ * @return                      An allocated mbuf chain on success;
+ *                              NULL on failure.
+ */
+typedef struct os_mbuf *mem_frag_alloc_fn(uint16_t frag_size, void *arg);
+
+
+
+struct os_mbuf *r_mem_split_frag(struct os_mbuf **om, uint16_t max_frag_sz,
+                               mem_frag_alloc_fn *alloc_cb, void *cb_arg);
+#define mem_split_frag r_mem_split_frag
+
+void *r_mem_pullup_obj(struct os_mbuf **om, uint16_t len);
+#define mem_pullup_obj r_mem_pullup_obj
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif

+ 13 - 4
components/bt/host/nimble/port/src/esp_nimble_mem.c → components/bt/porting/mem/bt_osi_mem.c

@@ -7,9 +7,8 @@
 #include "esp_attr.h"
 #include "esp_heap_caps.h"
 #include "sdkconfig.h"
-#include "esp_nimble_mem.h"
 
-IRAM_ATTR void *nimble_platform_mem_malloc(size_t size)
+IRAM_ATTR void *bt_osi_mem_malloc(size_t size)
 {
 #ifdef CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_INTERNAL
     return heap_caps_malloc(size, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT);
@@ -22,7 +21,7 @@ IRAM_ATTR void *nimble_platform_mem_malloc(size_t size)
 #endif
 }
 
-IRAM_ATTR void *nimble_platform_mem_calloc(size_t n, size_t size)
+IRAM_ATTR void *bt_osi_mem_calloc(size_t n, size_t size)
 {
 #ifdef CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_INTERNAL
     return heap_caps_calloc(n, size, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT);
@@ -35,7 +34,17 @@ IRAM_ATTR void *nimble_platform_mem_calloc(size_t n, size_t size)
 #endif
 }
 
-IRAM_ATTR void nimble_platform_mem_free(void *ptr)
+IRAM_ATTR void *bt_osi_mem_malloc_internal(size_t size)
+{
+    return heap_caps_malloc(size, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT);
+}
+
+IRAM_ATTR void *bt_osi_mem_calloc_internal(size_t n, size_t size)
+{
+    return heap_caps_calloc(n, size, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT);
+}
+
+IRAM_ATTR void bt_osi_mem_free(void *ptr)
 {
     heap_caps_free(ptr);
 }

+ 21 - 0
components/bt/porting/mem/bt_osi_mem.h

@@ -0,0 +1,21 @@
+/*
+ * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#pragma once
+
+#include "sdkconfig.h"
+#include "esp_attr.h"
+#include "esp_heap_caps.h"
+
+void *bt_osi_mem_malloc(size_t size);
+
+void *bt_osi_mem_calloc(size_t n, size_t size);
+
+void *bt_osi_mem_malloc_internal(size_t size);
+
+void *bt_osi_mem_calloc_internal(size_t n, size_t size);
+
+void bt_osi_mem_free(void *ptr);

+ 318 - 0
components/bt/porting/nimble/include/nimble/ble.h

@@ -0,0 +1,318 @@
+/*
+ * SPDX-FileCopyrightText: 2015-2022 The Apache Software Foundation (ASF)
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * SPDX-FileContributor: 2019-2022 Espressif Systems (Shanghai) CO LTD
+ */
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 H_BLE_
+#define H_BLE_
+
+#include <inttypes.h>
+#include <string.h>
+#include "syscfg/syscfg.h"
+#include "os/os.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* The number of advertising instances */
+#define BLE_ADV_INSTANCES    (MYNEWT_VAL(BLE_MULTI_ADV_INSTANCES) + 1)
+
+/* BLE encryption block definitions */
+#define BLE_ENC_BLOCK_SIZE       (16)
+
+/* 4 byte header + 251 byte payload. */
+#define BLE_ACL_MAX_PKT_SIZE     255
+
+struct ble_encryption_block
+{
+    uint8_t     key[BLE_ENC_BLOCK_SIZE];
+    uint8_t     plain_text[BLE_ENC_BLOCK_SIZE];
+    uint8_t     cipher_text[BLE_ENC_BLOCK_SIZE];
+};
+
+/*
+ * BLE MBUF structure:
+ *
+ * The BLE mbuf structure is as follows. Note that this structure applies to
+ * the packet header mbuf (not mbufs that are part of a "packet chain"):
+ *      struct os_mbuf          (16)
+ *      struct os_mbuf_pkthdr   (8)
+ *      struct ble_mbuf_hdr     (8)
+ *      Data buffer             (payload size, in bytes)
+ *
+ * The BLE mbuf header contains the following:
+ *  flags: bitfield with the following values
+ *      0x01:   Set if there was a match on the whitelist
+ *      0x02:   Set if a connect request was transmitted upon receiving pdu
+ *      0x04:   Set the first time we transmit the PDU (used to detect retry).
+ *  channel: The logical BLE channel PHY channel # (0 - 39)
+ *  crcok: flag denoting CRC check passed (1) or failed (0).
+ *  rssi: RSSI, in dBm.
+ */
+struct ble_mbuf_hdr_rxinfo
+{
+    uint16_t flags;
+    uint8_t channel;
+    uint8_t handle;
+    int8_t  rssi;
+    /* XXX: we could just use single phy_mode field */
+    int8_t  phy;
+    uint8_t phy_mode;
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY)
+    int8_t  rpa_index;
+#endif
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
+    void *user_data;
+#endif
+};
+
+/*
+ * Flag definitions for rxinfo
+ *
+ * Note: it's ok to have symbols with the same values as long as they cannot be
+ *       set for the same PDU (e.g. one use by scanner, other one used by
+ *       connection)
+ */
+#define BLE_MBUF_HDR_F_CONN_CREDIT      (0x8000)
+#define BLE_MBUF_HDR_F_IGNORED          (0x8000)
+#define BLE_MBUF_HDR_F_SCAN_REQ_TXD     (0x4000)
+#define BLE_MBUF_HDR_F_INITA_RESOLVED   (0x2000)
+#define BLE_MBUF_HDR_F_TARGETA_RESOLVED (0x2000)
+#define BLE_MBUF_HDR_F_EXT_ADV_SEC      (0x1000)
+#define BLE_MBUF_HDR_F_EXT_ADV          (0x0800)
+#define BLE_MBUF_HDR_F_RESOLVED         (0x0400)
+#define BLE_MBUF_HDR_F_AUX_PTR_WAIT     (0x0200)
+#define BLE_MBUF_HDR_F_AUX_INVALID      (0x0100)
+#define BLE_MBUF_HDR_F_CRC_OK           (0x0080)
+#define BLE_MBUF_HDR_F_DEVMATCH         (0x0040)
+#define BLE_MBUF_HDR_F_MIC_FAILURE      (0x0020)
+#define BLE_MBUF_HDR_F_SCAN_RSP_TXD     (0x0010)
+#define BLE_MBUF_HDR_F_SCAN_RSP_RXD     (0x0008)
+#define BLE_MBUF_HDR_F_RXSTATE_MASK     (0x0007)
+
+/* Transmit info. NOTE: no flags defined */
+struct ble_mbuf_hdr_txinfo
+{
+    uint8_t flags;
+    uint8_t offset;
+    uint8_t pyld_len;
+    uint8_t hdr_byte;
+};
+
+struct ble_mbuf_hdr
+{
+    union {
+        struct ble_mbuf_hdr_rxinfo rxinfo;
+        struct ble_mbuf_hdr_txinfo txinfo;
+    };
+    uint32_t beg_cputime;
+    uint32_t rem_usecs;
+};
+
+#define BLE_MBUF_HDR_IGNORED(hdr) \
+    (!!((hdr)->rxinfo.flags & BLE_MBUF_HDR_F_IGNORED))
+
+#define BLE_MBUF_HDR_SCAN_REQ_TXD(hdr) \
+    (!!((hdr)->rxinfo.flags & BLE_MBUF_HDR_F_SCAN_REQ_TXD))
+
+#define BLE_MBUF_HDR_EXT_ADV_SEC(hdr) \
+    (!!((hdr)->rxinfo.flags & BLE_MBUF_HDR_F_EXT_ADV_SEC))
+
+#define BLE_MBUF_HDR_EXT_ADV(hdr) \
+    (!!((hdr)->rxinfo.flags & BLE_MBUF_HDR_F_EXT_ADV))
+
+#define BLE_MBUF_HDR_DEVMATCH(hdr) \
+    (!!((hdr)->rxinfo.flags & BLE_MBUF_HDR_F_DEVMATCH))
+
+#define BLE_MBUF_HDR_SCAN_RSP_RXD(hdr) \
+    (!!((hdr)->rxinfo.flags & BLE_MBUF_HDR_F_SCAN_RSP_RXD))
+
+#define BLE_MBUF_HDR_AUX_INVALID(hdr) \
+    (!!((hdr)->rxinfo.flags & BLE_MBUF_HDR_F_AUX_INVALID))
+
+#define BLE_MBUF_HDR_WAIT_AUX(hdr)      \
+    (!!((hdr)->rxinfo.flags & BLE_MBUF_HDR_F_AUX_PTR_WAIT))
+
+#define BLE_MBUF_HDR_CRC_OK(hdr)        \
+    (!!((hdr)->rxinfo.flags & BLE_MBUF_HDR_F_CRC_OK))
+
+#define BLE_MBUF_HDR_MIC_FAILURE(hdr)   \
+    (!!((hdr)->rxinfo.flags & BLE_MBUF_HDR_F_MIC_FAILURE))
+
+#define BLE_MBUF_HDR_RESOLVED(hdr)      \
+    (!!((hdr)->rxinfo.flags & BLE_MBUF_HDR_F_RESOLVED))
+
+#define BLE_MBUF_HDR_INITA_RESOLVED(hdr)      \
+    (!!((hdr)->rxinfo.flags & BLE_MBUF_HDR_F_INITA_RESOLVED))
+
+#define BLE_MBUF_HDR_TARGETA_RESOLVED(hdr)      \
+    (!!((hdr)->rxinfo.flags & BLE_MBUF_HDR_F_TARGETA_RESOLVED))
+
+#define BLE_MBUF_HDR_RX_STATE(hdr)      \
+    ((uint8_t)((hdr)->rxinfo.flags & BLE_MBUF_HDR_F_RXSTATE_MASK))
+
+#define BLE_MBUF_HDR_PTR(om)            \
+    (struct ble_mbuf_hdr *)((uint8_t *)om + sizeof(struct os_mbuf) + \
+                            sizeof(struct os_mbuf_pkthdr))
+
+/* BLE mbuf overhead per packet header mbuf */
+#define BLE_MBUF_PKTHDR_OVERHEAD        \
+    (sizeof(struct os_mbuf_pkthdr) + sizeof(struct ble_mbuf_hdr))
+
+#define BLE_MBUF_MEMBLOCK_OVERHEAD      \
+    (sizeof(struct os_mbuf) + BLE_MBUF_PKTHDR_OVERHEAD)
+
+/* Length of host user header.  Only contains the peer's connection handle. */
+#define BLE_MBUF_HS_HDR_LEN     (2)
+
+#define BLE_DEV_ADDR_LEN        (6)
+extern uint8_t g_dev_addr[BLE_DEV_ADDR_LEN];
+extern uint8_t g_random_addr[BLE_DEV_ADDR_LEN];
+
+/* BLE Error Codes (Core v4.2 Vol 2 part D) */
+enum ble_error_codes
+{
+    /* An "error" code of 0x0 means success */
+    BLE_ERR_SUCCESS             = 0x00,
+    BLE_ERR_UNKNOWN_HCI_CMD     = 0x01,
+    BLE_ERR_UNK_CONN_ID         = 0x02,
+    BLE_ERR_HW_FAIL             = 0x03,
+    BLE_ERR_PAGE_TMO            = 0x04,
+    BLE_ERR_AUTH_FAIL           = 0x05,
+    BLE_ERR_PINKEY_MISSING      = 0x06,
+    BLE_ERR_MEM_CAPACITY        = 0x07,
+    BLE_ERR_CONN_SPVN_TMO       = 0x08,
+    BLE_ERR_CONN_LIMIT          = 0x09,
+    BLE_ERR_SYNCH_CONN_LIMIT    = 0x0a,
+    BLE_ERR_ACL_CONN_EXISTS     = 0x0b,
+    BLE_ERR_CMD_DISALLOWED      = 0x0c,
+    BLE_ERR_CONN_REJ_RESOURCES  = 0x0d,
+    BLE_ERR_CONN_REJ_SECURITY   = 0x0e,
+    BLE_ERR_CONN_REJ_BD_ADDR    = 0x0f,
+    BLE_ERR_CONN_ACCEPT_TMO     = 0x10,
+    BLE_ERR_UNSUPPORTED         = 0x11,
+    BLE_ERR_INV_HCI_CMD_PARMS   = 0x12,
+    BLE_ERR_REM_USER_CONN_TERM  = 0x13,
+    BLE_ERR_RD_CONN_TERM_RESRCS = 0x14,
+    BLE_ERR_RD_CONN_TERM_PWROFF = 0x15,
+    BLE_ERR_CONN_TERM_LOCAL     = 0x16,
+    BLE_ERR_REPEATED_ATTEMPTS   = 0x17,
+    BLE_ERR_NO_PAIRING          = 0x18,
+    BLE_ERR_UNK_LMP             = 0x19,
+    BLE_ERR_UNSUPP_REM_FEATURE  = 0x1a,
+    BLE_ERR_SCO_OFFSET          = 0x1b,
+    BLE_ERR_SCO_ITVL            = 0x1c,
+    BLE_ERR_SCO_AIR_MODE        = 0x1d,
+    BLE_ERR_INV_LMP_LL_PARM     = 0x1e,
+    BLE_ERR_UNSPECIFIED         = 0x1f,
+    BLE_ERR_UNSUPP_LMP_LL_PARM  = 0x20,
+    BLE_ERR_NO_ROLE_CHANGE      = 0x21,
+    BLE_ERR_LMP_LL_RSP_TMO      = 0x22,
+    BLE_ERR_LMP_COLLISION       = 0x23,
+    BLE_ERR_LMP_PDU             = 0x24,
+    BLE_ERR_ENCRYPTION_MODE     = 0x25,
+    BLE_ERR_LINK_KEY_CHANGE     = 0x26,
+    BLE_ERR_UNSUPP_QOS          = 0x27,
+    BLE_ERR_INSTANT_PASSED      = 0x28,
+    BLE_ERR_UNIT_KEY_PAIRING    = 0x29,
+    BLE_ERR_DIFF_TRANS_COLL     = 0x2a,
+    /* BLE_ERR_RESERVED         = 0x2b */
+    BLE_ERR_QOS_PARM            = 0x2c,
+    BLE_ERR_QOS_REJECTED        = 0x2d,
+    BLE_ERR_CHAN_CLASS          = 0x2e,
+    BLE_ERR_INSUFFICIENT_SEC    = 0x2f,
+    BLE_ERR_PARM_OUT_OF_RANGE   = 0x30,
+    /* BLE_ERR_RESERVED         = 0x31 */
+    BLE_ERR_PENDING_ROLE_SW     = 0x32,
+    /* BLE_ERR_RESERVED         = 0x33 */
+    BLE_ERR_RESERVED_SLOT       = 0x34,
+    BLE_ERR_ROLE_SW_FAIL        = 0x35,
+    BLE_ERR_INQ_RSP_TOO_BIG     = 0x36,
+    BLE_ERR_SEC_SIMPLE_PAIR     = 0x37,
+    BLE_ERR_HOST_BUSY_PAIR      = 0x38,
+    BLE_ERR_CONN_REJ_CHANNEL    = 0x39,
+    BLE_ERR_CTLR_BUSY           = 0x3a,
+    BLE_ERR_CONN_PARMS          = 0x3b,
+    BLE_ERR_DIR_ADV_TMO         = 0x3c,
+    BLE_ERR_CONN_TERM_MIC       = 0x3d,
+    BLE_ERR_CONN_ESTABLISHMENT  = 0x3e,
+    BLE_ERR_MAC_CONN_FAIL       = 0x3f,
+    BLE_ERR_COARSE_CLK_ADJ      = 0x40,
+    BLE_ERR_TYPE0_SUBMAP_NDEF   = 0x41,
+    BLE_ERR_UNK_ADV_INDENT      = 0x42,
+    BLE_ERR_LIMIT_REACHED       = 0x43,
+    BLE_ERR_OPERATION_CANCELLED = 0x44,
+    BLE_ERR_PACKET_TOO_LONG     = 0x45,
+    BLE_ERR_MAX                 = 0xff
+};
+
+/* HW error codes */
+#define BLE_HW_ERR_DO_NOT_USE           (0) /* XXX: reserve this one for now */
+#define BLE_HW_ERR_HCI_SYNC_LOSS        (1)
+
+/* Own Bluetooth Device address type */
+#define BLE_OWN_ADDR_PUBLIC                  (0x00)
+#define BLE_OWN_ADDR_RANDOM                  (0x01)
+#define BLE_OWN_ADDR_RPA_PUBLIC_DEFAULT      (0x02)
+#define BLE_OWN_ADDR_RPA_RANDOM_DEFAULT      (0x03)
+
+/* Bluetooth Device address type */
+#define BLE_ADDR_PUBLIC      (0x00)
+#define BLE_ADDR_RANDOM      (0x01)
+#define BLE_ADDR_PUBLIC_ID   (0x02)
+#define BLE_ADDR_RANDOM_ID   (0x03)
+
+#define BLE_ADDR_ANY (&(ble_addr_t) { 0, {0, 0, 0, 0, 0, 0} })
+
+#define BLE_ADDR_IS_RPA(addr)     (((addr)->type == BLE_ADDR_RANDOM) && \
+                                   ((addr)->val[5] & 0xc0) == 0x40)
+#define BLE_ADDR_IS_NRPA(addr)    (((addr)->type == BLE_ADDR_RANDOM) && \
+                                   ((addr)->val[5] & 0xc0) == 0x00)
+#define BLE_ADDR_IS_STATIC(addr)  (((addr)->type == BLE_ADDR_RANDOM) && \
+                                   ((addr)->val[5] & 0xc0) == 0xc0)
+
+typedef struct {
+    uint8_t type;
+    uint8_t val[6];
+} ble_addr_t;
+
+
+static inline int ble_addr_cmp(const ble_addr_t *a, const ble_addr_t *b)
+{
+    int type_diff;
+
+    type_diff = a->type - b->type;
+    if (type_diff != 0) {
+        return type_diff;
+    }
+
+    return memcmp(a->val, b->val, sizeof(a->val));
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* H_BLE_ */

+ 407 - 0
components/bt/porting/nimble/include/nimble/ble_hci_trans.h

@@ -0,0 +1,407 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 H_HCI_TRANSPORT_
+#define H_HCI_TRANSPORT_
+
+#include <inttypes.h>
+#include "os/os_mempool.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct os_mbuf;
+
+#define BLE_HCI_TRANS_CMD_SZ        260
+
+/*** Type of buffers for holding commands and events. */
+/**
+ * Controller-to-host event buffers.  Events have one of two priorities:
+ * o Low-priority   (BLE_HCI_TRANS_BUF_EVT_LO)
+ * o High-priority  (BLE_HCI_TRANS_BUF_EVT_HI)
+ *
+ * Low-priority event buffers are only used for advertising reports.  If there
+ * are no free low-priority event buffers, then an incoming advertising report
+ * will get dropped.
+ *
+ * High-priority event buffers are for everything except advertising reports.
+ * If there are no free high-priority event buffers, a request to allocate one
+ * will try to allocate a low-priority buffer instead.
+ *
+ * If you want all events to be given equal treatment, then you should allocate
+ * low-priority events only.
+ *
+ * Event priorities solve the problem of critical events getting dropped due to
+ * a flood of advertising reports.  This solution is likely temporary: when
+ * HCI flow control is added, event priorities may become obsolete.
+ *
+ * Not all transports distinguish between low and high priority events.  If the
+ * transport does not have separate settings for low and high buffer counts,
+ * then it treats all events with equal priority.
+ */
+#define BLE_HCI_TRANS_BUF_EVT_LO    1
+#define BLE_HCI_TRANS_BUF_EVT_HI    2
+
+/* Host-to-controller command. */
+#define BLE_HCI_TRANS_BUF_CMD       3
+
+/** Callback function types; executed when HCI packets are received. */
+typedef int ble_hci_trans_rx_cmd_fn(uint8_t *cmd, void *arg);
+typedef int ble_hci_trans_rx_acl_fn(struct os_mbuf *om, void *arg);
+
+#if CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32C2
+struct ble_hci_trans_funcs_t {
+    int(*_ble_hci_trans_hs_acl_tx)(struct os_mbuf *om);
+    int(*_ble_hci_trans_hs_cmd_tx)(uint8_t *cmd);
+    int(*_ble_hci_trans_ll_acl_tx)(struct os_mbuf *om);
+    int(*_ble_hci_trans_ll_evt_tx)(uint8_t *hci_ev);
+    int(*_ble_hci_trans_reset)(void);
+    int(*_ble_hci_trans_set_acl_free_cb)(os_mempool_put_fn *cb,void *arg);
+};
+
+extern struct ble_hci_trans_funcs_t *ble_hci_trans_funcs_ptr;
+
+/**
+ * Sends an HCI event from the controller to the host.
+ *
+ * @param cmd                   The HCI event to send.  This buffer must be
+ *                                  allocated via ble_hci_trans_buf_alloc().
+ *
+ * @return                      0 on success;
+ *                              A BLE_ERR_[...] error code on failure.
+ */
+extern int r_ble_hci_trans_ll_evt_tx(uint8_t *hci_ev);
+#define ble_hci_trans_ll_evt_tx ble_hci_trans_funcs_ptr->_ble_hci_trans_ll_evt_tx
+
+/**
+ * Sends ACL data from controller to host.
+ *
+ * @param om                    The ACL data packet to send.
+ *
+ * @return                      0 on success;
+ *                              A BLE_ERR_[...] error code on failure.
+ */
+extern int r_ble_hci_trans_ll_acl_tx(struct os_mbuf *om);
+#define ble_hci_trans_ll_acl_tx ble_hci_trans_funcs_ptr->_ble_hci_trans_ll_acl_tx
+
+/**
+ * Sends an HCI command from the host to the controller.
+ *
+ * @param cmd                   The HCI command to send.  This buffer must be
+ *                                  allocated via ble_hci_trans_buf_alloc().
+ *
+ * @return                      0 on success;
+ *                              A BLE_ERR_[...] error code on failure.
+ */
+extern int r_ble_hci_trans_hs_cmd_tx(uint8_t *cmd);
+#define ble_hci_trans_hs_cmd_tx ble_hci_trans_funcs_ptr->_ble_hci_trans_hs_cmd_tx
+
+/**
+ * Sends ACL data from host to controller.
+ *
+ * @param om                    The ACL data packet to send.
+ *
+ * @return                      0 on success;
+ *                              A BLE_ERR_[...] error code on failure.
+ */
+extern int r_ble_hci_trans_hs_acl_tx(struct os_mbuf *om);
+#define ble_hci_trans_hs_acl_tx ble_hci_trans_funcs_ptr->_ble_hci_trans_hs_acl_tx
+
+/**
+ * Allocates a flat buffer of the specified type.
+ *
+ * @param type                  The type of buffer to allocate; one of the
+ *                                  BLE_HCI_TRANS_BUF_[...] constants.
+ *
+ * @return                      The allocated buffer on success;
+ *                              NULL on buffer exhaustion.
+ */
+extern uint8_t *r_ble_hci_trans_buf_alloc(int type);
+#define ble_hci_trans_buf_alloc r_ble_hci_trans_buf_alloc
+
+/**
+ * Frees the specified flat buffer.  The buffer must have been allocated via
+ * ble_hci_trans_buf_alloc().
+ *
+ * @param buf                   The buffer to free.
+ */
+extern void r_ble_hci_trans_buf_free(uint8_t *buf);
+#define ble_hci_trans_buf_free r_ble_hci_trans_buf_free
+
+/**
+ * Configures a callback to get executed whenever an ACL data packet is freed.
+ * The function is called immediately before the free occurs.
+ *
+ * @param cb                    The callback to configure.
+ * @param arg                   An optional argument to pass to the callback.
+ *
+ * @return                      0 on success;
+ *                              BLE_ERR_UNSUPPORTED if the transport does not
+ *                                  support this operation.
+ */
+extern int r_ble_hci_trans_set_acl_free_cb(os_mempool_put_fn *cb, void *arg);
+#define ble_hci_trans_set_acl_free_cb ble_hci_trans_funcs_ptr->_ble_hci_trans_set_acl_free_cb
+
+/**
+ * Configures the HCI transport to operate with a controller.  The transport
+ * will execute specified callbacks upon receiving HCI packets from the host.
+ *
+ * @param cmd_cb                The callback to execute upon receiving an HCI
+ *                                  command.
+ * @param cmd_arg               Optional argument to pass to the command
+ *                                  callback.
+ * @param acl_cb                The callback to execute upon receiving ACL
+ *                                  data.
+ * @param acl_arg               Optional argument to pass to the ACL
+ *                                  callback.
+ */
+extern void r_ble_hci_trans_cfg_ll(ble_hci_trans_rx_cmd_fn *cmd_cb,
+                          void *cmd_arg,
+                          ble_hci_trans_rx_acl_fn *acl_cb,
+                          void *acl_arg);
+#define ble_hci_trans_cfg_ll r_ble_hci_trans_cfg_ll
+
+/**
+ * Configures the HCI transport to operate with a host.  The transport will
+ * execute specified callbacks upon receiving HCI packets from the controller.
+ *
+ * @param evt_cb                The callback to execute upon receiving an HCI
+ *                                  event.
+ * @param evt_arg               Optional argument to pass to the event
+ *                                  callback.
+ * @param acl_cb                The callback to execute upon receiving ACL
+ *                                  data.
+ * @param acl_arg               Optional argument to pass to the ACL
+ *                                  callback.
+ */
+extern void r_ble_hci_trans_cfg_hs(ble_hci_trans_rx_cmd_fn *evt_cb,
+                          void *evt_arg,
+                          ble_hci_trans_rx_acl_fn *acl_cb,
+                          void *acl_arg);
+#define ble_hci_trans_cfg_hs r_ble_hci_trans_cfg_hs
+
+/**
+ * Resets the HCI module to a clean state.  Frees all buffers and reinitializes
+ * the underlying transport.
+ *
+ * @return                      0 on success;
+ *                              A BLE_ERR_[...] error code on failure.
+ */
+extern int r_ble_hci_trans_reset(void);
+#define ble_hci_trans_reset ble_hci_trans_funcs_ptr->_ble_hci_trans_reset
+
+void esp_ble_hci_trans_init(uint8_t);
+#else
+/**
+ * Sends an HCI event from the controller to the host.
+ *
+ * @param cmd                   The HCI event to send.  This buffer must be
+ *                                  allocated via ble_hci_trans_buf_alloc().
+ *
+ * @return                      0 on success;
+ *                              A BLE_ERR_[...] error code on failure.
+ */
+int ble_hci_trans_ll_evt_tx(uint8_t *hci_ev);
+
+/**
+ * Sends ACL data from controller to host.
+ *
+ * @param om                    The ACL data packet to send.
+ *
+ * @return                      0 on success;
+ *                              A BLE_ERR_[...] error code on failure.
+ */
+int ble_hci_trans_ll_acl_tx(struct os_mbuf *om);
+
+/**
+ * Sends an HCI command from the host to the controller.
+ *
+ * @param cmd                   The HCI command to send.  This buffer must be
+ *                                  allocated via ble_hci_trans_buf_alloc().
+ *
+ * @return                      0 on success;
+ *                              A BLE_ERR_[...] error code on failure.
+ */
+int ble_hci_trans_hs_cmd_tx(uint8_t *cmd);
+
+/**
+ * Sends ACL data from host to controller.
+ *
+ * @param om                    The ACL data packet to send.
+ *
+ * @return                      0 on success;
+ *                              A BLE_ERR_[...] error code on failure.
+ */
+int ble_hci_trans_hs_acl_tx(struct os_mbuf *om);
+
+/**
+ * Allocates a flat buffer of the specified type.
+ *
+ * @param type                  The type of buffer to allocate; one of the
+ *                                  BLE_HCI_TRANS_BUF_[...] constants.
+ *
+ * @return                      The allocated buffer on success;
+ *                              NULL on buffer exhaustion.
+ */
+uint8_t *ble_hci_trans_buf_alloc(int type);
+
+/**
+ * Frees the specified flat buffer.  The buffer must have been allocated via
+ * ble_hci_trans_buf_alloc().
+ *
+ * @param buf                   The buffer to free.
+ */
+void ble_hci_trans_buf_free(uint8_t *buf);
+
+/**
+ * Configures a callback to get executed whenever an ACL data packet is freed.
+ * The function is called immediately before the free occurs.
+ *
+ * @param cb                    The callback to configure.
+ * @param arg                   An optional argument to pass to the callback.
+ *
+ * @return                      0 on success;
+ *                              BLE_ERR_UNSUPPORTED if the transport does not
+ *                                  support this operation.
+ */
+int ble_hci_trans_set_acl_free_cb(os_mempool_put_fn *cb, void *arg);
+
+/**
+ * Configures the HCI transport to operate with a controller.  The transport
+ * will execute specified callbacks upon receiving HCI packets from the host.
+ *
+ * @param cmd_cb                The callback to execute upon receiving an HCI
+ *                                  command.
+ * @param cmd_arg               Optional argument to pass to the command
+ *                                  callback.
+ * @param acl_cb                The callback to execute upon receiving ACL
+ *                                  data.
+ * @param acl_arg               Optional argument to pass to the ACL
+ *                                  callback.
+ */
+void ble_hci_trans_cfg_ll(ble_hci_trans_rx_cmd_fn *cmd_cb,
+                          void *cmd_arg,
+                          ble_hci_trans_rx_acl_fn *acl_cb,
+                          void *acl_arg);
+
+/**
+ * Configures the HCI transport to operate with a host.  The transport will
+ * execute specified callbacks upon receiving HCI packets from the controller.
+ *
+ * @param evt_cb                The callback to execute upon receiving an HCI
+ *                                  event.
+ * @param evt_arg               Optional argument to pass to the event
+ *                                  callback.
+ * @param acl_cb                The callback to execute upon receiving ACL
+ *                                  data.
+ * @param acl_arg               Optional argument to pass to the ACL
+ *                                  callback.
+ */
+void ble_hci_trans_cfg_hs(ble_hci_trans_rx_cmd_fn *evt_cb,
+                          void *evt_arg,
+                          ble_hci_trans_rx_acl_fn *acl_cb,
+                          void *acl_arg);
+
+/**
+ * Resets the HCI module to a clean state.  Frees all buffers and reinitializes
+ * the underlying transport.
+ *
+ * @return                      0 on success;
+ *                              A BLE_ERR_[...] error code on failure.
+ */
+int ble_hci_trans_reset(void);
+
+
+/**
+ * Sends an HCI command from the host to the controller.
+ *
+ * @param cmd                   The HCI command to send.  This buffer must be
+ *                                  allocated via ble_hci_trans_buf_alloc().
+ *
+ * @return                      0 on success;
+ *                              A BLE_ERR_[...] error code on failure.
+ */
+int esp_ble_hci_trans_hs_cmd_tx(uint8_t *cmd);
+
+/**
+ * Sends ACL data from host to controller.
+ *
+ * @param om                    The ACL data packet to send.
+ *
+ * @return                      0 on success;
+ *                              A BLE_ERR_[...] error code on failure.
+ */
+int esp_ble_hci_trans_hs_acl_tx(struct os_mbuf *om);
+
+/**
+ * Allocates a flat buffer of the specified type.
+ *
+ * @param type                  The type of buffer to allocate; one of the
+ *                                  BLE_HCI_TRANS_BUF_[...] constants.
+ *
+ * @return                      The allocated buffer on success;
+ *                              NULL on buffer exhaustion.
+ */
+uint8_t *esp_ble_hci_trans_buf_alloc(int type);
+
+/**
+ * Frees the specified flat buffer.  The buffer must have been allocated via
+ * ble_hci_trans_buf_alloc().
+ *
+ * @param buf                   The buffer to free.
+ */
+void esp_ble_hci_trans_buf_free(uint8_t *buf);
+
+/**
+ * Configures the HCI transport to operate with a host.  The transport will
+ * execute specified callbacks upon receiving HCI packets from the controller.
+ *
+ * @param evt_cb                The callback to execute upon receiving an HCI
+ *                                  event.
+ * @param evt_arg               Optional argument to pass to the event
+ *                                  callback.
+ * @param acl_cb                The callback to execute upon receiving ACL
+ *                                  data.
+ * @param acl_arg               Optional argument to pass to the ACL
+ *                                  callback.
+ */
+void esp_ble_hci_trans_cfg_hs(ble_hci_trans_rx_cmd_fn *evt_cb,
+                          void *evt_arg,
+                          ble_hci_trans_rx_acl_fn *acl_cb,
+                          void *acl_arg);
+
+/**
+ * Resets the HCI module to a clean state.  Frees all buffers and reinitializes
+ * the underlying transport.
+ *
+ * @return                      0 on success;
+ *                              A BLE_ERR_[...] error code on failure.
+ */
+int esp_ble_hci_trans_reset(void);
+
+
+#endif
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* H_HCI_TRANSPORT_ */

+ 1883 - 0
components/bt/porting/nimble/include/nimble/hci_common.h

@@ -0,0 +1,1883 @@
+/*
+ * SPDX-FileCopyrightText: 2015-2022 The Apache Software Foundation (ASF)
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * SPDX-FileContributor: 2019-2022 Espressif Systems (Shanghai) CO LTD
+ */
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 H_BLE_HCI_COMMON_
+#define H_BLE_HCI_COMMON_
+
+#include "ble.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define BLE_HCI_MAX_DATA_LEN (MYNEWT_VAL(BLE_HCI_EVT_BUF_SIZE) - \
+                              sizeof(struct ble_hci_ev))
+
+/* Generic command header */
+struct ble_hci_cmd {
+    uint16_t opcode;
+    uint8_t  length;
+    uint8_t  data[0];
+} __attribute__((packed));
+
+/* Generic event header */
+struct ble_hci_ev {
+    uint8_t opcode;
+    uint8_t length;
+    uint8_t  data[0];
+} __attribute__((packed));
+
+#define BLE_HCI_OPCODE_NOP                  (0)
+
+/* Set opcode based on OCF and OGF */
+#define BLE_HCI_OP(ogf, ocf)            ((ocf) | ((ogf) << 10))
+
+/* Get the OGF and OCF from the opcode in the command */
+#define BLE_HCI_OGF(opcode)                 (((opcode) >> 10) & 0x003F)
+#define BLE_HCI_OCF(opcode)                 ((opcode) & 0x03FF)
+
+/* Opcode Group definitions (note: 0x07 not defined in spec) */
+#define BLE_HCI_OGF_LINK_CTRL               (0x01)
+#define BLE_HCI_OGF_LINK_POLICY             (0x02)
+#define BLE_HCI_OGF_CTLR_BASEBAND           (0x03)
+#define BLE_HCI_OGF_INFO_PARAMS             (0x04)
+#define BLE_HCI_OGF_STATUS_PARAMS           (0x05)
+#define BLE_HCI_OGF_TESTING                 (0x06)
+#define BLE_HCI_OGF_LE                      (0x08)
+#define BLE_HCI_OGF_VENDOR                  (0x3F)
+
+/*
+ * Number of LE commands. NOTE: this is really just used to size the array
+ * containing the lengths of the LE commands.
+ */
+#define BLE_HCI_NUM_LE_CMDS                 (79)
+
+/* List of OCF for Link Control commands (OGF=0x01) */
+#define BLE_HCI_OCF_DISCONNECT_CMD          (0x0006)
+struct ble_hci_lc_disconnect_cp {
+    uint16_t conn_handle;
+    uint8_t  reason;
+} __attribute__((packed));
+
+#define BLE_HCI_OCF_RD_REM_VER_INFO         (0x001D)
+struct ble_hci_rd_rem_ver_info_cp {
+    uint16_t conn_handle;
+} __attribute__((packed));
+
+/* List of OCF for Controller and Baseband commands (OGF=0x03) */
+#define BLE_HCI_OCF_CB_SET_EVENT_MASK       (0x0001)
+struct ble_hci_cb_set_event_mask_cp {
+    uint64_t event_mask;
+} __attribute__((packed));
+
+#define BLE_HCI_OCF_CB_RESET                (0x0003)
+
+#define BLE_HCI_OCF_CB_READ_TX_PWR          (0x002D)
+struct ble_hci_cb_read_tx_pwr_cp {
+    uint16_t conn_handle;
+    uint8_t  type;
+} __attribute__((packed));
+
+struct ble_hci_cb_read_tx_pwr_rp {
+    uint16_t conn_handle;
+    int8_t   tx_level;
+} __attribute__((packed));
+
+
+#define BLE_HCI_OCF_CB_SET_CTLR_TO_HOST_FC  (0x0031)
+struct ble_hci_cb_ctlr_to_host_fc_cp {
+    uint8_t enable;
+} __attribute__((packed));
+
+#define BLE_HCI_OCF_CB_HOST_BUF_SIZE        (0x0033)
+struct ble_hci_cb_host_buf_size_cp {
+    uint16_t acl_data_len;
+    uint8_t  sco_data_len;
+    uint16_t acl_num;
+    uint16_t sco_num;
+} __attribute__((packed));
+
+#define BLE_HCI_OCF_CB_HOST_NUM_COMP_PKTS   (0x0035)
+struct  ble_hci_cb_host_num_comp_pkts_entry {
+    uint16_t handle;
+    uint16_t count;
+} __attribute__((packed));
+struct ble_hci_cb_host_num_comp_pkts_cp {
+    uint8_t handles;
+    struct ble_hci_cb_host_num_comp_pkts_entry h[0];
+} __attribute__((packed));
+
+#define BLE_HCI_OCF_CB_SET_EVENT_MASK2      (0x0063)
+struct ble_hci_cb_set_event_mask2_cp {
+    uint64_t event_mask2;
+} __attribute__((packed));
+
+#define BLE_HCI_OCF_CB_RD_AUTH_PYLD_TMO     (0x007B)
+struct ble_hci_cb_rd_auth_pyld_tmo_cp {
+    uint16_t conn_handle;
+} __attribute__((packed));
+struct ble_hci_cb_rd_auth_pyld_tmo_rp {
+    uint16_t conn_handle;
+    uint16_t tmo;
+} __attribute__((packed));
+
+#define BLE_HCI_OCF_CB_WR_AUTH_PYLD_TMO     (0x007C)
+struct ble_hci_cb_wr_auth_pyld_tmo_cp {
+    uint16_t conn_handle;
+    uint16_t tmo;
+} __attribute__((packed));
+struct ble_hci_cb_wr_auth_pyld_tmo_rp {
+    uint16_t conn_handle;
+} __attribute__((packed));
+
+/* List of OCF for Info Param commands (OGF=0x04) */
+#define BLE_HCI_OCF_IP_RD_LOCAL_VER         (0x0001)
+struct ble_hci_ip_rd_local_ver_rp {
+    uint8_t  hci_ver;
+    uint16_t hci_rev;
+    uint8_t  lmp_ver;
+    uint16_t manufacturer;
+    uint16_t lmp_subver;
+} __attribute__((packed));
+
+#define BLE_HCI_OCF_IP_RD_LOC_SUPP_CMD      (0x0002)
+struct ble_hci_ip_rd_loc_supp_cmd_rp {
+    uint8_t commands[64];
+} __attribute__((packed));
+
+#define BLE_HCI_OCF_IP_RD_LOC_SUPP_FEAT     (0x0003)
+struct ble_hci_ip_rd_loc_supp_feat_rp {
+    uint64_t features;
+} __attribute__((packed));
+
+#define BLE_HCI_OCF_IP_RD_BUF_SIZE          (0x0005)
+struct ble_hci_ip_rd_buf_size_rp {
+    uint16_t acl_data_len;
+    uint8_t  sco_data_len;
+    uint16_t acl_num;
+    uint16_t sco_num;
+} __attribute__((packed));
+
+#define BLE_HCI_OCF_IP_RD_BD_ADDR           (0x0009)
+struct ble_hci_ip_rd_bd_addr_rp {
+    uint8_t addr[6];
+} __attribute__((packed));
+
+/* List of OCF for Status parameters commands (OGF = 0x05) */
+#define BLE_HCI_OCF_RD_RSSI                 (0x0005)
+struct ble_hci_rd_rssi_cp {
+    uint16_t handle;
+} __attribute__((packed));
+struct ble_hci_rd_rssi_rp {
+    uint16_t handle;
+    int8_t   rssi;
+} __attribute__((packed));
+
+/* List of OCF for LE commands (OGF = 0x08) */
+#define BLE_HCI_OCF_LE_SET_EVENT_MASK               (0x0001)
+struct ble_hci_le_set_event_mask_cp {
+    uint64_t event_mask;
+} __attribute__((packed));
+
+#define BLE_HCI_OCF_LE_RD_BUF_SIZE                  (0x0002)
+struct ble_hci_le_rd_buf_size_rp {
+    uint16_t data_len;
+    uint8_t  data_packets;
+} __attribute__((packed));
+
+#define BLE_HCI_OCF_LE_RD_BUF_SIZE_V2                    (0x0060)
+struct ble_hci_le_rd_buf_size_v2_rp {
+    uint16_t data_len;
+    uint8_t  data_packets;
+    uint16_t iso_data_len;
+    uint8_t  iso_data_packets;
+} __attribute__((packed));
+
+#define BLE_HCI_OCF_LE_RD_LOC_SUPP_FEAT             (0x0003)
+struct ble_hci_le_rd_loc_supp_feat_rp {
+    uint64_t features;
+} __attribute__((packed));
+
+/* NOTE: 0x0004 is intentionally left undefined */
+#define BLE_HCI_OCF_LE_SET_RAND_ADDR                (0x0005)
+struct ble_hci_le_set_rand_addr_cp {
+    uint8_t addr[6];
+} __attribute__((packed));
+
+#define BLE_HCI_OCF_LE_SET_ADV_PARAMS               (0x0006)
+struct ble_hci_le_set_adv_params_cp {
+    uint16_t min_interval;
+    uint16_t max_interval;
+    uint8_t type;
+    uint8_t own_addr_type;
+    uint8_t peer_addr_type;
+    uint8_t peer_addr[6];
+    uint8_t chan_map;
+    uint8_t filter_policy;
+} __attribute__((packed));
+
+#define BLE_HCI_OCF_LE_RD_ADV_CHAN_TXPWR            (0x0007)
+struct ble_hci_le_rd_adv_chan_txpwr_rp {
+    int8_t power_level;
+} __attribute__((packed));
+
+#define BLE_HCI_OCF_LE_SET_ADV_DATA                 (0x0008)
+#define BLE_HCI_MAX_ADV_DATA_LEN                    (31)
+struct ble_hci_le_set_adv_data_cp {
+    uint8_t adv_data_len;
+    uint8_t adv_data[BLE_HCI_MAX_ADV_DATA_LEN];
+} __attribute__((packed));
+
+#define BLE_HCI_OCF_LE_SET_SCAN_RSP_DATA            (0x0009)
+#define BLE_HCI_MAX_SCAN_RSP_DATA_LEN               (31)
+struct ble_hci_le_set_scan_rsp_data_cp {
+    uint8_t scan_rsp_len;
+    uint8_t scan_rsp[BLE_HCI_MAX_SCAN_RSP_DATA_LEN];
+} __attribute__((packed));
+
+#define BLE_HCI_OCF_LE_SET_ADV_ENABLE               (0x000A)
+struct ble_hci_le_set_adv_enable_cp {
+    uint8_t enable;
+} __attribute__((packed));
+
+#define BLE_HCI_OCF_LE_SET_SCAN_PARAMS              (0x000B)
+struct ble_hci_le_set_scan_params_cp {
+    uint8_t  scan_type;
+    uint16_t scan_itvl;
+    uint16_t scan_window;
+    uint8_t  own_addr_type;
+    uint8_t  filter_policy;
+} __attribute__((packed));
+
+#define BLE_HCI_OCF_LE_SET_SCAN_ENABLE              (0x000C)
+struct ble_hci_le_set_scan_enable_cp {
+    uint8_t enable;
+    uint8_t filter_duplicates;
+} __attribute__((packed));
+
+#define BLE_HCI_OCF_LE_CREATE_CONN                  (0x000D)
+struct ble_hci_le_create_conn_cp {
+    uint16_t scan_itvl;
+    uint16_t scan_window;
+    uint8_t  filter_policy;
+    uint8_t  peer_addr_type;
+    uint8_t  peer_addr[6];
+    uint8_t  own_addr_type;
+    uint16_t min_conn_itvl;
+    uint16_t max_conn_itvl;
+    uint16_t conn_latency;
+    uint16_t tmo;
+    uint16_t min_ce;
+    uint16_t max_ce;
+} __attribute__((packed));
+
+#define BLE_HCI_OCF_LE_CREATE_CONN_CANCEL           (0x000E)
+
+#define BLE_HCI_OCF_LE_RD_WHITE_LIST_SIZE           (0x000F)
+struct ble_hci_le_rd_white_list_rp {
+    uint8_t size;
+} __attribute__((packed));
+
+#define BLE_HCI_OCF_LE_CLEAR_WHITE_LIST             (0x0010)
+
+#define BLE_HCI_OCF_LE_ADD_WHITE_LIST               (0x0011)
+struct ble_hci_le_add_whte_list_cp {
+    uint8_t addr_type;
+    uint8_t addr[6];
+} __attribute__((packed));
+
+#define BLE_HCI_OCF_LE_RMV_WHITE_LIST               (0x0012)
+struct ble_hci_le_rmv_white_list_cp {
+    uint8_t addr_type;
+    uint8_t addr[6];
+} __attribute__((packed));
+
+#define BLE_HCI_OCF_LE_CONN_UPDATE                  (0x0013)
+struct ble_hci_le_conn_update_cp {
+    uint16_t conn_handle;
+    uint16_t conn_itvl_min;
+    uint16_t conn_itvl_max;
+    uint16_t conn_latency;
+    uint16_t supervision_timeout;
+    uint16_t min_ce_len;
+    uint16_t max_ce_len;
+} __attribute__((packed));
+
+#define BLE_HCI_OCF_LE_SET_HOST_CHAN_CLASS          (0x0014)
+struct ble_hci_le_set_host_chan_class_cp {
+    uint8_t chan_map[5];
+} __attribute__((packed));
+
+#define BLE_HCI_OCF_LE_RD_CHAN_MAP                  (0x0015)
+struct ble_hci_le_rd_chan_map_cp {
+    uint16_t conn_handle;
+} __attribute__((packed));
+struct ble_hci_le_rd_chan_map_rp {
+    uint16_t conn_handle;
+    uint8_t chan_map[5];
+} __attribute__((packed));
+
+#define BLE_HCI_OCF_LE_RD_REM_FEAT                  (0x0016)
+struct ble_hci_le_rd_rem_feat_cp {
+    uint16_t conn_handle;
+} __attribute__((packed));
+
+#define BLE_HCI_OCF_LE_ENCRYPT                      (0x0017)
+struct ble_hci_le_encrypt_cp {
+    uint8_t key[16];
+    uint8_t data[16];
+} __attribute__((packed));
+struct ble_hci_le_encrypt_rp {
+    uint8_t data[16];
+} __attribute__((packed));
+
+#define BLE_HCI_OCF_LE_RAND                         (0x0018)
+struct ble_hci_le_rand_rp {
+    uint64_t random_number;
+} __attribute__((packed));
+
+#define BLE_HCI_OCF_LE_START_ENCRYPT                (0x0019)
+struct ble_hci_le_start_encrypt_cp {
+    uint16_t conn_handle;
+    uint64_t rand;
+    uint16_t div;
+    uint8_t  ltk[16];
+} __attribute__((packed));
+
+#define BLE_HCI_OCF_LE_LT_KEY_REQ_REPLY             (0x001A)
+struct ble_hci_le_lt_key_req_reply_cp {
+    uint16_t conn_handle;
+    uint8_t  ltk[16];
+} __attribute__((packed));
+struct ble_hci_le_lt_key_req_reply_rp {
+    uint16_t conn_handle;
+} __attribute__((packed));
+
+#define BLE_HCI_OCF_LE_LT_KEY_REQ_NEG_REPLY         (0x001B)
+struct ble_hci_le_lt_key_req_neg_reply_cp {
+    uint16_t conn_handle;
+} __attribute__((packed));
+struct ble_hci_le_lt_key_req_neg_reply_rp {
+    uint16_t conn_handle;
+} __attribute__((packed));
+
+#define BLE_HCI_OCF_LE_RD_SUPP_STATES               (0x001C)
+struct ble_hci_le_rd_supp_states_rp {
+    uint64_t states;
+} __attribute__((packed));
+
+#define BLE_HCI_OCF_LE_RX_TEST                      (0x001D)
+struct ble_hci_le_rx_test_cp {
+    uint8_t rx_chan;
+} __attribute__((packed));
+
+#define BLE_HCI_OCF_LE_TX_TEST                      (0x001E)
+struct ble_hci_le_tx_test_cp {
+    uint8_t tx_chan;
+    uint8_t test_data_len;
+    uint8_t payload;
+} __attribute__((packed));
+#if MYNEWT_VAL(BLE_LL_DTM_EXTENSIONS)
+struct ble_hci_le_tx_test_ext_cp {
+    uint8_t tx_chan;
+    uint8_t test_data_len;
+    uint8_t payload;
+    uint16_t interval;
+    uint16_t pkt_count;
+} __attribute__((packed));
+#endif
+
+#define BLE_HCI_OCF_LE_TEST_END                     (0x001F)
+struct ble_hci_le_test_end_rp {
+    uint16_t num_packets;
+} __attribute__((packed));
+
+#define BLE_HCI_OCF_LE_REM_CONN_PARAM_RR            (0x0020)
+struct ble_hci_le_rem_conn_param_rr_cp {
+    uint16_t conn_handle;
+    uint16_t conn_itvl_min;
+    uint16_t conn_itvl_max;
+    uint16_t conn_latency;
+    uint16_t supervision_timeout;
+    uint16_t min_ce;
+    uint16_t max_ce;
+} __attribute__((packed));
+struct ble_hci_le_rem_conn_param_rr_rp {
+    uint16_t conn_handle;
+} __attribute__((packed));
+
+#define BLE_HCI_OCF_LE_REM_CONN_PARAM_NRR           (0x0021)
+struct ble_hci_le_rem_conn_params_nrr_cp {
+    uint16_t conn_handle;
+    uint8_t  reason;
+} __attribute__((packed));
+struct ble_hci_le_rem_conn_params_nrr_rp {
+    uint16_t conn_handle;
+} __attribute__((packed));
+
+#define BLE_HCI_OCF_LE_SET_DATA_LEN                 (0x0022)
+struct ble_hci_le_set_data_len_cp {
+    uint16_t conn_handle;
+    uint16_t tx_octets;
+    uint16_t tx_time;
+} __attribute__((packed));
+struct ble_hci_le_set_data_len_rp {
+    uint16_t conn_handle;
+} __attribute__((packed));
+
+#define BLE_HCI_OCF_LE_RD_SUGG_DEF_DATA_LEN         (0x0023)
+struct ble_hci_le_rd_sugg_def_data_len_rp {
+    uint16_t max_tx_octets;
+    uint16_t max_tx_time;
+} __attribute__((packed));
+
+#define BLE_HCI_OCF_LE_WR_SUGG_DEF_DATA_LEN         (0x0024)
+struct ble_hci_le_wr_sugg_def_data_len_cp {
+    uint16_t max_tx_octets;
+    uint16_t max_tx_time;
+} __attribute__((packed));
+
+#define BLE_HCI_OCF_LE_RD_P256_PUBKEY               (0x0025)
+
+#define BLE_HCI_OCF_LE_GEN_DHKEY                    (0x0026)
+struct ble_hci_le_gen_dhkey_cp {
+    uint8_t pkey[64];
+} __attribute__((packed));
+
+#define BLE_HCI_OCF_LE_ADD_RESOLV_LIST              (0x0027)
+struct ble_hci_le_add_resolv_list_cp {
+    uint8_t peer_addr_type;
+    uint8_t peer_id_addr[6];
+    uint8_t peer_irk[16];
+    uint8_t local_irk[16];
+} __attribute__((packed));
+
+#define BLE_HCI_OCF_LE_RMV_RESOLV_LIST              (0x0028)
+struct ble_hci_le_rmv_resolve_list_cp {
+    uint8_t peer_addr_type;
+    uint8_t peer_id_addr[6];
+} __attribute__((packed));
+
+#define BLE_HCI_OCF_LE_CLR_RESOLV_LIST              (0x0029)
+
+#define BLE_HCI_OCF_LE_RD_RESOLV_LIST_SIZE          (0x002A)
+struct ble_hci_le_rd_resolv_list_size_rp {
+    uint8_t size;
+} __attribute__((packed));
+
+#define BLE_HCI_OCF_LE_RD_PEER_RESOLV_ADDR          (0x002B)
+struct ble_hci_le_rd_peer_recolv_addr_cp {
+    uint8_t peer_addr_type;
+    uint8_t peer_id_addr[6];
+} __attribute__((packed));
+struct ble_hci_le_rd_peer_recolv_addr_rp {
+    uint8_t rpa[6];
+} __attribute__((packed));
+
+#define BLE_HCI_OCF_LE_RD_LOCAL_RESOLV_ADDR         (0x002C)
+struct ble_hci_le_rd_local_recolv_addr_cp {
+    uint8_t peer_addr_type;
+    uint8_t peer_id_addr[6];
+} __attribute__((packed));
+struct ble_hci_le_rd_local_recolv_addr_rp {
+    uint8_t rpa[6];
+} __attribute__((packed));
+
+#define BLE_HCI_OCF_LE_SET_ADDR_RES_EN              (0x002D)
+struct ble_hci_le_set_addr_res_en_cp {
+    uint8_t enable;
+} __attribute__((packed));
+
+#define BLE_HCI_OCF_LE_SET_RPA_TMO                  (0x002E)
+struct ble_hci_le_set_rpa_tmo_cp {
+    uint16_t rpa_timeout;
+} __attribute__((packed));
+
+#define BLE_HCI_OCF_LE_RD_MAX_DATA_LEN              (0x002F)
+struct ble_hci_le_rd_max_data_len_rp {
+    uint16_t max_tx_octests;
+    uint16_t max_tx_time;
+    uint16_t max_rx_octests;
+    uint16_t max_rx_time;
+} __attribute__((packed));
+
+#define BLE_HCI_OCF_LE_RD_PHY                       (0x0030)
+struct ble_hci_le_rd_phy_cp {
+    uint16_t conn_handle;
+} __attribute__((packed));
+struct ble_hci_le_rd_phy_rp {
+    uint16_t conn_handle;
+    uint8_t tx_phy;
+    uint8_t rx_phy;
+} __attribute__((packed));
+
+#define BLE_HCI_OCF_LE_SET_DEFAULT_PHY              (0x0031)
+struct ble_hci_le_set_default_phy_cp {
+    uint8_t all_phys;
+    uint8_t tx_phys;
+    uint8_t rx_phys;
+} __attribute__((packed));
+
+#define BLE_HCI_OCF_LE_SET_PHY                      (0x0032)
+struct ble_hci_le_set_phy_cp {
+    uint16_t conn_handle;
+    uint8_t all_phys;
+    uint8_t tx_phys;
+    uint8_t rx_phys;
+    uint16_t phy_options;
+} __attribute__((packed));
+
+#define BLE_HCI_OCF_LE_RX_TEST_V2                  (0x0033)
+struct ble_hci_le_rx_test_v2_cp {
+    uint8_t rx_chan;
+    uint8_t phy;
+    uint8_t index;
+} __attribute__((packed));
+
+#define BLE_HCI_OCF_LE_TX_TEST_V2                  (0x0034)
+struct ble_hci_le_tx_test_v2_cp {
+    uint8_t tx_chan;
+    uint8_t test_data_len;
+    uint8_t payload;
+    uint8_t phy;
+} __attribute__((packed));
+#if MYNEWT_VAL(BLE_LL_DTM_EXTENSIONS)
+struct ble_hci_le_tx_test_v2_ext_cp {
+    uint8_t tx_chan;
+    uint8_t test_data_len;
+    uint8_t payload;
+    uint8_t phy;
+    uint16_t interval;
+    uint16_t pkt_count;
+} __attribute__((packed));
+#endif
+
+#define BLE_HCI_OCF_LE_SET_ADV_SET_RND_ADDR         (0x0035)
+struct ble_hci_le_set_adv_set_rnd_addr_cp {
+    uint8_t adv_handle;
+    uint8_t addr[6];
+} __attribute__((packed));
+
+#define BLE_HCI_OCF_LE_SET_EXT_ADV_PARAM            (0x0036)
+struct ble_hci_le_set_ext_adv_params_cp {
+    uint8_t  adv_handle;
+    uint16_t props;
+    uint8_t  pri_itvl_min[3];
+    uint8_t  pri_itvl_max[3];
+    uint8_t pri_chan_map;
+    uint8_t own_addr_type;
+    uint8_t peer_addr_type;
+    uint8_t peer_addr[6];
+    uint8_t filter_policy;
+    int8_t tx_power;
+    uint8_t pri_phy;
+    uint8_t sec_max_skip;
+    uint8_t sec_phy;
+    uint8_t sid;
+    uint8_t scan_req_notif;
+} __attribute__((packed));
+struct ble_hci_le_set_ext_adv_params_rp {
+    int8_t  tx_power;
+} __attribute__((packed));
+
+#define BLE_HCI_OCF_LE_SET_EXT_ADV_DATA             (0x0037)
+struct ble_hci_le_set_ext_adv_data_cp {
+    uint8_t adv_handle;
+    uint8_t operation;
+    uint8_t fragment_pref;
+    uint8_t adv_data_len;
+    uint8_t adv_data[0];
+} __attribute__((packed));
+
+#define BLE_HCI_OCF_LE_SET_EXT_SCAN_RSP_DATA        (0x0038)
+struct ble_hci_le_set_ext_scan_rsp_data_cp {
+    uint8_t adv_handle;
+    uint8_t operation;
+    uint8_t fragment_pref;
+    uint8_t scan_rsp_len;
+    uint8_t scan_rsp[0];
+} __attribute__((packed));
+
+#define BLE_HCI_OCF_LE_SET_EXT_ADV_ENABLE           (0x0039)
+struct adv_set {
+    uint8_t adv_handle;
+    uint16_t duration;
+    uint8_t max_events;
+} __attribute__((packed));
+struct ble_hci_le_set_ext_adv_enable_cp {
+    uint8_t enable;
+    uint8_t num_sets;
+    struct adv_set sets[0];
+} __attribute__((packed));
+
+#define BLE_HCI_OCF_LE_RD_MAX_ADV_DATA_LEN          (0x003A)
+struct ble_hci_le_rd_max_adv_data_len_rp {
+    uint16_t max_adv_data_len;
+} __attribute__((packed));
+
+#define BLE_HCI_OCF_LE_RD_NUM_OF_ADV_SETS           (0x003B)
+struct ble_hci_le_rd_num_of_adv_sets_rp {
+    uint8_t num_sets;
+} __attribute__((packed));
+
+#define BLE_HCI_OCF_LE_REMOVE_ADV_SET               (0x003C)
+struct ble_hci_le_remove_adv_set_cp {
+    uint8_t adv_handle;
+} __attribute__((packed));
+
+#define BLE_HCI_OCF_LE_CLEAR_ADV_SETS               (0x003D)
+
+#define BLE_HCI_OCF_LE_SET_PERIODIC_ADV_PARAMS      (0x003E)
+struct ble_hci_le_set_periodic_adv_params_cp {
+    uint8_t adv_handle;
+    uint16_t min_itvl;
+    uint16_t max_itvl;
+    uint16_t props;
+} __attribute__((packed));
+
+#define BLE_HCI_OCF_LE_SET_PERIODIC_ADV_DATA        (0x003F)
+struct ble_hci_le_set_periodic_adv_data_cp {
+    uint8_t adv_handle;
+    uint8_t operation;
+    uint8_t adv_data_len;
+    uint8_t adv_data[0];
+} __attribute__((packed));
+
+#define BLE_HCI_OCF_LE_SET_PERIODIC_ADV_ENABLE      (0x0040)
+struct ble_hci_le_set_periodic_adv_enable_cp {
+    uint8_t enable;
+    uint8_t adv_handle;
+} __attribute__((packed));
+
+#define BLE_HCI_OCF_LE_SET_EXT_SCAN_PARAM           (0x0041)
+struct scan_params {
+    uint8_t  type;
+    uint16_t itvl;
+    uint16_t window;
+} __attribute__((packed));
+struct ble_hci_le_set_ext_scan_params_cp {
+    uint8_t own_addr_type;
+    uint8_t filter_policy;
+    uint8_t phys;
+    struct scan_params scans[0];
+} __attribute__((packed));
+
+#define BLE_HCI_OCF_LE_SET_EXT_SCAN_ENABLE          (0x0042)
+struct ble_hci_le_set_ext_scan_enable_cp {
+    uint8_t  enable;
+    uint8_t  filter_dup;
+    uint16_t duration;
+    uint16_t period;
+} __attribute__((packed));
+
+#define BLE_HCI_OCF_LE_EXT_CREATE_CONN              (0x0043)
+struct conn_params {
+    uint16_t scan_itvl;
+    uint16_t scan_window;
+    uint16_t conn_min_itvl;
+    uint16_t conn_max_itvl;
+    uint16_t conn_latency;
+    uint16_t supervision_timeout;
+    uint16_t min_ce;
+    uint16_t max_ce;
+} __attribute__((packed));
+struct ble_hci_le_ext_create_conn_cp {
+    uint8_t filter_policy;
+    uint8_t own_addr_type;
+    uint8_t peer_addr_type;
+    uint8_t peer_addr[6];
+    uint8_t init_phy_mask;
+    struct conn_params conn_params[0];
+} __attribute__((packed));
+
+#define BLE_HCI_LE_PERIODIC_ADV_CREATE_SYNC_OPT_FILTER      0x01
+#define BLE_HCI_LE_PERIODIC_ADV_CREATE_SYNC_OPT_DISABLED    0x02
+
+#define BLE_HCI_OCF_LE_PERIODIC_ADV_CREATE_SYNC          (0x0044)
+struct ble_hci_le_periodic_adv_create_sync_cp {
+    uint8_t  options;
+    uint8_t  sid;
+    uint8_t  peer_addr_type;
+    uint8_t  peer_addr[6];
+    uint16_t skip;
+    uint16_t sync_timeout;
+    uint8_t  sync_cte_type;
+} __attribute__((packed));
+
+#define BLE_HCI_OCF_LE_PERIODIC_ADV_CREATE_SYNC_CANCEL   (0x0045)
+
+#define BLE_HCI_OCF_LE_PERIODIC_ADV_TERM_SYNC            (0x0046)
+struct ble_hci_le_periodic_adv_term_sync_cp {
+    uint16_t sync_handle;
+} __attribute__((packed));
+
+#define BLE_HCI_OCF_LE_ADD_DEV_TO_PERIODIC_ADV_LIST      (0x0047)
+struct ble_hci_le_add_dev_to_periodic_adv_list_cp {
+    uint8_t peer_addr_type;
+    uint8_t peer_addr[6];
+    uint8_t sid;
+} __attribute__((packed));
+
+#define BLE_HCI_OCF_LE_REM_DEV_FROM_PERIODIC_ADV_LIST    (0x0048)
+struct ble_hci_le_rem_dev_from_periodic_adv_list_cp {
+    uint8_t peer_addr_type;
+    uint8_t peer_addr[6];
+    uint8_t sid;
+} __attribute__((packed));
+
+#define BLE_HCI_OCF_LE_CLEAR_PERIODIC_ADV_LIST           (0x0049)
+
+#define BLE_HCI_OCF_LE_RD_PERIODIC_ADV_LIST_SIZE         (0x004A)
+struct ble_hci_le_rd_periodic_adv_list_size_rp {
+    uint8_t list_size;
+} __attribute__((packed));
+
+#define BLE_HCI_OCF_LE_RD_TRANSMIT_POWER            (0x004B)
+struct ble_hci_le_rd_transmit_power_rp {
+    int8_t min_tx_power;
+    int8_t max_tx_power;
+} __attribute__((packed));
+
+#define BLE_HCI_OCF_LE_RD_RF_PATH_COMPENSATION      (0x004C)
+struct ble_hci_le_rd_rf_path_compensation_rp {
+    int16_t tx_path_compensation;
+    int16_t rx_path_compensation;
+} __attribute__((packed));
+
+#define BLE_HCI_OCF_LE_WR_RF_PATH_COMPENSATION      (0x004D)
+struct ble_hci_le_wr_rf_path_compensation_cp {
+    int16_t tx_path_compensation;
+    int16_t rx_path_compensation;
+} __attribute__((packed));
+
+#define BLE_HCI_OCF_LE_SET_PRIVACY_MODE             (0x004E)
+struct ble_hci_le_set_privacy_mode_cp {
+    uint8_t peer_id_addr_type;
+    uint8_t peer_id_addr[6];
+    uint8_t mode;
+} __attribute__((packed));
+
+#define BLE_HCI_OCF_LE_RX_TEST_V3                        (0x004F)
+#define BLE_HCI_OCF_LE_TX_TEST_V3                        (0x0050)
+#define BLE_HCI_OCF_LE_SET_CONNLESS_CTE_TX_PARAMS        (0x0051)
+#define BLE_HCI_OCF_LE_SET_CONNLESS_CTE_TX_ENABLE        (0x0052)
+#define BLE_HCI_OCF_LE_SET_CONNLESS_IQ_SAMPLING_ENABLE   (0x0053)
+#define BLE_HCI_OCF_LE_SET_CONN_CTE_RX_PARAMS            (0x0054)
+#define BLE_HCI_OCF_LE_SET_CONN_CTE_TX_PARAMS            (0x0055)
+#define BLE_HCI_OCF_LE_SET_CONN_CTE_REQ_ENABLE           (0x0056)
+#define BLE_HCI_OCF_LE_SET_CONN_CTE_RESP_ENABLE          (0x0057)
+#define BLE_HCI_OCF_LE_RD_ANTENNA_INFO                   (0x0058)
+
+#define BLE_HCI_OCF_LE_PERIODIC_ADV_RECEIVE_ENABLE       (0x0059)
+struct ble_hci_le_periodic_adv_receive_enable_cp {
+    uint16_t sync_handle;
+    uint8_t enable;
+} __attribute__((packed));
+
+#define BLE_HCI_OCF_LE_PERIODIC_ADV_SYNC_TRANSFER        (0x005A)
+struct ble_hci_le_periodic_adv_sync_transfer_cp {
+    uint16_t conn_handle;
+    uint16_t service_data;
+    uint16_t sync_handle;
+} __attribute__((packed));
+struct ble_hci_le_periodic_adv_sync_transfer_rp {
+    uint16_t conn_handle;
+} __attribute__((packed));
+
+#define BLE_HCI_OCF_LE_PERIODIC_ADV_SET_INFO_TRANSFER    (0x005B)
+struct ble_hci_le_periodic_adv_set_info_transfer_cp {
+    uint16_t conn_handle;
+    uint16_t service_data;
+    uint8_t adv_handle;
+} __attribute__((packed));
+struct ble_hci_le_periodic_adv_set_info_transfer_rp {
+    uint16_t conn_handle;
+} __attribute__((packed));
+
+#define BLE_HCI_OCF_LE_PERIODIC_ADV_SYNC_TRANSFER_PARAMS (0x005C)
+struct ble_hci_le_periodic_adv_sync_transfer_params_cp {
+    uint16_t conn_handle;
+    uint8_t  mode;
+    uint16_t skip;
+    uint16_t sync_timeout;
+    uint8_t  sync_cte_type;
+} __attribute__((packed));
+struct ble_hci_le_periodic_adv_sync_transfer_params_rp {
+    uint16_t conn_handle;
+} __attribute__((packed));
+
+#define BLE_HCI_OCF_LE_SET_DEFAULT_SYNC_TRANSFER_PARAMS  (0x005D)
+struct ble_hci_le_set_default_periodic_sync_transfer_params_cp {
+    uint8_t  mode;
+    uint16_t skip;
+    uint16_t sync_timeout;
+    uint8_t  sync_cte_type;
+} __attribute__((packed));
+
+#define BLE_HCI_OCF_LE_GENERATE_DHKEY_V2                 (0x005E)
+#define BLE_HCI_OCF_LE_MODIFY_SCA                        (0x005F)
+
+#if MYNEWT_VAL(BLE_ISO)
+#define BLE_HCI_OCF_LE_READ_ISO_TX_SYNC                  (0x0061)
+struct ble_hci_le_read_iso_tx_sync_cp {
+    uint16_t conn_handle;
+} __attribute__((packed));
+
+struct ble_hci_le_read_iso_tx_sync_rp {
+    uint16_t conn_handle;
+    uint16_t packet_seq_num;
+    uint32_t timestamp;
+    uint8_t timeoffset[3];
+} __attribute__((packed));
+
+#define BLE_HCI_LE_SET_CIG_CIS_MAX_NUM                   (0x1F)
+#define BLE_HCI_OCF_LE_SET_CIG_PARAM                     (0x0062)
+struct ble_hci_le_cis_params {
+    uint8_t cis_id;
+    uint16_t max_sdu_mtos;
+    uint16_t max_sdu_stom;
+    uint8_t phy_mtos;
+    uint8_t phy_stom;
+    uint8_t rnt_mtos;
+    uint8_t rnt_stom;
+} __attribute__((packed));
+
+struct ble_hci_le_set_cig_params_cp {
+    uint8_t cig_id;
+    uint8_t sdu_interval_mtos[3];
+    uint8_t sdu_interval_stom[3];
+    uint8_t sca;
+    uint8_t packing;
+    uint8_t framing;
+    uint16_t max_latency_mtos;
+    uint16_t max_latency_stom;
+    uint8_t cis_cnt;
+    struct ble_hci_le_cis_params cis_params[0];
+} __attribute__((packed));
+
+struct ble_hci_le_set_cig_params_rp {
+    uint8_t cig_id;
+    uint8_t cis_cnt;
+    uint16_t cis_handle[0];
+} __attribute__((packed));
+
+#if MYNEWT_VAL(BLE_ISO_TEST)
+#define BLE_HCI_OCF_LE_SET_CIG_PARAM_TEST                (0x0063)
+struct ble_hci_le_cis_params_test {
+    uint8_t cis_id;
+    uint8_t nse;
+    uint16_t max_sdu_mtos;
+    uint16_t max_sdu_stom;
+    uint16_t max_pdu_mtos;
+    uint16_t max_pdu_stom;
+    uint8_t phy_mtos;
+    uint8_t phy_stom;
+    uint8_t bn_mtos;
+    uint8_t bn_stom;
+} __attribute__((packed));
+
+struct ble_hci_le_set_cig_params_test_cp {
+    uint8_t cig_id;
+    uint8_t sdu_interval_mtos[3];
+    uint8_t sdu_interval_stom[3];
+    uint8_t ft_mtos;
+    uint8_t ft_stom;
+    uint16_t iso_interval;
+    uint8_t sca;
+    uint8_t packing;
+    uint8_t framing;
+    uint8_t cis_cnt;
+    struct ble_hci_le_cis_params_test cis_params[0];
+} __attribute__((packed));
+#endif
+
+#define BLE_HCI_LE_CREATE_CIS_MAX_CIS_NUM                (0x1F)
+#define BLE_HCI_OCF_LE_CREATE_CIS                        (0x0064)
+struct ble_hci_le_create_cis_params {
+    uint16_t cis_handle;
+    uint16_t conn_handle;
+} __attribute__((packed));
+
+struct ble_hci_le_create_cis_cp {
+    uint8_t cis_cnt;
+    struct ble_hci_le_create_cis_params params[0];
+} __attribute__((packed));
+
+#define BLE_HCI_OCF_LE_REMOVE_CIG                        (0x0065)
+struct ble_hci_le_remove_cig_cp {
+    uint8_t cig_id;
+} __attribute__((packed));
+
+struct ble_hci_le_remove_cig_rp {
+    uint8_t cig_id;
+} __attribute__((packed));
+
+#define BLE_HCI_OCF_LE_ACCEPT_CIS_REQ                    (0x0066)
+struct ble_hci_le_accept_cis_request_cp {
+    uint16_t cis_handle;
+} __attribute__((packed));
+
+#define BLE_HCI_OCF_LE_REJECT_CIS_REQ                    (0x0067)
+struct ble_hci_le_reject_cis_request_cp {
+    uint16_t cis_handle;
+    uint8_t reason;
+} __attribute__((packed));
+
+struct ble_hci_le_reject_cis_request_rp {
+    uint16_t conn_handle;
+} __attribute__((packed));
+
+#define BLE_HCI_OCF_LE_CREATE_BIG                        (0x0068)
+struct ble_hci_le_create_big_cp {
+    uint8_t big_handle;
+    uint8_t adv_handle;
+    uint8_t bis_cnt;
+    uint8_t sdu_interval[3];
+    uint16_t max_sdu;
+    uint16_t max_transport_latency;
+    uint8_t rnt;
+    uint8_t phy;
+    uint8_t packing;
+    uint8_t framing;
+    uint8_t encryption;
+    uint8_t broadcast_code[16];
+} __attribute__((packed));
+
+#if MYNEWT_VAL(BLE_ISO_TEST)
+#define BLE_HCI_OCF_LE_CREATE_BIG_TEST                   (0x0069)
+struct ble_hci_le_create_big_test_cp {
+    uint8_t big_handle;
+    uint8_t adv_handle;
+    uint8_t bis_cnt;
+    uint8_t sdu_interval[3];
+    uint16_t iso_interval;
+    uint8_t nse;
+    uint16_t max_sdu;
+    uint16_t max_pdu;
+    uint8_t phy;
+    uint8_t packing;
+    uint8_t framing;
+    uint8_t bn;
+    uint8_t irc;
+    uint8_t pto;
+    uint8_t encryption;
+    uint8_t broadcast_code[16];
+} __attribute__((packed));
+#endif
+
+#define BLE_HCI_OCF_LE_TERMINATE_BIG                     (0x006a)
+struct ble_hci_le_terminate_big_cp {
+    uint8_t big_handle;
+    uint8_t reason;
+} __attribute__((packed));
+
+#define BLE_HCI_LE_BIG_CREATE_SYNC_LEN_MIN               (25)
+#define BLE_HCI_OCF_LE_BIG_CREATE_SYNC                   (0x006b)
+struct ble_hci_le_big_create_sync_cp {
+    uint8_t big_handle;
+    uint16_t sync_handle;
+    uint8_t big_cnt;
+    uint8_t encryption;
+    uint8_t broadcast_code[16];
+    uint8_t mse;
+    uint16_t timeout;
+    uint8_t bis[0];
+} __attribute__((packed));
+
+#define BLE_HCI_OCF_LE_BIG_TERMINATE_SYNC                (0x006c)
+struct ble_hci_le_terminate_big_sync_cp {
+    uint8_t big_handle;
+} __attribute__((packed));
+#endif
+
+#define BLE_HCI_OCF_LE_REQ_PEER_SCA                      (0x006d)
+struct ble_hci_le_request_peer_sca_cp {
+    uint16_t conn_handle;
+} __attribute__((packed));
+
+#if MYNEWT_VAL(BLE_ISO)
+#define BLE_HCI_OCF_LE_SETUP_ISO_DATA_PATH               (0x006e)
+struct ble_hci_le_iso_setup_data_path_cp {
+    uint16_t iso_handle;
+    uint8_t direction;
+    uint8_t id;
+    uint8_t codec_id[5];
+    uint8_t controller_delay[3];
+    uint8_t codec_conf_len;
+    uint8_t codec_conf[0];
+} __attribute__((packed));
+
+#define BLE_HCI_LE_REMOVE_INPUT_DATA_PATH_BIT            (0x01)
+#define BLE_HCI_LE_REMOVE_OUTPUT_DATA_PATH_BIT           (0x02)
+#define BLE_HCI_OCF_LE_REMOVE_ISO_DATA_PATH              (0x006f)
+struct ble_hci_le_iso_remove_data_path_cp {
+    uint16_t iso_handle;
+    uint8_t direction;
+} __attribute__((packed));
+
+#if MYNEWT_VAL(BLE_ISO_TEST)
+#define BLE_HCI_OCF_LE_ISO_TRANSMIT_TEST                 (0x0070)
+struct ble_hci_le_iso_transmit_test_cp {
+    uint16_t iso_handle;
+    uint8_t payload_type;
+} __attribute__((packed));
+
+#define BLE_HCI_OCF_LE_ISO_RECEIVE_TEST                  (0x0071)
+struct ble_hci_le_iso_receive_test_cp {
+    uint16_t iso_handle;
+} __attribute__((packed));
+
+#define BLE_HCI_OCF_LE_ISO_READ_TEST_COUNTERS            (0x0072)
+struct ble_hci_le_iso_read_test_counters_cp {
+    uint16_t iso_handle;
+} __attribute__((packed));
+
+#define BLE_HCI_OCF_LE_ISO_TEST_END                      (0x0073)
+struct ble_hci_le_iso_test_end_cp {
+    uint16_t iso_handle;
+} __attribute__((packed));
+#endif
+#endif
+
+#define BLE_HCI_OCF_LE_SET_HOST_FEAT                     (0x0074)
+struct ble_hci_le_set_host_feat_cp {
+    uint8_t bit_num;
+    uint8_t val;
+} __attribute__((packed));
+
+/* --- Vendor specific commands (OGF 0x00FF) */
+#define BLE_HCI_OCF_VS_RD_STATIC_ADDR                 (0x0001)
+struct ble_hci_vs_rd_static_addr_rp {
+    uint8_t addr[6];
+} __attribute__((packed));
+
+/* Command Specific Definitions */
+/* --- Set controller to host flow control (OGF 0x03, OCF 0x0031) --- */
+#define BLE_HCI_CTLR_TO_HOST_FC_OFF         (0)
+#define BLE_HCI_CTLR_TO_HOST_FC_ACL         (1)
+#define BLE_HCI_CTLR_TO_HOST_FC_SYNC        (2)
+#define BLE_HCI_CTLR_TO_HOST_FC_BOTH        (3)
+
+/* --- LE set advertising parameters (OCF 0x0006) */
+/* Advertising types */
+#define BLE_HCI_ADV_TYPE_ADV_IND            (0)
+#define BLE_HCI_ADV_TYPE_ADV_DIRECT_IND_HD  (1)
+#define BLE_HCI_ADV_TYPE_ADV_SCAN_IND       (2)
+#define BLE_HCI_ADV_TYPE_ADV_NONCONN_IND    (3)
+#define BLE_HCI_ADV_TYPE_ADV_DIRECT_IND_LD  (4)
+#define BLE_HCI_ADV_TYPE_MAX                (4)
+
+#define BLE_HCI_ADV_CONN_MASK               (0x0001)
+#define BLE_HCI_ADV_SCAN_MASK               (0x0002)
+#define BLE_HCI_ADV_DIRECT_MASK             (0x0004)
+#define BLE_HCI_ADV_SCAN_RSP_MASK           (0x0008)
+#define BLE_HCI_ADV_LEGACY_MASK             (0x0010)
+
+#define BLE_HCI_ADV_DATA_STATUS_COMPLETE    (0x0000)
+#define BLE_HCI_ADV_DATA_STATUS_INCOMPLETE  (0x0020)
+#define BLE_HCI_ADV_DATA_STATUS_TRUNCATED   (0x0040)
+#define BLE_HCI_ADV_DATA_STATUS_MASK        (0x0060)
+
+/* Own address types */
+#define BLE_HCI_ADV_OWN_ADDR_PUBLIC         (0)
+#define BLE_HCI_ADV_OWN_ADDR_RANDOM         (1)
+#define BLE_HCI_ADV_OWN_ADDR_PRIV_PUB       (2)
+#define BLE_HCI_ADV_OWN_ADDR_PRIV_RAND      (3)
+#define BLE_HCI_ADV_OWN_ADDR_MAX            (3)
+
+/* Advertisement peer address Type */
+#define BLE_HCI_ADV_PEER_ADDR_PUBLIC        (0)
+#define BLE_HCI_ADV_PEER_ADDR_RANDOM        (1)
+#define BLE_HCI_ADV_PEER_ADDR_MAX           (1)
+
+/* --- LE advertising channel tx power (OCF 0x0007) */
+#define BLE_HCI_ADV_CHAN_TXPWR_MIN             (-20)
+#define BLE_HCI_ADV_CHAN_TXPWR_MAX             (10)
+
+/* --- LE set scan enable (OCF 0x000c) */
+
+/* Connect peer address type */
+#define BLE_HCI_CONN_PEER_ADDR_PUBLIC        (0)
+#define BLE_HCI_CONN_PEER_ADDR_RANDOM        (1)
+#define BLE_HCI_CONN_PEER_ADDR_PUBLIC_IDENT  (2)
+#define BLE_HCI_CONN_PEER_ADDR_RANDOM_IDENT  (3)
+#define BLE_HCI_CONN_PEER_ADDR_MAX           (3)
+
+/*
+ * Advertising filter policy
+ *
+ * Determines how an advertiser filters scan and connection requests.
+ *
+ *  NONE: no filtering (default value). No whitelist used.
+ *  SCAN: process all connection requests but only scans from white list.
+ *  CONN: process all scan request but only connection requests from white list
+ *  BOTH: ignore all scan and connection requests unless in white list.
+ */
+#define BLE_HCI_ADV_FILT_NONE               (0)
+#define BLE_HCI_ADV_FILT_SCAN               (1)
+#define BLE_HCI_ADV_FILT_CONN               (2)
+#define BLE_HCI_ADV_FILT_BOTH               (3)
+#define BLE_HCI_ADV_FILT_MAX                (3)
+
+#define BLE_HCI_ADV_FILT_DEF                (BLE_HCI_ADV_FILT_NONE)
+
+/* Advertising interval */
+#define BLE_HCI_ADV_ITVL                    (625)           /* usecs */
+#define BLE_HCI_ADV_ITVL_MIN                (32)            /* units */
+#define BLE_HCI_ADV_ITVL_MAX                (16384)         /* units */
+#define BLE_HCI_ADV_ITVL_NONCONN_MIN        (160)           /* units */
+
+#define BLE_HCI_ADV_ITVL_DEF                (0x800)         /* 1.28 seconds */
+#define BLE_HCI_ADV_CHANMASK_DEF            (0x7)           /* all channels */
+
+/* Set scan parameters */
+#define BLE_HCI_SCAN_TYPE_PASSIVE           (0)
+#define BLE_HCI_SCAN_TYPE_ACTIVE            (1)
+
+/* Scan interval and scan window timing */
+#define BLE_HCI_SCAN_ITVL                   (625)           /* usecs */
+#define BLE_HCI_SCAN_ITVL_MIN               (4)             /* units */
+#define BLE_HCI_SCAN_ITVL_MAX               (16384)         /* units */
+#define BLE_HCI_SCAN_ITVL_DEF               (16)            /* units */
+#define BLE_HCI_SCAN_WINDOW_MIN             (4)             /* units */
+#define BLE_HCI_SCAN_WINDOW_MAX             (16384)         /* units */
+#define BLE_HCI_SCAN_WINDOW_DEF             (16)            /* units */
+
+/*
+ * Scanning filter policy
+ *  NO_WL:
+ *      Scanner processes all advertising packets (white list not used) except
+ *      directed, connectable advertising packets not sent to the scanner.
+ *  USE_WL:
+ *      Scanner processes advertisements from white list only. A connectable,
+ *      directed advertisment is ignored unless it contains scanners address.
+ *  NO_WL_INITA:
+ *      Scanner process all advertising packets (white list not used). A
+ *      connectable, directed advertisement shall not be ignored if the InitA
+ *      is a resolvable private address.
+ *  USE_WL_INITA:
+ *      Scanner process advertisements from white list only. A connectable,
+ *      directed advertisement shall not be ignored if the InitA is a
+ *      resolvable private address.
+ */
+#define BLE_HCI_SCAN_FILT_NO_WL             (0)
+#define BLE_HCI_SCAN_FILT_USE_WL            (1)
+#define BLE_HCI_SCAN_FILT_NO_WL_INITA       (2)
+#define BLE_HCI_SCAN_FILT_USE_WL_INITA      (3)
+#define BLE_HCI_SCAN_FILT_MAX               (3)
+
+/* Whitelist commands */
+#define BLE_HCI_ADD_WHITE_LIST_LEN          (7)
+#define BLE_HCI_RMV_WHITE_LIST_LEN          (7)
+
+/* Create Connection */
+#define BLE_HCI_CREATE_CONN_LEN             (25)
+#define BLE_HCI_CONN_ITVL                   (1250)  /* usecs */
+#define BLE_HCI_CONN_FILT_NO_WL             (0)
+#define BLE_HCI_CONN_FILT_USE_WL            (1)
+#define BLE_HCI_CONN_FILT_MAX               (1)
+#define BLE_HCI_CONN_ITVL_MIN               (0x0006)
+#define BLE_HCI_CONN_ITVL_MAX               (0x0c80)
+#define BLE_HCI_CONN_LATENCY_MIN            (0x0000)
+#define BLE_HCI_CONN_LATENCY_MAX            (0x01f3)
+#define BLE_HCI_CONN_SPVN_TIMEOUT_MIN       (0x000a)
+#define BLE_HCI_CONN_SPVN_TIMEOUT_MAX       (0x0c80)
+#define BLE_HCI_CONN_SPVN_TMO_UNITS         (10)    /* msecs */
+#define BLE_HCI_INITIATOR_FILT_POLICY_MAX   (1)
+
+/* Peer Address Type */
+#define BLE_HCI_CONN_PEER_ADDR_PUBLIC       (0)
+#define BLE_HCI_CONN_PEER_ADDR_RANDOM       (1)
+#define BLE_HCI_CONN_PEER_ADDR_PUB_ID       (2)
+#define BLE_HCI_CONN_PEER_ADDR_RAND_ID      (3)
+#define BLE_HCI_CONN_PEER_ADDR_MAX          (3)
+
+
+/* --- LE set data length (OCF 0x0022) */
+#define BLE_HCI_SET_DATALEN_TX_OCTETS_MIN   (0x001b)
+#define BLE_HCI_SET_DATALEN_TX_OCTETS_MAX   (0x00fb)
+#define BLE_HCI_SET_DATALEN_TX_TIME_MIN     (0x0148)
+#define BLE_HCI_SET_DATALEN_TX_TIME_MAX     (0x4290)
+
+/* --- LE read maximum default PHY (OCF 0x0030) */
+#define BLE_HCI_LE_PHY_1M                   (1)
+#define BLE_HCI_LE_PHY_2M                   (2)
+#define BLE_HCI_LE_PHY_CODED                (3)
+
+/* --- LE set default PHY (OCF 0x0031) */
+#define BLE_HCI_LE_PHY_NO_TX_PREF_MASK              (0x01)
+#define BLE_HCI_LE_PHY_NO_RX_PREF_MASK              (0x02)
+#define BLE_HCI_LE_PHY_1M_PREF_MASK                 (0x01)
+#define BLE_HCI_LE_PHY_2M_PREF_MASK                 (0x02)
+#define BLE_HCI_LE_PHY_CODED_PREF_MASK              (0x04)
+
+#define BLE_HCI_LE_PHY_PREF_MASK_ALL                \
+    (BLE_HCI_LE_PHY_1M_PREF_MASK | BLE_HCI_LE_PHY_2M_PREF_MASK |  \
+     BLE_HCI_LE_PHY_CODED_PREF_MASK)
+
+/* --- LE set PHY (OCF 0x0032) */
+#define BLE_HCI_LE_PHY_CODED_ANY                    (0x0000)
+#define BLE_HCI_LE_PHY_CODED_S2_PREF                (0x0001)
+#define BLE_HCI_LE_PHY_CODED_S8_PREF                (0x0002)
+
+/* --- LE enhanced receiver test (OCF 0x0033) */
+#define BLE_HCI_LE_PHY_1M                           (1)
+#define BLE_HCI_LE_PHY_2M                           (2)
+#define BLE_HCI_LE_PHY_CODED                        (3)
+
+/* --- LE enhanced transmitter test (OCF 0x0034) */
+#define BLE_HCI_LE_PHY_CODED_S8                     (3)
+#define BLE_HCI_LE_PHY_CODED_S2                     (4)
+
+/* --- LE set extended advertising parameters (OCF 0x0036) */
+#define BLE_HCI_LE_SET_EXT_ADV_PROP_CONNECTABLE     (0x0001)
+#define BLE_HCI_LE_SET_EXT_ADV_PROP_SCANNABLE       (0x0002)
+#define BLE_HCI_LE_SET_EXT_ADV_PROP_DIRECTED        (0x0004)
+#define BLE_HCI_LE_SET_EXT_ADV_PROP_HD_DIRECTED     (0x0008)
+#define BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY          (0x0010)
+#define BLE_HCI_LE_SET_EXT_ADV_PROP_ANON_ADV        (0x0020)
+#define BLE_HCI_LE_SET_EXT_ADV_PROP_INC_TX_PWR      (0x0040)
+#define BLE_HCI_LE_SET_EXT_ADV_PROP_MASK            (0x7F)
+
+#define BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY_IND      (0x0013)
+#define BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY_LD_DIR   (0x0015)
+#define BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY_HD_DIR   (0x001d)
+#define BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY_SCAN     (0x0012)
+#define BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY_NONCONN  (0x0010)
+
+/* --- LE set extended advertising data (OCF 0x0037) */
+#define BLE_HCI_MAX_EXT_ADV_DATA_LEN                (251)
+
+#define BLE_HCI_LE_SET_DATA_OPER_INT        (0)
+#define BLE_HCI_LE_SET_DATA_OPER_FIRST      (1)
+#define BLE_HCI_LE_SET_DATA_OPER_LAST       (2)
+#define BLE_HCI_LE_SET_DATA_OPER_COMPLETE   (3)
+#define BLE_HCI_LE_SET_DATA_OPER_UNCHANGED  (4)
+
+/* --- LE set extended scan response data (OCF 0x0038) */
+#define BLE_HCI_MAX_EXT_SCAN_RSP_DATA_LEN           (251)
+
+/* --- LE set periodic advertising parameters (OCF 0x003E) */
+#define BLE_HCI_LE_SET_PERIODIC_ADV_PROP_INC_TX_PWR (0x0040)
+#define BLE_HCI_LE_SET_PERIODIC_ADV_PROP_MASK       (0x0040)
+
+/* --- LE set periodic advertising data (OCF 0x003F) */
+#define BLE_HCI_MAX_PERIODIC_ADV_DATA_LEN                (252)
+
+/* --- LE remove device from periodic advertising list (OCF 0x0048) */
+#define BLE_HCI_PERIODIC_DATA_STATUS_COMPLETE   0x00
+#define BLE_HCI_PERIODIC_DATA_STATUS_INCOMPLETE 0x01
+#define BLE_HCI_PERIODIC_DATA_STATUS_TRUNCATED  0x02
+
+/* --- LE set privacy mode (OCF 0x004E) */
+#define BLE_HCI_PRIVACY_NETWORK                     (0)
+#define BLE_HCI_PRIVACY_DEVICE                      (1)
+
+/* Event Codes */
+#define BLE_HCI_EVCODE_INQUIRY_CMP          (0x01)
+#define BLE_HCI_EVCODE_INQUIRY_RESULT       (0x02)
+#define BLE_HCI_EVCODE_CONN_DONE            (0x03)
+#define BLE_HCI_EVCODE_CONN_REQUEST         (0x04)
+#define BLE_HCI_EVCODE_DISCONN_CMP          (0x05)
+struct ble_hci_ev_disconn_cmp {
+    uint8_t status;
+    uint16_t conn_handle;
+    uint8_t reason;
+} __attribute__((packed));
+
+#define BLE_HCI_EVCODE_AUTH_CMP             (0x06)
+#define BLE_HCI_EVCODE_REM_NAME_REQ_CMP     (0x07)
+
+#define BLE_HCI_EVCODE_ENCRYPT_CHG          (0x08)
+struct ble_hci_ev_enrypt_chg {
+    uint8_t status;
+    uint16_t connection_handle;
+    uint8_t enabled;
+} __attribute__((packed));
+
+#define BLE_HCI_EVCODE_CHG_LINK_KEY_CMP     (0x09)
+#define BLE_HCI_EVCODE_MASTER_LINK_KEY_CMP  (0x0A)
+#define BLE_HCI_EVCODE_RD_REM_SUPP_FEAT_CMP (0x0B)
+#define BLE_HCI_EVCODE_RD_REM_VER_INFO_CMP  (0x0C)
+struct ble_hci_ev_rd_rem_ver_info_cmp {
+    uint8_t  status;
+    uint16_t conn_handle;
+    uint8_t  version;
+    uint16_t manufacturer;
+    uint16_t subversion;
+} __attribute__((packed));
+
+#define BLE_HCI_EVCODE_QOS_SETUP_CMP        (0x0D)
+
+#define BLE_HCI_EVCODE_COMMAND_COMPLETE     (0x0E)
+struct ble_hci_ev_command_complete {
+    uint8_t  num_packets;
+    uint16_t opcode;
+    uint8_t  status;
+    uint8_t  return_params[0];
+} __attribute__((packed));
+/* NOP is exception and has no return parameters */
+struct ble_hci_ev_command_complete_nop {
+    uint8_t  num_packets;
+    uint16_t opcode;
+} __attribute__((packed));
+
+#define BLE_HCI_EVCODE_COMMAND_STATUS       (0x0F)
+struct ble_hci_ev_command_status {
+    uint8_t status;
+    uint8_t  num_packets;
+    uint16_t opcode;
+} __attribute__((packed));
+
+#define BLE_HCI_EVCODE_HW_ERROR             (0x10)
+struct ble_hci_ev_hw_error {
+    uint8_t hw_code;
+} __attribute__((packed));
+
+#define BLE_HCI_EVCODE_NUM_COMP_PKTS        (0x13)
+struct comp_pkt {
+    uint16_t handle;
+    uint16_t packets;
+} __attribute__((packed));;
+struct ble_hci_ev_num_comp_pkts {
+    uint8_t count;
+    struct comp_pkt completed[0];
+} __attribute__((packed));
+
+#define BLE_HCI_EVCODE_MODE_CHANGE          (0x14)
+#define BLE_HCI_EVCODE_RETURN_LINK_KEYS     (0x15)
+#define BLE_HCI_EVCODE_PIN_CODE_REQ         (0x16)
+#define BLE_HCI_EVCODE_LINK_KEY_REQ         (0x17)
+#define BLE_HCI_EVCODE_LINK_KEY_NOTIFY      (0x18)
+#define BLE_HCI_EVCODE_LOOPBACK_CMD         (0x19)
+
+#define BLE_HCI_EVCODE_DATA_BUF_OVERFLOW    (0x1A)
+struct ble_hci_ev_data_buf_overflow {
+    uint8_t link_type;
+} __attribute__((packed));
+
+#define BLE_HCI_EVCODE_MAX_SLOTS_CHG        (0x1B)
+#define BLE_HCI_EVCODE_READ_CLK_OFF_COMP    (0x1C)
+#define BLE_HCI_EVCODE_CONN_PKT_TYPE_CHG    (0x1D)
+#define BLE_HCI_EVCODE_QOS_VIOLATION        (0x1E)
+/* NOTE: 0x1F not defined */
+#define BLE_HCI_EVCODE_PSR_MODE_CHG         (0x20)
+#define BLE_HCI_EVCODE_FLOW_SPEC_COMP       (0x21)
+#define BLE_HCI_EVCODE_INQ_RESULT_RSSI      (0x22)
+#define BLE_HCI_EVCODE_READ_REM_EXT_FEAT    (0x23)
+/* NOTE: 0x24 - 0x2B not defined */
+#define BLE_HCI_EVCODE_SYNCH_CONN_COMP      (0x2C)
+#define BLE_HCI_EVCODE_SYNCH_CONN_CHG       (0x2D)
+#define BLE_HCI_EVCODE_SNIFF_SUBRATING      (0x2E)
+#define BLE_HCI_EVCODE_EXT_INQ_RESULT       (0x2F)
+
+#define BLE_HCI_EVCODE_ENC_KEY_REFRESH      (0x30)
+struct ble_hci_ev_enc_key_refresh {
+    uint8_t status;
+    uint16_t conn_handle;
+} __attribute__((packed));
+
+#define BLE_HCI_EVOCDE_IO_CAP_REQ           (0x31)
+#define BLE_HCI_EVCODE_IO_CAP_RSP           (0x32)
+#define BLE_HCI_EVCODE_USER_CONFIRM_REQ     (0x33)
+#define BLE_HCI_EVCODE_PASSKEY_REQ          (0x34)
+#define BLE_HCI_EVCODE_REM_OOB_DATA_REQ     (0x35)
+#define BLE_HCI_EVCODE_SIMPLE_PAIR_COMP     (0x36)
+/* NOTE: 0x37 not defined */
+#define BLE_HCI_EVCODE_LNK_SPVN_TMO_CHG     (0x38)
+#define BLE_HCI_EVCODE_ENH_FLUSH_COMP       (0x39)
+#define BLE_HCI_EVCODE_USER_PASSKEY_NOTIFY  (0x3B)
+#define BLE_HCI_EVCODE_KEYPRESS_NOTIFY      (0x3C)
+#define BLE_HCI_EVCODE_REM_HOST_SUPP_FEAT   (0x3D)
+
+#define BLE_HCI_EVCODE_LE_META              (0x3E)
+struct ble_hci_ev_le_meta {
+    uint8_t subevent;
+    uint8_t data[0];
+} __attribute__((packed));
+
+/* NOTE: 0x3F not defined */
+#define BLE_HCI_EVCODE_PHYS_LINK_COMP       (0x40)
+#define BLE_HCI_EVCODE_CHAN_SELECTED        (0x41)
+#define BLE_HCI_EVCODE_DISCONN_PHYS_LINK    (0x42)
+#define BLE_HCI_EVCODE_PHYS_LINK_LOSS_EARLY (0x43)
+#define BLE_HCI_EVCODE_PHYS_LINK_RECOVERY   (0x44)
+#define BLE_HCI_EVCODE_LOGICAL_LINK_COMP    (0x45)
+#define BLE_HCI_EVCODE_DISCONN_LOGICAL_LINK (0x46)
+#define BLE_HCI_EVCODE_FLOW_SPEC_MODE_COMP  (0x47)
+#define BLE_HCI_EVCODE_NUM_COMP_DATA_BLKS   (0x48)
+#define BLE_HCI_EVCODE_AMP_START_TEST       (0x49)
+#define BLE_HCI_EVOCDE_AMP_TEST_END         (0x4A)
+#define BLE_HCI_EVOCDE_AMP_RCVR_REPORT      (0x4B)
+#define BLE_HCI_EVCODE_SHORT_RANGE_MODE_CHG (0x4C)
+#define BLE_HCI_EVCODE_AMP_STATUS_CHG       (0x4D)
+#define BLE_HCI_EVCODE_TRIG_CLK_CAPTURE     (0x4E)
+#define BLE_HCI_EVCODE_SYNCH_TRAIN_COMP     (0x4F)
+#define BLE_HCI_EVCODE_SYNCH_TRAIN_RCVD     (0x50)
+#define BLE_HCI_EVCODE_SLAVE_BCAST_RX       (0x51)
+#define BLE_HCI_EVCODE_SLAVE_BCAST_TMO      (0x52)
+#define BLE_HCI_EVCODE_TRUNC_PAGE_COMP      (0x53)
+#define BLE_HCI_EVCODE_SLAVE_PAGE_RSP_TMO   (0x54)
+#define BLE_HCI_EVCODE_SLAVE_BCAST_CHAN_MAP (0x55)
+#define BLE_HCI_EVCODE_INQ_RSP_NOTIFY       (0x56)
+
+#define BLE_HCI_EVCODE_AUTH_PYLD_TMO        (0x57)
+struct ble_hci_ev_auth_pyld_tmo {
+    uint16_t conn_handle;
+} __attribute__((packed));
+
+#define BLE_HCI_EVCODE_SAM_STATUS_CHG       (0x58)
+
+#define BLE_HCI_EVCODE_VENDOR_DEBUG         (0xFF)
+struct ble_hci_ev_vendor_debug {
+    uint8_t id;
+    uint8_t data[0];
+} __attribute__((packed));
+
+/* LE sub-event codes */
+#define BLE_HCI_LE_SUBEV_CONN_COMPLETE          (0x01)
+struct ble_hci_ev_le_subev_conn_complete {
+    uint8_t  subev_code;
+    uint8_t  status;
+    uint16_t conn_handle;
+    uint8_t  role;
+    uint8_t  peer_addr_type;
+    uint8_t  peer_addr[6];
+    uint16_t conn_itvl;
+    uint16_t conn_latency;
+    uint16_t supervision_timeout;
+    uint8_t  mca;
+} __attribute__((packed));
+
+#define BLE_HCI_LE_SUBEV_ADV_RPT                (0x02)
+struct adv_report {
+    uint8_t type;
+    uint8_t addr_type;
+    uint8_t addr[6];
+    uint8_t data_len;
+    uint8_t data[0];
+} __attribute__((packed));
+struct ble_hci_ev_le_subev_adv_rpt {
+    uint8_t  subev_code;
+    uint8_t  num_reports;
+    struct adv_report reports[0];
+} __attribute__((packed));
+
+#define BLE_HCI_LE_SUBEV_CONN_UPD_COMPLETE      (0x03)
+struct ble_hci_ev_le_subev_conn_upd_complete {
+    uint8_t  subev_code;
+    uint8_t  status;
+    uint16_t conn_handle;
+    uint16_t conn_itvl;
+    uint16_t conn_latency;
+    uint16_t supervision_timeout;
+} __attribute__((packed));
+
+#define BLE_HCI_LE_SUBEV_RD_REM_USED_FEAT       (0x04)
+struct ble_hci_ev_le_subev_rd_rem_used_feat {
+    uint8_t  subev_code;
+    uint8_t  status;
+    uint16_t conn_handle;
+    uint8_t features[8];
+} __attribute__((packed));
+
+#define BLE_HCI_LE_SUBEV_LT_KEY_REQ             (0x05)
+struct ble_hci_ev_le_subev_lt_key_req {
+    uint8_t  subev_code;
+    uint16_t conn_handle;
+    uint64_t rand;
+    uint16_t div;
+} __attribute__((packed));
+
+#define BLE_HCI_LE_SUBEV_REM_CONN_PARM_REQ      (0x06)
+struct ble_hci_ev_le_subev_rem_conn_param_req {
+    uint8_t  subev_code;
+    uint16_t conn_handle;
+    uint16_t min_interval;
+    uint16_t max_interval;
+    uint16_t latency;
+    uint16_t timeout;
+} __attribute__((packed));
+
+#define BLE_HCI_LE_SUBEV_DATA_LEN_CHG           (0x07)
+struct ble_hci_ev_le_subev_data_len_chg {
+    uint8_t  subev_code;
+    uint16_t conn_handle;
+    uint16_t max_tx_octets;
+    uint16_t max_tx_time;
+    uint16_t max_rx_octets;
+    uint16_t max_rx_time;
+} __attribute__((packed));
+
+#define BLE_HCI_LE_SUBEV_RD_LOC_P256_PUBKEY     (0x08)
+struct ble_hci_ev_le_subev_rd_loc_p256_pubkey {
+    uint8_t subev_code;
+    uint8_t status;
+    uint8_t public_key[64];
+} __attribute__((packed));
+
+#define BLE_HCI_LE_SUBEV_GEN_DHKEY_COMPLETE     (0x09)
+struct ble_hci_ev_le_subev_gen_dhkey_complete {
+    uint8_t subev_code;
+    uint8_t status;
+    uint8_t dh_key[32];
+} __attribute__((packed));
+
+#define BLE_HCI_LE_SUBEV_ENH_CONN_COMPLETE      (0x0A)
+struct ble_hci_ev_le_subev_enh_conn_complete {
+    uint8_t  subev_code;
+    uint8_t  status;
+    uint16_t conn_handle;
+    uint8_t  role;
+    uint8_t  peer_addr_type;
+    uint8_t  peer_addr[6];
+    uint8_t  local_rpa[6];
+    uint8_t  peer_rpa[6];
+    uint16_t conn_itvl;
+    uint16_t conn_latency;
+    uint16_t supervision_timeout;
+    uint8_t  mca;
+} __attribute__((packed));
+
+#define BLE_HCI_LE_SUBEV_DIRECT_ADV_RPT         (0x0B)
+struct dir_adv_report {
+    uint8_t type;
+    uint8_t addr_type;
+    uint8_t addr[6];
+    uint8_t dir_addr_type;
+    uint8_t dir_addr[6];
+    int8_t  rssi;
+} __attribute__((packed));
+struct ble_hci_ev_le_subev_direct_adv_rpt {
+    uint8_t subev_code;
+    uint8_t num_reports;
+    struct dir_adv_report reports[0];
+} __attribute__((packed));
+
+#define BLE_HCI_LE_SUBEV_PHY_UPDATE_COMPLETE    (0x0C)
+struct ble_hci_ev_le_subev_phy_update_complete {
+    uint8_t  subev_code;
+    uint8_t  status;
+    uint16_t conn_handle;
+    uint8_t  tx_phy;
+    uint8_t  rx_phy;
+} __attribute__((packed));
+
+#define BLE_HCI_LE_SUBEV_EXT_ADV_RPT            (0x0D)
+struct ext_adv_report {
+    uint16_t  evt_type;
+    uint8_t  addr_type;
+    uint8_t  addr[6];
+    uint8_t  pri_phy;
+    uint8_t  sec_phy;
+    uint8_t  sid;
+    int8_t   tx_power;
+    int8_t   rssi;
+    uint16_t periodic_itvl;
+    uint8_t  dir_addr_type;
+    uint8_t  dir_addr[6];
+    uint8_t  data_len;
+    uint8_t  data[0];
+} __attribute__((packed));
+struct ble_hci_ev_le_subev_ext_adv_rpt {
+    uint8_t subev_code;
+    uint8_t num_reports;
+    struct ext_adv_report reports[0];
+} __attribute__((packed));
+
+#define BLE_HCI_LE_SUBEV_PERIODIC_ADV_SYNC_ESTAB     (0x0E)
+struct ble_hci_ev_le_subev_periodic_adv_sync_estab {
+    uint8_t  subev_code;
+    uint8_t  status;
+    uint16_t sync_handle;
+    uint8_t  sid;
+    uint8_t  peer_addr_type;
+    uint8_t  peer_addr[6];
+    uint8_t  phy;
+    uint16_t interval;
+    uint8_t  aca;
+} __attribute__((packed));
+
+#define BLE_HCI_LE_SUBEV_PERIODIC_ADV_RPT            (0x0F)
+struct ble_hci_ev_le_subev_periodic_adv_rpt {
+    uint8_t  subev_code;
+    uint16_t sync_handle;
+    int8_t   tx_power;
+    int8_t   rssi;
+    uint8_t  cte_type;
+    uint8_t  data_status;
+    uint8_t  data_len;
+    uint8_t  data[0];
+} __attribute__((packed));
+
+#define BLE_HCI_LE_SUBEV_PERIODIC_ADV_SYNC_LOST      (0x10)
+struct ble_hci_ev_le_subev_periodic_adv_sync_lost {
+    uint8_t  subev_code;
+    uint16_t sync_handle;
+} __attribute__((packed));
+
+#define BLE_HCI_LE_SUBEV_SCAN_TIMEOUT           (0x11)
+struct ble_hci_ev_le_subev_scan_timeout {
+    uint8_t  subev_code;
+} __attribute__((packed));
+
+#define BLE_HCI_LE_SUBEV_ADV_SET_TERMINATED     (0x12)
+struct ble_hci_ev_le_subev_adv_set_terminated {
+    uint8_t  subev_code;
+    uint8_t  status;
+    uint8_t  adv_handle;
+    uint16_t conn_handle;
+    uint8_t  num_events;
+} __attribute__((packed));
+
+#define BLE_HCI_LE_SUBEV_SCAN_REQ_RCVD          (0x13)
+struct ble_hci_ev_le_subev_scan_req_rcvd {
+    uint8_t subev_code;
+    uint8_t adv_handle;
+    uint8_t peer_addr_type;
+    uint8_t peer_addr[6];
+} __attribute__((packed));
+
+#define BLE_HCI_LE_SUBEV_CHAN_SEL_ALG           (0x14)
+struct ble_hci_ev_le_subev_chan_sel_alg {
+    uint8_t  subev_code;
+    uint16_t conn_handle;
+    uint8_t  csa;
+} __attribute__((packed));
+
+#define BLE_HCI_LE_SUBEV_CONNLESS_IQ_RPT        (0x15)
+#define BLE_HCI_LE_SUBEV_CONN_IQ_RPT            (0x16)
+#define BLE_HCI_LE_SUBEV_CTE_REQ_FAILED         (0x17)
+
+#define BLE_HCI_LE_SUBEV_PERIODIC_ADV_SYNC_TRANSFER   (0x18)
+struct ble_hci_ev_le_subev_periodic_adv_sync_transfer {
+    uint8_t  subev_code;
+    uint8_t  status;
+    uint16_t conn_handle;
+    uint16_t service_data;
+    uint16_t sync_handle;
+    uint8_t  sid;
+    uint8_t  peer_addr_type;
+    uint8_t  peer_addr[6];
+    uint8_t  phy;
+    uint16_t interval;
+    uint8_t  aca;
+} __attribute__((packed));
+
+#define BLE_HCI_LE_SUBEV_CIS_ESTAB              (0x19)
+struct ble_hci_ev_le_subev_cis_established {
+    uint8_t subev_code;
+    uint8_t status;
+    uint16_t cis_handle;
+    uint8_t cig_sync_delay[3];
+    uint8_t cis_sync_delay[3];
+    uint8_t trans_latency_mtos[3];
+    uint8_t trans_latency_stom[3];
+    uint8_t phy_mtos;
+    uint8_t phy_stom;
+    uint8_t nse;
+    uint8_t bn_mtos;
+    uint8_t bn_stom;
+    uint8_t ft_mtos;
+    uint8_t ft_stom;
+    uint16_t max_pdu_mtos;
+    uint16_t max_pdu_stom;
+    uint16_t iso_interval;
+} __attribute__((packed));
+
+#define BLE_HCI_LE_SUBEV_CIS_REQUEST            (0x1A)
+struct ble_hci_ev_le_subev_cis_request {
+    uint8_t subev_code;
+    uint16_t conn_handle;
+    uint16_t cis_handle;
+    uint8_t cig_id;
+    uint8_t cis_id;
+} __attribute__((packed));
+
+#define BLE_HCI_LE_SUBEV_BIG_COMP               (0x1B)
+struct ble_hci_ev_le_subev_big_complete {
+    uint8_t subev_code;
+    uint8_t status;
+    uint8_t big_handle;
+    uint8_t big_sync_delay[3];
+    uint8_t transport_latency[3];
+    uint8_t phy;
+    uint8_t nse;
+    uint8_t bn;
+    uint8_t pto;
+    uint8_t irc;
+    uint16_t max_pdu;
+    uint16_t iso_interval;
+    uint8_t bis_cnt;
+    uint16_t bis[0];
+} __attribute__((packed));
+
+#define BLE_HCI_LE_SUBEV_BIG_TERMINATE_COMP     (0x1C)
+struct ble_hci_ev_le_subev_big_terminate_complete {
+    uint8_t subev_code;
+    uint8_t big_handle;
+    uint8_t reason;
+} __attribute__((packed));
+
+#define BLE_HCI_LE_SUBEV_BIG_SYNC_ESTAB         (0x1D)
+struct ble_hci_ev_le_subev_big_sync_established {
+    uint8_t subev_code;
+    uint8_t status;
+    uint8_t big_handle;
+    uint8_t transport_latency[3];
+    uint8_t nse;
+    uint8_t bn;
+    uint8_t pto;
+    uint8_t irc;
+    uint16_t max_pdu;
+    uint16_t iso_interval;
+    uint8_t bis_cnt;
+    uint16_t bis_handles[0];
+} __attribute__((packed));
+
+#define BLE_HCI_LE_SUBEV_BIG_SYNC_LOST          (0x1E)
+struct ble_hci_ev_le_subev_big_sync_lost {
+    uint8_t subev_code;
+    uint8_t big_handle;
+    uint8_t reason;
+} __attribute__((packed));
+
+#define BLE_HCI_LE_SUBEV_REQ_PEER_SCA_COMP      (0x1F)
+struct ble_hci_ev_le_subev_peer_sca_complete {
+    uint8_t subev_code;
+    uint8_t status;
+    uint16_t conn_handle;
+    uint8_t sca;
+} __attribute__((packed));
+
+#define BLE_HCI_LE_SUBEV_BIGINFO_ADV_REPORT         (0x22)
+struct ble_hci_ev_le_subev_biginfo_adv_report {
+    uint8_t subev_code;
+    uint16_t sync_handle;
+    uint8_t bis_cnt;
+    uint8_t nse;
+    uint16_t iso_interval;
+    uint8_t bn;
+    uint8_t pto;
+    uint8_t irc;
+    uint16_t max_pdu;
+    uint8_t sdu_interval[3];
+    uint16_t max_sdu;
+    uint8_t phy;
+    uint8_t framing;
+    uint8_t encryption;
+} __attribute__((packed));
+
+/* Data buffer overflow event */
+#define BLE_HCI_EVENT_ACL_BUF_OVERFLOW      (0x01)
+
+/* Advertising report */
+#define BLE_HCI_ADV_RPT_EVTYPE_ADV_IND      (0)
+#define BLE_HCI_ADV_RPT_EVTYPE_DIR_IND      (1)
+#define BLE_HCI_ADV_RPT_EVTYPE_SCAN_IND     (2)
+#define BLE_HCI_ADV_RPT_EVTYPE_NONCONN_IND  (3)
+#define BLE_HCI_ADV_RPT_EVTYPE_SCAN_RSP     (4)
+
+/* Bluetooth 5, Vol 2, Part E, 7.7.65.13 */
+#define BLE_HCI_LEGACY_ADV_EVTYPE_ADV_IND                 (0x13)
+#define BLE_HCI_LEGACY_ADV_EVTYPE_ADV_DIRECT_IND          (0x15)
+#define BLE_HCI_LEGACY_ADV_EVTYPE_ADV_SCAN_IND            (0x12)
+#define BLE_HCI_LEGACY_ADV_EVTYPE_ADV_NONCON_IND          (0x10)
+#define BLE_HCI_LEGACY_ADV_EVTYPE_SCAN_RSP_ADV_IND        (0x1b)
+#define BLE_HCI_LEGACY_ADV_EVTYPE_SCAN_RSP_ADV_SCAN_IND   (0x1a)
+
+/* LE connection complete event (sub event 0x01) */
+#define BLE_HCI_LE_CONN_COMPLETE_ROLE_MASTER    (0x00)
+#define BLE_HCI_LE_CONN_COMPLETE_ROLE_SLAVE     (0x01)
+
+/* Maximum valid connection handle value */
+#define BLE_HCI_LE_CONN_HANDLE_MAX              (0x0eff)
+
+/* LE advertising report event. (sub event 0x02) */
+#define BLE_HCI_LE_ADV_RPT_NUM_RPTS_MIN     (1)
+#define BLE_HCI_LE_ADV_RPT_NUM_RPTS_MAX     (0x19)
+
+/* Bluetooth Assigned numbers for version information.*/
+#define BLE_HCI_VER_BCS_1_0b                (0)
+#define BLE_HCI_VER_BCS_1_1                 (1)
+#define BLE_HCI_VER_BCS_1_2                 (2)
+#define BLE_HCI_VER_BCS_2_0_EDR             (3)
+#define BLE_HCI_VER_BCS_2_1_EDR             (4)
+#define BLE_HCI_VER_BCS_3_0_HCS             (5)
+#define BLE_HCI_VER_BCS_4_0                 (6)
+#define BLE_HCI_VER_BCS_4_1                 (7)
+#define BLE_HCI_VER_BCS_4_2                 (8)
+#define BLE_HCI_VER_BCS_5_0                 (9)
+#define BLE_HCI_VER_BCS_5_1                 (10)
+#define BLE_HCI_VER_BCS_5_2                 (11)
+
+#define BLE_LMP_VER_BCS_1_0b                (0)
+#define BLE_LMP_VER_BCS_1_1                 (1)
+#define BLE_LMP_VER_BCS_1_2                 (2)
+#define BLE_LMP_VER_BCS_2_0_EDR             (3)
+#define BLE_LMP_VER_BCS_2_1_EDR             (4)
+#define BLE_LMP_VER_BCS_3_0_HCS             (5)
+#define BLE_LMP_VER_BCS_4_0                 (6)
+#define BLE_LMP_VER_BCS_4_1                 (7)
+#define BLE_LMP_VER_BCS_4_2                 (8)
+#define BLE_LMP_VER_BCS_5_0                 (9)
+#define BLE_LMP_VER_BCS_5_1                 (10)
+#define BLE_LMP_VER_BCS_5_2                 (11)
+
+/* selected HCI and LMP version */
+#if MYNEWT_VAL(BLE_VERSION) == 50
+#define BLE_HCI_VER_BCS BLE_HCI_VER_BCS_5_0
+#define BLE_LMP_VER_BCS BLE_LMP_VER_BCS_5_0
+#elif MYNEWT_VAL(BLE_VERSION) == 51
+#define BLE_HCI_VER_BCS BLE_HCI_VER_BCS_5_1
+#define BLE_LMP_VER_BCS BLE_LMP_VER_BCS_5_1
+#elif MYNEWT_VAL(BLE_VERSION) == 52
+#define BLE_HCI_VER_BCS BLE_HCI_VER_BCS_5_2
+#define BLE_LMP_VER_BCS BLE_LMP_VER_BCS_5_2
+
+#endif
+
+#define BLE_HCI_DATA_HDR_SZ                 4
+#define BLE_HCI_DATA_HANDLE(handle_pb_bc)   (((handle_pb_bc) & 0x0fff) >> 0)
+#define BLE_HCI_DATA_PB(handle_pb_bc)       (((handle_pb_bc) & 0x3000) >> 12)
+#define BLE_HCI_DATA_BC(handle_pb_bc)       (((handle_pb_bc) & 0xc000) >> 14)
+
+struct hci_data_hdr
+{
+    uint16_t hdh_handle_pb_bc;
+    uint16_t hdh_len;
+};
+
+#define BLE_HCI_PB_FIRST_NON_FLUSH          0
+#define BLE_HCI_PB_MIDDLE                   1
+#define BLE_HCI_PB_FIRST_FLUSH              2
+#define BLE_HCI_PB_FULL                     3
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* H_BLE_HCI_COMMON_ */

+ 180 - 0
components/bt/porting/nimble/include/nimble/nimble_npl.h

@@ -0,0 +1,180 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 _NIMBLE_NPL_H_
+#define _NIMBLE_NPL_H_
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct ble_npl_event;
+typedef void ble_npl_event_fn(struct ble_npl_event *ev);
+
+enum ble_npl_error {
+    BLE_NPL_OK = 0,
+    BLE_NPL_ENOMEM = 1,
+    BLE_NPL_EINVAL = 2,
+    BLE_NPL_INVALID_PARAM = 3,
+    BLE_NPL_MEM_NOT_ALIGNED = 4,
+    BLE_NPL_BAD_MUTEX = 5,
+    BLE_NPL_TIMEOUT = 6,
+    BLE_NPL_ERR_IN_ISR = 7,
+    BLE_NPL_ERR_PRIV = 8,
+    BLE_NPL_OS_NOT_STARTED = 9,
+    BLE_NPL_ENOENT = 10,
+    BLE_NPL_EBUSY = 11,
+    BLE_NPL_ERROR = 12,
+};
+
+typedef enum ble_npl_error ble_npl_error_t;
+
+/* Include OS-specific definitions */
+#include "nimble/nimble_npl_os.h"
+
+/*
+ * Generic
+ */
+
+bool ble_npl_os_started(void);
+
+void *ble_npl_get_current_task_id(void);
+
+/*
+ * Event queue
+ */
+
+void ble_npl_eventq_init(struct ble_npl_eventq *evq);
+
+void ble_npl_eventq_deinit(struct ble_npl_eventq *evq);
+
+struct ble_npl_event *ble_npl_eventq_get(struct ble_npl_eventq *evq,
+                                         ble_npl_time_t tmo);
+
+void ble_npl_eventq_put(struct ble_npl_eventq *evq, struct ble_npl_event *ev);
+
+void ble_npl_eventq_remove(struct ble_npl_eventq *evq,
+                           struct ble_npl_event *ev);
+
+void ble_npl_event_init(struct ble_npl_event *ev, ble_npl_event_fn *fn,
+                        void *arg);
+
+bool ble_npl_event_is_queued(struct ble_npl_event *ev);
+
+void *ble_npl_event_get_arg(struct ble_npl_event *ev);
+
+void ble_npl_event_set_arg(struct ble_npl_event *ev, void *arg);
+
+bool ble_npl_eventq_is_empty(struct ble_npl_eventq *evq);
+
+void ble_npl_event_run(struct ble_npl_event *ev);
+
+/*
+ * Mutexes
+ */
+
+ble_npl_error_t ble_npl_mutex_init(struct ble_npl_mutex *mu);
+
+ble_npl_error_t ble_npl_mutex_pend(struct ble_npl_mutex *mu,
+                                   ble_npl_time_t timeout);
+
+ble_npl_error_t ble_npl_mutex_release(struct ble_npl_mutex *mu);
+
+ble_npl_error_t ble_npl_mutex_deinit(struct ble_npl_mutex *mu);
+
+/*
+ * Semaphores
+ */
+
+ble_npl_error_t ble_npl_sem_init(struct ble_npl_sem *sem, uint16_t tokens);
+
+ble_npl_error_t ble_npl_sem_pend(struct ble_npl_sem *sem,
+                                 ble_npl_time_t timeout);
+
+ble_npl_error_t ble_npl_sem_release(struct ble_npl_sem *sem);
+
+ble_npl_error_t ble_npl_sem_deinit(struct ble_npl_sem *sem);
+
+uint16_t ble_npl_sem_get_count(struct ble_npl_sem *sem);
+
+/*
+ * Callouts
+ */
+
+void ble_npl_callout_init(struct ble_npl_callout *co, struct ble_npl_eventq *evq,
+                          ble_npl_event_fn *ev_cb, void *ev_arg);
+
+ble_npl_error_t ble_npl_callout_reset(struct ble_npl_callout *co,
+                                      ble_npl_time_t ticks);
+
+void ble_npl_callout_stop(struct ble_npl_callout *co);
+
+bool ble_npl_callout_is_active(struct ble_npl_callout *co);
+
+ble_npl_time_t ble_npl_callout_get_ticks(struct ble_npl_callout *co);
+
+ble_npl_time_t ble_npl_callout_remaining_ticks(struct ble_npl_callout *co,
+                                               ble_npl_time_t time);
+
+void ble_npl_callout_set_arg(struct ble_npl_callout *co,
+                             void *arg);
+/*
+ * Time functions
+ */
+
+ble_npl_time_t ble_npl_time_get(void);
+
+ble_npl_error_t ble_npl_time_ms_to_ticks(uint32_t ms, ble_npl_time_t *out_ticks);
+
+ble_npl_error_t ble_npl_time_ticks_to_ms(ble_npl_time_t ticks, uint32_t *out_ms);
+
+ble_npl_time_t ble_npl_time_ms_to_ticks32(uint32_t ms);
+
+uint32_t ble_npl_time_ticks_to_ms32(ble_npl_time_t ticks);
+
+void ble_npl_time_delay(ble_npl_time_t ticks);
+
+/*
+ * Hardware-specific
+ *
+ * These symbols should be most likely defined by application since they are
+ * specific to hardware, not to OS.
+ */
+
+#if NIMBLE_CFG_CONTROLLER
+
+void ble_npl_hw_set_isr(int irqn, uint32_t addr);
+
+#endif
+
+uint32_t ble_npl_hw_enter_critical(void);
+
+void ble_npl_hw_exit_critical(uint32_t ctx);
+
+bool ble_npl_hw_is_in_critical(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  /* _NIMBLE_NPL_H_ */

+ 34 - 0
components/bt/porting/nimble/include/nimble/nimble_opt.h

@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 H_NIMBLE_OPT_
+#define H_NIMBLE_OPT_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Include automatically-generated settings. */
+#include "nimble/nimble_opt_auto.h"
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

+ 124 - 0
components/bt/porting/nimble/include/nimble/nimble_opt_auto.h

@@ -0,0 +1,124 @@
+/*
+ * SPDX-FileCopyrightText: 2015-2022 The Apache Software Foundation (ASF)
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * SPDX-FileContributor: 2019-2022 Espressif Systems (Shanghai) CO LTD
+ */
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 H_NIMBLE_OPT_AUTO_
+#define H_NIMBLE_OPT_AUTO_
+
+#include "syscfg/syscfg.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/***
+ * Automatic options.
+ *
+ * These settings are generated automatically from the user-specified syscfg
+ * settings.
+ */
+
+#undef NIMBLE_BLE_ADVERTISE
+#define NIMBLE_BLE_ADVERTISE                    \
+    (MYNEWT_VAL(BLE_ROLE_BROADCASTER) || MYNEWT_VAL(BLE_ROLE_PERIPHERAL))
+
+#undef NIMBLE_BLE_SCAN
+#define NIMBLE_BLE_SCAN                         \
+    (MYNEWT_VAL(BLE_ROLE_CENTRAL) || MYNEWT_VAL(BLE_ROLE_OBSERVER))
+
+#undef NIMBLE_BLE_CONNECT
+#define NIMBLE_BLE_CONNECT                      \
+    (MYNEWT_VAL(BLE_ROLE_CENTRAL) || MYNEWT_VAL(BLE_ROLE_PERIPHERAL))
+
+
+/** Supported client ATT commands. */
+
+#undef NIMBLE_BLE_ATT_CLT_FIND_INFO
+#define NIMBLE_BLE_ATT_CLT_FIND_INFO            \
+    (MYNEWT_VAL(BLE_GATT_DISC_ALL_DSCS))
+
+#undef NIMBLE_BLE_ATT_CLT_FIND_TYPE
+#define NIMBLE_BLE_ATT_CLT_FIND_TYPE            \
+    (MYNEWT_VAL(BLE_GATT_DISC_SVC_UUID))
+
+#undef NIMBLE_BLE_ATT_CLT_READ_TYPE
+#define NIMBLE_BLE_ATT_CLT_READ_TYPE            \
+    (MYNEWT_VAL(BLE_GATT_FIND_INC_SVCS) ||      \
+     MYNEWT_VAL(BLE_GATT_DISC_ALL_CHRS) ||      \
+     MYNEWT_VAL(BLE_GATT_DISC_CHRS_UUID) ||     \
+     MYNEWT_VAL(BLE_GATT_READ_UUID))
+
+#undef NIMBLE_BLE_ATT_CLT_READ
+#define NIMBLE_BLE_ATT_CLT_READ                 \
+    (MYNEWT_VAL(BLE_GATT_READ) ||               \
+     MYNEWT_VAL(BLE_GATT_READ_LONG) ||          \
+     MYNEWT_VAL(BLE_GATT_FIND_INC_SVCS))
+
+#undef NIMBLE_BLE_ATT_CLT_READ_BLOB
+#define NIMBLE_BLE_ATT_CLT_READ_BLOB            \
+    (MYNEWT_VAL(BLE_GATT_READ_LONG))
+
+#undef NIMBLE_BLE_ATT_CLT_READ_MULT
+#define NIMBLE_BLE_ATT_CLT_READ_MULT            \
+    (MYNEWT_VAL(BLE_GATT_READ_MULT))
+
+#undef NIMBLE_BLE_ATT_CLT_READ_GROUP_TYPE
+#define NIMBLE_BLE_ATT_CLT_READ_GROUP_TYPE      \
+    (MYNEWT_VAL(BLE_GATT_DISC_ALL_SVCS))
+
+#undef NIMBLE_BLE_ATT_CLT_WRITE
+#define NIMBLE_BLE_ATT_CLT_WRITE                \
+    (MYNEWT_VAL(BLE_GATT_WRITE))
+
+#undef NIMBLE_BLE_ATT_CLT_WRITE_NO_RSP
+#define NIMBLE_BLE_ATT_CLT_WRITE_NO_RSP         \
+    (MYNEWT_VAL(BLE_GATT_WRITE_NO_RSP))
+
+#undef NIMBLE_BLE_ATT_CLT_PREP_WRITE
+#define NIMBLE_BLE_ATT_CLT_PREP_WRITE           \
+    (MYNEWT_VAL(BLE_GATT_WRITE_LONG))
+
+#undef NIMBLE_BLE_ATT_CLT_EXEC_WRITE
+#define NIMBLE_BLE_ATT_CLT_EXEC_WRITE           \
+    (MYNEWT_VAL(BLE_GATT_WRITE_LONG))
+
+#undef NIMBLE_BLE_ATT_CLT_NOTIFY
+#define NIMBLE_BLE_ATT_CLT_NOTIFY               \
+    (MYNEWT_VAL(BLE_GATT_NOTIFY))
+
+#undef NIMBLE_BLE_ATT_CLT_INDICATE
+#define NIMBLE_BLE_ATT_CLT_INDICATE             \
+    (MYNEWT_VAL(BLE_GATT_INDICATE))
+
+/** Security manager settings. */
+
+#undef NIMBLE_BLE_SM
+#define NIMBLE_BLE_SM   (MYNEWT_VAL(BLE_SM_LEGACY) || MYNEWT_VAL(BLE_SM_SC))
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

+ 57 - 0
components/bt/porting/nimble/include/nimble/nimble_port.h

@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 _NIMBLE_PORT_H
+#define _NIMBLE_PORT_H
+
+#include "esp_err.h"
+#include "nimble/nimble_npl.h"
+
+#define NIMBLE_CORE (CONFIG_BT_NIMBLE_PINNED_TO_CORE < portNUM_PROCESSORS ? CONFIG_BT_NIMBLE_PINNED_TO_CORE : tskNO_AFFINITY)
+
+#define NIMBLE_HS_STACK_SIZE CONFIG_BT_NIMBLE_HOST_TASK_STACK_SIZE
+
+#if (CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32C2)
+#define NIMBLE_LL_STACK_SIZE CONFIG_BT_LE_CONTROLLER_TASK_STACK_SIZE
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void nimble_port_init(void);
+void nimble_port_deinit(void);
+
+void nimble_port_run(void);
+int nimble_port_stop(void);
+
+struct ble_npl_eventq *nimble_port_get_dflt_eventq(void);
+
+esp_err_t esp_nimble_init(void);
+esp_err_t esp_nimble_enable(void *host_task);
+
+esp_err_t esp_nimble_disable(void);
+esp_err_t esp_nimble_deinit(void);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _NIMBLE_PORT_H */

+ 296 - 0
components/bt/porting/nimble/include/os/endian.h

@@ -0,0 +1,296 @@
+/*
+ * SPDX-FileCopyrightText: 2015-2022 The Apache Software Foundation (ASF)
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * SPDX-FileContributor: 2019-2022 Espressif Systems (Shanghai) CO LTD
+ */
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 H_ENDIAN_
+#define H_ENDIAN_
+
+#include <inttypes.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Internal helpers */
+#ifndef os_bswap_64
+#define os_bswap_64(x)   ((uint64_t)                \
+     ((((x) & 0xff00000000000000ull) >> 56) |       \
+      (((x) & 0x00ff000000000000ull) >> 40) |       \
+      (((x) & 0x0000ff0000000000ull) >> 24) |       \
+      (((x) & 0x000000ff00000000ull) >>  8) |       \
+      (((x) & 0x00000000ff000000ull) <<  8) |       \
+      (((x) & 0x0000000000ff0000ull) << 24) |       \
+      (((x) & 0x000000000000ff00ull) << 40) |       \
+      (((x) & 0x00000000000000ffull) << 56)))
+#endif
+
+#ifndef os_bswap_32
+#define os_bswap_32(x)    ((uint32_t)               \
+    ((((x) & 0xff000000) >> 24) |                   \
+     (((x) & 0x00ff0000) >>  8) |                   \
+     (((x) & 0x0000ff00) <<  8) |                   \
+     (((x) & 0x000000ff) << 24)))
+#endif
+
+#ifndef os_bswap_16
+#define os_bswap_16(x)   ((uint16_t)                \
+    ((((x) & 0xff00) >> 8) |                        \
+     (((x) & 0x00ff) << 8)))
+#endif
+
+#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+
+#ifndef ntohll
+#define ntohll(x)  ((uint64_t)(x))
+#endif
+
+#ifndef htonll
+#define htonll(x)  ((uint64_t)(x))
+#endif
+
+#ifndef ntohl
+#define ntohl(x)   ((uint32_t)(x))
+#endif
+
+#ifndef htonl
+#define htonl(x)   ((uint32_t)(x))
+#endif
+
+#ifndef ntohs
+#define ntohs(x)   ((uint16_t)(x))
+#endif
+
+#ifndef htons
+#define htons(x)   ((uint16_t)(x))
+#endif
+
+#ifndef htobe16
+#define htobe16(x) ((uint16_t)(x))
+#endif
+
+#ifndef htole16
+#define htole16(x) os_bswap_16 (x)
+#endif
+
+#ifndef be16toh
+#define be16toh(x) ((uint16_t)(x))
+#endif
+
+#ifndef le16toh
+#define le16toh(x) os_bswap_16 (x)
+#endif
+
+#ifndef htobe32
+#define htobe32(x) ((uint32_t)(x))
+#endif
+
+#ifndef htole32
+#define htole32(x) os_bswap_32 (x)
+#endif
+
+#ifndef be32toh
+#define be32toh(x) ((uint32_t)(x))
+#endif
+
+#ifndef le32toh
+#define le32toh(x) os_bswap_32 (x)
+#endif
+
+#ifndef htobe64
+#define htobe64(x) ((uint64_t)(x))
+#endif
+
+#ifndef htole64
+#define htole64(x) os_bswap_64 (x)
+#endif
+
+#ifndef be64toh
+#define be64toh(x) ((uint64_t)(x))
+#endif
+
+#ifndef le64toh
+#define le64toh(x) os_bswap_64 (x)
+#endif
+
+#else
+
+#ifndef ntohll
+#define ntohll(x)   os_bswap_64(x)
+#endif
+
+#ifndef htonll
+#define htonll      ntohll
+#endif
+
+/* These are not used in NimBLE and ESP-IDF uses them from LwIP */
+#if 0
+#ifndef ntohl
+#define ntohl(x)    os_bswap_32(x)
+#endif
+
+#ifndef htonl
+#define htonl       ntohl
+#endif
+
+#ifndef htons
+#define htons(x)    os_bswap_16(x)
+#endif
+
+#ifndef ntohs
+#define ntohs       htons
+#endif
+#endif
+
+#ifndef htobe16
+#define htobe16(x) os_bswap_16(x)
+#endif
+
+#ifndef htole16
+#define htole16(x) ((uint16_t)(x))
+#endif
+
+#ifndef be16toh
+#define be16toh(x) os_bswap_16(x)
+#endif
+
+#ifndef le16toh
+#define le16toh(x) ((uint16_t)(x))
+#endif
+
+#ifndef htobe32
+#define htobe32(x) os_bswap_32(x)
+#endif
+
+#ifndef htole32
+#define htole32(x) ((uint32_t)(x))
+#endif
+
+#ifndef be32toh
+#define be32toh(x) os_bswap_32(x)
+#endif
+
+#ifndef le32toh
+#define le32toh(x) ((uint32_t)(x))
+#endif
+
+#ifndef htobe64
+#define htobe64(x) os_bswap_64(x)
+#endif
+
+#ifndef htole64
+#define htole64(x) ((uint64_t)(x))
+#endif
+
+#ifndef be64toh
+#define be64toh(x) os_bswap_64(x)
+#endif
+
+#ifndef le64toh
+#define le64toh(x) ((uint64_t)(x))
+#endif
+
+#endif
+
+#if SOC_ESP_NIMBLE_CONTROLLER
+void r_put_le16(void *buf, uint16_t x);
+#define put_le16 r_put_le16
+
+void r_put_le24(void *buf, uint32_t x);
+#define put_le24 r_put_le24
+
+void r_put_le32(void *buf, uint32_t x);
+#define put_le32 r_put_le32
+
+void r_put_le64(void *buf, uint64_t x);
+#define put_le64 r_put_le64
+
+uint16_t r_get_le16(const void *buf);
+#define get_le16 r_get_le16
+
+uint32_t r_get_le24(const void *buf);
+#define get_le24 r_get_le24
+
+uint32_t r_get_le32(const void *buf);
+#define get_le32 r_get_le32
+
+uint64_t r_get_le64(const void *buf);
+#define get_le64 r_get_le64
+
+void r_put_be16(void *buf, uint16_t x);
+#define put_be16 r_put_be16
+
+void r_put_be24(void *buf, uint32_t x);
+#define put_be24 r_put_be24
+
+void r_put_be32(void *buf, uint32_t x);
+#define put_be32 r_put_be32
+
+void r_put_be64(void *buf, uint64_t x);
+#define put_be64 r_put_be64
+
+uint16_t r_get_be16(const void *buf);
+#define get_be16 r_get_be16
+
+uint32_t r_get_be24(const void *buf);
+#define get_be24 r_get_be24
+
+uint32_t r_get_be32(const void *buf);
+#define get_be32 r_get_be32
+
+uint64_t r_get_be64(const void *buf);
+#define get_be64 r_get_be64
+
+void r_swap_in_place(void *buf, int len);
+#define swap_in_place r_swap_in_place
+
+void r_swap_buf(uint8_t *dst, const uint8_t *src, int len);
+#define swap_buf r_swap_buf
+
+
+#else
+void put_le16(void *buf, uint16_t x);
+void put_le24(void *buf, uint32_t x);
+void put_le32(void *buf, uint32_t x);
+void put_le64(void *buf, uint64_t x);
+uint16_t get_le16(const void *buf);
+uint32_t get_le24(const void *buf);
+uint32_t get_le32(const void *buf);
+uint64_t get_le64(const void *buf);
+void put_be16(void *buf, uint16_t x);
+void put_be24(void *buf, uint32_t x);
+void put_be32(void *buf, uint32_t x);
+void put_be64(void *buf, uint64_t x);
+uint16_t get_be16(const void *buf);
+uint32_t get_be24(const void *buf);
+uint32_t get_be32(const void *buf);
+uint64_t get_be64(const void *buf);
+void swap_in_place(void *buf, int len);
+void swap_buf(uint8_t *dst, const uint8_t *src, int len);
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+#endif

+ 74 - 0
components/bt/porting/nimble/include/os/os.h

@@ -0,0 +1,74 @@
+/*
+ * SPDX-FileCopyrightText: 2015-2022 The Apache Software Foundation (ASF)
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * SPDX-FileContributor: 2019-2022 Espressif Systems (Shanghai) CO LTD
+ */
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 _OS_H
+#define _OS_H
+
+#include <assert.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if !defined __cplusplus
+#define static_assert _Static_assert
+#endif
+
+#ifndef min
+#define min(a, b) ((a)<(b)?(a):(b))
+#endif
+
+#ifndef max
+#define max(a, b) ((a)>(b)?(a):(b))
+#endif
+
+#include "soc/soc_caps.h"
+#include "nimble/nimble_npl.h"
+
+#define OS_ALIGN(__n, __a) (                             \
+        (((__n) & ((__a) - 1)) == 0)                   ? \
+            (__n)                                      : \
+            ((__n) + ((__a) - ((__n) & ((__a) - 1))))    \
+        )
+#define OS_ALIGNMENT    (BLE_NPL_OS_ALIGNMENT)
+
+typedef uint32_t os_sr_t;
+#define OS_ENTER_CRITICAL(_sr) (_sr = ble_npl_hw_enter_critical())
+#define OS_EXIT_CRITICAL(_sr) (ble_npl_hw_exit_critical(_sr))
+#define OS_ASSERT_CRITICAL() assert(ble_npl_hw_is_in_critical())
+
+/* Mynewt components (not abstracted in NPL) */
+#include "os/endian.h"
+#include "os/queue.h"
+#include "os/os_error.h"
+#include "os/os_mbuf.h"
+#include "os/os_mempool.h"
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _OS_H */

+ 69 - 0
components/bt/porting/nimble/include/os/os_error.h

@@ -0,0 +1,69 @@
+/*
+ * SPDX-FileCopyrightText: 2015-2022 The Apache Software Foundation (ASF)
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * SPDX-FileContributor: 2019-2022 Espressif Systems (Shanghai) CO LTD
+ */
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 H_OS_ERROR_
+#define H_OS_ERROR_
+
+#include <stdbool.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* OS error enumerations */
+enum os_error {
+    OS_OK = 0,
+    OS_ENOMEM = 1,
+    OS_EINVAL = 2,
+    OS_INVALID_PARM = 3,
+    OS_MEM_NOT_ALIGNED = 4,
+    OS_BAD_MUTEX = 5,
+    OS_TIMEOUT = 6,
+    OS_ERR_IN_ISR = 7,      /* Function cannot be called from ISR */
+    OS_ERR_PRIV = 8,        /* Privileged access error */
+    OS_NOT_STARTED = 9,     /* OS must be started to call this function, but isn't */
+    OS_ENOENT = 10,         /* No such thing */
+    OS_EBUSY = 11,          /* Resource busy */
+    OS_ERROR = 12,          /* Generic Error */
+};
+
+typedef enum os_error os_error_t;
+
+/**
+ * @brief Converts an OS error code (`OS_[...]`) to an equivalent system error
+ * code (`SYS_E[...]`).
+ *
+ * @param os_error              The OS error code to convert.
+ *
+ * @return                      The equivalent system error code.
+ */
+int os_error_to_sys(os_error_t os_error);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

+ 1146 - 0
components/bt/porting/nimble/include/os/os_mbuf.h

@@ -0,0 +1,1146 @@
+/*
+ * SPDX-FileCopyrightText: 2015-2022 The Apache Software Foundation (ASF)
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * SPDX-FileContributor: 2019-2022 Espressif Systems (Shanghai) CO LTD
+ */
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+
+/**
+ * @addtogroup OSKernel
+ * @{
+ *   @defgroup OSMbuf Chained Memory Buffers
+ *   @{
+ */
+
+
+#ifndef _OS_MBUF_H
+#define _OS_MBUF_H
+
+#include <stdbool.h>
+#include "os/os.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * A mbuf pool from which to allocate mbufs. This contains a pointer to the os
+ * mempool to allocate mbufs out of, the total number of elements in the pool,
+ * and the amount of "user" data in a non-packet header mbuf. The total pool
+ * size, in bytes, should be:
+ *  os_mbuf_count * (omp_databuf_len + sizeof(struct os_mbuf))
+ */
+struct os_mbuf_pool {
+    /**
+     * Total length of the databuf in each mbuf.  This is the size of the
+     * mempool block, minus the mbuf header
+     */
+    uint16_t omp_databuf_len;
+    /**
+     * The memory pool which to allocate mbufs out of
+     */
+    struct os_mempool *omp_pool;
+
+    STAILQ_ENTRY(os_mbuf_pool) omp_next;
+};
+
+
+/**
+ * A packet header structure that preceeds the mbuf packet headers.
+ */
+struct os_mbuf_pkthdr {
+    /**
+     * Overall length of the packet.
+     */
+    uint16_t omp_len;
+    /**
+     * Flags
+     */
+    uint16_t omp_flags;
+
+    STAILQ_ENTRY(os_mbuf_pkthdr) omp_next;
+};
+
+/**
+ * Chained memory buffer.
+ */
+struct os_mbuf {
+    /**
+     * Current pointer to data in the structure
+     */
+    uint8_t *om_data;
+    /**
+     * Flags associated with this buffer, see OS_MBUF_F_* defintions
+     */
+    uint8_t om_flags;
+    /**
+     * Length of packet header
+     */
+    uint8_t om_pkthdr_len;
+    /**
+     * Length of data in this buffer
+     */
+    uint16_t om_len;
+
+    /**
+     * The mbuf pool this mbuf was allocated out of
+     */
+    struct os_mbuf_pool *om_omp;
+
+    SLIST_ENTRY(os_mbuf) om_next;
+
+    /**
+     * Pointer to the beginning of the data, after this buffer
+     */
+    uint8_t om_databuf[0];
+};
+
+/**
+ * Structure representing a queue of mbufs.
+ */
+struct os_mqueue {
+    STAILQ_HEAD(, os_mbuf_pkthdr) mq_head;
+    /** Event to post when new buffers are available on the queue. */
+    struct ble_npl_event mq_ev;
+};
+
+/*
+ * Given a flag number, provide the mask for it
+ *
+ * @param __n The number of the flag in the mask
+ */
+#define OS_MBUF_F_MASK(__n) (1 << (__n))
+
+/*
+ * Checks whether a given mbuf is a packet header mbuf
+ *
+ * @param __om The mbuf to check
+ */
+#define OS_MBUF_IS_PKTHDR(__om) \
+    ((__om)->om_pkthdr_len >= sizeof (struct os_mbuf_pkthdr))
+
+/** Get a packet header pointer given an mbuf pointer */
+#define OS_MBUF_PKTHDR(__om) ((struct os_mbuf_pkthdr *)     \
+    ((uint8_t *)&(__om)->om_data + sizeof(struct os_mbuf)))
+
+/** Given a mbuf packet header pointer, return a pointer to the mbuf */
+#define OS_MBUF_PKTHDR_TO_MBUF(__hdr)   \
+     (struct os_mbuf *)((uint8_t *)(__hdr) - sizeof(struct os_mbuf))
+
+/**
+ * Gets the length of an entire mbuf chain.  The specified mbuf must have a
+ * packet header.
+ */
+#define OS_MBUF_PKTLEN(__om) (OS_MBUF_PKTHDR(__om)->omp_len)
+
+/**
+ * Access the data of a mbuf, and cast it to type
+ *
+ * @param __om The mbuf to access, and cast
+ * @param __type The type to cast it to
+ */
+#define OS_MBUF_DATA(__om, __type) \
+     (__type) ((__om)->om_data)
+
+/**
+ * Access the "user header" in the head of an mbuf chain.
+ *
+ * @param om                    Pointer to the head of an mbuf chain.
+ */
+#define OS_MBUF_USRHDR(om)                              \
+    (void *)((uint8_t *)om + sizeof (struct os_mbuf) +  \
+             sizeof (struct os_mbuf_pkthdr))
+
+/**
+ * Retrieves the length of the user header in an mbuf.
+ *
+ * @param om                    Pointer to the mbuf to query.
+ */
+#define OS_MBUF_USRHDR_LEN(om) \
+    ((om)->om_pkthdr_len - sizeof (struct os_mbuf_pkthdr))
+
+
+/** @cond INTERNAL_HIDDEN */
+
+/*
+ * Called by OS_MBUF_LEADINGSPACE() macro
+ */
+static inline uint16_t
+_os_mbuf_leadingspace(struct os_mbuf *om)
+{
+    uint16_t startoff;
+    uint16_t leadingspace;
+
+    startoff = 0;
+    if (OS_MBUF_IS_PKTHDR(om)) {
+        startoff = om->om_pkthdr_len;
+    }
+
+    leadingspace = (uint16_t) (OS_MBUF_DATA(om, uint8_t *) -
+                               ((uint8_t *) &om->om_databuf[0] + startoff));
+
+    return (leadingspace);
+}
+
+/** @endcond */
+
+/**
+ * Returns the leading space (space at the beginning) of the mbuf.
+ * Works on both packet header, and regular mbufs, as it accounts
+ * for the additional space allocated to the packet header.
+ *
+ * @param __omp Is the mbuf pool (which contains packet header length.)
+ * @param __om  Is the mbuf in that pool to get the leadingspace for
+ *
+ * @return Amount of leading space available in the mbuf
+ */
+#define OS_MBUF_LEADINGSPACE(__om) _os_mbuf_leadingspace(__om)
+
+
+/** @cond INTERNAL_HIDDEN */
+
+/* Called by OS_MBUF_TRAILINGSPACE() macro. */
+static inline uint16_t
+_os_mbuf_trailingspace(struct os_mbuf *om)
+{
+    struct os_mbuf_pool *omp;
+
+    omp = om->om_omp;
+
+    return (&om->om_databuf[0] + omp->omp_databuf_len) -
+           (om->om_data + om->om_len);
+}
+
+/** @endcond */
+
+/**
+ * Returns the trailing space (space at the end) of the mbuf.
+ * Works on both packet header and regular mbufs.
+ *
+ * @param __omp The mbuf pool for this mbuf
+ * @param __om  Is the mbuf in that pool to get trailing space for
+ *
+ * @return The amount of trailing space available in the mbuf
+ */
+#define OS_MBUF_TRAILINGSPACE(__om) _os_mbuf_trailingspace(__om)
+
+
+#if SOC_ESP_NIMBLE_CONTROLLER
+/**
+ * Initializes an mqueue.  An mqueue is a queue of mbufs that ties to a
+ * particular task's event queue.  Mqueues form a helper API around a common
+ * paradigm: wait on an event queue until at least one packet is available,
+ * then process a queue of packets.
+ *
+ * When mbufs are available on the queue, an event OS_EVENT_T_MQUEUE_DATA
+ * will be posted to the task's mbuf queue.
+ *
+ * @param mq                    The mqueue to initialize
+ * @param ev_cb                 The callback to associate with the mqeueue
+ *                                  event.  Typically, this callback pulls each
+ *                                  packet off the mqueue and processes them.
+ * @param arg                   The argument to associate with the mqueue event.
+ *
+ * @return                      0 on success, non-zero on failure.
+ */
+int r_os_mqueue_init(struct os_mqueue *mq, ble_npl_event_fn *ev_cb, void *arg);
+#define os_mqueue_init r_os_mqueue_init
+
+
+/**
+ * Remove and return a single mbuf from the mbuf queue.  Does not block.
+ *
+ * @param mq The mbuf queue to pull an element off of.
+ *
+ * @return The next mbuf in the queue, or NULL if queue has no mbufs.
+ */
+struct os_mbuf *r_os_mqueue_get(struct os_mqueue *);
+#define os_mqueue_get r_os_mqueue_get
+/**
+ * Adds a packet (i.e. packet header mbuf) to an mqueue. The event associated
+ * with the mqueue gets posted to the specified eventq.
+ *
+ * @param mq                    The mbuf queue to append the mbuf to.
+ * @param evq                   The event queue to post an event to.
+ * @param m                     The mbuf to append to the mbuf queue.
+ *
+ * @return 0 on success, non-zero on failure.
+ */
+int r_os_mqueue_put(struct os_mqueue *, struct ble_npl_eventq *, struct os_mbuf *);
+#define os_mqueue_put r_os_mqueue_put
+
+
+/**
+ * MSYS is a system level mbuf registry.  Allows the system to share
+ * packet buffers amongst the various networking stacks that can be running
+ * simultaeneously.
+ *
+ * Mbuf pools are created in the system initialization code, and then when
+ * a mbuf is allocated out of msys, it will try and find the best fit based
+ * upon estimated mbuf size.
+ *
+ * os_msys_register() registers a mbuf pool with MSYS, and allows MSYS to
+ * allocate mbufs out of it.
+ *
+ * @param new_pool The pool to register with MSYS
+ *
+ * @return 0 on success, non-zero on failure
+ */
+int r_os_msys_register(struct os_mbuf_pool *);
+#define os_msys_register r_os_msys_register
+
+
+/**
+ * Allocate a mbuf from msys.  Based upon the data size requested,
+ * os_msys_get() will choose the mbuf pool that has the best fit.
+ *
+ * @param dsize The estimated size of the data being stored in the mbuf
+ * @param leadingspace The amount of leadingspace to allocate in the mbuf
+ *
+ * @return A freshly allocated mbuf on success, NULL on failure.
+ */
+struct os_mbuf *r_os_msys_get(uint16_t dsize, uint16_t leadingspace);
+#define os_msys_get r_os_msys_get
+/**
+ * De-registers all mbuf pools from msys.
+ */
+void r_os_msys_reset(void);
+#define os_msys_reset r_os_msys_reset
+
+
+/**
+ * Allocate a packet header structure from the MSYS pool.  See
+ * os_msys_register() for a description of MSYS.
+ *
+ * @param dsize The estimated size of the data being stored in the mbuf
+ * @param user_hdr_len The length to allocate for the packet header structure
+ *
+ * @return A freshly allocated mbuf on success, NULL on failure.
+ */
+struct os_mbuf *r_os_msys_get_pkthdr(uint16_t dsize, uint16_t user_hdr_len);
+#define os_msys_get_pkthdr r_os_msys_get_pkthdr
+/**
+ * Count the number of blocks in all the mbuf pools that are allocated.
+ *
+ * @return total number of blocks allocated in Msys
+ */
+int r_os_msys_count(void);
+#define os_msys_count r_os_msys_count
+
+
+/**
+ * Return the number of free blocks in Msys
+ *
+ * @return Number of free blocks available in Msys
+ */
+int r_os_msys_num_free(void);
+#define os_msys_num_free r_os_msys_num_free
+
+
+/**
+ * Initialize a pool of mbufs.
+ *
+ * @param omp     The mbuf pool to initialize
+ * @param mp      The memory pool that will hold this mbuf pool
+ * @param buf_len The length of the buffer itself.
+ * @param nbufs   The number of buffers in the pool
+ *
+ * @return 0 on success, error code on failure.
+ */
+int r_os_mbuf_pool_init(struct os_mbuf_pool *, struct os_mempool *mp,
+                      uint16_t, uint16_t);
+#define os_mbuf_pool_init r_os_mbuf_pool_init
+/**
+ * Get an mbuf from the mbuf pool.  The mbuf is allocated, and initialized
+ * prior to being returned.
+ *
+ * @param omp The mbuf pool to return the packet from
+ * @param leadingspace The amount of leadingspace to put before the data
+ *     section by default.
+ *
+ * @return An initialized mbuf on success, and NULL on failure.
+ */
+struct os_mbuf *r_os_mbuf_get(struct os_mbuf_pool *omp, uint16_t);
+#define os_mbuf_get r_os_mbuf_get
+/**
+ * Allocate a new packet header mbuf out of the os_mbuf_pool.
+ *
+ * @param omp The mbuf pool to allocate out of
+ * @param user_pkthdr_len The packet header length to reserve for the caller.
+ *
+ * @return A freshly allocated mbuf on success, NULL on failure.
+ */
+struct os_mbuf *r_os_mbuf_get_pkthdr(struct os_mbuf_pool *omp,
+                                   uint8_t pkthdr_len);
+#define os_mbuf_get_pkthdr r_os_mbuf_get_pkthdr
+/**
+ * Duplicate a chain of mbufs.  Return the start of the duplicated chain.
+ *
+ * @param omp The mbuf pool to duplicate out of
+ * @param om  The mbuf chain to duplicate
+ *
+ * @return A pointer to the new chain of mbufs
+ */
+struct os_mbuf *r_os_mbuf_dup(struct os_mbuf *m);
+#define os_mbuf_dup r_os_mbuf_dup
+/**
+ * Locates the specified absolute offset within an mbuf chain.  The offset
+ * can be one past than the total length of the chain, but no greater.
+ *
+ * @param om                    The start of the mbuf chain to seek within.
+ * @param off                   The absolute address to find.
+ * @param out_off               On success, this points to the relative offset
+ *                                  within the returned mbuf.
+ *
+ * @return                      The mbuf containing the specified offset on
+ *                                  success.
+ *                              NULL if the specified offset is out of bounds.
+ */
+struct os_mbuf *r_os_mbuf_off(const struct os_mbuf *om, int off,
+                            uint16_t *out_off);
+#define os_mbuf_off r_os_mbuf_off
+
+/*
+ * Copy data from an mbuf chain starting "off" bytes from the beginning,
+ * continuing for "len" bytes, into the indicated buffer.
+ *
+ * @param m The mbuf chain to copy from
+ * @param off The offset into the mbuf chain to begin copying from
+ * @param len The length of the data to copy
+ * @param dst The destination buffer to copy into
+ *
+ * @return                      0 on success;
+ *                              -1 if the mbuf does not contain enough data.
+ */
+int r_os_mbuf_copydata(const struct os_mbuf *m, int off, int len, void *dst);
+#define os_mbuf_copydata r_os_mbuf_copydata
+
+
+/**
+ * @brief Calculates the length of an mbuf chain.
+ *
+ * Calculates the length of an mbuf chain.  If the mbuf contains a packet
+ * header, you should use `OS_MBUF_PKTLEN()` as a more efficient alternative to
+ * this function.
+ *
+ * @param om                    The mbuf to measure.
+ *
+ * @return                      The length, in bytes, of the provided mbuf
+ *                                  chain.
+ */
+uint16_t r_os_mbuf_len(const struct os_mbuf *om);
+#define os_mbuf_len r_os_mbuf_len
+
+
+/**
+ * Append data onto a mbuf
+ *
+ * @param om   The mbuf to append the data onto
+ * @param data The data to append onto the mbuf
+ * @param len  The length of the data to append
+ *
+ * @return 0 on success, and an error code on failure
+ */
+int r_os_mbuf_append(struct os_mbuf *m, const void *, uint16_t);
+#define os_mbuf_append r_os_mbuf_append
+
+
+/**
+ * Reads data from one mbuf and appends it to another.  On error, the specified
+ * data range may be partially appended.  Neither mbuf is required to contain
+ * an mbuf packet header.
+ *
+ * @param dst                   The mbuf to append to.
+ * @param src                   The mbuf to copy data from.
+ * @param src_off               The absolute offset within the source mbuf
+ *                                  chain to read from.
+ * @param len                   The number of bytes to append.
+ *
+ * @return                      0 on success;
+ *                              OS_EINVAL if the specified range extends beyond
+ *                                  the end of the source mbuf chain.
+ */
+int r_os_mbuf_appendfrom(struct os_mbuf *dst, const struct os_mbuf *src,
+                       uint16_t src_off, uint16_t len);
+#define os_mbuf_appendfrom r_os_mbuf_appendfrom
+/**
+ * Release a mbuf back to the pool
+ *
+ * @param omp The Mbuf pool to release back to
+ * @param om  The Mbuf to release back to the pool
+ *
+ * @return 0 on success, -1 on failure
+ */
+int os_mbuf_free(struct os_mbuf *mb);
+#define os_mbuf_free r_os_mbuf_free
+
+
+/**
+ * Free a chain of mbufs
+ *
+ * @param omp The mbuf pool to free the chain of mbufs into
+ * @param om  The starting mbuf of the chain to free back into the pool
+ *
+ * @return 0 on success, -1 on failure
+ */
+int r_os_mbuf_free_chain(struct os_mbuf *om);
+#define os_mbuf_free_chain r_os_mbuf_free_chain
+
+
+/**
+ * Adjust the length of a mbuf, trimming either from the head or the tail
+ * of the mbuf.
+ *
+ * @param mp The mbuf chain to adjust
+ * @param req_len The length to trim from the mbuf.  If positive, trims
+ *                from the head of the mbuf, if negative, trims from the
+ *                tail of the mbuf.
+ */
+void r_os_mbuf_adj(struct os_mbuf *mp, int req_len);
+#define os_mbuf_adj r_os_mbuf_adj
+
+
+
+/**
+ * Performs a memory compare of the specified region of an mbuf chain against a
+ * flat buffer.
+ *
+ * @param om                    The start of the mbuf chain to compare.
+ * @param off                   The offset within the mbuf chain to start the
+ *                                  comparison.
+ * @param data                  The flat buffer to compare.
+ * @param len                   The length of the flat buffer.
+ *
+ * @return                      0 if both memory regions are identical;
+ *                              A memcmp return code if there is a mismatch;
+ *                              INT_MAX if the mbuf is too short.
+ */
+int r_os_mbuf_cmpf(const struct os_mbuf *om, int off, const void *data, int len);
+#define os_mbuf_cmpf r_os_mbuf_cmpf
+
+
+/**
+ * Compares the contents of two mbuf chains.  The ranges of the two chains to
+ * be compared are specified via the two offset parameters and the len
+ * parameter.  Neither mbuf chain is required to contain a packet header.
+ *
+ * @param om1                   The first mbuf chain to compare.
+ * @param offset1               The absolute offset within om1 at which to
+ *                                  start the comparison.
+ * @param om2                   The second mbuf chain to compare.
+ * @param offset2               The absolute offset within om2 at which to
+ *                                  start the comparison.
+ * @param len                   The number of bytes to compare.
+ *
+ * @return                      0 if both mbuf segments are identical;
+ *                              A memcmp() return code if the segment contents
+ *                                  differ;
+ *                              INT_MAX if a specified range extends beyond the
+ *                                  end of its corresponding mbuf chain.
+ */
+int r_os_mbuf_cmpm(const struct os_mbuf *om1, uint16_t offset1,
+                 const struct os_mbuf *om2, uint16_t offset2,
+                 uint16_t len);
+#define os_mbuf_cmpm r_os_mbuf_cmpm
+/**
+ * Increases the length of an mbuf chain by adding data to the front.  If there
+ * is insufficient room in the leading mbuf, additional mbufs are allocated and
+ * prepended as necessary.  If this function fails to allocate an mbuf, the
+ * entire chain is freed.
+ *
+ * The specified mbuf chain does not need to contain a packet header.
+ *
+ * @param omp                   The mbuf pool to allocate from.
+ * @param om                    The head of the mbuf chain.
+ * @param len                   The number of bytes to prepend.
+ *
+ * @return                      The new head of the chain on success;
+ *                              NULL on failure.
+ */
+struct os_mbuf *r_os_mbuf_prepend(struct os_mbuf *om, int len);
+#define os_mbuf_prepend r_os_mbuf_prepend
+/**
+ * Prepends a chunk of empty data to the specified mbuf chain and ensures the
+ * chunk is contiguous.  If either operation fails, the specified mbuf chain is
+ * freed and NULL is returned.
+ *
+ * @param om                    The mbuf chain to prepend to.
+ * @param len                   The number of bytes to prepend and pullup.
+ *
+ * @return                      The modified mbuf on success;
+ *                              NULL on failure (and the mbuf chain is freed).
+ */
+struct os_mbuf *r_os_mbuf_prepend_pullup(struct os_mbuf *om, uint16_t len);
+#define os_mbuf_prepend_pullup r_os_mbuf_prepend_pullup
+/**
+ * Copies the contents of a flat buffer into an mbuf chain, starting at the
+ * specified destination offset.  If the mbuf is too small for the source data,
+ * it is extended as necessary.  If the destination mbuf contains a packet
+ * header, the header length is updated.
+ *
+ * @param omp                   The mbuf pool to allocate from.
+ * @param om                    The mbuf chain to copy into.
+ * @param off                   The offset within the chain to copy to.
+ * @param src                   The source buffer to copy from.
+ * @param len                   The number of bytes to copy.
+ *
+ * @return                      0 on success; nonzero on failure.
+ */
+int r_os_mbuf_copyinto(struct os_mbuf *om, int off, const void *src, int len);
+#define os_mbuf_copyinto r_os_mbuf_copyinto
+
+
+/**
+ * Attaches a second mbuf chain onto the end of the first.  If the first chain
+ * contains a packet header, the header's length is updated.  If the second
+ * chain has a packet header, its header is cleared.
+ *
+ * @param first                 The mbuf chain being attached to.
+ * @param second                The mbuf chain that gets attached.
+ */
+void r_os_mbuf_concat(struct os_mbuf *first, struct os_mbuf *second);
+#define os_mbuf_concat r_os_mbuf_concat
+
+
+
+/**
+ * Increases the length of an mbuf chain by the specified amount.  If there is
+ * not sufficient room in the last buffer, a new buffer is allocated and
+ * appended to the chain.  It is an error to request more data than can fit in
+ * a single buffer.
+ *
+ * @param omp
+ * @param om                    The head of the chain to extend.
+ * @param len                   The number of bytes to extend by.
+ *
+ * @return                      A pointer to the new data on success;
+ *                              NULL on failure.
+ */
+void *r_os_mbuf_extend(struct os_mbuf *om, uint16_t len);
+#define os_mbuf_extend r_os_mbuf_extend
+/**
+ * Rearrange a mbuf chain so that len bytes are contiguous,
+ * and in the data area of an mbuf (so that OS_MBUF_DATA() will
+ * work on a structure of size len.)  Returns the resulting
+ * mbuf chain on success, free's it and returns NULL on failure.
+ *
+ * If there is room, it will add up to "max_protohdr - len"
+ * extra bytes to the contiguous region, in an attempt to avoid being
+ * called next time.
+ *
+ * @param omp The mbuf pool to take the mbufs out of
+ * @param om The mbuf chain to make contiguous
+ * @param len The number of bytes in the chain to make contiguous
+ *
+ * @return The contiguous mbuf chain on success, NULL on failure.
+ */
+struct os_mbuf *r_os_mbuf_pullup(struct os_mbuf *om, uint16_t len);
+#define os_mbuf_pullup r_os_mbuf_pullup
+
+/**
+ * Removes and frees empty mbufs from the front of a chain.  If the chain
+ * contains a packet header, it is preserved.
+ *
+ * @param om                    The mbuf chain to trim.
+ *
+ * @return                      The head of the trimmed mbuf chain.
+ */
+struct os_mbuf *r_os_mbuf_trim_front(struct os_mbuf *om);
+#define os_mbuf_trim_front r_os_mbuf_trim_front
+/**
+ * Increases the length of an mbuf chain by inserting a gap at the specified
+ * offset.  The contents of the gap are indeterminate.  If the mbuf chain
+ * contains a packet header, its total length is increased accordingly.
+ *
+ * This function never frees the provided mbuf chain.
+ *
+ * @param om                    The mbuf chain to widen.
+ * @param off                   The offset at which to insert the gap.
+ * @param len                   The size of the gap to insert.
+ *
+ * @return                      0 on success; SYS_[...] error code on failure.
+ */
+int r_os_mbuf_widen(struct os_mbuf *om, uint16_t off, uint16_t len);
+#define os_mbuf_widen r_os_mbuf_widen
+
+
+
+/**
+ * Creates a single chained mbuf from m1 and m2 utilizing all
+ * the available buffer space in all mbufs in the resulting
+ * chain. In other words, ensures there is no leading space in
+ * any mbuf in the resulting chain and trailing space only in
+ * the last mbuf in the chain. Mbufs from either chain may be
+ * freed if not needed. No mbufs are allocated. Note that mbufs
+ * from m2 are added to the end of m1. If m1 has a packet
+ * header, it is retained and length updated. If m2 has a packet
+ * header it is discarded. If m1 is NULL, NULL is returned and
+ * m2 is left untouched.
+ *
+ * @param m1 Pointer to first mbuf chain to pack
+ * @param m2 Pointer to second mbuf chain to pack
+ *
+ * @return struct os_mbuf* Pointer to resulting mbuf chain
+ */
+struct os_mbuf *r_os_mbuf_pack_chains(struct os_mbuf *m1, struct os_mbuf *m2);
+#define os_mbuf_pack_chains r_os_mbuf_pack_chains
+
+#else
+/**
+ * Initializes an mqueue.  An mqueue is a queue of mbufs that ties to a
+ * particular task's event queue.  Mqueues form a helper API around a common
+ * paradigm: wait on an event queue until at least one packet is available,
+ * then process a queue of packets.
+ *
+ * When mbufs are available on the queue, an event OS_EVENT_T_MQUEUE_DATA
+ * will be posted to the task's mbuf queue.
+ *
+ * @param mq                    The mqueue to initialize
+ * @param ev_cb                 The callback to associate with the mqeueue
+ *                                  event.  Typically, this callback pulls each
+ *                                  packet off the mqueue and processes them.
+ * @param arg                   The argument to associate with the mqueue event.
+ *
+ * @return                      0 on success, non-zero on failure.
+ */
+int os_mqueue_init(struct os_mqueue *mq, ble_npl_event_fn *ev_cb, void *arg);
+
+/**
+ * Remove and return a single mbuf from the mbuf queue.  Does not block.
+ *
+ * @param mq The mbuf queue to pull an element off of.
+ *
+ * @return The next mbuf in the queue, or NULL if queue has no mbufs.
+ */
+struct os_mbuf *os_mqueue_get(struct os_mqueue *);
+
+/**
+ * Adds a packet (i.e. packet header mbuf) to an mqueue. The event associated
+ * with the mqueue gets posted to the specified eventq.
+ *
+ * @param mq                    The mbuf queue to append the mbuf to.
+ * @param evq                   The event queue to post an event to.
+ * @param m                     The mbuf to append to the mbuf queue.
+ *
+ * @return 0 on success, non-zero on failure.
+ */
+int os_mqueue_put(struct os_mqueue *, struct ble_npl_eventq *, struct os_mbuf *);
+
+/**
+ * MSYS is a system level mbuf registry.  Allows the system to share
+ * packet buffers amongst the various networking stacks that can be running
+ * simultaeneously.
+ *
+ * Mbuf pools are created in the system initialization code, and then when
+ * a mbuf is allocated out of msys, it will try and find the best fit based
+ * upon estimated mbuf size.
+ *
+ * os_msys_register() registers a mbuf pool with MSYS, and allows MSYS to
+ * allocate mbufs out of it.
+ *
+ * @param new_pool The pool to register with MSYS
+ *
+ * @return 0 on success, non-zero on failure
+ */
+int os_msys_register(struct os_mbuf_pool *);
+
+/**
+ * Allocate a mbuf from msys.  Based upon the data size requested,
+ * os_msys_get() will choose the mbuf pool that has the best fit.
+ *
+ * @param dsize The estimated size of the data being stored in the mbuf
+ * @param leadingspace The amount of leadingspace to allocate in the mbuf
+ *
+ * @return A freshly allocated mbuf on success, NULL on failure.
+ */
+struct os_mbuf *os_msys_get(uint16_t dsize, uint16_t leadingspace);
+
+/**
+ * De-registers all mbuf pools from msys.
+ */
+void os_msys_reset(void);
+
+/**
+ * Allocate a packet header structure from the MSYS pool.  See
+ * os_msys_register() for a description of MSYS.
+ *
+ * @param dsize The estimated size of the data being stored in the mbuf
+ * @param user_hdr_len The length to allocate for the packet header structure
+ *
+ * @return A freshly allocated mbuf on success, NULL on failure.
+ */
+struct os_mbuf *os_msys_get_pkthdr(uint16_t dsize, uint16_t user_hdr_len);
+
+/**
+ * Count the number of blocks in all the mbuf pools that are allocated.
+ *
+ * @return total number of blocks allocated in Msys
+ */
+int os_msys_count(void);
+
+/**
+ * Return the number of free blocks in Msys
+ *
+ * @return Number of free blocks available in Msys
+ */
+int os_msys_num_free(void);
+
+/**
+ * Initialize a pool of mbufs.
+ *
+ * @param omp     The mbuf pool to initialize
+ * @param mp      The memory pool that will hold this mbuf pool
+ * @param buf_len The length of the buffer itself.
+ * @param nbufs   The number of buffers in the pool
+ *
+ * @return 0 on success, error code on failure.
+ */
+int os_mbuf_pool_init(struct os_mbuf_pool *, struct os_mempool *mp,
+                      uint16_t, uint16_t);
+
+/**
+ * Get an mbuf from the mbuf pool.  The mbuf is allocated, and initialized
+ * prior to being returned.
+ *
+ * @param omp The mbuf pool to return the packet from
+ * @param leadingspace The amount of leadingspace to put before the data
+ *     section by default.
+ *
+ * @return An initialized mbuf on success, and NULL on failure.
+ */
+struct os_mbuf *os_mbuf_get(struct os_mbuf_pool *omp, uint16_t);
+
+/**
+ * Allocate a new packet header mbuf out of the os_mbuf_pool.
+ *
+ * @param omp The mbuf pool to allocate out of
+ * @param user_pkthdr_len The packet header length to reserve for the caller.
+ *
+ * @return A freshly allocated mbuf on success, NULL on failure.
+ */
+struct os_mbuf *os_mbuf_get_pkthdr(struct os_mbuf_pool *omp,
+                                   uint8_t pkthdr_len);
+
+/**
+ * Duplicate a chain of mbufs.  Return the start of the duplicated chain.
+ *
+ * @param omp The mbuf pool to duplicate out of
+ * @param om  The mbuf chain to duplicate
+ *
+ * @return A pointer to the new chain of mbufs
+ */
+struct os_mbuf *os_mbuf_dup(struct os_mbuf *m);
+
+/**
+ * Locates the specified absolute offset within an mbuf chain.  The offset
+ * can be one past than the total length of the chain, but no greater.
+ *
+ * @param om                    The start of the mbuf chain to seek within.
+ * @param off                   The absolute address to find.
+ * @param out_off               On success, this points to the relative offset
+ *                                  within the returned mbuf.
+ *
+ * @return                      The mbuf containing the specified offset on
+ *                                  success.
+ *                              NULL if the specified offset is out of bounds.
+ */
+struct os_mbuf *os_mbuf_off(const struct os_mbuf *om, int off,
+                            uint16_t *out_off);
+
+
+/*
+ * Copy data from an mbuf chain starting "off" bytes from the beginning,
+ * continuing for "len" bytes, into the indicated buffer.
+ *
+ * @param m The mbuf chain to copy from
+ * @param off The offset into the mbuf chain to begin copying from
+ * @param len The length of the data to copy
+ * @param dst The destination buffer to copy into
+ *
+ * @return                      0 on success;
+ *                              -1 if the mbuf does not contain enough data.
+ */
+int os_mbuf_copydata(const struct os_mbuf *m, int off, int len, void *dst);
+
+/**
+ * @brief Calculates the length of an mbuf chain.
+ *
+ * Calculates the length of an mbuf chain.  If the mbuf contains a packet
+ * header, you should use `OS_MBUF_PKTLEN()` as a more efficient alternative to
+ * this function.
+ *
+ * @param om                    The mbuf to measure.
+ *
+ * @return                      The length, in bytes, of the provided mbuf
+ *                                  chain.
+ */
+uint16_t os_mbuf_len(const struct os_mbuf *om);
+
+/**
+ * Append data onto a mbuf
+ *
+ * @param om   The mbuf to append the data onto
+ * @param data The data to append onto the mbuf
+ * @param len  The length of the data to append
+ *
+ * @return 0 on success, and an error code on failure
+ */
+int os_mbuf_append(struct os_mbuf *m, const void *, uint16_t);
+
+/**
+ * Reads data from one mbuf and appends it to another.  On error, the specified
+ * data range may be partially appended.  Neither mbuf is required to contain
+ * an mbuf packet header.
+ *
+ * @param dst                   The mbuf to append to.
+ * @param src                   The mbuf to copy data from.
+ * @param src_off               The absolute offset within the source mbuf
+ *                                  chain to read from.
+ * @param len                   The number of bytes to append.
+ *
+ * @return                      0 on success;
+ *                              OS_EINVAL if the specified range extends beyond
+ *                                  the end of the source mbuf chain.
+ */
+int os_mbuf_appendfrom(struct os_mbuf *dst, const struct os_mbuf *src,
+                       uint16_t src_off, uint16_t len);
+
+/**
+ * Release a mbuf back to the pool
+ *
+ * @param omp The Mbuf pool to release back to
+ * @param om  The Mbuf to release back to the pool
+ *
+ * @return 0 on success, -1 on failure
+ */
+int os_mbuf_free(struct os_mbuf *mb);
+
+/**
+ * Free a chain of mbufs
+ *
+ * @param omp The mbuf pool to free the chain of mbufs into
+ * @param om  The starting mbuf of the chain to free back into the pool
+ *
+ * @return 0 on success, -1 on failure
+ */
+int os_mbuf_free_chain(struct os_mbuf *om);
+
+/**
+ * Adjust the length of a mbuf, trimming either from the head or the tail
+ * of the mbuf.
+ *
+ * @param mp The mbuf chain to adjust
+ * @param req_len The length to trim from the mbuf.  If positive, trims
+ *                from the head of the mbuf, if negative, trims from the
+ *                tail of the mbuf.
+ */
+void os_mbuf_adj(struct os_mbuf *mp, int req_len);
+
+
+/**
+ * Performs a memory compare of the specified region of an mbuf chain against a
+ * flat buffer.
+ *
+ * @param om                    The start of the mbuf chain to compare.
+ * @param off                   The offset within the mbuf chain to start the
+ *                                  comparison.
+ * @param data                  The flat buffer to compare.
+ * @param len                   The length of the flat buffer.
+ *
+ * @return                      0 if both memory regions are identical;
+ *                              A memcmp return code if there is a mismatch;
+ *                              INT_MAX if the mbuf is too short.
+ */
+int os_mbuf_cmpf(const struct os_mbuf *om, int off, const void *data, int len);
+
+/**
+ * Compares the contents of two mbuf chains.  The ranges of the two chains to
+ * be compared are specified via the two offset parameters and the len
+ * parameter.  Neither mbuf chain is required to contain a packet header.
+ *
+ * @param om1                   The first mbuf chain to compare.
+ * @param offset1               The absolute offset within om1 at which to
+ *                                  start the comparison.
+ * @param om2                   The second mbuf chain to compare.
+ * @param offset2               The absolute offset within om2 at which to
+ *                                  start the comparison.
+ * @param len                   The number of bytes to compare.
+ *
+ * @return                      0 if both mbuf segments are identical;
+ *                              A memcmp() return code if the segment contents
+ *                                  differ;
+ *                              INT_MAX if a specified range extends beyond the
+ *                                  end of its corresponding mbuf chain.
+ */
+int os_mbuf_cmpm(const struct os_mbuf *om1, uint16_t offset1,
+                 const struct os_mbuf *om2, uint16_t offset2,
+                 uint16_t len);
+
+/**
+ * Increases the length of an mbuf chain by adding data to the front.  If there
+ * is insufficient room in the leading mbuf, additional mbufs are allocated and
+ * prepended as necessary.  If this function fails to allocate an mbuf, the
+ * entire chain is freed.
+ *
+ * The specified mbuf chain does not need to contain a packet header.
+ *
+ * @param omp                   The mbuf pool to allocate from.
+ * @param om                    The head of the mbuf chain.
+ * @param len                   The number of bytes to prepend.
+ *
+ * @return                      The new head of the chain on success;
+ *                              NULL on failure.
+ */
+struct os_mbuf *os_mbuf_prepend(struct os_mbuf *om, int len);
+
+/**
+ * Prepends a chunk of empty data to the specified mbuf chain and ensures the
+ * chunk is contiguous.  If either operation fails, the specified mbuf chain is
+ * freed and NULL is returned.
+ *
+ * @param om                    The mbuf chain to prepend to.
+ * @param len                   The number of bytes to prepend and pullup.
+ *
+ * @return                      The modified mbuf on success;
+ *                              NULL on failure (and the mbuf chain is freed).
+ */
+struct os_mbuf *os_mbuf_prepend_pullup(struct os_mbuf *om, uint16_t len);
+
+/**
+ * Copies the contents of a flat buffer into an mbuf chain, starting at the
+ * specified destination offset.  If the mbuf is too small for the source data,
+ * it is extended as necessary.  If the destination mbuf contains a packet
+ * header, the header length is updated.
+ *
+ * @param omp                   The mbuf pool to allocate from.
+ * @param om                    The mbuf chain to copy into.
+ * @param off                   The offset within the chain to copy to.
+ * @param src                   The source buffer to copy from.
+ * @param len                   The number of bytes to copy.
+ *
+ * @return                      0 on success; nonzero on failure.
+ */
+int os_mbuf_copyinto(struct os_mbuf *om, int off, const void *src, int len);
+
+/**
+ * Attaches a second mbuf chain onto the end of the first.  If the first chain
+ * contains a packet header, the header's length is updated.  If the second
+ * chain has a packet header, its header is cleared.
+ *
+ * @param first                 The mbuf chain being attached to.
+ * @param second                The mbuf chain that gets attached.
+ */
+void os_mbuf_concat(struct os_mbuf *first, struct os_mbuf *second);
+
+
+/**
+ * Increases the length of an mbuf chain by the specified amount.  If there is
+ * not sufficient room in the last buffer, a new buffer is allocated and
+ * appended to the chain.  It is an error to request more data than can fit in
+ * a single buffer.
+ *
+ * @param omp
+ * @param om                    The head of the chain to extend.
+ * @param len                   The number of bytes to extend by.
+ *
+ * @return                      A pointer to the new data on success;
+ *                              NULL on failure.
+ */
+void *os_mbuf_extend(struct os_mbuf *om, uint16_t len);
+
+/**
+ * Rearrange a mbuf chain so that len bytes are contiguous,
+ * and in the data area of an mbuf (so that OS_MBUF_DATA() will
+ * work on a structure of size len.)  Returns the resulting
+ * mbuf chain on success, free's it and returns NULL on failure.
+ *
+ * If there is room, it will add up to "max_protohdr - len"
+ * extra bytes to the contiguous region, in an attempt to avoid being
+ * called next time.
+ *
+ * @param omp The mbuf pool to take the mbufs out of
+ * @param om The mbuf chain to make contiguous
+ * @param len The number of bytes in the chain to make contiguous
+ *
+ * @return The contiguous mbuf chain on success, NULL on failure.
+ */
+struct os_mbuf *os_mbuf_pullup(struct os_mbuf *om, uint16_t len);
+
+
+/**
+ * Removes and frees empty mbufs from the front of a chain.  If the chain
+ * contains a packet header, it is preserved.
+ *
+ * @param om                    The mbuf chain to trim.
+ *
+ * @return                      The head of the trimmed mbuf chain.
+ */
+struct os_mbuf *os_mbuf_trim_front(struct os_mbuf *om);
+
+/**
+ * Increases the length of an mbuf chain by inserting a gap at the specified
+ * offset.  The contents of the gap are indeterminate.  If the mbuf chain
+ * contains a packet header, its total length is increased accordingly.
+ *
+ * This function never frees the provided mbuf chain.
+ *
+ * @param om                    The mbuf chain to widen.
+ * @param off                   The offset at which to insert the gap.
+ * @param len                   The size of the gap to insert.
+ *
+ * @return                      0 on success; SYS_[...] error code on failure.
+ */
+int os_mbuf_widen(struct os_mbuf *om, uint16_t off, uint16_t len);
+
+
+/**
+ * Creates a single chained mbuf from m1 and m2 utilizing all
+ * the available buffer space in all mbufs in the resulting
+ * chain. In other words, ensures there is no leading space in
+ * any mbuf in the resulting chain and trailing space only in
+ * the last mbuf in the chain. Mbufs from either chain may be
+ * freed if not needed. No mbufs are allocated. Note that mbufs
+ * from m2 are added to the end of m1. If m1 has a packet
+ * header, it is retained and length updated. If m2 has a packet
+ * header it is discarded. If m1 is NULL, NULL is returned and
+ * m2 is left untouched.
+ *
+ * @param m1 Pointer to first mbuf chain to pack
+ * @param m2 Pointer to second mbuf chain to pack
+ *
+ * @return struct os_mbuf* Pointer to resulting mbuf chain
+ */
+struct os_mbuf *os_mbuf_pack_chains(struct os_mbuf *m1, struct os_mbuf *m2);
+
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _OS_MBUF_H */
+
+
+/**
+ *   @} OSMbuf
+ * @} OSKernel
+ */

+ 408 - 0
components/bt/porting/nimble/include/os/os_mempool.h

@@ -0,0 +1,408 @@
+/*
+ * SPDX-FileCopyrightText: 2015-2022 The Apache Software Foundation (ASF)
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * SPDX-FileContributor: 2019-2022 Espressif Systems (Shanghai) CO LTD
+ */
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+/**
+ * @addtogroup OSKernel
+ * @{
+ *   @defgroup OSMempool Memory Pools
+ *   @{
+ */
+
+
+#ifndef _OS_MEMPOOL_H_
+#define _OS_MEMPOOL_H_
+
+#include <stdbool.h>
+#include "os/os.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * A memory block structure. This simply contains a pointer to the free list
+ * chain and is only used when the block is on the free list. When the block
+ * has been removed from the free list the entire memory block is usable by the
+ * caller.
+ */
+struct os_memblock {
+    SLIST_ENTRY(os_memblock) mb_next;
+};
+
+/* XXX: Change this structure so that we keep the first address in the pool? */
+/* XXX: add memory debug structure and associated code */
+/* XXX: Change how I coded the SLIST_HEAD here. It should be named:
+   SLIST_HEAD(,os_memblock) mp_head; */
+
+/**
+ * Memory pool
+ */
+struct os_mempool {
+    /** Size of the memory blocks, in bytes. */
+    uint32_t mp_block_size;
+    /** The number of memory blocks. */
+    uint16_t mp_num_blocks;
+    /** The number of free blocks left */
+    uint16_t mp_num_free;
+    /** The lowest number of free blocks seen */
+    uint16_t mp_min_free;
+    /** Bitmap of OS_MEMPOOL_F_[...] values. */
+    uint8_t mp_flags;
+    /** Address of memory buffer used by pool */
+    uint32_t mp_membuf_addr;
+    STAILQ_ENTRY(os_mempool) mp_list;
+    SLIST_HEAD(,os_memblock);
+    /** Name for memory block */
+    const char *name;
+};
+
+/**
+ * Indicates an extended mempool.  Address can be safely cast to
+ * (struct os_mempool_ext *).
+ */
+#define OS_MEMPOOL_F_EXT        0x01
+
+struct os_mempool_ext;
+
+/**
+ * Block put callback function.  If configured, this callback gets executed
+ * whenever a block is freed to the corresponding extended mempool.  Note: The
+ * os_memblock_put() function calls this callback instead of freeing the block
+ * itself.  Therefore, it is the callback's responsibility to free the block
+ * via a call to os_memblock_put_from_cb().
+ *
+ * @param ome                   The extended mempool that a block is being
+ *                                  freed back to.
+ * @param data                  The block being freed.
+ * @param arg                   Optional argument configured along with the
+ *                                  callback.
+ *
+ * @return                      Indicates whether the block was successfully
+ *                                  freed.  A non-zero value should only be
+ *                                  returned if the block was not successfully
+ *                                  released back to its pool.
+ */
+typedef os_error_t os_mempool_put_fn(struct os_mempool_ext *ome, void *data,
+                                     void *arg);
+
+struct os_mempool_ext {
+    struct os_mempool mpe_mp;
+
+    /* Callback that is executed immediately when a block is freed. */
+    os_mempool_put_fn *mpe_put_cb;
+    void *mpe_put_arg;
+};
+
+#define OS_MEMPOOL_INFO_NAME_LEN (32)
+
+/**
+ * Information describing a memory pool, used to return OS information
+ * to the management layer.
+ */
+struct os_mempool_info {
+    /** Size of the memory blocks in the pool */
+    int omi_block_size;
+    /** Number of memory blocks in the pool */
+    int omi_num_blocks;
+    /** Number of free memory blocks */
+    int omi_num_free;
+    /** Minimum number of free memory blocks ever */
+    int omi_min_free;
+    /** Name of the memory pool */
+    char omi_name[OS_MEMPOOL_INFO_NAME_LEN];
+};
+
+/**
+ * Get information about the next system memory pool.
+ *
+ * @param mempool The current memory pool, or NULL if starting iteration.
+ * @param info    A pointer to the structure to return memory pool information
+ *                into.
+ *
+ * @return The next memory pool in the list to get information about, or NULL
+ *         when at the last memory pool.
+ */
+struct os_mempool *os_mempool_info_get_next(struct os_mempool *,
+                                            struct os_mempool_info *);
+
+
+#if (OS_ALIGNMENT == 4)
+typedef uint32_t os_membuf_t;
+#elif (OS_ALIGNMENT == 8)
+typedef uint64_t os_membuf_t;
+#elif (OS_ALIGNMENT == 16)
+typedef __uint128_t os_membuf_t;
+#else
+#error "Unhandled `OS_ALIGNMENT` for `os_membuf_t`"
+#endif /* OS_ALIGNMENT == * */
+#define OS_MEMPOOL_SIZE(n,blksize)      ((((blksize) + ((OS_ALIGNMENT)-1)) / (OS_ALIGNMENT)) * (n))
+
+/** Calculates the number of bytes required to initialize a memory pool. */
+#define OS_MEMPOOL_BYTES(n,blksize)     \
+    (sizeof (os_membuf_t) * OS_MEMPOOL_SIZE((n), (blksize)))
+
+#if SOC_ESP_NIMBLE_CONTROLLER
+/**
+ * Initialize a memory pool.
+ *
+ * @param mp            Pointer to a pointer to a mempool
+ * @param blocks        The number of blocks in the pool
+ * @param blocks_size   The size of the block, in bytes.
+ * @param membuf        Pointer to memory to contain blocks.
+ * @param name          Name of the pool.
+ *
+ * @return os_error_t
+ */
+os_error_t r_os_mempool_init(struct os_mempool *mp, uint16_t blocks,
+                           uint32_t block_size, void *membuf, const char *name);
+#define os_mempool_init r_os_mempool_init
+/**
+ * Initializes an extended memory pool.  Extended attributes (e.g., callbacks)
+ * are not specified when this function is called; they are assigned manually
+ * after initialization.
+ *
+ * @param mpe           The extended memory pool to initialize.
+ * @param blocks        The number of blocks in the pool.
+ * @param block_size    The size of each block, in bytes.
+ * @param membuf        Pointer to memory to contain blocks.
+ * @param name          Name of the pool.
+ *
+ * @return os_error_t
+ */
+os_error_t r_os_mempool_ext_init(struct os_mempool_ext *mpe, uint16_t blocks,
+                               uint32_t block_size, void *membuf, const char *name);
+#define os_mempool_ext_init r_os_mempool_ext_init
+/**
+ * Removes the specified mempool from the list of initialized mempools.
+ *
+ * @param mp                    The mempool to unregister.
+ *
+ * @return                      0 on success;
+ *                              OS_INVALID_PARM if the mempool is not
+ *                                  registered.
+ */
+os_error_t r_os_mempool_unregister(struct os_mempool *mp);
+#define os_mempool_unregister r_os_mempool_unregister
+
+
+/**
+ * Clears a memory pool.
+ *
+ * @param mp            The mempool to clear.
+ *
+ * @return os_error_t
+ */
+os_error_t r_os_mempool_clear(struct os_mempool *mp);
+#define os_mempool_clear r_os_mempool_clear
+
+
+/**
+ * Performs an integrity check of the specified mempool.  This function
+ * attempts to detect memory corruption in the specified memory pool.
+ *
+ * @param mp                    The mempool to check.
+ *
+ * @return                      true if the memory pool passes the integrity
+ *                                  check;
+ *                              false if the memory pool is corrupt.
+ */
+bool r_os_mempool_is_sane(const struct os_mempool *mp);
+#define os_mempool_is_sane r_os_mempool_is_sane
+
+
+/**
+ * Checks if a memory block was allocated from the specified mempool.
+ *
+ * @param mp                    The mempool to check as parent.
+ * @param block_addr            The memory block to check as child.
+ *
+ * @return                      0 if the block does not belong to the mempool;
+ *                              1 if the block does belong to the mempool.
+ */
+int r_os_memblock_from(const struct os_mempool *mp, const void *block_addr);
+#define os_memblock_from r_os_memblock_from
+
+
+/**
+ * Get a memory block from a memory pool
+ *
+ * @param mp Pointer to the memory pool
+ *
+ * @return void* Pointer to block if available; NULL otherwise
+ */
+void *r_os_memblock_get(struct os_mempool *mp);
+#define os_memblock_get r_os_memblock_get
+/**
+ * Puts the memory block back into the pool, ignoring the put callback, if any.
+ * This function should only be called from a put callback to free a block
+ * without causing infinite recursion.
+ *
+ * @param mp Pointer to memory pool
+ * @param block_addr Pointer to memory block
+ *
+ * @return os_error_t
+ */
+os_error_t r_os_memblock_put_from_cb(struct os_mempool *mp, void *block_addr);
+#define os_memblock_put_from_cb r_os_memblock_put_from_cb
+
+
+/**
+ * Puts the memory block back into the pool
+ *
+ * @param mp Pointer to memory pool
+ * @param block_addr Pointer to memory block
+ *
+ * @return os_error_t
+ */
+os_error_t r_os_memblock_put(struct os_mempool *mp, void *block_addr);
+#define os_memblock_put r_os_memblock_put
+
+#else
+/**
+ * Initialize a memory pool.
+ *
+ * @param mp            Pointer to a pointer to a mempool
+ * @param blocks        The number of blocks in the pool
+ * @param blocks_size   The size of the block, in bytes.
+ * @param membuf        Pointer to memory to contain blocks.
+ * @param name          Name of the pool.
+ *
+ * @return os_error_t
+ */
+os_error_t os_mempool_init(struct os_mempool *mp, uint16_t blocks,
+                           uint32_t block_size, void *membuf, const char *name);
+
+/**
+ * Initializes an extended memory pool.  Extended attributes (e.g., callbacks)
+ * are not specified when this function is called; they are assigned manually
+ * after initialization.
+ *
+ * @param mpe           The extended memory pool to initialize.
+ * @param blocks        The number of blocks in the pool.
+ * @param block_size    The size of each block, in bytes.
+ * @param membuf        Pointer to memory to contain blocks.
+ * @param name          Name of the pool.
+ *
+ * @return os_error_t
+ */
+os_error_t os_mempool_ext_init(struct os_mempool_ext *mpe, uint16_t blocks,
+                               uint32_t block_size, void *membuf, const char *name);
+
+/**
+ * Removes the specified mempool from the list of initialized mempools.
+ *
+ * @param mp                    The mempool to unregister.
+ *
+ * @return                      0 on success;
+ *                              OS_INVALID_PARM if the mempool is not
+ *                                  registered.
+ */
+os_error_t os_mempool_unregister(struct os_mempool *mp);
+
+/**
+ * Clears a memory pool.
+ *
+ * @param mp            The mempool to clear.
+ *
+ * @return os_error_t
+ */
+os_error_t os_mempool_clear(struct os_mempool *mp);
+
+/**
+ * Clears an extended memory pool.
+ *
+ * @param mpe            The extended memory pool to clear.
+ *
+ * @return os_error_t
+ */
+os_error_t os_mempool_ext_clear(struct os_mempool_ext *mpe);
+
+/**
+ * Performs an integrity check of the specified mempool.  This function
+ * attempts to detect memory corruption in the specified memory pool.
+ *
+ * @param mp                    The mempool to check.
+ *
+ * @return                      true if the memory pool passes the integrity
+ *                                  check;
+ *                              false if the memory pool is corrupt.
+ */
+bool os_mempool_is_sane(const struct os_mempool *mp);
+
+/**
+ * Checks if a memory block was allocated from the specified mempool.
+ *
+ * @param mp                    The mempool to check as parent.
+ * @param block_addr            The memory block to check as child.
+ *
+ * @return                      0 if the block does not belong to the mempool;
+ *                              1 if the block does belong to the mempool.
+ */
+int os_memblock_from(const struct os_mempool *mp, const void *block_addr);
+
+/**
+ * Get a memory block from a memory pool
+ *
+ * @param mp Pointer to the memory pool
+ *
+ * @return void* Pointer to block if available; NULL otherwise
+ */
+void *os_memblock_get(struct os_mempool *mp);
+
+/**
+ * Puts the memory block back into the pool, ignoring the put callback, if any.
+ * This function should only be called from a put callback to free a block
+ * without causing infinite recursion.
+ *
+ * @param mp Pointer to memory pool
+ * @param block_addr Pointer to memory block
+ *
+ * @return os_error_t
+ */
+os_error_t os_memblock_put_from_cb(struct os_mempool *mp, void *block_addr);
+
+/**
+ * Puts the memory block back into the pool
+ *
+ * @param mp Pointer to memory pool
+ * @param block_addr Pointer to memory block
+ *
+ * @return os_error_t
+ */
+os_error_t os_memblock_put(struct os_mempool *mp, void *block_addr);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  /* _OS_MEMPOOL_H_ */
+
+
+/**
+ *   @} OSMempool
+ * @} OSKernel
+ */

+ 218 - 0
components/bt/porting/nimble/include/os/queue.h

@@ -0,0 +1,218 @@
+/*
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ *	@(#)queue.h	8.5 (Berkeley) 8/20/94
+ * $FreeBSD: src/sys/sys/queue.h,v 1.32.2.7 2002/04/17 14:21:02 des Exp $
+ */
+
+#ifndef _QUEUE_H_
+#define	_QUEUE_H_
+
+/* The common BSD linked list queue macros are already defined here for ESP-IDF */
+#include <sys/queue.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * This file defines circular queues. The other types of data structures:
+ * singly-linked lists, singly-linked tail queues, lists and tail queues
+ * are used from sys/queue.h
+ *
+ * A singly-linked list is headed by a single forward pointer. The elements
+ * are singly linked for minimum space and pointer manipulation overhead at
+ * the expense of O(n) removal for arbitrary elements. New elements can be
+ * added to the list after an existing element or at the head of the list.
+ * Elements being removed from the head of the list should use the explicit
+ * macro for this purpose for optimum efficiency. A singly-linked list may
+ * only be traversed in the forward direction.  Singly-linked lists are ideal
+ * for applications with large datasets and few or no removals or for
+ * implementing a LIFO queue.
+ *
+ * A singly-linked tail queue is headed by a pair of pointers, one to the
+ * head of the list and the other to the tail of the list. The elements are
+ * singly linked for minimum space and pointer manipulation overhead at the
+ * expense of O(n) removal for arbitrary elements. New elements can be added
+ * to the list after an existing element, at the head of the list, or at the
+ * end of the list. Elements being removed from the head of the tail queue
+ * should use the explicit macro for this purpose for optimum efficiency.
+ * A singly-linked tail queue may only be traversed in the forward direction.
+ * Singly-linked tail queues are ideal for applications with large datasets
+ * and few or no removals or for implementing a FIFO queue.
+ *
+ * A list is headed by a single forward pointer (or an array of forward
+ * pointers for a hash table header). The elements are doubly linked
+ * so that an arbitrary element can be removed without a need to
+ * traverse the list. New elements can be added to the list before
+ * or after an existing element or at the head of the list. A list
+ * may only be traversed in the forward direction.
+ *
+ * A tail queue is headed by a pair of pointers, one to the head of the
+ * list and the other to the tail of the list. The elements are doubly
+ * linked so that an arbitrary element can be removed without a need to
+ * traverse the list. New elements can be added to the list before or
+ * after an existing element, at the head of the list, or at the end of
+ * the list. A tail queue may be traversed in either direction.
+ *
+ * A circle queue is headed by a pair of pointers, one to the head of the
+ * list and the other to the tail of the list. The elements are doubly
+ * linked so that an arbitrary element can be removed without a need to
+ * traverse the list. New elements can be added to the list before or after
+ * an existing element, at the head of the list, or at the end of the list.
+ * A circle queue may be traversed in either direction, but has a more
+ * complex end of list detection.
+ *
+ * For details on the use of these macros, see the queue(3) manual page.
+ *
+ *
+ *                      SLIST   LIST    STAILQ  TAILQ   CIRCLEQ
+ * _HEAD                +       +       +       +       +
+ * _HEAD_INITIALIZER    +       +       +       +       +
+ * _ENTRY               +       +       +       +       +
+ * _INIT                +       +       +       +       +
+ * _EMPTY               +       +       +       +       +
+ * _FIRST               +       +       +       +       +
+ * _NEXT                +       +       +       +       +
+ * _PREV                -       -       -       +       +
+ * _LAST                -       -       +       +       +
+ * _FOREACH             +       +       +       +       +
+ * _FOREACH_REVERSE     -       -       -       +       +
+ * _INSERT_HEAD         +       +       +       +       +
+ * _INSERT_BEFORE       -       +       -       +       +
+ * _INSERT_AFTER        +       +       +       +       +
+ * _INSERT_TAIL         -       -       +       +       +
+ * _REMOVE_HEAD         +       -       +       -       -
+ * _REMOVE              +       +       +       +       +
+ *
+ */
+
+/*
+ * Circular queue declarations.
+ */
+#define	CIRCLEQ_HEAD(name, type)					\
+struct name {								\
+	struct type *cqh_first;		/* first element */		\
+	struct type *cqh_last;		/* last element */		\
+}
+
+#define	CIRCLEQ_HEAD_INITIALIZER(head)					\
+	{ (void *)&(head), (void *)&(head) }
+
+#define	CIRCLEQ_ENTRY(type)						\
+struct {								\
+	struct type *cqe_next;		/* next element */		\
+	struct type *cqe_prev;		/* previous element */		\
+}
+
+/*
+ * Circular queue functions.
+ */
+#define	CIRCLEQ_EMPTY(head)	((head)->cqh_first == (void *)(head))
+
+#define	CIRCLEQ_FIRST(head)	((head)->cqh_first)
+
+#define	CIRCLEQ_FOREACH(var, head, field)				\
+	for ((var) = CIRCLEQ_FIRST((head));				\
+	    (var) != (void *)(head) || ((var) = NULL);			\
+	    (var) = CIRCLEQ_NEXT((var), field))
+
+#define	CIRCLEQ_FOREACH_REVERSE(var, head, field)			\
+	for ((var) = CIRCLEQ_LAST((head));				\
+	    (var) != (void *)(head) || ((var) = NULL);			\
+	    (var) = CIRCLEQ_PREV((var), field))
+
+#define	CIRCLEQ_INIT(head) do {						\
+	CIRCLEQ_FIRST((head)) = (void *)(head);				\
+	CIRCLEQ_LAST((head)) = (void *)(head);				\
+} while (0)
+
+#define	CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do {		\
+	CIRCLEQ_NEXT((elm), field) = CIRCLEQ_NEXT((listelm), field);	\
+	CIRCLEQ_PREV((elm), field) = (listelm);				\
+	if (CIRCLEQ_NEXT((listelm), field) == (void *)(head))		\
+		CIRCLEQ_LAST((head)) = (elm);				\
+	else								\
+		CIRCLEQ_PREV(CIRCLEQ_NEXT((listelm), field), field) = (elm);\
+	CIRCLEQ_NEXT((listelm), field) = (elm);				\
+} while (0)
+
+#define	CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do {		\
+	CIRCLEQ_NEXT((elm), field) = (listelm);				\
+	CIRCLEQ_PREV((elm), field) = CIRCLEQ_PREV((listelm), field);	\
+	if (CIRCLEQ_PREV((listelm), field) == (void *)(head))		\
+		CIRCLEQ_FIRST((head)) = (elm);				\
+	else								\
+		CIRCLEQ_NEXT(CIRCLEQ_PREV((listelm), field), field) = (elm);\
+	CIRCLEQ_PREV((listelm), field) = (elm);				\
+} while (0)
+
+#define	CIRCLEQ_INSERT_HEAD(head, elm, field) do {			\
+	CIRCLEQ_NEXT((elm), field) = CIRCLEQ_FIRST((head));		\
+	CIRCLEQ_PREV((elm), field) = (void *)(head);			\
+	if (CIRCLEQ_LAST((head)) == (void *)(head))			\
+		CIRCLEQ_LAST((head)) = (elm);				\
+	else								\
+		CIRCLEQ_PREV(CIRCLEQ_FIRST((head)), field) = (elm);	\
+	CIRCLEQ_FIRST((head)) = (elm);					\
+} while (0)
+
+#define	CIRCLEQ_INSERT_TAIL(head, elm, field) do {			\
+	CIRCLEQ_NEXT((elm), field) = (void *)(head);			\
+	CIRCLEQ_PREV((elm), field) = CIRCLEQ_LAST((head));		\
+	if (CIRCLEQ_FIRST((head)) == (void *)(head))			\
+		CIRCLEQ_FIRST((head)) = (elm);				\
+	else								\
+		CIRCLEQ_NEXT(CIRCLEQ_LAST((head)), field) = (elm);	\
+	CIRCLEQ_LAST((head)) = (elm);					\
+} while (0)
+
+#define	CIRCLEQ_LAST(head)	((head)->cqh_last)
+
+#define	CIRCLEQ_NEXT(elm,field)	((elm)->field.cqe_next)
+
+#define	CIRCLEQ_PREV(elm,field)	((elm)->field.cqe_prev)
+
+#define	CIRCLEQ_REMOVE(head, elm, field) do {				\
+	if (CIRCLEQ_NEXT((elm), field) == (void *)(head))		\
+		CIRCLEQ_LAST((head)) = CIRCLEQ_PREV((elm), field);	\
+	else								\
+		CIRCLEQ_PREV(CIRCLEQ_NEXT((elm), field), field) =	\
+		    CIRCLEQ_PREV((elm), field);				\
+	if (CIRCLEQ_PREV((elm), field) == (void *)(head))		\
+		CIRCLEQ_FIRST((head)) = CIRCLEQ_NEXT((elm), field);	\
+	else								\
+		CIRCLEQ_NEXT(CIRCLEQ_PREV((elm), field), field) =	\
+		    CIRCLEQ_NEXT((elm), field);				\
+} while (0)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !_SYS_QUEUE_H_ */

+ 45 - 0
components/bt/porting/nimble/include/os/util.h

@@ -0,0 +1,45 @@
+/*
+ * SPDX-FileCopyrightText: 2015-2022 The Apache Software Foundation (ASF)
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * SPDX-FileContributor: 2019-2022 Espressif Systems (Shanghai) CO LTD
+ */
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 H_OS_UTIL_
+#define H_OS_UTIL_
+
+/* Helpers to pass integers as pointers and vice-versa */
+#define POINTER_TO_UINT(p) ((unsigned int) ((uintptr_t) (p)))
+#define UINT_TO_POINTER(u) ((void *) ((uintptr_t) (u)))
+#define POINTER_TO_INT(p) ((int) ((intptr_t) (p)))
+#define INT_TO_POINTER(u) ((void *) ((intptr_t) (u)))
+
+/* Helper to retrieve pointer to "parent" object in structure */
+#define CONTAINER_OF(ptr, type, field) \
+        ((type *)(((char *)(ptr)) - offsetof(type, field)))
+
+/* Helper to calculate number of elements in array */
+#ifndef ARRAY_SIZE
+#define ARRAY_SIZE(array) \
+        (sizeof(array) / sizeof((array)[0]))
+#endif
+#endif

+ 206 - 0
components/bt/porting/nimble/src/os_msys_init.c

@@ -0,0 +1,206 @@
+/*
+ * SPDX-FileCopyrightText: 2015-2022 The Apache Software Foundation (ASF)
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * SPDX-FileContributor: 2019-2022 Espressif Systems (Shanghai) CO LTD
+ */
+
+#include <assert.h>
+
+#include "os/os.h"
+#include "mem_api.h"
+#include "bt_osi_mem.h"
+#include "esp_err.h"
+
+#if CONFIG_BT_NIMBLE_ENABLED
+#include "syscfg/syscfg.h"
+#endif
+
+#define SYSINIT_PANIC_ASSERT(rc)        assert(rc);
+
+static STAILQ_HEAD(, os_mbuf_pool) g_msys_pool_list =
+    STAILQ_HEAD_INITIALIZER(g_msys_pool_list);
+
+#if CONFIG_BT_NIMBLE_ENABLED
+#define OS_MSYS_1_BLOCK_COUNT MYNEWT_VAL(MSYS_1_BLOCK_COUNT)
+#define OS_MSYS_1_BLOCK_SIZE MYNEWT_VAL(MSYS_1_BLOCK_SIZE)
+#define OS_MSYS_2_BLOCK_COUNT MYNEWT_VAL(MSYS_2_BLOCK_COUNT)
+#define OS_MSYS_2_BLOCK_SIZE MYNEWT_VAL(MSYS_2_BLOCK_SIZE)
+
+#define OS_MSYS_1_SANITY_MIN_COUNT MYNEWT_VAL(MSYS_1_SANITY_MIN_COUNT)
+#define OS_MSYS_2_SANITY_MIN_COUNT MYNEWT_VAL(MSYS_2_SANITY_MIN_COUNT)
+#else
+#define OS_MSYS_1_BLOCK_COUNT CONFIG_BT_LE_MSYS_1_BLOCK_COUNT
+#define OS_MSYS_1_BLOCK_SIZE CONFIG_BT_LE_MSYS_1_BLOCK_SIZE
+#define OS_MSYS_2_BLOCK_COUNT CONFIG_BT_LE_MSYS_2_BLOCK_COUNT
+#define OS_MSYS_2_BLOCK_SIZE CONFIG_BT_LE_MSYS_2_BLOCK_SIZE
+
+#define OS_MSYS_1_SANITY_MIN_COUNT 0
+#define OS_MSYS_2_SANITY_MIN_COUNT 0
+#endif
+
+
+
+#if OS_MSYS_1_BLOCK_COUNT > 0
+#define SYSINIT_MSYS_1_MEMBLOCK_SIZE                \
+    OS_ALIGN(OS_MSYS_1_BLOCK_SIZE, 4)
+#define SYSINIT_MSYS_1_MEMPOOL_SIZE                 \
+    OS_MEMPOOL_SIZE(OS_MSYS_1_BLOCK_COUNT,  \
+                    SYSINIT_MSYS_1_MEMBLOCK_SIZE)
+static os_membuf_t *os_msys_init_1_data;
+static struct os_mbuf_pool os_msys_init_1_mbuf_pool;
+static struct os_mempool os_msys_init_1_mempool;
+#endif
+
+#if OS_MSYS_2_BLOCK_COUNT > 0
+#define SYSINIT_MSYS_2_MEMBLOCK_SIZE                \
+    OS_ALIGN(OS_MSYS_2_BLOCK_SIZE, 4)
+#define SYSINIT_MSYS_2_MEMPOOL_SIZE                 \
+    OS_MEMPOOL_SIZE(OS_MSYS_2_BLOCK_COUNT,  \
+                    SYSINIT_MSYS_2_MEMBLOCK_SIZE)
+static os_membuf_t *os_msys_init_2_data;
+static struct os_mbuf_pool os_msys_init_2_mbuf_pool;
+static struct os_mempool os_msys_init_2_mempool;
+#endif
+
+#define OS_MSYS_SANITY_ENABLED                  \
+    (OS_MSYS_1_SANITY_MIN_COUNT > 0 || \
+     OS_MSYS_1_SANITY_MIN_COUNT > 0)
+
+#if OS_MSYS_SANITY_ENABLED
+static struct os_sanity_check os_msys_sc;
+#endif
+
+#if OS_MSYS_SANITY_ENABLED
+
+/**
+ * Retrieves the minimum safe buffer count for an msys pool.  That is, the
+ * lowest a pool's buffer count can be without causing the sanity check to
+ * fail.
+ *
+ * @param idx                   The index of the msys pool to query.
+ *
+ * @return                      The msys pool's minimum safe buffer count.
+ */
+static int
+IRAM_ATTR os_msys_sanity_min_count(int idx)
+{
+    switch (idx) {
+    case 0:
+        return OS_MSYS_1_SANITY_MIN_COUNT;
+
+    case 1:
+        return OS_MSYS_1_SANITY_MIN_COUNT;
+
+    default:
+        BLE_LL_ASSERT(0);
+        return ESP_OK;
+    }
+}
+
+static int
+IRAM_ATTR os_msys_sanity(struct os_sanity_check *sc, void *arg)
+{
+    const struct os_mbuf_pool *omp;
+    int min_count;
+    int idx;
+
+    idx = 0;
+    STAILQ_FOREACH(omp, &g_msys_pool_list, omp_next) {
+        min_count = os_msys_sanity_min_count(idx);
+        if (omp->omp_pool->mp_num_free < min_count) {
+            return OS_ENOMEM;
+        }
+
+        idx++;
+    }
+
+    return ESP_OK;
+}
+#endif
+
+static void
+os_msys_init_once(void *data, struct os_mempool *mempool,
+                  struct os_mbuf_pool *mbuf_pool,
+                  int block_count, int block_size, const char *name)
+{
+    int rc;
+
+    rc = mem_init_mbuf_pool(data, mempool, mbuf_pool, block_count, block_size,
+                            name);
+    SYSINIT_PANIC_ASSERT(rc == 0);
+
+    rc = os_msys_register(mbuf_pool);
+    SYSINIT_PANIC_ASSERT(rc == 0);
+}
+
+int
+os_msys_buf_alloc(void)
+{
+#if OS_MSYS_1_BLOCK_COUNT > 0
+    os_msys_init_1_data = (os_membuf_t *)bt_osi_mem_calloc(1, (sizeof(os_membuf_t) * SYSINIT_MSYS_1_MEMPOOL_SIZE));
+    if (!os_msys_init_1_data) {
+        return ESP_FAIL;
+    }
+#endif
+
+#if OS_MSYS_2_BLOCK_COUNT > 0
+    os_msys_init_2_data = (os_membuf_t *)bt_osi_mem_calloc(1, (sizeof(os_membuf_t) * SYSINIT_MSYS_2_MEMPOOL_SIZE));
+    if (!os_msys_init_2_data) {
+        return ESP_FAIL;
+    }
+#endif
+
+    return ESP_OK;
+}
+
+void
+os_msys_buf_free(void)
+{
+#if OS_MSYS_1_BLOCK_COUNT > 0
+    bt_osi_mem_free(os_msys_init_1_data);
+    os_msys_init_1_data = NULL;
+#endif
+
+#if OS_MSYS_2_BLOCK_COUNT > 0
+    bt_osi_mem_free(os_msys_init_2_data);
+    os_msys_init_2_data = NULL;
+#endif
+
+}
+
+void os_msys_init(void)
+{
+#if OS_MSYS_SANITY_ENABLED
+    int rc;
+#endif
+
+    os_msys_reset();
+
+#if OS_MSYS_1_BLOCK_COUNT > 0
+    os_msys_init_once(os_msys_init_1_data,
+                      &os_msys_init_1_mempool,
+                      &os_msys_init_1_mbuf_pool,
+                      OS_MSYS_1_BLOCK_COUNT,
+                      SYSINIT_MSYS_1_MEMBLOCK_SIZE,
+                      "msys_1");
+#endif
+
+#if OS_MSYS_2_BLOCK_COUNT > 0
+    os_msys_init_once(os_msys_init_2_data,
+                      &os_msys_init_2_mempool,
+                      &os_msys_init_2_mbuf_pool,
+                      OS_MSYS_2_BLOCK_COUNT,
+                      SYSINIT_MSYS_2_MEMBLOCK_SIZE,
+                      "msys_2");
+#endif
+
+#if OS_MSYS_SANITY_ENABLED
+    os_msys_sc.sc_func = os_msys_sanity;
+    os_msys_sc.sc_checkin_itvl =
+        OS_TICKS_PER_SEC * MYNEWT_VAL(MSYS_SANITY_TIMEOUT) / 1000;
+    rc = os_sanity_check_register(&os_msys_sc);
+    SYSINIT_PANIC_ASSERT(rc == 0);
+#endif
+}

+ 381 - 0
components/bt/porting/npl/freertos/include/nimble/nimble_npl_os.h

@@ -0,0 +1,381 @@
+/*
+ * SPDX-FileCopyrightText: 2015-2022 The Apache Software Foundation (ASF)
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * SPDX-FileContributor: 2019-2022 Espressif Systems (Shanghai) CO LTD
+ */
+
+#ifndef _NIMBLE_NPL_OS_H_
+#define _NIMBLE_NPL_OS_H_
+
+#include <assert.h>
+#include <stdint.h>
+#include <string.h>
+#include "freertos/FreeRTOS.h"
+#include "freertos/queue.h"
+#include "freertos/semphr.h"
+#include "freertos/task.h"
+#include "freertos/timers.h"
+#include "esp_timer.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef ARRAY_SIZE
+#define ARRAY_SIZE(array) \
+        (sizeof(array) / sizeof((array)[0]))
+#endif
+
+extern int ets_printf(const char *fmt, ...);
+#define  BLE_LL_ASSERT(con)                         \
+    do{                                             \
+        if(!(con))  {                               \
+            ets_printf("assertion:%s\n",#con);      \
+            ets_printf("line:%d,function:%s\n", __LINE__, __func__);\
+            assert(0);                              \
+        }                                           \
+    }while(0)
+
+#define BLE_NPL_OS_ALIGNMENT    (4)/*ble_npl_get_os_alignment()*/
+
+#define BLE_NPL_TIME_FOREVER    ble_npl_get_time_forever()
+
+/* This should be compatible with TickType_t */
+typedef uint32_t ble_npl_time_t;
+typedef int32_t ble_npl_stime_t;
+
+struct ble_npl_event;
+typedef void ble_npl_event_fn(struct ble_npl_event *ev);
+
+struct ble_npl_event {
+    void *event;
+};
+
+struct ble_npl_eventq {
+    void *eventq;
+};
+
+struct ble_npl_callout {
+    void *co;
+};
+
+struct ble_npl_mutex {
+    void *mutex;
+};
+
+struct ble_npl_sem {
+    void *sem;
+};
+
+/*
+ * Simple APIs are just defined as static inline below, but some are a bit more
+ * complex or require some global state variables and thus are defined in .c
+ * file instead and static inline wrapper just calls proper implementation.
+ * We need declarations of these functions and they are defined in header below.
+ */
+#include "npl_freertos.h"
+
+struct npl_funcs_t {
+    bool (*p_ble_npl_os_started)(void);
+    void *(*p_ble_npl_get_current_task_id)(void);
+    void (*p_ble_npl_eventq_init)(struct ble_npl_eventq *);
+    void (*p_ble_npl_eventq_deinit)(struct ble_npl_eventq *);
+    struct ble_npl_event * (*p_ble_npl_eventq_get)(struct ble_npl_eventq *, ble_npl_time_t);
+    void (*p_ble_npl_eventq_put)(struct ble_npl_eventq *, struct ble_npl_event *);
+    void (*p_ble_npl_eventq_remove)(struct ble_npl_eventq *, struct ble_npl_event *);
+    void (*p_ble_npl_event_run)(struct ble_npl_event *);
+    bool (*p_ble_npl_eventq_is_empty)(struct ble_npl_eventq *);
+    void (*p_ble_npl_event_init)(struct ble_npl_event *, ble_npl_event_fn *, void *);
+    void (*p_ble_npl_event_deinit)(struct ble_npl_event *);
+    void (*p_ble_npl_event_reset)(struct ble_npl_event *);
+    bool (*p_ble_npl_event_is_queued)(struct ble_npl_event *);
+    void * (*p_ble_npl_event_get_arg)(struct ble_npl_event *);
+    void (*p_ble_npl_event_set_arg)(struct ble_npl_event *, void *);
+    ble_npl_error_t (*p_ble_npl_mutex_init)(struct ble_npl_mutex *);
+    ble_npl_error_t (*p_ble_npl_mutex_deinit)(struct ble_npl_mutex *);
+    ble_npl_error_t (*p_ble_npl_mutex_pend)(struct ble_npl_mutex *, ble_npl_time_t);
+    ble_npl_error_t (*p_ble_npl_mutex_release)(struct ble_npl_mutex *);
+    ble_npl_error_t (*p_ble_npl_sem_init)(struct ble_npl_sem *, uint16_t);
+    ble_npl_error_t (*p_ble_npl_sem_deinit)(struct ble_npl_sem *);
+    ble_npl_error_t (*p_ble_npl_sem_pend)(struct ble_npl_sem *, ble_npl_time_t);
+    ble_npl_error_t (*p_ble_npl_sem_release)(struct ble_npl_sem *);
+    uint16_t (*p_ble_npl_sem_get_count)(struct ble_npl_sem *);
+    void (*p_ble_npl_callout_init)(struct ble_npl_callout *, struct ble_npl_eventq *, ble_npl_event_fn *, void *);
+    ble_npl_error_t (*p_ble_npl_callout_reset)(struct ble_npl_callout *, ble_npl_time_t);
+    void (*p_ble_npl_callout_stop)(struct ble_npl_callout *);
+    void (*p_ble_npl_callout_deinit)(struct ble_npl_callout *);
+    void (*p_ble_npl_callout_mem_reset)(struct ble_npl_callout *);
+    bool (*p_ble_npl_callout_is_active)(struct ble_npl_callout *);
+    ble_npl_time_t (*p_ble_npl_callout_get_ticks)(struct ble_npl_callout *);
+    uint32_t (*p_ble_npl_callout_remaining_ticks)(struct ble_npl_callout *, ble_npl_time_t);
+    void (*p_ble_npl_callout_set_arg)(struct ble_npl_callout *, void *);
+    uint32_t (*p_ble_npl_time_get)(void);
+    ble_npl_error_t (*p_ble_npl_time_ms_to_ticks)(uint32_t ms, ble_npl_time_t *);
+    ble_npl_error_t (*p_ble_npl_time_ticks_to_ms)(ble_npl_time_t, uint32_t *);
+    ble_npl_time_t (*p_ble_npl_time_ms_to_ticks32)(uint32_t);
+    uint32_t (*p_ble_npl_time_ticks_to_ms32)(ble_npl_time_t);
+    void (*p_ble_npl_time_delay)(ble_npl_time_t);
+    void (*p_ble_npl_hw_set_isr)(int, uint32_t);
+    uint32_t (*p_ble_npl_hw_enter_critical)(void);
+    void (*p_ble_npl_hw_exit_critical)(uint32_t);
+    uint32_t (*p_ble_npl_get_time_forever)(void);
+    uint8_t (*p_ble_npl_hw_is_in_critical)(void);
+};
+
+extern struct npl_funcs_t *npl_funcs;
+
+static inline bool
+IRAM_ATTR ble_npl_os_started(void)
+{
+    return npl_funcs->p_ble_npl_os_started();
+}
+
+static inline void *
+IRAM_ATTR ble_npl_get_current_task_id(void)
+{
+    return npl_funcs->p_ble_npl_get_current_task_id();
+}
+
+static inline void
+IRAM_ATTR ble_npl_eventq_init(struct ble_npl_eventq *evq)
+{
+    return npl_funcs->p_ble_npl_eventq_init(evq);
+}
+
+static inline void
+IRAM_ATTR ble_npl_eventq_deinit(struct ble_npl_eventq *evq)
+{
+    return npl_funcs->p_ble_npl_eventq_deinit(evq);
+}
+
+static inline struct ble_npl_event *
+IRAM_ATTR ble_npl_eventq_get(struct ble_npl_eventq *evq, ble_npl_time_t tmo)
+{
+    return npl_funcs->p_ble_npl_eventq_get(evq, tmo);
+}
+
+static inline void
+IRAM_ATTR ble_npl_eventq_put(struct ble_npl_eventq *evq, struct ble_npl_event *ev)
+{
+    return npl_funcs->p_ble_npl_eventq_put(evq, ev);
+}
+
+static inline void
+IRAM_ATTR ble_npl_eventq_remove(struct ble_npl_eventq *evq, struct ble_npl_event *ev)
+{
+    return npl_funcs->p_ble_npl_eventq_remove(evq, ev);
+}
+
+static inline void
+IRAM_ATTR ble_npl_event_run(struct ble_npl_event *ev)
+{
+    return npl_funcs->p_ble_npl_event_run(ev);
+}
+
+static inline bool
+IRAM_ATTR ble_npl_eventq_is_empty(struct ble_npl_eventq *evq)
+{
+    return npl_funcs->p_ble_npl_eventq_is_empty(evq);
+}
+
+static inline void
+IRAM_ATTR ble_npl_event_init(struct ble_npl_event *ev, ble_npl_event_fn *fn,
+                   void *arg)
+{
+    return npl_funcs->p_ble_npl_event_init(ev, fn, arg);
+}
+
+static inline bool
+IRAM_ATTR ble_npl_event_is_queued(struct ble_npl_event *ev)
+{
+    return npl_funcs->p_ble_npl_event_is_queued(ev);
+}
+
+static inline void *
+IRAM_ATTR ble_npl_event_get_arg(struct ble_npl_event *ev)
+{
+    return npl_funcs->p_ble_npl_event_get_arg(ev);
+}
+
+static inline void
+IRAM_ATTR ble_npl_event_set_arg(struct ble_npl_event *ev, void *arg)
+{
+    return npl_funcs->p_ble_npl_event_set_arg(ev, arg);
+}
+
+static inline ble_npl_error_t
+IRAM_ATTR ble_npl_mutex_init(struct ble_npl_mutex *mu)
+{
+    return npl_funcs->p_ble_npl_mutex_init(mu);
+}
+
+static inline ble_npl_error_t
+IRAM_ATTR ble_npl_mutex_deinit(struct ble_npl_mutex *mu)
+{
+   return npl_funcs->p_ble_npl_mutex_deinit(mu);
+}
+
+static inline ble_npl_error_t
+IRAM_ATTR ble_npl_mutex_pend(struct ble_npl_mutex *mu, ble_npl_time_t timeout)
+{
+    return npl_funcs->p_ble_npl_mutex_pend(mu, timeout);
+}
+
+static inline ble_npl_error_t
+IRAM_ATTR ble_npl_mutex_release(struct ble_npl_mutex *mu)
+{
+    return npl_funcs->p_ble_npl_mutex_release(mu);
+}
+
+static inline ble_npl_error_t
+IRAM_ATTR ble_npl_sem_init(struct ble_npl_sem *sem, uint16_t tokens)
+{
+   return npl_funcs->p_ble_npl_sem_init(sem, tokens);
+}
+
+static inline ble_npl_error_t
+IRAM_ATTR ble_npl_sem_deinit(struct ble_npl_sem *sem)
+{
+    return npl_funcs->p_ble_npl_sem_deinit(sem);
+}
+
+static inline ble_npl_error_t
+IRAM_ATTR ble_npl_sem_pend(struct ble_npl_sem *sem, ble_npl_time_t timeout)
+{
+    return npl_funcs->p_ble_npl_sem_pend(sem, timeout);
+}
+
+static inline ble_npl_error_t
+IRAM_ATTR ble_npl_sem_release(struct ble_npl_sem *sem)
+{
+    return npl_funcs->p_ble_npl_sem_release(sem);
+}
+
+static inline uint16_t
+IRAM_ATTR ble_npl_sem_get_count(struct ble_npl_sem *sem)
+{
+    return npl_funcs->p_ble_npl_sem_get_count(sem);
+}
+
+static inline void
+IRAM_ATTR ble_npl_callout_init(struct ble_npl_callout *co, struct ble_npl_eventq *evq,
+                     ble_npl_event_fn *ev_cb, void *ev_arg)
+{
+    return npl_funcs->p_ble_npl_callout_init(co, evq, ev_cb, ev_arg);
+}
+static inline void
+IRAM_ATTR ble_npl_callout_deinit(struct ble_npl_callout *co)
+{
+    return npl_funcs->p_ble_npl_callout_deinit(co);
+}
+
+static inline ble_npl_error_t
+IRAM_ATTR ble_npl_callout_reset(struct ble_npl_callout *co, ble_npl_time_t ticks)
+{
+    return npl_funcs->p_ble_npl_callout_reset(co, ticks);
+}
+
+static inline void
+IRAM_ATTR ble_npl_callout_stop(struct ble_npl_callout *co)
+{
+    return npl_funcs->p_ble_npl_callout_stop(co);
+}
+
+static inline bool
+IRAM_ATTR ble_npl_callout_is_active(struct ble_npl_callout *co)
+{
+    return npl_funcs->p_ble_npl_callout_is_active(co);
+}
+
+static inline ble_npl_time_t
+IRAM_ATTR ble_npl_callout_get_ticks(struct ble_npl_callout *co)
+{
+    return npl_funcs->p_ble_npl_callout_get_ticks(co);
+}
+
+static inline ble_npl_time_t
+IRAM_ATTR ble_npl_callout_remaining_ticks(struct ble_npl_callout *co,
+                                ble_npl_time_t time)
+{
+    return npl_funcs->p_ble_npl_callout_remaining_ticks(co, time);
+}
+
+static inline void
+IRAM_ATTR ble_npl_callout_set_arg(struct ble_npl_callout *co, void *arg)
+{
+    return npl_funcs->p_ble_npl_callout_set_arg(co, arg);
+}
+
+static inline ble_npl_time_t
+IRAM_ATTR ble_npl_time_get(void)
+{
+    return npl_funcs->p_ble_npl_time_get();
+}
+
+static inline ble_npl_error_t
+IRAM_ATTR ble_npl_time_ms_to_ticks(uint32_t ms, ble_npl_time_t *out_ticks)
+{
+    return npl_funcs->p_ble_npl_time_ms_to_ticks(ms, out_ticks);
+}
+
+static inline ble_npl_error_t
+IRAM_ATTR ble_npl_time_ticks_to_ms(ble_npl_time_t ticks, uint32_t *out_ms)
+{
+    return npl_funcs->p_ble_npl_time_ticks_to_ms(ticks, out_ms);
+}
+
+static inline ble_npl_time_t
+IRAM_ATTR ble_npl_time_ms_to_ticks32(uint32_t ms)
+{
+    return npl_funcs->p_ble_npl_time_ms_to_ticks32(ms);
+}
+
+static inline uint32_t
+IRAM_ATTR ble_npl_time_ticks_to_ms32(ble_npl_time_t ticks)
+{
+    return npl_funcs->p_ble_npl_time_ticks_to_ms32(ticks);
+}
+
+static inline void
+IRAM_ATTR ble_npl_time_delay(ble_npl_time_t ticks)
+{
+    return npl_funcs->p_ble_npl_time_delay(ticks);
+}
+
+#if NIMBLE_CFG_CONTROLLER
+static inline void
+IRAM_ATTR ble_npl_hw_set_isr(int irqn, uint32_t addr)
+{
+    return npl_funcs->p_ble_npl_hw_set_isr(irqn, addr);
+}
+#endif
+
+static inline uint32_t
+IRAM_ATTR ble_npl_hw_enter_critical(void)
+{
+    return npl_funcs->p_ble_npl_hw_enter_critical();
+}
+
+static inline void
+IRAM_ATTR ble_npl_hw_exit_critical(uint32_t ctx)
+{
+    return npl_funcs->p_ble_npl_hw_exit_critical(ctx);
+}
+
+static inline bool IRAM_ATTR ble_npl_hw_is_in_critical(void)
+{
+    return npl_funcs->p_ble_npl_hw_is_in_critical();
+}
+
+#define ble_npl_get_time_forever (*npl_funcs->p_ble_npl_get_time_forever)
+#define ble_npl_callout_mem_reset (*npl_funcs->p_ble_npl_callout_mem_reset)
+#define ble_npl_event_deinit (*npl_funcs->p_ble_npl_event_deinit)
+#define ble_npl_event_reset (*npl_funcs->p_ble_npl_event_reset)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  /* _NPL_H_ */

+ 28 - 0
components/bt/porting/npl/freertos/include/nimble/nimble_port_freertos.h

@@ -0,0 +1,28 @@
+/*
+ * SPDX-FileCopyrightText: 2015-2022 The Apache Software Foundation (ASF)
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * SPDX-FileContributor: 2019-2022 Espressif Systems (Shanghai) CO LTD
+ */
+
+#ifndef _NIMBLE_PORT_FREERTOS_H
+#define _NIMBLE_PORT_FREERTOS_H
+
+#include "nimble/nimble_npl.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void nimble_port_freertos_init(TaskFunction_t host_task_fn);
+void nimble_port_freertos_deinit(void);
+void npl_freertos_funcs_init(void);
+void npl_freertos_funcs_deinit(void);
+int npl_freertos_mempool_init(void);
+struct npl_funcs_t * npl_freertos_funcs_get(void);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _NIMBLE_PORT_FREERTOS_H */

+ 108 - 0
components/bt/porting/npl/freertos/include/nimble/npl_freertos.h

@@ -0,0 +1,108 @@
+/*
+ * SPDX-FileCopyrightText: 2015-2022 The Apache Software Foundation (ASF)
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * SPDX-FileContributor: 2019-2022 Espressif Systems (Shanghai) CO LTD
+ */
+
+#ifndef _NPL_FREERTOS_H_
+#define _NPL_FREERTOS_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef void ble_npl_event_fn(struct ble_npl_event *ev);
+
+struct ble_npl_event_freertos {
+    bool queued;
+    ble_npl_event_fn *fn;
+    void *arg;
+};
+
+struct ble_npl_eventq_freertos {
+    QueueHandle_t q;
+};
+
+struct ble_npl_callout_freertos {
+#if CONFIG_BT_NIMBLE_USE_ESP_TIMER
+   esp_timer_handle_t handle;
+#else
+    TimerHandle_t handle;
+#endif
+    struct ble_npl_eventq *evq;
+    struct ble_npl_event ev;
+};
+
+struct ble_npl_mutex_freertos {
+    SemaphoreHandle_t handle;
+};
+
+struct ble_npl_sem_freertos {
+    SemaphoreHandle_t handle;
+};
+
+typedef void ble_npl_event_fn_freertos(struct ble_npl_event_freertos *ev);
+
+struct ble_npl_eventq *npl_freertos_eventq_dflt_get(void);
+
+struct ble_npl_event *npl_freertos_eventq_get(struct ble_npl_eventq *evq,
+                                              ble_npl_time_t tmo);
+
+void npl_freertos_eventq_put(struct ble_npl_eventq *evq,
+                             struct ble_npl_event *ev);
+
+void npl_freertos_eventq_remove(struct ble_npl_eventq *evq,
+                                struct ble_npl_event *ev);
+
+ble_npl_error_t npl_freertos_mutex_init(struct ble_npl_mutex *mu);
+ble_npl_error_t npl_freertos_mutex_deinit(struct ble_npl_mutex *mu);
+
+ble_npl_error_t npl_freertos_mutex_pend(struct ble_npl_mutex *mu,
+                                        ble_npl_time_t timeout);
+
+ble_npl_error_t npl_freertos_mutex_release(struct ble_npl_mutex *mu);
+
+ble_npl_error_t npl_freertos_sem_init(struct ble_npl_sem *sem, uint16_t tokens);
+ble_npl_error_t npl_freertos_sem_deinit(struct ble_npl_sem *sem);
+
+ble_npl_error_t npl_freertos_sem_pend(struct ble_npl_sem *sem,
+                                      ble_npl_time_t timeout);
+
+ble_npl_error_t npl_freertos_sem_release(struct ble_npl_sem *sem);
+
+void npl_freertos_callout_init(struct ble_npl_callout *co,
+                               struct ble_npl_eventq *evq,
+                               ble_npl_event_fn *ev_cb, void *ev_arg);
+
+void npl_freertos_callout_deinit(struct ble_npl_callout *co);
+
+void npl_freertos_callout_stop(struct ble_npl_callout *co);
+
+bool npl_freertos_callout_is_active(struct ble_npl_callout *co);
+
+ble_npl_time_t npl_freertos_callout_get_ticks(struct ble_npl_callout *co);
+
+ble_npl_error_t npl_freertos_callout_reset(struct ble_npl_callout *co,
+                                           ble_npl_time_t ticks);
+
+ble_npl_time_t npl_freertos_callout_remaining_ticks(struct ble_npl_callout *co,
+						    ble_npl_time_t now);
+
+ble_npl_error_t npl_freertos_time_ms_to_ticks(uint32_t ms,
+                                              ble_npl_time_t *out_ticks);
+
+ble_npl_error_t npl_freertos_time_ticks_to_ms(ble_npl_time_t ticks,
+                                              uint32_t *out_ms);
+
+
+uint32_t npl_freertos_hw_enter_critical(void);
+
+void npl_freertos_hw_exit_critical(uint32_t ctx);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  /* _NPL_FREERTOS_H_ */

+ 1211 - 0
components/bt/porting/npl/freertos/src/npl_os_freertos.c

@@ -0,0 +1,1211 @@
+/*
+ * SPDX-FileCopyrightText: 2015-2022 The Apache Software Foundation (ASF)
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * SPDX-FileContributor: 2019-2022 Espressif Systems (Shanghai) CO LTD
+ */
+
+#include <assert.h>
+#include <stddef.h>
+#include <string.h>
+
+#include "nimble/nimble_npl.h"
+#include "freertos/FreeRTOS.h"
+#include "freertos/queue.h"
+#include "freertos/semphr.h"
+#include "freertos/task.h"
+#include "freertos/timers.h"
+#include "freertos/portable.h"
+#include "nimble/npl_freertos.h"
+
+#include "os/os_mempool.h"
+#include "esp_log.h"
+#include "soc/soc_caps.h"
+#include "esp_bt.h"
+
+portMUX_TYPE ble_port_mutex = portMUX_INITIALIZER_UNLOCKED;
+
+#if CONFIG_BT_NIMBLE_USE_ESP_TIMER
+static const char *TAG = "Timer";
+#endif
+
+#define OS_MEM_ALLOC (1)
+
+#define BT_LE_HCI_EVT_HI_BUF_COUNT DEFAULT_BT_LE_HCI_EVT_HI_BUF_COUNT
+#define BT_LE_HCI_EVT_LO_BUF_COUNT DEFAULT_BT_LE_HCI_EVT_LO_BUF_COUNT
+#define BT_LE_MAX_EXT_ADV_INSTANCES DEFAULT_BT_LE_MAX_EXT_ADV_INSTANCES
+#define BT_LE_MAX_CONNECTIONS DEFAULT_BT_LE_MAX_CONNECTIONS
+
+#if CONFIG_BT_NIMBLE_ENABLED
+    #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_PING)
+    #define LL_CFG_FEAT_LE_PING_EVT         (1)
+    #else
+    #define LL_CFG_FEAT_LE_PING_EVT         (0)
+    #endif
+
+    #if MYNEWT_VAL(BLE_LL_CFG_FEAT_CTRL_TO_HOST_FLOW_CONTROL)
+    #define LL_CTRL_TO_HOST_FLOW_CTRL_EVT   (1)
+    #else
+    #define LL_CTRL_TO_HOST_FLOW_CTRL_EVT   (0)
+    #endif
+
+    #define BT_LE_LL_EXT_ADV_AUX_PTR_CNT MYNEWT_VAL(BLE_LL_EXT_ADV_AUX_PTR_CNT)
+
+#else
+    #define BT_LE_LL_EXT_ADV_AUX_PTR_CNT    (5)
+    #define LL_CFG_FEAT_LE_PING_EVT         (1)
+    #define LL_CTRL_TO_HOST_FLOW_CTRL_EVT   (1)
+#endif
+
+#define BLE_HS_HCI_EVT_COUNT                    \
+    (BT_LE_HCI_EVT_HI_BUF_COUNT +        \
+     BT_LE_HCI_EVT_LO_BUF_COUNT)
+
+
+#define LL_NPL_BASE_EVENT_COUNT     (11)
+#define LL_SCAN_EXT_AUX_EVT_CNT     (BT_LE_LL_EXT_ADV_AUX_PTR_CNT)
+#define HCI_LL_NPL_EVENT_COUNT      (1)
+#define ADV_LL_NPL_EVENT_COUNT      ((BT_LE_MAX_EXT_ADV_INSTANCES+1)*3)
+#define SCAN_LL_NPL_EVENT_COUNT     (2)
+#define RL_LL_NPL_EVENT_COUNT       (1)
+#define SYNC_LL_NPL_EVENT_COUNT     (7)
+
+
+
+
+
+#define CONN_MODULE_NPL_EVENT_COUNT (((LL_CFG_FEAT_LE_PING_EVT+2)*BT_LE_MAX_CONNECTIONS)+LL_CTRL_TO_HOST_FLOW_CTRL_EVT)
+
+
+#define BLE_LL_EV_COUNT (LL_NPL_BASE_EVENT_COUNT +      \
+                         LL_SCAN_EXT_AUX_EVT_CNT +      \
+                         HCI_LL_NPL_EVENT_COUNT +       \
+                         ADV_LL_NPL_EVENT_COUNT +       \
+                         SCAN_LL_NPL_EVENT_COUNT +      \
+                         RL_LL_NPL_EVENT_COUNT +        \
+                         SYNC_LL_NPL_EVENT_COUNT +      \
+                         CONN_MODULE_NPL_EVENT_COUNT)
+
+#define BLE_TOTAL_EV_COUNT (BLE_LL_EV_COUNT + BLE_HS_HCI_EVT_COUNT)
+
+#define BLE_TOTAL_EVQ_COUNT (10)
+
+#define BLE_TOTAL_CO_COUNT (40)
+
+#define BLE_TOTAL_SEM_COUNT (10)
+
+#define BLE_TOTAL_MUTEX_COUNT (10)
+
+#if SOC_ESP_NIMBLE_CONTROLLER
+
+struct os_mempool ble_freertos_ev_pool;
+static os_membuf_t *ble_freertos_ev_buf = NULL;
+
+struct os_mempool ble_freertos_evq_pool;
+static os_membuf_t *ble_freertos_evq_buf = NULL;
+
+struct os_mempool ble_freertos_co_pool;
+static os_membuf_t *ble_freertos_co_buf = NULL;
+
+struct os_mempool ble_freertos_sem_pool;
+static os_membuf_t *ble_freertos_sem_buf = NULL;
+
+struct os_mempool ble_freertos_mutex_pool;
+static os_membuf_t *ble_freertos_mutex_buf = NULL;
+
+#else
+
+struct os_mempool ble_freertos_ev_pool;
+static os_membuf_t ble_freertos_ev_buf[
+    OS_MEMPOOL_SIZE(BLE_TOTAL_EV_COUNT, sizeof (struct ble_npl_event_freertos))
+];
+
+struct os_mempool ble_freertos_evq_pool;
+static os_membuf_t ble_freertos_evq_buf[
+    OS_MEMPOOL_SIZE(BLE_TOTAL_EVQ_COUNT, sizeof (struct ble_npl_eventq_freertos))
+];
+
+struct os_mempool ble_freertos_co_pool;
+static os_membuf_t ble_freertos_co_buf[
+    OS_MEMPOOL_SIZE(BLE_TOTAL_CO_COUNT, sizeof (struct ble_npl_callout_freertos))
+];
+
+struct os_mempool ble_freertos_sem_pool;
+static os_membuf_t ble_freertos_sem_buf[
+    OS_MEMPOOL_SIZE(BLE_TOTAL_SEM_COUNT, sizeof (struct ble_npl_sem_freertos))
+];
+
+struct os_mempool ble_freertos_mutex_pool;
+static os_membuf_t ble_freertos_mutex_buf[
+    OS_MEMPOOL_SIZE(BLE_TOTAL_MUTEX_COUNT, sizeof (struct ble_npl_mutex_freertos))
+];
+
+#endif
+
+bool
+IRAM_ATTR npl_freertos_os_started(void)
+{
+    return xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED;
+}
+
+void *
+IRAM_ATTR npl_freertos_get_current_task_id(void)
+{
+    return xTaskGetCurrentTaskHandle();
+}
+
+void
+IRAM_ATTR npl_freertos_event_init(struct ble_npl_event *ev, ble_npl_event_fn *fn,
+                    void *arg)
+{
+    struct ble_npl_event_freertos *event = NULL;
+#if OS_MEM_ALLOC
+    if (!os_memblock_from(&ble_freertos_ev_pool,ev->event)) {
+        ev->event = os_memblock_get(&ble_freertos_ev_pool);
+    }
+#else
+    if(!ev->event) {
+        ev->event = malloc(sizeof(struct ble_npl_event_freertos));
+    }
+#endif
+    event = (struct ble_npl_event_freertos *)ev->event;
+    BLE_LL_ASSERT(event);
+
+    memset(event, 0, sizeof(*event));
+    event->fn = fn;
+    event->arg = arg;
+}
+
+void
+IRAM_ATTR npl_freertos_event_deinit(struct ble_npl_event *ev)
+{
+    BLE_LL_ASSERT(ev->event);
+#if OS_MEM_ALLOC
+    os_memblock_put(&ble_freertos_ev_pool,ev->event);
+#else
+    free(ev->event);
+#endif
+    ev->event = NULL;
+}
+
+void
+IRAM_ATTR npl_freertos_event_reset(struct ble_npl_event *ev)
+{
+    struct ble_npl_event_freertos *event = (struct ble_npl_event_freertos *)ev->event;
+    BLE_LL_ASSERT(event);
+    event->queued = 0;
+}
+
+void
+IRAM_ATTR npl_freertos_eventq_init(struct ble_npl_eventq *evq)
+{
+    struct ble_npl_eventq_freertos *eventq = NULL;
+#if OS_MEM_ALLOC
+    if (!os_memblock_from(&ble_freertos_evq_pool,evq->eventq)) {
+        evq->eventq = os_memblock_get(&ble_freertos_evq_pool);
+        eventq = (struct ble_npl_eventq_freertos*)evq->eventq;
+        BLE_LL_ASSERT(eventq);
+
+        memset(eventq, 0, sizeof(*eventq));
+        eventq->q = xQueueCreate(BLE_TOTAL_EV_COUNT, sizeof(struct ble_npl_eventq *));
+        BLE_LL_ASSERT(eventq->q);
+    }
+#else
+    if(!evq->eventq) {
+        evq->eventq = malloc(sizeof(struct ble_npl_eventq_freertos));
+        eventq = (struct ble_npl_eventq_freertos*)evq->eventq;
+        BLE_LL_ASSERT(eventq);
+
+        memset(eventq, 0, sizeof(*eventq));
+        eventq->q = xQueueCreate(BLE_TOTAL_EV_COUNT, sizeof(struct ble_npl_eventq *));
+        BLE_LL_ASSERT(eventq->q);
+    }
+#endif
+}
+
+void
+IRAM_ATTR npl_freertos_eventq_deinit(struct ble_npl_eventq *evq)
+{
+    struct ble_npl_eventq_freertos *eventq = (struct ble_npl_eventq_freertos *)evq->eventq;
+
+    BLE_LL_ASSERT(eventq);
+    vQueueDelete(eventq->q);
+#if OS_MEM_ALLOC
+    os_memblock_put(&ble_freertos_evq_pool,eventq);
+#else
+    free((void *)eventq);
+#endif
+    evq->eventq = NULL;
+}
+
+void
+IRAM_ATTR npl_freertos_callout_mem_reset(struct ble_npl_callout *co)
+{
+    struct ble_npl_callout_freertos *callout = (struct ble_npl_callout_freertos *)co->co;
+
+    BLE_LL_ASSERT(callout);
+    BLE_LL_ASSERT(callout->handle);
+
+    ble_npl_event_reset(&callout->ev);
+}
+
+static inline bool
+IRAM_ATTR in_isr(void)
+{
+    /* XXX hw specific! */
+    return xPortInIsrContext() != 0;
+}
+
+struct ble_npl_event *
+IRAM_ATTR npl_freertos_eventq_get(struct ble_npl_eventq *evq, ble_npl_time_t tmo)
+{
+    struct ble_npl_event *ev = NULL;
+    struct ble_npl_eventq_freertos *eventq = (struct ble_npl_eventq_freertos *)evq->eventq;
+    BaseType_t woken;
+    BaseType_t ret;
+
+    if (in_isr()) {
+        BLE_LL_ASSERT(tmo == 0);
+        ret = xQueueReceiveFromISR(eventq->q, &ev, &woken);
+        if( woken == pdTRUE ) {
+            portYIELD_FROM_ISR();
+        }
+    } else {
+        ret = xQueueReceive(eventq->q, &ev, tmo);
+    }
+    BLE_LL_ASSERT(ret == pdPASS || ret == errQUEUE_EMPTY);
+
+    if (ev) {
+	struct ble_npl_event_freertos *event = (struct ble_npl_event_freertos *)ev->event;
+	if (event) {
+            event->queued = false;
+	}
+    }
+
+    return ev;
+}
+
+void
+IRAM_ATTR npl_freertos_eventq_put(struct ble_npl_eventq *evq, struct ble_npl_event *ev)
+{
+    BaseType_t woken;
+    BaseType_t ret;
+    struct ble_npl_eventq_freertos *eventq = (struct ble_npl_eventq_freertos *)evq->eventq;
+    struct ble_npl_event_freertos *event = (struct ble_npl_event_freertos *)ev->event;
+
+    if (event->queued) {
+        return;
+    }
+
+    event->queued = true;
+
+    if (in_isr()) {
+        ret = xQueueSendToBackFromISR(eventq->q, &ev, &woken);
+        if( woken == pdTRUE ) {
+            portYIELD_FROM_ISR();
+        }
+    } else {
+        ret = xQueueSendToBack(eventq->q, &ev, portMAX_DELAY);
+    }
+
+    BLE_LL_ASSERT(ret == pdPASS);
+}
+
+void
+IRAM_ATTR npl_freertos_eventq_remove(struct ble_npl_eventq *evq,
+                       struct ble_npl_event *ev)
+{
+    struct ble_npl_event *tmp_ev;
+    BaseType_t ret;
+    int i;
+    int count;
+    BaseType_t woken, woken2;
+    struct ble_npl_eventq_freertos *eventq = (struct ble_npl_eventq_freertos *)evq->eventq;
+    struct ble_npl_event_freertos *event = (struct ble_npl_event_freertos *)ev->event;
+
+    if (!event->queued) {
+        return;
+    }
+
+    /*
+     * XXX We cannot extract element from inside FreeRTOS queue so as a quick
+     * workaround we'll just remove all elements and add them back except the
+     * one we need to remove. This is silly, but works for now - we probably
+     * better use counting semaphore with os_queue to handle this in future.
+     */
+
+    if (in_isr()) {
+        woken = pdFALSE;
+
+        count = uxQueueMessagesWaitingFromISR(eventq->q);
+        for (i = 0; i < count; i++) {
+            ret = xQueueReceiveFromISR(eventq->q, &tmp_ev, &woken2);
+            BLE_LL_ASSERT(ret == pdPASS);
+            woken |= woken2;
+
+            if (tmp_ev == ev) {
+                continue;
+            }
+
+            ret = xQueueSendToBackFromISR(eventq->q, &tmp_ev, &woken2);
+            BLE_LL_ASSERT(ret == pdPASS);
+            woken |= woken2;
+        }
+
+        if( woken == pdTRUE ) {
+            portYIELD_FROM_ISR();
+        }
+    } else {
+        portMUX_TYPE ble_npl_mut = portMUX_INITIALIZER_UNLOCKED;
+        portENTER_CRITICAL(&ble_npl_mut);
+
+        count = uxQueueMessagesWaiting(eventq->q);
+        for (i = 0; i < count; i++) {
+            ret = xQueueReceive(eventq->q, &tmp_ev, 0);
+            BLE_LL_ASSERT(ret == pdPASS);
+
+            if (tmp_ev == ev) {
+                continue;
+            }
+
+            ret = xQueueSendToBack(eventq->q, &tmp_ev, 0);
+            BLE_LL_ASSERT(ret == pdPASS);
+        }
+
+        portEXIT_CRITICAL(&ble_npl_mut);
+    }
+
+    event->queued = 0;
+}
+
+ble_npl_error_t
+IRAM_ATTR npl_freertos_mutex_init(struct ble_npl_mutex *mu)
+{
+    struct ble_npl_mutex_freertos *mutex = NULL;
+#if OS_MEM_ALLOC
+    if (!os_memblock_from(&ble_freertos_mutex_pool,mu->mutex)) {
+        mu->mutex = os_memblock_get(&ble_freertos_mutex_pool);
+        mutex = (struct ble_npl_mutex_freertos *)mu->mutex;
+
+        if (!mutex) {
+            return BLE_NPL_INVALID_PARAM;
+        }
+
+        memset(mutex, 0, sizeof(*mutex));
+        mutex->handle = xSemaphoreCreateRecursiveMutex();
+        BLE_LL_ASSERT(mutex->handle);
+    }
+#else
+    if(!mu->mutex) {
+        mu->mutex = malloc(sizeof(struct ble_npl_mutex_freertos));
+        mutex = (struct ble_npl_mutex_freertos *)mu->mutex;
+
+        if (!mutex) {
+            return BLE_NPL_INVALID_PARAM;
+        }
+
+        memset(mutex, 0, sizeof(*mutex));
+        mutex->handle = xSemaphoreCreateRecursiveMutex();
+        BLE_LL_ASSERT(mutex->handle);
+    }
+#endif
+
+    return BLE_NPL_OK;
+}
+
+ble_npl_error_t
+IRAM_ATTR npl_freertos_mutex_deinit(struct ble_npl_mutex *mu)
+{
+    struct ble_npl_mutex_freertos *mutex = (struct ble_npl_mutex_freertos *)mu->mutex;
+
+    if (!mutex) {
+        return BLE_NPL_INVALID_PARAM;
+    }
+
+    BLE_LL_ASSERT(mutex->handle);
+    vSemaphoreDelete(mutex->handle);
+
+#if OS_MEM_ALLOC
+    os_memblock_put(&ble_freertos_mutex_pool,mutex);
+#else
+    free((void *)mutex);
+#endif
+    mu->mutex = NULL;
+
+    return BLE_NPL_OK;
+}
+
+void
+IRAM_ATTR npl_freertos_event_run(struct ble_npl_event *ev)
+{
+    struct ble_npl_event_freertos *event = (struct ble_npl_event_freertos *)ev->event;
+    event->fn(ev);
+}
+
+bool
+IRAM_ATTR npl_freertos_eventq_is_empty(struct ble_npl_eventq *evq)
+{
+    struct ble_npl_eventq_freertos *eventq = (struct ble_npl_eventq_freertos *)evq->eventq;
+    return xQueueIsQueueEmptyFromISR(eventq->q);
+}
+
+bool
+IRAM_ATTR npl_freertos_event_is_queued(struct ble_npl_event *ev)
+{
+    struct ble_npl_event_freertos *event = (struct ble_npl_event_freertos *)ev->event;
+    return event->queued;
+}
+
+void *
+IRAM_ATTR npl_freertos_event_get_arg(struct ble_npl_event *ev)
+{
+    struct ble_npl_event_freertos *event = (struct ble_npl_event_freertos *)ev->event;
+    return event->arg;
+}
+
+void
+IRAM_ATTR npl_freertos_event_set_arg(struct ble_npl_event *ev, void *arg)
+{
+    struct ble_npl_event_freertos *event = (struct ble_npl_event_freertos *)ev->event;
+    event->arg = arg;
+}
+
+
+ble_npl_error_t
+IRAM_ATTR npl_freertos_mutex_pend(struct ble_npl_mutex *mu, ble_npl_time_t timeout)
+{
+    BaseType_t ret;
+    struct ble_npl_mutex_freertos *mutex = (struct ble_npl_mutex_freertos *)mu->mutex;
+
+    if (!mutex) {
+        return BLE_NPL_INVALID_PARAM;
+    }
+
+    BLE_LL_ASSERT(mutex->handle);
+
+    if (in_isr()) {
+        ret = pdFAIL;
+        BLE_LL_ASSERT(0);
+    } else {
+        ret = xSemaphoreTakeRecursive(mutex->handle, timeout);
+    }
+
+    return ret == pdPASS ? BLE_NPL_OK : BLE_NPL_TIMEOUT;
+}
+
+ble_npl_error_t
+IRAM_ATTR npl_freertos_mutex_release(struct ble_npl_mutex *mu)
+{
+    struct ble_npl_mutex_freertos *mutex = (struct ble_npl_mutex_freertos *)mu->mutex;
+
+    if (!mutex) {
+        return BLE_NPL_INVALID_PARAM;
+    }
+
+    BLE_LL_ASSERT(mutex->handle);
+
+    if (in_isr()) {
+        BLE_LL_ASSERT(0);
+    } else {
+        if (xSemaphoreGiveRecursive(mutex->handle) != pdPASS) {
+            return BLE_NPL_BAD_MUTEX;
+        }
+    }
+
+    return BLE_NPL_OK;
+}
+
+ble_npl_error_t
+IRAM_ATTR npl_freertos_sem_init(struct ble_npl_sem *sem, uint16_t tokens)
+{
+    struct ble_npl_sem_freertos *semaphor = NULL;
+#if OS_MEM_ALLOC
+    if (!os_memblock_from(&ble_freertos_sem_pool,sem->sem)) {
+        sem->sem = os_memblock_get(&ble_freertos_sem_pool);
+        semaphor = (struct ble_npl_sem_freertos *)sem->sem;
+
+        if (!semaphor) {
+            return BLE_NPL_INVALID_PARAM;
+        }
+
+        memset(semaphor, 0, sizeof(*semaphor));
+        semaphor->handle = xSemaphoreCreateCounting(128, tokens);
+        BLE_LL_ASSERT(semaphor->handle);
+    }
+#else
+    if(!sem->sem) {
+        sem->sem = malloc(sizeof(struct ble_npl_sem_freertos));
+        semaphor = (struct ble_npl_sem_freertos *)sem->sem;
+
+        if (!semaphor) {
+            return BLE_NPL_INVALID_PARAM;
+        }
+
+        memset(semaphor, 0, sizeof(*semaphor));
+        semaphor->handle = xSemaphoreCreateCounting(128, tokens);
+        BLE_LL_ASSERT(semaphor->handle);
+    }
+#endif
+
+    return BLE_NPL_OK;
+}
+
+ble_npl_error_t
+IRAM_ATTR npl_freertos_sem_deinit(struct ble_npl_sem *sem)
+{
+    struct ble_npl_sem_freertos *semaphor = (struct ble_npl_sem_freertos *)sem->sem;
+
+    if (!semaphor) {
+        return BLE_NPL_INVALID_PARAM;
+    }
+
+    BLE_LL_ASSERT(semaphor->handle);
+    vSemaphoreDelete(semaphor->handle);
+
+#if OS_MEM_ALLOC
+    os_memblock_put(&ble_freertos_sem_pool,semaphor);
+#else
+    free((void *)semaphor);
+#endif
+    sem->sem = NULL;
+
+    return BLE_NPL_OK;
+}
+
+ble_npl_error_t
+IRAM_ATTR npl_freertos_sem_pend(struct ble_npl_sem *sem, ble_npl_time_t timeout)
+{
+    BaseType_t woken;
+    BaseType_t ret;
+    struct ble_npl_sem_freertos *semaphor = (struct ble_npl_sem_freertos *)sem->sem;
+
+    if (!semaphor) {
+        return BLE_NPL_INVALID_PARAM;
+    }
+
+    BLE_LL_ASSERT(semaphor->handle);
+
+    if (in_isr()) {
+        BLE_LL_ASSERT(timeout == 0);
+        ret = xSemaphoreTakeFromISR(semaphor->handle, &woken);
+        if( woken == pdTRUE ) {
+            portYIELD_FROM_ISR();
+        }
+    } else {
+        ret = xSemaphoreTake(semaphor->handle, timeout);
+    }
+
+    return ret == pdPASS ? BLE_NPL_OK : BLE_NPL_TIMEOUT;
+}
+
+ble_npl_error_t
+IRAM_ATTR npl_freertos_sem_release(struct ble_npl_sem *sem)
+{
+    BaseType_t ret;
+    BaseType_t woken;
+    struct ble_npl_sem_freertos *semaphor = (struct ble_npl_sem_freertos *)sem->sem;
+
+    if (!semaphor) {
+        return BLE_NPL_INVALID_PARAM;
+    }
+
+    BLE_LL_ASSERT(semaphor->handle);
+
+    if (in_isr()) {
+        ret = xSemaphoreGiveFromISR(semaphor->handle, &woken);
+        if( woken == pdTRUE ) {
+            portYIELD_FROM_ISR();
+        }
+    } else {
+        ret = xSemaphoreGive(semaphor->handle);
+    }
+
+    BLE_LL_ASSERT(ret == pdPASS);
+    return BLE_NPL_OK;
+}
+
+#if CONFIG_BT_NIMBLE_USE_ESP_TIMER
+static void
+IRAM_ATTR ble_npl_event_fn_wrapper(void *arg)
+{
+    struct ble_npl_callout_freertos *callout = (struct ble_npl_callout_freertos *)arg;
+    BLE_LL_ASSERT(callout);
+
+    if (callout->evq) {
+        ble_npl_eventq_put(callout->evq, &callout->ev);
+    } else {
+        struct ble_npl_event_freertos *event = (struct ble_npl_event_freertos *)callout->ev.event;
+        event->fn(&callout->ev);
+    }
+}
+
+static
+IRAM_ATTR ble_npl_error_t esp_err_to_npl_error(esp_err_t err)
+{
+    switch(err) {
+    case ESP_ERR_INVALID_ARG:
+        return BLE_NPL_INVALID_PARAM;
+
+    case ESP_ERR_INVALID_STATE:
+        return BLE_NPL_EINVAL;
+
+    case ESP_OK:
+        return BLE_NPL_OK;
+
+   default:
+        return BLE_NPL_ERROR;
+    }
+}
+#else
+
+static void
+IRAM_ATTR os_callout_timer_cb(TimerHandle_t timer)
+{
+    struct ble_npl_callout_freertos *callout;
+
+    callout = pvTimerGetTimerID(timer);
+    BLE_LL_ASSERT(callout);
+
+    if (callout->evq) {
+        ble_npl_eventq_put(callout->evq, &callout->ev);
+    } else {
+        struct ble_npl_event_freertos *event = (struct ble_npl_event_freertos *)callout->ev.event;
+        event->fn(&callout->ev);
+    }
+}
+#endif
+
+void
+IRAM_ATTR npl_freertos_callout_init(struct ble_npl_callout *co, struct ble_npl_eventq *evq,
+                      ble_npl_event_fn *ev_cb, void *ev_arg)
+{
+    struct ble_npl_callout_freertos *callout = NULL;
+
+#if OS_MEM_ALLOC
+    if (!os_memblock_from(&ble_freertos_co_pool, co->co)) {
+        co->co = os_memblock_get(&ble_freertos_co_pool);
+        callout = (struct ble_npl_callout_freertos *)co->co;
+        BLE_LL_ASSERT(callout);
+
+        memset(callout, 0, sizeof(*callout));
+        ble_npl_event_init(&callout->ev, ev_cb, ev_arg);
+
+#if CONFIG_BT_NIMBLE_USE_ESP_TIMER
+	callout->evq = evq;
+
+	esp_timer_create_args_t create_args = {
+		.callback = ble_npl_event_fn_wrapper,
+		.arg = callout,
+		.name = "nimble_timer"
+	};
+
+	ESP_ERROR_CHECK(esp_timer_create(&create_args, &callout->handle));
+
+#else
+	callout->handle = xTimerCreate("co", 1, pdFALSE, callout, os_callout_timer_cb);
+#endif
+
+	BLE_LL_ASSERT(callout->handle);
+    } else {
+	callout = (struct ble_npl_callout_freertos *)co->co;
+	BLE_LL_ASSERT(callout);
+	callout->evq = evq;
+	ble_npl_event_init(&callout->ev, ev_cb, ev_arg);
+    }
+#else
+
+    if(!co->co) {
+        co->co = malloc(sizeof(struct ble_npl_callout_freertos));
+        callout = (struct ble_npl_callout_freertos *)co->co;
+        BLE_LL_ASSERT(callout);
+
+	memset(callout, 0, sizeof(*callout));
+        ble_npl_event_init(&callout->ev, ev_cb, ev_arg);
+
+#if CONFIG_BT_NIMBLE_USE_ESP_TIMER
+	callout->evq = evq;
+
+	esp_timer_create_args_t create_args = {
+		.callback = ble_npl_event_fn_wrapper,
+		.arg = callout,
+		.name = "nimble_timer"
+	};
+
+	ESP_ERROR_CHECK(esp_timer_create(&create_args, &callout->handle));
+#else
+	callout->handle = xTimerCreate("co", 1, pdFALSE, callout, os_callout_timer_cb);
+#endif
+
+	BLE_LL_ASSERT(callout->handle);
+    }
+    else {
+        callout = (struct ble_npl_callout_freertos *)co->co;
+        BLE_LL_ASSERT(callout);
+	callout->evq = evq;
+	ble_npl_event_init(&callout->ev, ev_cb, ev_arg);
+    }
+#endif
+
+}
+
+void
+IRAM_ATTR npl_freertos_callout_deinit(struct ble_npl_callout *co)
+{
+    struct ble_npl_callout_freertos *callout = (struct ble_npl_callout_freertos *)co->co;
+
+    /* Since we dynamically deinit timers, function can be called for NULL timers. Return for such scenarios */
+    if (!callout) {
+	return;
+    }
+
+    BLE_LL_ASSERT(callout->handle);
+
+#if CONFIG_BT_NIMBLE_USE_ESP_TIMER
+    if(esp_timer_stop(callout->handle))
+        ESP_LOGW(TAG, "Timer not stopped");
+
+    if(esp_timer_delete(callout->handle))
+        ESP_LOGW(TAG, "Timer not deleted");
+
+#else
+
+    xTimerDelete(callout->handle, portMAX_DELAY);
+    ble_npl_event_deinit(&callout->ev);
+
+#if OS_MEM_ALLOC
+    os_memblock_put(&ble_freertos_co_pool,callout);
+#else
+    free((void *)callout);
+#endif
+
+#endif
+    co->co = NULL;
+    memset(co, 0, sizeof(struct ble_npl_callout));
+}
+
+uint16_t
+IRAM_ATTR npl_freertos_sem_get_count(struct ble_npl_sem *sem)
+{
+    struct ble_npl_sem_freertos *semaphor = (struct ble_npl_sem_freertos *)sem->sem;
+    return uxSemaphoreGetCount(semaphor->handle);
+}
+
+
+ble_npl_error_t
+IRAM_ATTR npl_freertos_callout_reset(struct ble_npl_callout *co, ble_npl_time_t ticks)
+{
+    struct ble_npl_callout_freertos *callout = (struct ble_npl_callout_freertos *)co->co;
+#if CONFIG_BT_NIMBLE_USE_ESP_TIMER
+    esp_timer_stop(callout->handle);
+
+    return esp_err_to_npl_error(esp_timer_start_once(callout->handle, ticks*1000));
+#else
+
+    BaseType_t woken1, woken2, woken3;
+
+    if (ticks == 0) {
+        ticks = 1;
+    }
+    if (in_isr()) {
+        xTimerStopFromISR(callout->handle, &woken1);
+        xTimerChangePeriodFromISR(callout->handle, ticks, &woken2);
+        xTimerResetFromISR(callout->handle, &woken3);
+
+        if( woken1 == pdTRUE || woken2 == pdTRUE || woken3 == pdTRUE) {
+            portYIELD_FROM_ISR();
+        }
+    } else {
+        xTimerStop(callout->handle, portMAX_DELAY);
+        xTimerChangePeriod(callout->handle, ticks, portMAX_DELAY);
+        xTimerReset(callout->handle, portMAX_DELAY);
+    }
+
+    return BLE_NPL_OK;
+#endif
+}
+
+void
+IRAM_ATTR npl_freertos_callout_stop(struct ble_npl_callout *co)
+{
+    struct ble_npl_callout_freertos *callout = (struct ble_npl_callout_freertos *)co->co;
+
+    if (!callout) {
+	return;
+    }
+
+#if CONFIG_BT_NIMBLE_USE_ESP_TIMER
+    esp_timer_stop(callout->handle);
+#else
+    xTimerStop(callout->handle, portMAX_DELAY);
+#endif
+}
+
+bool
+IRAM_ATTR npl_freertos_callout_is_active(struct ble_npl_callout *co)
+{
+    struct ble_npl_callout_freertos *callout = (struct ble_npl_callout_freertos *)co->co;
+#if CONFIG_BT_NIMBLE_USE_ESP_TIMER
+    return esp_timer_is_active(callout->handle);
+#else
+    return xTimerIsTimerActive(callout->handle) == pdTRUE;
+#endif
+}
+
+ble_npl_time_t
+IRAM_ATTR npl_freertos_callout_get_ticks(struct ble_npl_callout *co)
+{
+#if CONFIG_BT_NIMBLE_USE_ESP_TIMER
+   /* Currently, esp_timer does not support an API which gets the expiry time for
+    * current timer.
+    * Returning 0 from here should not cause any effect.
+    * Drawback of this approach is that existing code to reset timer would be called
+    * more often (since the if condition to invoke reset timer would always succeed if
+    * timer is active).
+    */
+
+    return 0;
+#else
+    struct ble_npl_callout_freertos *callout = (struct ble_npl_callout_freertos *)co->co;
+    return xTimerGetExpiryTime(callout->handle);
+#endif
+}
+
+ble_npl_time_t
+IRAM_ATTR npl_freertos_callout_remaining_ticks(struct ble_npl_callout *co,
+                                     ble_npl_time_t now)
+{
+    ble_npl_time_t rt;
+    uint32_t exp = 0;
+
+    struct ble_npl_callout_freertos *callout = (struct ble_npl_callout_freertos *)co->co;
+
+#if CONFIG_BT_NIMBLE_USE_ESP_TIMER
+#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0)
+    uint64_t expiry = 0;
+    esp_err_t err;
+
+    //Fetch expiry time in microseconds
+    err = esp_timer_get_expiry_time((esp_timer_handle_t)(callout->handle), &expiry);
+    if (err != ESP_OK) {
+        //Error. Could not fetch the expiry time
+        return 0;
+    }
+
+    //Convert microseconds to ticks
+    npl_freertos_time_ms_to_ticks((uint32_t)(expiry / 1000), &exp);
+#else
+    //esp_timer_get_expiry_time() is only available from IDF 5.0 onwards
+    //Set expiry to 0
+    exp = 0;
+#endif //ESP_IDF_VERSION
+#else
+    exp = xTimerGetExpiryTime(callout->handle);
+#endif
+
+    if (exp > now) {
+        rt = exp - now;
+    } else {
+        rt = 0;
+    }
+
+    return rt;
+}
+
+void
+IRAM_ATTR npl_freertos_callout_set_arg(struct ble_npl_callout *co, void *arg)
+{
+    struct ble_npl_callout_freertos *callout = (struct ble_npl_callout_freertos *)co->co;
+    struct ble_npl_event_freertos *event = (struct ble_npl_event_freertos *)callout->ev.event;
+    event->arg = arg;
+}
+
+uint32_t
+IRAM_ATTR npl_freertos_time_get(void)
+{
+#if CONFIG_BT_NIMBLE_USE_ESP_TIMER
+    return esp_timer_get_time() / 1000;
+#else
+    return xTaskGetTickCountFromISR();
+#endif
+}
+
+ble_npl_error_t
+IRAM_ATTR npl_freertos_time_ms_to_ticks(uint32_t ms, ble_npl_time_t *out_ticks)
+{
+    uint64_t ticks;
+#if CONFIG_BT_NIMBLE_USE_ESP_TIMER
+    ticks = (uint64_t)ms;
+#else
+    ticks = ((uint64_t)ms * configTICK_RATE_HZ) / 1000;
+#endif
+    if (ticks > UINT32_MAX) {
+        return BLE_NPL_EINVAL;
+    }
+
+    *out_ticks = ticks;
+
+    return 0;
+}
+
+ble_npl_error_t
+IRAM_ATTR npl_freertos_time_ticks_to_ms(ble_npl_time_t ticks, uint32_t *out_ms)
+{
+    uint64_t ms;
+#if CONFIG_BT_NIMBLE_USE_ESP_TIMER
+    ms = ((uint64_t)ticks);
+#else
+    ms = ((uint64_t)ticks * 1000) / configTICK_RATE_HZ;
+#endif
+    if (ms > UINT32_MAX) {
+        return BLE_NPL_EINVAL;
+     }
+
+    *out_ms = ms;
+
+    return 0;
+}
+
+ble_npl_time_t
+IRAM_ATTR npl_freertos_time_ms_to_ticks32(uint32_t ms)
+{
+#if CONFIG_BT_NIMBLE_USE_ESP_TIMER
+    return ms;
+#else
+    return ms * configTICK_RATE_HZ / 1000;
+#endif
+}
+
+uint32_t
+IRAM_ATTR npl_freertos_time_ticks_to_ms32(ble_npl_time_t ticks)
+{
+#if CONFIG_BT_NIMBLE_USE_ESP_TIMER
+    return ticks;
+#else
+    return ticks * 1000 / configTICK_RATE_HZ;
+#endif
+}
+
+void
+IRAM_ATTR npl_freertos_time_delay(ble_npl_time_t ticks)
+{
+#if CONFIG_BT_NIMBLE_USE_ESP_TIMER
+    vTaskDelay(ticks / portTICK_PERIOD_MS);
+#else
+    vTaskDelay(ticks);
+#endif
+}
+
+
+uint8_t hw_critical_state_status = 0;
+
+uint32_t
+IRAM_ATTR npl_freertos_hw_enter_critical(void)
+{
+    ++hw_critical_state_status;
+    portENTER_CRITICAL(&ble_port_mutex);
+    return 0;
+}
+
+uint8_t
+IRAM_ATTR npl_freertos_hw_is_in_critical(void)
+{
+    return hw_critical_state_status;
+}
+
+void
+IRAM_ATTR npl_freertos_hw_exit_critical(uint32_t ctx)
+{
+    --hw_critical_state_status;
+    portEXIT_CRITICAL(&ble_port_mutex);
+
+}
+
+uint32_t
+IRAM_ATTR npl_freertos_get_time_forever(void)
+{
+    return portMAX_DELAY;
+}
+
+const struct npl_funcs_t npl_funcs_ro = {
+    .p_ble_npl_os_started = npl_freertos_os_started,
+    .p_ble_npl_get_current_task_id = npl_freertos_get_current_task_id,
+    .p_ble_npl_eventq_init = npl_freertos_eventq_init,
+    .p_ble_npl_eventq_deinit = npl_freertos_eventq_deinit,
+    .p_ble_npl_eventq_get = npl_freertos_eventq_get,
+    .p_ble_npl_eventq_put = npl_freertos_eventq_put,
+    .p_ble_npl_eventq_remove = npl_freertos_eventq_remove,
+    .p_ble_npl_event_run = npl_freertos_event_run,
+    .p_ble_npl_eventq_is_empty = npl_freertos_eventq_is_empty,
+    .p_ble_npl_event_init = npl_freertos_event_init,
+    .p_ble_npl_event_deinit = npl_freertos_event_deinit,
+    .p_ble_npl_event_reset = npl_freertos_event_reset,
+    .p_ble_npl_event_is_queued = npl_freertos_event_is_queued,
+    .p_ble_npl_event_get_arg = npl_freertos_event_get_arg,
+    .p_ble_npl_event_set_arg = npl_freertos_event_set_arg,
+    .p_ble_npl_mutex_init = npl_freertos_mutex_init,
+    .p_ble_npl_mutex_deinit = npl_freertos_mutex_deinit,
+    .p_ble_npl_mutex_pend = npl_freertos_mutex_pend,
+    .p_ble_npl_mutex_release = npl_freertos_mutex_release,
+    .p_ble_npl_sem_init = npl_freertos_sem_init,
+    .p_ble_npl_sem_deinit = npl_freertos_sem_deinit,
+    .p_ble_npl_sem_pend = npl_freertos_sem_pend,
+    .p_ble_npl_sem_release = npl_freertos_sem_release,
+    .p_ble_npl_sem_get_count = npl_freertos_sem_get_count,
+    .p_ble_npl_callout_init = npl_freertos_callout_init,
+    .p_ble_npl_callout_reset = npl_freertos_callout_reset,
+    .p_ble_npl_callout_stop = npl_freertos_callout_stop,
+    .p_ble_npl_callout_deinit = npl_freertos_callout_deinit,
+    .p_ble_npl_callout_mem_reset = npl_freertos_callout_mem_reset,
+    .p_ble_npl_callout_is_active = npl_freertos_callout_is_active,
+    .p_ble_npl_callout_get_ticks = npl_freertos_callout_get_ticks,
+    .p_ble_npl_callout_remaining_ticks = npl_freertos_callout_remaining_ticks,
+    .p_ble_npl_callout_set_arg = npl_freertos_callout_set_arg,
+    .p_ble_npl_time_get = npl_freertos_time_get,
+    .p_ble_npl_time_ms_to_ticks = npl_freertos_time_ms_to_ticks,
+    .p_ble_npl_time_ticks_to_ms = npl_freertos_time_ticks_to_ms,
+    .p_ble_npl_time_ms_to_ticks32 = npl_freertos_time_ms_to_ticks32,
+    .p_ble_npl_time_ticks_to_ms32 = npl_freertos_time_ticks_to_ms32,
+    .p_ble_npl_time_delay = npl_freertos_time_delay,
+#if NIMBLE_CFG_CONTROLLER || CONFIG_NIMBLE_CONTROLLER_MODE
+    .p_ble_npl_hw_set_isr = NULL,
+#endif
+    .p_ble_npl_hw_enter_critical = npl_freertos_hw_enter_critical,
+    .p_ble_npl_hw_exit_critical = npl_freertos_hw_exit_critical,
+    .p_ble_npl_get_time_forever = npl_freertos_get_time_forever,
+    .p_ble_npl_hw_is_in_critical = npl_freertos_hw_is_in_critical
+};
+
+struct npl_funcs_t *npl_funcs = NULL;
+
+struct npl_funcs_t * npl_freertos_funcs_get(void)
+{
+    return npl_funcs;
+}
+
+void npl_freertos_funcs_init(void)
+{
+    npl_funcs = (struct npl_funcs_t *)malloc(sizeof(struct npl_funcs_t));
+    if(!npl_funcs) {
+        printf("npl funcs init failed\n");
+        assert(0);
+    }
+    memcpy(npl_funcs, &npl_funcs_ro, sizeof(struct npl_funcs_t));
+}
+
+int npl_freertos_mempool_init(void)
+{
+    int rc = -1;
+
+#if SOC_ESP_NIMBLE_CONTROLLER
+    ble_freertos_ev_buf  = malloc(OS_MEMPOOL_SIZE(BLE_TOTAL_EV_COUNT, sizeof (struct ble_npl_event_freertos)) * sizeof(os_membuf_t));
+    if(!ble_freertos_ev_buf) {
+        goto _error;
+    }
+    ble_freertos_evq_buf  = malloc(OS_MEMPOOL_SIZE(BLE_TOTAL_EVQ_COUNT, sizeof (struct ble_npl_eventq_freertos)) * sizeof(os_membuf_t));
+    if(!ble_freertos_evq_buf) {
+        goto _error;
+    }
+    ble_freertos_co_buf  = malloc(OS_MEMPOOL_SIZE(BLE_TOTAL_CO_COUNT, sizeof (struct ble_npl_callout_freertos)) * sizeof(os_membuf_t));
+    if(!ble_freertos_co_buf) {
+        goto _error;
+    }
+    ble_freertos_sem_buf  = malloc(OS_MEMPOOL_SIZE(BLE_TOTAL_SEM_COUNT, sizeof (struct ble_npl_sem_freertos)) * sizeof(os_membuf_t));
+    if(!ble_freertos_sem_buf) {
+        goto _error;
+    }
+    ble_freertos_mutex_buf  = malloc( OS_MEMPOOL_SIZE(BLE_TOTAL_MUTEX_COUNT, sizeof (struct ble_npl_mutex_freertos)) * sizeof(os_membuf_t));
+    if(!ble_freertos_mutex_buf) {
+        goto _error;
+    }
+
+#endif
+
+    rc = os_mempool_init(&ble_freertos_ev_pool, BLE_TOTAL_EV_COUNT,
+                         sizeof (struct ble_npl_event_freertos), ble_freertos_ev_buf,
+                         "ble_freertos_ev_pool");
+    if(rc != 0) {
+        goto _error;
+    }
+
+    rc = os_mempool_init(&ble_freertos_evq_pool, BLE_TOTAL_EVQ_COUNT,
+                         sizeof (struct ble_npl_eventq_freertos), ble_freertos_evq_buf,
+                         "ble_freertos_evq_pool");
+    if(rc != 0) {
+        goto _error;
+    }
+
+    rc = os_mempool_init(&ble_freertos_co_pool, BLE_TOTAL_CO_COUNT,
+                         sizeof (struct ble_npl_callout_freertos), ble_freertos_co_buf,
+                         "ble_freertos_co_pool");
+    if(rc != 0) {
+        goto _error;
+    }
+
+    rc = os_mempool_init(&ble_freertos_sem_pool, BLE_TOTAL_SEM_COUNT,
+                         sizeof (struct ble_npl_sem_freertos), ble_freertos_sem_buf,
+                         "ble_freertos_sem_pool");
+    if(rc != 0) {
+        goto _error;
+    }
+
+    rc = os_mempool_init(&ble_freertos_mutex_pool, BLE_TOTAL_MUTEX_COUNT,
+                         sizeof (struct ble_npl_mutex_freertos), ble_freertos_mutex_buf,
+                         "ble_freertos_mutex_pool");
+    if(rc == 0) {
+        return rc;
+    }
+_error:
+
+#if SOC_ESP_NIMBLE_CONTROLLER
+    if(ble_freertos_ev_buf) {
+        free(ble_freertos_ev_buf);
+    }
+    if(ble_freertos_evq_buf) {
+        free(ble_freertos_evq_buf);
+    }
+    if(ble_freertos_co_buf) {
+        free(ble_freertos_co_buf);
+    }
+    if(ble_freertos_sem_buf) {
+        free(ble_freertos_sem_buf);
+    }
+    if(ble_freertos_mutex_buf) {
+        free(ble_freertos_mutex_buf);
+    }
+    return -1;
+#else
+
+   BLE_LL_ASSERT(rc == 0);
+   return rc;
+#endif
+}
+
+void npl_freertos_mempool_deinit(void)
+{
+#if SOC_ESP_NIMBLE_CONTROLLER
+    if(ble_freertos_ev_buf) {
+        free(ble_freertos_ev_buf);
+    }
+    if(ble_freertos_evq_buf) {
+        free(ble_freertos_evq_buf);
+    }
+    if(ble_freertos_co_buf) {
+        free(ble_freertos_co_buf);
+    }
+    if(ble_freertos_sem_buf) {
+        free(ble_freertos_sem_buf);
+    }
+    if(ble_freertos_mutex_buf) {
+        free(ble_freertos_mutex_buf);
+    }
+#endif
+}
+
+void npl_freertos_funcs_deinit(void)
+{
+    if (npl_funcs) {
+        free(npl_funcs);
+    }
+    npl_funcs = NULL;
+}

+ 90 - 0
components/bt/porting/transport/include/hci_uart.h

@@ -0,0 +1,90 @@
+/*
+ * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <inttypes.h>
+#include "driver/uart.h"
+
+/**
+ * Function prototype for UART driver to ask for more data to send.
+ * Returns -1 if no more data is available for TX.
+ * Driver must call this with interrupts disabled.
+ */
+typedef int (*hci_uart_tx_char)(void *arg);
+
+/**
+ * Function prototype for UART driver to report that transmission is
+ * complete. This should be called when transmission of last byte is
+ * finished.
+ * Driver must call this with interrupts disabled.
+ */
+typedef void (*hci_uart_tx_done)(void *arg);
+
+/**
+ * Function prototype for UART driver to report incoming byte of data.
+ * Returns -1 if data was dropped.
+ * Driver must call this with interrupts disabled.
+ */
+typedef int (*hci_uart_rx_char)(void *arg, uint8_t byte);
+
+
+/**
+ * Initializes given uart. Mapping of logical UART number to physical
+ * UART/GPIO pins is in BSP.
+ */
+int hci_uart_init_cbs(int uart, hci_uart_tx_char tx_func,
+                      hci_uart_tx_done tx_done, hci_uart_rx_char rx_func, void *arg);
+
+
+/**
+ * Applies given configuration to UART.
+ *
+ * @param port_num The UART number to configure
+ * @param speed The baudrate in bps to configure
+ * @param databits The number of databits to send per byte
+ * @param stopbits The number of stop bits to send
+ * @param parity The UART parity
+ * @param flow_ctl Flow control settings on the UART
+ *
+ * @return 0 on success, non-zero error code on failure
+ */
+int hci_uart_config(int port_num, int32_t baud_rate, uint8_t data_bits, uint8_t stop_bits,
+                    uart_parity_t parity, uart_hw_flowcontrol_t flow_ctl);
+
+/**
+ * Close UART port. Can call hal_uart_config() with different settings after
+ * calling this.
+ *
+ * @param port_num The UART number to close
+ */
+int hci_uart_close(int port_num);
+
+/**
+ * More data queued for transmission. UART driver will start asking for that
+ * data.
+ *
+ * @param port_num The UART number to start TX on
+ */
+void hci_uart_start_tx(int port_num);
+
+/**
+ * Upper layers have consumed some data, and are now ready to receive more.
+ * This is meaningful after uart_rx_char callback has returned -1 telling
+ * that no more data can be accepted.
+ *
+ * @param port_num The UART number to begin RX on
+ */
+void hci_uart_start_rx(int port_num);
+
+
+#ifdef __cplusplus
+}
+#endif

+ 190 - 0
components/bt/porting/transport/uart/hci_uart.c

@@ -0,0 +1,190 @@
+/*
+ * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include "freertos/FreeRTOS.h"
+#include "freertos/task.h"
+#include "freertos/queue.h"
+#include "driver/uart.h"
+#include "hci_uart.h"
+#include "esp_log.h"
+#include "esp_attr.h"
+
+#ifdef CONFIG_BT_LE_HCI_INTERFACE_USE_UART
+
+static const char *TAG = "hci_uart";
+
+#define BUF_SIZE (1024)
+#define RD_BUF_SIZE (BUF_SIZE)
+
+#define HCI_UART_TX_PIN CONFIG_BT_LE_HCI_UART_TX_PIN
+#define HCI_UART_RX_PIN CONFIG_BT_LE_HCI_UART_RX_PIN
+
+
+#ifdef CONFIG_BT_LE_HCI_UART_FLOWCTRL
+#define HCI_UART_FLOWCTRL UART_HW_FLOWCTRL_CTS_RTS
+#define HCI_UART_RTS_PIN CONFIG_BT_LE_HCI_UART_RTS_PIN
+#define HCI_UART_CTS_PIN CONFIG_BT_LE_HCI_UART_CTS_PIN
+#else
+#define HCI_UART_FLOWCTRL UART_HW_FLOWCTRL_DISABLE
+#define HCI_UART_RTS_PIN (-1)
+#define HCI_UART_CTS_PIN (-1)
+#endif
+
+
+typedef struct {
+    bool uart_opened;
+    uart_port_t port;
+    uart_config_t cfg;
+    QueueHandle_t evt_queue;
+    TaskHandle_t rx_task_handler;
+    hci_uart_tx_char tx_char;
+    hci_uart_tx_done tx_done;
+    hci_uart_rx_char rx_char;
+    void *u_func_arg;
+
+} hci_uart_t;
+
+static hci_uart_t hci_uart;
+
+static void IRAM_ATTR hci_uart_rx_task(void *pvParameters)
+{
+    uart_event_t event;
+    uint8_t *dtmp = (uint8_t *) malloc(RD_BUF_SIZE);
+    while (hci_uart.uart_opened) {
+        //Waiting for UART event.
+        if (xQueueReceive(hci_uart.evt_queue, (void * )&event, (TickType_t)portMAX_DELAY)) {
+            bzero(dtmp, RD_BUF_SIZE);
+            ESP_LOGD(TAG, "uart[%d] event:", hci_uart.port);
+            switch (event.type) {
+            //Event of UART receving data
+            /*We'd better handler data event fast, there would be much more data events than
+            other types of events. If we take too much time on data event, the queue might
+            be full.*/
+            case UART_DATA:
+                // ESP_LOGI(TAG, "[UART DATA]: %d", event.size);
+                uart_read_bytes(hci_uart.port, dtmp, event.size, portMAX_DELAY);
+                for (int i = 0 ; i < event.size; i++) {
+                    hci_uart.rx_char(hci_uart.u_func_arg, dtmp[i]);
+                }
+                break;
+            //Event of HW FIFO overflow detected
+            case UART_FIFO_OVF:
+                ESP_LOGI(TAG, "hw fifo overflow");
+                // If fifo overflow happened, you should consider adding flow control for your application.
+                // The ISR has already reset the rx FIFO,
+                uart_flush_input(hci_uart.port);
+                xQueueReset(hci_uart.evt_queue);
+                break;
+            //Event of UART ring buffer full
+            case UART_BUFFER_FULL:
+                ESP_LOGI(TAG, "ring buffer full");
+                // If buffer full happened, you should consider encreasing your buffer size
+                uart_flush_input(hci_uart.port);
+                xQueueReset(hci_uart.evt_queue);
+                break;
+            //Event of UART RX break detected
+            case UART_BREAK:
+                ESP_LOGI(TAG, "uart rx break");
+                break;
+            //Event of UART parity check error
+            case UART_PARITY_ERR:
+                ESP_LOGI(TAG, "uart parity error");
+                break;
+            //Event of UART frame error
+            case UART_FRAME_ERR:
+                ESP_LOGI(TAG, "uart frame error");
+                break;
+            //Others
+            default:
+                ESP_LOGI(TAG, "uart event type: %d", event.type);
+                break;
+            }
+        }
+    }
+    free(dtmp);
+    dtmp = NULL;
+    hci_uart.rx_task_handler = NULL;
+    vTaskDelete(NULL);
+}
+
+int hci_uart_config(int port_num, int32_t baud_rate, uint8_t data_bits, uint8_t stop_bits,
+                    uart_parity_t parity, uart_hw_flowcontrol_t flow_ctl)
+{
+    uart_config_t uart_cfg = {
+        .baud_rate = baud_rate,
+        .data_bits = data_bits,
+        .parity    = parity,
+        .stop_bits = stop_bits,
+        .flow_ctrl = HCI_UART_FLOWCTRL,
+        .source_clk = UART_SCLK_DEFAULT,
+    };
+    hci_uart.port = port_num;
+    hci_uart.cfg = uart_cfg;
+
+    int intr_alloc_flags = 0;
+    intr_alloc_flags = ESP_INTR_FLAG_IRAM;
+
+    printf("set uart pin tx:%d, rx:%d.\n", HCI_UART_TX_PIN, HCI_UART_RX_PIN);
+    printf("set rts:%d, cts:%d.\n", HCI_UART_RTS_PIN, HCI_UART_CTS_PIN);
+    printf("set baud_rate:%d.\n", baud_rate);
+
+    ESP_ERROR_CHECK(uart_driver_delete(port_num));
+    ESP_ERROR_CHECK(uart_driver_install(port_num, BUF_SIZE * 2, BUF_SIZE * 2, 20, &hci_uart.evt_queue, intr_alloc_flags));
+    ESP_ERROR_CHECK(uart_param_config(port_num, &hci_uart.cfg));
+    ESP_ERROR_CHECK(uart_set_pin(port_num, HCI_UART_TX_PIN, HCI_UART_RX_PIN, HCI_UART_RTS_PIN, HCI_UART_CTS_PIN));
+
+    hci_uart.uart_opened = true;
+
+    //Create a task to handler UART event from ISR
+    xTaskCreate(hci_uart_rx_task, "hci_uart_rx_task", 2048, NULL, 12, &hci_uart.rx_task_handler);
+    return 0;
+}
+
+void IRAM_ATTR hci_uart_start_tx(int port_num)
+{
+    int data;
+    uint8_t u8_data = 0;
+    while (1) {
+        data = hci_uart.tx_char(hci_uart.u_func_arg);
+        if (data >= 0) {
+            u8_data = data;
+            uart_tx_chars(port_num, (char *)&u8_data, 1);
+        } else {
+            break;
+        }
+    }
+    if (hci_uart.tx_done) {
+        hci_uart.tx_done(hci_uart.u_func_arg);
+    }
+}
+
+int hci_uart_init_cbs(int port_num, hci_uart_tx_char tx_func,
+                      hci_uart_tx_done tx_done, hci_uart_rx_char rx_func, void *arg)
+{
+    hci_uart.tx_char = tx_func;
+    hci_uart.rx_char = rx_func;
+    hci_uart.tx_done = tx_done;
+    hci_uart.u_func_arg = arg;
+    return 0;
+}
+
+int hci_uart_close(int port_num)
+{
+    hci_uart.uart_opened = false;
+    // Stop uart rx task
+    if (hci_uart.rx_task_handler != NULL) {
+        ESP_LOGW(TAG, "Waiting for uart task finish...");
+    }
+    while (hci_uart.rx_task_handler != NULL);
+
+    uart_driver_delete(port_num);
+    ESP_LOGI(TAG, "hci uart close success.");
+    return 0;
+}
+
+#endif //CONFIG_BT_LE_HCI_INTERFACE_USE_UART

+ 0 - 3
components/esp_rom/esp32c2/ld/esp32c2.rom.ld

@@ -764,7 +764,6 @@ r_ble_ll_conn_hci_set_data_len = 0x40000ddc;
 r_ble_ll_conn_hci_update = 0x40000de0;
 r_ble_ll_conn_hci_wr_auth_pyld_tmo = 0x40000de4;
 r_ble_ll_conn_init_phy = 0x40000de8;
-r_ble_ll_conn_is_dev_connected = 0x40000dec;
 r_ble_ll_conn_is_empty_pdu = 0x40000df0;
 r_ble_ll_conn_is_lru = 0x40000df4;
 r_ble_ll_conn_master_init = 0x40000df8;
@@ -1215,7 +1214,6 @@ r_ble_lll_conn_coex_dpc_update_on_event_started = 0x400014e8;
 r_ble_lll_conn_cth_flow_alloc_credit = 0x400014ec;
 r_ble_lll_conn_cth_flow_free_credit = 0x400014f0;
 r_ble_lll_conn_current_sm_over = 0x400014f4;
-r_ble_lll_conn_end = 0x400014f8;
 r_ble_lll_conn_env_deinit = 0x400014fc;
 r_ble_lll_conn_env_init = 0x40001500;
 r_ble_lll_conn_event_end = 0x40001504;
@@ -1361,7 +1359,6 @@ r_ble_lll_sched_conn_reschedule = 0x40001730;
 r_ble_lll_sched_deinit = 0x40001734;
 r_ble_lll_sched_dtm = 0x40001738;
 r_ble_lll_sched_env_init = 0x4000173c;
-r_ble_lll_sched_execute_check = 0x40001740;
 r_ble_lll_sched_execute_item = 0x40001744;
 r_ble_lll_sched_init = 0x40001748;
 r_ble_lll_sched_insert_if_empty = 0x4000174c;

+ 9 - 0
examples/bluetooth/bluedroid/ble/gatt_server/sdkconfig.defaults.esp32c2

@@ -0,0 +1,9 @@
+# This file was generated using idf.py save-defconfig. It can be edited manually.
+# Espressif IoT Development Framework (ESP-IDF) Project Minimal Configuration
+#
+CONFIG_IDF_TARGET="esp32c2"
+CONFIG_BT_ENABLED=y
+# CONFIG_BT_BLE_50_FEATURES_SUPPORTED is not set
+CONFIG_BT_BLE_42_FEATURES_SUPPORTED=y
+# CONFIG_BT_LE_50_FEATURE_SUPPORT is not set
+CONFIG_BT_LE_HCI_EVT_BUF_SIZE=257

+ 8 - 0
examples/bluetooth/nimble/blecent/sdkconfig.defaults.esp32c2

@@ -0,0 +1,8 @@
+# This file was generated using idf.py save-defconfig. It can be edited manually.
+# Espressif IoT Development Framework (ESP-IDF) Project Minimal Configuration
+#
+CONFIG_IDF_TARGET="esp32c2"
+# CONFIG_EXAMPLE_EXTENDED_ADV is not set
+CONFIG_BT_ENABLED=y
+CONFIG_BT_NIMBLE_ENABLED=y
+# CONFIG_BT_NIMBLE_50_FEATURE_SUPPORT is not set

+ 7 - 0
examples/bluetooth/nimble/blehr/sdkconfig.defaults.esp32c2

@@ -0,0 +1,7 @@
+# This file was generated using idf.py save-defconfig. It can be edited manually.
+# Espressif IoT Development Framework (ESP-IDF) Project Minimal Configuration
+#
+CONFIG_IDF_TARGET="esp32c2"
+CONFIG_BT_ENABLED=y
+CONFIG_BT_NIMBLE_ENABLED=y
+# CONFIG_BT_NIMBLE_50_FEATURE_SUPPORT is not set

+ 6 - 6
examples/bluetooth/nimble/bleprph/main/main.c

@@ -31,10 +31,10 @@
 
 #if CONFIG_EXAMPLE_EXTENDED_ADV
 static uint8_t ext_adv_pattern_1[] = {
-        0x02, 0x01, 0x06,
-	0x03, 0x03, 0xab, 0xcd,
-	0x03, 0x03, 0x18, 0x11,
-	0x11, 0X09, 'e', 's', 'p', '3', '2', 'h', '2', '-', 'B', 'L', 'E', '5', '0', '-', 'S', '\0',
+    0x02, 0x01, 0x06,
+    0x03, 0x03, 0xab, 0xcd,
+    0x03, 0x03, 0x18, 0x11,
+    0x11, 0X09, 'n', 'i', 'm', 'b', 'l', 'e', '-', 'b', 'l', 'e', 'p', 'r', 'p', 'h', '-', 'e',
 };
 #endif
 
@@ -231,7 +231,7 @@ bleprph_gap_event(struct ble_gap_event *event, void *arg)
         if (event->connect.status != 0) {
             /* Connection failed; resume advertising. */
 #if CONFIG_EXAMPLE_EXTENDED_ADV
-	    ext_bleprph_advertise();
+            ext_bleprph_advertise();
 #else
             bleprph_advertise();
 #endif
@@ -245,7 +245,7 @@ bleprph_gap_event(struct ble_gap_event *event, void *arg)
 
         /* Connection terminated; resume advertising. */
 #if CONFIG_EXAMPLE_EXTENDED_ADV
-	ext_bleprph_advertise();
+        ext_bleprph_advertise();
 #else
         bleprph_advertise();
 #endif

+ 8 - 0
examples/bluetooth/nimble/bleprph/sdkconfig.defaults.esp32c2

@@ -0,0 +1,8 @@
+# This file was generated using idf.py save-defconfig. It can be edited manually.
+# Espressif IoT Development Framework (ESP-IDF) Project Minimal Configuration
+#
+CONFIG_IDF_TARGET="esp32c2"
+CONFIG_BT_ENABLED=y
+CONFIG_BT_NIMBLE_ENABLED=y
+CONFIG_BT_NIMBLE_HCI_EVT_BUF_SIZE=70
+CONFIG_BT_NIMBLE_EXT_ADV=y

+ 4 - 10
examples/bluetooth/nimble/bleprph/sdkconfig.defaults.esp32h2

@@ -1,14 +1,8 @@
+# This file was generated using idf.py save-defconfig. It can be edited manually.
+# Espressif IoT Development Framework (ESP-IDF) Project Minimal Configuration
+#
 CONFIG_IDF_TARGET="esp32h2"
-CONFIG_BT_NIMBLE_50_FEATURE_SUPPORT=y
-CONFIG_ESPTOOLPY_FLASHMODE_QIO=y
-CONFIG_ESPTOOLPY_FLASHFREQ_40M=y
-CONFIG_ESPTOOLPY_FLASHFREQ="40m"
-CONFIG_RTC_CLK_SRC_EXT_CRYS=y
-CONFIG_RTC_CLK_CAL_CYCLES=576
 CONFIG_BT_ENABLED=y
-CONFIG_BTDM_CTRL_MODE_BLE_ONLY=y
-CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY=n
-CONFIG_BTDM_CTRL_MODE_BTDM=n
-CONFIG_BT_BLUEDROID_ENABLED=n
 CONFIG_BT_NIMBLE_ENABLED=y
+CONFIG_BT_NIMBLE_HCI_EVT_BUF_SIZE=70
 CONFIG_BT_NIMBLE_EXT_ADV=y

+ 6 - 0
examples/bluetooth/nimble/hci/CMakeLists.txt

@@ -0,0 +1,6 @@
+# The following lines of boilerplate have to be in your project's
+# CMakeLists in this exact order for cmake to work correctly
+cmake_minimum_required(VERSION 3.5)
+
+include($ENV{IDF_PATH}/tools/cmake/project.cmake)
+project(hci)

+ 63 - 0
examples/bluetooth/nimble/hci/README.md

@@ -0,0 +1,63 @@
+| Supported Targets | ESP32-C2 |
+| ----------------- | -------- |
+
+
+ESP-IDF UART HCI Controller
+===========================
+
+This is a BLE controller use UART as HCI interface. 
+
+It can do the configuration of UART number and UART baudrate by menuconfig.
+
+## BLE HCI example
+
+(See the README.md file in the upper level 'examples' directory for more information about examples.)
+
+This example start controller with uart hci.
+
+It uses ESP32C2's Bluetooth controller.
+
+In this example, two UARTs are used:
+
+- UART0 is used as normal output or by IDF monitor
+
+- UART1 is used to convey HCI messages
+
+Pins 8, 9 are used as TxD, RxD PINs of UART1.
+
+
+## How to use example
+
+### Configure the project
+
+```
+idf.py menuconfig
+```
+
+
+### Build and Flash
+
+Build the project and flash it to the board, then run monitor tool to view serial output:
+
+```
+idf.py -p PORT flash monitor
+```
+
+(To exit the serial monitor, type ``Ctrl-]``.)
+
+See the Getting Started Guide for full steps to configure and use ESP-IDF to build projects.
+
+## Example Output
+
+There is this console output when bleprph is connected and characteristic is read:
+
+```
+set nimble port tx:8, rx:9.
+set baud:115200.
+controller lib commit: [fb738d4]
+controller rom commit: [3314f9d]
+I (346) system_api: Base MAC address is not set
+I (356) system_api: read default base MAC address from EFUSE
+
+```
+

+ 4 - 0
examples/bluetooth/nimble/hci/main/CMakeLists.txt

@@ -0,0 +1,4 @@
+set(srcs "main.c")
+
+idf_component_register(SRCS "${srcs}"
+                    INCLUDE_DIRS ".")

+ 4 - 0
examples/bluetooth/nimble/hci/main/component.mk

@@ -0,0 +1,4 @@
+#
+# "main" pseudo-component makefile.
+#
+# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.)

+ 43 - 0
examples/bluetooth/nimble/hci/main/main.c

@@ -0,0 +1,43 @@
+/*
+ * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include "esp_log.h"
+#include "nvs_flash.h"
+
+#include "esp_bt.h"
+
+#ifndef CONFIG_BT_LE_HCI_INTERFACE_USE_UART
+#error "Please Enable Uart for HCI"
+#endif
+
+#define TAG "BLE_HCI"
+
+void
+app_main(void)
+{
+    esp_err_t ret;
+    /* Initialize NVS — it is used to store PHY calibration data */
+    ret = nvs_flash_init();
+    if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
+        ESP_ERROR_CHECK(nvs_flash_erase());
+        ret = nvs_flash_init();
+    }
+    ESP_ERROR_CHECK(ret);
+
+    esp_bt_controller_config_t config_opts = BT_CONTROLLER_INIT_CONFIG_DEFAULT();
+
+    /*
+     *  Initialize Bluetooth Controller parameters.
+     */
+    ESP_ERROR_CHECK(esp_bt_controller_init(&config_opts));
+
+    /*
+     * Enable the task stack of the Bluetooth Controller.
+     */
+    ESP_ERROR_CHECK(esp_bt_controller_enable(ESP_BT_MODE_BLE));
+
+
+}

+ 9 - 0
examples/bluetooth/nimble/hci/sdkconfig.defaults

@@ -0,0 +1,9 @@
+# This file was generated using idf.py save-defconfig. It can be edited manually.
+# Espressif IoT Development Framework (ESP-IDF) Project Minimal Configuration
+#
+CONFIG_BT_ENABLED=y
+CONFIG_BT_CONTROLLER_ONLY=y
+CONFIG_BT_LE_HCI_INTERFACE_USE_UART=y
+CONFIG_BT_LE_HCI_UART_TX_PIN=8
+CONFIG_BT_LE_HCI_UART_RX_PIN=9
+CONFIG_BT_LE_HCI_UART_BAUD=115200

+ 2 - 0
tools/ci/check_copyright_config.yaml

@@ -125,6 +125,8 @@ ignore:
   include:
     - components/bt/host/nimble/nimble/
     - components/bt/common/osi/
+    - components/bt/porting/ext/
+    - components/bt/porting/nimble/
     - components/http_parser/
     - components/wpa_supplicant/src/
     - '!components/wpa_supplicant/esp_supplicant/'