xref: /btstack/src/mesh/mesh_network.h (revision bd9002edc00f5b115f3ddf0f2b718eb3185adc6f)
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 
77*bd9002edSMatthias Ringwald #define MESH_NETWORK_PDU_FLAGS_PROXY_MESSAGE 1
78*bd9002edSMatthias Ringwald 
7977ba3d3fSMatthias Ringwald typedef struct mesh_network_pdu {
8077ba3d3fSMatthias Ringwald     mesh_pdu_t pdu_header;
8177ba3d3fSMatthias Ringwald 
8277ba3d3fSMatthias Ringwald     // callback
8377ba3d3fSMatthias Ringwald     void (*callback)(struct mesh_network_pdu * network_pdu);
8477ba3d3fSMatthias Ringwald 
8577ba3d3fSMatthias Ringwald     // meta data network layer
8677ba3d3fSMatthias Ringwald     uint16_t              netkey_index;
8777ba3d3fSMatthias Ringwald     // meta data transport layer
8877ba3d3fSMatthias Ringwald     uint16_t              appkey_index;
8977ba3d3fSMatthias Ringwald     // flags: bit 0 indicates Proxy PDU
9077ba3d3fSMatthias Ringwald     uint16_t              flags;
9177ba3d3fSMatthias Ringwald 
9277ba3d3fSMatthias Ringwald     // pdu
9377ba3d3fSMatthias Ringwald     uint16_t              len;
9477ba3d3fSMatthias Ringwald     uint8_t               data[MESH_NETWORK_PAYLOAD_MAX];
9577ba3d3fSMatthias Ringwald } mesh_network_pdu_t;
9677ba3d3fSMatthias Ringwald 
9777ba3d3fSMatthias Ringwald typedef struct {
9877ba3d3fSMatthias Ringwald     mesh_pdu_t pdu_header;
9977ba3d3fSMatthias Ringwald 
10077ba3d3fSMatthias Ringwald     // rx/tx: acknowledgement timer / segment transmission timer
10177ba3d3fSMatthias Ringwald     btstack_timer_source_t acknowledgement_timer;
10277ba3d3fSMatthias Ringwald     // rx: incomplete timer / tx: resend timer
10377ba3d3fSMatthias Ringwald     btstack_timer_source_t incomplete_timer;
10477ba3d3fSMatthias Ringwald     // block access
10577ba3d3fSMatthias Ringwald     uint32_t              block_ack;
10677ba3d3fSMatthias Ringwald     // meta data network layer
10777ba3d3fSMatthias Ringwald     uint16_t              netkey_index;
10877ba3d3fSMatthias Ringwald     // meta data transport layer
10977ba3d3fSMatthias Ringwald     uint16_t              appkey_index;
11077ba3d3fSMatthias Ringwald     // transmic size
11177ba3d3fSMatthias Ringwald     uint8_t               transmic_len;
11277ba3d3fSMatthias Ringwald     // akf - aid
11377ba3d3fSMatthias Ringwald     uint8_t               akf_aid;
11477ba3d3fSMatthias Ringwald     // network pdu header
11577ba3d3fSMatthias Ringwald     uint8_t               network_header[9];
11677ba3d3fSMatthias Ringwald     // acknowledgement timer active
11777ba3d3fSMatthias Ringwald     uint8_t               acknowledgement_timer_active;
11877ba3d3fSMatthias Ringwald     // incomplete timer active
11977ba3d3fSMatthias Ringwald     uint8_t               incomplete_timer_active;
12077ba3d3fSMatthias Ringwald     // message complete
12177ba3d3fSMatthias Ringwald     uint8_t               message_complete;
12277ba3d3fSMatthias Ringwald     // seq_zero for segmented messages
12377ba3d3fSMatthias Ringwald     uint16_t              seq_zero;
12477ba3d3fSMatthias Ringwald     // pdu
12577ba3d3fSMatthias Ringwald     uint16_t              len;
12677ba3d3fSMatthias Ringwald     uint8_t               data[MESH_ACCESS_PAYLOAD_MAX];
12777ba3d3fSMatthias Ringwald } mesh_transport_pdu_t;
12877ba3d3fSMatthias Ringwald 
12977ba3d3fSMatthias Ringwald 
13077ba3d3fSMatthias Ringwald /**
13177ba3d3fSMatthias Ringwald  * @brief Init Mesh Network Layer
13277ba3d3fSMatthias Ringwald  */
13377ba3d3fSMatthias Ringwald void mesh_network_init(void);
13477ba3d3fSMatthias Ringwald 
13577ba3d3fSMatthias Ringwald /**
13677ba3d3fSMatthias Ringwald  * @brief Set higher layer Network PDU handler
13777ba3d3fSMatthias Ringwald  * @param packet_handler
13877ba3d3fSMatthias Ringwald  */
13977ba3d3fSMatthias Ringwald void mesh_network_set_higher_layer_handler(void (*packet_handler)(mesh_network_callback_type_t callback_type, mesh_network_pdu_t * network_pdu));
14077ba3d3fSMatthias Ringwald 
14177ba3d3fSMatthias Ringwald /**
14277ba3d3fSMatthias Ringwald  * @brief Set higher layer Proxy PDU handler
14377ba3d3fSMatthias Ringwald  * @param packet_handler
14477ba3d3fSMatthias Ringwald  */
14577ba3d3fSMatthias Ringwald void mesh_network_set_proxy_message_handler(void (*packet_handler)(mesh_network_callback_type_t callback_type, mesh_network_pdu_t * network_pdu));
14677ba3d3fSMatthias Ringwald 
14777ba3d3fSMatthias Ringwald /**
14877ba3d3fSMatthias Ringwald  * @brief Mark packet as processed
14977ba3d3fSMatthias Ringwald  * @param newtork_pdu received via call packet_handler
15077ba3d3fSMatthias Ringwald  */
15177ba3d3fSMatthias Ringwald void mesh_network_message_processed_by_higher_layer(mesh_network_pdu_t * network_pdu);
15277ba3d3fSMatthias Ringwald 
15377ba3d3fSMatthias Ringwald /**
15477ba3d3fSMatthias Ringwald  * @brief Configure address filter
15577ba3d3fSMatthias Ringwald  */
15677ba3d3fSMatthias Ringwald void mesh_network_set_primary_element_address(uint16_t addr);
15777ba3d3fSMatthias Ringwald 
15877ba3d3fSMatthias Ringwald /**
15977ba3d3fSMatthias Ringwald  * @brief Send network_pdu after encryption
16077ba3d3fSMatthias Ringwald  * @param network_pdu
16177ba3d3fSMatthias Ringwald  */
16277ba3d3fSMatthias Ringwald void mesh_network_send_pdu(mesh_network_pdu_t * network_pdu);
16377ba3d3fSMatthias Ringwald 
16477ba3d3fSMatthias Ringwald /*
16577ba3d3fSMatthias Ringwald  * @brief Setup network pdu header
16677ba3d3fSMatthias Ringwald  * @param netkey_index
16777ba3d3fSMatthias Ringwald  * @param nid
16877ba3d3fSMatthias Ringwald  * @param ctl
16977ba3d3fSMatthias Ringwald  * @param ttl
17077ba3d3fSMatthias Ringwald  * @param seq
17177ba3d3fSMatthias Ringwald  * @param dst
17277ba3d3fSMatthias Ringwald  * @param transport_pdu_data
17377ba3d3fSMatthias Ringwald  * @param transport_pdu_len
17477ba3d3fSMatthias Ringwald  */
17577ba3d3fSMatthias 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);
17677ba3d3fSMatthias Ringwald 
17777ba3d3fSMatthias Ringwald /**
17877ba3d3fSMatthias Ringwald  * Setup network pdu header without modifying len or payload
17977ba3d3fSMatthias Ringwald  * @param network_pdu
18077ba3d3fSMatthias Ringwald  * @param netkey_index
18177ba3d3fSMatthias Ringwald  * @param nid
18277ba3d3fSMatthias Ringwald  * @param ctl
18377ba3d3fSMatthias Ringwald  * @param ttl
18477ba3d3fSMatthias Ringwald  * @param seq
18577ba3d3fSMatthias Ringwald  * @param src
18677ba3d3fSMatthias Ringwald  * @param dest
18777ba3d3fSMatthias Ringwald  */
18877ba3d3fSMatthias 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);
18977ba3d3fSMatthias Ringwald 
19077ba3d3fSMatthias Ringwald /**
19177ba3d3fSMatthias Ringwald  * @brief Validate network addresses
19277ba3d3fSMatthias Ringwald  * @param ctl
19377ba3d3fSMatthias Ringwald  * @param src
19477ba3d3fSMatthias Ringwald  * @param dst
19577ba3d3fSMatthias Ringwald  * @returns 1 if valid,
19677ba3d3fSMatthias Ringwald  */
19777ba3d3fSMatthias Ringwald int mesh_network_addresses_valid(uint8_t ctl, uint16_t src, uint16_t dst);
19877ba3d3fSMatthias Ringwald 
19977ba3d3fSMatthias Ringwald /**
20077ba3d3fSMatthias Ringwald  * @brief Check if Unicast address
20177ba3d3fSMatthias Ringwald  * @param addr
20277ba3d3fSMatthias Ringwald  * @returns 1 if unicast
20377ba3d3fSMatthias Ringwald  */
20477ba3d3fSMatthias Ringwald int mesh_network_address_unicast(uint16_t addr);
20577ba3d3fSMatthias Ringwald 
20677ba3d3fSMatthias Ringwald /**
20777ba3d3fSMatthias Ringwald  * @brief Check if Unicast address
20877ba3d3fSMatthias Ringwald  * @param addr
20977ba3d3fSMatthias Ringwald  * @returns 1 if unicast
21077ba3d3fSMatthias Ringwald  */
21177ba3d3fSMatthias Ringwald int mesh_network_address_group(uint16_t addr);
21277ba3d3fSMatthias Ringwald 
21377ba3d3fSMatthias Ringwald /**
21477ba3d3fSMatthias Ringwald  * @brief Check if All Proxies address
21577ba3d3fSMatthias Ringwald  * @param addr
21677ba3d3fSMatthias Ringwald  * @returns 1 if all proxies
21777ba3d3fSMatthias Ringwald  */
21877ba3d3fSMatthias Ringwald int mesh_network_address_all_proxies(uint16_t addr);
21977ba3d3fSMatthias Ringwald 
22077ba3d3fSMatthias Ringwald /**
22177ba3d3fSMatthias Ringwald  * @brief Check if All Nodes address
22277ba3d3fSMatthias Ringwald  * @param addr
22377ba3d3fSMatthias Ringwald  * @returns 1 if all nodes
22477ba3d3fSMatthias Ringwald  */
22577ba3d3fSMatthias Ringwald int mesh_network_address_all_nodes(uint16_t addr);
22677ba3d3fSMatthias Ringwald 
22777ba3d3fSMatthias Ringwald /**
22877ba3d3fSMatthias Ringwald  * @brief Check if All Friends address
22977ba3d3fSMatthias Ringwald  * @param addr
23077ba3d3fSMatthias Ringwald  * @returns 1 if all friends
23177ba3d3fSMatthias Ringwald  */
23277ba3d3fSMatthias Ringwald int mesh_network_address_all_friends(uint16_t addr);
23377ba3d3fSMatthias Ringwald 
23477ba3d3fSMatthias Ringwald /**
23577ba3d3fSMatthias Ringwald  * @brief Check if All Relays address
23677ba3d3fSMatthias Ringwald  * @param addr
23777ba3d3fSMatthias Ringwald  * @returns 1 if all relays
23877ba3d3fSMatthias Ringwald  */
23977ba3d3fSMatthias Ringwald int mesh_network_address_all_relays(uint16_t addr);
24077ba3d3fSMatthias Ringwald 
24177ba3d3fSMatthias Ringwald 
24277ba3d3fSMatthias Ringwald /**
24377ba3d3fSMatthias Ringwald  * @brief Check if Virtual address
24477ba3d3fSMatthias Ringwald  * @param addr
24577ba3d3fSMatthias Ringwald  * @returns 1 if virtual
24677ba3d3fSMatthias Ringwald  */
24777ba3d3fSMatthias Ringwald int mesh_network_address_virtual(uint16_t addr);
24877ba3d3fSMatthias Ringwald 
24977ba3d3fSMatthias Ringwald // buffer pool
25077ba3d3fSMatthias Ringwald mesh_network_pdu_t * mesh_network_pdu_get(void);
25177ba3d3fSMatthias Ringwald void mesh_network_pdu_free(mesh_network_pdu_t * network_pdu);
25277ba3d3fSMatthias Ringwald 
25377ba3d3fSMatthias Ringwald // Mesh Network PDU Getter
25477ba3d3fSMatthias Ringwald uint16_t  mesh_network_control(mesh_network_pdu_t * network_pdu);
25577ba3d3fSMatthias Ringwald uint8_t   mesh_network_nid(mesh_network_pdu_t * network_pdu);
25677ba3d3fSMatthias Ringwald uint8_t   mesh_network_ttl(mesh_network_pdu_t * network_pdu);
25777ba3d3fSMatthias Ringwald uint32_t  mesh_network_seq(mesh_network_pdu_t * network_pdu);
25877ba3d3fSMatthias Ringwald uint16_t  mesh_network_src(mesh_network_pdu_t * network_pdu);
25977ba3d3fSMatthias Ringwald uint16_t  mesh_network_dst(mesh_network_pdu_t * network_pdu);
26077ba3d3fSMatthias Ringwald int       mesh_network_segmented(mesh_network_pdu_t * network_pdu);
26177ba3d3fSMatthias Ringwald uint8_t * mesh_network_pdu_data(mesh_network_pdu_t * network_pdu);
26277ba3d3fSMatthias Ringwald uint8_t   mesh_network_pdu_len(mesh_network_pdu_t * network_pdu);
26377ba3d3fSMatthias Ringwald 
26477ba3d3fSMatthias Ringwald void     mesh_set_iv_index(uint32_t iv_index);
26577ba3d3fSMatthias Ringwald uint32_t mesh_get_iv_index(void);
26677ba3d3fSMatthias Ringwald 
26777ba3d3fSMatthias Ringwald // Testing only
26877ba3d3fSMatthias Ringwald void mesh_network_received_message(const uint8_t * pdu_data, uint8_t pdu_len);
26977ba3d3fSMatthias Ringwald void mesh_network_process_proxy_message(const uint8_t * pdu_data, uint8_t pdu_len);
27077ba3d3fSMatthias Ringwald void mesh_network_encrypt_proxy_message(mesh_network_pdu_t * network_pdu, void (* callback)(mesh_network_pdu_t * callback));
27177ba3d3fSMatthias Ringwald void mesh_network_dump(void);
27277ba3d3fSMatthias Ringwald void mesh_network_reset(void);
27377ba3d3fSMatthias Ringwald 
27477ba3d3fSMatthias Ringwald #if defined __cplusplus
27577ba3d3fSMatthias Ringwald }
27677ba3d3fSMatthias Ringwald #endif
27777ba3d3fSMatthias Ringwald 
27877ba3d3fSMatthias Ringwald #endif
279