xref: /btstack/src/mesh/mesh_network.h (revision f727526daff8273b20d6f675fb3a6526ea68b9bb)
177ba3d3fSMatthias Ringwald /*
277ba3d3fSMatthias Ringwald  * Copyright (C) 2018 BlueKitchen GmbH
377ba3d3fSMatthias Ringwald  *
477ba3d3fSMatthias Ringwald  * Redistribution and use in source and binary forms, with or without
577ba3d3fSMatthias Ringwald  * modification, are permitted provided that the following conditions
677ba3d3fSMatthias Ringwald  * are met:
777ba3d3fSMatthias Ringwald  *
877ba3d3fSMatthias Ringwald  * 1. Redistributions of source code must retain the above copyright
977ba3d3fSMatthias Ringwald  *    notice, this list of conditions and the following disclaimer.
1077ba3d3fSMatthias Ringwald  * 2. Redistributions in binary form must reproduce the above copyright
1177ba3d3fSMatthias Ringwald  *    notice, this list of conditions and the following disclaimer in the
1277ba3d3fSMatthias Ringwald  *    documentation and/or other materials provided with the distribution.
1377ba3d3fSMatthias Ringwald  * 3. Neither the name of the copyright holders nor the names of
1477ba3d3fSMatthias Ringwald  *    contributors may be used to endorse or promote products derived
1577ba3d3fSMatthias Ringwald  *    from this software without specific prior written permission.
1677ba3d3fSMatthias Ringwald  * 4. Any redistribution, use, or modification is done solely for
1777ba3d3fSMatthias Ringwald  *    personal benefit and not for any commercial purpose or for
1877ba3d3fSMatthias Ringwald  *    monetary gain.
1977ba3d3fSMatthias Ringwald  *
2077ba3d3fSMatthias Ringwald  * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
2177ba3d3fSMatthias Ringwald  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2277ba3d3fSMatthias Ringwald  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
2377ba3d3fSMatthias Ringwald  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS
2477ba3d3fSMatthias Ringwald  * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
2577ba3d3fSMatthias Ringwald  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
2677ba3d3fSMatthias Ringwald  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
2777ba3d3fSMatthias Ringwald  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
2877ba3d3fSMatthias Ringwald  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
2977ba3d3fSMatthias Ringwald  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
3077ba3d3fSMatthias Ringwald  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3177ba3d3fSMatthias Ringwald  * SUCH DAMAGE.
3277ba3d3fSMatthias Ringwald  *
3377ba3d3fSMatthias Ringwald  * Please inquire about commercial licensing options at
3477ba3d3fSMatthias Ringwald  * [email protected]
3577ba3d3fSMatthias Ringwald  *
3677ba3d3fSMatthias Ringwald  */
3777ba3d3fSMatthias Ringwald 
3877ba3d3fSMatthias Ringwald #ifndef __MESH_NETWORK
3977ba3d3fSMatthias Ringwald #define __MESH_NETWORK
4077ba3d3fSMatthias Ringwald 
4177ba3d3fSMatthias Ringwald #include "btstack_linked_list.h"
4277ba3d3fSMatthias Ringwald #include "provisioning.h"
4377ba3d3fSMatthias Ringwald #include "btstack_run_loop.h"
4477ba3d3fSMatthias Ringwald 
4577ba3d3fSMatthias Ringwald #if defined __cplusplus
4677ba3d3fSMatthias Ringwald extern "C" {
4777ba3d3fSMatthias Ringwald #endif
4877ba3d3fSMatthias Ringwald 
4977ba3d3fSMatthias Ringwald #define MESH_DEVICE_KEY_INDEX     0xffff
5077ba3d3fSMatthias Ringwald 
5177ba3d3fSMatthias Ringwald #define MESH_NETWORK_PAYLOAD_MAX      29
5277ba3d3fSMatthias Ringwald #define MESH_ACCESS_PAYLOAD_MAX      384
5377ba3d3fSMatthias Ringwald 
5477ba3d3fSMatthias Ringwald #define MESH_ADDRESS_UNSASSIGNED     0x0000u
5577ba3d3fSMatthias Ringwald #define MESH_ADDRESS_ALL_PROXIES     0xFFFCu
5677ba3d3fSMatthias Ringwald #define MESH_ADDRESS_ALL_FRIENDS     0xFFFDu
5777ba3d3fSMatthias Ringwald #define MESH_ADDRESS_ALL_RELAYS      0xFFFEu
5877ba3d3fSMatthias Ringwald #define MESH_ADDRESS_ALL_NODES       0xFFFFu
5977ba3d3fSMatthias Ringwald 
6077ba3d3fSMatthias Ringwald typedef enum {
6177ba3d3fSMatthias Ringwald     MESH_NETWORK_PDU_RECEIVED,
6277ba3d3fSMatthias Ringwald     MESH_NETWORK_PDU_SENT,
6377ba3d3fSMatthias Ringwald } mesh_network_callback_type_t;
6477ba3d3fSMatthias Ringwald 
6577ba3d3fSMatthias Ringwald typedef enum {
6677ba3d3fSMatthias Ringwald     MESH_PDU_TYPE_NETWORK = 0,
6777ba3d3fSMatthias Ringwald     MESH_PDU_TYPE_TRANSPORT,
6877ba3d3fSMatthias Ringwald } mesh_pdu_type_t;
6977ba3d3fSMatthias Ringwald 
7077ba3d3fSMatthias Ringwald typedef struct mesh_pdu {
7177ba3d3fSMatthias Ringwald     // allow for linked lists
7277ba3d3fSMatthias Ringwald     btstack_linked_item_t item;
7377ba3d3fSMatthias Ringwald     // type
7477ba3d3fSMatthias Ringwald     mesh_pdu_type_t pdu_type;
7577ba3d3fSMatthias Ringwald } mesh_pdu_t;
7677ba3d3fSMatthias Ringwald 
77fd7ffe00SMatthias Ringwald //
78fd7ffe00SMatthias Ringwald #define MESH_NETWORK_PDU_FLAGS_PROXY_CONFIGURATION 1
79fd7ffe00SMatthias Ringwald #define MESH_NETWORK_PDU_FLAGS_GATT_BEARER   2
80bd9002edSMatthias Ringwald 
8177ba3d3fSMatthias Ringwald typedef struct mesh_network_pdu {
8277ba3d3fSMatthias Ringwald     mesh_pdu_t pdu_header;
8377ba3d3fSMatthias Ringwald 
8477ba3d3fSMatthias Ringwald     // callback
8577ba3d3fSMatthias Ringwald     void (*callback)(struct mesh_network_pdu * network_pdu);
8677ba3d3fSMatthias Ringwald 
8777ba3d3fSMatthias Ringwald     // meta data network layer
8877ba3d3fSMatthias Ringwald     uint16_t              netkey_index;
8977ba3d3fSMatthias Ringwald     // meta data transport layer
9077ba3d3fSMatthias Ringwald     uint16_t              appkey_index;
9177ba3d3fSMatthias Ringwald     // flags: bit 0 indicates Proxy PDU
9277ba3d3fSMatthias Ringwald     uint16_t              flags;
9377ba3d3fSMatthias Ringwald 
9477ba3d3fSMatthias Ringwald     // pdu
9577ba3d3fSMatthias Ringwald     uint16_t              len;
9677ba3d3fSMatthias Ringwald     uint8_t               data[MESH_NETWORK_PAYLOAD_MAX];
9777ba3d3fSMatthias Ringwald } mesh_network_pdu_t;
9877ba3d3fSMatthias Ringwald 
9977ba3d3fSMatthias Ringwald typedef struct {
10077ba3d3fSMatthias Ringwald     mesh_pdu_t pdu_header;
10177ba3d3fSMatthias Ringwald 
10277ba3d3fSMatthias Ringwald     // rx/tx: acknowledgement timer / segment transmission timer
10377ba3d3fSMatthias Ringwald     btstack_timer_source_t acknowledgement_timer;
10477ba3d3fSMatthias Ringwald     // rx: incomplete timer / tx: resend timer
10577ba3d3fSMatthias Ringwald     btstack_timer_source_t incomplete_timer;
10677ba3d3fSMatthias Ringwald     // block access
10777ba3d3fSMatthias Ringwald     uint32_t              block_ack;
10877ba3d3fSMatthias Ringwald     // meta data network layer
10977ba3d3fSMatthias Ringwald     uint16_t              netkey_index;
11077ba3d3fSMatthias Ringwald     // meta data transport layer
11177ba3d3fSMatthias Ringwald     uint16_t              appkey_index;
11277ba3d3fSMatthias Ringwald     // transmic size
11377ba3d3fSMatthias Ringwald     uint8_t               transmic_len;
11477ba3d3fSMatthias Ringwald     // akf - aid
11577ba3d3fSMatthias Ringwald     uint8_t               akf_aid;
11677ba3d3fSMatthias Ringwald     // network pdu header
11777ba3d3fSMatthias Ringwald     uint8_t               network_header[9];
11877ba3d3fSMatthias Ringwald     // acknowledgement timer active
11977ba3d3fSMatthias Ringwald     uint8_t               acknowledgement_timer_active;
12077ba3d3fSMatthias Ringwald     // incomplete timer active
12177ba3d3fSMatthias Ringwald     uint8_t               incomplete_timer_active;
12277ba3d3fSMatthias Ringwald     // message complete
12377ba3d3fSMatthias Ringwald     uint8_t               message_complete;
12477ba3d3fSMatthias Ringwald     // seq_zero for segmented messages
12577ba3d3fSMatthias Ringwald     uint16_t              seq_zero;
12677ba3d3fSMatthias Ringwald     // pdu
12777ba3d3fSMatthias Ringwald     uint16_t              len;
12877ba3d3fSMatthias Ringwald     uint8_t               data[MESH_ACCESS_PAYLOAD_MAX];
12977ba3d3fSMatthias Ringwald } mesh_transport_pdu_t;
13077ba3d3fSMatthias Ringwald 
13177ba3d3fSMatthias Ringwald 
13277ba3d3fSMatthias Ringwald /**
13377ba3d3fSMatthias Ringwald  * @brief Init Mesh Network Layer
13477ba3d3fSMatthias Ringwald  */
13577ba3d3fSMatthias Ringwald void mesh_network_init(void);
13677ba3d3fSMatthias Ringwald 
13777ba3d3fSMatthias Ringwald /**
13877ba3d3fSMatthias Ringwald  * @brief Set higher layer Network PDU handler
13977ba3d3fSMatthias Ringwald  * @param packet_handler
14077ba3d3fSMatthias Ringwald  */
14177ba3d3fSMatthias Ringwald void mesh_network_set_higher_layer_handler(void (*packet_handler)(mesh_network_callback_type_t callback_type, mesh_network_pdu_t * network_pdu));
14277ba3d3fSMatthias Ringwald 
14377ba3d3fSMatthias Ringwald /**
14477ba3d3fSMatthias Ringwald  * @brief Set higher layer Proxy PDU handler
14577ba3d3fSMatthias Ringwald  * @param packet_handler
14677ba3d3fSMatthias Ringwald  */
14777ba3d3fSMatthias Ringwald void mesh_network_set_proxy_message_handler(void (*packet_handler)(mesh_network_callback_type_t callback_type, mesh_network_pdu_t * network_pdu));
14877ba3d3fSMatthias Ringwald 
14977ba3d3fSMatthias Ringwald /**
15077ba3d3fSMatthias Ringwald  * @brief Mark packet as processed
15177ba3d3fSMatthias Ringwald  * @param newtork_pdu received via call packet_handler
15277ba3d3fSMatthias Ringwald  */
15377ba3d3fSMatthias Ringwald void mesh_network_message_processed_by_higher_layer(mesh_network_pdu_t * network_pdu);
15477ba3d3fSMatthias Ringwald 
15577ba3d3fSMatthias Ringwald /**
15677ba3d3fSMatthias Ringwald  * @brief Configure address filter
15777ba3d3fSMatthias Ringwald  */
15877ba3d3fSMatthias Ringwald void mesh_network_set_primary_element_address(uint16_t addr);
15977ba3d3fSMatthias Ringwald 
16077ba3d3fSMatthias Ringwald /**
16177ba3d3fSMatthias Ringwald  * @brief Send network_pdu after encryption
16277ba3d3fSMatthias Ringwald  * @param network_pdu
16377ba3d3fSMatthias Ringwald  */
16477ba3d3fSMatthias Ringwald void mesh_network_send_pdu(mesh_network_pdu_t * network_pdu);
16577ba3d3fSMatthias Ringwald 
16677ba3d3fSMatthias Ringwald /*
16777ba3d3fSMatthias Ringwald  * @brief Setup network pdu header
16877ba3d3fSMatthias Ringwald  * @param netkey_index
16977ba3d3fSMatthias Ringwald  * @param nid
17077ba3d3fSMatthias Ringwald  * @param ctl
17177ba3d3fSMatthias Ringwald  * @param ttl
17277ba3d3fSMatthias Ringwald  * @param seq
17377ba3d3fSMatthias Ringwald  * @param dst
17477ba3d3fSMatthias Ringwald  * @param transport_pdu_data
17577ba3d3fSMatthias Ringwald  * @param transport_pdu_len
17677ba3d3fSMatthias Ringwald  */
17777ba3d3fSMatthias Ringwald void mesh_network_setup_pdu(mesh_network_pdu_t * network_pdu, uint16_t netkey_index, uint8_t nid, uint8_t ctl, uint8_t ttl, uint32_t seq, uint16_t src, uint16_t dst, const uint8_t * transport_pdu_data, uint8_t transport_pdu_len);
17877ba3d3fSMatthias Ringwald 
17977ba3d3fSMatthias Ringwald /**
18077ba3d3fSMatthias Ringwald  * Setup network pdu header without modifying len or payload
18177ba3d3fSMatthias Ringwald  * @param network_pdu
18277ba3d3fSMatthias Ringwald  * @param netkey_index
18377ba3d3fSMatthias Ringwald  * @param nid
18477ba3d3fSMatthias Ringwald  * @param ctl
18577ba3d3fSMatthias Ringwald  * @param ttl
18677ba3d3fSMatthias Ringwald  * @param seq
18777ba3d3fSMatthias Ringwald  * @param src
18877ba3d3fSMatthias Ringwald  * @param dest
18977ba3d3fSMatthias Ringwald  */
19077ba3d3fSMatthias Ringwald void mesh_network_setup_pdu_header(mesh_network_pdu_t * network_pdu, uint16_t netkey_index, uint8_t nid, uint8_t ctl, uint8_t ttl, uint32_t seq, uint16_t src, uint16_t dest);
19177ba3d3fSMatthias Ringwald 
19277ba3d3fSMatthias Ringwald /**
19377ba3d3fSMatthias Ringwald  * @brief Validate network addresses
19477ba3d3fSMatthias Ringwald  * @param ctl
19577ba3d3fSMatthias Ringwald  * @param src
19677ba3d3fSMatthias Ringwald  * @param dst
19777ba3d3fSMatthias Ringwald  * @returns 1 if valid,
19877ba3d3fSMatthias Ringwald  */
19977ba3d3fSMatthias Ringwald int mesh_network_addresses_valid(uint8_t ctl, uint16_t src, uint16_t dst);
20077ba3d3fSMatthias Ringwald 
20177ba3d3fSMatthias Ringwald /**
20277ba3d3fSMatthias Ringwald  * @brief Check if Unicast address
20377ba3d3fSMatthias Ringwald  * @param addr
20477ba3d3fSMatthias Ringwald  * @returns 1 if unicast
20577ba3d3fSMatthias Ringwald  */
20677ba3d3fSMatthias Ringwald int mesh_network_address_unicast(uint16_t addr);
20777ba3d3fSMatthias Ringwald 
20877ba3d3fSMatthias Ringwald /**
20977ba3d3fSMatthias Ringwald  * @brief Check if Unicast address
21077ba3d3fSMatthias Ringwald  * @param addr
21177ba3d3fSMatthias Ringwald  * @returns 1 if unicast
21277ba3d3fSMatthias Ringwald  */
21377ba3d3fSMatthias Ringwald int mesh_network_address_group(uint16_t addr);
21477ba3d3fSMatthias Ringwald 
21577ba3d3fSMatthias Ringwald /**
21677ba3d3fSMatthias Ringwald  * @brief Check if All Proxies address
21777ba3d3fSMatthias Ringwald  * @param addr
21877ba3d3fSMatthias Ringwald  * @returns 1 if all proxies
21977ba3d3fSMatthias Ringwald  */
22077ba3d3fSMatthias Ringwald int mesh_network_address_all_proxies(uint16_t addr);
22177ba3d3fSMatthias Ringwald 
22277ba3d3fSMatthias Ringwald /**
22377ba3d3fSMatthias Ringwald  * @brief Check if All Nodes address
22477ba3d3fSMatthias Ringwald  * @param addr
22577ba3d3fSMatthias Ringwald  * @returns 1 if all nodes
22677ba3d3fSMatthias Ringwald  */
22777ba3d3fSMatthias Ringwald int mesh_network_address_all_nodes(uint16_t addr);
22877ba3d3fSMatthias Ringwald 
22977ba3d3fSMatthias Ringwald /**
23077ba3d3fSMatthias Ringwald  * @brief Check if All Friends address
23177ba3d3fSMatthias Ringwald  * @param addr
23277ba3d3fSMatthias Ringwald  * @returns 1 if all friends
23377ba3d3fSMatthias Ringwald  */
23477ba3d3fSMatthias Ringwald int mesh_network_address_all_friends(uint16_t addr);
23577ba3d3fSMatthias Ringwald 
23677ba3d3fSMatthias Ringwald /**
23777ba3d3fSMatthias Ringwald  * @brief Check if All Relays address
23877ba3d3fSMatthias Ringwald  * @param addr
23977ba3d3fSMatthias Ringwald  * @returns 1 if all relays
24077ba3d3fSMatthias Ringwald  */
24177ba3d3fSMatthias Ringwald int mesh_network_address_all_relays(uint16_t addr);
24277ba3d3fSMatthias Ringwald 
24377ba3d3fSMatthias Ringwald 
24477ba3d3fSMatthias Ringwald /**
24577ba3d3fSMatthias Ringwald  * @brief Check if Virtual address
24677ba3d3fSMatthias Ringwald  * @param addr
24777ba3d3fSMatthias Ringwald  * @returns 1 if virtual
24877ba3d3fSMatthias Ringwald  */
24977ba3d3fSMatthias Ringwald int mesh_network_address_virtual(uint16_t addr);
25077ba3d3fSMatthias Ringwald 
25177ba3d3fSMatthias Ringwald // buffer pool
25277ba3d3fSMatthias Ringwald mesh_network_pdu_t * mesh_network_pdu_get(void);
25377ba3d3fSMatthias Ringwald void mesh_network_pdu_free(mesh_network_pdu_t * network_pdu);
25477ba3d3fSMatthias Ringwald 
25577ba3d3fSMatthias Ringwald // Mesh Network PDU Getter
25677ba3d3fSMatthias Ringwald uint16_t  mesh_network_control(mesh_network_pdu_t * network_pdu);
25777ba3d3fSMatthias Ringwald uint8_t   mesh_network_nid(mesh_network_pdu_t * network_pdu);
25877ba3d3fSMatthias Ringwald uint8_t   mesh_network_ttl(mesh_network_pdu_t * network_pdu);
25977ba3d3fSMatthias Ringwald uint32_t  mesh_network_seq(mesh_network_pdu_t * network_pdu);
26077ba3d3fSMatthias Ringwald uint16_t  mesh_network_src(mesh_network_pdu_t * network_pdu);
26177ba3d3fSMatthias Ringwald uint16_t  mesh_network_dst(mesh_network_pdu_t * network_pdu);
26277ba3d3fSMatthias Ringwald int       mesh_network_segmented(mesh_network_pdu_t * network_pdu);
26377ba3d3fSMatthias Ringwald uint8_t * mesh_network_pdu_data(mesh_network_pdu_t * network_pdu);
26477ba3d3fSMatthias Ringwald uint8_t   mesh_network_pdu_len(mesh_network_pdu_t * network_pdu);
26577ba3d3fSMatthias Ringwald 
26677ba3d3fSMatthias Ringwald void     mesh_set_iv_index(uint32_t iv_index);
26777ba3d3fSMatthias Ringwald uint32_t mesh_get_iv_index(void);
26877ba3d3fSMatthias Ringwald 
26977ba3d3fSMatthias Ringwald // Testing only
270*f727526dSMatthias Ringwald void mesh_network_received_message(const uint8_t * pdu_data, uint8_t pdu_len, uint8_t flags);
271fd7ffe00SMatthias Ringwald void mesh_network_process_proxy_configuration_message(const uint8_t * pdu_data, uint8_t pdu_len);
272fd7ffe00SMatthias Ringwald void mesh_network_encrypt_proxy_configuration_message(mesh_network_pdu_t * network_pdu, void (* callback)(mesh_network_pdu_t * callback));
27377ba3d3fSMatthias Ringwald void mesh_network_dump(void);
27477ba3d3fSMatthias Ringwald void mesh_network_reset(void);
27577ba3d3fSMatthias Ringwald 
27677ba3d3fSMatthias Ringwald #if defined __cplusplus
27777ba3d3fSMatthias Ringwald }
27877ba3d3fSMatthias Ringwald #endif
27977ba3d3fSMatthias Ringwald 
28077ba3d3fSMatthias Ringwald #endif
281