From fd54c9a9efff6bb1c62251e47b3ac4dcebe555ba Mon Sep 17 00:00:00 2001 From: David Cermak Date: Fri, 21 Jun 2024 16:49:29 +0200 Subject: [PATCH] fix(6lowpan_ble): Moved files to component folders --- .clang-format | 65 ------ .editorconfig | 37 --- .pre-commit-config.yaml | 2 +- .../6lowpan_ble/CMakeLists.txt | 0 LICENSE => components/6lowpan_ble/LICENSE | 1 - components/6lowpan_ble/README.md | 93 ++++++++ .../6lowpan_ble/examples}/echo/README.md | 0 .../examples}/echo/client/CMakeLists.txt | 0 .../examples}/echo/client/main/CMakeLists.txt | 0 .../examples}/echo/client/main/main.c | 116 ++++------ .../examples}/echo/client/sdkconfig | 0 .../examples}/echo/server/CMakeLists.txt | 0 .../examples}/echo/server/main/CMakeLists.txt | 0 .../examples}/echo/server/main/main.c | 128 +++++------ .../examples}/echo/server/sdkconfig | 0 .../6lowpan_ble/include}/lowpan6_ble.h | 56 +++-- .../6lowpan_ble/src}/debug_print_utils.c | 14 +- .../6lowpan_ble/src}/debug_print_utils.h | 7 +- .../6lowpan_ble/src}/lowpan6_ble.c | 211 +++++++----------- .../6lowpan_ble/src}/lowpan6_ble_netif.c | 99 ++++---- .../6lowpan_ble/src}/lowpan6_ble_netif.h | 27 ++- 21 files changed, 381 insertions(+), 475 deletions(-) delete mode 100644 .clang-format delete mode 100644 .editorconfig rename CMakeLists.txt => components/6lowpan_ble/CMakeLists.txt (100%) rename LICENSE => components/6lowpan_ble/LICENSE (99%) create mode 100644 components/6lowpan_ble/README.md rename {examples => components/6lowpan_ble/examples}/echo/README.md (100%) rename {examples => components/6lowpan_ble/examples}/echo/client/CMakeLists.txt (100%) rename {examples => components/6lowpan_ble/examples}/echo/client/main/CMakeLists.txt (100%) rename {examples => components/6lowpan_ble/examples}/echo/client/main/main.c (84%) rename {examples => components/6lowpan_ble/examples}/echo/client/sdkconfig (100%) rename {examples => components/6lowpan_ble/examples}/echo/server/CMakeLists.txt (100%) rename {examples => components/6lowpan_ble/examples}/echo/server/main/CMakeLists.txt (100%) rename {examples => components/6lowpan_ble/examples}/echo/server/main/main.c (79%) rename {examples => components/6lowpan_ble/examples}/echo/server/sdkconfig (100%) rename {include => components/6lowpan_ble/include}/lowpan6_ble.h (91%) rename {src => components/6lowpan_ble/src}/debug_print_utils.c (86%) rename {src => components/6lowpan_ble/src}/debug_print_utils.h (85%) rename {src => components/6lowpan_ble/src}/lowpan6_ble.c (80%) rename {src => components/6lowpan_ble/src}/lowpan6_ble_netif.c (70%) rename {src => components/6lowpan_ble/src}/lowpan6_ble_netif.h (78%) diff --git a/.clang-format b/.clang-format deleted file mode 100644 index 06d015dd75..0000000000 --- a/.clang-format +++ /dev/null @@ -1,65 +0,0 @@ ---- -AlignAfterOpenBracket: BlockIndent -AlignConsecutiveMacros: 'true' -AlignConsecutiveAssignments: 'true' -AlignConsecutiveDeclarations: 'false' -AlignEscapedNewlines: Left -AlignOperands: 'true' -AlignTrailingComments: 'true' -AllowAllArgumentsOnNextLine: 'false' -AllowAllConstructorInitializersOnNextLine: 'false' -AllowAllParametersOfDeclarationOnNextLine: 'false' -AllowShortBlocksOnASingleLine: 'false' -AllowShortCaseLabelsOnASingleLine: 'false' -AllowShortFunctionsOnASingleLine: None -AllowShortIfStatementsOnASingleLine: Never -AllowShortLambdasOnASingleLine: All -AllowShortLoopsOnASingleLine: 'false' -AlwaysBreakBeforeMultilineStrings: 'false' -AlwaysBreakTemplateDeclarations: 'Yes' -BinPackArguments: 'false' -BinPackParameters: 'false' -BreakBeforeBraces: Allman -BreakBeforeTernaryOperators: 'false' -BreakConstructorInitializers: BeforeColon -BreakInheritanceList: BeforeColon -BreakStringLiterals: 'false' -ColumnLimit: '100' -CompactNamespaces: 'false' -ConstructorInitializerAllOnOneLineOrOnePerLine: 'true' -ConstructorInitializerIndentWidth: '2' -ContinuationIndentWidth: '4' -FixNamespaceComments: 'true' -IncludeBlocks: Regroup -IndentCaseLabels: 'false' -IndentPPDirectives: BeforeHash -IndentWidth: '4' -IndentWrappedFunctionNames: 'false' -KeepEmptyLinesAtTheStartOfBlocks: 'false' -MaxEmptyLinesToKeep: '2' -NamespaceIndentation: None -PointerAlignment: Left -ReflowComments: 'true' -SortIncludes: 'true' -SortUsingDeclarations: 'true' -SpaceAfterCStyleCast: 'false' -SpaceAfterLogicalNot: 'false' -SpaceAfterTemplateKeyword: 'false' -SpaceBeforeAssignmentOperators: 'true' -SpaceBeforeCpp11BracedList: 'true' -SpaceBeforeCtorInitializerColon: 'true' -SpaceBeforeInheritanceColon: 'true' -SpaceBeforeParens: ControlStatements -SpaceBeforeRangeBasedForLoopColon: 'true' -SpaceInEmptyParentheses: 'false' -SpacesBeforeTrailingComments: '2' -SpacesInAngles: 'false' -SpacesInCStyleCastParentheses: 'false' -SpacesInContainerLiterals: 'false' -SpacesInParentheses: 'false' -SpacesInSquareBrackets: 'false' -Standard: c++20 -StatementMacros: ['GOOGLE_PROTOBUF_VERIFY_VERSION'] -UseTab: Never - -... diff --git a/.editorconfig b/.editorconfig deleted file mode 100644 index 4fd7122fef..0000000000 --- a/.editorconfig +++ /dev/null @@ -1,37 +0,0 @@ -# EditorConfig helps developers define and maintain consistent -# coding styles between different editors and IDEs -# http://editorconfig.org - -root = true - -[*] -indent_style = space -indent_size = 4 -end_of_line = lf -charset = utf-8 -trim_trailing_whitespace = true -insert_final_newline = true - -[{*.md,*.rst}] -trim_trailing_whitespace = false - -[{Makefile,*.mk,*.bat}] -indent_style = tab -indent_size = 2 - -[*.pem] -insert_final_newline = false - -[*.py] -max_line_length = 119 - -[{*.cmake,CMakeLists.txt}] -indent_style = space -indent_size = 4 -max_line_length = 120 - -[{*.sh,*.yml,*.yaml}] -indent_size = 2 - -[*.ini] -indent_size = 2 diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 19a05a7350..481dd7c75f 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -62,7 +62,7 @@ repos: hooks: - id: commit message scopes name: "commit message must be scoped with: mdns, modem, websocket, asio, mqtt_cxx, console, common, eppp, wifi_remote, tls_cxx" - entry: '\A(?!(feat|fix|ci|bump|test|docs)\((mdns|modem|common|console|websocket|asio|mqtt_cxx|examples|eppp|wifi_remote|tls_cxx)\)\:)' + entry: '\A(?!(feat|fix|ci|bump|test|docs)\((mdns|modem|common|console|websocket|asio|mqtt_cxx|examples|eppp|wifi_remote|tls_cxx|6lowpan_ble)\)\:)' language: pygrep args: [--multiline] stages: [commit-msg] diff --git a/CMakeLists.txt b/components/6lowpan_ble/CMakeLists.txt similarity index 100% rename from CMakeLists.txt rename to components/6lowpan_ble/CMakeLists.txt diff --git a/LICENSE b/components/6lowpan_ble/LICENSE similarity index 99% rename from LICENSE rename to components/6lowpan_ble/LICENSE index 6b0b1270ff..d645695673 100644 --- a/LICENSE +++ b/components/6lowpan_ble/LICENSE @@ -200,4 +200,3 @@ 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. - diff --git a/components/6lowpan_ble/README.md b/components/6lowpan_ble/README.md new file mode 100644 index 0000000000..329676bda6 --- /dev/null +++ b/components/6lowpan_ble/README.md @@ -0,0 +1,93 @@ +# LoWPAN6 BLE Netif + +This component provides a custom ESP-NETIF layer for +[RFC7668](https://datatracker.ietf.org/doc/html/rfc7668), allowing devices to +transport IPv6 over Bluetooth Low Energy links. + +> :warning: This is an experimental library, developed for a pretty narrow +> use-case. In particular, we just needed to connect to a peripheral using +> LoWPAN6 for local communications so have not really tested this component as +> a LoWPAN6 client. This component does not implement any routing capabilities: +> this won't allow you to route packets from your personal area network to the +> public internet, for example. + +## Usage + +This component only supports the NimBLE stack. It also requires support for +L2CAP COC connections. This means your project's `sdkconfig` needs at least: +* NimBLE as the Bluetooth stack (`CONFIG_BT_NIMBLE_ENABLED=y`) +* `CONFIG_BT_NIMBLE_L2CAP_COC_MAX_NUM` set to a non-zero value + +There is some boilerplate required to set up this netif layer. +```c +// Initialize the lowpan6_ble module +ESP_ERROR_CHECK(lowpan6_ble_init()); + +// Configure a new esp_netif to use the lowpan6_ble netstack +esp_netif_inherent_config_t base_cfg = ESP_NETIF_INHERENT_DEFAULT_LOWPAN6_BLE(); +esp_netif_config_t cfg = { + .base = &base_cfg, + .driver = NULL, + .stack = netstack_default_lowpan6_ble, +}; +esp_netif_t* lowpan6_ble_netif = esp_netif_new(&cfg); + +// Create a lowpan6_ble driver instance. Note that each driver instance only +// supports a single LoWPAN6 BLE channel. +s_l6ble_handle = lowpan6_ble_create(); +if (s_l6ble_handle != NULL) +{ + // Finally, attach the driver instance to the netif you created above. + ESP_ERROR_CHECK(esp_netif_attach(lowpan6_ble_netif, s_l6ble_handle)); +} +``` + +All that is left to bring this netif up is to connect to a BLE peer that +supports LoWPAN6 BLE. You can discover potential peers during, e.g., GAP discovery: + +```c +// Note: no error handling included for brevity's sake +static int on_gap_event(struct ble_gap_event* event, void* arg) +{ + switch (event->type) + { + case BLE_GAP_EVENT_DISC: + // Verify that the discovered peer supports LoWPAN6 BLE + if (lowpan6_ble_connectable(&event->disc)) + { + // Cancel the current discovery process so we can connect + ble_gap_disc_cancel(); + + lowpan6_ble_connect( + s_l6ble_handle, // handle to the driver we created above + &event->disc.addr, // peer's BLE address + BLE_CONNECT_TIMEOUT, // GAP connect timeout in ms + on_lowpan6_ble_event, // user-defined callback + NULL // user-defined callback argument + ); + } + } +} +``` + +Once that netif is up, you should be able to communicate to the BLE peer with +generic network interfaces. For example, a UDP socket listening for messages +from any address using LwIP's BSD sockets API: + +```c +struct sockaddr_in6 server_addr; + +server_addr.sin6_family = AF_INET6; +server_addr.sin6_addr = in6addr_any; +server_addr.sin6_port = htons(PORT); + +int s = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP); +bind(s, (struct sockaddr*)&server_addr, sizeof(server_addr)); +int rc = recvfrom(s, buf, len, 0, client_addr, addr_len); +``` + +> :warning: If using LwIP's Raw API, be careful to separate message receipt +> from further communications. Raw API callbacks are serviced by the NimBLE +> event handler, which means that trying to send data in a callback can and +> will deadlock as the event handler waits for a BLE unstalled event that will +> never arrive. diff --git a/examples/echo/README.md b/components/6lowpan_ble/examples/echo/README.md similarity index 100% rename from examples/echo/README.md rename to components/6lowpan_ble/examples/echo/README.md diff --git a/examples/echo/client/CMakeLists.txt b/components/6lowpan_ble/examples/echo/client/CMakeLists.txt similarity index 100% rename from examples/echo/client/CMakeLists.txt rename to components/6lowpan_ble/examples/echo/client/CMakeLists.txt diff --git a/examples/echo/client/main/CMakeLists.txt b/components/6lowpan_ble/examples/echo/client/main/CMakeLists.txt similarity index 100% rename from examples/echo/client/main/CMakeLists.txt rename to components/6lowpan_ble/examples/echo/client/main/CMakeLists.txt diff --git a/examples/echo/client/main/main.c b/components/6lowpan_ble/examples/echo/client/main/main.c similarity index 84% rename from examples/echo/client/main/main.c rename to components/6lowpan_ble/examples/echo/client/main/main.c index 60e132408b..15a6363989 100644 --- a/examples/echo/client/main/main.c +++ b/components/6lowpan_ble/examples/echo/client/main/main.c @@ -1,4 +1,7 @@ -/* Copyright 2024 Tenera Care +/* + * SPDX-FileCopyrightText: 2024 Tenera Care + * + * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -29,7 +32,7 @@ #include #include -static const char* TAG = "main"; +static const char *TAG = "main"; static uint8_t own_addr_type; struct sockaddr_in6 dest_addr; @@ -38,10 +41,9 @@ struct sockaddr_in6 dest_addr; static void do_advertise(); // forward declaration -static int on_gap_event(struct ble_gap_event* event, void* arg) +static int on_gap_event(struct ble_gap_event *event, void *arg) { - switch (event->type) - { + switch (event->type) { case BLE_GAP_EVENT_CONNECT: // A new connection was established or a connection attempt failed. ESP_LOGI( @@ -51,13 +53,10 @@ static int on_gap_event(struct ble_gap_event* event, void* arg) event->connect.status ); - if (event->connect.status != 0) - { + if (event->connect.status != 0) { // Connection failed; resume advertising. do_advertise(); - } - else - { + } else { // We've had a peer connect to us! We'll store their address in `dest_addr` so the // `udp_task` function below can send messages to the correct destination. struct ble_gap_conn_desc desc; @@ -102,7 +101,7 @@ static void do_advertise() { struct ble_gap_adv_params adv_params; struct ble_hs_adv_fields fields; - const char* name; + const char *name; int rc; memset(&fields, 0, sizeof fields); @@ -111,18 +110,19 @@ static void do_advertise() fields.tx_pwr_lvl_is_present = 1; fields.tx_pwr_lvl = BLE_HS_ADV_TX_PWR_LVL_AUTO; name = ble_svc_gap_device_name(); - fields.name = (uint8_t*)name; + fields.name = (uint8_t *)name; fields.name_len = strlen(name); fields.name_is_complete = 1; // Advertise support for the Internet Protocol Support Services (IPSS). - fields.uuids16 = (ble_uuid16_t[]) {BLE_UUID16_INIT(LOWPAN6_BLE_SERVICE_UUID_IPSS)}; + fields.uuids16 = (ble_uuid16_t[]) { + BLE_UUID16_INIT(LOWPAN6_BLE_SERVICE_UUID_IPSS) + }; fields.num_uuids16 = 1; fields.uuids16_is_complete = 1; rc = ble_gap_adv_set_fields(&fields); - if (rc != 0) - { + if (rc != 0) { ESP_LOGE(TAG, "Error setting advertisement data; rc=%d\n", rc); return; } @@ -132,8 +132,7 @@ static void do_advertise() adv_params.conn_mode = BLE_GAP_CONN_MODE_UND; adv_params.disc_mode = BLE_GAP_DISC_MODE_GEN; rc = ble_gap_adv_start(own_addr_type, NULL, BLE_HS_FOREVER, &adv_params, on_gap_event, NULL); - if (rc != 0) - { + if (rc != 0) { ESP_LOGE(TAG, "Error enabling advertisement; rc=%d\n", rc); return; } @@ -147,14 +146,12 @@ static void on_reset(int reason) static void on_sync() { int rc = ble_hs_util_ensure_addr(0); - if (rc != 0) - { + if (rc != 0) { ESP_ERROR_CHECK(ESP_FAIL); } rc = ble_hs_id_infer_auto(0, &own_addr_type); - if (rc != 0) - { + if (rc != 0) { ESP_LOGE(TAG, "Failed to determine address type; rc=%d", rc); return; } @@ -162,7 +159,7 @@ static void on_sync() do_advertise(); } -void nimble_task(void* params) +void nimble_task(void *params) { ESP_LOGI(TAG, "BLE host task started"); @@ -170,7 +167,7 @@ void nimble_task(void* params) nimble_port_freertos_deinit(); } -void udp_task(esp_netif_t* lowpan6_netif) +void udp_task(esp_netif_t *lowpan6_netif) { char rx_buffer[128]; @@ -178,8 +175,7 @@ void udp_task(esp_netif_t* lowpan6_netif) // would be to add a `lowpan6_ble` event for "netif up" that we can subscribe to in our // `lowpan6_ble_create_server` callback. Not currently implemented though so for the sake of // this example... - while (!esp_netif_is_netif_up(lowpan6_netif)) - { + while (!esp_netif_is_netif_up(lowpan6_netif)) { ESP_LOGI(TAG, "netif not up, waiting..."); vTaskDelay(pdMS_TO_TICKS(1000)); } @@ -194,8 +190,7 @@ void udp_task(esp_netif_t* lowpan6_netif) dest_addr.sin6_scope_id = esp_netif_get_netif_impl_index(lowpan6_netif); int sock = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP); - if (sock < 0) - { + if (sock < 0) { ESP_LOGE(TAG, "Failed to create socket; errno=%d", errno); return; } @@ -205,15 +200,13 @@ void udp_task(esp_netif_t* lowpan6_netif) struct timeval tv; tv.tv_sec = 2; tv.tv_usec = 0; - if (setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0) - { + if (setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0) { ESP_LOGE(TAG, "Failed to set socket timeout"); return; } - const char* payload = "hello it's me!!!"; - while (1) - { + const char *payload = "hello it's me!!!"; + while (1) { char addr_str[INET6_ADDRSTRLEN]; inet_ntop(AF_INET6, &dest_addr.sin6_addr, addr_str, INET6_ADDRSTRLEN); ESP_LOGI(TAG, "sending to %s", addr_str); @@ -221,15 +214,14 @@ void udp_task(esp_netif_t* lowpan6_netif) // Fire a message over to the dest_addr. Note that the `sin6_addr` for this gets set in our // GAP connect callback. int err = sendto( - sock, - payload, - strlen(payload), - 0, - (struct sockaddr*)&dest_addr, - sizeof(dest_addr) - ); - if (err < 0) - { + sock, + payload, + strlen(payload), + 0, + (struct sockaddr *)&dest_addr, + sizeof(dest_addr) + ); + if (err < 0) { ESP_LOGE(TAG, "Failed to send payload; errno=%d", errno); break; } @@ -238,27 +230,21 @@ void udp_task(esp_netif_t* lowpan6_netif) struct sockaddr_in6 recv_addr; socklen_t recv_addr_len = sizeof(recv_addr); int len = recvfrom( - sock, - rx_buffer, - sizeof(rx_buffer) - 1, - 0, - (struct sockaddr*)&recv_addr, - &recv_addr_len - ); - if (len < 0) - { - if (errno == EAGAIN) - { + sock, + rx_buffer, + sizeof(rx_buffer) - 1, + 0, + (struct sockaddr *)&recv_addr, + &recv_addr_len + ); + if (len < 0) { + if (errno == EAGAIN) { ESP_LOGD(TAG, "Receive timed out"); - } - else - { + } else { ESP_LOGE(TAG, "Failed to receive from socket; errno=%d", errno); break; } - } - else - { + } else { rx_buffer[len] = 0; // null terminate whatever we got ESP_LOGI(TAG, "Received %d bytes: `%s`", len, rx_buffer); } @@ -266,8 +252,7 @@ void udp_task(esp_netif_t* lowpan6_netif) vTaskDelay(pdMS_TO_TICKS(2000)); } - if (sock != -1) - { + if (sock != -1) { shutdown(sock, 0); close(sock); } @@ -276,8 +261,7 @@ void udp_task(esp_netif_t* lowpan6_netif) void app_main() { esp_err_t err = nvs_flash_init(); - if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND) - { + if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND) { ESP_ERROR_CHECK(nvs_flash_erase()); err = nvs_flash_init(); } @@ -295,8 +279,7 @@ void app_main() ble_hs_cfg.store_status_cb = ble_store_util_status_rr; int rc = ble_svc_gap_device_name_set("l6ble-client"); - if (rc != 0) - { + if (rc != 0) { ESP_LOGE(TAG, "Failed to set GAP device name; rc=%d", rc); return; } @@ -312,11 +295,10 @@ void app_main() .stack = netstack_default_lowpan6_ble, }; - esp_netif_t* lowpan6_ble_netif = esp_netif_new(&cfg); + esp_netif_t *lowpan6_ble_netif = esp_netif_new(&cfg); lowpan6_ble_driver_handle lowpan6_ble_driver = lowpan6_ble_create(); - if (lowpan6_ble_driver != NULL) - { + if (lowpan6_ble_driver != NULL) { ESP_ERROR_CHECK(esp_netif_attach(lowpan6_ble_netif, lowpan6_ble_driver)); } diff --git a/examples/echo/client/sdkconfig b/components/6lowpan_ble/examples/echo/client/sdkconfig similarity index 100% rename from examples/echo/client/sdkconfig rename to components/6lowpan_ble/examples/echo/client/sdkconfig diff --git a/examples/echo/server/CMakeLists.txt b/components/6lowpan_ble/examples/echo/server/CMakeLists.txt similarity index 100% rename from examples/echo/server/CMakeLists.txt rename to components/6lowpan_ble/examples/echo/server/CMakeLists.txt diff --git a/examples/echo/server/main/CMakeLists.txt b/components/6lowpan_ble/examples/echo/server/main/CMakeLists.txt similarity index 100% rename from examples/echo/server/main/CMakeLists.txt rename to components/6lowpan_ble/examples/echo/server/main/CMakeLists.txt diff --git a/examples/echo/server/main/main.c b/components/6lowpan_ble/examples/echo/server/main/main.c similarity index 79% rename from examples/echo/server/main/main.c rename to components/6lowpan_ble/examples/echo/server/main/main.c index a828ef728b..4b31e7c8d2 100644 --- a/examples/echo/server/main/main.c +++ b/components/6lowpan_ble/examples/echo/server/main/main.c @@ -1,4 +1,7 @@ -/* Copyright 2024 Tenera Care +/* + * SPDX-FileCopyrightText: 2024 Tenera Care + * + * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -35,21 +38,18 @@ //! What port we'll listen on. #define PORT 1234 -static const char* TAG = "main"; +static const char *TAG = "main"; static bool do_scan(); -static int on_gap_event(struct ble_gap_event* event, void* arg); +static int on_gap_event(struct ble_gap_event *event, void *arg); static lowpan6_ble_driver_handle s_l6ble_handle; -static inline int on_gap_connected(struct ble_gap_event* event) +static inline int on_gap_connected(struct ble_gap_event *event) { - if (event->connect.status == 0) - { + if (event->connect.status == 0) { ESP_LOGI(TAG, "BLE GAP connection established"); - } - else - { + } else { ESP_LOGE(TAG, "BLE GAP connection failed; status=%d", event->connect.status); do_scan(); } @@ -57,7 +57,7 @@ static inline int on_gap_connected(struct ble_gap_event* event) return 0; } -static inline int on_gap_disconnected(struct ble_gap_event* event) +static inline int on_gap_disconnected(struct ble_gap_event *event) { ESP_LOGI(TAG, "BLE GAP connection disconnected; reason=%d", event->disconnect.reason); @@ -68,12 +68,11 @@ static inline int on_gap_disconnected(struct ble_gap_event* event) static void on_lowpan6_ble_event( lowpan6_ble_driver_handle handle, - struct lowpan6_ble_event* event, - void* userdata + struct lowpan6_ble_event *event, + void *userdata ) { - switch (event->type) - { + switch (event->type) { case LOWPAN6_BLE_EVENT_GAP_CONNECTED: on_gap_connected(event->gap_connected.event); break; @@ -84,22 +83,19 @@ static void on_lowpan6_ble_event( } //! On discover, connect to _any_ device that advertises IPSS support. -static inline int on_gap_event_discovery(struct ble_gap_event* event) +static inline int on_gap_event_discovery(struct ble_gap_event *event) { struct ble_hs_adv_fields fields; int rc = ble_hs_adv_parse_fields(&fields, event->disc.data, event->disc.length_data); - if (rc != 0) - { + if (rc != 0) { ESP_LOGE(TAG, "Failed to parse advertisement fields; rc=%d", rc); return 0; } - if (lowpan6_ble_connectable(&event->disc)) - { + if (lowpan6_ble_connectable(&event->disc)) { // Cancel the scan so we can use the BLE device for connecting rc = ble_gap_disc_cancel(); - if (rc != 0 && rc != BLE_HS_EALREADY) - { + if (rc != 0 && rc != BLE_HS_EALREADY) { ESP_LOGE(TAG, "Failed to cancel scan; rc=%d", rc); return rc; } @@ -108,14 +104,13 @@ static inline int on_gap_event_discovery(struct ble_gap_event* event) // lowpan6 ble events. Note that the `lowpan6_ble` driver will replace the GAP event // callback in NimBLE here! esp_err_t err = lowpan6_ble_connect( - s_l6ble_handle, - &event->disc.addr, - BLE_CONNECT_TIMEOUT, - on_lowpan6_ble_event, - NULL - ); - if (err != ESP_OK) - { + s_l6ble_handle, + &event->disc.addr, + BLE_CONNECT_TIMEOUT, + on_lowpan6_ble_event, + NULL + ); + if (err != ESP_OK) { ESP_LOGE(TAG, "Failed to lowpan6_ble_connect; err=%d", err); } } @@ -123,10 +118,9 @@ static inline int on_gap_event_discovery(struct ble_gap_event* event) return 0; } -static int on_gap_event(struct ble_gap_event* event, void* arg) +static int on_gap_event(struct ble_gap_event *event, void *arg) { - switch (event->type) - { + switch (event->type) { case BLE_GAP_EVENT_DISC: return on_gap_event_discovery(event); @@ -142,8 +136,7 @@ static bool do_scan() { uint8_t own_addr_type; int rc = ble_hs_id_infer_auto(0, &own_addr_type); - if (rc != 0) - { + if (rc != 0) { ESP_LOGE(TAG, "Failed to automatically infer address type; rc=%d", rc); return false; } @@ -160,8 +153,7 @@ static bool do_scan() // Start discovery and configure `on_gap_event` as our event callback. We'll use this to // initiate a lowpan6_ble connection once we've found the peer we want to connect to. rc = ble_gap_disc(own_addr_type, BLE_HS_FOREVER, &disc_params, on_gap_event, NULL); - if (rc != 0) - { + if (rc != 0) { ESP_LOGE(TAG, "Failed to start GAP discovery; rc=%d", rc); return false; } @@ -172,8 +164,7 @@ static bool do_scan() void on_sync() { int rc = ble_hs_util_ensure_addr(0); - if (rc != 0) - { + if (rc != 0) { ESP_LOGE(TAG, "Failed to ensure addr"); return; } @@ -186,7 +177,7 @@ void on_reset(int reason) ESP_LOGI(TAG, "Resetting state; reason=%d", reason); } -void nimble_host_task(void* param) +void nimble_host_task(void *param) { ESP_LOGI(TAG, "BLE host task started"); nimble_port_run(); @@ -203,14 +194,12 @@ void udp_task() server_addr.sin6_port = htons(PORT); int s = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP); - if (s < 0) - { + if (s < 0) { ESP_LOGE(TAG, "failed to create socket; rc=%d", s); return; } - if (bind(s, (struct sockaddr*)&server_addr, sizeof(server_addr)) == -1) - { + if (bind(s, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1) { ESP_LOGE(TAG, "failed to bind address"); close(s); return; @@ -220,8 +209,7 @@ void udp_task() struct timeval tv; tv.tv_sec = 0; tv.tv_usec = 0; - if (setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0) - { + if (setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0) { ESP_LOGE(TAG, "failed to clear socket recv timeout"); return; } @@ -231,22 +219,20 @@ void udp_task() // These buffers are hard-code sized to match the buffers in the corresponding client. uint8_t rx_buffer[128]; uint8_t tx_buffer[192]; // A bit bigger to fit the extra characters we add to responses. - while (1) - { + while (1) { ESP_LOGI(TAG, "waiting to receive..."); struct sockaddr_in6 recv_addr; socklen_t recv_addr_len = sizeof(recv_addr); int len = recvfrom( - s, - rx_buffer, - sizeof(rx_buffer), - 0, - (struct sockaddr*)&recv_addr, - &recv_addr_len - ); - if (len < 0) - { + s, + rx_buffer, + sizeof(rx_buffer), + 0, + (struct sockaddr *)&recv_addr, + &recv_addr_len + ); + if (len < 0) { ESP_LOGE(TAG, "Failed to receive from socket; errno=%d", errno); break; } @@ -266,19 +252,18 @@ void udp_task() ); // Prepare our response (prepend their message with `echo: ` - snprintf((char*)tx_buffer, 192, "echo: %s", rx_buffer); + snprintf((char *)tx_buffer, 192, "echo: %s", rx_buffer); // Respond! int rc = sendto( - s, - tx_buffer, - strlen((char*)tx_buffer), - 0, - (struct sockaddr*)&recv_addr, - recv_addr_len - ); - if (rc < 0) - { + s, + tx_buffer, + strlen((char *)tx_buffer), + 0, + (struct sockaddr *)&recv_addr, + recv_addr_len + ); + if (rc < 0) { ESP_LOGE(TAG, "Failed to send to socket; errno=%d", errno); } } @@ -287,8 +272,7 @@ void udp_task() void app_main() { esp_err_t err = nvs_flash_init(); - if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND) - { + if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND) { ESP_ERROR_CHECK(nvs_flash_erase()); err = nvs_flash_init(); } @@ -306,8 +290,7 @@ void app_main() ble_hs_cfg.store_status_cb = ble_store_util_status_rr; int rc = ble_svc_gap_device_name_set("l6ble-server"); - if (rc != 0) - { + if (rc != 0) { ESP_LOGE(TAG, "Failed to set GAP device name; rc=%d", rc); return; } @@ -323,11 +306,10 @@ void app_main() .stack = netstack_default_lowpan6_ble, }; - esp_netif_t* lowpan6_ble_netif = esp_netif_new(&cfg); + esp_netif_t *lowpan6_ble_netif = esp_netif_new(&cfg); s_l6ble_handle = lowpan6_ble_create(); - if (s_l6ble_handle != NULL) - { + if (s_l6ble_handle != NULL) { ESP_ERROR_CHECK(esp_netif_attach(lowpan6_ble_netif, s_l6ble_handle)); } diff --git a/examples/echo/server/sdkconfig b/components/6lowpan_ble/examples/echo/server/sdkconfig similarity index 100% rename from examples/echo/server/sdkconfig rename to components/6lowpan_ble/examples/echo/server/sdkconfig diff --git a/include/lowpan6_ble.h b/components/6lowpan_ble/include/lowpan6_ble.h similarity index 91% rename from include/lowpan6_ble.h rename to components/6lowpan_ble/include/lowpan6_ble.h index 060d38a2d5..9caebe5784 100644 --- a/include/lowpan6_ble.h +++ b/components/6lowpan_ble/include/lowpan6_ble.h @@ -1,4 +1,7 @@ -/* Copyright 2024 Tenera Care +/* + * SPDX-FileCopyrightText: 2024 Tenera Care + * + * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,14 +28,14 @@ #include #if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(4, 4, 0) - // Add missing includes to esp_netif_types.h - // https://github.com/espressif/esp-idf/commit/822129e234aaedf86e76fe92ab9b49c5f0a612e0 - #include "esp_err.h" - #include "esp_event_base.h" - #include "esp_netif_ip_addr.h" +// Add missing includes to esp_netif_types.h +// https://github.com/espressif/esp-idf/commit/822129e234aaedf86e76fe92ab9b49c5f0a612e0 +#include "esp_err.h" +#include "esp_event_base.h" +#include "esp_netif_ip_addr.h" - #include - #include +#include +#include #endif #include "esp_netif_types.h" @@ -100,39 +103,34 @@ #endif // clang-format on -enum lowpan6_ble_event_type -{ +enum lowpan6_ble_event_type { LOWPAN6_BLE_EVENT_GAP_CONNECTED, LOWPAN6_BLE_EVENT_GAP_DISCONNECTED }; //! Event struct for LoWPAN6 BLE events. -struct lowpan6_ble_event -{ +struct lowpan6_ble_event { //! Discriminator for the event data included in this event. enum lowpan6_ble_event_type type; - union - { + union { //! Data available for type LOWPAN6_BLE_EVENT_GAP_CONNECTED. - struct - { + struct { //! The underlying GAP event. - struct ble_gap_event* event; + struct ble_gap_event *event; } gap_connected; //! Data available for type LOWPAN6_BLE_EVENT_GAP_DISCONNECTED. - struct - { + struct { //! The underlying GAP event. - struct ble_gap_event* event; + struct ble_gap_event *event; } gap_disconnected; }; }; -extern esp_netif_netstack_config_t* netstack_default_lowpan6_ble; +extern esp_netif_netstack_config_t *netstack_default_lowpan6_ble; -typedef struct lowpan6_ble_driver* lowpan6_ble_driver_handle; +typedef struct lowpan6_ble_driver *lowpan6_ble_driver_handle; /** A LoWPAN6 BLE event handler * @@ -142,8 +140,8 @@ typedef struct lowpan6_ble_driver* lowpan6_ble_driver_handle; */ typedef void (*lowpan6_ble_event_handler)( lowpan6_ble_driver_handle handle, - struct lowpan6_ble_event* event, - void* userdata + struct lowpan6_ble_event *event, + void *userdata ); /** Initialize the LoWPAN6 BLE module. @@ -221,7 +219,7 @@ esp_err_t lowpan6_ble_destroy(lowpan6_ble_driver_handle driver); * * @returns True if the device is connectable, False otherwise. */ -bool lowpan6_ble_connectable(struct ble_gap_disc_desc* disc); +bool lowpan6_ble_connectable(struct ble_gap_disc_desc *disc); /** Establish a LoWPAN6 BLE connection with the given BLE address. * @@ -271,10 +269,10 @@ bool lowpan6_ble_connectable(struct ble_gap_disc_desc* disc); */ esp_err_t lowpan6_ble_connect( lowpan6_ble_driver_handle handle, - ble_addr_t* addr, + ble_addr_t *addr, int32_t timeout_ms, lowpan6_ble_event_handler cb, - void* userdata + void *userdata ); /** Disconnect the given LoWPAN6 BLE connection. @@ -326,7 +324,7 @@ esp_err_t lowpan6_ble_disconnect(lowpan6_ble_driver_handle handle); esp_err_t lowpan6_ble_create_server( lowpan6_ble_driver_handle handle, lowpan6_ble_event_handler cb, - void* userdata + void *userdata ); /** Transform the given BLE address into a link-local IPv6 address. @@ -336,4 +334,4 @@ esp_err_t lowpan6_ble_create_server( * * @returns ESP_OK on success. */ -esp_err_t ble_addr_to_link_local(ble_addr_t* ble_addr, ip6_addr_t* ip_addr); +esp_err_t ble_addr_to_link_local(ble_addr_t *ble_addr, ip6_addr_t *ip_addr); diff --git a/src/debug_print_utils.c b/components/6lowpan_ble/src/debug_print_utils.c similarity index 86% rename from src/debug_print_utils.c rename to components/6lowpan_ble/src/debug_print_utils.c index 789a83f88b..88fdf14faa 100644 --- a/src/debug_print_utils.c +++ b/components/6lowpan_ble/src/debug_print_utils.c @@ -1,4 +1,7 @@ -/* Copyright 2024 Tenera Care +/* + * SPDX-FileCopyrightText: 2024 Tenera Care + * + * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,14 +18,13 @@ #include "debug_print_utils.h" -char* debug_print_ble_addr(ble_addr_t* addr) +char *debug_print_ble_addr(ble_addr_t *addr) { // 2 char per byte * 6 bytes + 5 colon + 1 null terminator // 12 + 5 + 1 == 18 static char addr_buf[18]; - if (addr != NULL) - { + if (addr != NULL) { // NimBLE addresses are stored in reverse order so we print these from index 5 to 0 snprintf( addr_buf, @@ -35,9 +37,7 @@ char* debug_print_ble_addr(ble_addr_t* addr) addr->val[1], addr->val[0] ); - } - else - { + } else { strcpy(addr_buf, "null"); } diff --git a/src/debug_print_utils.h b/components/6lowpan_ble/src/debug_print_utils.h similarity index 85% rename from src/debug_print_utils.h rename to components/6lowpan_ble/src/debug_print_utils.h index 791f53802b..86627944c0 100644 --- a/src/debug_print_utils.h +++ b/components/6lowpan_ble/src/debug_print_utils.h @@ -1,4 +1,7 @@ -/* Copyright 2024 Tenera Care +/* + * SPDX-FileCopyrightText: 2024 Tenera Care + * + * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -24,4 +27,4 @@ * * @param[in] addr The Bluetooth address to print. */ -char* debug_print_ble_addr(ble_addr_t* addr); +char *debug_print_ble_addr(ble_addr_t *addr); diff --git a/src/lowpan6_ble.c b/components/6lowpan_ble/src/lowpan6_ble.c similarity index 80% rename from src/lowpan6_ble.c rename to components/6lowpan_ble/src/lowpan6_ble.c index 5f5e822809..ca323ad35e 100644 --- a/src/lowpan6_ble.c +++ b/components/6lowpan_ble/src/lowpan6_ble.c @@ -1,4 +1,7 @@ -/* Copyright 2024 Tenera Care +/* + * SPDX-FileCopyrightText: 2024 Tenera Care + * + * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -38,7 +41,7 @@ #define MBUF_MEMBLOCK_SIZE (MBUF_BUF_SIZE + MBUF_MEMBLOCK_OVERHEAD) #define MBUF_MEMPOOL_SIZE OS_MEMPOOL_SIZE(MBUF_NUM_MBUFS, MBUF_MEMBLOCK_SIZE) -static const char* TAG = "lowpan6_ble"; +static const char *TAG = "lowpan6_ble"; //! Pool of mbufs, shared by all the channels in this module. static struct os_mbuf_pool s_mbuf_pool; @@ -57,8 +60,7 @@ static EventGroupHandle_t s_lowpan6_event_group; * * This struct provides glue logic between esp_netif and the BLE channel used as a transport. */ -struct lowpan6_ble_driver -{ +struct lowpan6_ble_driver { // esp_netif driver base esp_netif_driver_base_t base; @@ -66,47 +68,44 @@ struct lowpan6_ble_driver uint16_t conn_handle; // Pointer to L2CAP channel used for LoWPAN6-BLE - struct ble_l2cap_chan* chan; + struct ble_l2cap_chan *chan; // (Optional) event handler provided by the user. lowpan6_ble_event_handler cb; // (Optional) event handler data provided by the user. - void* userdata; + void *userdata; }; -void user_notify(struct lowpan6_ble_driver* driver, struct lowpan6_ble_event* event) +void user_notify(struct lowpan6_ble_driver *driver, struct lowpan6_ble_event *event) { - if (driver && driver->cb && event) - { + if (driver && driver->cb && event) { driver->cb(driver, event, driver->userdata); } } -static inline int set_recv_ready(struct ble_l2cap_chan* chan) +static inline int set_recv_ready(struct ble_l2cap_chan *chan) { - struct os_mbuf* next = os_mbuf_get_pkthdr(&s_mbuf_pool, 0); + struct os_mbuf *next = os_mbuf_get_pkthdr(&s_mbuf_pool, 0); int rc = ble_l2cap_recv_ready(chan, next); return rc; } -static int on_l2cap_event(struct ble_l2cap_event* event, void* arg) +static int on_l2cap_event(struct ble_l2cap_event *event, void *arg) { ESP_LOGD(TAG, "(%s) event->type=%d", __func__, event->type); - struct lowpan6_ble_driver* driver = (struct lowpan6_ble_driver*)arg; + struct lowpan6_ble_driver *driver = (struct lowpan6_ble_driver *)arg; int rc = 0; - switch (event->type) - { + switch (event->type) { case BLE_L2CAP_EVENT_COC_CONNECTED: driver->conn_handle = event->connect.conn_handle; driver->chan = event->connect.chan; struct ble_gap_conn_desc desc; rc = ble_gap_conn_find(event->connect.conn_handle, &desc); - if (rc != 0) - { + if (rc != 0) { ESP_LOGE( TAG, "(%s) could not find GAP conn with handle %d", @@ -137,8 +136,7 @@ static int on_l2cap_event(struct ble_l2cap_event* event, void* arg) // We'll do this after the user callback automatically. os_mbuf_free_chain(event->receive.sdu_rx); rc = set_recv_ready(event->receive.chan); - if (rc != 0) - { + if (rc != 0) { ESP_LOGE(TAG, "(%s) couldn't set up next recv ready; rc=%d", __func__, rc); } @@ -146,8 +144,7 @@ static int on_l2cap_event(struct ble_l2cap_event* event, void* arg) case BLE_L2CAP_EVENT_COC_ACCEPT: rc = set_recv_ready(event->accept.chan); - if (rc != 0) - { + if (rc != 0) { ESP_LOGE(TAG, "(%s) couldn't set up next recv ready; rc=%d", __func__, rc); } break; @@ -172,18 +169,16 @@ static int on_l2cap_event(struct ble_l2cap_event* event, void* arg) } static inline int -on_gap_event_connect(struct lowpan6_ble_driver* driver, struct ble_gap_event* event) +on_gap_event_connect(struct lowpan6_ble_driver *driver, struct ble_gap_event *event) { - if (event->connect.status != 0) - { + if (event->connect.status != 0) { ESP_LOGE(TAG, "(%s) connection failed; status=%d", __func__, event->connect.status); return ESP_FAIL; } struct ble_gap_conn_desc desc; int rc = ble_gap_conn_find(event->connect.conn_handle, &desc); - if (rc != 0) - { + if (rc != 0) { ESP_LOGE( TAG, "(%s) connection not found; conn_handle=%d", @@ -200,24 +195,22 @@ on_gap_event_connect(struct lowpan6_ble_driver* driver, struct ble_gap_event* ev event->connect.conn_handle ); - struct os_mbuf* sdu_rx = os_mbuf_get_pkthdr(&s_mbuf_pool, 0); - if (sdu_rx == NULL) - { + struct os_mbuf *sdu_rx = os_mbuf_get_pkthdr(&s_mbuf_pool, 0); + if (sdu_rx == NULL) { ESP_LOGE(TAG, "(%s) cannot allocate memory for connect mbuf", __func__); return ESP_ERR_NO_MEM; } rc = ble_l2cap_connect( - event->connect.conn_handle, - LOWPAN6_BLE_IPSP_PSM, - LOWPAN6_BLE_IPSP_MTU, - sdu_rx, - on_l2cap_event, - driver - ); - - if (rc != 0) - { + event->connect.conn_handle, + LOWPAN6_BLE_IPSP_PSM, + LOWPAN6_BLE_IPSP_MTU, + sdu_rx, + on_l2cap_event, + driver + ); + + if (rc != 0) { ESP_LOGE(TAG, "(%s) failed to l2cap connect; rc=%d", __func__, rc); return rc; } @@ -226,23 +219,22 @@ on_gap_event_connect(struct lowpan6_ble_driver* driver, struct ble_gap_event* ev } static inline int -on_gap_event_disconnect(struct lowpan6_ble_driver* driver, struct ble_gap_event* event) +on_gap_event_disconnect(struct lowpan6_ble_driver *driver, struct ble_gap_event *event) { ESP_LOGD(TAG, "(%s) disconnected; reason=%d", __func__, event->disconnect.reason); return 0; } -static int on_gap_event(struct ble_gap_event* event, void* arg) +static int on_gap_event(struct ble_gap_event *event, void *arg) { - struct lowpan6_ble_driver* driver = (struct lowpan6_ble_driver*)arg; + struct lowpan6_ble_driver *driver = (struct lowpan6_ble_driver *)arg; ESP_LOGD(TAG, "(%s) GAP event; event->type=%d", __func__, event->type); int rc = 0; struct lowpan6_ble_event out_event; - switch (event->type) - { + switch (event->type) { case BLE_GAP_EVENT_CONNECT: rc = on_gap_event_connect(driver, event); out_event.type = LOWPAN6_BLE_EVENT_GAP_CONNECTED; @@ -265,33 +257,29 @@ static int on_gap_event(struct ble_gap_event* event, void* arg) return rc; } -static void lowpan6_ble_free_rx_buffer(void* h, void* buffer) +static void lowpan6_ble_free_rx_buffer(void *h, void *buffer) { int rc = os_mbuf_free_chain(buffer); - if (rc != 0) - { + if (rc != 0) { ESP_LOGW(TAG, "(%s) failed to free os_mbuf; om=%p rc=%d", __func__, buffer, rc); } } -static esp_err_t lowpan6_ble_transmit(void* h, void* buffer, size_t len) +static esp_err_t lowpan6_ble_transmit(void *h, void *buffer, size_t len) { - struct lowpan6_ble_driver* driver = (struct lowpan6_ble_driver*)h; - if (driver == NULL || driver->chan == NULL) - { + struct lowpan6_ble_driver *driver = (struct lowpan6_ble_driver *)h; + if (driver == NULL || driver->chan == NULL) { return ESP_ERR_INVALID_STATE; } - struct os_mbuf* sdu_tx = os_mbuf_get_pkthdr(&s_mbuf_pool, 0); - if (sdu_tx == NULL) - { + struct os_mbuf *sdu_tx = os_mbuf_get_pkthdr(&s_mbuf_pool, 0); + if (sdu_tx == NULL) { ESP_LOGE(TAG, "(%s) cannot allocate memory for output mbuf", __func__); return ESP_ERR_NO_MEM; } int rc = os_mbuf_append(sdu_tx, buffer, len); - if (rc != 0) - { + if (rc != 0) { ESP_LOGE(TAG, "(%s) could not append data to mbuf; rc=%d", __func__, rc); os_mbuf_free_chain(sdu_tx); return ESP_FAIL; @@ -303,12 +291,10 @@ static esp_err_t lowpan6_ble_transmit(void* h, void* buffer, size_t len) // If, however, there's already a stalled transmission for some OTHER message, we'll get // BLE_HS_EBUSY. In _this_ case, we'll wait for the unstalled event and try again in case the // previous operation completed. - do - { + do { ESP_LOGD(TAG, "(%s) sending; sdu_tx=%p", __func__, sdu_tx); rc = ble_l2cap_send(driver->chan, sdu_tx); - if (rc == BLE_HS_EBUSY) - { + if (rc == BLE_HS_EBUSY) { ESP_LOGD(TAG, "(%s) waiting for unstall; sdu_tx=%p", __func__, sdu_tx); xEventGroupWaitBits( s_lowpan6_event_group, @@ -317,9 +303,7 @@ static esp_err_t lowpan6_ble_transmit(void* h, void* buffer, size_t len) pdTRUE, portMAX_DELAY ); - } - else if (rc != 0 && rc != BLE_HS_ESTALLED) - { + } else if (rc != 0 && rc != BLE_HS_ESTALLED) { ESP_LOGW(TAG, "(%s) failed to send data via ipsp; rc=%d", __func__, rc); os_mbuf_free_chain(sdu_tx); return ESP_FAIL; @@ -329,9 +313,9 @@ static esp_err_t lowpan6_ble_transmit(void* h, void* buffer, size_t len) return ESP_OK; } -static esp_err_t lowpan6_ble_post_attach(esp_netif_t* esp_netif, void* args) +static esp_err_t lowpan6_ble_post_attach(esp_netif_t *esp_netif, void *args) { - struct lowpan6_ble_driver* driver = (struct lowpan6_ble_driver*)args; + struct lowpan6_ble_driver *driver = (struct lowpan6_ble_driver *)args; ESP_LOGD(TAG, "(%s) esp_netif=%p args=%p", __func__, esp_netif, args); @@ -353,15 +337,13 @@ esp_err_t lowpan6_ble_init() { int rc = os_mempool_init(&s_mempool, MBUF_NUM_MBUFS, MBUF_MEMBLOCK_SIZE, s_membuf, "lowpan6_ble"); - if (rc != 0) - { + if (rc != 0) { ESP_LOGE(TAG, "(%s) failed to initialize mempool; rc=%d", __func__, rc); return ESP_FAIL; } rc = os_mbuf_pool_init(&s_mbuf_pool, &s_mempool, MBUF_MEMBLOCK_SIZE, MBUF_NUM_MBUFS); - if (rc != 0) - { + if (rc != 0) { ESP_LOGE(TAG, "(%s) failed to initialize mbuf pool; rc=%d", __func__, rc); os_mempool_clear(&s_mempool); return ESP_FAIL; @@ -371,8 +353,7 @@ esp_err_t lowpan6_ble_init() // we should _never_ hit this since we're initializing from a static event group. Still, for // completeness' sake... - if (s_lowpan6_event_group == NULL) - { + if (s_lowpan6_event_group == NULL) { ESP_LOGE(TAG, "(%s) failed to initialize event group", __func__); return ESP_FAIL; } @@ -384,9 +365,8 @@ lowpan6_ble_driver_handle lowpan6_ble_create() { ESP_LOGI(TAG, "(%s) creating lowpan6_ble driver", __func__); - struct lowpan6_ble_driver* driver = calloc(1, sizeof(struct lowpan6_ble_driver)); - if (driver == NULL) - { + struct lowpan6_ble_driver *driver = calloc(1, sizeof(struct lowpan6_ble_driver)); + if (driver == NULL) { ESP_LOGE(TAG, "(%s) failed to allocate memory for lowpan6_ble driver", __func__); return NULL; } @@ -404,7 +384,7 @@ esp_err_t lowpan6_ble_destroy(lowpan6_ble_driver_handle driver) return ESP_OK; } -bool lowpan6_ble_connectable(struct ble_gap_disc_desc* disc) +bool lowpan6_ble_connectable(struct ble_gap_disc_desc *disc) { // Must advertise one of the following Protocol Data Units (PDUs) in order to be // "connectable". Other PDUs mean it's scannable or not connectable. The Directed @@ -412,8 +392,7 @@ bool lowpan6_ble_connectable(struct ble_gap_disc_desc* disc) // connection requests from a peer device. Theoretically we'd maybe want to confirm that we // are that peer device instead of just saying "yeah it's connectable". if (disc->event_type != BLE_HCI_ADV_RPT_EVTYPE_ADV_IND && - disc->event_type != BLE_HCI_ADV_RPT_EVTYPE_DIR_IND) - { + disc->event_type != BLE_HCI_ADV_RPT_EVTYPE_DIR_IND) { return false; } @@ -421,16 +400,13 @@ bool lowpan6_ble_connectable(struct ble_gap_disc_desc* disc) // Service to be lowpan6_ble compatible. struct ble_hs_adv_fields fields; int rc = ble_hs_adv_parse_fields(&fields, disc->data, disc->length_data); - if (rc != 0) - { + if (rc != 0) { ESP_LOGE(TAG, "(%s) failed to parse fields; rc=%d", __func__, rc); return false; } - for (int i = 0; i < fields.num_uuids16; ++i) - { - if (ble_uuid_u16(&fields.uuids16[i].u) == LOWPAN6_BLE_SERVICE_UUID_IPSS) - { + for (int i = 0; i < fields.num_uuids16; ++i) { + if (ble_uuid_u16(&fields.uuids16[i].u) == LOWPAN6_BLE_SERVICE_UUID_IPSS) { return true; } } @@ -440,40 +416,34 @@ bool lowpan6_ble_connectable(struct ble_gap_disc_desc* disc) esp_err_t lowpan6_ble_connect( lowpan6_ble_driver_handle handle, - ble_addr_t* addr, + ble_addr_t *addr, int32_t timeout_ms, lowpan6_ble_event_handler cb, - void* userdata + void *userdata ) { - struct lowpan6_ble_driver* driver = (struct lowpan6_ble_driver*)handle; - if (driver == NULL) - { + struct lowpan6_ble_driver *driver = (struct lowpan6_ble_driver *)handle; + if (driver == NULL) { return ESP_ERR_INVALID_ARG; } - if (cb) - { + if (cb) { driver->cb = cb; driver->userdata = userdata; - } - else - { + } else { driver->cb = NULL; driver->userdata = NULL; } uint8_t own_addr_type; int rc = ble_hs_id_infer_auto(0, &own_addr_type); - if (rc != 0) - { + if (rc != 0) { ESP_LOGE(TAG, "(%s) failed to automatically infer address type; rc=%d", __func__, rc); return ESP_FAIL; } rc = ble_gap_connect(own_addr_type, addr, timeout_ms, NULL, on_gap_event, handle); - if (rc != 0) - { + if (rc != 0) { ESP_LOGE( TAG, "(%s) failed to connect to device; addr_type=%d addr=%s rc=%d", @@ -490,36 +460,27 @@ esp_err_t lowpan6_ble_connect( esp_err_t lowpan6_ble_disconnect(lowpan6_ble_driver_handle handle) { - struct lowpan6_ble_driver* driver = (struct lowpan6_ble_driver*)handle; - if (driver == NULL) - { + struct lowpan6_ble_driver *driver = (struct lowpan6_ble_driver *)handle; + if (driver == NULL) { return ESP_ERR_INVALID_ARG; } - if (driver->chan != NULL) - { + if (driver->chan != NULL) { int rc = ble_l2cap_disconnect(driver->chan); - if (rc != 0 && rc != BLE_HS_EALREADY && rc != BLE_HS_ENOTCONN) - { + if (rc != 0 && rc != BLE_HS_EALREADY && rc != BLE_HS_ENOTCONN) { ESP_LOGW(TAG, "(%s) failed to l2cap disconnect; rc=%d", __func__, rc); // continue to try GAP disconnect anyways - } - else - { + } else { driver->chan = NULL; } } - if (driver->conn_handle != BLE_HS_CONN_HANDLE_NONE) - { + if (driver->conn_handle != BLE_HS_CONN_HANDLE_NONE) { int rc = ble_gap_terminate(driver->conn_handle, BLE_ERR_REM_USER_CONN_TERM); - if (rc != 0 && rc != BLE_HS_EALREADY && rc != BLE_HS_ENOTCONN) - { + if (rc != 0 && rc != BLE_HS_EALREADY && rc != BLE_HS_ENOTCONN) { ESP_LOGW(TAG, "(%s) failed to gap terminate; rc=%d", __func__, rc); return ESP_FAIL; - } - else - { + } else { driver->conn_handle = BLE_HS_CONN_HANDLE_NONE; } } @@ -530,22 +491,18 @@ esp_err_t lowpan6_ble_disconnect(lowpan6_ble_driver_handle handle) esp_err_t lowpan6_ble_create_server( lowpan6_ble_driver_handle handle, lowpan6_ble_event_handler cb, - void* userdata + void *userdata ) { - struct lowpan6_ble_driver* driver = (struct lowpan6_ble_driver*)handle; - if (driver == NULL) - { + struct lowpan6_ble_driver *driver = (struct lowpan6_ble_driver *)handle; + if (driver == NULL) { return ESP_ERR_INVALID_ARG; } - if (cb) - { + if (cb) { driver->cb = cb; driver->userdata = userdata; - } - else - { + } else { driver->cb = NULL; driver->userdata = NULL; } @@ -553,8 +510,7 @@ esp_err_t lowpan6_ble_create_server( int rc = ble_l2cap_create_server(LOWPAN6_BLE_IPSP_PSM, LOWPAN6_BLE_IPSP_MTU, on_l2cap_event, driver); - if (rc != 0) - { + if (rc != 0) { ESP_LOGE(TAG, "(%s) failed to create L2CAP server; rc=%d", __func__, rc); return ESP_FAIL; } @@ -562,10 +518,9 @@ esp_err_t lowpan6_ble_create_server( return ESP_OK; } -esp_err_t ble_addr_to_link_local(ble_addr_t* ble_addr, ip6_addr_t* ip_addr) +esp_err_t ble_addr_to_link_local(ble_addr_t *ble_addr, ip6_addr_t *ip_addr) { - if (ble_addr == NULL || ip_addr == NULL) - { + if (ble_addr == NULL || ip_addr == NULL) { return ESP_ERR_INVALID_ARG; } diff --git a/src/lowpan6_ble_netif.c b/components/6lowpan_ble/src/lowpan6_ble_netif.c similarity index 70% rename from src/lowpan6_ble_netif.c rename to components/6lowpan_ble/src/lowpan6_ble_netif.c index 9f33596245..d58f84151f 100644 --- a/src/lowpan6_ble_netif.c +++ b/components/6lowpan_ble/src/lowpan6_ble_netif.c @@ -1,4 +1,7 @@ -/* Copyright 2024 Tenera Care +/* + * SPDX-FileCopyrightText: 2024 Tenera Care + * + * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,8 +25,8 @@ #include "lwip/err.h" #include "netif/lowpan6_ble.h" -static err_t lowpan6_ble_netif_init(struct netif* netif); -static void lowpan6_ble_netif_input(void* h, void* buffer, size_t len, void* eb); +static err_t lowpan6_ble_netif_init(struct netif *netif); +static void lowpan6_ble_netif_input(void *h, void *buffer, size_t len, void *eb); // The esp_netif_netstack_config_t struct was not publically exposed until after v5 // If we're running a lower version, we'll define the struct ourselves like in the following @@ -32,50 +35,48 @@ static void lowpan6_ble_netif_input(void* h, void* buffer, size_t len, void* eb) #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0) // clang-format off - #include "lwip/esp_netif_net_stack.h" - const struct esp_netif_netstack_config s_netif_config_lowpan6_ble = { - .lwip = { - .init_fn = lowpan6_ble_netif_init, - .input_fn = lowpan6_ble_netif_input, - } - }; +#include "lwip/esp_netif_net_stack.h" +const struct esp_netif_netstack_config s_netif_config_lowpan6_ble = { + .lwip = { + .init_fn = lowpan6_ble_netif_init, + .input_fn = lowpan6_ble_netif_input, + } +}; // clang-format on #else // clang-format off - struct esp_netif_lwip_vanilla_config - { - err_t (*init_fn)(struct netif*); - void (*input_fn)(void* netif, void* buffer, size_t len, void* eb); - }; - - const struct esp_netif_lwip_vanilla_config s_netif_config_lowpan6_ble = { - .init_fn = lowpan6_ble_netif_init, - .input_fn = lowpan6_ble_netif_input, - }; +struct esp_netif_lwip_vanilla_config { + err_t (*init_fn)(struct netif *); + void (*input_fn)(void *netif, void *buffer, size_t len, void *eb); +}; + +const struct esp_netif_lwip_vanilla_config s_netif_config_lowpan6_ble = { + .init_fn = lowpan6_ble_netif_init, + .input_fn = lowpan6_ble_netif_input, +}; // clang-format on #endif -const esp_netif_netstack_config_t* netstack_default_lowpan6_ble = - (const esp_netif_netstack_config_t*)&s_netif_config_lowpan6_ble; +const esp_netif_netstack_config_t *netstack_default_lowpan6_ble = + (const esp_netif_netstack_config_t *) &s_netif_config_lowpan6_ble; -static const char* TAG = "lowpan6_ble_netif"; +static const char *TAG = "lowpan6_ble_netif"; -err_t lowpan6_ble_netif_linkoutput(struct netif* netif, struct pbuf* p) +err_t lowpan6_ble_netif_linkoutput(struct netif *netif, struct pbuf *p) { esp_err_t err = esp_netif_transmit(netif->state, p->payload, p->len); - if (err != ESP_OK) - { + if (err != ESP_OK) { return ERR_IF; } return ERR_OK; } -static err_t lowpan6_ble_netif_init(struct netif* netif) +static err_t lowpan6_ble_netif_init(struct netif *netif) { rfc7668_if_init(netif); netif->linkoutput = lowpan6_ble_netif_linkoutput; @@ -85,16 +86,15 @@ static err_t lowpan6_ble_netif_init(struct netif* netif) return ERR_OK; } -static void lowpan6_ble_netif_input(void* h, void* buffer, size_t len, void* eb) +static void lowpan6_ble_netif_input(void *h, void *buffer, size_t len, void *eb) { - struct netif* netif = (struct netif*)h; - struct os_mbuf* sdu_rx = (struct os_mbuf*)eb; + struct netif *netif = (struct netif *)h; + struct os_mbuf *sdu_rx = (struct os_mbuf *)eb; size_t rx_len = (size_t)OS_MBUF_PKTLEN(sdu_rx); - struct pbuf* p = pbuf_alloc(PBUF_RAW, rx_len, PBUF_POOL); - if (p == NULL) - { + struct pbuf *p = pbuf_alloc(PBUF_RAW, rx_len, PBUF_POOL); + if (p == NULL) { ESP_LOGE(TAG, "(%s) failed to allocate memory for pbuf", __func__); return; } @@ -103,8 +103,7 @@ static void lowpan6_ble_netif_input(void* h, void* buffer, size_t len, void* eb) // it into a format LwIP understands (i.e., to go from mbuf to pbuf). Better would be if the // pbuf just referred to data in the mbuf. Not sure if that's possible though. int rc = os_mbuf_copydata(sdu_rx, 0, rx_len, p->payload); - if (rc != 0) - { + if (rc != 0) { ESP_LOGE(TAG, "(%s) failed to copy mbuf into pbuf", __func__); pbuf_free(p); return; @@ -123,14 +122,13 @@ static void lowpan6_ble_netif_input(void* h, void* buffer, size_t len, void* eb) rfc7668_input(p, netif); } -void nimble_addr_to_eui64(ble_addr_t const* addr, uint8_t* eui64) +void nimble_addr_to_eui64(ble_addr_t const *addr, uint8_t *eui64) { // NimBLE stores addresses in _reverse_ order. We need to reverse these // before doing the EUI64 conversion, otherwise we get incorrect // addresses in our IPv6 headers. uint8_t addr_reversed[6]; - for (int i = 0; i < 6; ++i) - { + for (int i = 0; i < 6; ++i) { addr_reversed[i] = addr->val[6 - 1 - i]; } @@ -138,7 +136,7 @@ void nimble_addr_to_eui64(ble_addr_t const* addr, uint8_t* eui64) ble_addr_to_eui64(eui64, addr_reversed, is_public_addr); } -void ipv6_create_link_local_from_eui64(uint8_t const* eui64_addr, ip6_addr_t* dst) +void ipv6_create_link_local_from_eui64(uint8_t const *eui64_addr, ip6_addr_t *dst) { IP6_ADDR_PART(dst, 0, 0xFE, 0x80, 0x00, 0x00); IP6_ADDR_PART(dst, 1, 0x00, 0x00, 0x00, 0x00); @@ -146,7 +144,7 @@ void ipv6_create_link_local_from_eui64(uint8_t const* eui64_addr, ip6_addr_t* ds IP6_ADDR_PART(dst, 3, eui64_addr[4], eui64_addr[5], eui64_addr[6], eui64_addr[7]); } -static inline void configure_netif_addresses(struct netif* netif, ble_addr_t* addr, bool is_peer) +static inline void configure_netif_addresses(struct netif *netif, ble_addr_t *addr, bool is_peer) { ESP_LOGD( TAG, @@ -159,12 +157,9 @@ static inline void configure_netif_addresses(struct netif* netif, ble_addr_t* ad uint8_t eui64_addr[8]; nimble_addr_to_eui64(addr, eui64_addr); - if (is_peer) - { + if (is_peer) { rfc7668_set_peer_addr_eui64(netif, eui64_addr, sizeof(eui64_addr)); - } - else - { + } else { rfc7668_set_local_addr_eui64(netif, eui64_addr, sizeof(eui64_addr)); ip6_addr_t lladdr; @@ -184,11 +179,10 @@ static inline void configure_netif_addresses(struct netif* netif, ble_addr_t* ad } } -void lowpan6_ble_netif_up(esp_netif_t* esp_netif, ble_addr_t* peer_addr, ble_addr_t* our_addr) +void lowpan6_ble_netif_up(esp_netif_t *esp_netif, ble_addr_t *peer_addr, ble_addr_t *our_addr) { - struct netif* netif = esp_netif_get_netif_impl(esp_netif); - if (netif == NULL || peer_addr == NULL || our_addr == NULL) - { + struct netif *netif = esp_netif_get_netif_impl(esp_netif); + if (netif == NULL || peer_addr == NULL || our_addr == NULL) { ESP_LOGE(TAG, "(%s) invalid parameters", __func__); return; } @@ -202,11 +196,10 @@ void lowpan6_ble_netif_up(esp_netif_t* esp_netif, ble_addr_t* peer_addr, ble_add ESP_LOGD(TAG, "(%s) netif up; esp_netif=%p netif=%p", __func__, esp_netif, netif); } -void lowpan6_ble_netif_down(esp_netif_t* esp_netif) +void lowpan6_ble_netif_down(esp_netif_t *esp_netif) { - struct netif* netif = esp_netif_get_netif_impl(esp_netif); - if (netif == NULL) - { + struct netif *netif = esp_netif_get_netif_impl(esp_netif); + if (netif == NULL) { ESP_LOGE(TAG, "(%s) invalid parameters", __func__); return; } diff --git a/src/lowpan6_ble_netif.h b/components/6lowpan_ble/src/lowpan6_ble_netif.h similarity index 78% rename from src/lowpan6_ble_netif.h rename to components/6lowpan_ble/src/lowpan6_ble_netif.h index 5b41da947e..bf8df72a66 100644 --- a/src/lowpan6_ble_netif.h +++ b/components/6lowpan_ble/src/lowpan6_ble_netif.h @@ -1,4 +1,7 @@ -/* Copyright 2024 Tenera Care +/* + * SPDX-FileCopyrightText: 2024 Tenera Care + * + * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,14 +20,14 @@ #include "esp_idf_version.h" #if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(4, 4, 0) - // Add missing includes to esp_netif_types.h - // https://github.com/espressif/esp-idf/commit/822129e234aaedf86e76fe92ab9b49c5f0a612e0 - #include "esp_err.h" - #include "esp_event_base.h" - #include "esp_netif_ip_addr.h" +// Add missing includes to esp_netif_types.h +// https://github.com/espressif/esp-idf/commit/822129e234aaedf86e76fe92ab9b49c5f0a612e0 +#include "esp_err.h" +#include "esp_event_base.h" +#include "esp_netif_ip_addr.h" - #include - #include +#include +#include #endif #include "esp_netif_types.h" @@ -37,13 +40,13 @@ * @param[in] peer_addr The BLE address of the peer we've connected to. * @param[in] our_addr Our BLE address for this connection. */ -void lowpan6_ble_netif_up(esp_netif_t* esp_netif, ble_addr_t* peer_addr, ble_addr_t* our_addr); +void lowpan6_ble_netif_up(esp_netif_t *esp_netif, ble_addr_t *peer_addr, ble_addr_t *our_addr); /** Bring down the netif upon disconnection. * * @param[in] esp_netif The netif to mark down. */ -void lowpan6_ble_netif_down(esp_netif_t* netif); +void lowpan6_ble_netif_down(esp_netif_t *netif); /** Convert a NimBLE BLE addr to an EUI64 identifier. * @@ -53,7 +56,7 @@ void lowpan6_ble_netif_down(esp_netif_t* netif); * @param[in] addr The BLE addr to translate from. * @param[out] eui64 The resulting EUI64 address. */ -void nimble_addr_to_eui64(ble_addr_t const* addr, uint8_t* eui64); +void nimble_addr_to_eui64(ble_addr_t const *addr, uint8_t *eui64); /** Create a link-local address from an EUI64 identifier. * @@ -80,4 +83,4 @@ void nimble_addr_to_eui64(ble_addr_t const* addr, uint8_t* eui64); * @param[in] src The source EUI64 address. MUST contain at least 8 bytes. * @param[out] dst The resulting IPv6 address. */ -void ipv6_create_link_local_from_eui64(uint8_t const* src, ip6_addr_t* dst); +void ipv6_create_link_local_from_eui64(uint8_t const *src, ip6_addr_t *dst);