Browse Source

Merge branch 'feature/optimize_bluetooth_architecture_0616' into 'master'

Feature/optimize bluetooth architecture

See merge request espressif/esp-idf!18553
Jiang Jiang Jian 3 years ago
parent
commit
3cc134672b
91 changed files with 15721 additions and 998 deletions
  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)
         list(APPEND include_dirs include/esp32c2/include)
     endif()
     endif()
 
 
+
     # Common
     # Common
     list(APPEND include_dirs common/osi/include)
     list(APPEND include_dirs common/osi/include)
 
 
     list(APPEND priv_include_dirs
     list(APPEND priv_include_dirs
             common/btc/include
             common/btc/include
-            common/include)
+            common/include
+            porting/mem/
+        )
     list(APPEND include_dirs
     list(APPEND include_dirs
          common/api/include/api
          common/api/include/api
          common/btc/profile/esp/blufi/include
          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"
     list(APPEND srcs "common/btc/core/btc_alarm.c"
@@ -56,7 +60,9 @@ if(CONFIG_BT_ENABLED)
          "common/osi/mutex.c"
          "common/osi/mutex.c"
          "common/osi/thread.c"
          "common/osi/thread.c"
          "common/osi/osi.c"
          "common/osi/osi.c"
-         "common/osi/semaphore.c")
+         "common/osi/semaphore.c"
+         "porting/mem/bt_osi_mem.c"
+         )
 
 
     # Host Bluedroid
     # Host Bluedroid
     if(CONFIG_BT_BLUEDROID_ENABLED)
     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_l2c.c"
                    "host/bluedroid/stack/smp/smp_main.c"
                    "host/bluedroid/stack/smp/smp_main.c"
                    "host/bluedroid/stack/smp/smp_utils.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")
         list(APPEND srcs "common/btc/profile/esp/blufi/bluedroid_host/esp_blufi.c")
 
 
@@ -466,67 +467,48 @@ if(CONFIG_BT_ENABLED)
     endif()
     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
             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
             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()
     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)
     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"
                     "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
             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
             list(APPEND srcs
                     "host/nimble/nimble/porting/nimble/src/endian.c"
                     "host/nimble/nimble/porting/nimble/src/endian.c"
                     "host/nimble/nimble/porting/nimble/src/os_mempool.c"
                     "host/nimble/nimble/porting/nimble/src/os_mempool.c"
                     "host/nimble/nimble/porting/nimble/src/mem.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()
         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
         list(APPEND srcs
                     "common/btc/profile/esp/blufi/nimble_host/esp_blufi.c")
                     "common/btc/profile/esp/blufi/nimble_host/esp_blufi.c")

+ 0 - 1
components/bt/Kconfig

@@ -45,7 +45,6 @@ menu "Bluetooth"
             bool "Enabled"
             bool "Enabled"
             help
             help
                 This option is recommended for Bluetooth controller usecases
                 This option is recommended for Bluetooth controller usecases
-                This option is recommended for Bluetooth controller usecases
 
 
         config BT_CONTROLLER_DISABLED
         config BT_CONTROLLER_DISABLED
             bool "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
         config BT_LE_HCI_INTERFACE_USE_RAM
             bool "ram"
             bool "ram"
             help
             help
-                    Use RAM as HCI interface
+                Use RAM as HCI interface
         config BT_LE_HCI_INTERFACE_USE_UART
         config BT_LE_HCI_INTERFACE_USE_UART
             bool "uart"
             bool "uart"
             help
             help
-                    Use UART as HCI interface
+                Use UART as HCI interface
     endchoice
     endchoice
 
 
     config BT_LE_HCI_UART_PORT
     config BT_LE_HCI_UART_PORT
@@ -22,6 +22,11 @@ menu "HCI Config"
         help
         help
             Set the port number of HCI UART
             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
     config BT_LE_HCI_UART_TX_PIN
         int "HCI uart Tx gpio"
         int "HCI uart Tx gpio"
         depends on BT_LE_HCI_INTERFACE_USE_UART
         depends on BT_LE_HCI_INTERFACE_USE_UART
@@ -32,72 +37,142 @@ menu "HCI Config"
         depends on BT_LE_HCI_INTERFACE_USE_UART
         depends on BT_LE_HCI_INTERFACE_USE_UART
         default 10
         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
     config BT_LE_HCI_UART_BAUD
         int "HCI uart baudrate"
         int "HCI uart baudrate"
         depends on BT_LE_HCI_INTERFACE_USE_UART
         depends on BT_LE_HCI_INTERFACE_USE_UART
         default 921600
         default 921600
         help
         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
 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
     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
     depends on !BT_NIMBLE_ENABLED
     default y
     default y
     help
     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
     default y
     help
     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
     default y
     help
     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
     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
     help
-            Enable encryption connection
+        Set this option to set the upper limit for number of periodic advertiser list.
 
 
 menu "Memory Settings"
 menu "Memory Settings"
     depends on !BT_NIMBLE_ENABLED
     depends on !BT_NIMBLE_ENABLED
@@ -112,22 +187,22 @@ menu "Memory Settings"
             count.
             count.
 
 
     config BT_LE_MSYS_1_BLOCK_SIZE
     config BT_LE_MSYS_1_BLOCK_SIZE
-        int    "MSYS_1 Block Size"
+        int "MSYS_1 Block Size"
         default 256
         default 256
         help
         help
-                Dynamic memory size of block 1
+            Dynamic memory size of block 1
 
 
     config BT_LE_MSYS_2_BLOCK_COUNT
     config BT_LE_MSYS_2_BLOCK_COUNT
-        int    "MSYS_2 Block Count"
+        int "MSYS_2 Block Count"
         default 24
         default 24
         help
         help
-                Dynamic memory count
+            Dynamic memory count
 
 
     config BT_LE_MSYS_2_BLOCK_SIZE
     config BT_LE_MSYS_2_BLOCK_SIZE
-        int    "MSYS_2 Block Size"
+        int "MSYS_2 Block Size"
         default 320
         default 320
         help
         help
-                Dynamic memory size of block 2
+            Dynamic memory size of block 2
 
 
     config BT_LE_ACL_BUF_COUNT
     config BT_LE_ACL_BUF_COUNT
         int "ACL Buffer count"
         int "ACL Buffer count"
@@ -170,135 +245,95 @@ menu "Memory Settings"
             get dropped
             get dropped
 endmenu
 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
     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
     depends on !BT_NIMBLE_ENABLED
     default y
     default y
     help
     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
     default y
     help
     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
     default y
     help
     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
     default n
+    depends on BT_LE_SECURITY_ENABLE && BT_LE_SM_SC
     help
     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
     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
     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
 config BT_LE_WHITELIST_SIZE
     int "BLE white list 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
     depends on !BT_NIMBLE_ENABLED
 
 
     help
     help
-            BLE list size
+        BLE list size
 
 
 config BT_LE_LL_DUP_SCAN_LIST_COUNT
 config BT_LE_LL_DUP_SCAN_LIST_COUNT
     int "BLE duplicate scan list count"
     int "BLE duplicate scan list count"
     range 1 100
     range 1 100
     default 20
     default 20
     help
     help
-            config the max count of duplicate scan list
+        config the max count of duplicate scan list
 
 
 config BT_LE_LL_SCA
 config BT_LE_LL_SCA
     int "BLE Sleep clock accuracy"
     int "BLE Sleep clock accuracy"
     range 0 500
     range 0 500
     default 60
     default 60
     help
     help
-            Sleep clock accuracy of our device (in ppm)
+        Sleep clock accuracy of our device (in ppm)
 
 
 config BT_LE_MAX_CONNECTIONS
 config BT_LE_MAX_CONNECTIONS
     int "Maximum number of concurrent connections"
     int "Maximum number of concurrent connections"
     depends on !BT_NIMBLE_ENABLED
     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
     help
         Defines maximum number of concurrent BLE connections. For ESP32, user
         Defines maximum number of concurrent BLE connections. For ESP32, user
         is expected to configure BTDM_CTRL_BLE_MAX_CONN from controller menu
         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
     default BT_LE_COEX_PHY_CODED_TX_RX_TLIM_DIS
     depends on !BT_NIMBLE_ENABLED
     depends on !BT_NIMBLE_ENABLED
     help
     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
 endchoice
 
 
 config BT_LE_COEX_PHY_CODED_TX_RX_TLIM_EFF
 config BT_LE_COEX_PHY_CODED_TX_RX_TLIM_EFF
     int
     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 1 if BT_LE_COEX_PHY_CODED_TX_RX_TLIM_EN
     default 0 if BT_LE_COEX_PHY_CODED_TX_RX_TLIM_DIS
     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 "sdkconfig.h"
 
 
-#include "os/os.h"
-#include "sysinit/sysinit.h"
 #include "nimble/nimble_port.h"
 #include "nimble/nimble_port.h"
 #include "nimble/nimble_port_freertos.h"
 #include "nimble/nimble_port_freertos.h"
 
 
@@ -27,24 +25,21 @@
 #include "esp_coexist_internal.h"
 #include "esp_coexist_internal.h"
 #endif
 #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 "nimble/ble_hci_trans.h"
+#include "os/endian.h"
 
 
-#include "nimble/nimble_npl_os.h"
 #include "esp_bt.h"
 #include "esp_bt.h"
 #include "esp_intr_alloc.h"
 #include "esp_intr_alloc.h"
-#include "nimble/nimble_npl_os.h"
 #include "esp_sleep.h"
 #include "esp_sleep.h"
 #include "esp_pm.h"
 #include "esp_pm.h"
 #include "esp_phy_init.h"
 #include "esp_phy_init.h"
 #include "soc/syscon_reg.h"
 #include "soc/syscon_reg.h"
 #include "soc/modem_clkrst_reg.h"
 #include "soc/modem_clkrst_reg.h"
 #include "esp_private/periph_ctrl.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
 #ifdef CONFIG_BT_BLUEDROID_ENABLED
 #include "hci/hci_hal.h"
 #include "hci/hci_hal.h"
 #endif
 #endif
@@ -86,8 +81,8 @@ struct ext_funcs_t {
     void *(* _malloc)(size_t size);
     void *(* _malloc)(size_t size);
     void (*_free)(void *p);
     void (*_free)(void *p);
     void (*_hal_uart_start_tx)(int);
     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);
     int (*_hal_uart_close)(int);
     void (*_hal_uart_blocking_tx)(int, uint8_t);
     void (*_hal_uart_blocking_tx)(int, uint8_t);
     int (*_hal_uart_init)(int, void *);
     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 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 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_deinit(void);
 extern int ble_controller_enable(uint8_t mode);
 extern int ble_controller_enable(uint8_t mode);
 extern int ble_controller_disable(void);
 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 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 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 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_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 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);
 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,
     .ext_version = EXT_FUNC_VERSION,
     ._esp_intr_alloc = esp_intr_alloc_wrapper,
     ._esp_intr_alloc = esp_intr_alloc_wrapper,
     ._esp_intr_free = esp_intr_free_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_create = task_create_wrapper,
     ._task_delete = task_delete_wrapper,
     ._task_delete = task_delete_wrapper,
     ._osi_assert = osi_assert_wrapper,
     ._osi_assert = osi_assert_wrapper,
@@ -328,56 +327,53 @@ static void task_delete_wrapper(void *task_handle)
     vTaskDelete(task_handle);
     vTaskDelete(task_handle);
 }
 }
 
 
-static void hal_uart_start_tx_wrapper(int uart_no)
-{
 #ifdef CONFIG_BT_LE_HCI_INTERFACE_USE_UART
 #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;
     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;
     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;
     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;
     return rc;
 }
 }
 
 
-static int hal_uart_close_wrapper(int uart_no)
+static int hci_uart_close_wrapper(int uart_no)
 {
 {
     int rc = -1;
     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;
     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)
 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) {
     if (esp_timer_create(&create_args, &s_btdm_slp_tmr) != ESP_OK) {
         goto error;
         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
 #endif //CONFIG_BT_LE_WAKEUP_SOURCE_CPU_RTC_TIMER
 
 
 #ifdef CONFIG_BT_LE_WAKEUP_SOURCE_BLE_RTC_TIMER
 #ifdef CONFIG_BT_LE_WAKEUP_SOURCE_BLE_RTC_TIMER
     esp_sleep_enable_bt_wakeup();
     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
 #endif // CONFIG_BT_LE_WAKEUP_SOURCE_BLE_RTC_TIMER
 
 
     s_pm_lock_acquired = true;
     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) {
     if (ble_controller_status != ESP_BT_CONTROLLER_STATUS_IDLE) {
         ESP_LOGW(NIMBLE_PORT_LOG_TAG, "invalid controller state");
         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);
     esp_ble_ll_set_public_addr(mac);
 
 
     ble_controller_status = ESP_BT_CONTROLLER_STATUS_INITED;
     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;
     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
         config BT_LE_HCI_INTERFACE_USE_RAM
             bool "ram"
             bool "ram"
             help
             help
-                    Use RAM as HCI interface
+                Use RAM as HCI interface
         config BT_LE_HCI_INTERFACE_USE_UART
         config BT_LE_HCI_INTERFACE_USE_UART
             bool "uart"
             bool "uart"
             help
             help
-                    Use UART as HCI interface
+                Use UART as HCI interface
     endchoice
     endchoice
 
 
     config BT_LE_HCI_UART_PORT
     config BT_LE_HCI_UART_PORT
@@ -22,6 +22,11 @@ menu "HCI Config"
         help
         help
             Set the port number of HCI UART
             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
     config BT_LE_HCI_UART_TX_PIN
         int "HCI uart Tx gpio"
         int "HCI uart Tx gpio"
         depends on BT_LE_HCI_INTERFACE_USE_UART
         depends on BT_LE_HCI_INTERFACE_USE_UART
@@ -32,151 +37,82 @@ menu "HCI Config"
         depends on BT_LE_HCI_INTERFACE_USE_UART
         depends on BT_LE_HCI_INTERFACE_USE_UART
         default 10
         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
     config BT_LE_HCI_UART_BAUD
         int "HCI uart baudrate"
         int "HCI uart baudrate"
         depends on BT_LE_HCI_INTERFACE_USE_UART
         depends on BT_LE_HCI_INTERFACE_USE_UART
         default 921600
         default 921600
         help
         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
         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
 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
     default y
-    depends on !BT_NIMBLE_ENABLED
-    select MBEDTLS_ECP_RESTARTABLE
-    select MBEDTLS_CMAC_C
     help
     help
-        Enable this option to choose mbedTLS instead of TinyCrypt for crypto
-        computations.
+        Enable NPL porting for controller.
+
 
 
 menuconfig BT_LE_50_FEATURE_SUPPORT
 menuconfig BT_LE_50_FEATURE_SUPPORT
     bool "Enable BLE 5 feature"
     bool "Enable BLE 5 feature"
     depends on !BT_NIMBLE_ENABLED
     depends on !BT_NIMBLE_ENABLED
     default y
     default y
     help
     help
-            Enable BLE 5 feature
+        Enable BLE 5 feature
 
 
 config BT_LE_LL_CFG_FEAT_LE_2M_PHY
 config BT_LE_LL_CFG_FEAT_LE_2M_PHY
     bool "Enable 2M Phy"
     bool "Enable 2M Phy"
     depends on BT_LE_50_FEATURE_SUPPORT
     depends on BT_LE_50_FEATURE_SUPPORT
     default y
     default y
     help
     help
-            Enable 2M-PHY
+        Enable 2M-PHY
 
 
 config BT_LE_LL_CFG_FEAT_LE_CODED_PHY
 config BT_LE_LL_CFG_FEAT_LE_CODED_PHY
     bool "Enable coded Phy"
     bool "Enable coded Phy"
     depends on BT_LE_50_FEATURE_SUPPORT
     depends on BT_LE_50_FEATURE_SUPPORT
     default y
     default y
     help
     help
-            Enable coded-PHY
+        Enable coded-PHY
 
 
 config BT_LE_EXT_ADV
 config BT_LE_EXT_ADV
     bool "Enable extended advertising"
     bool "Enable extended advertising"
     depends on BT_LE_50_FEATURE_SUPPORT
     depends on BT_LE_50_FEATURE_SUPPORT
-    default n
+    default y
     help
     help
         Enable this option to do extended advertising. Extended advertising
         Enable this option to do extended advertising. Extended advertising
         will be supported from BLE 5.0 onwards.
         will be supported from BLE 5.0 onwards.
@@ -185,8 +121,7 @@ if BT_LE_EXT_ADV
     config BT_LE_MAX_EXT_ADV_INSTANCES
     config BT_LE_MAX_EXT_ADV_INSTANCES
         int "Maximum number of extended advertising instances."
         int "Maximum number of extended advertising instances."
         range 0 4
         range 0 4
-        default 1 if BT_LE_EXT_ADV
-        default 0
+        default 1
         depends on BT_LE_EXT_ADV
         depends on BT_LE_EXT_ADV
         help
         help
             Change this option to set maximum number of extended advertising
             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
     config BT_LE_EXT_ADV_MAX_SIZE
         int "Maximum length of the advertising data."
         int "Maximum length of the advertising data."
         range 0 1650
         range 0 1650
-        default 1650 if BT_LE_EXT_ADV
-        default 0
+        default 1650
         depends on BT_LE_EXT_ADV
         depends on BT_LE_EXT_ADV
         help
         help
             Defines the length of the extended adv data. The value should not
             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
         depends on BT_LE_ENABLE_PERIODIC_ADV
         default y
         default y
         help
         help
-                This enables controller transfer periodic sync events to host
+            This enables controller transfer periodic sync events to host
 
 
 endif
 endif
 
 
@@ -224,8 +158,7 @@ config BT_LE_MAX_PERIODIC_SYNCS
     int "Maximum number of periodic advertising syncs"
     int "Maximum number of periodic advertising syncs"
     depends on BT_LE_50_FEATURE_SUPPORT && !BT_NIMBLE_ENABLED
     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 1 if BT_LE_ENABLE_PERIODIC_ADV
     default 0
     default 0
     help
     help
@@ -235,42 +168,172 @@ config BT_LE_MAX_PERIODIC_SYNCS
 
 
 config BT_LE_MAX_PERIODIC_ADVERTISER_LIST
 config BT_LE_MAX_PERIODIC_ADVERTISER_LIST
     int "Maximum number of 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
     range 1 5
-    default 5 if BT_LE_50_FEATURE_SUPPORT
+    default 5
     help
     help
         Set this option to set the upper limit for number of periodic advertiser list.
         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
 config BT_LE_WHITELIST_SIZE
     int "BLE white list 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
     depends on !BT_NIMBLE_ENABLED
 
 
     help
     help
-            BLE list size
+        BLE list size
 
 
 config BT_LE_LL_DUP_SCAN_LIST_COUNT
 config BT_LE_LL_DUP_SCAN_LIST_COUNT
     int "BLE duplicate scan list count"
     int "BLE duplicate scan list count"
     range 1 100
     range 1 100
     default 20
     default 20
     help
     help
-            config the max count of duplicate scan list
+        config the max count of duplicate scan list
 
 
 config BT_LE_LL_SCA
 config BT_LE_LL_SCA
     int "BLE Sleep clock accuracy"
     int "BLE Sleep clock accuracy"
     range 0 500
     range 0 500
     default 60
     default 60
     help
     help
-            Sleep clock accuracy of our device (in ppm)
+        Sleep clock accuracy of our device (in ppm)
 
 
 config BT_LE_MAX_CONNECTIONS
 config BT_LE_MAX_CONNECTIONS
     int "Maximum number of concurrent connections"
     int "Maximum number of concurrent connections"
     depends on !BT_NIMBLE_ENABLED
     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
     help
         Defines maximum number of concurrent BLE connections. For ESP32, user
         Defines maximum number of concurrent BLE connections. For ESP32, user
         is expected to configure BTDM_CTRL_BLE_MAX_CONN from controller menu
         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
     default BT_LE_COEX_PHY_CODED_TX_RX_TLIM_DIS
     depends on !BT_NIMBLE_ENABLED
     depends on !BT_NIMBLE_ENABLED
     help
     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
 endchoice
 
 
 config BT_LE_COEX_PHY_CODED_TX_RX_TLIM_EFF
 config BT_LE_COEX_PHY_CODED_TX_RX_TLIM_EFF
     int
     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 1 if BT_LE_COEX_PHY_CODED_TX_RX_TLIM_EN
     default 0 if BT_LE_COEX_PHY_CODED_TX_RX_TLIM_DIS
     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 <stdio.h>
 #include <string.h>
 #include <string.h>
 
 
-#include <esp_random.h>
+#include "esp_random.h"
 #include <esp_mac.h>
 #include <esp_mac.h>
 
 
 #include "sdkconfig.h"
 #include "sdkconfig.h"
 
 
-#include "os/os.h"
-#include "sysinit/sysinit.h"
 #include "nimble/nimble_port.h"
 #include "nimble/nimble_port.h"
 #include "nimble/nimble_port_freertos.h"
 #include "nimble/nimble_port_freertos.h"
 
 
@@ -27,21 +25,20 @@
 #include "esp_coexist_internal.h"
 #include "esp_coexist_internal.h"
 #endif
 #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 "nimble/ble_hci_trans.h"
+#include "os/endian.h"
 
 
-#include "nimble/nimble_npl_os.h"
 #include "esp_bt.h"
 #include "esp_bt.h"
 #include "esp_intr_alloc.h"
 #include "esp_intr_alloc.h"
 #include "esp_sleep.h"
 #include "esp_sleep.h"
 #include "esp_pm.h"
 #include "esp_pm.h"
 #include "esp_phy_init.h"
 #include "esp_phy_init.h"
 #include "soc/system_reg.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
 #ifdef CONFIG_BT_BLUEDROID_ENABLED
 #include "hci/hci_hal.h"
 #include "hci/hci_hal.h"
 #endif
 #endif
@@ -50,7 +47,8 @@
 #include "freertos/task.h"
 #include "freertos/task.h"
 
 
 #include "esp_private/periph_ctrl.h"
 #include "esp_private/periph_ctrl.h"
-#include "nimble/hci_common.h"
+#include "esp_sleep.h"
+
 /* Macro definition
 /* Macro definition
  ************************************************************************
  ************************************************************************
  */
  */
@@ -79,8 +77,8 @@ struct ext_funcs_t {
     void *(* _malloc)(size_t size);
     void *(* _malloc)(size_t size);
     void (*_free)(void *p);
     void (*_free)(void *p);
     void (*_hal_uart_start_tx)(int);
     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);
     int (*_hal_uart_close)(int);
     void (*_hal_uart_blocking_tx)(int, uint8_t);
     void (*_hal_uart_blocking_tx)(int, uint8_t);
     int (*_hal_uart_init)(int, void *);
     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_plf_set_log_level(int level);
 extern int ble_osi_coex_funcs_register(struct osi_coex_funcs_t *coex_funcs);
 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 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_deinit(void);
 extern int ble_controller_enable(uint8_t mode);
 extern int ble_controller_enable(uint8_t mode);
 extern int ble_controller_disable(void);
 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 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 int os_msys_init(void);
 extern void os_msys_buf_free(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);
 extern void bt_bb_set_le_tx_on_delay(uint32_t delay_us);
 
 
 /* Local Function Declaration
 /* 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 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 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 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_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 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);
 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 variable declare */
 static DRAM_ATTR esp_bt_controller_status_t ble_controller_status = ESP_BT_CONTROLLER_STATUS_IDLE;
 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
 #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 DRAM_ATTR esp_pm_lock_handle_t s_pm_lock = NULL;
 static bool s_pm_lock_acquired = true;
 static bool s_pm_lock_acquired = true;
 static DRAM_ATTR bool s_btdm_allow_light_sleep;
 static DRAM_ATTR bool s_btdm_allow_light_sleep;
 // pm_lock to prevent light sleep when using main crystal as Bluetooth low power clock
 // 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 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)
 #define BTDM_MIN_TIMER_UNCERTAINTY_US      (200)
 #endif /* #ifdef CONFIG_PM_ENABLE */
 #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)
 #define BLE_RTC_DELAY_US                    (1100)
-#else
+#endif
+
+#ifdef CONFIG_BT_LE_WAKEUP_SOURCE_CPU_RTC_TIMER
 #define BLE_RTC_DELAY_US                    (0)
 #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
 #endif
 
 
 static const struct osi_coex_funcs_t s_osi_coex_funcs_ro = {
 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,
     .ext_version = 0xE0000001,
     ._esp_intr_alloc = esp_intr_alloc_wrapper,
     ._esp_intr_alloc = esp_intr_alloc_wrapper,
     ._esp_intr_free = esp_intr_free_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_create = task_create_wrapper,
     ._task_delete = task_delete_wrapper,
     ._task_delete = task_delete_wrapper,
     ._osi_assert = osi_assert_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)
 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);
     assert(0);
 }
 }
 
 
@@ -236,8 +233,7 @@ bool esp_vhci_host_check_send_available(void)
 /**
 /**
  * Allocates an mbuf for use by the nimble host.
  * 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;
     struct os_mbuf *om;
     int rc;
     int rc;
@@ -264,8 +260,7 @@ ble_hs_mbuf_gen_pkt(uint16_t leading_space)
  * @return                  An empty mbuf on success; null on memory
  * @return                  An empty mbuf on success; null on memory
  *                              exhaustion.
  *                              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);
     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;
         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;
     return ESP_OK;
 }
 }
@@ -316,56 +311,53 @@ static void task_delete_wrapper(void *task_handle)
     vTaskDelete(task_handle);
     vTaskDelete(task_handle);
 }
 }
 
 
-static void hal_uart_start_tx_wrapper(int uart_no)
-{
 #ifdef CONFIG_BT_LE_HCI_INTERFACE_USE_UART
 #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;
     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;
     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;
     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;
     return rc;
 }
 }
 
 
-static int hal_uart_close_wrapper(int uart_no)
+static int hci_uart_close_wrapper(int uart_no)
 {
 {
     int rc = -1;
     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;
     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)
 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)
 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_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
         // 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);
         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) {
     if (s_pm_lock_acquired) {
+        assert(s_pm_lock != NULL);
         esp_pm_lock_release(s_pm_lock);
         esp_pm_lock_release(s_pm_lock);
         s_pm_lock_acquired = false;
         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)
 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
 #ifdef CONFIG_PM_ENABLE
+    assert(s_pm_lock != NULL);
     if (!s_pm_lock_acquired) {
     if (!s_pm_lock_acquired) {
         s_pm_lock_acquired = true;
         s_pm_lock_acquired = true;
         esp_pm_lock_acquire(s_pm_lock);
         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_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);
     (void)(arg);
     if (!s_pm_lock_acquired) {
     if (!s_pm_lock_acquired) {
+        assert(s_pm_lock != NULL);
         s_pm_lock_acquired = true;
         s_pm_lock_acquired = true;
         esp_pm_lock_acquire(s_pm_lock);
         esp_pm_lock_acquire(s_pm_lock);
     }
     }
 }
 }
 
 
-#endif
+#endif // CONFIG_BT_LE_WAKEUP_SOURCE_CPU_RTC_TIMER
 #endif // CONFIG_PM_ENABLE
 #endif // CONFIG_PM_ENABLE
 
 
 void controller_sleep_init(void)
 void controller_sleep_init(void)
 {
 {
 
 
-#ifdef CONFIG_NIMBLE_SLEEP_ENABLE
-    s_is_sleep_state = false;
 #ifdef CONFIG_PM_ENABLE
 #ifdef CONFIG_PM_ENABLE
-    s_btdm_allow_light_sleep = true;
+    s_btdm_allow_light_sleep = false;
 #endif // CONFIG_PM_ENABLE
 #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
 #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_PM_ENABLE
-#endif // CONFIG_NIMBLE_SLEEP_ENABLE
+
+#endif // CONFIG_BT_LE_SLEEP_ENABLE
 
 
     // enable light sleep
     // enable light sleep
 #ifdef CONFIG_PM_ENABLE
 #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) {
     if (esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 0, "bt", &s_pm_lock) != ESP_OK) {
         goto error;
         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 = {
     esp_timer_create_args_t create_args = {
         .callback = btdm_slp_tmr_callback,
         .callback = btdm_slp_tmr_callback,
         .arg = NULL,
         .arg = NULL,
         .name = "btSlp"
         .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;
         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_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;
     s_pm_lock_acquired = true;
 
 
@@ -518,16 +504,18 @@ error:
         esp_pm_lock_delete(s_pm_lock);
         esp_pm_lock_delete(s_pm_lock);
         s_pm_lock = NULL;
         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) {
     if (s_btdm_slp_tmr != NULL) {
         esp_timer_delete(s_btdm_slp_tmr);
         esp_timer_delete(s_btdm_slp_tmr);
         s_btdm_slp_tmr = NULL;
         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();
     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);
         esp_pm_lock_delete(s_pm_lock);
         s_pm_lock = NULL;
         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_stop(s_btdm_slp_tmr);
         esp_timer_delete(s_btdm_slp_tmr);
         esp_timer_delete(s_btdm_slp_tmr);
         s_btdm_slp_tmr = NULL;
         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) {
     if (ble_controller_status != ESP_BT_CONTROLLER_STATUS_IDLE) {
         ESP_LOGW(NIMBLE_PORT_LOG_TAG, "invalid controller state");
         ESP_LOGW(NIMBLE_PORT_LOG_TAG, "invalid controller state");
         return ESP_FAIL;
         return ESP_FAIL;
     }
     }
     if (cfg == NULL) {
     if (cfg == NULL) {
+        ESP_LOGW(NIMBLE_PORT_LOG_TAG, "cfg is NULL");
         return ESP_ERR_INVALID_ARG;
         return ESP_ERR_INVALID_ARG;
     }
     }
 
 
     if (esp_register_ext_funcs(&ext_funcs_ro) != 0) {
     if (esp_register_ext_funcs(&ext_funcs_ro) != 0) {
+        ESP_LOGW(NIMBLE_PORT_LOG_TAG, "register extend functions failed");
         return ESP_ERR_INVALID_ARG;
         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
 #if CONFIG_SW_COEXIST_ENABLE
     coex_init();
     coex_init();
 #endif
 #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;
         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);
     esp_ble_ll_set_public_addr(mac);
 
 
     ble_controller_status = ESP_BT_CONTROLLER_STATUS_INITED;
     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;
     return ESP_OK;
 }
 }
 
 
@@ -672,70 +664,6 @@ esp_err_t esp_bt_controller_deinit(void)
     return ESP_OK;
     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)
 esp_err_t esp_bt_controller_enable(esp_bt_mode_t mode)
 {
 {
     if (mode != ESP_BT_MODE_BLE) {
     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");
         ESP_LOGW(NIMBLE_PORT_LOG_TAG, "invalid controller state");
         return ESP_FAIL;
         return ESP_FAIL;
     }
     }
-
 #if CONFIG_SW_COEXIST_ENABLE
 #if CONFIG_SW_COEXIST_ENABLE
     coex_enable();
     coex_enable();
 #endif
 #endif
-
     if (ble_controller_enable(mode) != 0) {
     if (ble_controller_enable(mode) != 0) {
         return ESP_FAIL;
         return ESP_FAIL;
     }
     }
-
     ble_controller_status = ESP_BT_CONTROLLER_STATUS_ENABLED;
     ble_controller_status = ESP_BT_CONTROLLER_STATUS_ENABLED;
     return ESP_OK;
     return ESP_OK;
 }
 }
@@ -768,6 +693,7 @@ esp_err_t esp_bt_controller_disable(void)
     if (ble_controller_disable() != 0) {
     if (ble_controller_disable() != 0) {
         return ESP_FAIL;
         return ESP_FAIL;
     }
     }
+    ble_controller_status = ESP_BT_CONTROLLER_STATUS_INITED;
     return ESP_OK;
     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__);
     ESP_LOGW(NIMBLE_PORT_LOG_TAG, "%s not implemented, return OK", __func__);
     return ESP_OK;
     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
 config BT_NIMBLE_HS_FLOW_CTRL
     bool "Enable Host Flow control"
     bool "Enable Host Flow control"
     depends on BT_NIMBLE_ENABLED
     depends on BT_NIMBLE_ENABLED
-    default n if BT_SOC_SUPPORT_5_0
-    default y
+    default y if IDF_TARGET_ESP32
+    default n
     help
     help
         Enable Host Flow control
         Enable Host Flow control
 
 
@@ -605,10 +605,8 @@ config BT_NIMBLE_COEX_PHY_CODED_TX_RX_TLIM_EFF
 config BT_NIMBLE_WHITELIST_SIZE
 config BT_NIMBLE_WHITELIST_SIZE
     int "BLE white list size"
     int "BLE white list size"
     depends on BT_NIMBLE_ENABLED
     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
     help
             BLE list size
             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 "nimble/nimble_port_freertos.h"
 #include "esp_nimble_hci.h"
 #include "esp_nimble_hci.h"
 #include "esp_nimble_mem.h"
 #include "esp_nimble_mem.h"
+#include "bt_osi_mem.h"
 #include "esp_bt.h"
 #include "esp_bt.h"
 #include "freertos/semphr.h"
 #include "freertos/semphr.h"
 #include "esp_compiler.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
 #define IRAM_ATTR_64MCPU IRAM_ATTR
 #endif
 #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
 #if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3
 #define NIMBLE_CFG_CONTROLLER    0
 #define NIMBLE_CFG_CONTROLLER    0
@@ -1594,18 +1569,6 @@
 #define MYNEWT_VAL_BLE_HCI_UART_STOP_BITS (1)
 #define MYNEWT_VAL_BLE_HCI_UART_STOP_BITS (1)
 #endif
 #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
 #ifndef MYNEWT_VAL_NEWT_FEATURE_LOGCFG
 #define MYNEWT_VAL_NEWT_FEATURE_LOGCFG (1)
 #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" {
 extern "C" {
 #endif
 #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
 #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 "esp_task.h"
 
 
 #include "nimble/nimble_npl.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
 #endif
 
 
-#if (SOC_ESP_NIMBLE_CONTROLLER)
-#define NIMBLE_LL_STACK_SIZE CONFIG_BT_LE_CONTROLLER_TASK_STACK_SIZE
+#ifdef __cplusplus
+extern "C" {
 #endif
 #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.
  *        some options or parameters of some functions enabled by config mask.
  */
  */
 
 
-struct esp_bt_controller_config_t{
+typedef struct {
     uint32_t config_version;
     uint32_t config_version;
     uint16_t ble_ll_resolv_list_size;
     uint16_t ble_ll_resolv_list_size;
     uint16_t ble_hci_evt_hi_buf_count;
     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 dis_scan_backoff;
     uint8_t esp_scan_filter_en;
     uint8_t esp_scan_filter_en;
     uint32_t config_magic;
     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() {                                           \
 #define BT_CONTROLLER_INIT_CONFIG_DEFAULT() {                                           \
     .config_version = CONFIG_VERSION,                                                   \
     .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_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_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_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_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,                       \
     .ble_ll_ctrl_proc_timeout_ms = BLE_LL_CTRL_PROC_TIMEOUT_MS_N,                       \
     .nimble_max_connections = DEFAULT_BT_LE_MAX_CONNECTIONS,                            \
     .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_stop_bits     = DEFAULT_BT_LE_HCI_UART_STOP_BITS,                     \
     .ble_hci_uart_flow_ctrl     = DEFAULT_BT_LE_HCI_UART_FLOW_CTRL,                     \
     .ble_hci_uart_flow_ctrl     = DEFAULT_BT_LE_HCI_UART_FLOW_CTRL,                     \
     .ble_hci_uart_uart_parity   = DEFAULT_BT_LE_HCI_UART_PARITY,                        \
     .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,                                  \
     .sleep_en                   = NIMBLE_SLEEP_ENABLE,                                  \
     .coex_phy_coded_tx_rx_time_limit = DEFAULT_BT_LE_COEX_PHY_CODED_TX_RX_TLIM_EFF,     \
     .coex_phy_coded_tx_rx_time_limit = DEFAULT_BT_LE_COEX_PHY_CODED_TX_RX_TLIM_EFF,     \
     .dis_scan_backoff           = NIMBLE_DISABLE_SCAN_BACKOFF,                          \
     .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,                                                       \
     .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
  * @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 "esp_task.h"
 
 
 #include "nimble/nimble_npl.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
 #endif
-#include "nimble/ble.h"
+
 
 
 #ifdef __cplusplus
 #ifdef __cplusplus
 extern "C" {
 extern "C" {
 #endif
 #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
  * @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.
  *        some options or parameters of some functions enabled by config mask.
  */
  */
 
 
-struct esp_bt_controller_config_t{
+typedef struct {
     uint32_t config_version;
     uint32_t config_version;
     uint16_t ble_ll_resolv_list_size;
     uint16_t ble_ll_resolv_list_size;
     uint16_t ble_hci_evt_hi_buf_count;
     uint16_t ble_hci_evt_hi_buf_count;
@@ -176,140 +173,8 @@ struct esp_bt_controller_config_t{
     uint8_t sleep_en;
     uint8_t sleep_en;
     uint8_t coex_phy_coded_tx_rx_time_limit;
     uint8_t coex_phy_coded_tx_rx_time_limit;
     uint32_t config_magic;
     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() {                                           \
 #define BT_CONTROLLER_INIT_CONFIG_DEFAULT() {                                           \
     .config_version = CONFIG_VERSION,                                                   \
     .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_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_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_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_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,                       \
     .ble_ll_ctrl_proc_timeout_ms = BLE_LL_CTRL_PROC_TIMEOUT_MS_N,                       \
     .nimble_max_connections = DEFAULT_BT_LE_MAX_CONNECTIONS,                            \
     .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_stop_bits     = DEFAULT_BT_LE_HCI_UART_STOP_BITS,                     \
     .ble_hci_uart_flow_ctrl     = DEFAULT_BT_LE_HCI_UART_FLOW_CTRL,                     \
     .ble_hci_uart_flow_ctrl     = DEFAULT_BT_LE_HCI_UART_FLOW_CTRL,                     \
     .ble_hci_uart_uart_parity   = DEFAULT_BT_LE_HCI_UART_PARITY,                        \
     .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,                                  \
     .sleep_en                   = NIMBLE_SLEEP_ENABLE,                                  \
     .coex_phy_coded_tx_rx_time_limit = DEFAULT_BT_LE_COEX_PHY_CODED_TX_RX_TLIM_EFF,     \
     .coex_phy_coded_tx_rx_time_limit = DEFAULT_BT_LE_COEX_PHY_CODED_TX_RX_TLIM_EFF,     \
     .config_magic = CONFIG_MAGIC,                                                       \
     .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
  * @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_attr.h"
 #include "esp_heap_caps.h"
 #include "esp_heap_caps.h"
 #include "sdkconfig.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
 #ifdef CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_INTERNAL
     return heap_caps_malloc(size, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT);
     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
 #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
 #ifdef CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_INTERNAL
     return heap_caps_calloc(n, size, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT);
     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
 #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);
     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_update = 0x40000de0;
 r_ble_ll_conn_hci_wr_auth_pyld_tmo = 0x40000de4;
 r_ble_ll_conn_hci_wr_auth_pyld_tmo = 0x40000de4;
 r_ble_ll_conn_init_phy = 0x40000de8;
 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_empty_pdu = 0x40000df0;
 r_ble_ll_conn_is_lru = 0x40000df4;
 r_ble_ll_conn_is_lru = 0x40000df4;
 r_ble_ll_conn_master_init = 0x40000df8;
 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_alloc_credit = 0x400014ec;
 r_ble_lll_conn_cth_flow_free_credit = 0x400014f0;
 r_ble_lll_conn_cth_flow_free_credit = 0x400014f0;
 r_ble_lll_conn_current_sm_over = 0x400014f4;
 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_deinit = 0x400014fc;
 r_ble_lll_conn_env_init = 0x40001500;
 r_ble_lll_conn_env_init = 0x40001500;
 r_ble_lll_conn_event_end = 0x40001504;
 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_deinit = 0x40001734;
 r_ble_lll_sched_dtm = 0x40001738;
 r_ble_lll_sched_dtm = 0x40001738;
 r_ble_lll_sched_env_init = 0x4000173c;
 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_execute_item = 0x40001744;
 r_ble_lll_sched_init = 0x40001748;
 r_ble_lll_sched_init = 0x40001748;
 r_ble_lll_sched_insert_if_empty = 0x4000174c;
 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
 #if CONFIG_EXAMPLE_EXTENDED_ADV
 static uint8_t ext_adv_pattern_1[] = {
 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
 #endif
 
 
@@ -231,7 +231,7 @@ bleprph_gap_event(struct ble_gap_event *event, void *arg)
         if (event->connect.status != 0) {
         if (event->connect.status != 0) {
             /* Connection failed; resume advertising. */
             /* Connection failed; resume advertising. */
 #if CONFIG_EXAMPLE_EXTENDED_ADV
 #if CONFIG_EXAMPLE_EXTENDED_ADV
-	    ext_bleprph_advertise();
+            ext_bleprph_advertise();
 #else
 #else
             bleprph_advertise();
             bleprph_advertise();
 #endif
 #endif
@@ -245,7 +245,7 @@ bleprph_gap_event(struct ble_gap_event *event, void *arg)
 
 
         /* Connection terminated; resume advertising. */
         /* Connection terminated; resume advertising. */
 #if CONFIG_EXAMPLE_EXTENDED_ADV
 #if CONFIG_EXAMPLE_EXTENDED_ADV
-	ext_bleprph_advertise();
+        ext_bleprph_advertise();
 #else
 #else
         bleprph_advertise();
         bleprph_advertise();
 #endif
 #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_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_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_ENABLED=y
+CONFIG_BT_NIMBLE_HCI_EVT_BUF_SIZE=70
 CONFIG_BT_NIMBLE_EXT_ADV=y
 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:
   include:
     - components/bt/host/nimble/nimble/
     - components/bt/host/nimble/nimble/
     - components/bt/common/osi/
     - components/bt/common/osi/
+    - components/bt/porting/ext/
+    - components/bt/porting/nimble/
     - components/http_parser/
     - components/http_parser/
     - components/wpa_supplicant/src/
     - components/wpa_supplicant/src/
     - '!components/wpa_supplicant/esp_supplicant/'
     - '!components/wpa_supplicant/esp_supplicant/'